Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/IMPLEMENTATION_MASTERPLAN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Taskdeck Implementation Masterplan

Last Updated: 2026-06-30
Last Updated: 2026-07-02
<br>
Planning Horizon: the finite archive-pivot waves (Paper UI activation → easy local run → general quality → archive), then archival — _(historical: this was an open "Next 8 to 12 weeks" release horizon before the 2026-06-13 archive pivot)_
Companion Active Docs:
Expand Down Expand Up @@ -54,6 +54,10 @@ Update this file at the end of each meaningful delivery cycle or when new work i

Delivered in the latest cycle:

Security + a11y quality slices (2026-07-02, **2 PRs merged** — `#1263` (`#1241`), `#1265` (`#1218`); full review gate per PR — independent adversarial reviews, all-severity findings fixed or tracked, Gemini/Copilot bot rounds resolved (+Codex rounds on `#1263`), fresh green CI + aging):
- **Windows secrets-at-rest ACL:** `#1263` (`#1241`) locks `appsettings.local.json` (JWT secret + connector encryption key) to the current user — `RestrictFileToCurrentUser` (Unix `0600` / Windows protected owner-only DACL, dependency-free on net8.0) runs create→restrict→write in `PersistValue`, fail-closed (an unrestrictable file is never written; callers fall back in-memory), with startup forward remediation for pre-`#1241` installs and a locked-down `.corrupt-*` backup. Review rounds also hardened the **MCP launch paths**: both MCP modes now load the local config via the same hardened path as the web API (absolute exe-adjacent path — MCP clients launch stdio servers from arbitrary CWDs; corrupt-file quarantine; env-vars keep priority over the file). Seeded: `#1262` (CLI bootstrapper sibling), `#1264` (atomic create-with-ACL — in flight as `#1267`).
- **WCAG focus-ring contrast sweep:** `#1265` (`#1218`) resolves all 19 remaining `ring-primary/50` sites (0 left repo-wide): 13 rendered focus rings + the selected-label state ring lifted to the full-opacity treatment (`#1216` precedent) — from a marginal 3.0–3.5:1 to 8.4–10.1:1 on every adjacent surface across all shipped themes — and 5 compile-proven dead checkbox `focus:ring-primary` classes removed (no ring-width utility, so they never painted; the global `*:focus-visible` rule already covers those checkboxes at 4.52:1). Seeded: `#1266` (pre-existing white ring-offset halo on the selected-label state).

Wave-3 default-theme flip — Paper is now the DEFAULT UI (2026-06-27, `#1252`): `paperThemeStore` default `'off'`→`'paper'` (Paper canonical per ADR-0038), with the storage key bumped to `td.paper.mode.v2` and a one-time migration (a deliberate pre-flip `paper`/`paper-night`/`auto` choice carries over and the legacy key is cleared; a stored `'off'` — the old default / never-opted-in — or absent/invalid resolves to the new `'paper'` default). Legacy stays reachable through the Appearance toggle and is pinned in the test suites: the E2E `authSession` helper and a global vitest `setup.ts` hook both pin `td.paper.mode.v2='off'` so the ~19 legacy `.td-*` E2E specs and the Legacy-DOM unit specs keep asserting Legacy, while Paper-variant specs opt in explicitly. Review: a 2-lens adversarial sweep (0 confirmed) + Gemini round (migration inlined into `readStoredMode`); CI caught a 112-spec blast radius (the view shells render Paper by default) → fixed with the global off-pin; full FE suite green (3,752 tests).

Paper-review de-stubs — Wave-2 completion (2026-06-27, 1 PR; built design-first): the last two stubbed Paper deep-Review handlers were wired to net-new backend, **unblocking the Wave-3 default-theme flip** (now shipped, above):
Expand Down
7 changes: 4 additions & 3 deletions docs/STATUS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Taskdeck Status (Source of Truth)

Last Updated: 2026-06-30
Last Updated: 2026-07-02
<!-- 2026-07-02: post-merge sync — #1263 (#1241, Windows owner-only ACL on appsettings.local.json secrets at rest + hardened MCP local-config loading: absolute path, quarantine, env-var priority) and #1265 (#1218, WCAG focus-ring contrast sweep to full opacity + dead checkbox ring classes removed) merged. Seeded: #1262, #1264 (in flight as #1267), #1266. -->
<!-- 2026-06-30: post-merge sync — two Wave-6 seeded follow-ups shipped: #1239 (#1254, push the capture board pre-filter into SQL) and #1209 (#1256, recover non-capture LlmRequests stuck in Processing). -->
<!-- 2026-06-19: post-merge sync — #1219/#1220/#1221/#1225 merged to main; Paper-activation toggle + File-away dismiss now shipped. -->
<!-- 2026-06-26: post-merge sync — #1236 (#1195) / #1238 (#1193) / #1240 (#1131) merged to main; Wave-6 backend bounds + desktop run-story connector key shipped. -->
Expand All @@ -12,7 +13,7 @@ Wave-6 backend + run-story delivery (2026-06-26, **3 PRs merged**; full review g
- **`#1238` (`#1193`) — paged `CaptureService.ListAsync` from the database.** New capture-only `GetCapturesByUserAsync(userId, limit, offset)` (newest-first `ORDER BY CreatedAt DESC, Id`, SQLite raw + EF) replaces loading the user's entire `LlmRequest` history then filtering/paging in memory; a fetch-until-enough loop with a `seenIds` dedup guard keeps filtered queries correctly filled across OFFSET page boundaries. `GetByUserAsync` untouched → GDPR-safe. Seeded `#1239` (push board/status filters into SQL).
- **`#1240` (`#1131`) — made the self-contained desktop exe runnable without manually supplying a connector key.** `ShouldAutoGenerateConnectorKey(isProd, isHeadless) => !isProd || !isHeadless`: a desktop install (Production, not headless) auto-generates + persists the connector encryption key to `appsettings.local.json`; **headless Production (CI / container / Terraform) still hard-fails** without a supplied stable key (`backend.Dockerfile` sets `TASKDECK_HEADLESS=true` so every container image is classified headless). The AWS single-node Terraform `user_data` generates+persists the key onto the durable EBS data volume (refusing to regenerate when a DB already exists without a key), `scripts/backup.sh`/`restore.sh`/`restore.ps1` keep the key paired with the database, and a deep review loop hardened the persistence path against silent key loss (reuse a masked persisted key instead of overwriting it; self-heal a corrupt local config; case-insensitive + provider-lenient reads; read-vs-parse error separation; owner-only ACL on the restored key). **`ADR-0041`** records the decision. ~15 distinct review findings (1 HIGH + many P2) across 6 Codex rounds + a 2-lens adversarial sweep, all fixed with tests.
- **ADR added on main:** `ADR-0041` (desktop connector-key auto-generation; headless Production excluded).
- **Seeded follow-ups:** `#1237` (bound remaining unbounded Pending reads) **— shipped (`#1250`)**; `#1239` (push capture board/status filters into SQL) **— board pre-filter shipped 2026-06-30 (`#1254`); the status filter stays in-service (provenance-derived), so `#1239` remains open for that portion**. Still open from earlier: `#1241` (Windows ACL on the desktop key file), `#1242` (relocate persisted secrets to the durable app-data location).
- **Seeded follow-ups:** `#1237` (bound remaining unbounded Pending reads) **— shipped (`#1250`)**; `#1239` (push capture board/status filters into SQL) **— board pre-filter shipped 2026-06-30 (`#1254`); the status filter stays in-service (provenance-derived), so `#1239` remains open for that portion**. Shipped from earlier: `#1241` (Windows ACL on the desktop key file) **— 2026-07-02 (`#1263`)**. Still open from earlier: `#1242` (relocate persisted secrets to the durable app-data location).

Direction + canonical UI (2026-06-13, maintainer-decided):
- **Project direction is finish-for-personal-use, then archive.** Taskdeck will not be distributed; the goals are to finish and activate the Paper UI, make the app trivially easy to run locally, land general quality improvements, and archive cleanly. This supersedes the 2026-06-05 ship-first framing; distribution-era tracks (code-signing, GTM, cloud, mobile) are de-scoped.
Expand All @@ -23,7 +24,7 @@ Archive-pivot delivery wave (2026-06-13, **17 PRs merged** across Waves 0–2, i
- **Wave 1 — decision + cheap foundations (3 PRs):** **ADR-0038 ratified — Paper is the canonical UI, Legacy frozen `#1207`** (STATUS + masterplan now state the canonical stack; storage-key migration deferred to the Wave-3 flip); `#1139` AC1 compose-secret quickstart docs `#1205` (README + `docs/ops/DEPLOYMENT_CONTAINERS.md` now name BOTH required secrets, since compose aborts on a missing `TASKDECK_CONNECTORS_ENCRYPTION_KEY`); `*.migrate.lock` gitignored + `.dockerignore` mirror `#1204` (the SerializedMigrator sidecar no longer dirties `git status` on every startup).
- **Wave 2/6 — Paper activation prerequisites + backend quality (5 PRs):** paper-night straggler tokenization `#1216` (`#1135` — KeyboardShortcutsHelp border + full-opacity WCAG focus ring; seeded `#1218` for the repo-wide `focus:ring-primary/50` contrast sweep); **shared review-actionability composable `#1217`** — extracted `isProposalApplyActionable` / `isProposalRejectActionable` / `isProposalApproveActionable` / `isProposalDismissable` / `isProposalStale` as pure functions in `useReviewProposals` so Paper and Legacy can never drift at the 24h-stale or Approved+expired boundaries (the `#1124` bug class is now fixed once, not twice), and de-stubbed the fabricated `4s · 1.2k tokens` author metadata in favour of the real `/confidence` value; dead-code removal `#1198`/`#1214` (see below); Redis lock-starvation fix `#1213` (`#1189` — dropped the in-lock retry loop and the 3s blocking Connect inside the lock; single attempt per throttle window → null/no-cache fallthrough, proven by deterministic regression guards); **one-command dev-up + clean-workspace scripts `#1208` (`#1140`)** — `dev-up.ps1/.sh` (dependency check, `%LOCALAPPDATA%` DB path to fix the CWD-dependent `taskdeck.db`, port-bound API via `--no-launch-profile --urls`, `/health/ready` poll, npm dev, optional `-Seed demo/demo123`) and `clean-workspace.ps1/.sh` (stray DBs/migrate-locks/logs, process-held-DB refusal), with recursive process-tree kill, live-PID-file refusal, and a `.migrate.lock` guard against deletion during an active migration; the dev-up DB-pinning path was live-smoke-verified before merge.
- **ADRs added on main:** `ADR-0038` (Paper UI canonical / Legacy frozen), `ADR-0039` (Central Package Management, SDK pin, 8.x dependency alignment), `ADR-0040` (global UTC DateTime materialization for SQLite).
- **Seeded follow-ups:** `#1209` (no sweeper recovers non-capture `LlmRequests` stuck in Processing) **— shipped 2026-06-30 (`#1256`)**; `#1215` (`FieldVerifier`/`DeterministicPreExtractor` registered-but-unconsumed after V1 removal — keep-for-V2 decision), `#1218` (repo-wide focus-ring contrast sweep).
- **Seeded follow-ups:** `#1209` (no sweeper recovers non-capture `LlmRequests` stuck in Processing) **— shipped 2026-06-30 (`#1256`)**; `#1215` (`FieldVerifier`/`DeterministicPreExtractor` registered-but-unconsumed after V1 removal — keep-for-V2 decision), `#1218` (repo-wide focus-ring contrast sweep) **— shipped 2026-07-02 (`#1265`)**.
- **Merged 2026-06-19** (maintainer lifted the merge hold; all four shipped to `main` after 2 independent adversarial reviews, all-severity findings fixed, fresh green CI):
- `#1219` (`#1161`) — Paper review "File away" dismiss affordance built on the `#1217` shared-actionability foundation (per-proposal filing rail in terminal states + bulk "File away N settled" + dual-purpose ⌫). Closes `#1161`.
- `#1221` — reachable in-app **Appearance** theme toggle (`AppearanceSettingsView` at `/workspace/settings/appearance`; off / paper / paper-night / auto), the reachable Legacy escape hatch that replaces the unlinked `/styleguide/paper` route — a Paper-activation prerequisite.
Expand Down
Loading