Owner Dogfooding Issue Inventory
Captured: 2026-07-28
Source: first-hand use of the organization app
Status: reported friction; not yet a code-verified implementation plan
Purpose
This document turns raw dogfooding notes into a set of problems that can be investigated and resolved one at a time.
The original notes contain a mix of:
- reproducible-looking defects
- unclear or excessive workflows
- missing or inconsistent interactions
- product-direction concerns
- codebase and architecture concerns
Those categories should not be handed to an implementation agent as one large request. Each issue below is intentionally separable. A future pass should investigate the current behavior, confirm the desired product decision, define the affected surfaces, implement the change, and verify it before moving to the next issue.
This inventory preserves the force of the original feedback without treating frustration as a substitute for diagnosis. Reported behavior is not marked as a confirmed root cause until the relevant implementation has been inspected.
Product Standard Expressed By The Notes
The app is intended to be the daily operating system for a freelancer or small agency, not merely a collection of administrative features.
The primary experience should support the work that occupies most of the operator's day:
- knowing what matters today
- moving between clients and projects without reconstructing context
- capturing notes and time without ceremony
- creating and linking follow-up work naturally
- collaborating with a team when one exists
- keeping client context close without exposing internal work accidentally
Billing, contracts, and invoicing matter, but they occupy a smaller portion of the working day. The product will not earn daily use merely by reproducing administrative capabilities that already exist elsewhere. Its advantage must come from making the operator's actual work calmer, faster, more coherent, and easier to resume.
The standard for the first public beta is therefore not just feature presence. The features must form one understandable system:
- one concept should not behave like several unrelated mini-features
- common actions should have consistent behavior across surfaces
- the interface should hide unnecessary internal complexity
- routine work should require the fewest meaningful decisions and actions
- the user should be able to trust that the state shown in one place is the same state shown everywhere else
How To Use This Inventory
For each implementation session:
- Select one issue ID.
- Reproduce and inspect the current behavior before proposing a fix.
- Read the linked product and implementation docs.
- Separate the observed symptom from its technical root cause.
- Confirm any unresolved product decision.
- Define a bounded acceptance contract.
- Implement and test the issue across every surface named in that contract.
- Update this document with the result before selecting another issue.
Issues may be combined only after investigation proves they share the same root cause and can be verified with one coherent acceptance contract.
Triage Summary
| ID | Issue | Type | Initial urgency |
|---|---|---|---|
| NOTE-01 | Notes show stale or duplicated state across surfaces | Trust and consistency defect | Critical |
| NOTE-02 | Notes should have one clear autosave model | Product behavior and consistency | High |
| NOTE-03 | New-note dialog is too short for its editing job | Interaction and layout | Medium |
| NOTE-04 | Starred and recent notes cannot be pinned from the topbar list | Missing interaction | Medium |
| TIME-01 | Personal time capture has an excessive approval loop | Workflow design | High |
| REM-01 | Timed reminder date selection does not preserve the chosen date | Functional defect | High |
| REM-02 | Reminder creation does not make client and project context easy to add | Workflow and linking | High |
| REM-03 | Opening a reminder from the topbar produces an awkward dialog flow | Information architecture | Medium |
| NAV-01 | Today may deserve priority over Overview in the sidebar | Navigation and product emphasis | Medium |
| TOP-01 | Pinned projects in the topbar are not actionable | Working-context design | Medium |
| I18N-01 | Billing notification copy appears untranslated or developer-facing | Localization and product copy | High |
| PROD-01 | The app lacks a consistently obvious, low-friction operating flow | Product-system concern | Foundational |
| PROD-02 | Personal, linked, internal, and client-visible concepts are too exposed | Product-model and vocabulary concern | Foundational |
| ARCH-01 | UX inconsistency is reinforced by god files and fragmented state ownership | Architecture and sequencing | Foundational |
The urgency labels are an initial reading of the reported impact, not a final delivery order. Trust-breaking data presentation and functional defects should generally be investigated before interaction polish. Foundational product questions should be discussed before a broad refactor, but they should not delay bounded fixes for confirmed defects.
NOTE-01 — Notes Show Stale Or Duplicated State Across Surfaces
Reported behavior
The same note can appear more than once in the topbar, and one copy may show an older editing state while the Notes page shows the current content. Unpinning the stale copy and pinning the note again appears to refresh it.
The Notes page is currently perceived as the only reliable place to edit a note.
Why this matters
This is a trust failure, not merely visual duplication. A user cannot safely use notes as working memory if two views of the same record disagree. The user is forced to reason about which surface owns the real note and to perform manual recovery steps.
Intended outcome
A note is one canonical record that can be viewed or edited through several surfaces. The Notes page, topbar quick view, pinned-note view, recent-note view, and any dialog or full-screen editor must converge on the same saved state.
Opening the same note in more than one presentation must not create competing copies, independent edit histories, or stale pinned snapshots.
Investigation questions
- Are duplicate topbar items separate working-tab and pinned-record instances, or is one record being assigned multiple non-canonical IDs?
- Does any surface retain a note snapshot instead of subscribing to the canonical record?
- Do quick-note drafts and saved notes cross the draft-to-record boundary cleanly?
- Can delayed saves, optimistic updates, or subscription revisions overwrite newer content?
- Do rich-text changes and plain-text changes pass through the same persistence path?
Resolution boundary
Do not close this issue after removing a duplicate chip visually. Resolution requires proving canonical identity, state ownership, persistence, and cross-surface synchronization for the same note.
Implementation result — 2026-07-28
The stale-state path was confirmed and repaired.
Root causes:
- a saved note opened from the topbar was copied into a durable local quick-note session
- reopening that note reused the local snapshot without reconciling it against the current Convex record
- pinned-record labels were synchronized only from the selected Notes-page record, not centrally from canonical note data
- delayed autosave completion targeted the currently active session rather than the exact session that initiated the request
The repaired contract is:
- clean saved-note sessions refresh from the canonical subscribed note record
- genuinely unsaved local edits are not overwritten by subscription refresh
- reopening a saved note reconciles the session before presenting it
- pinned-note labels and context synchronize from canonical note data
- legacy plain-text notes pass through the same canonical rich-text hydration used by the Notes page
- save completion and session cleanup target the initiating session ID, even if the user switches notes while the request is pending
- the topbar keeps one saved-note tab when a pinned or temporary record item already represents that note
Automated verification:
apps/app/tests/org/quick-note-context.test.tsapps/app/tests/org/working-quick-view-strip.test.tsapps/app/tests/org/note-quick-access-popover-content.test.tsx- focused result: 32 tests passed
- app TypeScript validation passed
- ESLint passed for all changed app and test files
Owner dogfood confirmation remains pending because no controllable signed-in browser session was available during implementation.
NOTE-02 — Notes Should Have One Clear Autosave Model
Reported behavior
The note editor presents a Save action, but its state is confusing. It may
temporarily appear muted as though work is being saved and then become
actionable again. Some editor operations, such as applying a bullet list, do not
appear to mark the note as changed.
An older observation questioned whether quick notes saved automatically. The current product decision expressed in the notes is stronger: all note editing should save automatically, including durable backend persistence rather than only local draft recovery.
Why this matters
A visible save button makes the user monitor persistence instead of writing. If the button does not recognize every meaningful editor change, it also gives unreliable feedback. Different save rules across the Notes page, quick notes, topbar views, and expanded editors make Notes feel like several features.
Intended outcome
Saved notes autosave after the user pauses editing. Every meaningful editor change participates in the same dirty-state and persistence model, including format-only changes.
Local draft recovery may protect unsaved work, but it must not be confused with
durable server persistence. The UI should communicate exceptional states such
as an active save or failed save without requiring a routine Save button.
Decisions required
- What debounce or idle behavior should trigger durable persistence?
- What minimal saving, saved, offline, and failed-save feedback is necessary?
- When does a quick-note draft become a saved note record?
- What happens when the editor closes while a save is pending?
- How are concurrent edits or stale revisions handled?
Resolution boundary
This issue applies to every editor surface for the same note model. It should not be solved by hiding the button while leaving inconsistent or local-only persistence underneath.
Owner reconfirmation — 2026-07-28
After the NOTE-01 consistency repair, the owner reconfirmed that routine
Save buttons still feel wrong for Notes. Treat their removal as part of this
dedicated autosave contract pass, not as a cosmetic follow-up to NOTE-01.
Implementation result — 2026-07-28
The Notes page, topbar quick-note editor, and shared new-note compose dialog now use one durable autosave contract:
- a valid note persists after a 900 ms editing pause
- closing, minimizing, switching notes, or unmounting flushes the latest valid draft instead of depending on the debounce
- new quick notes and compose-dialog drafts become durable note records automatically and remain open for continued editing
- incomplete new drafts remain in organization- and user-scoped local recovery without being presented as server-saved notes
- all rich-text payload fields participate in dirty detection, so format-only changes persist
- routine
SaveandSave and linkactions are removed; the surfaces show only quietSaving,Saved, or failure state, while explicit follow-through actions such asLink to timerremain available - updates carry the last observed server revision; the backend rejects stale writers instead of silently overwriting a newer edit
- backend no-op updates return the existing revision without rewriting the note
- queued edits made while a new note is being created attach to that first record rather than creating duplicates
Automated verification:
packages/backend/tests/org/note-autosave.test.tsapps/app/tests/org/note-drafts.test.tsapps/app/tests/org/note-compose-dialog.test.tsxapps/app/tests/org/note-quick-access-popover-content.test.tsxapps/app/tests/org/quick-note-context.test.ts- focused app result: 32 tests passed
- backend autosave result: 1 test passed
- app and backend TypeScript validation passed
- locale, action-copy, copy, and targeted ESLint checks passed
Owner dogfood confirmation remains pending. The next hands-on check should cover creating and continuing a note from each surface, closing before the debounce completes, applying format-only changes, and opening the same note in two browser sessions to confirm that a stale writer is stopped visibly.
NOTE-03 — New-Note Dialog Is Too Short For Its Editing Job
Reported behavior
The editor in the dedicated new-note flow is vertically cramped.
Why this matters
The available writing area does not match the scope of the task. It makes a normal note feel constrained before the user has written meaningful content.
Intended outcome
The creation surface should provide enough room for comfortable note composition at common viewport sizes while remaining consistent with the chosen editor-scale rule.
Decisions required
- Is note creation still a bounded dialog job, or has it become a route-backed workspace?
- Should the editor have a larger fixed minimum, responsive height, or an explicit expansion path?
- Should new-note and existing-note editors use the same size behavior?
Resolution boundary
Test the result on small laptop, common desktop, and constrained-height viewports. Do not solve the desktop complaint by making the dialog unusable on smaller screens.
Scope clarification — 2026-07-28
The owner clarified that the cramped presentation occurs specifically when creating a note from the Notes page. Client, project, timer, and other quick-capture entry points should retain their existing compact presentation.
Implementation result — 2026-07-28
The owner chose a workspace-native interaction instead of enlarging the modal.
The Notes-page New note action now:
- inserts a selected draft row into the existing note list immediately
- opens that draft in the same full Notes-page editor used for existing notes and focuses the title
- inherits the current project or client context when the page was opened in that context
- keeps an incomplete draft in scoped local recovery without creating an empty backend record
- promotes the draft to one durable note after meaningful body content is entered, then autosaves later edits to that same record
- quietly discards a completely empty draft when another note is selected
- withholds pin, archive, delete, timer-link, and promotion actions until the draft has a durable note identity
Client, project, timer, topbar, and other quick-capture note entry points keep the compact shared composer because those entry points are deliberately brief contextual capture flows. This makes the dedicated Notes route behave like a real notes workspace without forcing every create surface into a full-page interaction.
Automated verification covers contextual draft defaults, inline selection, create-once behavior, follow-up revision-aware autosave, and empty-draft discarding in:
apps/app/tests/org/note-drafts.test.tsapps/app/tests/org/notes-page-inline-create.test.tsxapps/app/tests/org/note-compose-dialog.test.tsx
Focused result: 7 tests passed. App TypeScript and targeted ESLint validation passed. Owner visual confirmation remains pending.
NOTE-04 — Starred And Recent Notes Cannot Be Pinned From The Topbar List
Reported behavior
Hovering a note in the topbar's starred or recent sections does not offer the expected pin action.
Why this matters
The topbar is meant to manage a working set. Discovering a note there but having to leave that context to pin it breaks the purpose of the surface.
Intended outcome
Eligible notes shown in starred and recent lists expose a consistent, accessible pin or unpin action without requiring navigation to the Notes page.
Investigation questions
- Is
starreda separate durable concept frompinned, and is that distinction clear enough to keep? - Are the same note actions intentionally available in recent, starred, search, and pinned sections?
- How should the action remain discoverable for keyboard and touch users, where hover is unavailable?
Implementation result — 2026-07-28
Starred and Pinned are now explicit independent states:
- Starred remains the note-level organization state backed by the existing note fields
- Pinned is the durable shell working set backed by workspace preferences
- Starred and Recent topbar rows expose the same note-specific pin/unpin action without navigating away or closing the launcher
- the action uses a visible touch target plus localized
aria-label,title, andaria-pressedstate - the note's Starred state is represented with a Star indicator and is never mutated by the shell action
- when one note appears in both Starred and Recent, both controls resolve from the same shell state and cannot create duplicate pins
Focused interaction coverage verifies the independent state combinations, canonical pin payload, unpin behavior, duplicate-row synchronization, and action/link isolation. App locale validation and focused linting pass. Owner dogfood confirmation remains pending.
TIME-01 — Personal Time Capture Has An Excessive Approval Loop
Reported behavior
Stopping a timer creates a draft entry. The user must then submit the entry for review, open the review queue, and approve their own time. A small block of personal work therefore requires several administrative actions after the time has already been captured.
Why this matters
Frequent time capture must be nearly effortless. A workflow that may make sense for team oversight becomes unreasonable when an owner or independent operator must approve their own routine work. Users will forget the steps, allow drafts to accumulate, or stop using the timer.
Intended outcome
The workflow should preserve review and billing integrity where they are actually needed without forcing every user and every entry through the same state ceremony.
Decisions required
- Should an organization owner's own entry be approved automatically?
- Should organizations without a team default to a simpler flow?
- Is approval policy based on role, authorship, billing status, organization settings, or a combination?
- When is a draft genuinely useful rather than an implementation artifact?
- Which corrections must remain possible after an entry becomes billable or approved?
Resolution boundary
Do not merely add a bulk-approve button to the existing loop. First decide which users and entries need approval at all. Preserve auditability and invoice locking without making routine capture serve the most complex case.
Implementation result — 2026-07-28
Time capture is now a single completed action rather than the start of a mandatory self-approval loop:
- routine time is tracked immediately for every role by default
- an organization can opt into
Require review for staff timefrom General settings; the switch persists immediately without a separate Save action - when review is enabled, staff time goes directly to
Needs reviewwhile owners and members with time-review authority continue tracking directly - correcting a returned staff entry sends it straight back to review
- correcting an unlocked entry as a reviewer keeps it tracked
- the timer and manual-entry confirmations now say
Time tracked
The UI no longer exposes Submit actions or treats approval as the primary
language for routine capture. The visible states are Saved for legacy drafts,
Needs review, Changes requested, and Tracked. Draft remains in
the stored enum only for compatibility with older records and the legacy
submission mutation remains available to recover those records.
Tracked time is also no longer treated as an overdue billing task. It does not
create an overview attention signal or force a billing profile merely because
it is unbilled. Client and project time views may show unbilled tracked hours as
useful context. Selecting a client in the invoice composer now produces one
optional Ready to bill recommendation with total hours, value, project count,
and date range. Add to invoice selects the exact entries; Review reveals
the separate project/rate groups, exact entries, custom periods, and overrides.
A client-wide invoice may combine multiple separately priced scopes, while a
project invoice accepts only that project's time. Manual invoice lines remain
first-class. Currency, service label, tax, PDF, memo, footer, and custom fields
remain available behind Additional options instead of crowding the default
path.
The active timer is now durable server state with a local instant-response mirror. It survives refresh, browser-data loss, and device handoff; repeated or concurrent starts for one member and organization resolve to one timer. The global timer chip offers one-action stop-and-track while opening the timer retains client, project, task, note, billable, work-log, pause, resume, and discard controls.
The first owner retest exposed two shell regressions in that implementation.
Independent timer-hook instances could calibrate from different cached server
timestamps, causing the dialog and topbar to disagree, and a separate discard X
was layered over the topbar's stop control. The shell now owns one shared timer
controller and clock. The timer chip exposes only its open action and one
outline Stop and track control; discard remains in the timer dialog behind
confirmation. Active timer buttons use semantic success styling rather than a
black selected state.
New time entries snapshot their billing mode, hourly rate, rate source, and currency at capture. Later project or client default changes therefore split older and newer work into accurate internal billing groups rather than repricing old work. Pre-snapshot entries use the current configuration as a compatibility fallback because historical prices cannot be reconstructed safely.
The review state is no longer reused as a client-visibility decision. Projects
have an explicit Show tracked time in the client portal setting, off by
default, which gates project, task, update, and portal-billing time totals.
Invoice eligibility remains internal and independent.
Team behaviour is explicit rather than inherited from broad client-record management:
time.view_teamexposes teammate time metadata and totalstime.reviewadds review authority and private detailtime.manageadds edit, delete, and lock authority over team entries- default staff see only their own entries and summaries
The standalone Entries page now defaults to the current month, supports week/month/quarter/year/custom ranges, calculates totals across the complete selected range, and automatically estimates hourly value from project overrides and client defaults for invoice-authorized members. Retainer, non-billable, and subscription-covered time is excluded; missing rates remain visible as unpriced time and currencies remain separate.
Invoice integrity is unchanged: only internally approved, billable entries can be allocated, reservation locks the exact entries, and reserved or invoiced entries cannot be unlocked or deleted. Uninvoiced, unlocked entries can still be corrected, archived, or deleted so an automatically ready owner entry does not become permanent merely because it was captured.
Regression coverage verifies direct staff tracking by default, opt-in staff review, automatic resubmission after a requested change, deletion of uninvoiced time, single-instance durable timers, capture-time pricing, historical-rate grouping, and unchanged exact-allocation integrity. TIME-01 remains open only for owner dogfood confirmation of the revised interaction.
REM-01 — Timed Reminder Date Selection Does Not Preserve The Chosen Date
Reported behavior
The reminder date picker appears to work when All day is selected. When a
specific time is used, the saved reminder does not retain the intended date.
Why this matters
Incorrect reminder scheduling defeats the feature's primary purpose and can cause real work to be missed.
Intended outcome
All-day and timed reminders save the exact date intended by the user. Timezone, date, and time controls must form one predictable value across create, edit, display, and notification behavior.
Investigation questions
- Is the defect caused by local/UTC conversion, stale form state, parsing, or serialization?
- Does it reproduce in create and edit flows?
- Does the displayed date differ immediately or only after reload?
- Does the behavior vary by timezone, daylight-saving boundary, or locale?
- Do other date-time controls share the same implementation?
Resolution boundary
After fixing Reminders, audit other consumers of the same date-time primitive. The issue is complete only when timed and all-day cases have regression coverage.
Implementation result — 2026-07-28
The defect was in the reminder dialog's local date-time composition:
- single-digit minutes were formatted as invalid time-input values such as
08:5instead of08:05 - changing the date or time derived its replacement value from render-time draft state, so closely sequenced changes could restore the previous value
The reminder dialog now uses one tested local date-time helper for formatting
and replacing date, time, and all-day values. Every update derives from the
latest functional draft state. The backend already persisted dueAt
unchanged, so no schema or data migration was required.
Regression coverage now verifies:
- a date change preserves a timed reminder's time
- a time change preserves the selected date
- single-digit minutes round-trip through valid
HH:mminput formatting - all-day reminders retain the documented local
09:00convention - invalid partial inputs do not corrupt the existing timestamp
- dialog submission sends the selected local date and time with
allDay: false
A narrow audit found no other instance of the malformed minute-formatting pattern. The calendar date-time formatter pads minutes correctly.
Owner confirmation — 2026-07-28
The owner verified that timed reminder date and time selection now persists correctly. REM-01 is closed.
REM-02 — Reminder Creation Does Not Make Context Easy To Add
Reported behavior
The reminder Add control is not useful enough. While creating a reminder to
add tasks for a particular client project, it was not easy to link the reminder
through client → project, so the attempt was abandoned.
The flow also does not appear to participate adequately in client-focus mode.
Why this matters
A reminder without the context needed to act on it becomes another isolated item the user must interpret later. If adding that context requires hunting through generic record types or leaving the current client, the linking model adds work instead of preserving context.
Intended outcome
Reminder creation should inherit known client or project context and make related records easy to find. Starting in client-focus mode, from a client, or from a project should materially narrow and improve the flow.
The Add interaction should represent the useful things a reminder can refer
to in language and grouping that match the user's current job.
Decisions required
- Which contexts should prefill automatically?
- Should project choices be filtered by the selected or focused client?
- Which record types are genuinely useful reminder targets?
- Should the flow support creating a missing related item, such as a project task, or only link to existing records?
- Is
Addthe right label for this job?
Resolution boundary
Do not treat this as a larger picker alone. Success means a user can express “remind me to add tasks for this client's project” without reconstructing the relationship manually.
Implementation result — 2026-07-28
Reminder creation now treats client and project as primary structured context instead of burying them inside a generic record picker:
- the dialog exposes one compact client → project context control
- projects are scoped to the selected client, and choosing another client clears incompatible project context
- client focus prefills a brand-new generic reminder
- explicit client and project detail actions prefill their owning context
- a persisted dirty create draft wins when resumed, so a later focus change does not overwrite user work
- notes, files, time entries, commercial records, and resources remain
optional under
Add related item - existing reminders with additional legacy client/project links keep those records visible as related items rather than silently hiding them
Reminder writes now re-resolve visible client and project records, reject inaccessible or mismatched context, and store canonical titles, routes, and client/project IDs instead of trusting browser-provided snapshots. Focused UI coverage verifies inherited context, exact mutation payloads, client-scoped project choices, and incompatible-project reset. Backend coverage verifies the context authorization and canonicalization boundary. Owner dogfood confirmation remains pending.
REM-03 — Opening A Reminder From The Topbar Produces An Awkward Dialog Flow
Reported behavior
Clicking a reminder in the topbar opens a dialog. The result feels like another mini-feature embedded in the topbar rather than a coherent way to inspect and act on a reminder.
Why this matters
The topbar already carries several utilities and working records. If every type opens through a different ad hoc interaction, the shell becomes difficult to predict and maintain.
Intended outcome
Opening a reminder from the topbar should follow a deliberate, consistent working-record model. The user should be able to inspect the reminder, act on its linked context, and open a durable destination when deeper work is needed.
Decisions required
- Is a bounded preview/edit dialog appropriate for reminders, or does a reminder need a detail route?
- What should a topbar click do versus an explicit
Open reminderaction? - Which reminder actions belong in the quick view?
- How should the behavior align with Notes, Projects, and other working tabs?
Resolution boundary
Do not create a detail page solely to avoid examining the shell interaction model. Choose the correct destination based on the reminder's work scope, then make topbar behavior consistent with that choice.
Implementation result
REM-03 is implemented as a two-level reminder model:
- selecting a reminder in the topbar stays in the shell and opens a compact non-blocking quick view without creating a working tab
- pinning from the quick view is the explicit action that adds the reminder to Working
- pinned reminder tabs use the same quick view, including completed reminders
- the quick view exposes due/status, priority, details, assignees, linked
context, Complete/Reopen, permission-gated Edit, pin/unpin, and an explicit
Open reminderaction Open reminder, reminder-list rows, Today, Calendar, and new notification links use/reminders?reminderId=…to open the full reminder drawer without leaving the workspace- the detail drawer separates client/project context from other related records, honors client focus, permission-gates edit/delete, and safely handles unavailable or deleted reminders
- legacy
/reminders/[reminderId]links redirect to the canonical drawer route - pinned reminder visibility now mirrors reminder visibility exactly: creator or current assignee, never every member merely because the audience is team
- one-day snooze advances from the later of now or the existing due time and preserves the local 09:00 all-day convention
Focused UI, route-registry, date-time, notification, backend visibility, and project-workflow coverage protects the new contract. Owner dogfood confirmation remains pending.
NAV-01 — Today May Deserve Priority Over Overview In The Sidebar
Reported preference
Today should appear before Overview.
Product rationale
The first thing an operator needs is a calm answer to “what do I need to do today?” Broader agency reporting and exploration should remain available, but the navigation hierarchy should reflect the app's daily-use promise.
Intended outcome
The default entry and navigation order reduce startup stress and foreground the user's immediate work.
Decisions required
- Should
Todaymerely appear first, or should it become the default landing route? - Is the answer the same for owners, members, and users with different responsibilities?
- Does
Todaycurrently contain enough reliable, actionable information to deserve that priority? - How should
TodayandOverviewdiffer so they do not become competing dashboards?
Resolution boundary
Treat this as an information-architecture decision, not a one-line reorder. Validate the role and content of both destinations before changing the default experience.
Implementation result
Today is now the role-neutral organization home:
- the Home navigation order is
Today,Overview, thenAnalytics - authenticated app-root visits, org login without a requested destination,
completed MFA, completed onboarding, organization creation, organization
switching, signup, and verification now land on
Today - valid requested destinations are still honored, so the new default does not
force people away from intentional deep links or from
Overview - all active organization roles share the same default; Today already adapts task and workflow scope, available actions, client focus, and team controls through the existing access model
Todayremains the daily execution surface: immediate workflow, tasks, timer, agenda, reminders, and pinned notesOverviewremains the organization-health surface: cross-client attention, delivery risk, billing coverage, project load, and intervention signals- the open Today page now refreshes its date boundary and overdue calculations each minute so it does not retain yesterday's state across midnight
Focused navigation, redirect-policy, login, and proxy coverage protects the new default while explicitly confirming that intentional deep links remain intact. Owner dogfood confirmation remains pending.
TOP-01 — Pinned Projects In The Topbar Are Not Actionable
Reported behavior
Pinned projects currently provide too little useful information to justify their place in the topbar.
Why this matters
A pinned project should help the user resume work. A shortcut that exposes only identity or basic metadata does not reduce context reconstruction.
Intended outcome
A pinned project quick view should make the next useful work visible, with project tasks identified as an important candidate. It should help the operator understand current state and take a relevant action without turning the topbar into a duplicate project page.
Decisions required
- Which project information is essential in a quick view?
- Should open, assigned, due, or blocked tasks be prioritized?
- Which actions belong in the topbar and which should open the project route?
- How does the view behave when a project has many tasks or no next action?
- Can the same actionable-preview pattern serve other pinned record types?
Implementation result
Pinned projects now open a compact, non-blocking resume view instead of a reporting-heavy modal:
- the preview loads only when opened through a dedicated access-scoped project quick-view query rather than subscribing every pin to the full project detail, commercial, update, file, and time payloads
- the project client, status, concise summary, target date, due-now count, viewer-assigned count, and total open-task count establish enough context without recreating the project page
- an open blocker leads the preview and exposes its exact next action plus the durable project-blockers destination
- tasks are deliberately ranked: viewer-assigned work first, then unassigned work, then other team work; within each group, overdue/due work leads future or unscheduled work, followed by priority and project order
- the first four tasks are shown, while
Open taskshandles larger projects - task rows can complete work in place, start a timer with exact client/project/task context, or open the canonical task route
- project-level actions can start project time, add a task, or open the full project; archived projects remain readable without offering invalid writes
- unavailable or newly inaccessible projects fail safely rather than exposing stale pinned metadata
The interaction anatomy—small status context, a prioritized next-action preview, bounded inline actions, and one explicit durable destination—can guide other pinned record improvements, but no premature shared abstraction was added before a second record type proves the same behavior.
Focused shell interaction, project ranking, authorization, localization, and project-workflow coverage protects the new contract. Owner dogfood confirmation remains pending.
I18N-01 — Billing Notification Copy Appears Untranslated Or Developer-Facing
Reported example
Billing update
Panther and cub recorded customer.subscription.created. Tier: basic. Status: active.
Why this matters
The message reads like an internal event log rather than intentional product copy. Raw event identifiers and lowercase enum values suggest that localization or user-facing formatting is missing. The concern may extend beyond this one notification.
Intended outcome
Notifications use localized, human-readable copy appropriate to their audience. Internal provider event names, raw enum values, and diagnostic language should appear only where an operator genuinely needs technical detail.
Investigation questions
- Is this a missing locale key, a fallback string, or intentionally generated backend copy?
- Who is the intended recipient and what action should the notification support?
- Are organization name, event name, tier, and status localized at render time or persisted as final prose?
- Which other notification families contain raw technical vocabulary or missing translations?
Resolution boundary
Audit the notification catalog and fallback behavior rather than patching only the reported sentence. Preserve technical detail in audit logs where useful, but do not make notification copy read like a webhook payload.
Implementation result — 2026-07-28
The reported sentence came from a split and incomplete localization contract:
- billing notification metadata was created by delivery code but silently discarded during inbox insertion
- the client attempted to localize billing copy while still rendering raw Stripe event names and raw plan/status enums
- inbox action labels were persisted as final English prose
- deterministic organization and portal notification families persisted final English sentences rather than structured template data
The repaired notification contract now:
- persists structured notification metadata end to end
- renders billing events as subscription-started, changed, or ended product copy without exposing provider event identifiers
- localizes plan names, subscription statuses, and notification actions in English, Spanish, French, and Italian
- uses structured templates for organization security, webhook failure, portal access, portal account security/activity, portal support, and default reminder copy
- preserves user-authored reminder titles, reminder details, and support subjects as written
- treats platform-operator notices as the intentional technical exception because their operational detail is the product content
- replaces raw billing event and enum values in the English billing email with human-readable subscription copy
- renders legacy billing rows without metadata through safe localized generic copy, so existing inbox entries do not continue exposing provider language
Automated verification covers localized Italian billing output, legacy billing fallbacks, structured portal notifications, reminder copy ownership, destination-derived localized actions, metadata persistence, and billing email copy. App and backend typechecks, changed-file lint, and the full four-locale guard and validator pass.
PROD-01 — The App Lacks A Consistently Obvious, Low-Friction Operating Flow
Concern
The app has many of the necessary building blocks, but day-to-day use still feels like clicking around and adjusting controls until the correct path is found. The product does not yet have the “smartness” or flow expected of a modern operating tool.
This is not a request to add more explanatory copy, more settings, or more steps. It is a request to make the product infer and preserve context, present the next useful action, and remove decisions that do not benefit the user.
Why this matters
Feature completeness is not product coherence. A freelancer or agency operator spends most of the day doing client work, making notes, coordinating projects, tracking follow-through, communicating, and switching contexts. If those activities remain cumbersome, billing and administrative breadth will not make the app worth adopting.
Product outcome
The product should behave as a connected operating layer:
- current client and project context follows the user where appropriate
- create flows prefill what the app already knows
- saved records lead naturally to the next useful action
- daily priorities are more prominent than passive reporting
- related work is visible without forcing the user through feature silos
- interruptions do not require the user to reconstruct their working context
- common behavior is consistent enough to become instinctive
Required product exercise
Review the app feature by feature and job by job, beginning with the operator's daily work rather than the existing route map.
For each job, document:
- the trigger that brings the user into the app
- the context the app already knows
- the smallest successful path
- the state or handoff produced by success
- the next likely action
- where the current flow asks the user to repeat, classify, approve, link, or navigate unnecessarily
Resolution boundary
This concern cannot be closed by one feature or a cosmetic redesign. It should produce explicit product principles and a sequenced set of bounded workflow changes. It must also remain grounded in real dogfooding rather than speculative automation.
Code-grounded operating-flow audit — 2026-07-28
The first full pass is captured in
../development/operator-job-flow-audit.md.
The audit confirms that aegi should not introduce one mandatory agency funnel. The client account remains the anchor while projects, time, billing, files, portal access, and commercial records stay optional and interoperable. The experience direction is “quietly prepared”: surface what genuinely needs the viewer, what is committed today, and what they can continue, without declaring one correct next move.
The repeated friction is concentrated in seven bounded seams:
- visible record context is not yet a shared shell-level create contract
- genuine attention is mixed with prompts to adopt optional features
- a few high-frequency completion paths still end without an actionable handoff
- Today has the right work but no bounded cross-queue
Start hereordering - billing readiness needs owner dogfooding now that one optional period loop exists in Invoices
- exact portal spotlight routing now needs owner dogfooding
- the quick-action dock cannot become safely state-aware until context and recommendation truth are stable
The product direction is confirmed. The first implementation slice is safe working-scope inheritance, followed by separating state-driven client attention from optional client-scoped creation.
PROD-01A implementation result — 2026-07-28
The first system-contract slice is now implemented:
- client and project detail routes publish temporary visible working context to one shell-owned contract
- global creation consistently resolves explicit context, then visible route context, then persistent client focus
- project context now reaches global task, timer, note, reminder, drive, link, and contract entrypoints where those records support it
- client context reaches the related delivery, capture, commercial, file, link, and portal entrypoints
- changing visible route context does not change persistent client focus
- explicit mismatched context drops unsafe inherited project/task context instead of composing an invalid relationship
This establishes a reusable product-law layer rather than adding another page convention. PROD-01B can now remove absent optional features from client attention and leave them available as quiet client-scoped creation choices.
PROD-01B implementation result — 2026-07-28
Client overview attention now represents current operational truth:
- an enabled portal without the person/access context it needs remains actionable
- an existing billing profile in
attentionorpast_dueremains actionable - missing projects, invoices, subscriptions, files, and unused billing setup no longer appear as recommendations merely because the feature has not been adopted
- permission-valid person, project, invoice, and subscription actions remain
nearby in a separate
Creategroup
This preserves flexible freelancer and agency workflows while keeping the client page useful. The user can adopt any supported structure without aegi describing the absence of that structure as a problem.
PROD-01C implementation result — 2026-07-28
High-frequency completion paths now preserve momentum while exposing the exact durable result:
- topbar timer quick-stop offers
Open entryfor the saved time entry - reminder creation offers
Open reminderwhile retaining the existing pinned working-record promotion - portal support and project request creation offer
Open requestwithout forcing the user away from the current page - exact portal request routes preserve the selected client workspace and focus the created request inside its existing history
- the actionable-success helper now belongs to the shared locale surface rather than the organization route tree
The request and portal response audit also established a restraint rule: replies, owner changes, resolutions, approvals, acknowledgements, and uploads remain confirmation-only when the user is already inside the exact causal record or the success already exposes the submitted file. Action links are for lost context, not decoration.
PROD-01D implementation result — 2026-07-28
Today now orients the workday without choosing the user's work for them:
Needs youdefaults to actionable operational records owned by the viewer or available in an unassigned shared queueTodayholds overdue and due-today tasks, due reminders, and commitments on the viewer's local calendar dateContinueholds the active timer, pinned notes, and every remaining open task- one page-wide task scope switches between viewer/unassigned tasks and all team tasks
- the operational lane retains its separate explicit team-queue view
- calendar, reminder, project, note, timer, and exact working-record destinations remain directly available
The old numeric task-focus score was removed. Tasks keep their backend-defined ordering within deterministic due and continue partitions, so unlike work is no longer presented as one speculative universal ranking.
PROD-01E implementation result — 2026-07-28
Invoices now provides an optional, period-based billing-readiness loop without turning tracked time into required work:
All invoicesshows readiness only when the viewer may invoice, Stripe is ready, and eligible time exists- the period defaults to the current month and supports shared week, month, quarter, year, and custom range controls
- results are grouped by client and currency and summarize duration, accurately calculated value, project/general-work scope, and period
Prepare invoicecarries the client, currency, and exact period into a separate draft; it never overwrites an unrelated manual invoice draft- the invoice composer still requires an explicit
Add to invoiceconfirmation before reserving exact time entries - historical hourly rates and currencies are preserved, while current non-billable and subscription coverage still exclude work correctly
- pending-review, retainer, non-billable, reserved, invoiced, and subscription-covered time never contributes to readiness
- missing rates and oversized periods fail visibly and safely instead of producing a plausible but incomplete amount
Manual invoices, manual lines, project-specific invoices, and organizations that do not track time retain their existing direct path. Readiness is a shortcut for available billing input, not an obligation or a new work queue.
PROD-01F implementation result — 2026-07-28
Portal follow-through now preserves the causal record whenever the authorized workspace already has its identity:
- recent project spotlights open project detail rather than Projects
- recent shared files and featured resources open their exact artifact when a direct URL exists; URL-less file records are focused inside Files
- submitted support requests and agency replies focus the exact request thread
- file-request attention focuses the exact request and its current next step
- project-update attention opens the project and focuses the exact update
- contract attention opens the exact agreement review dialog, quote attention focuses the exact quote, and invoice attention opens invoice detail
- exact handoffs scroll, focus, and visibly mark only records present in the viewer's authorized result set
Request response and acknowledgment success stays quiet when the user is
already on the causal request. Generic Open Files toast actions were removed
from those cases, while standalone uploads still offer the exact created file.
Portal relationship attention also no longer exposes draft quotes that the
Agreements workspace correctly keeps internal.
PROD-01G implementation result — 2026-07-28
The quick-action dock is now subtly state-aware without becoming a second sidebar, overview, or pinned-work surface:
- the attention source is the existing viewer-specific operational workflow truth used by Today
- one actionable record opens its exact blocker, time entry, file request, support request, or client-feedback destination
- two or more unrelated records open the anchored
Needs youlane rather than receiving a speculative universal priority - teammate-owned and view-only records never create a personal cue
- persistent client focus scopes the cue and destination
- the collapsed dock uses only a small attention dot; the expanded action shows a truthful count and contextual accessible label
- configured create actions retain their order, shortcuts, permissions, and behavior, and the attention action is not mixed into customization
- optional billing readiness remains in Invoices and does not masquerade as an interruption
PROD-02 — Personal, Linked, Internal, And Client-Visible Concepts Are Too Exposed
Concern
The interface asks users to understand distinctions such as:
- personal versus organizational
- linked versus unlinked
- client-associated versus project-associated
- internal versus client-visible
- viewable versus not viewable to a client
Some of these distinctions are necessary for permissions and data safety, but the current experience makes the user carry too much of the underlying product model.
Why this matters
Users should not need training in the app's storage and visibility model to capture ordinary work. Repeated classification increases hesitation and creates the risk of accidental disclosure or incorrectly isolated records.
Intended outcome
The system should choose safe, useful defaults from the current context. The UI should expose a distinction only when changing it is meaningful for the user's job.
Technical capabilities may remain in the data model while being:
- inferred from context
- defaulted safely
- progressively disclosed
- grouped under clearer user-facing language
- removed from routine flows when they do not affect the outcome
Decisions required
- What is the simplest user-facing vocabulary for ownership, relationship, and visibility?
- Which distinctions are required for authorization or disclosure safety?
- Which distinctions can be derived from the owning surface?
- Which controls should be exceptional rather than always visible?
- Does linking a record change ownership, visibility, discoverability, or only context?
- What defaults should apply in personal, client, project, and client-focus contexts?
Resolution boundary
Do not simplify this only by renaming labels. First define the canonical product model and safety invariants, then decide which parts the interface must reveal.
ARCH-01 — UX Inconsistency Is Reinforced By God Files And Fragmented State Ownership
Concern
The codebase contains large files, accumulated “slush,” and parallel implementations of behavior that should be identical. Notes and topbar state are the clearest reported example, but the same risk applies to linking, visibility, creation, date-time inputs, record previews, and other shared UX contracts.
The open sequencing question is whether to define the deep product model first or refactor the existing code first.
Why this matters
A broad structural cleanup without settled product contracts may preserve the wrong abstractions more neatly. A broad UX redesign on top of fragmented state ownership may deepen duplication and make behavior harder to align.
Intended outcome
Refactoring should follow confirmed product invariants and make those invariants hard to violate:
- one canonical record identity across presentations
- one owner for each class of state
- one shared contract for repeated behavior
- clear feature and route boundaries
- small adapters for presentation differences
- tests that cover cross-surface behavior, not only individual components
Recommended sequencing principle
Use alternating product and architecture slices:
- Confirm one deep product invariant.
- Trace every current implementation of that invariant.
- Refactor only the ownership and shared boundary needed to enforce it.
- implement the improved UX on that boundary.
- Add cross-surface regression coverage.
- Repeat with the next invariant.
This avoids both an unbounded cleanup project and continued patching of contradictory behavior.
Candidate first invariant
“A note is one canonical record viewable and editable through multiple surfaces” is a strong first slice because NOTE-01 is already trust-breaking and the desired product model is explicit.
Shared shell ownership slice — 2026-07-28
The active-timer retest exposed a broader version of ARCH-01: independent
stateful hook instances and parent-owned overlay controls could make two shell
surfaces disagree or make one action intercept another. The app-wide audit
found and removed a second organization SessionAccessProvider, centralized
the persistent organization shell providers, and gave calendar consumers and
minute-based urgency displays one controller/clock each.
The timer and client-focus split controls now use the shared ButtonGroup
primitive in normal document flow. Numeric z-index utilities were removed from
the app surface in favor of the semantic stack. architecture:guard now blocks
duplicate org shell state owners, nested rendered controls, undeclared
absolute/fixed controls, and numeric or arbitrary z-index utilities during
lint.
Resolution boundary
Do not turn this inventory into authorization for an application-wide rewrite. Produce a separate, code-grounded refactor plan after the product invariants and affected ownership boundaries have been inspected.
Suggested Investigation Order
This is a discussion order, not permission to implement the entire list:
- NOTE-01: restore trust in canonical note state.
- REM-01: correct reminder date-time persistence.
- I18N-01: audit user-facing notification localization and raw event copy.
- TIME-01: confirm the automatic capture and review-routing policy.
- NOTE-02: define and implement the universal Notes autosave contract.
- PROD-02: simplify ownership, linking, and visibility vocabulary and defaults.
- REM-02: rebuild reminder context selection against that clearer model.
- NAV-01: decide the roles and priority of Today versus Overview.
- TOP-01: define actionable pinned-project behavior.
- REM-03: align reminder opening with the working-record shell model.
- NOTE-03: right-size note creation after the note surface model is clear.
- NOTE-04: complete topbar note actions under the canonical note model.
- PROD-01: continue the broader job-by-job operating-flow review.
- ARCH-01: run architecture slices alongside the confirmed product work.
The first five items address immediate trust, correctness, confusing product copy, and repeated daily friction. The foundational reviews continue in parallel as product work, but should be converted into bounded implementation issues before code changes begin.
Related Product And Implementation Docs
../product/notes-and-today-spec.md../product/reminders-spec.md../product/entries-and-timer-v1.md../product/client-operating-model.md../development/org-topbar-working-tabs.md../development/notes-and-timer-follow-through-audit.md../development/agency-owner-smart-workflows.md../development/cross-feature-surface-audit.md
Issue Status Log
Update this table as individual passes are completed.
| ID | Status | Evidence or decision link |
|---|---|---|
| NOTE-01 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| NOTE-02 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| NOTE-03 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| NOTE-04 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| TIME-01 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| REM-01 | Closed; owner confirmed | Owner confirmation in this document |
| REM-02 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| REM-03 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| NAV-01 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| TOP-01 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| I18N-01 | Implemented; automated checks passed; owner dogfood confirmation pending | Implementation result in this document |
| PROD-01 | In progress; doctrine confirmed, PROD-01A through PROD-01F implemented | ../development/operator-job-flow-audit.md |
| PROD-02 | Foundational concern captured | — |
| ARCH-01 | In progress; shell ownership slice and automated guards implemented | Shared shell ownership result above |