loki-mode 10.7.1 → 10.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/README.md +2 -2
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/loki +20 -32
  5. package/autonomy/run.sh +9 -5
  6. package/autonomy/tui.sh +5 -1
  7. package/dashboard/__init__.py +1 -1
  8. package/dashboard/api_phases.py +1 -1
  9. package/dashboard/api_start.py +0 -1
  10. package/dashboard/server.py +28 -146
  11. package/docs/COCKPIT-SPEC.md +3 -1
  12. package/docs/DASHBOARD-9.12-EVIDENCE.md +1 -1
  13. package/docs/DASHBOARD-ARCHITECTURE.md +13 -11
  14. package/docs/DASHBOARD_V2_CHECKLIST.md +2 -0
  15. package/docs/INSTALLATION.md +12 -11
  16. package/docs/MERGE-DEDUP-MAP.md +1 -1
  17. package/docs/MERGE-ROUTE-MAP.md +1 -1
  18. package/docs/MERGE3-PLAN.md +2 -2
  19. package/docs/R3-COST-OBSERVABILITY-DESIGN.md +2 -2
  20. package/docs/R4-TRUST-TRAJECTORY-DESIGN.md +1 -1
  21. package/docs/R5-AUTO-WIKI-DESIGN.md +1 -1
  22. package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +1 -1
  23. package/docs/RARV-C-100X-PLAN.md +3 -3
  24. package/docs/SONNET5-DEFAULT-PLAN.md +2 -2
  25. package/docs/SYNERGY-TASKS.md +1 -1
  26. package/docs/TOOL-INTEGRATION.md +1 -1
  27. package/docs/TOP-100-BACKLOG.md +1 -1
  28. package/docs/alternative-installations.md +1 -1
  29. package/docs/architecture/ADR-001-runtime-migration.md +1 -1
  30. package/docs/architecture/DASHBOARD_V2_ARCHITECTURE.md +2 -0
  31. package/docs/audit-logging.md +2 -0
  32. package/docs/authentication.md +2 -0
  33. package/docs/authorization.md +2 -0
  34. package/docs/certification/02-enterprise-features/lab.md +2 -0
  35. package/docs/certification/02-enterprise-features/lesson.md +2 -0
  36. package/docs/certification/04-production-deployment/lab.md +2 -0
  37. package/docs/certification/04-production-deployment/lesson.md +2 -0
  38. package/docs/control-plane-migration.md +97 -0
  39. package/docs/dashboard-guide.md +6 -7
  40. package/docs/dev/release-checklist.md +9 -11
  41. package/docs/enterprise/integration-cookbook.md +2 -0
  42. package/docs/enterprise/migration.md +1 -1
  43. package/docs/enterprise/performance.md +3 -1
  44. package/docs/enterprise/sdk-guide.md +2 -0
  45. package/docs/enterprise/security.md +2 -0
  46. package/docs/plans/FORGE-AUTONOMOUS-QUEUE.md +2 -2
  47. package/docs/research-2026-07/OBSERVABILITY-TOOL-SPEC.md +1 -1
  48. package/docs/retrospectives/v7.5.15-honesty-audit.md +2 -2
  49. package/docs/test-scenarios/enterprise-scenarios.md +2 -2
  50. package/docs/v10/ARCHITECT-CUTS.md +9 -9
  51. package/docs/v10/BACKLOG.md +7 -7
  52. package/docs/v10/BOARD.md +25 -25
  53. package/docs/v10/CONTROL-PLANE.md +4 -4
  54. package/docs/v10/CP-ENTERPRISE-UI.md +270 -9
  55. package/docs/v10/D51-PHASE-B.md +1 -1
  56. package/docs/v10/DECISIONS.md +3 -3
  57. package/docs/v10/DEPS.md +10 -10
  58. package/docs/v10/FAILURE-CLASSES.md +66 -1
  59. package/docs/v10/LEGACY-REMOVAL.md +2 -2
  60. package/docs/v10/METRICS.md +6 -0
  61. package/docs/v10/SWARM.md +2 -2
  62. package/loki-ts/data/model-pricing.json +6 -6
  63. package/loki-ts/dist/cockpit.js +11 -11
  64. package/loki-ts/dist/loki.js +819 -809
  65. package/loki-ts/package.json +1 -1
  66. package/magic/core/design_tokens.py +1 -2
  67. package/magic/core/generator.py +2 -2
  68. package/magic/tokens/README.md +1 -3
  69. package/mcp/__init__.py +1 -1
  70. package/package.json +3 -8
  71. package/packages/control-plane/dist/server.js +17954 -5696
  72. package/packages/control-plane/drizzle/0004_cpe03_local_repos_actions.sql +17 -0
  73. package/packages/control-plane/drizzle/meta/0004_snapshot.json +542 -0
  74. package/packages/control-plane/drizzle/meta/_journal.json +9 -2
  75. package/packages/control-plane/package.json +4 -1
  76. package/packages/control-plane/src/db/schema.ts +19 -0
  77. package/packages/control-plane/src/server/app.ts +11 -22
  78. package/packages/control-plane/src/server/audit.ts +15 -0
  79. package/packages/control-plane/src/server/auth.ts +7 -1
  80. package/packages/control-plane/src/server/legacy/routes-audit.ts +50 -0
  81. package/packages/control-plane/src/server/legacy/routes-control.ts +26 -0
  82. package/packages/control-plane/src/server/legacy/routes-memory.ts +30 -0
  83. package/packages/control-plane/src/server/legacy/routes-metrics.ts +18 -0
  84. package/packages/control-plane/src/server/legacy/routes.ts +237 -0
  85. package/packages/control-plane/src/server/legacy/shim.ts +201 -0
  86. package/packages/control-plane/src/server/repos.ts +27 -0
  87. package/packages/control-plane/src/server/routes/artifacts.ts +104 -0
  88. package/packages/control-plane/src/server/routes/audit.ts +17 -0
  89. package/packages/control-plane/src/server/routes/checkpoints.ts +171 -0
  90. package/packages/control-plane/src/server/routes/config.ts +319 -0
  91. package/packages/control-plane/src/server/routes/control.ts +75 -0
  92. package/packages/control-plane/src/server/routes/cost.ts +70 -0
  93. package/packages/control-plane/src/server/routes/cost_ledger.ts +210 -0
  94. package/packages/control-plane/src/server/routes/fleet.ts +101 -0
  95. package/packages/control-plane/src/server/routes/index.ts +71 -0
  96. package/packages/control-plane/src/server/routes/integrations.ts +123 -0
  97. package/packages/control-plane/src/server/routes/memory.ts +219 -0
  98. package/packages/control-plane/src/server/routes/merge_risk.ts +209 -0
  99. package/packages/control-plane/src/server/routes/metrics.ts +93 -0
  100. package/packages/control-plane/src/server/routes/notify.ts +48 -0
  101. package/packages/control-plane/src/server/routes/providers.ts +111 -0
  102. package/packages/control-plane/src/server/routes/session_control.ts +155 -0
  103. package/packages/control-plane/src/server/routes/start.ts +39 -0
  104. package/packages/control-plane/src/server/routes/stats.ts +76 -0
  105. package/packages/control-plane/src/server/routes/stream.ts +85 -0
  106. package/packages/control-plane/src/server/routes/verify.ts +66 -0
  107. package/packages/control-plane/src/server/spawn.ts +79 -0
  108. package/packages/control-plane/src/shipper/discover.ts +19 -1
  109. package/packages/control-plane/ui/dist/assets/index-BQbFv65M.css +1 -0
  110. package/packages/control-plane/ui/dist/assets/index-Dbhu244h.js +155 -0
  111. package/packages/control-plane/ui/dist/index.html +2 -2
  112. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  113. package/references/magic-modules-patterns.md +2 -2
  114. package/skills/factory-operations.md +3 -3
  115. package/skills/magic-modules.md +1 -1
  116. package/skills/release-cadence.md +1 -1
  117. package/tools/audit-docs.py +1 -1
  118. package/tools/index-codebase.py +1 -1
  119. package/web-app/dist/assets/{AdminPage-BJSU5hY1.js → AdminPage-DqMnfZrH.js} +1 -1
  120. package/web-app/dist/assets/{Avatar-CSOSpw9c.js → Avatar-BEof29du.js} +1 -1
  121. package/web-app/dist/assets/{Badge-COr7vj0D.js → Badge-WD53OL5m.js} +1 -1
  122. package/web-app/dist/assets/{Button-DGoWFERp.js → Button-Rzk5flhU.js} +1 -1
  123. package/web-app/dist/assets/{CockpitPage-CBpWkNXY.js → CockpitPage-Bqz3PCMh.js} +1 -1
  124. package/web-app/dist/assets/{ComparePage-BwT8vqrL.js → ComparePage-Byo2NzAZ.js} +1 -1
  125. package/web-app/dist/assets/{ErrorBoundary-D7SicDDA.js → ErrorBoundary-BuE0kH3W.js} +1 -1
  126. package/web-app/dist/assets/{EvidenceReceiptPanel-bx-5liG2.js → EvidenceReceiptPanel-CKFHOPBx.js} +1 -1
  127. package/web-app/dist/assets/{GitHubIssuesPanel-BAeeWLqY.js → GitHubIssuesPanel-Df_kTMqI.js} +1 -1
  128. package/web-app/dist/assets/{GitHubPRsPanel-CssD8lGI.js → GitHubPRsPanel-CouvcKrZ.js} +1 -1
  129. package/web-app/dist/assets/{HomePage-SL5PT3m5.js → HomePage-dEpLzj0x.js} +2 -2
  130. package/web-app/dist/assets/{LoginPage-C8hFOZOM.js → LoginPage-6DVjUND5.js} +1 -1
  131. package/web-app/dist/assets/{MagicPage-xHbHkrPf.js → MagicPage-BDQ9MOfY.js} +1 -1
  132. package/web-app/dist/assets/{MetricsPage-B_2CKFcC.js → MetricsPage-CXiJ04G_.js} +1 -1
  133. package/web-app/dist/assets/{NotFoundPage-CXwXMq35.js → NotFoundPage-BaXhZvyj.js} +1 -1
  134. package/web-app/dist/assets/{ProjectPage-AaisMQI-.js → ProjectPage-BzE4V7Ti.js} +3 -3
  135. package/web-app/dist/assets/{ProjectsPage-Cej5ResX.js → ProjectsPage-ipf6TLMX.js} +1 -1
  136. package/web-app/dist/assets/{SettingsPage-DKv4mn9H.js → SettingsPage-BDxkUKN6.js} +1 -1
  137. package/web-app/dist/assets/{ShowcasePage-Dkiyzne4.js → ShowcasePage-YQXD72SM.js} +1 -1
  138. package/web-app/dist/assets/{SystemSettingsPage-DaBLQ5dU.js → SystemSettingsPage-Dou7zHS0.js} +1 -1
  139. package/web-app/dist/assets/{TeamsPage-B2yUr31k.js → TeamsPage-CQarfcYr.js} +1 -1
  140. package/web-app/dist/assets/{TemplatesPage-CfYiANhU.js → TemplatesPage-CPi1R8Xj.js} +1 -1
  141. package/web-app/dist/assets/{TerminalOutput-CMXoexLM.js → TerminalOutput-WiGhWdYD.js} +1 -1
  142. package/web-app/dist/assets/{activity-B0dzoZtY.js → activity-DOa7ejQA.js} +1 -1
  143. package/web-app/dist/assets/{bell-DFOTaSoo.js → bell-CX-VAlYN.js} +1 -1
  144. package/web-app/dist/assets/{bot-Dz-WSQyP.js → bot-EDXaZmHc.js} +1 -1
  145. package/web-app/dist/assets/{check-L1QIRueJ.js → check-CnBdKk3L.js} +1 -1
  146. package/web-app/dist/assets/{chevron-left-1TrnIEZS.js → chevron-left-BJ_ydRQW.js} +1 -1
  147. package/web-app/dist/assets/{circle-alert-8Bf6xEDx.js → circle-alert-tz8ufhc_.js} +1 -1
  148. package/web-app/dist/assets/{clock-DB8NE6P5.js → clock-DFBZPSsH.js} +1 -1
  149. package/web-app/dist/assets/{cloud-DUSL3wZS.js → cloud-uy3p_5Q7.js} +1 -1
  150. package/web-app/dist/assets/{code-xml-DbjryWNl.js → code-xml-3CbYD9YL.js} +1 -1
  151. package/web-app/dist/assets/{database-DrezrMSs.js → database-YiNBXc9c.js} +1 -1
  152. package/web-app/dist/assets/{dollar-sign-CGbaLMzR.js → dollar-sign-D0wBa4Cv.js} +1 -1
  153. package/web-app/dist/assets/{file-code-corner-Dfypa-r4.js → file-code-corner-DDdZVZ5v.js} +1 -1
  154. package/web-app/dist/assets/{file-plus-CzV5L2Gd.js → file-plus-D09LTBqt.js} +1 -1
  155. package/web-app/dist/assets/{globe-BoYjTwPQ.js → globe-BirTPwff.js} +1 -1
  156. package/web-app/dist/assets/{hammer-WO-HuiyJ.js → hammer-DaE5qgnd.js} +1 -1
  157. package/web-app/dist/assets/{index-CjIOUjnd.js → index-D8t7KnQf.js} +3 -3
  158. package/web-app/dist/assets/{layers-Bn6jtKNk.js → layers-DVVrckRY.js} +1 -1
  159. package/web-app/dist/assets/{loader-circle-gERWRnmW.js → loader-circle-2-nMGmcb.js} +1 -1
  160. package/web-app/dist/assets/{lock-BIiMLJq8.js → lock-D0Xj43pC.js} +1 -1
  161. package/web-app/dist/assets/{package-dLvDSVys.js → package-BB7S3egm.js} +1 -1
  162. package/web-app/dist/assets/{plus-BHM3ZLhZ.js → plus-BLhoMrn3.js} +1 -1
  163. package/web-app/dist/assets/{refresh-cw-BAp_alv6.js → refresh-cw-DMc2uPLw.js} +1 -1
  164. package/web-app/dist/assets/{rotate-ccw-CBhwq_MG.js → rotate-ccw-DM3IP9x7.js} +1 -1
  165. package/web-app/dist/assets/{scroll-text-DoS-6dfU.js → scroll-text-lH2uW7rB.js} +1 -1
  166. package/web-app/dist/assets/{server-5JgdDWQO.js → server-BkerZcdR.js} +1 -1
  167. package/web-app/dist/assets/{shield-alert-DjmlLT34.js → shield-alert-B8ohcUfu.js} +1 -1
  168. package/web-app/dist/assets/{thumbs-up-BtiEXl3p.js → thumbs-up-CTIxLzPD.js} +1 -1
  169. package/web-app/dist/assets/{trash-2-ClsWU_Vg.js → trash-2-C3zIpsH5.js} +1 -1
  170. package/web-app/dist/assets/{trending-down-DPS4M7_X.js → trending-down-BTT7wV4Y.js} +1 -1
  171. package/web-app/dist/assets/{trending-up-D6OJ38-V.js → trending-up-BzHdCDvF.js} +1 -1
  172. package/web-app/dist/assets/{upload-DOCzLUpF.js → upload-HxR34-A8.js} +1 -1
  173. package/web-app/dist/assets/{usePolling-CljQTWj_.js → usePolling-DDj6Fupy.js} +1 -1
  174. package/web-app/dist/assets/{user-C0G82Weu.js → user-qH5y9yNy.js} +1 -1
  175. package/web-app/dist/index.html +1 -1
  176. package/dashboard/static/assets/mermaid.min.js +0 -2030
  177. package/dashboard/static/cost.html +0 -344
  178. package/dashboard/static/favicon.svg +0 -5
  179. package/dashboard/static/index.html +0 -15577
  180. package/dashboard/static/proofs.html +0 -194
  181. package/dashboard/static/start.html +0 -131
  182. package/dashboard/static/trust.html +0 -325
  183. package/packages/control-plane/src/server/actions.ts +0 -60
  184. package/packages/control-plane/ui/dist/assets/index-DHDI_dHM.css +0 -1
  185. package/packages/control-plane/ui/dist/assets/index-DaQr0MPS.js +0 -129
@@ -3,7 +3,7 @@
3
3
  Architect design, 2026-10-01, base 1dfc87103. Design only. Flag: `LOKI_CONTROL=1` until acceptance (slice CP-17).
4
4
 
5
5
  ## 1. Goal
6
- 1. One service plus one UI, `loki control`, replaces dashboard/, dashboard-ui/ and engine10/dashboard. Zero config locally; deployed once for hundreds of runs.
6
+ 1. One service plus one UI, `loki control`, replaces dashboard/, legacy-ui/ and engine10/dashboard. Zero config locally; deployed once for hundreds of runs.
7
7
  2. Stateless processes, all state in one DB (SQLite by default, Postgres via DATABASE_URL), self-healing, horizontally scalable on Postgres.
8
8
  3. Every number is folded from ingested run events. A panel with no data says "no data ingested", never 0.
9
9
 
@@ -22,7 +22,7 @@ Architect design, 2026-10-01, base 1dfc87103. Design only. Flag: `LOKI_CONTROL=1
22
22
  | engine10 dashboard | engine10/dashboard/server.ts:30-57 (fold-based), routes :116-125 | REAL, but one repo, one process, 127.0.0.1 |
23
23
  | Python dashboard, 168 routes | dashboard/server.py (13,171 lines); cost reads `.loki/metrics/efficiency` server.py:7869 | REAL but legacy: reads run.sh state that v10 runs never write |
24
24
  | Pricing table | dashboard/server.py:7748, :8582 ("Unverified placeholder rate") | INVENTED |
25
- | dashboard-ui /api/v2 activity, agents/leaderboard, cost/breakdown, memory/graph, pipeline/status, providers/health | dashboard-ui/index.js:100-105, issue #203 | INVENTED (no server route) |
25
+ | legacy-ui /api/v2 activity, agents/leaderboard, cost/breakdown, memory/graph, pipeline/status, providers/health | legacy-ui/index.js:100-105, issue #203 | INVENTED (no server route) |
26
26
  | Secret redaction | util/redact.ts:4-14 `redactSecrets`; seal.ts:30 `sanitizeReason`; output.ts:79 Reason line | REAL. Reuse. |
27
27
 
28
28
  ## 3. Data model (Drizzle, one schema for SQLite and Postgres)
@@ -63,7 +63,7 @@ Architect design, 2026-10-01, base 1dfc87103. Design only. Flag: `LOKI_CONTROL=1
63
63
  ## 8. Migration and deletion
64
64
  1. Build in packages/control-plane/ behind LOKI_CONTROL=1. The old UIs keep running; old-dashboard bug work is retired (D56.6).
65
65
  2. Acceptance (CP-17): real runs in, correct counts out, on SQLite and Postgres; first-run gate passes with the flag on.
66
- 3. Flip the default. One release later, delete dashboard/, dashboard-ui/, engine10/dashboard/ (and its registry.ts:19 line), `loki dashboard` becomes an alias of `loki control`, and the dashboard tests are removed (CP-18).
66
+ 3. Flip the default. One release later, delete dashboard/, legacy-ui/, engine10/dashboard/ (and its registry.ts:19 line), `loki dashboard` becomes an alias of `loki control`, and the dashboard tests are removed (CP-18).
67
67
 
68
68
  ## 9. v0 (ships in 1 to 2 hours on a D46 train)
69
69
  CP-00 corpus, then CP-01, CP-02 and CP-03 in parallel, then CP-04 to wire them: SQLite service with ingest, the shipper with backfill, and a UI with the Runs list and detail, all behind the flag.
@@ -91,7 +91,7 @@ Rules for every card: file sets do not overlap; only CP-02 touches supervisor.ts
91
91
  | CP-15 | Deploy: `packages/control-plane/Dockerfile`, `deploy/helm/loki-control/` | image boots, /ready 200 after migrations; `helm template` renders probes; replicas>1 without DATABASE_URL fails render | MEDIUM | CP-07 |
92
92
  | CP-16 | Self-heal: /ready gating, stale-run derivation, replay on boot | DB file removed while up: /ready 503, recovers; stale run flagged after heartbeat gap | LOW | 01,05 |
93
93
  | CP-17 | Acceptance + flag flip | full corpus and one real first-run demo run on SQLite and Postgres: every view's counts equal EXPECTED.json | HIGH | all above |
94
- | CP-18 | Delete dashboard/, dashboard-ui/, engine10/dashboard/, their tests and references | `rg` finds no imports; local-ci fast tier green; first-run gate opens the control UI | HIGH | CP-17 + 1 release |
94
+ | CP-18 | Delete dashboard/, legacy-ui/, engine10/dashboard/, their tests and references | `rg` finds no imports; local-ci fast tier green; first-run gate opens the control UI | HIGH | CP-17 + 1 release |
95
95
 
96
96
  Dependencies to add (none present today; web-app/package.json pins react 19, vite 6, tailwind 3, so align): hono, drizzle-orm, drizzle-kit (dev), react, react-dom, vite, @vitejs/plugin-react, tailwindcss. SQLite uses built-in `bun:sqlite`. Postgres uses drizzle's `bun-sql` driver if the pinned drizzle-orm exports it, otherwise `postgres` is the one extra. No hard blocker found: Bun is already the runtime (bin/loki:94).
97
97
 
@@ -20,24 +20,24 @@ Package: packages/control-plane (server in src/server, UI in ui/src). Sources ci
20
20
 
21
21
  ## 1. Legacy inventory (KEEP / REWORK / DROP)
22
22
 
23
- Shell: dashboard-ui/scripts/build-standalone.js (generates dashboard/static/index.html). Nav groups at build-standalone.js:1266-1347 (Build, Quality and Trust, Insights, Ops, Wiki). Pages at :1358-1882. RARV, Council, gates, checkpoints and app runner are legacy engine concepts with no v10 producer (docs/v10/LEGACY-REMOVAL.md:36-37), so they DROP or remap to v10 stages (events stage.started/completed/failed/skipped, loki-ts/src/engine10/status.ts:9).
23
+ Shell: legacy-ui/scripts/build-standalone.js (generates legacy-ui-static/index.html). Nav groups at build-standalone.js:1266-1347 (Build, Quality and Trust, Insights, Ops, Wiki). Pages at :1358-1882. RARV, Council, gates, checkpoints and app runner are legacy engine concepts with no v10 producer (docs/v10/LEGACY-REMOVAL.md:36-37), so they DROP or remap to v10 stages (events stage.started/completed/failed/skipped, loki-ts/src/engine10/status.ts:9).
24
24
 
25
25
  | Legacy page or control | Source | Decision | v10 home |
26
26
  |---|---|---|---|
27
27
  | Overview (spec, tasks, RARV timeline, diff) | components/loki-overview.js, loki-spec-panel.js, loki-rarv-timeline.js, loki-session-diff.js, loki-task-board.js; build-standalone.js:1358-1415 | REWORK | Home (KPI row, recent runs, BLOCKED inbox). RARV timeline becomes the v10 stage timeline in the run thread. Task board DROP (no v10 task queue). Diff KEEP inside the run thread. |
28
28
  | First-run hero ("loki quickstart") | build-standalone.js:1365-1387 | REWORK | Empty state of the New run composer (one action: paste an issue). |
29
29
  | App Runner | loki-app-preview.js, loki-app-status.js (/api/app-runner/*) | DROP | Screenshots and evidence in the run thread replace it. |
30
- | Checkpoints | loki-checkpoint-viewer.js (/api/checkpoints, rollback) | DROP | No v10 checkpoints; rollback deleted (LEGACY-REMOVAL.md:37). |
30
+ | Checkpoints | loki-checkpoint-viewer.js (/api/checkpoints, rollback) | REWORK | Served by the Control Plane: /v1/checkpoints read routes, plus create and rollback on the loopback-only action path (CPE24-P2). |
31
31
  | Context | loki-context-tracker.js (/api/context) | DROP | Token counts per run (input_tokens, output_tokens) shown in the run cost card. |
32
32
  | Fleet | loki-fleet.js (/api/fleet/*) | REWORK | Runs table (all repos, filters, group_id rollup). Its table styling is the Table primitive. |
33
33
  | Quality (score, gates, prompt optimizer) | loki-quality-score.js, loki-quality-gates.js, loki-prompt-optimizer.js | DROP | v10 verify stage plus NOT PROVEN list in the run thread. |
34
- | Trust trajectory and receipts panel | dashboard/static/trust.html, proofs.html; build-standalone.js:1811-1828 | KEEP on v10 data | Receipts page (list, inline verify, verified-rate trend from runs). |
34
+ | Trust trajectory and receipts panel | legacy-ui-static/trust.html, proofs.html; build-standalone.js:1811-1828 | KEEP on v10 data | Receipts page (list, inline verify, verified-rate trend from runs). |
35
35
  | Completion Council | loki-council-dashboard.js, loki-council-transcripts.js | DROP | Remapped: the v10 verify stage and receipt verdict. |
36
36
  | Spec Checklist | loki-checklist-viewer.js (/api/checklist) | REWORK | Plans and traceability (plan.json, issue.json, receipt claims). |
37
37
  | Insights: logs | loki-log-stream.js (/api/logs) | KEEP | Streaming log inside the run thread (events.jsonl). |
38
38
  | Insights: memory, learnings, USAGE.md | loki-memory-browser.js, loki-learning-dashboard.js; build-standalone.js:1427-1590 | DROP now | Memory page deferred until a v10 memory read API exists (section 3.2). USAGE.md becomes a Help link. |
39
39
  | Analytics | loki-analytics.js (/api/activity) | REWORK | Home trends (runs per day, verified rate) from the runs table. |
40
- | Cost | loki-cost-dashboard.js, loki-cost-waterfall.js, dashboard/static/cost.html; spend-cap banner build-standalone.js:1800-1806 | KEEP on v10 data | Cost and usage page; the "no cap" banner is kept and fed by loki.yaml budgets. |
40
+ | Cost | loki-cost-dashboard.js, loki-cost-waterfall.js, legacy-ui-static/cost.html; spend-cap banner build-standalone.js:1800-1806 | KEEP on v10 data | Cost and usage page; the "no cap" banner is kept and fed by loki.yaml budgets. |
41
41
  | Notifications | loki-notification-center.js | REWORK | Derived from events: BLOCKED, FAILED, budget.hit, tampered, conflict. |
42
42
  | Escalations | loki-escalations.js | REWORK | BLOCKED inbox on Home plus the reply prompt in the thread. |
43
43
  | Migration | loki-migration-dashboard.js | REWORK | Runs filtered to `loki modernize` runs once they ship events (engine10/modernize); hidden until then. |
@@ -55,11 +55,11 @@ Shell: dashboard-ui/scripts/build-standalone.js (generates dashboard/static/inde
55
55
  | Budget banner | build-standalone.js:1200-1203 | KEEP | Top banner when a budget is hit (budget.hit event). |
56
56
  | Run manager, audit viewer | loki-run-manager.js, loki-audit-viewer.js | REWORK | Runs table actions; Audit log page (control-plane actions). |
57
57
  | API keys, tenant switcher, managed memory | loki-api-keys.js, loki-tenant-switcher.js, loki-managed-memory-panel.js | DROP | Local single user; the bearer token is set by env (src/server/auth.ts). |
58
- | Onboarding (start.html) | dashboard/static/start.html (/api/onboarding/*, /api/backlog/*) | REWORK | Integrations page (GitHub connect status) plus the composer empty state. |
58
+ | Onboarding (start.html) | legacy-ui-static/start.html (/api/onboarding/*, /api/backlog/*) | REWORK | Integrations page (GitHub connect status) plus the composer empty state. |
59
59
 
60
60
  ## 2. Design system (extracted, binding)
61
61
 
62
- Two legacy layers exist and disagree on ground colors. The SHELL layer in build-standalone.js:113-185 is documented as the founder-approved identity (light-grey ground, comment at :113) and is what users saw around every page; the COMPONENT layer in dashboard-ui/core/loki-unified-styles.js:20-146 (also loki-theme.js:44-124) supplies the scales, status colors and component specs. Decision: shell ground and accent per theme from the shell layer; scales, radii, shadows, model colors and component recipes from the component layer. (Open question 1.)
62
+ Two legacy layers exist and disagree on ground colors. The SHELL layer in build-standalone.js:113-185 is documented as the founder-approved identity (light-grey ground, comment at :113) and is what users saw around every page; the COMPONENT layer in legacy-ui/core/loki-unified-styles.js:20-146 (also loki-theme.js:44-124) supplies the scales, status colors and component specs. Decision: shell ground and accent per theme from the shell layer; scales, radii, shadows, model colors and component recipes from the component layer. (Open question 1.)
63
63
 
64
64
  Package: packages/control-plane/ui/src/design/ with tokens.css (custom properties below), fonts.css (Google Fonts link, build-standalone parity: Fraunces opsz 9..144 wght 400/500/600, Inter 300-700, JetBrains Mono 400/500; static/index.html:11), tailwind.preset.ts (maps Tailwind colors, radius, spacing, fontFamily to the vars, so existing Tailwind classes keep working), and primitives/*.tsx.
65
65
 
@@ -230,13 +230,274 @@ Gap: the server stores events only. Artifacts live in the local repo, and source
230
230
 
231
231
  Every mutating endpoint: requires the bearer token when the server is not loopback-only, refuses non-JSON bodies, checks Origin against the served host, writes an audit row before acting, and returns the resulting state for optimistic reconciliation.
232
232
 
233
- ## 5. Parity checklist (gate for CPE-24)
233
+ ## 5. Legacy integration contract (gate for CPE-24)
234
+
235
+ The legacy dashboard (dashboard/server.py, port 57374, 13194 lines) serves 234 routes (method and path entries after dropping HEAD; routers api_v2 at /api/v2, api_operator at /api/operator, api_start, api_runs_v1 at /api/v1/runs, the /lab and /assets mounts, WS /ws and /ws/collab). Deleting it (CPE-24) must not break a real integration. This section is the contract: one row per route, what consumes it, what the Control Plane offers, and what the shim at packages/control-plane/src/server/legacy/ does with it.
236
+
237
+ Method. Route list: FastAPI introspection of `dashboard.server.app` (the 234 entries). Consumers: a repo-wide text scan of git-tracked files, then each used route's consumer lines were read by hand. Counted as a consumer: the TypeScript and Python SDKs, vscode-extension (src and the bundled media/loki-dashboard.js webview), autonomy/loki and autonomy/run.sh, web-app, .github/workflows, tests/moat, tests/e2e, tests/integration, scripts/run-dashboard-* (marked "(test)" when a test). Not counted: dashboard/ itself, dashboard-ui/ (the legacy UI is deleted with the server), docs, generated maps, packages/control-plane. The scan matches path text, so single-segment paths (/start, /cost, /trust, /) were checked by hand: every hit was `loki start`, `/api/cost` or `/lab/api/cost`, none a request to that HTML route. Limits: a path built at runtime from parts is invisible to a text scan, and an HTTP verb is inferred from the nearby call text, so a verb on a bundled-JS row is best effort. A route with a consumer is USED, otherwise UNUSED.
238
+
239
+ Status values: EXISTS (the CP serves it today), PARTIAL (the shim maps it and says what differs), MISSING (a USED route the CP has no data or mechanism for), UNUSED (no consumer). Shim actions: map (answer from CP data), 308 to CP UI (HTML page), 410 with notice (UNUSED, retired), 501 not yet supported (USED but no CP data or mechanism: the shim answers an explicit 501, never a faked success), none (the CP already serves the path).
240
+
241
+ Counts: map 35, 308 5, 501 21, 410 169, none 4; total 234. A 410 row with a non-empty CP column also names that replacement in the 410 body (CPE24-P6).
242
+
243
+ Auth contract (never looser than legacy). Legacy `require_scope` is open when LOKI_ENTERPRISE_AUTH and OIDC are both off, and otherwise answers 401 without a token and 403 on a missing scope. Open in every mode: /health, /.well-known/agent.json, /api/enterprise/status, /api/auth/info, /api/providers/models, /metrics, the docs routes. The shim applies one rule to every route the legacy server guarded: if LOKI_CONTROL_TOKEN is set, require the CP bearer token (401 with www-authenticate otherwise); if no CP token is set but legacy enterprise auth or OIDC is enabled in the environment, fail closed with 401 (the CP has no way to check the legacy `loki_*` tokens); if neither is set, open, matching the legacy default. The CP token carries every scope, which is safe because the shim exposes only read routes and answers 501 or 410 for the rest. 501 and 410 answers are also behind the guard, so an unauthenticated caller learns nothing about a guarded route. The shim never binds a port; mounting it on the CP app keeps hostGuard and the loopback-only action routes exactly as they are.
244
+
245
+ First hit per process, each route logs one line: `legacy dashboard route <path> is served by the Control Plane; migrate to /v1/...` (mapped and 308 routes). A 501 or 410 route logs the same single line in the words "is not served by the Control Plane (501)" or "is retired (410)".
246
+
247
+ ### 5.1 Parity checklist (gate for CPE-24)
234
248
  1. Every row of section 1 marked KEEP or REWORK has its v10 home rendered on real data, proven by a UI test with a fixture run.
235
249
  2. Every row of section 3.3 not marked DEFERRED works end to end in tests/e2e (start a fixture run, stream, BLOCKED answer, stop, retry, verify, config write).
236
250
  3. Visual parity: screenshots of wordmark, nav, card, KPI, badge, table in light and dark compared against legacy captures (CPE-23).
237
251
  4. No route under the old dashboard is reachable except the CP-LEGACY redirects (7b701d238).
238
252
  5. Lighthouse accessibility at or above 95 on composer, thread, Home; axe zero serious violations.
239
253
 
254
+
255
+ ### 5.2 Route contract
256
+
257
+ | Method and path | Consumers (verified file:line) | CP /v1 equivalent | Status | Shim action |
258
+ |---|---|---|---|---|
259
+ | GET `/openapi.json` | none | none | UNUSED | 410 with notice |
260
+ | GET `/docs` | none | none | UNUSED | 410 with notice |
261
+ | GET `/docs/oauth2-redirect` | none | none | UNUSED | 410 with notice |
262
+ | GET `/redoc` | none | none | UNUSED | 410 with notice |
263
+ | POST `/api/v2/tenants` | sdk/python/loki_mode_sdk/client.py:204, sdk/typescript/src/client.ts:237 | no tenants: local single user | DROPPED (section 1) | 410 with notice |
264
+ | GET `/api/v2/tenants` | sdk/python/loki_mode_sdk/client.py:191, sdk/typescript/src/client.ts:225 | no tenants: local single user | DROPPED (section 1) | 410 with notice |
265
+ | GET `/api/v2/tenants/{tenant_id}` | sdk/typescript/src/client.ts:229 | no tenants: local single user | DROPPED (section 1) | 410 with notice |
266
+ | PUT `/api/v2/tenants/{tenant_id}` | none | none | UNUSED | 410 with notice |
267
+ | DELETE `/api/v2/tenants/{tenant_id}` | sdk/typescript/src/client.ts:241 | no tenants: local single user | DROPPED (section 1) | 410 with notice |
268
+ | GET `/api/v2/tenants/{tenant_id}/projects` | none | none | UNUSED | 410 with notice |
269
+ | POST `/api/v2/runs` | vscode-extension/media/loki-dashboard.js:9617 | none | MISSING | 501 not yet supported |
270
+ | GET `/api/v2/runs` | sdk/python/loki_mode_sdk/client.py:220, sdk/typescript/src/client.ts:201 | /v1/runs | PARTIAL (ids are source:run strings, not ints; no project_id filter; status maps to running/completed; limit/offset map to limit/cursor) | map |
271
+ | GET `/api/v2/runs/{run_id}` | sdk/python/loki_mode_sdk/client.py:228, sdk/typescript/src/client.ts:205 | /v1/runs/:id | PARTIAL (run_id is source:run (URL-encoded) or a bare run id; legacy integer ids answer 404) | map |
272
+ | POST `/api/v2/runs/{run_id}/cancel` | sdk/python/loki_mode_sdk/client.py:233, sdk/typescript/src/client.ts:209, vscode-extension/media/loki-dashboard.js:9617 | none | MISSING | 501 not yet supported |
273
+ | POST `/api/v2/runs/{run_id}/replay` | sdk/python/loki_mode_sdk/client.py:238, sdk/typescript/src/client.ts:213, vscode-extension/media/loki-dashboard.js:9617 | none | MISSING | 501 not yet supported |
274
+ | GET `/api/v2/runs/{run_id}/timeline` | sdk/python/loki_mode_sdk/client.py:243, sdk/typescript/src/client.ts:217, vscode-extension/media/loki-dashboard.js:9255 | /v1/runs/:id (stages, events) | PARTIAL (phases are CP stages; events carry seq, ts, type, stage only) | map |
275
+ | POST `/api/v2/api-keys` | sdk/python/loki_mode_sdk/client.py:263, sdk/typescript/src/client.ts:178, vscode-extension/media/loki-dashboard.js:10097 | CP bearer token set by env (LOKI_CONTROL_TOKEN) | DROPPED (section 1) | 410 with notice |
276
+ | GET `/api/v2/api-keys` | sdk/python/loki_mode_sdk/client.py:253, sdk/typescript/src/client.ts:170 | CP bearer token set by env (LOKI_CONTROL_TOKEN) | DROPPED (section 1) | 410 with notice |
277
+ | GET `/api/v2/api-keys/{identifier}` | none | none | UNUSED | 410 with notice |
278
+ | PUT `/api/v2/api-keys/{identifier}` | none | none | UNUSED | 410 with notice |
279
+ | DELETE `/api/v2/api-keys/{identifier}` | sdk/typescript/src/client.ts:190, vscode-extension/media/loki-dashboard.js:10097 | CP bearer token set by env (LOKI_CONTROL_TOKEN) | DROPPED (section 1) | 410 with notice |
280
+ | POST `/api/v2/api-keys/{identifier}/rotate` | sdk/python/loki_mode_sdk/client.py:271, sdk/typescript/src/client.ts:186, vscode-extension/media/loki-dashboard.js:10097 | CP bearer token set by env (LOKI_CONTROL_TOKEN) | DROPPED (section 1) | 410 with notice |
281
+ | GET `/api/v2/policies` | none | none | UNUSED | 410 with notice |
282
+ | PUT `/api/v2/policies` | none | none | UNUSED | 410 with notice |
283
+ | POST `/api/v2/policies/evaluate` | none | none | UNUSED | 410 with notice |
284
+ | GET `/api/v2/audit` | sdk/python/loki_mode_sdk/client.py:293, sdk/typescript/src/client.ts:254, vscode-extension/media/loki-dashboard.js:9813 | /v1/audit (added by the shim) | PARTIAL (CP audit is an operator-action log (run removal, prune), not the legacy hash-chained log; resource_type filter answers 400) | map |
285
+ | GET `/api/v2/audit/verify` | tests/moat/p2-honest-verdict.sh:1162 (test), tests/moat/p2-honest-verdict.sh:1258 (test), vscode-extension/media/loki-dashboard.js:9813 | none | MISSING | 501 not yet supported |
286
+ | GET `/api/v2/audit/export` | none | /v1/audit | UNUSED | 410 with notice |
287
+ | GET `/api/operator/runs/{run_id}` | none | /v1/runs/:id | UNUSED | 410 with notice |
288
+ | GET `/api/operator/tests` | none | none | UNUSED | 410 with notice |
289
+ | GET `/api/operator/receipts` | none | none | UNUSED | 410 with notice |
290
+ | GET `/api/operator/releases` | none | none | UNUSED | 410 with notice |
291
+ | GET `/api/operator/phases` | none | none | UNUSED | 410 with notice |
292
+ | GET `/api/operator/workspaces/runs` | none | none | UNUSED | 410 with notice |
293
+ | GET `/api/operator/workspaces/runs/{ws}/{run_id}` | none | none | UNUSED | 410 with notice |
294
+ | GET `/api/onboarding/state` | none | none | UNUSED | 410 with notice |
295
+ | POST `/api/onboarding/provider` | none | none | UNUSED | 410 with notice |
296
+ | POST `/api/onboarding/github` | none | none | UNUSED | 410 with notice |
297
+ | GET `/api/onboarding/repos` | none | none | UNUSED | 410 with notice |
298
+ | POST `/api/onboarding/repo` | none | none | UNUSED | 410 with notice |
299
+ | GET `/api/backlog/issues` | none | none | UNUSED | 410 with notice |
300
+ | POST `/api/backlog/run` | none | none | UNUSED | 410 with notice |
301
+ | GET `/api/backlog/status` | none | none | UNUSED | 410 with notice |
302
+ | GET `/api/v1/runs` | none | /v1/runs | UNUSED | 410 with notice |
303
+ | GET `/api/v1/runs/{run_id}` | none | /v1/runs/:id | UNUSED | 410 with notice |
304
+ | POST `/api/v1/runs` | none | /v1/runs | UNUSED | 410 with notice |
305
+ | POST `/api/v1/runs/{run_id}/stop` | none | none | UNUSED | 410 with notice |
306
+ | GET `/start` | none | CP UI (/) | EXISTS | 308 to CP UI |
307
+ | MOUNT `/lab` | none | CP UI (/) | EXISTS | 308 to CP UI |
308
+ | GET `/health` | autonomy/loki:1929, autonomy/loki:7760, autonomy/run.sh:19293 (+10) | /health | EXISTS (CP /health answers {service, pid, install_path}, not the legacy body; CLI discovery relies on that identity, so the shim never overrides it) | none (CP /health serves) |
309
+ | GET `/api/providers/models` | none | none | UNUSED | 410 with notice |
310
+ | GET `/.well-known/agent.json` | .github/workflows/integrity-audit.yml:114, .github/workflows/integrity-audit.yml:115 | none (static card) | PARTIAL (static card from shim constants; capabilities the CP cannot back (streaming, enterprise rbac/multi-tenant) are false) | map |
311
+ | GET `/api/status` | autonomy/loki:15601, autonomy/run.sh:19357, autonomy/run.sh:19541 (+10) | /v1/runs (derived) | PARTIAL (status, version, uptime, active_sessions, phase, provider only; no running_agents, pending_tasks, iteration, complexity, mode, current_task (CP has no such data, fields omitted)) | map |
312
+ | GET `/api/projects` | sdk/python/loki_mode_sdk/client.py:166, sdk/typescript/src/client.ts:127, tests/moat/p7-no-fabricated-data.sh:446 (test) | none | MISSING | 501 not yet supported |
313
+ | POST `/api/projects` | sdk/python/loki_mode_sdk/client.py:184, sdk/typescript/src/client.ts:139, tests/moat/p7-no-fabricated-data.sh:437 (test) (+1) | none | MISSING | 501 not yet supported |
314
+ | GET `/api/projects/{project_id}` | sdk/python/loki_mode_sdk/client.py:174, sdk/typescript/src/client.ts:131 | none | MISSING | 501 not yet supported |
315
+ | PUT `/api/projects/{project_id}` | vscode-extension/media/loki-dashboard.js:496 | none | MISSING | 501 not yet supported |
316
+ | DELETE `/api/projects/{project_id}` | vscode-extension/media/loki-dashboard.js:496 | none | MISSING | 501 not yet supported |
317
+ | GET `/api/tasks` | sdk/python/loki_mode_sdk/tasks.py:30, sdk/typescript/src/client.ts:150 | /v1/tasks (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
318
+ | POST `/api/tasks` | sdk/python/loki_mode_sdk/tasks.py:56, sdk/typescript/src/client.ts:162, vscode-extension/media/loki-dashboard.js:496 | no v10 task queue; read-only GET /v1/tasks | DROPPED (section 1) | 410 with notice |
319
+ | GET `/api/tasks/{task_id}` | sdk/python/loki_mode_sdk/tasks.py:38, sdk/typescript/src/client.ts:154, vscode-extension/src/views/dashboardWebview.ts:168 | no v10 task queue; read-only GET /v1/tasks | DROPPED (section 1) | 410 with notice |
320
+ | PUT `/api/tasks/{task_id}` | sdk/python/loki_mode_sdk/tasks.py:71, vscode-extension/media/loki-dashboard.js:496 | no v10 task queue; read-only GET /v1/tasks | DROPPED (section 1) | 410 with notice |
321
+ | DELETE `/api/tasks/{task_id}` | vscode-extension/media/loki-dashboard.js:496 | no v10 task queue; read-only GET /v1/tasks | DROPPED (section 1) | 410 with notice |
322
+ | POST `/api/tasks/{task_id}/move` | vscode-extension/media/loki-dashboard.js:496 | no v10 task queue; read-only GET /v1/tasks | DROPPED (section 1) | 410 with notice |
323
+ | WS `/ws` | vscode-extension/media/loki-dashboard.js:496 | SSE at GET /v1/stream | DROPPED (section 1) | 410 with notice |
324
+ | GET `/api/registry/projects` | none | none | UNUSED | 410 with notice |
325
+ | POST `/api/registry/projects` | vscode-extension/media/loki-dashboard.js:496 | repos are discovered locally; GET /v1/repos | DROPPED (section 1) | 410 with notice |
326
+ | GET `/api/registry/projects/{identifier}` | none | none | UNUSED | 410 with notice |
327
+ | DELETE `/api/registry/projects/{identifier}` | none | none | UNUSED | 410 with notice |
328
+ | GET `/api/registry/projects/{identifier}/health` | none | none | UNUSED | 410 with notice |
329
+ | POST `/api/registry/projects/{identifier}/access` | none | none | UNUSED | 410 with notice |
330
+ | GET `/api/registry/discover` | none | none | UNUSED | 410 with notice |
331
+ | POST `/api/registry/sync` | vscode-extension/media/loki-dashboard.js:496 | repos are discovered locally; GET /v1/repos | DROPPED (section 1) | 410 with notice |
332
+ | GET `/api/registry/tasks` | none | none | UNUSED | 410 with notice |
333
+ | GET `/api/registry/learnings` | none | none | UNUSED | 410 with notice |
334
+ | GET `/api/fleet/runs` | tests/moat/p7-no-fabricated-data.sh:4637 (test), tests/moat/p7-no-fabricated-data.sh:4706 (test), tests/moat/p7-no-fabricated-data.sh:4710 (test) (+1) | /v1/fleet/runs (CPE24-P1) | PARTIAL (reads the same .loki or registry source; unmeasured values are null with a not-measured marker) | map |
335
+ | GET `/api/fleet/summary` | tests/moat/p7-no-fabricated-data.sh:4637 (test), tests/moat/p7-no-fabricated-data.sh:4695 (test), tests/moat/p7-no-fabricated-data.sh:4696 (test) (+1) | /v1/fleet/summary (CPE24-P1) | PARTIAL (reads the same .loki or registry source; unmeasured values are null with a not-measured marker) | map |
336
+ | GET `/api/fleet/runs/{identifier}` | none | none | UNUSED | 410 with notice |
337
+ | POST `/api/focus` | autonomy/run.sh:24831, web-app/server.py:2744 | /v1/focus (CPE24-P3) | PARTIAL (focus only to this checkout or a registered project; loopback, JSON, same-origin) | map |
338
+ | GET `/api/focus` | none | none | UNUSED | 410 with notice |
339
+ | DELETE `/api/focus` | none | none | UNUSED | 410 with notice |
340
+ | GET `/api/session/model` | none | none | UNUSED | 410 with notice |
341
+ | POST `/api/session/model` | vscode-extension/media/loki-dashboard.js:496 | no mid-run model switch; start a new run with another model (POST /v1/runs) | DROPPED (section 1) | 410 with notice |
342
+ | GET `/api/running-projects` | none | none | UNUSED | 410 with notice |
343
+ | POST `/api/control/start` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/src/api/client.ts:257, vscode-extension/src/extension.ts:580 | none | MISSING | 501 not yet supported |
344
+ | GET `/api/control/builds/{execution_id}` | none | none | UNUSED | 410 with notice |
345
+ | GET `/api/control/builds/{execution_id}/proof` | none | none | UNUSED | 410 with notice |
346
+ | POST `/api/control/builds/{execution_id}/stop` | none | none | UNUSED | 410 with notice |
347
+ | POST `/api/running-projects/stop` | none | none | UNUSED | 410 with notice |
348
+ | POST `/api/fleet/runs/{identifier}/retry` | none | none | UNUSED | 410 with notice |
349
+ | POST `/api/fleet/runs/{identifier}/cancel` | none | none | UNUSED | 410 with notice |
350
+ | GET `/api/enterprise/status` | none | none | UNUSED | 410 with notice |
351
+ | GET `/api/auth/info` | none | none | UNUSED | 410 with notice |
352
+ | POST `/api/enterprise/tokens` | none | none | UNUSED | 410 with notice |
353
+ | GET `/api/enterprise/tokens` | none | none | UNUSED | 410 with notice |
354
+ | DELETE `/api/enterprise/tokens/{identifier}` | none | none | UNUSED | 410 with notice |
355
+ | GET `/api/enterprise/audit` | none | /v1/audit (CPE24-P2) | PARTIAL (read-only; the operator audit table, no hash chain access) | map |
356
+ | GET `/api/enterprise/audit/summary` | none | /v1/audit/summary (CPE24-P2) | PARTIAL (read-only; success, failure and resource-type counts are null, not measured) | map |
357
+ | GET `/api/compliance` | none | none | UNUSED | 410 with notice |
358
+ | GET `/api/memory/summary` | none | none | UNUSED | 410 with notice |
359
+ | GET `/api/memory/episodes` | vscode-extension/src/views/memoryViewProvider.ts:152 | /v1/memory/episodes (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
360
+ | GET `/api/memory/episodes/{episode_id}` | vscode-extension/src/views/dashboardWebview.ts:204, vscode-extension/src/views/memoryViewProvider.ts:215 | /v1/memory/episodes/{id} (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
361
+ | GET `/api/memory/patterns` | vscode-extension/src/views/memoryViewProvider.ts:151 | /v1/memory/patterns (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
362
+ | GET `/api/memory/patterns/{pattern_id}` | vscode-extension/src/views/dashboardWebview.ts:186, vscode-extension/src/views/memoryViewProvider.ts:197 | /v1/memory/patterns/{id} (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
363
+ | GET `/api/memory/skills` | vscode-extension/src/views/memoryViewProvider.ts:153 | /v1/memory/skills (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
364
+ | GET `/api/memory/skills/{skill_id}` | none | none | UNUSED | 410 with notice |
365
+ | GET `/api/memory/economics` | tests/moat/p7-no-fabricated-data.sh:4638 (test), tests/moat/p7-no-fabricated-data.sh:4749 (test), tests/moat/p7-no-fabricated-data.sh:4750 (test) (+2) | /v1/memory/economics (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
366
+ | POST `/api/memory/consolidate` | vscode-extension/media/loki-dashboard.js:496 | read-only GET /v1/memory/* | DROPPED (section 1) | 410 with notice |
367
+ | POST `/api/memory/retrieve` | vscode-extension/media/loki-dashboard.js:496 | read-only GET /v1/memory/* | DROPPED (section 1) | 410 with notice |
368
+ | GET `/api/memory/index` | none | none | UNUSED | 410 with notice |
369
+ | GET `/api/memory/timeline` | none | none | UNUSED | 410 with notice |
370
+ | GET `/api/memory/files` | none | none | UNUSED | 410 with notice |
371
+ | GET `/api/memory/file` | none | none | UNUSED | 410 with notice |
372
+ | GET `/api/memory/search` | none | none | UNUSED | 410 with notice |
373
+ | GET `/api/memory/stats` | none | none | UNUSED | 410 with notice |
374
+ | GET `/api/learning/metrics` | tests/moat/p7-no-fabricated-data.sh:4638 (test), tests/moat/p7-no-fabricated-data.sh:4752 (test) | none | MISSING | 501 not yet supported |
375
+ | GET `/api/learning/trends` | none | none | UNUSED | 410 with notice |
376
+ | GET `/api/learning/signals` | none | none | UNUSED | 410 with notice |
377
+ | GET `/api/learning/aggregation` | none | none | UNUSED | 410 with notice |
378
+ | POST `/api/learning/aggregate` | vscode-extension/media/loki-dashboard.js:496 | read-only GET /v1/memory/patterns | DROPPED (section 1) | 410 with notice |
379
+ | GET `/api/learning/preferences` | none | none | UNUSED | 410 with notice |
380
+ | GET `/api/learning/errors` | none | none | UNUSED | 410 with notice |
381
+ | GET `/api/learning/success` | none | none | UNUSED | 410 with notice |
382
+ | GET `/api/learning/tools` | none | none | UNUSED | 410 with notice |
383
+ | POST `/api/control/pause` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/src/api/client.ts:277, vscode-extension/src/extension.ts:703 | /v1/control/pause (CPE24-P4) | PARTIAL (writes only the .loki signal file run.sh reads; no process is signalled; same-origin plus loopback or CP token required) | map |
384
+ | POST `/api/control/resume` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/src/api/client.ts:285, vscode-extension/src/extension.ts:743 | /v1/control/resume (CPE24-P4) | PARTIAL (writes only the .loki signal file run.sh reads; no process is signalled; same-origin plus loopback or CP token required) | map |
385
+ | POST `/api/control/stop` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/src/api/client.ts:269, vscode-extension/src/extension.ts:651 | /v1/control/stop (CPE24-P4) | PARTIAL (writes only the .loki signal file run.sh reads; no process is signalled; same-origin plus loopback or CP token required) | map |
386
+ | GET `/api/cost` | tests/moat/p7-no-fabricated-data.sh:4637 (test), tests/moat/p7-no-fabricated-data.sh:4646 (test), tests/moat/p7-no-fabricated-data.sh:4647 (test) (+3) | /v1/cost/snapshot (CPE24-P1) | PARTIAL (reads the same .loki or registry source; unmeasured values are null with a not-measured marker) | map |
387
+ | GET `/api/budget` | tests/e2e/dashboard-evidence-panels.mjs:73 (test), tests/moat/p7-no-fabricated-data.sh:4637 (test), tests/moat/p7-no-fabricated-data.sh:4650 (test) (+3) | none | MISSING | 501 not yet supported |
388
+ | GET `/api/cost/timeline` | tests/moat/p7-no-fabricated-data.sh:4637 (test), tests/moat/p7-no-fabricated-data.sh:4652 (test), tests/moat/p7-no-fabricated-data.sh:4653 (test) (+15) | /v1/cost/timeline (CPE24-P1) | PARTIAL (reads the same .loki or registry source; unmeasured values are null with a not-measured marker) | map |
389
+ | GET `/api/trust/trajectory` | none | none | UNUSED | 410 with notice |
390
+ | GET `/api/gate-policy` | none | none | UNUSED | 410 with notice |
391
+ | GET `/api/pricing` | none | none | UNUSED | 410 with notice |
392
+ | GET `/api/council/state` | none | /v1/council/state (CPE24-P4) | PARTIAL (reads the same .loki/council files; read-only) | map |
393
+ | GET `/api/council/verdicts` | none | /v1/council/verdicts (CPE24-P4) | PARTIAL (reads the same .loki/council files; read-only) | map |
394
+ | GET `/api/council/convergence` | none | /v1/council/convergence (CPE24-P4) | PARTIAL (reads the same .loki/council files; read-only) | map |
395
+ | GET `/api/council/report` | none | /v1/council/report (CPE24-P4) | PARTIAL (reads the same .loki/council files; read-only) | map |
396
+ | POST `/api/council/force-review` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/media/loki-dashboard.js:4312 | /v1/control/council-review (CPE24-P4) | PARTIAL (writes only the .loki signal file run.sh reads; no process is signalled; same-origin plus loopback or CP token required) | map |
397
+ | GET `/api/council/transcripts` | vscode-extension/media/loki-dashboard.js:12426 | /v1/council/transcripts (CPE24-P4) | PARTIAL (reads the same .loki/council files; read-only) | map |
398
+ | GET `/api/council/transcripts/{iteration_id}` | none | none | UNUSED | 410 with notice |
399
+ | GET `/api/context` | tests/moat/p7-no-fabricated-data.sh:4638 (test), tests/moat/p7-no-fabricated-data.sh:4745 (test), tests/moat/p7-no-fabricated-data.sh:4746 (test) (+3) | /v1/context (CPE24-P3) | PARTIAL (reads the same .loki source; legacy SQLite memory backend not read; unmeasured values are null) | map |
400
+ | GET `/api/notifications` | none | none | UNUSED | 410 with notice |
401
+ | GET `/api/notifications/triggers` | none | none | UNUSED | 410 with notice |
402
+ | PUT `/api/notifications/triggers` | vscode-extension/media/loki-dashboard.js:496, vscode-extension/media/loki-dashboard.js:6802 | GET /v1/notifications (derived from events) | DROPPED (section 1) | 410 with notice |
403
+ | POST `/api/notifications/{notification_id}/acknowledge` | none | none | UNUSED | 410 with notice |
404
+ | POST `/api/notifications/{notification_id}/unacknowledge` | none | none | UNUSED | 410 with notice |
405
+ | GET `/api/checkpoints` | vscode-extension/src/views/checkpointProvider.ts:108, vscode-extension/src/views/checkpointProvider.ts:134 | /v1/checkpoints (CPE24-P2) | PARTIAL (reads the same .loki/state/checkpoints store; unmeasured values are null) | map |
406
+ | GET `/api/checkpoints/{checkpoint_id}` | none | /v1/checkpoints/{id} (CPE24-P2) | PARTIAL (reads the same .loki/state/checkpoints store; unmeasured values are null) | map |
407
+ | POST `/api/checkpoints` | vscode-extension/media/loki-dashboard.js:5960 | /v1/checkpoints (CPE24-P2) | PARTIAL (loopback peer, loopback Host and JSON required; audited) | map |
408
+ | POST `/api/checkpoints/{checkpoint_id}/rollback` | vscode-extension/media/loki-dashboard.js:5960 | /v1/checkpoints/{id}/rollback (CPE24-P2) | PARTIAL (loopback peer, loopback Host and JSON required; forced pre-rollback snapshot; audited) | map |
409
+ | GET `/api/agents` | none | none | UNUSED | 410 with notice |
410
+ | POST `/api/agents/{agent_id}/kill` | vscode-extension/media/loki-dashboard.js:4312 | POST /v1/control/stop | DROPPED (section 1) | 410 with notice |
411
+ | POST `/api/agents/{agent_id}/pause` | vscode-extension/media/loki-dashboard.js:4312 | POST /v1/control/stop (v10 has no pause) | DROPPED (section 1) | 410 with notice |
412
+ | POST `/api/agents/{agent_id}/resume` | vscode-extension/media/loki-dashboard.js:4312 | POST /v1/control/resume | DROPPED (section 1) | 410 with notice |
413
+ | GET `/api/logs` | none | none | UNUSED | 410 with notice |
414
+ | POST `/api/collab/join` | none | none | UNUSED | 410 with notice |
415
+ | POST `/api/collab/leave` | none | none | UNUSED | 410 with notice |
416
+ | GET `/api/collab/users` | none | none | UNUSED | 410 with notice |
417
+ | GET `/api/collab/users/{user_id}` | none | none | UNUSED | 410 with notice |
418
+ | POST `/api/collab/users/{user_id}/heartbeat` | none | none | UNUSED | 410 with notice |
419
+ | POST `/api/collab/users/{user_id}/cursor` | none | none | UNUSED | 410 with notice |
420
+ | POST `/api/collab/users/{user_id}/status` | none | none | UNUSED | 410 with notice |
421
+ | GET `/api/collab/presence` | none | none | UNUSED | 410 with notice |
422
+ | GET `/api/collab/file/{file_path:path}` | none | none | UNUSED | 410 with notice |
423
+ | GET `/api/collab/state` | none | none | UNUSED | 410 with notice |
424
+ | GET `/api/collab/state/value` | none | none | UNUSED | 410 with notice |
425
+ | POST `/api/collab/operation` | none | none | UNUSED | 410 with notice |
426
+ | POST `/api/collab/sync` | none | none | UNUSED | 410 with notice |
427
+ | GET `/api/collab/history` | none | none | UNUSED | 410 with notice |
428
+ | WS `/ws/collab` | none | none | UNUSED | 410 with notice |
429
+ | GET `/api/collab/status` | none | none | UNUSED | 410 with notice |
430
+ | GET `/api/secrets/status` | none | none | UNUSED | 410 with notice |
431
+ | GET `/api/github/status` | none | none | UNUSED | 410 with notice |
432
+ | GET `/api/github/tasks` | none | none | UNUSED | 410 with notice |
433
+ | GET `/api/github/sync-log` | none | none | UNUSED | 410 with notice |
434
+ | GET `/api/health/processes` | none | none | UNUSED | 410 with notice |
435
+ | GET `/metrics` | autonomy/loki:29162, tests/e2e/webapp-admin-honesty.mjs:271 (test), tests/e2e/webapp-receipt-panel.mjs:54 (test) (+2) | /v1/metrics (CPE24-P1) | PARTIAL (reads the same .loki or registry source; unmeasured values are null with a not-measured marker) | map |
436
+ | GET `/api/checklist` | none | none | UNUSED | 410 with notice |
437
+ | GET `/api/usage` | none | none | UNUSED | 410 with notice |
438
+ | GET `/api/checklist/summary` | none | none | UNUSED | 410 with notice |
439
+ | GET `/api/prd-observations` | none | none | UNUSED | 410 with notice |
440
+ | GET `/api/checklist/waivers` | none | none | UNUSED | 410 with notice |
441
+ | POST `/api/checklist/waivers` | vscode-extension/media/loki-dashboard.js:496 | plan.json and receipt claims in GET /v1/runs/:id | DROPPED (section 1) | 410 with notice |
442
+ | DELETE `/api/checklist/waivers/{item_id}` | vscode-extension/media/loki-dashboard.js:496 | plan.json and receipt claims in GET /v1/runs/:id | DROPPED (section 1) | 410 with notice |
443
+ | GET `/api/council/gate` | tests/moat/p7-no-fabricated-data.sh:4638 (test), tests/moat/p7-no-fabricated-data.sh:4760 (test), tests/moat/p7-no-fabricated-data.sh:4762 (test) (+1) | none | MISSING | 501 not yet supported |
444
+ | GET `/api/app-runner/status` | none | none | UNUSED | 410 with notice |
445
+ | GET `/api/app-runner/logs` | none | none | UNUSED | 410 with notice |
446
+ | GET `/api/app-runner/errors` | none | none | UNUSED | 410 with notice |
447
+ | POST `/api/control/app-restart` | vscode-extension/media/loki-dashboard.js:496 | evidence in GET /v1/runs/:source/:run/artifact/* | DROPPED (section 1) | 410 with notice |
448
+ | POST `/api/control/app-stop` | vscode-extension/media/loki-dashboard.js:496 | evidence in GET /v1/runs/:source/:run/artifact/* | DROPPED (section 1) | 410 with notice |
449
+ | GET `/api/playwright/results` | none | none | UNUSED | 410 with notice |
450
+ | GET `/api/playwright/screenshot` | none | none | UNUSED | 410 with notice |
451
+ | GET `/api/failures` | none | none | UNUSED | 410 with notice |
452
+ | GET `/api/prompt-versions` | none | none | UNUSED | 410 with notice |
453
+ | POST `/api/prompt-optimize` | autonomy/loki:17793, vscode-extension/media/loki-dashboard.js:7581 | verify stage: POST /v1/runs/:source/:run/verify | DROPPED (section 1) | 410 with notice |
454
+ | MOUNT `/assets` | none | UI static assets | EXISTS (vite output under ui/dist/assets) | none (CP UI serves it) |
455
+ | GET `/api/activity` | vscode-extension/media/loki-dashboard.js:8596 | none | MISSING | 501 not yet supported |
456
+ | GET `/api/session-diff` | none | none | UNUSED | 410 with notice |
457
+ | POST `/api/activity` | none | none | UNUSED | 410 with notice |
458
+ | GET `/favicon.svg` | none | UI static asset | EXISTS (the CP UI serves its own favicon from ui/dist) | none (CP UI serves it) |
459
+ | GET `/cost` | none | CP UI (/) | EXISTS | 308 to CP UI |
460
+ | GET `/trust` | none | CP UI (/) | EXISTS | 308 to CP UI |
461
+ | GET `/` | none | CP UI (/) | EXISTS | 308 to CP UI |
462
+ | GET `/api/quality-score` | none | none | UNUSED | 410 with notice |
463
+ | GET `/api/quality-score/history` | none | none | UNUSED | 410 with notice |
464
+ | POST `/api/quality-scan` | autonomy/loki:23927, vscode-extension/media/loki-dashboard.js:7832 | verify stage: POST /v1/runs/:source/:run/verify | DROPPED (section 1) | 410 with notice |
465
+ | GET `/api/quality-report` | autonomy/loki:23994 | verify stage: POST /v1/runs/:source/:run/verify | DROPPED (section 1) | 410 with notice |
466
+ | GET `/api/migration/list` | vscode-extension/media/loki-dashboard.js:8173 | none | MISSING | 501 not yet supported |
467
+ | POST `/api/migration/start` | none | none | UNUSED | 410 with notice |
468
+ | GET `/api/migration/{migration_id}/status` | vscode-extension/media/loki-dashboard.js:8173 | none | MISSING | 501 not yet supported |
469
+ | GET `/api/migration/{migration_id}/plan` | none | none | UNUSED | 410 with notice |
470
+ | GET `/api/migration/{migration_id}/features` | none | none | UNUSED | 410 with notice |
471
+ | GET `/api/migration/{migration_id}/seams` | none | none | UNUSED | 410 with notice |
472
+ | POST `/api/migration/{migration_id}/advance` | none | none | UNUSED | 410 with notice |
473
+ | POST `/api/migration/{migration_id}/start-phase` | none | none | UNUSED | 410 with notice |
474
+ | GET `/api/managed/events` | vscode-extension/media/loki-dashboard.js:11965 | managed memory dropped; GET /v1/runs/:source/:run/events | DROPPED (section 1) | 410 with notice |
475
+ | GET `/api/managed/status` | tests/integration/test_dashboard_api_smoke.sh:105 (test), tests/integration/test_dashboard_api_smoke.sh:106 (test), vscode-extension/media/loki-dashboard.js:11965 | managed memory dropped; GET /v1/runs | DROPPED (section 1) | 410 with notice |
476
+ | GET `/api/managed/memory_versions/{memory_id}` | none | none | UNUSED | 410 with notice |
477
+ | GET `/api/findings/{iteration}` | none | none | UNUSED | 410 with notice |
478
+ | GET `/api/quality/architecture` | none | none | UNUSED | 410 with notice |
479
+ | GET `/api/learnings` | tests/e2e/dashboard-evidence-panels.mjs:72 (test) | none | MISSING | 501 not yet supported |
480
+ | GET `/api/escalations` | vscode-extension/media/loki-dashboard.js:12356 | none | MISSING | 501 not yet supported |
481
+ | GET `/api/escalations/{filename}` | none | none | UNUSED | 410 with notice |
482
+ | GET `/api/phases` | none | none | UNUSED | 410 with notice |
483
+ | GET `/api/proofs` | tests/e2e/dashboard-evidence-panels.mjs:71 (test), tests/e2e/webapp-receipt-panel.mjs:75 (test), tests/e2e/webapp-receipt-panel.mjs:84 (test) | none | MISSING | 501 not yet supported |
484
+ | GET `/api/proofs/summary` | tests/e2e/webapp-receipt-panel.mjs:76 (test) | none | MISSING | 501 not yet supported |
485
+ | GET `/api/proofs/{run_id}` | tests/moat/p2-honest-verdict.sh:1251 (test) | none | MISSING | 501 not yet supported |
486
+ | GET `/api/proofs/{run_id}/html` | none | none | UNUSED | 410 with notice |
487
+ | GET `/api/spec` | none | none | UNUSED | 410 with notice |
488
+ | GET `/api/spec/history` | none | none | UNUSED | 410 with notice |
489
+ | GET `/api/wiki` | none | none | UNUSED | 410 with notice |
490
+ | GET `/api/wiki/{section}` | none | none | UNUSED | 410 with notice |
491
+ | POST `/api/wiki/ask` | vscode-extension/media/loki-dashboard.js:12595 | wiki deleted; no replacement | DROPPED (section 1) | 410 with notice |
492
+ | GET `/{full_path:path}` | none | SPA fallback | EXISTS (CP app.get("*") serves the SPA and 404s missing assets) | none (CP UI serves it) |
493
+
494
+ ### 5.3 Notes for the deletion gate
495
+
496
+ - Test consumers that block deleting the legacy routes (they run the Python app in process, so they need the routes or a rewrite): tests/moat/p2-honest-verdict.sh (GET /api/proofs/{run_id}, GET /api/v2/audit/verify) and tests/moat/p7-no-fabricated-data.sh (/api/status, /api/projects, /api/cost, /api/budget, /api/cost/timeline, /api/fleet/runs, /api/fleet/summary, /api/context, /api/memory/economics, /api/learning/metrics, /api/council/gate, /metrics). tests/e2e/dashboard-evidence-panels.mjs and webapp-receipt-panel.mjs read /api/proofs, /api/proofs/summary, /api/learnings, /api/budget. None of these may be weakened or added to tests/moat/pending.txt; CPE-24 must port the property each one proves before the route goes.
497
+ - Corrections to the inventory hints: tests/moat/p5-sovereignty.sh does not call /api/enterprise/status or /api/enterprise/tokens (it runs `loki start`, matched by the text `/start`); autonomy/loki does not call /api/control/start or /api/control/stop on the dashboard; the VS Code extension requests `/status`, which the legacy server never served (its catch-all answered HTML), so it is not a row.
498
+ - /api/memory/* and /api/learning/* are consumed by the VS Code memory view (src/views/memoryViewProvider.ts, dashboardWebview.ts) and the bundled webview, and p7 reads /api/memory/economics and /api/learning/metrics, so those that appear USED above are not deletable on the UI alone.
499
+ - /health: the CP /health identity ({service: "loki-control"}) is relied on by CLI discovery. Callers that probe the legacy /health body at port 57374 (autonomy/loki, autonomy/run.sh, web-app) need either a migrated probe or a separate listener; the shim does not add one.
500
+
240
501
  ## 6. STEP 2 slice plan
241
502
 
242
503
  Rules: one writer per file; UI pages register through ui/src/pages/registry.ts and server routes through src/server/routes/index.ts, both CREATED with stubs for every planned page and route by CPE-02 and CPE-03, so later slices only fill their own stub files. Wall checks run from packages/control-plane. HIGH = opus D12 review.
@@ -251,7 +512,7 @@ Rules: one writer per file; UI pages register through ui/src/pages/registry.ts a
251
512
  | CPE-06 | Run thread view: stage messages, live log, diff, evidence, receipt, NOT PROVEN, cost, PR, BLOCKED reply prompt, Details drawer; replaces Live.tsx | ui/src/pages/run/**, ui/src/Live.tsx (delete), test/ui/run.test.tsx | `bun test test/ui/run.test.tsx` (fixture run renders every section; missing cost shows "not measured") | 02, 04, 05 | MEDIUM |
252
513
  | CPE-07 | Start-run endpoint POST /v1/runs | src/server/routes/start.ts, src/server/spawn.ts, test/server/start.test.ts | `bun test test/server/start.test.ts` (unknown repo, shell metacharacters, unknown flag, missing token, bad Origin all refused; argv exact) | 03 | HIGH |
253
514
  | CPE-08 | New run composer: one input, chips, Cmd+Enter, optimistic session row, empty state | ui/src/pages/compose/**, test/ui/compose.test.tsx | `bun test test/ui/compose.test.tsx` | 02, 07 | MEDIUM |
254
- | CPE-09 | Run control: supervisor writes <run>/run.pid (pid, start time, argv); stop, retry, resume endpoints | loki-ts/src/engine10/run_pid.ts, loki-ts/src/engine10/supervisor.ts, src/server/routes/control.ts, test/server/control.test.ts, loki-ts/tests/engine10/run_pid.test.ts | `bun test test/server/control.test.ts` and `cd loki-ts && bun test tests/engine10/run_pid.test.ts` (stale pid, reused pid, other run's pid refused) | 03 | HIGH |
515
+ | CPE-09 | Run control: supervisor writes <run>/run.pid (pid, start time, argv); stop, retry, resume endpoints | loki-ts/src/util/run_pid.ts, loki-ts/src/engine10/supervisor.ts, src/server/routes/control.ts, test/server/control.test.ts, loki-ts/tests/engine10/run_pid.test.ts | `bun test test/server/control.test.ts` and `cd loki-ts && bun test tests/engine10/run_pid.test.ts` (stale pid, reused pid, other run's pid refused) | 03 | HIGH |
255
516
  | CPE-10 | Run control UI: Stop (confirm), Retry, Resume with optimistic state and rollback | ui/src/pages/run-controls/** (mounted in the run header slot CPE-06 provides), test/ui/controls.test.tsx | `bun test test/ui/controls.test.tsx` | 06, 09 | LOW |
256
517
  | CPE-11 | Runs table page with filters and group rollup | ui/src/pages/runs/**, test/ui/runs.test.tsx | `bun test test/ui/runs.test.tsx` | 02 | LOW |
257
518
  | CPE-12 | Home: /v1/stats plus KPI tiles, recent runs, BLOCKED inbox | src/server/routes/stats.ts, ui/src/pages/home/**, test/server/stats.test.ts, test/ui/home.test.tsx | `bun test test/server/stats.test.ts test/ui/home.test.tsx` (numbers equal a hand-folded fixture) | 02, 03 | MEDIUM |
@@ -266,7 +527,7 @@ Rules: one writer per file; UI pages register through ui/src/pages/registry.ts a
266
527
  | CPE-21 | Notifications and Audit log: derived notifications, actions view | src/server/routes/notify.ts, src/server/routes/audit.ts, ui/src/pages/notifications/**, ui/src/pages/audit/**, test/server/notify.test.ts | `bun test test/server/notify.test.ts` | 03 | LOW |
267
528
  | CPE-22 | Cmd+K palette, global search, shortcuts (Cmd+Enter, Cmd+N, Cmd+Shift+D, Esc) | ui/src/palette/**, test/ui/palette.test.tsx | `bun test test/ui/palette.test.tsx` | 02 | LOW |
268
529
  | CPE-23 | Accessibility, mobile and visual parity: axe, keyboard path, 375 px layout, light and dark screenshot comparison to legacy captures | test/e2e/cp-ui.spec.ts, test/e2e/legacy-baseline/**, ui/playwright.config.ts | `bunx playwright test test/e2e/cp-ui.spec.ts` (headless, LOKI_NO_BROWSER=1) | 06, 08, 12 | MEDIUM |
269
- | CPE-24 | Delete legacy dashboard at parity: dashboard-ui/, dashboard/static/, legacy server routes, their tests and package entries | dashboard-ui/**, dashboard/static/**, dashboard/server.py (UI routes), package.json files list, tests naming them | section 5 checklist all green plus `bash scripts/local-ci.sh` | all, section 5 | MEDIUM |
530
+ | CPE-24 | Delete legacy dashboard at parity: legacy-ui/, legacy-ui-static/, legacy server routes, their tests and package entries | legacy-ui/**, legacy-ui-static/**, dashboard/server.py (UI routes), package.json files list, tests naming them | section 5 checklist all green plus `bash scripts/local-ci.sh` | all, section 5 | MEDIUM |
270
531
 
271
532
  Parallelism: CPE-01 and CPE-03 start at once; after them up to 12 builders run in parallel (04, 05, 07, 09, 11, 12, 13, 14, 15, 18, 21, 22). HIGH slices (04, 07, 09, 14) carry the security review the founder asked for.
272
533
 
@@ -98,7 +98,7 @@ Failure modes:
98
98
  | B11 | PR comment with the integration result, via the existing gh token path (no LLM in the step) | autonomy/lib/workspace_comment.py, tests/workspace/80-comment.sh | stub gh receives one comment per PR; the token appears in no log or argv | MEDIUM |
99
99
  | B12 | CLI `loki workspace` subcommand (list, show, run, status, clean) | autonomy/loki, tests/workspace/90-cli.sh | flag off: the command says it is disabled; `clean` never removes a worktree whose branch has an open PR | MEDIUM |
100
100
  | B13 | Dashboard endpoints reading group.json; run launches a detached runner | dashboard/api_workspaces.py, dashboard/server.py, tests/dashboard/test_api_workspaces.py | the group survives an app restart; non-loopback Host gets 403; control scope required for run | HIGH |
101
- | B14 | Dashboard group card (per-repo rows, integration row, stale-evidence badge) | dashboard/static/start.html | Playwright: a fixture group renders 2 repo rows plus integration; a mismatched head SHA shows stale | LOW |
101
+ | B14 | Dashboard group card (per-repo rows, integration row, stale-evidence badge) | legacy-ui-static/start.html | Playwright: a fixture group renders 2 repo rows plus integration; a mismatched head SHA shows stale | LOW |
102
102
  | B15 | 10x metric: PRs per wall-clock hour and per attention minute from group.json timestamps | autonomy/lib/workspace_metrics.py, tests/workspace/95-metrics.sh | a fixture group gives the hand-computed rate; unmeasured runs are reported, not counted as zero | LOW |
103
103
  | B16 | Docs plus flag flip after the whole-feature Wall: a 2-repo fixture (lib and app) ends with 2 PRs and integration passed | docs/WORKSPACES.md, tests/workspace/99-e2e.sh | the e2e part passes on CI with the stub provider; one real run is recorded in METRICS.md | MEDIUM |
104
104
 
@@ -451,18 +451,18 @@ Loki's definition: "autonomous software factory that runs with the knowledge of
451
451
  4. Order: P0 first-run bugs, first run end to end with a recorded demo, PR body and cost cap, D51 Phase B, D51 Phase C. D50 continues only where it raises completion or merge rate. Every release note leads with the user-visible v1 change.
452
452
 
453
453
  ## D55 (CTO, 2026-10-01; reversible via repo variable LOKI_E160_REUSE=0): a push to main reuses a train's verdict for the identical SHA
454
- 1. Rule (E-160, scripts/ci/train-verdict-reuse.sh). A push to refs/heads/main skips the heavy jobs only when ALL hold: LOKI_E160_REUSE is not 0; the workflow-runs listing for the SHA has total_count of 100 or less; among completed push runs of the same workflow file, other than this run, whose head_branch starts with train/, there is at least one success and no failure, timed_out or startup_failure (cancelled, skipped and neutral count for nothing); and, for Tests only, BEFORE is not all zeros and the BEFORE...SHA compare succeeded, lists fewer than 300 files and touches none of loki-ts/bun.lock, requirements-test.txt, dashboard-ui/package-lock.json. Any parse or API error means reuse=false and the full suite runs. The newest success by created_at is recorded (run id, attempt, branch) in the step summary and a notice; attempts above 1 are accepted.
454
+ 1. Rule (E-160, scripts/ci/train-verdict-reuse.sh). A push to refs/heads/main skips the heavy jobs only when ALL hold: LOKI_E160_REUSE is not 0; the workflow-runs listing for the SHA has total_count of 100 or less; among completed push runs of the same workflow file, other than this run, whose head_branch starts with train/, there is at least one success and no failure, timed_out or startup_failure (cancelled, skipped and neutral count for nothing); and, for Tests only, BEFORE is not all zeros and the BEFORE...SHA compare succeeded, lists fewer than 300 files and touches none of loki-ts/bun.lock, requirements-test.txt, legacy-ui/package-lock.json. Any parse or API error means reuse=false and the full suite runs. The newest success by created_at is recorded (run id, attempt, branch) in the step summary and a notice; attempts above 1 are accepted.
455
455
  2. Wiring. test.yml: the version-bump-gate skip output is true when either the S-132 gate or the reuse step says so. bun-parity, coverage, first-run-gate and security-audit get a first job train-reuse; every other job needs it and runs under `!cancelled() && needs.train-reuse.outputs.reuse != 'true'`. security-audit sast (CodeQL) is never gated: it always runs on main. coverage and first-run-gate take test.yml's concurrency block (per-ref with cancel for pull_request and train/**, per-SHA without cancel on main).
456
456
  3. Rationale: D28 and D46 item 4 (same SHA means same tree means same workflow YAML). required-ci, train-cycle, the pulse and the version-bump gate already read the train run by head_sha, so no gate gains new trust. Dependency lockfiles are excluded because a fast-forward from an older main can change resolved dependencies that the train run did not see.
457
457
  ## D56 (founder, relayed 15:40Z; numbered D56 because D55 is the E-160 CTO ruling): the Loki Control Plane replaces the dashboards
458
- 1. One service plus one UI, `loki control`, replaces dashboard/, dashboard-ui/ and engine10/dashboard. It runs locally with zero config or is deployed once for many runs. It is stateless and horizontally scalable, keeps all state in a DB (SQLite locally, Postgres via DATABASE_URL), and is self-healing (/health, /ready, migrations on boot, spool replay, CLI restart of a dead local instance, k8s probes, version-checked reuse).
458
+ 1. One service plus one UI, `loki control`, replaces dashboard/, legacy-ui/ and engine10/dashboard. It runs locally with zero config or is deployed once for many runs. It is stateless and horizontally scalable, keeps all state in a DB (SQLite locally, Postgres via DATABASE_URL), and is self-healing (/health, /ready, migrations on boot, spool replay, CLI restart of a dead local instance, k8s probes, version-checked reuse).
459
459
  2. Stack: TypeScript on Bun with Hono and Drizzle; React, Vite and Tailwind built into static assets served by the same service; one container image.
460
460
  3. Ingest: engine10 ships batched events with idempotent ids to LOKI_CONTROL_URL, with retry; the run's own events.jsonl is the spool. `loki control backfill` imports existing runs.
461
461
  4. Every number comes from ingested events; no placeholders or invented data; an empty panel says so. Localhost-only by default, token auth when bound non-local, no secrets in events.
462
462
  5. Built in packages/control-plane/ behind LOKI_CONTROL=1 until it passes its acceptance tests (real runs in, correct counts out), then the default flips and the old UIs are deleted. v0 (service, SQLite, ingest, shipper, Runs list and detail) ships on D46 trains first; the other views follow train by train.
463
463
  6. Design: docs/v10/CONTROL-PLANE.md (architect slice in progress). Old-dashboard bug work is retired, except the P0 that shipped in 10.5.34.
464
464
  ## D55 (CTO, 2026-10-01; reversible via repo variable LOKI_E160_REUSE=0): a push to main reuses a train's verdict for the identical SHA
465
- 1. Rule (E-160, scripts/ci/train-verdict-reuse.sh). A push to refs/heads/main skips the heavy jobs only when ALL hold: LOKI_E160_REUSE is not 0; the workflow-runs listing for the SHA has total_count of 100 or less; among completed push runs of the same workflow file, other than this run, whose head_branch starts with train/, there is at least one success and no failure, timed_out or startup_failure (cancelled, skipped and neutral count for nothing); and, for Tests only, BEFORE is not all zeros and the BEFORE...SHA compare succeeded, lists fewer than 300 files and touches none of loki-ts/bun.lock, requirements-test.txt, dashboard-ui/package-lock.json. Any parse or API error means reuse=false and the full suite runs. The newest success by created_at is recorded (run id, attempt, branch) in the step summary and a notice; attempts above 1 are accepted.
465
+ 1. Rule (E-160, scripts/ci/train-verdict-reuse.sh). A push to refs/heads/main skips the heavy jobs only when ALL hold: LOKI_E160_REUSE is not 0; the workflow-runs listing for the SHA has total_count of 100 or less; among completed push runs of the same workflow file, other than this run, whose head_branch starts with train/, there is at least one success and no failure, timed_out or startup_failure (cancelled, skipped and neutral count for nothing); and, for Tests only, BEFORE is not all zeros and the BEFORE...SHA compare succeeded, lists fewer than 300 files and touches none of loki-ts/bun.lock, requirements-test.txt, legacy-ui/package-lock.json. Any parse or API error means reuse=false and the full suite runs. The newest success by created_at is recorded (run id, attempt, branch) in the step summary and a notice; attempts above 1 are accepted.
466
466
  2. Wiring. test.yml: the version-bump-gate skip output is true when either the S-132 gate or the reuse step says so. bun-parity, coverage, first-run-gate and security-audit get a first job train-reuse; every other job needs it and runs under `!cancelled() && needs.train-reuse.outputs.reuse != 'true'`. security-audit sast (CodeQL) is never gated: it always runs on main. coverage and first-run-gate take test.yml's concurrency block (per-ref with cancel for pull_request and train/**, per-SHA without cancel on main).
467
467
  3. Rationale: D28 and D46 item 4 (same SHA means same tree means same workflow YAML). required-ci, train-cycle, the pulse and the version-bump gate already read the train run by head_sha, so no gate gains new trust. Dependency lockfiles are excluded because a fast-forward from an older main can change resolved dependencies that the train run did not see.
468
468
 
package/docs/v10/DEPS.md CHANGED
@@ -8,11 +8,11 @@ Inventory only. No dependency, lockfile, workflow or image was changed to produc
8
8
 
9
9
  | File | Name | Current | Latest stable | Bump | Note |
10
10
  |---|---|---|---|---|---|
11
- | `dashboard-ui/package.json` | `@playwright/test` | `^1.58.1` | `1.63.0` | minor | |
12
- | `dashboard-ui/package.json` | `esbuild` | `^0.24.0` | `0.28.2` | 0.x breaking | |
13
- | `dashboard-ui/package.json` | `jest` | `^29.7.0` | `30.5.2` | MAJOR | |
14
- | `dashboard-ui/package.json` | `jest-environment-jsdom` | `^29.7.0` | `30.5.2` | MAJOR | |
15
- | `dashboard-ui/package.json` | `jsdom` | `^24.0.0` | `30.1.1` | MAJOR | |
11
+ | `legacy-ui/package.json` | `@playwright/test` | `^1.58.1` | `1.63.0` | minor | |
12
+ | `legacy-ui/package.json` | `esbuild` | `^0.24.0` | `0.28.2` | 0.x breaking | |
13
+ | `legacy-ui/package.json` | `jest` | `^29.7.0` | `30.5.2` | MAJOR | |
14
+ | `legacy-ui/package.json` | `jest-environment-jsdom` | `^29.7.0` | `30.5.2` | MAJOR | |
15
+ | `legacy-ui/package.json` | `jsdom` | `^24.0.0` | `30.1.1` | MAJOR | |
16
16
  | `loki-ts/package.json` | `@anthropic-ai/claude-agent-sdk` | `0.3.283` | `0.3.283` | up-to-date | |
17
17
  | `loki-ts/package.json` | `@anthropic-ai/sdk` | `^0.124.0` | `0.128.0` | 0.x breaking | |
18
18
  | `loki-ts/package.json` | `@resvg/resvg-wasm` | `^2.6.2` | `2.6.2` | up-to-date | |
@@ -384,7 +384,7 @@ Counts are all from the single `Bump` column (current line vs newest line in the
384
384
  ## Proposed slice list (D35)
385
385
 
386
386
  - **LOW - npm/bun patch+minor batch** (one slice for the whole ecosystem, touching every file below; lockfiles regenerated and committed):
387
- - `dashboard-ui/package.json`: @playwright/test ^1.58.1->1.63.0
387
+ - `legacy-ui/package.json`: @playwright/test ^1.58.1->1.63.0
388
388
  - `vscode-extension/package.json`: @types/vscode ^1.85.0->1.138.0
389
389
  - `web-app/package.json`: @playwright/test ^1.58.2->1.63.0, @types/react ^19.0.10->19.3.0, @types/react-dom ^19.0.4->19.3.0, autoprefixer ^10.4.20->10.6.1, postcss ^8.5.3->8.5.28, react ^19.0.0->19.3.0, react-dom ^19.0.0->19.3.0, react-resizable-panels ^4.7.3->4.14.1, react-router-dom ^7.13.1->7.18.4, typescript-eslint ^8.24.1->8.70.1
390
390
  - **LOW - Python patch+minor batch** (one slice for the whole ecosystem, touching every file below; lockfiles regenerated and committed):
@@ -404,16 +404,16 @@ Counts are all from the single `Bump` column (current line vs newest line in the
404
404
  - `anthropic` -> `1.8.0` (MAJOR): mcp/requirements.txt
405
405
  - `asyncpg` -> `0.31.0` (0.x breaking): web-app/requirements.txt
406
406
  - `cryptography` -> `50.0.1` (MAJOR): requirements-test.txt, web-app/requirements.txt
407
- - `esbuild` -> `0.28.2` (0.x breaking): dashboard-ui/package.json, vscode-extension/package.json
407
+ - `esbuild` -> `0.28.2` (0.x breaking): legacy-ui/package.json, vscode-extension/package.json
408
408
  - `eslint` -> `10.11.0` (MAJOR): vscode-extension/package.json, web-app/package.json
409
409
  - `eslint-plugin-react-hooks` -> `7.1.1` (MAJOR): web-app/package.json
410
410
  - `eslint-plugin-react-refresh` -> `0.5.7` (0.x breaking): web-app/package.json
411
411
  - `fastapi` -> `0.141.1` (0.x breaking): dashboard/requirements.txt, web-app/requirements.txt
412
412
  - `globals` -> `17.12.0` (MAJOR): web-app/package.json
413
413
  - `httpx` -> `0.28.1` (0.x breaking): sdk/python/pyproject.toml, web-app/requirements-test.txt, web-app/requirements.txt
414
- - `jest` -> `30.5.2` (MAJOR): dashboard-ui/package.json, package.json
415
- - `jest-environment-jsdom` -> `30.5.2` (MAJOR): dashboard-ui/package.json
416
- - `jsdom` -> `30.1.1` (MAJOR): dashboard-ui/package.json, package.json
414
+ - `jest` -> `30.5.2` (MAJOR): legacy-ui/package.json, package.json
415
+ - `jest-environment-jsdom` -> `30.5.2` (MAJOR): legacy-ui/package.json
416
+ - `jsdom` -> `30.1.1` (MAJOR): legacy-ui/package.json, package.json
417
417
  - `lucide-react` -> `1.48.0` (MAJOR): web-app/package.json
418
418
  - `mcp` -> `2.2.0` (MAJOR): mcp/requirements.txt, requirements-test.txt
419
419
  - `pytest` -> `9.1.1` (MAJOR): web-app/requirements-test.txt