Skip to content

feat(daily): GTD/todo surface redesign — due-based Today, Inbox split, status-flow Todos, routines overview#16

Merged
Koopa0 merged 7 commits into
mainfrom
feat/gtd-todo-redesign
Jun 30, 2026
Merged

feat(daily): GTD/todo surface redesign — due-based Today, Inbox split, status-flow Todos, routines overview#16
Koopa0 merged 7 commits into
mainfrom
feat/gtd-todo-redesign

Conversation

@Koopa0

@Koopa0 Koopa0 commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

Reshapes the admin Daily surface around a due/recurring-driven workflow (the owner does not build daily plans, so the old plan-driven model read empty).

  • Today hero → due-based. The day-progress strip is now Open / Completed / Overdue, derived from what is actually scheduled today (due-today + recurring-due + in_progress; today's completions incl. recurring last_completed_on=today; past-due-still-open). It no longer reads the committed daily_plan (which was empty → a constant 0/0/0, plus a latent bug: the front end counted daily_plan_items.status, a column with no write path). Backend adds CompletedTodoItemsOn / Store.CompletedItemsOn feeding a new completed_todos section; the dead PlanCompletion block is removed. Completing a row updates the strip live.
  • Inbox split into its own page (/admin/daily/inbox). Capture + triage only, reusing the GTD store/row/clarify-modal locked to the inbox view. Previously Inbox and Todos were the same component differing only by a route flag.
  • Todos = status-flow tabs: Pending / In Progress / Someday / Complete. The Today, Inbox, and Recurring tabs and the capture bar are gone. Complete (已了結) is backed by a resolved-since query (done + dropped/archived + recurring occurrences), badging each row's kind. Recurring routines are excluded from the working status tabs.
  • Per-row detail panel. Clicking a row's title opens a panel surfacing state / project / due / energy / recurrence and the actions previously hidden behind hover + keyboard (advance, defer, drop, make/edit routine).
  • Routines overview (/admin/daily/routines, new sidebar entry). Lists every active recurring schedule from the recurring endpoint's new all bucket — the home for a routine on its off-days, which neither the Today due-today list nor the recurring-excluding status tabs show. Read-only; editing is via the Todos detail panel.
  • Frontend TodoState widened to match the backend enum (archived, dismissed); semantic-contract note added (human Today = due-based vs MCP brief(reflection) = plan-based; routines manage-all surface).

Test Plan

Automated verification — all green:

  • Backend: go build ./..., go vet (incl. -tags integration), golangci-lint (0 issues), unit tests, and integration tests against real PostgreSQL (testcontainers) for internal/todo, internal/today, internal/daily — including the extended History (resolved: done + dropped + recurring) and Recurring (all bucket) assertions.
  • Frontend: tsc (app + spec), ng lint (0), 609 unit tests, ng build (AOT, full template type-check).
  • L1 review on slice 1 (go-reviewer + db-reviewer): no BLOCKING.

⚠️ Visual / runtime acceptance is NOT done in this PR — the live-render "no 跑版 (layout break)" check requires the running app and is reserved for the owner's review. Eyeball these four routes after pulling: /admin/daily/today, /admin/daily/inbox, /admin/daily/todos (Pending/In Progress/Someday/Complete + click a row for the detail panel), /admin/daily/routines.

Koopa0 added 4 commits June 30, 2026 11:02
The Today strip counted only the committed daily plan (daily_plan_items),
so it read 0/0/0 whenever no plan was built — the normal case for a
recurring/due-driven workflow. Recompute it from what is actually
scheduled today: Open = due-today + recurring-due + started, Overdue =
past-due still open, Completed = finished today (one-time done today plus
recurring occurrences stamped today). The front end derives the strip
from the section lengths, so completing an item updates it live without a
refetch and without a committed plan existing.

Adds CompletedTodoItemsOn / Store.CompletedItemsOn for the done-today
section and removes the dead plan-based PlanCompletion counting — the
daily_plan_items.status column it read has no write path, so it always
reported planned.
Inbox and Todos were the same GtdPageComponent differing only by a route
data flag. Inbox now has its own page (capture + triage), reusing the GTD
store, row, and clarify modal locked to the inbox view. The Todos page
becomes a pure status-flow surface: Pending / In Progress / Someday /
Complete. The Today and Recurring tabs and the capture bar are gone —
"today" lives on the Today dashboard, routines in their own overview and
each row's detail, and capture in the Inbox.

The Complete tab is backed by a resolved-since query (done + dropped/
archived + recurring occurrences), so a recurring routine's daily
completion is visible there; rows badge their resolution kind (done /
dropped / recurring). Recurring routines are excluded from the working
status tabs so the flow stays free of daily routines.

Also adds AllRecurringTodoItems for the upcoming routines overview, and
widens the frontend TodoState to match the backend enum (archived,
dismissed).
The row's actions (advance, defer, drop, edit recurrence) and its facts
(state, project, due, energy, whether it is a recurring routine) were only
reachable through hover affordances and keyboard verbs. Clicking a row's
title on the Todos page now opens a detail panel that surfaces all of them
in one place, including making or editing the todo's recurrence. The panel
emits intent against the open target; the store owns the round-trips and
closes the panel after a mutation so the backlog reload doesn't pull the
row out from under it.
Removing the Recurring tab left a routine on its off-days with nowhere to
appear — the Today dashboard shows only what is due today, and the Todos
status tabs exclude routines. Add a Routines page (sidebar entry under
Daily) that lists every active recurring schedule from the recurring
endpoint's new `all` bucket, with its schedule, a due-today marker, and
when it last ran. Read-only: a routine's schedule is edited from its
Todos detail panel; today's occurrence is completed on Today.

Records the two cross-surface decisions in the semantic contract: the
human Today dashboard is due-based while the MCP brief(reflection) stays
plan-based, and routines have a manage-all surface distinct from due-today.
@augmentcode

augmentcode Bot commented Jun 30, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR reshapes the Admin Daily UI around a due/recurring-driven workflow instead of a plan-driven one, so Today/Todos reflect actual work even when no daily plan is committed.

Changes:

  • Today “day progress” strip becomes due-based (Open/Completed/Overdue) and removes the old plan-completion model
  • Adds a completed_todos section to the Today aggregate and wires optimistic completion updates to keep the strip live
  • Splits Inbox into a dedicated /admin/daily/inbox capture + triage page reusing the GTD store/row/clarify-modal
  • Reworks Todos into status-flow tabs: Pending / In Progress / Someday / Complete (resolved history)
  • Adds a per-row detail modal for state/project/due/energy/recurrence + actions previously hidden behind hover/keys
  • Adds a new read-only Routines overview at /admin/daily/routines

Technical Notes: Backend expands /todos/recurring with an all bucket, replaces history with a “resolved since” query (done + dropped + recurring occurrences), and updates types/enums to include archived/dismissed.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread internal/todo/query.sql Outdated
completed_at, energy, priority, recur_interval, recur_unit, recur_weekdays, last_completed_on,
description, created_by, created_at, updated_at
FROM todos
WHERE state NOT IN ('archived', 'dismissed')

@augmentcode augmentcode Bot Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AllRecurringTodoItems is described as “every active recurring schedule”, but the predicate only excludes archived/dismissed and will still include state='done' (and potentially other non-active states). This can make the Routines overview show closed routines; consider excluding terminal done here to match the “active” semantics used elsewhere (e.g. RecurringTodoItemsDueToday).

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f54fb0c — confirmed valid. AllRecurringTodoItems now uses the same active-state filter as RecurringTodoItemsDueToday (excludes done/someday/inbox/archived/dismissed), so the Routines overview is a strict superset of due-today and never lists a closed routine. Added integration coverage that a terminally-done recurring row appears in neither bucket.

@augmentcode

augmentcode Bot commented Jun 30, 2026

Copy link
Copy Markdown

augment review

AllRecurringTodoItems excluded only archived/dismissed, so a recurring row
that had been terminally closed (state=done) — reachable e.g. by setting a
recurrence on an already-done todo — would still show in the Routines
overview as if it were a live schedule. Match the active-state filter
RecurringTodoItemsDueToday uses (also excluding done/someday/inbox), so the
overview is a strict superset of the due-today list and never lists a closed
routine; those rows remain reachable on their own Complete/Someday/Inbox
surfaces. Adds integration coverage that a done recurring row appears in
neither bucket.

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

this.store.advanceRow(row);
break;
case 'clarify':
this.store.clarifyTarget.set(row);

@augmentcode augmentcode Bot Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InboxPageComponent.handleKeydown sets store.clarifyTarget directly for the clarify action; this bypasses store.openClarify() which resets clarifyIntent to 'clarify'. If the user previously hit t (pull) on an inbox row, the intent can stay 'pull' and a later keyboard-clarify could unexpectedly append the clarified todo to today’s plan.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 05e75a6. Confirmed it is not yet reachable (the keyboard clarify case only fires when clarifyTarget is null, and every path that nulls it also resets intent to clarify), but routing through openClarify() removes the fragility so a future change cannot leak a stale pull intent into a keyboard clarify.

Comment thread internal/todo/handler.go
completed, err := h.store.CompletedItemsDetailSince(r.Context(), since)
// Resolved-since path: the default Complete-tab view — done, dropped, and
// recurring routines' recent occurrences.
resolved, err := h.store.ResolvedItemsDetailSince(r.Context(), since)

@augmentcode augmentcode Bot Jun 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the default history endpoint returns “resolved” items (done + dropped + recurring occurrences), the ?q= search path still goes through SearchItems with a completed_after filter (based on completed_at), so dropped/recurring resolutions likely won’t be searchable in the Complete tab. Also, the function header comment above still says “completed-since path,” which no longer matches the new semantics.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 75ef4f1 — confirmed valid. The ?q= path now uses SearchResolvedTodoItems, which applies the same resolution arms as ResolvedTodoDetailSince (done/dropped/recurring), so dropped and recurring resolutions are searchable in the Complete tab; the stale completed_at-only SearchItems/SearchTodoItems/SearchDetail are removed and the History doc comment is corrected. Integration coverage added: ?q=Japanese finds the recurring occurrence and ?q=do returns the dropped row but not a non-resolved pending one.

Koopa0 added 2 commits June 30, 2026 12:17
The inbox keyboard 'clarify' action set clarifyTarget directly, bypassing
openClarify() which resets the clarify intent. The intent only ever
becomes 'pull' alongside an open modal today, so this was not yet
reachable — but poking the signal instead of the store's API left a stale
'pull' intent one refactor away from making a keyboard clarify silently
append the todo to today's plan. Use openClarify so the intent is always
reset.
The default Complete view returns resolved todos (done + dropped + recurring
occurrences), but the ?q= search path still filtered on completed_at, so
dropped rows (no completed_at) and recurring occurrences (last_completed_on)
were unsearchable — searching for a completed routine returned nothing.
Replace the completed_at-scoped SearchTodoItems with SearchResolvedTodoItems,
which applies the same resolution arms as ResolvedTodoDetailSince, so both
Complete-tab paths search the same set. Removes the now-dead SearchItems /
SearchTodoItems / SearchDetail and fixes the stale History doc comment. Adds
integration coverage that ?q= finds a dropped and a recurring resolution and
still excludes a non-resolved pending row.
@Koopa0 Koopa0 merged commit 7229509 into main Jun 30, 2026
5 checks passed
@Koopa0 Koopa0 deleted the feat/gtd-todo-redesign branch June 30, 2026 04:19
@Koopa0

Koopa0 commented Jun 30, 2026

Copy link
Copy Markdown
Owner Author

augment review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant