loki-mode 10.8.0 → 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 (147) hide show
  1. package/README.md +2 -2
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/loki +16 -31
  5. package/autonomy/tui.sh +5 -1
  6. package/dashboard/__init__.py +1 -1
  7. package/dashboard/api_phases.py +1 -1
  8. package/dashboard/api_start.py +0 -1
  9. package/dashboard/server.py +22 -138
  10. package/docs/COCKPIT-SPEC.md +3 -1
  11. package/docs/DASHBOARD-9.12-EVIDENCE.md +1 -1
  12. package/docs/DASHBOARD-ARCHITECTURE.md +13 -11
  13. package/docs/DASHBOARD_V2_CHECKLIST.md +2 -0
  14. package/docs/INSTALLATION.md +12 -11
  15. package/docs/MERGE-DEDUP-MAP.md +1 -1
  16. package/docs/MERGE-ROUTE-MAP.md +1 -1
  17. package/docs/MERGE3-PLAN.md +2 -2
  18. package/docs/R3-COST-OBSERVABILITY-DESIGN.md +2 -2
  19. package/docs/R4-TRUST-TRAJECTORY-DESIGN.md +1 -1
  20. package/docs/R5-AUTO-WIKI-DESIGN.md +1 -1
  21. package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +1 -1
  22. package/docs/RARV-C-100X-PLAN.md +3 -3
  23. package/docs/SONNET5-DEFAULT-PLAN.md +2 -2
  24. package/docs/SYNERGY-TASKS.md +1 -1
  25. package/docs/TOOL-INTEGRATION.md +1 -1
  26. package/docs/TOP-100-BACKLOG.md +1 -1
  27. package/docs/alternative-installations.md +1 -1
  28. package/docs/architecture/ADR-001-runtime-migration.md +1 -1
  29. package/docs/architecture/DASHBOARD_V2_ARCHITECTURE.md +2 -0
  30. package/docs/audit-logging.md +2 -0
  31. package/docs/authentication.md +2 -0
  32. package/docs/authorization.md +2 -0
  33. package/docs/certification/02-enterprise-features/lab.md +2 -0
  34. package/docs/certification/02-enterprise-features/lesson.md +2 -0
  35. package/docs/certification/04-production-deployment/lab.md +2 -0
  36. package/docs/certification/04-production-deployment/lesson.md +2 -0
  37. package/docs/control-plane-migration.md +97 -0
  38. package/docs/dashboard-guide.md +6 -7
  39. package/docs/dev/release-checklist.md +9 -11
  40. package/docs/enterprise/integration-cookbook.md +2 -0
  41. package/docs/enterprise/migration.md +1 -1
  42. package/docs/enterprise/performance.md +3 -1
  43. package/docs/enterprise/sdk-guide.md +2 -0
  44. package/docs/enterprise/security.md +2 -0
  45. package/docs/plans/FORGE-AUTONOMOUS-QUEUE.md +2 -2
  46. package/docs/research-2026-07/OBSERVABILITY-TOOL-SPEC.md +1 -1
  47. package/docs/retrospectives/v7.5.15-honesty-audit.md +2 -2
  48. package/docs/test-scenarios/enterprise-scenarios.md +2 -2
  49. package/docs/v10/ARCHITECT-CUTS.md +9 -9
  50. package/docs/v10/BACKLOG.md +7 -7
  51. package/docs/v10/BOARD.md +25 -25
  52. package/docs/v10/CONTROL-PLANE.md +4 -4
  53. package/docs/v10/CP-ENTERPRISE-UI.md +66 -66
  54. package/docs/v10/D51-PHASE-B.md +1 -1
  55. package/docs/v10/DECISIONS.md +3 -3
  56. package/docs/v10/DEPS.md +10 -10
  57. package/docs/v10/FAILURE-CLASSES.md +45 -1
  58. package/docs/v10/LEGACY-REMOVAL.md +2 -2
  59. package/docs/v10/SWARM.md +2 -2
  60. package/loki-ts/dist/cockpit.js +11 -11
  61. package/loki-ts/dist/loki.js +596 -579
  62. package/magic/core/design_tokens.py +1 -2
  63. package/magic/core/generator.py +2 -2
  64. package/magic/tokens/README.md +1 -3
  65. package/mcp/__init__.py +1 -1
  66. package/package.json +2 -7
  67. package/packages/control-plane/dist/server.js +1683 -843
  68. package/packages/control-plane/src/server/legacy/routes-audit.ts +50 -0
  69. package/packages/control-plane/src/server/legacy/routes-control.ts +26 -0
  70. package/packages/control-plane/src/server/legacy/routes-memory.ts +30 -0
  71. package/packages/control-plane/src/server/legacy/routes.ts +58 -58
  72. package/packages/control-plane/src/server/legacy/shim.ts +10 -4
  73. package/packages/control-plane/src/server/routes/checkpoints.ts +171 -0
  74. package/packages/control-plane/src/server/routes/index.ts +4 -1
  75. package/packages/control-plane/src/server/routes/memory.ts +219 -0
  76. package/packages/control-plane/src/server/routes/session_control.ts +155 -0
  77. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  78. package/references/magic-modules-patterns.md +2 -2
  79. package/skills/factory-operations.md +3 -3
  80. package/skills/magic-modules.md +1 -1
  81. package/skills/release-cadence.md +1 -1
  82. package/tools/audit-docs.py +1 -1
  83. package/tools/index-codebase.py +1 -1
  84. package/web-app/dist/assets/{AdminPage-DDDvUz0N.js → AdminPage-DqMnfZrH.js} +1 -1
  85. package/web-app/dist/assets/{Avatar-Dcdz46i6.js → Avatar-BEof29du.js} +1 -1
  86. package/web-app/dist/assets/{Badge-BB24cCpK.js → Badge-WD53OL5m.js} +1 -1
  87. package/web-app/dist/assets/{Button-D0-DmPZL.js → Button-Rzk5flhU.js} +1 -1
  88. package/web-app/dist/assets/{CockpitPage-CdjpU2JW.js → CockpitPage-Bqz3PCMh.js} +1 -1
  89. package/web-app/dist/assets/{ComparePage-DT5U0y0d.js → ComparePage-Byo2NzAZ.js} +1 -1
  90. package/web-app/dist/assets/{ErrorBoundary-lEHcl0EO.js → ErrorBoundary-BuE0kH3W.js} +1 -1
  91. package/web-app/dist/assets/{EvidenceReceiptPanel-GpnWvdCr.js → EvidenceReceiptPanel-CKFHOPBx.js} +1 -1
  92. package/web-app/dist/assets/{GitHubIssuesPanel-C7VOh1B7.js → GitHubIssuesPanel-Df_kTMqI.js} +1 -1
  93. package/web-app/dist/assets/{GitHubPRsPanel-G_kOuINv.js → GitHubPRsPanel-CouvcKrZ.js} +1 -1
  94. package/web-app/dist/assets/{HomePage-PqRisOny.js → HomePage-dEpLzj0x.js} +2 -2
  95. package/web-app/dist/assets/{LoginPage-DU7pFAkf.js → LoginPage-6DVjUND5.js} +1 -1
  96. package/web-app/dist/assets/{MagicPage-C5JWIWMk.js → MagicPage-BDQ9MOfY.js} +1 -1
  97. package/web-app/dist/assets/{MetricsPage-CbIGS_qo.js → MetricsPage-CXiJ04G_.js} +1 -1
  98. package/web-app/dist/assets/{NotFoundPage-vU1pvdSt.js → NotFoundPage-BaXhZvyj.js} +1 -1
  99. package/web-app/dist/assets/{ProjectPage-SsixIPPv.js → ProjectPage-BzE4V7Ti.js} +3 -3
  100. package/web-app/dist/assets/{ProjectsPage-BfQKSR9k.js → ProjectsPage-ipf6TLMX.js} +1 -1
  101. package/web-app/dist/assets/{SettingsPage-B8YfXAom.js → SettingsPage-BDxkUKN6.js} +1 -1
  102. package/web-app/dist/assets/{ShowcasePage-Ba407f2-.js → ShowcasePage-YQXD72SM.js} +1 -1
  103. package/web-app/dist/assets/{SystemSettingsPage-DzNQhhBS.js → SystemSettingsPage-Dou7zHS0.js} +1 -1
  104. package/web-app/dist/assets/{TeamsPage-tqUnpZ15.js → TeamsPage-CQarfcYr.js} +1 -1
  105. package/web-app/dist/assets/{TemplatesPage-ClB5EpI3.js → TemplatesPage-CPi1R8Xj.js} +1 -1
  106. package/web-app/dist/assets/{TerminalOutput-CBvpYfEu.js → TerminalOutput-WiGhWdYD.js} +1 -1
  107. package/web-app/dist/assets/{activity-C1s0L_X9.js → activity-DOa7ejQA.js} +1 -1
  108. package/web-app/dist/assets/{bell-DMEiXr73.js → bell-CX-VAlYN.js} +1 -1
  109. package/web-app/dist/assets/{bot-BF_xIOxu.js → bot-EDXaZmHc.js} +1 -1
  110. package/web-app/dist/assets/{check-Dv1Ynvrs.js → check-CnBdKk3L.js} +1 -1
  111. package/web-app/dist/assets/{chevron-left-Ddhsod7S.js → chevron-left-BJ_ydRQW.js} +1 -1
  112. package/web-app/dist/assets/{circle-alert-OATHUkBZ.js → circle-alert-tz8ufhc_.js} +1 -1
  113. package/web-app/dist/assets/{clock-C1Ltva07.js → clock-DFBZPSsH.js} +1 -1
  114. package/web-app/dist/assets/{cloud-B-S4oOy9.js → cloud-uy3p_5Q7.js} +1 -1
  115. package/web-app/dist/assets/{code-xml-D3Femn_F.js → code-xml-3CbYD9YL.js} +1 -1
  116. package/web-app/dist/assets/{database-DBSeFgO3.js → database-YiNBXc9c.js} +1 -1
  117. package/web-app/dist/assets/{dollar-sign-sgDgNuGE.js → dollar-sign-D0wBa4Cv.js} +1 -1
  118. package/web-app/dist/assets/{file-code-corner-C-MbdZEc.js → file-code-corner-DDdZVZ5v.js} +1 -1
  119. package/web-app/dist/assets/{file-plus-CCB6yqXv.js → file-plus-D09LTBqt.js} +1 -1
  120. package/web-app/dist/assets/{globe-DlbrNAj1.js → globe-BirTPwff.js} +1 -1
  121. package/web-app/dist/assets/{hammer-B-DWm695.js → hammer-DaE5qgnd.js} +1 -1
  122. package/web-app/dist/assets/{index-Dvny-1SU.js → index-D8t7KnQf.js} +3 -3
  123. package/web-app/dist/assets/{layers-99qsKpOT.js → layers-DVVrckRY.js} +1 -1
  124. package/web-app/dist/assets/{loader-circle-ZvZyZl3J.js → loader-circle-2-nMGmcb.js} +1 -1
  125. package/web-app/dist/assets/{lock-DosGjcxP.js → lock-D0Xj43pC.js} +1 -1
  126. package/web-app/dist/assets/{package-C-PumesN.js → package-BB7S3egm.js} +1 -1
  127. package/web-app/dist/assets/{plus-CTYYskTB.js → plus-BLhoMrn3.js} +1 -1
  128. package/web-app/dist/assets/{refresh-cw-qW2ztTFS.js → refresh-cw-DMc2uPLw.js} +1 -1
  129. package/web-app/dist/assets/{rotate-ccw-ZIKrf-vO.js → rotate-ccw-DM3IP9x7.js} +1 -1
  130. package/web-app/dist/assets/{scroll-text-BamlXjAT.js → scroll-text-lH2uW7rB.js} +1 -1
  131. package/web-app/dist/assets/{server-BljXb79I.js → server-BkerZcdR.js} +1 -1
  132. package/web-app/dist/assets/{shield-alert-Dr6eT9c_.js → shield-alert-B8ohcUfu.js} +1 -1
  133. package/web-app/dist/assets/{thumbs-up-v3oBXZgU.js → thumbs-up-CTIxLzPD.js} +1 -1
  134. package/web-app/dist/assets/{trash-2-BOuIrCpi.js → trash-2-C3zIpsH5.js} +1 -1
  135. package/web-app/dist/assets/{trending-down-Dp7jMCgH.js → trending-down-BTT7wV4Y.js} +1 -1
  136. package/web-app/dist/assets/{trending-up-CDiur-nP.js → trending-up-BzHdCDvF.js} +1 -1
  137. package/web-app/dist/assets/{upload-DxIHXhNE.js → upload-HxR34-A8.js} +1 -1
  138. package/web-app/dist/assets/{usePolling-D2Uu-YZb.js → usePolling-DDj6Fupy.js} +1 -1
  139. package/web-app/dist/assets/{user-BVWCUAfF.js → user-qH5y9yNy.js} +1 -1
  140. package/web-app/dist/index.html +1 -1
  141. package/dashboard/static/assets/mermaid.min.js +0 -2030
  142. package/dashboard/static/cost.html +0 -344
  143. package/dashboard/static/favicon.svg +0 -5
  144. package/dashboard/static/index.html +0 -15577
  145. package/dashboard/static/proofs.html +0 -194
  146. package/dashboard/static/start.html +0 -131
  147. package/dashboard/static/trust.html +0 -325
@@ -63,7 +63,7 @@
63
63
  - Add an optional `(?:React\.)?useMemo\(\s*\(\)\s*=>\s*` prefix ahead of the fabricator-call pattern.
64
64
  - The comment stops listing this shape as a ceiling.
65
65
  - Branch: run the widened arm on main first.
66
- - On any live hit in dashboard-ui or web-app, the slice becomes report-only.
66
+ - On any live hit in legacy-ui or web-app, the slice becomes report-only.
67
67
  - Never add an allowlist. cases.txt stays unchanged.
68
68
  - Wall:
69
69
  - `bash tests/moat/p7-no-fabricated-data.sh` prints PASS for every P7 case and flags the composed fixture.
@@ -207,9 +207,9 @@
207
207
  ### S-223: notification triggers read "No triggers configured" after a failed read (BACKLOG 114 and 118)
208
208
  - Files:
209
209
  - dashboard/server.py: `get_notification_triggers` only.
210
- - dashboard-ui/components/loki-notification-center.js: `_loadTriggers` and the triggers empty branch only.
210
+ - legacy-ui/components/loki-notification-center.js: `_loadTriggers` and the triggers empty branch only.
211
211
  - tests/dashboard/test_notification_triggers_unreadable.py (new)
212
- - dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs (new)
212
+ - legacy-ui/tests/loki-notification-triggers-error.node.test.mjs (new)
213
213
  - Tier: LOW
214
214
  - Red:
215
215
  - A corrupt triggers.json answers `{"triggers": []}`.
@@ -220,7 +220,7 @@
220
220
  - A missing file still answers `[]`.
221
221
  - Wall:
222
222
  - `python3 -m pytest -q tests/dashboard/test_notification_triggers_unreadable.py` passes.
223
- - `node --test dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs` passes: an error lacks "No triggers configured", and an empty list keeps it.
223
+ - `node --test legacy-ui/tests/loki-notification-triggers-error.node.test.mjs` passes: an error lacks "No triggers configured", and an empty list keeps it.
224
224
 
225
225
  ### S-224: the web-app receipt and cost trend show a partly priced run as a complete cost (BACKLOG 118)
226
226
  - Files:
@@ -240,7 +240,7 @@
240
240
 
241
241
  ### S-225: the standalone receipts list shows a partly priced run as a complete cost (BACKLOG 118)
242
242
  - Files:
243
- - dashboard-ui/scripts/build-standalone.js (the `loadReceipts` cost cell only)
243
+ - legacy-ui/scripts/build-standalone.js (the `loadReceipts` cost cell only)
244
244
  - tests/test-receipts-panel.sh (one new leg)
245
245
  - Tier: LOW
246
246
  - Green:
@@ -382,7 +382,7 @@
382
382
  - S-220: tests/test-untrack-keeps-force-staged.sh
383
383
  - S-221: tests/dashboard/test_audit_verify_cli_nothing_checked.py
384
384
  - S-222: tests/dashboard/test_skill_session_ws_running_agents.py
385
- - S-223: tests/dashboard/test_notification_triggers_unreadable.py and dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs
385
+ - S-223: tests/dashboard/test_notification_triggers_unreadable.py and legacy-ui/tests/loki-notification-triggers-error.node.test.mjs
386
386
  - S-224: web-app/src/components/EvidenceReceiptPanel.cost.test.mjs
387
387
  - S-226: tests/test-stats-unmeasured-cost.sh and loki-ts/tests/commands/stats_unmeasured.test.ts
388
388
  - S-227: tests/test-status-budget-unmeasured.sh
@@ -394,7 +394,7 @@
394
394
  - loki-ts/dist: S-226, S-227.
395
395
  - web-app/dist: S-224, S-228, S-229, S-230.
396
396
  - dashboard static: S-225.
397
- - dashboard-ui dist and dashboard static: S-223.
397
+ - legacy-ui dist and dashboard static: S-223.
398
398
  - **Merge order:**
399
399
  - run.sh: S-217, S-218, S-219, S-220 and S-233, plus S-194 and S-195 in flight. They name regions that do not overlap, anchor on function names, and merge one at a time.
400
400
  - autonomy/loki: S-226 and S-227, plus S-197 in flight, one at a time.
@@ -427,9 +427,9 @@
427
427
  | S-220 | BACKLOG 109: untrack step's global reset drops force-staged agent files from the session commit | autonomy/run.sh (_loki_untrack_agent_committed_user_files only), tests/test-untrack-keeps-force-staged.sh (new) | MEDIUM | bash tests/test-untrack-keeps-force-staged.sh exits 0: git add -f dist/bundle.js lands in the session commit while the pre-existing user file stays untracked on disk; restoring git reset -q in a scratch copy fails it; bash tests/test-branch-lifecycle.sh exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
428
428
  | S-221 | BACKLOG 123: audit.py verify exits 0 when it checked nothing | dashboard/audit.py (_unified_cli verify branch and docstring only; tip and prefix untouched), tests/dashboard/test_audit_verify_cli_nothing_checked.py (new) | MEDIUM | python3 -m pytest -q tests/dashboard/test_audit_verify_cli_nothing_checked.py: empty dir exits 2, valid chain 0, tampered 1, tip on an empty dir still 0; bash tests/test-audit-chain-honesty.sh and bash tests/test-audit-js-suites.sh exit 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
429
429
  | S-222 | BACKLOG 118: skill-session WebSocket status push hardcodes running_agents 0 | dashboard/server.py (skill-session broadcast payload ~1030-1047 only), tests/dashboard/test_skill_session_ws_running_agents.py (new) | LOW | python3 -m pytest -q tests/dashboard/test_skill_session_ws_running_agents.py shows running_agents None on the skill-session push; restoring 0 fails it | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
430
- | S-223 | BACKLOG 114/118: notification triggers read No triggers configured after a failed read | dashboard/server.py (get_notification_triggers only), dashboard-ui/components/loki-notification-center.js (_loadTriggers and triggers empty branch only), tests/dashboard/test_notification_triggers_unreadable.py (new), dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs (new) | LOW | python3 -m pytest -q tests/dashboard/test_notification_triggers_unreadable.py shows triggers null with error on a corrupt file and [] on a missing one; node --test dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs shows an error lacks No triggers configured and an empty list keeps it | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
430
+ | S-223 | BACKLOG 114/118: notification triggers read No triggers configured after a failed read | dashboard/server.py (get_notification_triggers only), legacy-ui/components/loki-notification-center.js (_loadTriggers and triggers empty branch only), tests/dashboard/test_notification_triggers_unreadable.py (new), legacy-ui/tests/loki-notification-triggers-error.node.test.mjs (new) | LOW | python3 -m pytest -q tests/dashboard/test_notification_triggers_unreadable.py shows triggers null with error on a corrupt file and [] on a missing one; node --test legacy-ui/tests/loki-notification-triggers-error.node.test.mjs shows an error lacks No triggers configured and an empty list keeps it | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
431
431
  | S-224 | BACKLOG 118: web-app receipt and cost trend show a partly priced run as a complete cost | web-app/src/components/EvidenceReceiptPanel.tsx (Cost field only), web-app/src/api/client.ts (ProofDetail cost type and cost/timeline runs type only), web-app/src/pages/MetricsPage.tsx (costTrend only), web-app/src/components/EvidenceReceiptPanel.cost.test.mjs (new) | MEDIUM | node --test web-app/src/components/EvidenceReceiptPanel.cost.test.mjs: cost_partial true renders at least $1.20, absent keeps $1.20, a partial run's trend label carries (partial); cd web-app && npx tsc -b exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
432
- | S-225 | BACKLOG 118: standalone receipts list shows a partly priced run as a complete cost | dashboard-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg) | LOW | bash tests/test-receipts-panel.sh exits 0 with the new leg asserting at least $X.XX only when cost_partial is true; bash tests/test-budget-banner-dedup.sh exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
432
+ | S-225 | BACKLOG 118: standalone receipts list shows a partly priced run as a complete cost | legacy-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg) | LOW | bash tests/test-receipts-panel.sh exits 0 with the new leg asserting at least $X.XX only when cost_partial is true; bash tests/test-budget-banner-dedup.sh exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
433
433
  | S-226 | BACKLOG 106 class: loki stats reads unmeasured cost as $0.00 on both routes | autonomy/loki (cmd_stats only), loki-ts/src/commands/stats.ts, loki-ts/tests/commands/stats_unmeasured.test.ts (new), tests/test-stats-unmeasured-cost.sh (new) | MEDIUM | bash tests/test-stats-unmeasured-cost.sh exits 0 (all-zero records give cost_usd null and not recorded, same on both routes); cd loki-ts && bun test tests/commands/stats.test.ts tests/commands/stats_unmeasured.test.ts exits 0; bash tests/test-bash-bun-parity.sh exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
434
434
  | S-227 | BACKLOG 106 class: loki status prints Budget $0 for a run it never measured, on both routes | autonomy/loki (cmd_status budget block only), loki-ts/src/commands/status.ts (readBudgetField and its budget caller only), loki-ts/tests/commands/status.test.ts (budget legs only), tests/test-status-budget-unmeasured.sh (new) | MEDIUM | bash tests/test-status-budget-unmeasured.sh exits 0 (budget_used 0, null or absent prints not recorded on both routes, a positive value prints as today); cd loki-ts && bun test tests/commands/status.test.ts exits 0; bash tests/test-status-cli-provider-parity.sh exits 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
435
435
  | S-228 | BACKLOG 121: DeployConnections pushes default not-connected states upward after its own fetch failed | web-app/src/components/DeployConnections.tsx (connect and disconnect handlers only), web-app/src/components/DeployConnections.propagate.test.mjs (new) | LOW | node --test web-app/src/components/DeployConnections.propagate.test.mjs shows no synthesized statuses reach onStatusChange after a failed fetch; node --test web-app/src/components/DeployConnections.state.test.mjs and cd web-app && npx tsc -b exit 0 | ready@2026-09-27T20:59Z | Source: 20:59Z cut. |
@@ -144,7 +144,7 @@ Status values: todo, in progress, shipped (version), parked (reason).
144
144
  101. **Nested repo gitlink stays on the tip:** an untracked `vendor/lib/` with its own `.git` that the agent's `git add -A` records as a gitlink is not matched (`vendor/lib` vs snapshot entry `vendor/lib/`); nothing is lost (checkout keeps the directory).
145
145
  102. **`.loki/state/agent-committed-user-files.z` has no reader** outside the lifecycle test and is never cleared by a later session with no hits.
146
146
  103. **Bash failure-count gaps:** jest "Test Suites: 1 failed" with "Tests: 2 passed" (a suite that failed to compile), and vitest "Test Files 1 failed", still read as passed (`run.sh` ~12697-12707).
147
- 104. **Pre-existing failing node test:** `dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 5/5 at v9.54.0 and before; not registered in any runner.
147
+ 104. **Pre-existing failing node test:** `legacy-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 5/5 at v9.54.0 and before; not registered in any runner.
148
148
 
149
149
  105. **User-committed files on the session branch are misattributed (council S4c):** a file the user deliberately commits on the session branch between sessions is taken off the tip by the next session's untrack step and reported as "the agent committed". It stays on disk. Needs a session-end marker written at every clean session end to tell user commits from an interrupted agent's.
150
150
  106. **Unmeasured spend in the CLI and the budget breaker:** `loki cost` (autonomy/loki) reports `budget_used = 0.0` when unmeasured (ok/0%); `check_budget_limit` writes `0.0` to `budget.json` for a run it measured nothing for; the bash and Bun breakers treat unmeasured cost as $0 and never warn. Proposed default: warn (never pause) when a cap is set and spend is unmeasured, and show unknown in the CLI.
@@ -156,19 +156,19 @@ Status values: todo, in progress, shipped (version), parked (reason).
156
156
  111. **pytest "1 passed, 1 error" parses as failed_count 0 and passes** (only "N failed" is counted in the bd39d359 summary parser).
157
157
 
158
158
  112. **(Partly fixed in the P7 sweep: web-app `/api/session/status` and its status push, dashboard `/api/context` with no `tracking.json`, and the timeline per-iteration token counts and model now send null; `current_run` and the budget snapshot carry a `partial` flag; pinned in P7.unmeasured-cost-never-zero's server and web-app legs, except the WebSocket status push, which shares `_measured_state_cost` and `_max_iterations_or_none` with the pinned GET but whose own payload no test drives. Open: `/metrics` `loki_cost_usd`, the `/api/cost` tracker fallback, the per-run partial flag, and the R3 design doc.) Remaining server paths that send 0 for unmeasured cost:** `web-app/server.py` `/api/session/status` (~2932, ~2956) and its status push (~6292, ~6315); dashboard `/api/context` with no `tracking.json` (~8804, ~8810); `/metrics` `loki_cost_usd` (~10048, sums with no "measured" check; Prometheus needs its own decision); the `/api/cost` tracker fallback when tokens were seen but no cost (~7914, ~7919); timeline per-iteration token counts; a fleet run with mixed priced and unpriced records has no per-run partial flag. `docs/R3-COST-OBSERVABILITY-DESIGN.md` still describes `project_total_usd` as a plain sum.
159
- 113. **(Fixed in cycle 4, `3a139d81`: `get_proof` adds a computed `integrity_check`; the receipt panel and audit viewer render only computed verdicts; new case P2.console-verdict-needs-computed-result.)** **Critical (moat P1/P2, not P7): two panels state a verification verdict nothing computed.** Found by the P7 sweep; a different property, so not fixed there. `web-app/src/components/EvidenceReceiptPanel.tsx` `classify()` (~43, ~50, ~70-76) labels a receipt "Proven: internally consistent with its own integrity hash" although the browser never recomputes the hash (`dashboard/server.py` `get_proof` returns the raw proof.json with no verification result), labels a receipt with NO hash the same way (`!v.hash`), and can never return "tampered". `dashboard-ui/components/loki-audit-viewer.js` prints "[VALID] ... verified" for `valid !== false`, so `dashboard/audit.py` returning `valid: True, files_checked: 0` reads as verified, and its catch (~169) turns a failed request into "[TAMPERED]". Fix: a server verify endpoint (or the `loki proof verify` result) behind the receipt label; require `valid === true && files_checked > 0`; a failed request is NOT VERIFIED, never TAMPERED.
159
+ 113. **(Fixed in cycle 4, `3a139d81`: `get_proof` adds a computed `integrity_check`; the receipt panel and audit viewer render only computed verdicts; new case P2.console-verdict-needs-computed-result.)** **Critical (moat P1/P2, not P7): two panels state a verification verdict nothing computed.** Found by the P7 sweep; a different property, so not fixed there. `web-app/src/components/EvidenceReceiptPanel.tsx` `classify()` (~43, ~50, ~70-76) labels a receipt "Proven: internally consistent with its own integrity hash" although the browser never recomputes the hash (`dashboard/server.py` `get_proof` returns the raw proof.json with no verification result), labels a receipt with NO hash the same way (`!v.hash`), and can never return "tampered". `legacy-ui/components/loki-audit-viewer.js` prints "[VALID] ... verified" for `valid !== false`, so `dashboard/audit.py` returning `valid: True, files_checked: 0` reads as verified, and its catch (~169) turns a failed request into "[TAMPERED]". Fix: a server verify endpoint (or the `loki proof verify` result) behind the receipt label; require `valid === true && files_checked > 0`; a failed request is NOT VERIFIED, never TAMPERED.
160
160
  114. **False empty on a failed fetch (class, P7-adjacent).** A request that fails renders the same "nothing here" copy as a real empty result. Sites: `web-app/src/components/NLSearch.tsx` (~140-143, "No results found"), `CommandPalette.tsx` (~171-173), `pages/ProjectsPage.tsx` (~65, ~166-168 ignore the poll hook's error), `ProjectWorkspace.tsx` SecretsPanel (~248-256, ~366-372) and DocsPanel (~431-442, ~589-592), the cockpit (`cockpit/useCockpitState.ts` ~119-123 swallows git status and checkpoint failures, so `ChangeReview.tsx` says "The working tree is clean", `FinalActions.tsx` "Nothing to push", `RiskPanel.tsx` "No checkpoints were recorded"), `DeployConnections.tsx` (~353-370), `CICDPanel.tsx` (unknown conclusions shown as "Failed"), `AIChatPanel.tsx` (~543, ~622 "Done." with no output); dashboard `loki-checkpoint-viewer.js` (~95-106), `loki-task-board.js` (~164-169 hides the error when local tasks exist), `loki-log-stream.js` (~152-181), `loki-council-transcripts.js` (~111-114), `loki-managed-memory-panel.js` (~138-141 ignores `data.error`), `loki-migration-dashboard.js` (~94-98), `loki-api-keys.js` (~557-558). Fix per site: keep the error and render "Could not load ..."; a scanner rule for `.catch(() => [])` followed by an empty-state string would pin the class.
161
161
  115. **Status inference presents a guess as a state.** `web-app/server.py` `_infer_session_status` (~3603-3666) returns "completed" for a failed or paused run once its state file is five minutes old, and for any directory with a top-level source file; the cockpit then shows "Run finished" with every step ticked. `cockpit/useCockpitState.ts` (~209-218) also falls back to "completed" for unknown statuses, and (~118) shows `/api/session/checklist`, which reads the globally running project, as a historical session's gates. `ProjectWorkspace.tsx` (~1403-1412) labels REASON/REFLECT and unknown phases "building"; `PhaseVisualizer.tsx` styles earlier RARV steps as done. Fix: an explicit "unknown"/"stale" status and a per-session checklist (or none).
162
162
  116. **Key misreads that hide or zero real data.** `web-app/src/components/GitHubPRsPanel.tsx` reads `statusCheckRollup.contexts` (~204, ~713) although gh returns an array, so failing CI shows "No status checks"; `reviewDecision || "PENDING"` (~222); uppercase gh `state` never equals `'open'` (~751), which also hides the Close button that only posts a comment yet says "PR #N closed" (~592-606); `GitHubIssuesPanel.tsx`/`GitHubPRsPanel.tsx` comment counts read a number where gh sends an array. `EvidenceReceiptPanel.tsx` (~211, ~219) reads `detail.cost_usd`/`detail.files_changed` where proof.json stores `cost.usd` and `files_changed.count`, so a measured cost reads "unknown". `loki-memory-browser.js` episodes read camelCase keys (`actionLog`, `taskId`, `phase`) where the store writes snake_case, so episode details never open and every episode is titled "Task"; `/api/memory/stats` sends `episode_count`, the panel reads `episodes_count`. `loki-overview.js` `_renderCouncilGateCard` (~394) keys on `g.status`, which `/api/council/gate` never sends (it sends `blocked`), so a blocked gate reads "Not evaluated".
163
163
  117. **Stale or false static copy.** `WhatsNew.tsx` `CURRENT_VERSION = '6.73.1'` and `Footer.tsx` `v6.73.0` (current 9.x); `SettingsPage.tsx` says License "MIT" (the LICENSE is BUSL-1.1) and a hardcoded build date; `ComparePage.tsx` lists Gemini as supported (runtime removed v7.5.18) and "9 automated quality gates", `BenefitCards.tsx` "10 quality gates" and Gemini (the canonical count is 8); `ProductTour.tsx`, `DocsSidebar.tsx` promise Railway deploys (only Vercel, Netlify, GitHub Pages exist) and a coverage gate; `ContextualHelp.tsx`, `SettingsPage.tsx` and `CostEstimator.tsx` still list Gemini; `Roadmap.tsx` hardcodes Q2 2026 as "Current"; `ChangelogWidget.tsx` shows March 2026 tags as "Recent Changes"; `TrustedBy.tsx` asserts "Trusted by developers building the future". The P7 scanner cannot see module-level copy tables (the deleted testimonials were one); a narrow rule for invented person/company rows would close that gap.
164
- 118. **Fabrications the P7 sweep found and did not fix (outside its enumerated shapes or needing a design).** Per-run `cost.cost_partial` is dropped by `/api/cost/timeline` `runs[]` and `/api/proofs`, so a partly priced run shows as complete (`dashboard/static/cost.html` ~287, ~301, `proofs.html` ~145, the dashboard receipts list); `workspace_diff.py` returns count 0 when the folder is not a git repo (feeds the receipt hash, so needs care); `trust.html` says "Stable" when no axis has two data points, and `trust_trajectory.py` maps any non-PASS verdict to 0.0; `/cost` prices a record with tokens but no `cost_usd` at Sonnet rates when the model is unknown, with no "estimate" label; `loki metrics --json` (`autonomy/loki` cmd_metrics) sends `tokens.total` 0 and `agent_activity.total_iterations` 0 when nothing was recorded; server-side zero or "not blocked" sentinels the panels now render as unknown only where the client can tell: the council-state fallback `total_votes: 0` (`dashboard/server.py` ~8617), a corrupt `notifications/active.json` answered with a zero summary (~8883), a waivers read error answered 200 (~10321), a corrupt app-runner state answered `{"status":"error"}` (~11240), `prompt_optimizer.py` (~73-84) never-ran sentinel zeros, `migration_engine.py` (~770-793) 0/0 progress; the dashboard `StatusResponse` model (~594-607) defaults iteration/pending to 0 and provider/complexity to "claude"/"standard", and the skill-session WS fallback hardcodes `running_agents: 0` (~1042); `loki-analytics.js` counts days outside the returned log window as 0 activities; `CostEstimator.tsx` prices the whole iteration cap as the estimate once a real cap (e.g. 1000) is known; the web-app "Replay Build" button can never appear (`buildPhase` is "idle" whenever no build runs) and the StatusBar "Built in" line no longer receives a value; the dashboard shell has two elements with `id="budget-banner"` (`build-standalone.js` ~1200, ~1801), reverses a newest-first receipts list under a "Newest first" label (~2510), and colours "VERIFIED WITH GAPS" as success (`/^VERIFIED/`).
164
+ 118. **Fabrications the P7 sweep found and did not fix (outside its enumerated shapes or needing a design).** Per-run `cost.cost_partial` is dropped by `/api/cost/timeline` `runs[]` and `/api/proofs`, so a partly priced run shows as complete (`legacy-ui-static/cost.html` ~287, ~301, `proofs.html` ~145, the dashboard receipts list); `workspace_diff.py` returns count 0 when the folder is not a git repo (feeds the receipt hash, so needs care); `trust.html` says "Stable" when no axis has two data points, and `trust_trajectory.py` maps any non-PASS verdict to 0.0; `/cost` prices a record with tokens but no `cost_usd` at Sonnet rates when the model is unknown, with no "estimate" label; `loki metrics --json` (`autonomy/loki` cmd_metrics) sends `tokens.total` 0 and `agent_activity.total_iterations` 0 when nothing was recorded; server-side zero or "not blocked" sentinels the panels now render as unknown only where the client can tell: the council-state fallback `total_votes: 0` (`dashboard/server.py` ~8617), a corrupt `notifications/active.json` answered with a zero summary (~8883), a waivers read error answered 200 (~10321), a corrupt app-runner state answered `{"status":"error"}` (~11240), `prompt_optimizer.py` (~73-84) never-ran sentinel zeros, `migration_engine.py` (~770-793) 0/0 progress; the dashboard `StatusResponse` model (~594-607) defaults iteration/pending to 0 and provider/complexity to "claude"/"standard", and the skill-session WS fallback hardcodes `running_agents: 0` (~1042); `loki-analytics.js` counts days outside the returned log window as 0 activities; `CostEstimator.tsx` prices the whole iteration cap as the estimate once a real cap (e.g. 1000) is known; the web-app "Replay Build" button can never appear (`buildPhase` is "idle" whenever no build runs) and the StatusBar "Built in" line no longer receives a value; the dashboard shell has two elements with `id="budget-banner"` (`build-standalone.js` ~1200, ~1801), reverses a newest-first receipts list under a "Newest first" label (~2510), and colours "VERIFIED WITH GAPS" as success (`/^VERIFIED/`).
165
165
  119. **(Fixed in cycle 4, `3a139d81`: `validate_token` rejects a key past `rotation_expires_at`; `cleanup_expired_rotating_keys` still has no caller.)** **High (security, found by the P7 sweep): a rotating API key past its grace period still authenticates.** `dashboard/auth.py` `validate_token` (~346-390) checks `revoked` and `expires_at` but never `rotation_expires_at`, and `dashboard/api_keys.py` `cleanup_expired_rotating_keys` (~291) has no callers. The key panel now derives "rotating" from the timestamps, which still understates it. Fix: reject in `validate_token` once `rotation_expires_at` has passed, with a test.
166
- 120. **Two dashboard-ui test files do not test the shipped code.** `dashboard-ui/tests/ui-components.test.js` asserts hand-copied versions of `formatGateTime`, `summarizeGates` and `formatRunDuration` that still encode the old "Never" / "pending" / growing-duration behaviour, and jest is not installed, so nothing runs it. `dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 0/5 at 61af5915 and after this change (the disconnected view hides the journey since 1a871725 and the test never sets `_data.connected`); it is registered in no runner. Import the real functions or delete the copies; fix and register the journey test.
166
+ 120. **Two legacy-ui test files do not test the shipped code.** `legacy-ui/tests/ui-components.test.js` asserts hand-copied versions of `formatGateTime`, `summarizeGates` and `formatRunDuration` that still encode the old "Never" / "pending" / growing-duration behaviour, and jest is not installed, so nothing runs it. `legacy-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 0/5 at 61af5915 and after this change (the disconnected view hides the journey since 1a871725 and the test never sets `_data.connected`); it is registered in no runner. Import the real functions or delete the copies; fix and register the journey test.
167
167
  121. **Browser-only settings still read like live config.** `web-app/src/pages/SettingsPage.tsx` stores provider API keys in plain text in localStorage, and "Budget limit" and "Auto-deploy on success" describe effects nothing implements; each category now carries a "saved in this browser only" note, but removing or wiring them is a product decision. `DeployConnections.tsx` still starts from `{connected:false}` and, if its own fetch fails, pushes those defaults up to `DeployPanel` on the next connect or disconnect.
168
168
 
169
169
  122. **Receipt field `first_result_verified_patch` is `True` for any first code change** (`autonomy/lib/proof-generator.py:1164`, from `first-artifact.json`), so the name claims a verification nothing ran. The overview now labels it "first code change"; rename the field additively (`first_result_kind` already carries the kind) or set it only from a verified result.
170
170
  123. **More verdict-class leftovers from the 113 sweep:** the `audit.py verify` CLI and `compute_chain_tip_in_dir` still report valid, exit 0, when nothing was checked (the cross-chain verifier reads them, so changing them needs its own review); the cockpit, overview, checklist, gate-card, standalone, proofs.html and cost.html verdict relabels have no test of their own (only the receipt and audit surfaces are pinned by the moat case); the standalone receipt list shows the oldest receipts first (see 118).
171
- 124. **Dashboard innerHTML audit:** the standalone receipt and learning panels interpolated run-written text into innerHTML unescaped (fixed in cycle 4, `f6050ef1`, with hostile-input tests). No systematic audit of the other `innerHTML` sites in `dashboard-ui/components` and `build-standalone.js` has been done; add a guard that flags a template literal or string concatenation of a response field into innerHTML without an escape.
171
+ 124. **Dashboard innerHTML audit:** the standalone receipt and learning panels interpolated run-written text into innerHTML unescaped (fixed in cycle 4, `f6050ef1`, with hostile-input tests). No systematic audit of the other `innerHTML` sites in `legacy-ui/components` and `build-standalone.js` has been done; add a guard that flags a template literal or string concatenation of a response field into innerHTML without an escape.
172
172
 
173
173
  125. **P7 scanner (`tests/moat/p7-no-fabricated-data.sh`) bypass shapes found by PF-2 round 5's review but not fixed there (pre-existing before and after `fa5de15f`, not a regression -- each is a candidate for its own small slice):**
174
174
  - **B-1 reassignment fallback:** `let rows = data; if (!rows.length) rows = [rows]; setRows(rows);` -- `DECL_ARR` only matches the `const/let/var x = [` declaration, never a later bare `x = [` assignment.
@@ -212,11 +212,11 @@ Status values: todo, in progress, shipped (version), parked (reason).
212
212
 
213
213
  143. **CONFIRMED STRUCTURAL (4 occurrences, all the SAME shard index): GitHub Actions "Shell tests (shard 2/4)" has now hung 4 times (23min, 22m42s, 23m50s, 20m22s) against a configured `timeout-minutes: 20`, well past GitHub's own enforcement point, while every other shard/job on the same runs finished in under a minute.** All 4 manually cancelled and a fresh push retriggered a clean run each time. This is no longer "watch for a third occurrence" -- 4 hangs on the identical shard index across one session is structural, not noise. Possible causes to investigate: a specific suite in shard 2's partition hanging on a resource wait (network, lock file, background process not exiting), a GitHub-side runner/queue issue unrelated to this repo's code, or `timeout-minutes` not being honored correctly for this job's shape (e.g. a step-level timeout vs job-level, or a step that traps/ignores the timeout signal). Fix direction: add a per-suite or per-step timeout inside the shard runner itself (not just the job-level `timeout-minutes`) so a single hanging suite can't consume the whole shard's budget silently, and instrument which specific suite was running when the hang occurred (a log timestamp before/after each suite in the shard).
214
214
 
215
- 144. **P7's fabricated-return-from-helper scanner arm (S-29 BACKLOG 125 B-7's fix, merged/in-review) only recognizes function declarations, arrow functions, function expressions, and typed variants -- not class methods.** Found by S-31's builder during their own honest ceiling-disclosure while building the fix: a neutrally-named class method (`_getRows() { return [{...fabricated...}]; } ... this._rows = this._getRows();`) is caught by no rule, including the pre-existing rule 5 (`this.x =` direct-literal arm), because the fabrication is one level removed through the method call. Flagged as the DOMINANT uncovered shape in `dashboard-ui`'s `LokiElement`-based components, which use this exact class-method pattern extensively. No known live instance confirmed yet (a full-repo scan diff was empty both before and after S-31's fix), so this is a real, structurally-plausible gap, not yet a proven live bypass. Fix direction: extend the helper-return-tracking arm to also recognize a class method declaration (`methodName(...) { ... return [literal]; ... }`) as a trackable helper head, with the same sink-resolution logic already built for standalone functions.
215
+ 144. **P7's fabricated-return-from-helper scanner arm (S-29 BACKLOG 125 B-7's fix, merged/in-review) only recognizes function declarations, arrow functions, function expressions, and typed variants -- not class methods.** Found by S-31's builder during their own honest ceiling-disclosure while building the fix: a neutrally-named class method (`_getRows() { return [{...fabricated...}]; } ... this._rows = this._getRows();`) is caught by no rule, including the pre-existing rule 5 (`this.x =` direct-literal arm), because the fabrication is one level removed through the method call. Flagged as the DOMINANT uncovered shape in `legacy-ui`'s `LokiElement`-based components, which use this exact class-method pattern extensively. No known live instance confirmed yet (a full-repo scan diff was empty both before and after S-31's fix), so this is a real, structurally-plausible gap, not yet a proven live bypass. Fix direction: extend the helper-return-tracking arm to also recognize a class method declaration (`methodName(...) { ... return [literal]; ... }`) as a trackable helper head, with the same sink-resolution logic already built for standalone functions.
216
216
 
217
217
  145. **P7's `Array.from` generator scanner arm (S-32 BACKLOG 125 B-8's fix, merged) loses an outer scope's loop variable when Array.from generators are nested.** Found by S-32's reviewer 2: `Array.from({length}, (_, r) => Array.from({length}, (_, c) => ({...fabricated...})))` -- the inner generator's parameter substitution only zeroes its own immediate arrow's params, not the outer enclosing generator's index variable it references by closure (e.g. `r`). That leftover free identifier makes `is_literal` reject the whole row as non-literal, so a real fabricated field sitting next to it goes undetected. A different mechanism from BACKLOG 144's class-method gap and from a separately-found destructured-params gap (both already disclosed as this arm's ceiling) -- this one is specifically about nested-scope variable leakage through the substitution step. No known live instance confirmed. Fix direction: when substituting arrow params with 0 for the fabrication check, also substitute any enclosing (outer) generator's own parameters if the inner callback is itself inside another Array.from generator's callback body.
218
218
 
219
- 146. **P7's entire fabricated-data scanner (`FLOWS_TO_STATE_TMPL`/`SETTER` regex, used by every detection arm) only recognizes a literal setter name (`\bset[A-Z]\w*\(`) or `useState(` as a data sink -- a computed/dynamic sink call bypasses every arm, not just one.** Found and re-verified by S-31's rework builder while fixing the useMemo bypass: `window[sinkName](rows)` or `this[dynamicKey](rows)` (rows being fabricated) reproduces identically with S-31 fully reverted, confirming this is scanner-wide and pre-existing, not introduced by any of the P7 sibling slices (S-27 through S-32) built this session. No known live instance confirmed in web-app/dashboard-ui today (computed sink names are an unusual/obfuscated pattern, not mainstream React idiom). Fix direction: broaden the sink-matching regex to also resolve a bracket-indexed or computed member-expression call when the property/key resolves to a name already known to be a setter-like binding (harder than the literal-name case; likely needs its own dedicated slice rather than a quick regex tweak, given the scope of every arm that would need updating).
219
+ 146. **P7's entire fabricated-data scanner (`FLOWS_TO_STATE_TMPL`/`SETTER` regex, used by every detection arm) only recognizes a literal setter name (`\bset[A-Z]\w*\(`) or `useState(` as a data sink -- a computed/dynamic sink call bypasses every arm, not just one.** Found and re-verified by S-31's rework builder while fixing the useMemo bypass: `window[sinkName](rows)` or `this[dynamicKey](rows)` (rows being fabricated) reproduces identically with S-31 fully reverted, confirming this is scanner-wide and pre-existing, not introduced by any of the P7 sibling slices (S-27 through S-32) built this session. No known live instance confirmed in web-app/legacy-ui today (computed sink names are an unusual/obfuscated pattern, not mainstream React idiom). Fix direction: broaden the sink-matching regex to also resolve a bracket-indexed or computed member-expression call when the property/key resolves to a name already known to be a setter-like binding (harder than the literal-name case; likely needs its own dedicated slice rather than a quick regex tweak, given the scope of every arm that would need updating).
220
220
 
221
221
  147. **P7's `DECL_USEMEMO` arm (S-31 BACKLOG 125 B-7's rework, in review) only detects a `useMemo` factory that returns a literal directly (`useMemo(() => [...], deps)`), not one that calls ANOTHER already-registered fabricator (`useMemo(() => helperCall(), deps)`, where `helperCall` is itself a HELPER_HEAD-registered function that returns a fabricated literal).** Found during S-31's own second-round review: the rework's comment initially claimed this composed form was "covered by DECL_USEMEMO," which is inaccurate -- DECL_USEMEMO only inspects the factory body for a direct literal return, never a call expression, so this shape is invisible to both DECL_USEMEMO (no direct literal) and HELPER_HEAD's own call-site machinery (the useMemo-bound name is a value, never itself called as `name(args)`). No known live instance confirmed. Fix direction: `HELPER_LOCAL_DECL_TMPL` already matches `{name}\s*\(` with `fabricators` populated -- adding an optional `(?:React\.)?useMemo\(\s*\(\)\s*=>\s*` prefix ahead of the fabricator-call pattern is a plausible one-line close for the concise-arrow form, offered as a candidate by a reviewer, not a requirement.
222
222
 
package/docs/v10/BOARD.md CHANGED
@@ -36,7 +36,7 @@ merge (all touch trust-core or security-relevant surfaces), oldest first.
36
36
  | GF-2 | P5 slice | main @ c7b2d8b4 | providers/loader.sh, autonomy/loki, bin/loki, docs/air-gapped.md, docs/enterprise/*, README.md, tests/moat/p5-*.sh, tests/test-doctor-json-sentrux.sh | HIGH | released@2026-09-27T15:00Z | Rebased onto current main (past S-11), 4 conflicts resolved (cloud-tag detection + OLLAMA_HOST override are complementary, merged with cloud-tag checked first). HIGH review APPROVE. P5 PROVEN (9/9), pushed. Moat is now 3 of 9 (P5, P6, P7). CORRECTION: the `.loki/state/provider` issue found during verification was NOT a local-only false alarm -- it is a real CI-breaking cross-test contamination bug (test-iteration-grace.sh writes it, poisoning every later test in the same CI shard's shared checkout, including test-airgap-ollama-host.sh); it genuinely broke `Tests` (shard 3/4) on `ba6610dc`. See BACKLOG 126 for the corrected root cause and the fix (shipped, see PROGRESS.md/BACKLOG 126). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
37
37
  | GF-3 | P9 slice | main @ 4c15ef5b | .github/workflows/*.yml, .github/actions/issue-to-pr, autonomy/run.sh (github_token wrap), loki-ts/src/runner/github_token.ts, autonomy/lib/proof-check.sh, action.yml, docs/environment-variables.md, tests/moat/p9-rule-of-two.sh, tests/test-issue-to-pr-action.sh, loki-ts/tests/runner/github_token_withheld.test.ts, loki-ts/dist/loki.js | HIGH | released@2026-09-27T15:00Z | Rebased cleanly (0 conflicts) onto current main; 4/4 P9 moat cases re-verified fresh at every step, never trusted from a stale note. Full 4-reviewer HIGH-tier quorum, effectively unanimous: 2/4 clean APPROVE, 1/4 APPROVE-with-precondition (found and live-reproduced a real TOCTOU gap via a planted git hook, correctly bucket-(b) per D21, filed BACKLOG 138/139), 1/4 CONCERN citing the same dist-staleness gap independently via commit-timestamp comparison. Fixed by rebuilding loki-ts/dist (confirmed new env-var literals present in the built artifact) and re-verifying: P9 genuinely PROVEN, 4 of 9 moat properties overall (a clean superset of main, zero regressions once `npm ci` corrected an environment gap in review worktrees), 6/6 Bun tests, clean tsc. BACKLOG 140/141 filed for two more non-blocking follow-ups. Per D22, ships alone (release.yml touched: 3 no-cache additions, verified minimal through every review round) -- pushed, its own triggered CI run being watched to green before anything else merges. S-18 and S-37 (duplicate) now unblocked to re-cut once this CI run is confirmed green. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
38
38
  | GF-4 | P4 slice | main @ 0f214c3f | providers/model_catalog.json, loki-ts/src/commands/start.ts, loki-ts/src/runner/providers.ts, tests/moat/pending.txt | MEDIUM | released@2026-09-27T15:00Z | Both reviewers landed APPROVE (reviewer 2 conditional on the commit-message fix, already applied at cd07adb2; reviewer 1 independently traced bash/Bun parity end to end and found the same commit-message defect). Re-rebased onto main post-S-41, re-verified moat clean (P4.catalog-has-top-model promoted, P7 PROVEN, 4/9) on the real checkout with deps installed. Merged. Correction: this row was left at `review@` after the actual merge -- caught by the pulse's REVIEW_STALE violation, a repeat of the same status-tracking-lag class as S-30/S-32. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
39
- | GF-5 | verdict/security fix | worktree-agent-a9b8124e8cfc6809a @ 399e1f3a | web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-audit-viewer.js, dashboard/audit.py, dashboard/server.py (get_proof), dashboard/auth.py | HIGH | released@2026-09-27T15:00Z | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
39
+ | GF-5 | verdict/security fix | worktree-agent-a9b8124e8cfc6809a @ 399e1f3a | web-app/src/components/EvidenceReceiptPanel.tsx, legacy-ui/components/loki-audit-viewer.js, dashboard/audit.py, dashboard/server.py (get_proof), dashboard/auth.py | HIGH | released@2026-09-27T15:00Z | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
40
40
 
41
41
  ## Priority out-of-band fix (severity: kills unrelated user sessions)
42
42
 
@@ -63,7 +63,7 @@ set is declared to avoid overlap with those and with each other.
63
63
  |---|---|---|---|---|---|---|
64
64
  | S-45 | BACKLOG 111: pytest "1 passed, 1 error" parses as failed_count 0 and passes | autonomy/run.sh (bd39d359's summary parser only), its test | MEDIUM | red: a pytest run with 1 passed + 1 error exits 0 from the parser's perspective; green: the error count is counted, gate does not pass | released@2026-09-27T15:00Z | Isolated to the pytest summary regex; does not touch any GH-token/withhold code the in-flight security rework owns. Merged 52179cf4 (auto-merged cleanly onto S-44's run.sh diff, different region), 44/44 reconfirmed on main. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
65
65
  | S-46 | BACKLOG 115: status inference presents a guess as a state | web-app/server.py (`_infer_session_status` only), cockpit/useCockpitState.ts (completed fallback + checklist scoping) | MEDIUM | red: a paused/failed run older than 5 min reads "completed"; green: an explicit unknown/stale status is possible and surfaced | released@2026-09-27T15:00Z | File set disjoint from any moat scanner or run.sh trust-core path. Merged 18013159, 11/11 reconfirmed on main. Terminal statuses trusted regardless of file age; a stale active-looking status or a bare source file now falls through to an honest 'unknown' instead of guessed 'completed'. Also fixed the checklist-scoping bug (a historical session no longer shows the globally-running project's live checklist). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
66
- | S-47 | BACKLOG 116: key misreads hide or zero real data (GitHubPRsPanel statusCheckRollup/state case, EvidenceReceiptPanel cost_usd/files_changed keys, memory-browser camelCase mismatch) | web-app/src/components/GitHubPRsPanel.tsx, web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-memory-browser.js, dashboard-ui/components/loki-overview.js | MEDIUM | red: each named field misreads and shows a false empty/zero; green: each reads the real emitted key, one test per site | released@2026-09-27T15:00Z | EvidenceReceiptPanel.tsx already touched by GF-5 (merged) for a different concern (classify()); this slice is the cost_usd/files_changed key-path only, disjoint lines. Merged 11a3e7fb (auto-merged onto loki-overview.js cleanly, different function), 34/34 reconfirmed on main; builder verified every key against the real writer/API source, not the backlog description alone. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
66
+ | S-47 | BACKLOG 116: key misreads hide or zero real data (GitHubPRsPanel statusCheckRollup/state case, EvidenceReceiptPanel cost_usd/files_changed keys, memory-browser camelCase mismatch) | web-app/src/components/GitHubPRsPanel.tsx, web-app/src/components/EvidenceReceiptPanel.tsx, legacy-ui/components/loki-memory-browser.js, legacy-ui/components/loki-overview.js | MEDIUM | red: each named field misreads and shows a false empty/zero; green: each reads the real emitted key, one test per site | released@2026-09-27T15:00Z | EvidenceReceiptPanel.tsx already touched by GF-5 (merged) for a different concern (classify()); this slice is the cost_usd/files_changed key-path only, disjoint lines. Merged 11a3e7fb (auto-merged onto loki-overview.js cleanly, different function), 34/34 reconfirmed on main; builder verified every key against the real writer/API source, not the backlog description alone. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
67
67
  | S-48 | BACKLOG 128: stale docs assert a `{"runner":"none","pass":true}` writer shape that does not exist (D20 already corrected the real shape) | references/core-workflow.md, docs/VERIFIED-COMPLETION-PLAN.md, tests/test-council-devils-advocate.sh, tests/test-da-veto.sh, tests/test-council-convergence-floor.sh | LOW | docs describe the real writer shape (`pass:"inconclusive"` string); the 3 named test fixtures use the real shape instead of a synthetic `pass:true` | released@2026-09-27T10:58Z | STALE DUPLICATE, already fixed: builder found all 5 target locations already correct (commit c06b50ee, "S-33"), verified directly against `enforce_test_coverage` in run.sh and re-ran all 3 test suites clean (6/6, 9/9, 40/40). No new commit needed. Marking released since the underlying fix already shipped in main. One non-blocking follow-up noted: `test-council-convergence-floor.sh` NEGATIVE-B passes even without the `runner!='none'` guard, since `pass:"inconclusive"` alone already fails `pass===True` -- candidate for a future assertion-hardening slice, not filed as a new backlog item yet. |
68
68
  | S-49 | BACKLOG 134: completion-council.sh's 3 test-result readers use bare PATH python3 -E -c with no -I/-S/fixed-path resolution (same bypass class BACKLOG 129 already closed for run.sh) | autonomy/completion-council.sh (council_heuristic_review, council_evaluate_member, council_devils_advocate_review only), new moat case planting a user-site .pth | HIGH | red: a planted .pth flips a genuinely-failing test-results.json to CONFIRMED_COMPLETE; green: routed through a resolved-interpreter helper matching `_loki_snapshot_py_tool`'s pattern, .pth has no effect | released@2026-09-27T16:40Z | Disjoint from S-18/BACKLOG 149's run.sh GH-token work and from S-17's vote-text assertions (already merged, different lines in the same file -- verify no line-range collision before editing). Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 6b276aaf (wf_29a75a9c-652-1): 3 readers via _loki_snapshot_py_tool -I -S, new P2 case red pre-fix and green after, mutation red. 2 HIGH reviewers dispatched 15:16. Reviewer B APPROVE; reviewer A CONCERN (reproduced): queue readers at ~3769/~4050 still use bare python3 -E, so a .pth flips the verdict. Rework sent 15:28. Rework 17eeb940+8ce7f1b1: queue and convergence readers isolated and fail closed, no-interpreter veto, byte-identity test. Re-review (HIGH) dispatched 15:40. Round 2: HIGH reviewer A APPROVE (the .pth attack fails on every reader in the 3 functions; 7 of 8 mutations red; M3b checklist leg is a test gap, fix holds on a direct probe). Reviewer B approved round 1. Train 4. Follow-up: council readers outside the 3 functions (~1425, ~1564, ~4215-4245). Cherry-picked onto main for train 4 (3 commits); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
69
69
  | S-50 | BACKLOG 137: S-02's dynamic-repo-root fix breaks P7's own sed-workaround for the same bug | tests/moat/p7-no-fabricated-data.sh (lines 477-501, the client-route helper invocation only) | MEDIUM | red: P7.webapp-client-routes-exist fails post-S-02 because the sed target no longer exists; green: helpers run in place or receive the root explicitly, case passes again | released@2026-09-27T19:42Z | NARROW SCOPE WARNING: this file is the most contended file this session (S-27/S-29/S-30/S-31/S-32 lineage). Builder must rebase onto main AFTER the S-29 merge-pass lands and touch ONLY the named 477-501 invocation block, nothing else in the file. Coordinate with Captain before starting if S-29's merge is still in flight. Batch 5 build (wf_38d4e17c-211). Review APPROVE found the fix already on main from S-39 bf9776fb (tests/moat/p7-no-fabricated-data.sh:477-497 runs helpers from $REPO_ROOT/tests, no sed); no new commit. Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
@@ -73,7 +73,7 @@ set is declared to avoid overlap with those and with each other.
73
73
  | S-54 | BACKLOG 139: shipped composite GitHub Actions put GH_TOKEN in the SAME step as the agent invocation (issue-to-pr) | .github/actions/issue-to-pr/action.yml, root action.yml | HIGH | the issue content is fetched in an earlier, separate step that does not hold the token; the agent-invoking step receives only a file, never a step with GH_TOKEN in its env | released@2026-09-28T01:11Z | NOTE: S-41 (merged 8a714c73) may have already partially addressed this exact split for .github/actions/issue-to-pr/action.yml -- builder must read S-41's actual merged diff first via `git show 8a714c73` and confirm what remains before starting, to avoid redundant or conflicting work. If S-41 already fully closed this, report back as a stale duplicate rather than editing. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 9c64533b: the fix was already in S-41 (8a714c73), so it adds only a step-level test (17 failures on pre-S-41 files, 0 now, 2 mutations red). HIGH reviewer dispatched 15:16. CONCERN: hand-listed action files; detection misses npx loki-mode@ver, path or variable calls and scripts. Rework sent 15:28. Rework 2b81483d: globbed actions, wider detector; it blanked tokens in 3 production steps (incl. Run Quality Review). HIGH re-review is checking whether that breaks PR commenting. Re-review CONCERN: the narrowed separator lost if/while/timeout/env/pipe/subshell detection (reproduced). The token blanking is fine (the 3 steps never used a token; no CEO decision needed). Rework sent 15:59. Train 6 (release 64676dce, v9.61.0, pushed 16:24:32Z, ls-remote verified), round 3 not re-reviewed (founder instruction). Released v9.80.1 (npm view loki-mode time: 2026-09-28T01:11:53Z). |
74
74
  | S-55 | Found by S-44's reviewer 1: `.github/workflows/test.yml`'s `Tests` workflow has no `paths-ignore`, so every docs-only `docs/v10/**` push (BOARD.md/BACKLOG.md/PROGRESS.md status bookkeeping) retriggers the full sharded suite and cancels any in-flight run via `cancel-in-progress` -- confirmed as the majority cause of this session's own repeated shard-2 "hangs" (self-inflicted, not a product bug) | .github/workflows/test.yml (paths-ignore only) | LOW | red: a docs/v10/BOARD.md-only push currently retriggers Tests and can cancel an in-flight run; green: a docs/v10/**-only push (and ideally other pure-doc paths) does not trigger Tests, verified by pushing a real docs-only commit and confirming no new Tests run starts | parked@2026-09-27T14:21Z | High value, low risk: directly stops the self-cancellation pattern this session hit repeatedly (including twice from the Captain's own BOARD.md bookkeeping pushes this turn). Do not broaden paths-ignore beyond doc-only globs -- must not accidentally skip Tests on a real code change that happens to touch a doc in the same commit (paths-ignore is all-or-nothing per push: verify no historical commit mixed docs/v10/** with code changes in the same push before landing, or scope the exclusion pattern more conservatively if any did). Built 0ec9c251, never merged. Parked: superseded by S-80 (main runs no longer cancel) and it conflicts with verdict reuse (S-84): a docs-only commit with no Tests run leaves a later release nothing to reuse. |
75
75
  | S-56 | BACKLOG 119 follow-through / BACKLOG 33: `cleanup_expired_rotating_keys` has no caller (the fix in cycle 4 correctly rejects an expired rotating key at validate_token time, but the cleanup function that would purge them from storage is dead code) | dashboard/api_keys.py (add a caller only, e.g. a periodic sweep or an on-validate-failure purge; do not touch dashboard/auth.py's already-fixed validate_token), its test | LOW | red: an expired rotating key stays in storage indefinitely (confirmed via a test that seeds one, advances time past rotation_expires_at, and checks it is still listed); green: cleanup_expired_rotating_keys is actually invoked on some real trigger and the key is purged | released@2026-09-27T15:53Z | Read the BACKLOG 119 fix (dashboard/auth.py validate_token) first to avoid duplicating or conflicting with it -- this slice only wires up the already-written cleanup function, does not touch the security-relevant rejection logic. Also found and fixed a latent crash (bare datetime.fromisoformat instead of the fail-closed _deadline_passed helper validate_token already uses -- would have 500'd on any bad timestamp once wired live). Merged e3c27c6d, 32/32 reconfirmed on main. Correction: this row was stale at building@. Merged as e3c27c6d (ancestor of main, verified with git merge-base --is-ancestor), shipped in v9.56.0. Correction: e3c27c6d is an ancestor of v9.56.0 (git log v9.56.0 shows it at 07:45), so it shipped in v9.56.0, not train 2. |
76
- | S-57 | BACKLOG 120: two dashboard-ui test files do not test the shipped code (`ui-components.test.js` asserts hand-copied stale logic and is never run by any test runner; `loki-overview-issue-journey.node.test.mjs` fails 0/5 and is registered nowhere) | dashboard-ui/tests/ui-components.test.js, dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs, tests/run-all-tests.sh (registration only, coordinate: S-44 also touched this file -- rebase onto post-S-44-merge main first) | MEDIUM | ui-components.test.js imports and asserts against the REAL shipped functions (formatGateTime, summarizeGates, formatRunDuration), not hand-copied logic; the journey test is fixed (sets `_data.connected` per the known cause) and passes 5/5; both are registered in a real runner and actually execute in CI | released@2026-09-27T15:00Z | Merged 21a539df, 23/23 + 6/6 reconfirmed on main. Found the real drift: shipped formatGateTime/summarizeGates/formatRunDuration had all changed behavior since the hand-copied test was written; rewrote to dynamically import the real functions after a DOM stub (needed since the components extend LokiElement at class-definition time). Journey test's 6 (not 5) failing cases all traced to one root cause (_data.connected never set), fixed once in the shared mounted() helper. Both registered in run-all-tests.sh, additive alongside S-44's timeout wrapping. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
76
+ | S-57 | BACKLOG 120: two legacy-ui test files do not test the shipped code (`ui-components.test.js` asserts hand-copied stale logic and is never run by any test runner; `loki-overview-issue-journey.node.test.mjs` fails 0/5 and is registered nowhere) | legacy-ui/tests/ui-components.test.js, legacy-ui/tests/loki-overview-issue-journey.node.test.mjs, tests/run-all-tests.sh (registration only, coordinate: S-44 also touched this file -- rebase onto post-S-44-merge main first) | MEDIUM | ui-components.test.js imports and asserts against the REAL shipped functions (formatGateTime, summarizeGates, formatRunDuration), not hand-copied logic; the journey test is fixed (sets `_data.connected` per the known cause) and passes 5/5; both are registered in a real runner and actually execute in CI | released@2026-09-27T15:00Z | Merged 21a539df, 23/23 + 6/6 reconfirmed on main. Found the real drift: shipped formatGateTime/summarizeGates/formatRunDuration had all changed behavior since the hand-copied test was written; rewrote to dynamically import the real functions after a DOM stub (needed since the components extend LokiElement at class-definition time). Journey test's 6 (not 5) failing cases all traced to one root cause (_data.connected never set), fixed once in the shared mounted() helper. Both registered in run-all-tests.sh, additive alongside S-44's timeout wrapping. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
77
77
  | S-58 | BACKLOG 114 (scoped subset): false-empty-on-failed-fetch in the cockpit -- `cockpit/useCockpitState.ts` swallows git-status and checkpoint failures, so ChangeReview.tsx says "The working tree is clean" and RiskPanel.tsx says "No checkpoints were recorded" on a FAILED fetch, not a real empty result | cockpit/useCockpitState.ts (the git status / checkpoint fetch error handling only), web-app/src/components/ChangeReview.tsx, web-app/src/components/RiskPanel.tsx | MEDIUM | red: a failed git-status/checkpoint fetch (simulate a 500 or network error) renders the same copy as a genuine empty result; green: a failed fetch renders "Could not load..." distinctly from a genuine empty state, one test per component | released@2026-09-27T15:00Z | Merged 14d80a54, 22/22 (11 pre-existing S-46 + 11 new) reconfirmed on main, no conflict with S-46's earlier changes to the same file. Verified against the real server responses first (a genuine empty case returns HTTP 200, never a rejection) before implementing, confirming the fix's premise; a `settle()` helper now distinguishes resolved-empty from rejected. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
78
78
  | S-59 | BACKLOG 71: `evidence-gate-details` `tests.ok` stays true for an inconclusive test axis -- `surface_evidence_gate_details` prints `tests_ok=True` next to `tests_inconclusive` | autonomy/lib/proof-generator.py or wherever surface_evidence_gate_details lives (grep first), its test | LOW | red: an inconclusive test axis (zero-test or no-runner) still shows tests_ok=True in evidence-gate-details.json; green: tests_ok is false or absent when the axis is inconclusive, with a test | released@2026-09-27T15:00Z | Real bug, correctly located: `surface_evidence_gate_details` lives in autonomy/run.sh:13966 (not proof-generator.py, which is a different already-correct consumer). Reused the existing 'inconclusive dominates ok' convention already established in proof-generator.py's _classify_func_axis rather than inventing a new pattern. Merged 72afa3e9, 15/15 reconfirmed on main. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
79
79
  | S-60 | BACKLOG 92: receipt path bases mix under a subdirectory TARGET_DIR -- tracked entries are repo-top-relative, untracked and preexisting_modified entries are cwd-relative, so a receipt read from a subdirectory build shows inconsistent path bases | autonomy/lib/proof-generator.py (path normalization only), its test | MEDIUM | red: a receipt generated with TARGET_DIR set to a subdirectory has tracked-entry paths repo-relative and untracked-entry paths cwd-relative in the same receipt; green: both use a single consistent base (repo-relative preferred, matching the tracked-entry convention), with a test | released@2026-09-27T15:00Z | Merged 6148446f, 76/76 reconfirmed on main. Root cause: git itself reports --numstat repo-relative but ls-files --others TARGET_DIR-relative; fixed by reusing the already-computed prefix/key at one shared point. Builder honestly flagged that a pre-fix receipt from a subdirectory build will now fail hash_ok on re-verify (expected: the old receipts were internally inconsistent). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
@@ -107,7 +107,7 @@ set is declared to avoid overlap with those and with each other.
107
107
  | S-88 | CEO Part C item 10b: parallelize moat P6, P9 and P5 internally | tests/moat/p6-*.sh, p9-rule-of-two.sh, p5-*.sh | MEDIUM | moat suite wall time drops; same cases, same verdicts | released@2026-09-27T18:12Z | SEQUENCING: p9-rule-of-two.sh is in S-18's file set; start only after S-18 merges. Batch 1 (build then review), dispatched 17:06. Train 5, pushed 51ae52fe at 17:52:16Z (ls-remote verified); approved by review. S-88: P9 4/4 in 43s (was about 90s). S-130: web-app dist rebuilt. S-111: pytest -n auto back on after S-102. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
108
108
  | S-89 | CEO Part C item 11: pip and bun install caches on read-only test jobs | test.yml cache steps only | LOW | cache hits on a second run; never on a job holding a write token or publish secret (P9) | released@2026-09-27T16:40Z | Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built e85a23d4. Reviewer dispatched 15:16. CONCERN: the fixed -A5 permissions window misses a late contents: write. Rework sent 15:28 (parse the YAML). Rework ab32c540: YAML-parsed permissions, 15/15. Re-review dispatched 15:40. 1/1 APPROVE. Train 4. Cherry-picked onto main for train 4 (2 commits); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
109
109
  | S-90 | CEO Part C item 12: move bun=latest, macOS bun and hyperfine to nightly (test.yml:303-312, 390-400) | test.yml those jobs, a nightly workflow | LOW | those jobs no longer run on push; they run on a nightly schedule | released@2026-09-27T16:40Z | Built 93482497 (bun matrix 4->1 on push; nightly.yml runs the other 3 plus hyperfine). Reviewer dispatched 14:24. 1/1 APPROVE. Non-blocking: release gate now requires only the pinned bun combo (intended); hyperfine no longer runs for the pinned combo anywhere; macOS-only branches in a few test files now run nightly only. Train 2: 329882d7. In train 2 release commit 5332bfc3 (v9.57.0), pushed 15:50:12Z (ls-remote verified); becomes released when publish-npm succeeds (D27). Correction 15:54: I had marked this released too early. Released in v9.57.0 (Release run 36331009098 publish-npm success). |
110
- | S-91 | CEO Part C item 13: Tier A diff-selected tests with selection rules R0-R7; anything touching tests/lib, run-all-tests.sh, package.json, requirements*, loki-ts/dist, VERSION or .github/workflows runs everything | a selection script, a Tier A workflow or job | MEDIUM | Tier A finishes in 2 min or less on a typical change; the run-everything triggers are honored; Tier A never replaces Tier B | released@2026-09-27T16:40Z | OVER BUDGET 14:56 (33.5 min vs 30): told to stop and commit; the rest gets re-sliced. Committed cb8ddb07 at 39 min (over budget): R0-R7 done, 29/29, P9 4/4 on tier-a.yml, real-commit runs 25s/86s/5s. Remainder re-sliced as S-96. Tech Lead review dispatched 15:08. REJECT: the .py-suffixed grep misses Python imports (workspace_diff.py, fast_verify.py moat miss); R5 targets tests/dashboard only; no dashboard-ui rule. Round 2 sent 15:23. Round 2 52a58e86: import needles, dashboard-ui rule, node match kind; 38/38. Re-review dispatched 15:46. Round 2: 1/1 APPROVE (all 4 misses reproduced as fixed, 38/38, shellcheck clean). Advisory: generic stems (base.py) over-select (bloat, not a miss). Train 4. Cherry-picked onto main for train 4 (3ee19595+10090cd3); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
110
+ | S-91 | CEO Part C item 13: Tier A diff-selected tests with selection rules R0-R7; anything touching tests/lib, run-all-tests.sh, package.json, requirements*, loki-ts/dist, VERSION or .github/workflows runs everything | a selection script, a Tier A workflow or job | MEDIUM | Tier A finishes in 2 min or less on a typical change; the run-everything triggers are honored; Tier A never replaces Tier B | released@2026-09-27T16:40Z | OVER BUDGET 14:56 (33.5 min vs 30): told to stop and commit; the rest gets re-sliced. Committed cb8ddb07 at 39 min (over budget): R0-R7 done, 29/29, P9 4/4 on tier-a.yml, real-commit runs 25s/86s/5s. Remainder re-sliced as S-96. Tech Lead review dispatched 15:08. REJECT: the .py-suffixed grep misses Python imports (workspace_diff.py, fast_verify.py moat miss); R5 targets tests/dashboard only; no legacy-ui rule. Round 2 sent 15:23. Round 2 52a58e86: import needles, legacy-ui rule, node match kind; 38/38. Re-review dispatched 15:46. Round 2: 1/1 APPROVE (all 4 misses reproduced as fixed, 38/38, shellcheck clean). Advisory: generic stems (base.py) over-select (bloat, not a miss). Train 4. Cherry-picked onto main for train 4 (3ee19595+10090cd3); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
111
111
  | S-92 | CEO Part C item 14: tests/quarantine.txt (suite, owner, expiry max 7 days, issue); quarantined suites still run but do not block; moat and review suites can never be quarantined; no retry loops | tests/quarantine.txt, tests/run-all-tests.sh (quarantine handling) | LOW | a listed suite's failure is reported but non-blocking; an expired or moat entry is rejected | released@2026-09-28T01:11Z | SEQUENCING: after S-79 and S-81 merge (same runner file). Dispatched 15:49 on top of S-79+S-81. Train 7 (release 9218ea04, v9.62.0, pushed 16:29:17Z, ls-remote and tag ^{} verified), unreviewed (founder "release everything"). The v9.62.0 Release run was cancelled at 16:30 (the tree carries the S-18 P9 regression). Released v9.80.1 (npm view loki-mode time: 2026-09-28T01:11:53Z). |
112
112
  | S-93 | CEO Part C item 15: the 38 unregistered test files: register each or delete it with a reason | tests/run-all-tests.sh registrations, the files | LOW | zero unregistered test files; each deletion has a stated reason | released@2026-09-28T01:11Z | SEQUENCING: after S-79 and S-81 merge (same runner file). Dispatched 15:49 on top of S-79+S-81. Train 7 (release 9218ea04, v9.62.0, pushed 16:29:17Z, ls-remote and tag ^{} verified), unreviewed (founder "release everything"). The v9.62.0 Release run was cancelled at 16:30 (the tree carries the S-18 P9 regression). Released v9.80.1 (npm view loki-mode time: 2026-09-28T01:11:53Z). |
113
113
  | S-94 | Worktree follow-up: triage the 27 worktrees whose branches hold commits not on main (merge, record in BOARD, or discard with a reason), check the 3 with an uncommitted edit to tests/moat/p7-no-fabricated-data.sh, and add a pulse violation for more than 15 worktrees | scripts/v10-pulse.sh, tests/test-v10-pulse.sh (violation only); triage is a Captain decision per branch | LOW | worktree count at or below 10 with no unmerged work lost; the new violation fires above 15 with a fixture | released@2026-09-27T17:53Z | SEQUENCING: the pulse change waits for S-75 (same file). Triage list: scratchpad/s72-classification.tsv. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built ad60e018 (WORKTREE_COUNT violation). Reviewer dispatched 15:16; worktree triage still pending (orchestrator). CONCERN: git merge-tree with S-76 (30ed0f19) conflicts in both files (adjacent inserts). Rebase onto S-76 after its rework lands. Back to ready: ad60e018 must be rebuilt on main after S-109 lands (both edit v10-pulse.sh); fold WORKTREE_COUNT in then. Batch 1 (build then review), dispatched 17:06. In v9.65.0 (release commit 0103adfa, pushed 17:45:33Z; required-ci success). |
@@ -217,7 +217,7 @@ set is declared to avoid overlap with those and with each other.
217
217
  | S-155 | Velocity: reachability scan (95s on CI, 47s local) under 10s via a per-module stem prefilter, identical verdicts | tests/lib/scan-unreachable-shipped.py | LOW | scan wall time under 10s; stdout and rc byte-identical to the pre-change capture; bash tests/test-no-unreachable-shipped.sh 4 passed 0 failed; removing one real require is still reported | released@2026-09-27T20:13Z | Builder measures regex vs I/O first and records both numbers. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3f786ce0; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
218
218
  | S-156 | BACKLOG 127 remainder: auto-capture shadow_write runs with PROJECT_DIR unset, and float() splices episode importance into python source | autonomy/run.sh (shadow_write auto-capture block about 21380-21396 only), tests/test-autocapture-shadow-write-guard.sh (new) | HIGH | bash tests/test-autocapture-shadow-write-guard.sh exits 0 under /bin/bash and bash 5; no marker from a planted cwd memory package; no file from an injected importance; trust-core suite passes | released@2026-09-27T20:13Z | Builder names who writes episode_path_file. Only run.sh row in this cut. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 71d7a246; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
219
219
  | S-157 | BACKLOG 98/89: council member vote and _council_convergence_evidence_green read pass:true as green whatever failed_count says | autonomy/completion-council.sh (those 2 parsers only), tests/test-council-failed-count-honesty.sh (new) | HIGH | pass:true with failed_count 2 is not green at both sites; failed_count 0 stays green; trust-core and convergence-floor suites pass; reverting either site fails its case | released@2026-09-27T20:24Z | Mirrors the evidence gate rule (~2014). Only completion-council.sh row in this cut. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. 7a709fde (HIGH review APPROVE); in train 12, main ec01d54b pushed 20:05:58 (`git ls-remote origin refs/heads/main` = ec01d54b). Published in v9.73.0 (`npm view loki-mode version` = 9.73.0; npm time 2026-09-27T20:24Z). |
220
- | S-158 | BACKLOG 118: per-run cost_partial dropped by /api/cost/timeline runs[] and /api/proofs; pages show a lower bound as a total | dashboard/server.py (runs.append in _compute_cost_timeline and the /api/proofs row only), dashboard/static/cost.html, dashboard/static/proofs.html, tests/dashboard/test_cost_partial_surfaced.py (new) | MEDIUM | pytest test_cost_partial_surfaced.py passes; fixture cost_partial true surfaces in both endpoints and renders as at least $X; dropping the key fails | released@2026-09-27T20:13Z | Builder names the consumers checked. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 931a93b6; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
220
+ | S-158 | BACKLOG 118: per-run cost_partial dropped by /api/cost/timeline runs[] and /api/proofs; pages show a lower bound as a total | dashboard/server.py (runs.append in _compute_cost_timeline and the /api/proofs row only), legacy-ui-static/cost.html, legacy-ui-static/proofs.html, tests/dashboard/test_cost_partial_surfaced.py (new) | MEDIUM | pytest test_cost_partial_surfaced.py passes; fixture cost_partial true surfaces in both endpoints and renders as at least $X; dropping the key fails | released@2026-09-27T20:13Z | Builder names the consumers checked. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 931a93b6; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
221
221
  | S-159 | BACKLOG 114: NLSearch renders No results found when the search request failed | web-app/src/components/NLSearch.tsx, web-app/src/components/NLSearch.state.test.mjs (new) | LOW | node --test NLSearch.state.test.mjs passes incl. the negative assertion; npx tsc -b exits 0 | released@2026-09-27T20:13Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on ea5b4462; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
222
222
  | S-160 | BACKLOG 114: CommandPalette file-search failure reads as No results found | web-app/src/components/CommandPalette.tsx, web-app/src/components/CommandPalette.state.test.mjs (new) | LOW | node --test CommandPalette.state.test.mjs passes; npx tsc -b exits 0 | released@2026-09-27T20:13Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3f9873f3; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
223
223
  | S-161 | BACKLOG 114: ProjectsPage ignores usePolling error and says No projects yet on a failed fetch | web-app/src/pages/ProjectsPage.tsx, web-app/src/pages/ProjectsPage.state.test.mjs (new) | LOW | node --test ProjectsPage.state.test.mjs passes (error, stale-data and real-empty cases); npx tsc -b exits 0 | released@2026-09-27T20:13Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on d2dd3645; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
@@ -225,11 +225,11 @@ set is declared to avoid overlap with those and with each other.
225
225
  | S-163 | BACKLOG 114: CICDPanel maps neutral/action_required/stale/null conclusions to Failed and unknown statuses to running | web-app/src/components/CICDPanel.tsx (3 normalizers and status map only), web-app/src/components/CICDPanel.status.test.mjs (new) | LOW | node --test CICDPanel.status.test.mjs passes for every conclusion; npx tsc -b exits 0 | released@2026-09-27T20:13Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 36052758; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
226
226
  | S-164 | BACKLOG 114: AIChatPanel prints Done. for a non-zero exit with no output | web-app/src/components/AIChatPanel.tsx (the two Done. fallbacks only), web-app/src/components/AIChatPanel.result.test.mjs (new) | LOW | node --test AIChatPanel.result.test.mjs passes; npx tsc -b exits 0 | released@2026-09-27T20:13Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 8aceef56; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
227
227
  | S-165 | BACKLOG 117 remainder: TrustedBy asserts Trusted by developers; ChangelogWidget shows March 2026 v6.x as Recent Changes | web-app/src/components/TrustedBy.tsx, web-app/src/components/ChangelogWidget.tsx | LOW | grep for Trusted by developers and 6.71.1 in those files returns rc 1; npx tsc -b exits 0 | released@2026-09-27T20:13Z | Copy only. Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 97ba623f; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
228
- | S-166 | BACKLOG 114: checkpoint viewer ignores a rejected allSettled fetch and clears the error | dashboard-ui/components/loki-checkpoint-viewer.js (load block only), dashboard-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes incl. the negative assertion | released@2026-09-27T20:13Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 4035d21d; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
229
- | S-167 | BACKLOG 114: council transcripts render a failed hook-events read as zero events | dashboard-ui/components/loki-council-transcripts.js (hook events load only), dashboard-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes | released@2026-09-27T20:13Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3fea74e8; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
230
- | S-168 | BACKLOG 114: task board hides a server load error whenever local tasks exist | dashboard-ui/components/loki-task-board.js (catch and error render only), dashboard-ui/tests/loki-task-board-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-task-board-modal-guard test still passes | released@2026-09-27T20:13Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on aa2a64a4; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
231
- | S-169 | BACKLOG 114: log stream swallows API failures with an empty catch | dashboard-ui/components/loki-log-stream.js (API poll catch and empty render only), dashboard-ui/tests/loki-log-stream-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-poll-registry test still passes | released@2026-09-27T20:24Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. a990a9ce review REJECT; rework dispatched 19:57Z. 707283f3 (re-review APPROVE, runner lists 598 = main + 1); in train 12, main ec01d54b pushed 20:05:58 (`git ls-remote origin refs/heads/main` = ec01d54b). Published in v9.73.0 (`npm view loki-mode version` = 9.73.0; npm time 2026-09-27T20:24Z). |
232
- | S-170 | BACKLOG 114: API keys panel renders No API keys configured under its own load-error banner | dashboard-ui/components/loki-api-keys.js (table branch only), dashboard-ui/tests/loki-api-keys-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; error render lacks the empty-state sentence | released@2026-09-27T20:13Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on ab837a75; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
228
+ | S-166 | BACKLOG 114: checkpoint viewer ignores a rejected allSettled fetch and clears the error | legacy-ui/components/loki-checkpoint-viewer.js (load block only), legacy-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes incl. the negative assertion | released@2026-09-27T20:13Z | Captain rebuilds legacy-ui-static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 4035d21d; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
229
+ | S-167 | BACKLOG 114: council transcripts render a failed hook-events read as zero events | legacy-ui/components/loki-council-transcripts.js (hook events load only), legacy-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes | released@2026-09-27T20:13Z | Captain rebuilds legacy-ui-static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3fea74e8; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
230
+ | S-168 | BACKLOG 114: task board hides a server load error whenever local tasks exist | legacy-ui/components/loki-task-board.js (catch and error render only), legacy-ui/tests/loki-task-board-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-task-board-modal-guard test still passes | released@2026-09-27T20:13Z | Captain rebuilds legacy-ui-static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on aa2a64a4; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
231
+ | S-169 | BACKLOG 114: log stream swallows API failures with an empty catch | legacy-ui/components/loki-log-stream.js (API poll catch and empty render only), legacy-ui/tests/loki-log-stream-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-poll-registry test still passes | released@2026-09-27T20:24Z | Captain rebuilds legacy-ui-static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. a990a9ce review REJECT; rework dispatched 19:57Z. 707283f3 (re-review APPROVE, runner lists 598 = main + 1); in train 12, main ec01d54b pushed 20:05:58 (`git ls-remote origin refs/heads/main` = ec01d54b). Published in v9.73.0 (`npm view loki-mode version` = 9.73.0; npm time 2026-09-27T20:24Z). |
232
+ | S-170 | BACKLOG 114: API keys panel renders No API keys configured under its own load-error banner | legacy-ui/components/loki-api-keys.js (table branch only), legacy-ui/tests/loki-api-keys-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; error render lacks the empty-state sentence | released@2026-09-27T20:13Z | Captain rebuilds legacy-ui-static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on ab837a75; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
233
233
  | S-171 | BACKLOG 124: lint for response fields interpolated into innerHTML without the escape helper | tests/test-no-unescaped-innerhtml.sh (new), tests/lib/scan-unescaped-innerhtml.py (new) | MEDIUM | passes on main with a reasoned in-file allowlist; planted fixture exits 1; empty-reason entry fails; at least 20 files scanned | released@2026-09-27T20:24Z | Any real XSS found is reported only; repairs go to separate slices. Captain registers. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. db501eba (review APPROVE); in train 12, main ec01d54b pushed 20:05:58 (`git ls-remote origin refs/heads/main` = ec01d54b). Published in v9.73.0 (`npm view loki-mode version` = 9.73.0; npm time 2026-09-27T20:24Z). |
234
234
  | S-172 | BACKLOG 132: shadow-write mutant check is green on bash 5.3 and red on /bin/bash 3.2 | tests/test-council-shadow-write-project-dir.sh | LOW | bash tests/test-council-shadow-write-project-dir.sh exits 0; mutant leg red under both /bin/bash and PATH bash, both versions printed | released@2026-09-27T20:13Z | Test-only. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on e2114d09; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
235
235
  | S-173 | BACKLOG 135: P2.council-readers-not-shadowed does not drive council_managed_should_stop (cwd-shadow class only) | tests/moat/p2-honest-verdict.sh (that case only) | HIGH | p2-honest-verdict.sh prints CASE P2.council-readers-not-shadowed PASS; removing the sys.path filter in a scratch copy prints FAIL | released@2026-09-27T20:13Z | No .pth leg: that reader is still python3 -E, so a .pth leg would redden a proven case; follows alternate A2. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 6bc4b5cf; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). Published in v9.72.0 (`npm view loki-mode version` = 9.72.0; npm time 20:13Z). |
@@ -242,13 +242,13 @@ set is declared to avoid overlap with those and with each other.
242
242
  | S-180 | BACKLOG 144: P7 helper-return arm misses class-method helpers | tests/moat/p7-no-fabricated-data.sh (helper-return arm only) | HIGH | bash tests/moat/p7-no-fabricated-data.sh prints PASS for every P7 case and flags the in-script class-method fixture; removing the method-head pattern lets the fixture through; tests/moat/cases.txt unchanged | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on e8d30a0b; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
243
243
  | S-181 | GUARDS 11: v10-guard blocks a glob rm whose parent is a shared root (/tmp, TMPDIR, scratchpad) | scripts/v10-guard.sh (Rule 4 region only), tests/test-v10-guard.sh, docs/v10/GUARDS.md (section 11 only) | MEDIUM | bash tests/test-v10-guard.sh exits 0 with rm -f /tmp/*.log and rm -f scratchpad/* blocked and rm -f /tmp/run-1/*.log allowed; dropping the new rule fails the blocked cases | released@2026-09-27T21:15Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. 692ec781 review CONCERN (relative glob in scratchpad root); rework 310d2fed, re-review in batch 8 (wf_ff8d537c-40e). Review APPROVE on 310d2fed (re-review APPROVE); in train 14, main 04af133a pushed 20:58:10 (`git ls-remote origin refs/heads/main` = 04af133a). Published in v9.75.0 (`npm view loki-mode version` = 9.75.0; npm time 2026-09-27T21:15Z). |
244
244
  | S-182 | docs/exit-codes.md omits the pending loki verify codes (verify --fast exits 0 on INCONCLUSIVE until v10.0.0) | docs/exit-codes.md (loki verify section only) | LOW | bash tests/test-exit-codes-documented.sh exits 0; grep -n P2.fast-verify-inconclusive-not-zero docs/exit-codes.md prints one line; the four measured codes appear in the report with their commands | released@2026-09-27T21:15Z | Source: 19:57Z cut. Batch 8 (wf_ff8d537c-40e), build then review. Review APPROVE on 4b4af831; in train 14, main 04af133a pushed 20:58:10 (`git ls-remote origin refs/heads/main` = 04af133a). Published in v9.75.0 (`npm view loki-mode version` = 9.75.0; npm time 2026-09-27T21:15Z). |
245
- | S-183 | BACKLOG 114: migration dashboard renders a failed load as No migration data available | dashboard-ui/components/loki-migration-dashboard.js (error render branch only), dashboard-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs (new) | LOW | node --test dashboard-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs passes: a rejected fetch renders Could not load and lacks the empty-state sentence; an empty list still renders No migrations found | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 1f0dd435; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
246
- | S-184 | BACKLOG 114: managed memory panel ignores a 200 events payload carrying error | dashboard-ui/components/loki-managed-memory-panel.js (events load only), dashboard-ui/tests/loki-managed-memory-events-error.node.test.mjs (new) | LOW | node --test dashboard-ui/tests/loki-managed-memory-events-error.node.test.mjs passes: the error payload renders the error line and not the empty sentence; events [] with no error still renders the empty sentence | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 13a33840; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
245
+ | S-183 | BACKLOG 114: migration dashboard renders a failed load as No migration data available | legacy-ui/components/loki-migration-dashboard.js (error render branch only), legacy-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs (new) | LOW | node --test legacy-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs passes: a rejected fetch renders Could not load and lacks the empty-state sentence; an empty list still renders No migrations found | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 1f0dd435; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
246
+ | S-184 | BACKLOG 114: managed memory panel ignores a 200 events payload carrying error | legacy-ui/components/loki-managed-memory-panel.js (events load only), legacy-ui/tests/loki-managed-memory-events-error.node.test.mjs (new) | LOW | node --test legacy-ui/tests/loki-managed-memory-events-error.node.test.mjs passes: the error payload renders the error line and not the empty sentence; events [] with no error still renders the empty sentence | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 13a33840; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
247
247
  | S-185 | BACKLOG 114: DeployConnections rows read Not connected under their own load error | web-app/src/components/DeployConnections.tsx (row status render only), web-app/src/components/DeployConnections.state.test.mjs (new) | LOW | node --test web-app/src/components/DeployConnections.state.test.mjs passes: no row reads Not connected after a failed fetch; a real connected false still does; cd web-app && npx tsc -b exits 0 | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on d88c64ac; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
248
248
  | S-186 | BACKLOG 116: issue list comment count never shows (gh sends comments as an array) | web-app/src/components/GitHubIssuesPanel.tsx (list comment badge only), web-app/src/types/api.ts (GitHubIssue.comments only), web-app/src/components/GitHubIssuesPanel.comments.test.mjs (new) | LOW | node --test web-app/src/components/GitHubIssuesPanel.comments.test.mjs passes: array of 2 renders 2, number 3 renders 3; cd web-app && npx tsc -b exits 0 | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 3817c6f3; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
249
249
  | S-187 | BACKLOG 118: CostEstimator prices the whole iteration cap as the estimate | web-app/src/components/ProjectWorkspace.tsx (CostEstimator props only), web-app/src/components/CostEstimator.tsx (export only if needed), web-app/src/components/CostEstimator.estimate.test.mjs (new) | LOW | node --test web-app/src/components/CostEstimator.estimate.test.mjs passes; grep -n 'estimatedIterations={buildStatus.maxIterations' web-app/src/components/ProjectWorkspace.tsx exits 1; cd web-app && npx tsc -b exits 0 | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on d03a237e; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
250
- | S-188 | BACKLOG 123: overview proof card wording has no test of its own | dashboard-ui/tests/loki-overview-proof-card.node.test.mjs (new) | LOW | node --test dashboard-ui/tests/loki-overview-proof-card.node.test.mjs passes: no proof reads Not evaluated, a headline carries the recorded-copy prefix, gaps null reads uncertainty not measured; deleting the prefix in a scratch copy fails it | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 6d965cca; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
251
- | S-189 | BACKLOG 114: learning dashboard renders failed metrics and trends reads as no data | dashboard-ui/components/loki-learning-dashboard.js (metrics and trends load plus their two empty branches only), dashboard-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs (new) | LOW | node --test dashboard-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs passes: rejected metrics and trends render Could not load; an empty trends response still renders No trend data available | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on a746655f; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
250
+ | S-188 | BACKLOG 123: overview proof card wording has no test of its own | legacy-ui/tests/loki-overview-proof-card.node.test.mjs (new) | LOW | node --test legacy-ui/tests/loki-overview-proof-card.node.test.mjs passes: no proof reads Not evaluated, a headline carries the recorded-copy prefix, gaps null reads uncertainty not measured; deleting the prefix in a scratch copy fails it | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on 6d965cca; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
251
+ | S-189 | BACKLOG 114: learning dashboard renders failed metrics and trends reads as no data | legacy-ui/components/loki-learning-dashboard.js (metrics and trends load plus their two empty branches only), legacy-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs (new) | LOW | node --test legacy-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs passes: rejected metrics and trends render Could not load; an empty trends response still renders No trend data available | released@2026-09-27T20:54Z | Source: 19:57Z cut. Batch 7 (wf_a3ea2c8c-560), build then review. Review APPROVE on a746655f; in train 13, main 28e62e44 pushed 20:35:00 (`git ls-remote origin refs/heads/main` = 28e62e44). Published in v9.74.0 (`npm view loki-mode version` = 9.74.0; npm time 2026-09-27T20:54Z). |
252
252
  | S-190 | BACKLOG 112: R3 design doc describes project_total_usd as a plain sum | docs/R3-COST-OBSERVABILITY-DESIGN.md | LOW | grep -n 'sum of per-run proof costs' docs/R3-COST-OBSERVABILITY-DESIGN.md exits 1; grep -n project_total_partial docs/R3-COST-OBSERVABILITY-DESIGN.md prints at least one line | released@2026-09-27T21:15Z | Source: 19:57Z cut. Batch 8 (wf_ff8d537c-40e), build then review. Review APPROVE on 1d6786bf; in train 14, main 04af133a pushed 20:58:10 (`git ls-remote origin refs/heads/main` = 04af133a). Published in v9.75.0 (`npm view loki-mode version` = 9.75.0; npm time 2026-09-27T21:15Z). |
253
253
  | S-191 | Bring tests/test-review-assurance-tail.sh under 60 s wall time with bounded concurrency, keeping every per-case budget and assertion unchanged. | tests/test-review-assurance-tail.sh, tests/shard-durations.tsv (update its row) | RED: `time bash tests/test-review-assurance-tail.sh` over 60 s today (memory says load-flaky). GREEN: under 60 s on 3 consecutive runs, with identical pass counts printed, and every case still runs (compare the case-name lists before and after). Under `LOKI_TEST_JOBS=1` it still passes. Each parallel case uses its own run-owned temp dir; record and wait on your own PIDs only. Reuse built commit 63396544 (branch worktree-wf_ff8d537c-40e-4) as a starting point after rebasing. No CHANGELOG. | MEDIUM | merged@2026-10-03T10:50Z | df4f23207..328ad1f05 on main (MEDIUM TL APPROVE), shard row 116 to 45 |
254
254
  | S-192 | BACKLOG 112: no test drives the web-app WebSocket status push payload for unmeasured cost | web-app/tests/test_status_push_unmeasured.py (new), web-app/server.py (lift the nested status reader only if needed) | MEDIUM | python3 -m pytest -q web-app/tests/test_status_push_unmeasured.py passes: no tokens gives cost null and max_iterations null, priced tokens give a number; forcing 0.0 in a scratch copy fails case 1 | released@2026-09-27T21:15Z | Source: 19:57Z cut. Batch 8 (wf_ff8d537c-40e), build then review. Review APPROVE on 0b6deb16; in train 14, main 04af133a pushed 20:58:10 (`git ls-remote origin refs/heads/main` = 04af133a). Published in v9.75.0 (`npm view loki-mode version` = 9.75.0; npm time 2026-09-27T21:15Z). |
@@ -272,7 +272,7 @@ set is declared to avoid overlap with those and with each other.
272
272
  | S-210 | Velocity: help-discoverability (29s) and completion-coverage (30s) probe loops under 10s each | tests/test-help-discoverability.sh, tests/test-completion-coverage.sh (probe loops only) | LOW | time bash tests/test-help-discoverability.sh and time bash tests/test-completion-coverage.sh each exit 0 with real under 10s; real_count and pass counts match the pre-change capture; both timings reported | released@2026-09-27T21:45Z | Source: 20:12Z cut. Batch 9 (wf_4da25841-89e), build then review. Review APPROVE on d4fb8ad2; in train 16, main 800ac46e pushed 21:25:40 (`git ls-remote origin refs/heads/main` = 800ac46e). Published in v9.76.0 (`npm view loki-mode version` = 9.76.0; npm time 2026-09-27T21:45Z). |
273
273
  | S-211 | BACKLOG 75: register the four suites no runner executes (Captain, after S-174 merges) | tests/run-all-tests.sh (four run_test lines only, after S-174 merges), tests/shard-durations.tsv (four lines) | LOW | grep -c -e test_managed_completion_flag -e test_managed_review_flag -e test-evidence-gate-no-tests -e test-voter-agents-json tests/run-all-tests.sh prints 8; bash tests/test-shard-coverage.sh exits 0; each suite ran 3 of 3 from a scratch cwd with no .loki/state/provider left | released@2026-09-27T21:45Z | Source: 20:12Z cut. Batch 9 (wf_4da25841-89e), build then review. Review APPROVE on a04bbb7a; in train 15, main e72bcd66 pushed 21:22:34 (`git ls-remote origin refs/heads/main` = e72bcd66). Published in v9.76.0 (`npm view loki-mode version` = 9.76.0; npm time 2026-09-27T21:45Z). |
274
274
  | S-212 | GUARDS 5, 12 and 13 still read PENDING after S-138, S-139 and S-154 landed (after S-181 merges) | docs/v10/GUARDS.md (sections 5, 12, 13 only; does not overlap S-181 section 11) | LOW | awk '/^## 12\./,0' docs/v10/GUARDS.md piped to grep -c 'PENDING, no slice cut' prints 0; bash tests/test-no-ambient-gitconfig-writes.sh and bash tests/test-v10-pulse.sh exit 0 | released@2026-09-27T21:45Z | Source: 20:12Z cut. Batch 9 (wf_4da25841-89e), build then review. Review APPROVE on bd135cb8; in train 15, main e72bcd66 pushed 21:22:34 (`git ls-remote origin refs/heads/main` = e72bcd66). Published in v9.76.0 (`npm view loki-mode version` = 9.76.0; npm time 2026-09-27T21:45Z). |
275
- | S-213 | BACKLOG 123: cost.html and proofs.html council-vote labels have no test of their own | dashboard-ui/tests/static-council-vote-label.node.test.mjs (new) | LOW | node --test dashboard-ui/tests/static-council-vote-label.node.test.mjs passes (proofs.html council prefix and title, cost.html Council vote header); renaming the header or dropping the title in a scratch copy fails it | parked@2026-09-27T21:43Z | Source: 20:12Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit ce106a03 kept on branch worktree-wf_6fed529f-a3d-1. |
275
+ | S-213 | BACKLOG 123: cost.html and proofs.html council-vote labels have no test of their own | legacy-ui/tests/static-council-vote-label.node.test.mjs (new) | LOW | node --test legacy-ui/tests/static-council-vote-label.node.test.mjs passes (proofs.html council prefix and title, cost.html Council vote header); renaming the header or dropping the title in a scratch copy fails it | parked@2026-09-27T21:43Z | Source: 20:12Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit ce106a03 kept on branch worktree-wf_6fed529f-a3d-1. |
276
276
  | S-214 | BACKLOG 147: P7 useMemo arm misses a factory that calls a registered fabricator | tests/moat/p7-no-fabricated-data.sh (HELPER_LOCAL_DECL_TMPL ~1182 and its use ~2186, ceiling comment ~978-986, one fixture beside the DECL_USEMEMO fixture ~3138-3160 only; does not overlap S-198) | HIGH | bash tests/moat/p7-no-fabricated-data.sh prints PASS for every P7 case and flags the composed useMemo fixture; removing the useMemo prefix in a scratch copy lets it through; git diff --stat tests/moat/cases.txt is empty | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit 657597c1 kept on branch worktree-wf_6fed529f-a3d-2. |
277
277
  | S-215 | PR receipt renderer in proof-pr.sh imports json from the target repo (cwd shadow) | autonomy/lib/proof-pr.sh (render_evidence_receipt_md heredoc reader plus guarded _loki_snapshot_py_tool copy), tests/test-proof-pr-no-cwd-shadow.sh (new) | HIGH | bash tests/test-proof-pr-no-cwd-shadow.sh exits 0 (a planted json.py cannot forge the headline) and reverting to bare python3 - in a scratch copy fails it; bash tests/test-proven-pr-receipt.sh exits 0; bash tests/test-council-py-tool-identity.sh exits 0 and counts one more copy | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit 56a41332 kept on branch worktree-wf_6fed529f-a3d-3. |
278
278
  | S-216 | loki verify inline readers import from the tree under review (cwd shadow) | autonomy/verify.sh (reader sites ~190, 591, 1269, 1271, 1295, 1337, 1339, 1441 plus guarded helper copy; not the unittest or py_compile runs), tests/test-verify-no-cwd-shadow.sh (new) | HIGH | bash tests/test-verify-no-cwd-shadow.sh exits 0 and reverting one site in a scratch copy fails it; bash tests/test-verify.sh exits 0; bash tests/moat/run.sh reports no rule failed; bash tests/test-council-py-tool-identity.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit 29eb5d3b kept on branch worktree-wf_6fed529f-a3d-4. |
@@ -282,9 +282,9 @@ set is declared to avoid overlap with those and with each other.
282
282
  | S-220 | BACKLOG 109: untrack step's global reset drops force-staged agent files from the session commit | autonomy/run.sh (_loki_untrack_agent_committed_user_files only), tests/test-untrack-keeps-force-staged.sh (new) | MEDIUM | bash tests/test-untrack-keeps-force-staged.sh exits 0: git add -f dist/bundle.js lands in the session commit while the pre-existing user file stays untracked on disk; restoring git reset -q in a scratch copy fails it; bash tests/test-branch-lifecycle.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Paused by CEO P0 (Loki 10 engine). |
283
283
  | S-221 | BACKLOG 123: audit.py verify exits 0 when it checked nothing | dashboard/audit.py (_unified_cli verify branch and docstring only; tip and prefix untouched), tests/dashboard/test_audit_verify_cli_nothing_checked.py (new) | MEDIUM | python3 -m pytest -q tests/dashboard/test_audit_verify_cli_nothing_checked.py: empty dir exits 2, valid chain 0, tampered 1, tip on an empty dir still 0; bash tests/test-audit-chain-honesty.sh and bash tests/test-audit-js-suites.sh exit 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit 725adbf1 kept on branch worktree-wf_6fed529f-a3d-7. |
284
284
  | S-222 | BACKLOG 118: skill-session WebSocket status push hardcodes running_agents 0 | dashboard/server.py (skill-session broadcast payload ~1030-1047 only), tests/dashboard/test_skill_session_ws_running_agents.py (new) | LOW | python3 -m pytest -q tests/dashboard/test_skill_session_ws_running_agents.py shows running_agents None on the skill-session push; restoring 0 fails it | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit e41553cd kept on branch worktree-wf_6fed529f-a3d-8. |
285
- | S-223 | BACKLOG 114/118: notification triggers read No triggers configured after a failed read | dashboard/server.py (get_notification_triggers only), dashboard-ui/components/loki-notification-center.js (_loadTriggers and triggers empty branch only), tests/dashboard/test_notification_triggers_unreadable.py (new), dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs (new) | LOW | python3 -m pytest -q tests/dashboard/test_notification_triggers_unreadable.py shows triggers null with error on a corrupt file and [] on a missing one; node --test dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs shows an error lacks No triggers configured and an empty list keeps it | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Paused by CEO P0 (Loki 10 engine). |
285
+ | S-223 | BACKLOG 114/118: notification triggers read No triggers configured after a failed read | dashboard/server.py (get_notification_triggers only), legacy-ui/components/loki-notification-center.js (_loadTriggers and triggers empty branch only), tests/dashboard/test_notification_triggers_unreadable.py (new), legacy-ui/tests/loki-notification-triggers-error.node.test.mjs (new) | LOW | python3 -m pytest -q tests/dashboard/test_notification_triggers_unreadable.py shows triggers null with error on a corrupt file and [] on a missing one; node --test legacy-ui/tests/loki-notification-triggers-error.node.test.mjs shows an error lacks No triggers configured and an empty list keeps it | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Paused by CEO P0 (Loki 10 engine). |
286
286
  | S-224 | BACKLOG 118: web-app receipt and cost trend show a partly priced run as a complete cost | web-app/src/components/EvidenceReceiptPanel.tsx (Cost field only), web-app/src/api/client.ts (ProofDetail cost type and cost/timeline runs type only), web-app/src/pages/MetricsPage.tsx (costTrend only), web-app/src/components/EvidenceReceiptPanel.cost.test.mjs (new) | MEDIUM | node --test web-app/src/components/EvidenceReceiptPanel.cost.test.mjs: cost_partial true renders at least $1.20, absent keeps $1.20, a partial run's trend label carries (partial); cd web-app && npx tsc -b exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit 3d463e79 kept on branch worktree-wf_6fed529f-a3d-9. |
287
- | S-225 | BACKLOG 118: standalone receipts list shows a partly priced run as a complete cost | dashboard-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg) | LOW | bash tests/test-receipts-panel.sh exits 0 with the new leg asserting at least $X.XX only when cost_partial is true; bash tests/test-budget-banner-dedup.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit c9cd69c4 kept on branch worktree-wf_6fed529f-a3d-10. |
287
+ | S-225 | BACKLOG 118: standalone receipts list shows a partly priced run as a complete cost | legacy-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg) | LOW | bash tests/test-receipts-panel.sh exits 0 with the new leg asserting at least $X.XX only when cost_partial is true; bash tests/test-budget-banner-dedup.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit c9cd69c4 kept on branch worktree-wf_6fed529f-a3d-10. |
288
288
  | S-226 | BACKLOG 106 class: loki stats reads unmeasured cost as $0.00 on both routes | autonomy/loki (cmd_stats only), loki-ts/src/commands/stats.ts, loki-ts/tests/commands/stats_unmeasured.test.ts (new), tests/test-stats-unmeasured-cost.sh (new) | MEDIUM | bash tests/test-stats-unmeasured-cost.sh exits 0 (all-zero records give cost_usd null and not recorded, same on both routes); cd loki-ts && bun test tests/commands/stats.test.ts tests/commands/stats_unmeasured.test.ts exits 0; bash tests/test-bash-bun-parity.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Batch 10 (wf_6fed529f-a3d), build then review. Paused by CEO P0 (Loki 10 engine) before review; built commit ea739eed kept on branch s-226-stats-unmeasured-cost. |
289
289
  | S-227 | BACKLOG 106 class: loki status prints Budget $0 for a run it never measured, on both routes | autonomy/loki (cmd_status budget block only), loki-ts/src/commands/status.ts (readBudgetField and its budget caller only), loki-ts/tests/commands/status.test.ts (budget legs only), tests/test-status-budget-unmeasured.sh (new) | MEDIUM | bash tests/test-status-budget-unmeasured.sh exits 0 (budget_used 0, null or absent prints not recorded on both routes, a positive value prints as today); cd loki-ts && bun test tests/commands/status.test.ts exits 0; bash tests/test-status-cli-provider-parity.sh exits 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Paused by CEO P0 (Loki 10 engine). |
290
290
  | S-228 | BACKLOG 121: DeployConnections pushes default not-connected states upward after its own fetch failed | web-app/src/components/DeployConnections.tsx (connect and disconnect handlers only), web-app/src/components/DeployConnections.propagate.test.mjs (new) | LOW | node --test web-app/src/components/DeployConnections.propagate.test.mjs shows no synthesized statuses reach onStatusChange after a failed fetch; node --test web-app/src/components/DeployConnections.state.test.mjs and cd web-app && npx tsc -b exit 0 | parked@2026-09-27T21:43Z | Source: 20:59Z cut. Paused by CEO P0 (Loki 10 engine). |
@@ -427,7 +427,7 @@ set is declared to avoid overlap with those and with each other.
427
427
  | E-95 | Guard for red main 8f2179cd (App Runner Watchdog Health fixture server never came up; rerun 36453069628 passed): free port by binding 0, readiness poll up to 10s with a clear message; 20/20 under parallel load | tests/test-app-runner-watchdog-health.sh, docs/v10/GUARDS.md | LOW | 20 consecutive passes while 4 parallel pulse suites run | released@2026-09-28T21:01Z | Source: founder 17:22Z. Wave E27 (wf_bcacb1d1-e76). Wave E27 stopped 18:37Z (founder: over budget, load 50). TL APPROVE; merged locally; `bash tests/test-app-runner-watchdog-health.sh` 12 passed 0 failed. Released in v10.5.0 (merge 08dd38f4 is an ancestor of v10.5.0). |
428
428
  | E-86 | Pre-push gitleaks for eval task fixtures (founder 15:16Z): pinned v8.30.0 with hardcoded checksums, every pushed commit scanned in dir mode from the pushed commit (not the working tree), refusal names file, line and rule, never the secret | .githooks/pre-push, scripts/install-gitleaks.sh, tests/test-pre-push-gitleaks.sh, .gitleaksignore | HIGH | real-push fixtures: a sourcegraph URL plus 40-hex pin is refused; opus security review | released@2026-09-28T21:01Z | Source: v10.2.0 blocked by gitleaks. Rounds 1-3 opus REJECT with reproduced fail-opens (non-ASCII dirs, unfetched force-push, working-tree scan, checksum bypass; intermediate commits; root commits, history leak, case collisions). Round 4 building as one squashed commit off main. Round 4 8f9baace opus APPROVE (every earlier reproduction refuses; fresh-clone Security Audit gitleaks rc=0 with the branch merged); merged on main; `bash tests/test-pre-push-gitleaks.sh` 40 passed 0 failed. Follow-ups in E-99. Released in v10.5.0 (merge d7ce074b is an ancestor of v10.5.0). |
429
429
  | E-96 | Safe worktree pruning: scripts/prune-worktrees.sh removes a .claude/worktrees entry only when it is not locked, has no process with a cwd inside it (lsof), and its branch has no commit or file change in the last 30 minutes measured with git and stat (never find -newermt), refusing when any check cannot run; the pulse WORKTREE_COUNT NEXT ACTION names the script | scripts/prune-worktrees.sh, tests/test-prune-worktrees.sh, scripts/v10-pulse.sh (NEXT ACTION text only) | MEDIUM | fixture: a worktree with a live process inside is kept; an idle one is removed; an unsupported check refuses | parked@2026-09-28T18:58Z | Source: 17:36Z incident: the Chief of Staff pruned by `find -newermt "-25 minutes"` (unsupported on BSD find, matched nothing) and force-removed 7 live builder worktrees (M-07 r4, M-11 r3, EV-14, EV-12F-a, EV-12G, E-95, E-87); every branch had its work committed, uncommitted edits since the last commit were lost. Superseded by E-101 (same prune-worktrees.sh scope). |
430
- | DEP-05 | npm/bun patch and minor batch from docs/v10/DEPS.md (web-app, dashboard-ui, vscode-extension, root; lockfiles regenerated and committed; 0.x packages excluded) | the package.json and lockfiles DEPS.md names for patch/minor only | LOW | npm audit: no new high or critical; hallucinated-dependency guard rc=0; full Tier B plus the moat suite on a PR run | released@2026-09-28T22:02Z | Source: DEP-01 inventory (D35). Dispatched 21:18Z sonnet (founder 17:10 staffing directive). Tech Lead REJECT 82e35ffa: @types/vscode ^1.138 with engines.vscode ^1.85 (types expose APIs older users lack); rework drops that bump. r2 31c06cc2 restores @types/vscode ^1.85.0 (extension compile passes); merged cdec9666. web-app high audit findings 2 to 0. Released in v10.5.2 (merge cdec9666 is an ancestor of v10.5.2). |
430
+ | DEP-05 | npm/bun patch and minor batch from docs/v10/DEPS.md (web-app, legacy-ui, vscode-extension, root; lockfiles regenerated and committed; 0.x packages excluded) | the package.json and lockfiles DEPS.md names for patch/minor only | LOW | npm audit: no new high or critical; hallucinated-dependency guard rc=0; full Tier B plus the moat suite on a PR run | released@2026-09-28T22:02Z | Source: DEP-01 inventory (D35). Dispatched 21:18Z sonnet (founder 17:10 staffing directive). Tech Lead REJECT 82e35ffa: @types/vscode ^1.138 with engines.vscode ^1.85 (types expose APIs older users lack); rework drops that bump. r2 31c06cc2 restores @types/vscode ^1.85.0 (extension compile passes); merged cdec9666. web-app high audit findings 2 to 0. Released in v10.5.2 (merge cdec9666 is an ancestor of v10.5.2). |
431
431
  | DEP-06 | Python patch and minor batch from docs/v10/DEPS.md (dashboard, mcp, web-app requirements, sdk/python pyproject; 0.x excluded) | those requirements*.txt and pyproject.toml | LOW | pip-audit: no new high or critical; guard rc=0; PR run of Tests conclusion success (run id cited) | released@2026-09-28T22:02Z | Source: DEP-01 (D35). Dispatched 21:18Z sonnet (founder 17:10 staffing directive). Tech Lead APPROVE ecb628bd (no SQLAlchemy 2.1 removals used; tests mcp 59/0, web-app 164/0, dashboard 39/0; 5 pip-audit findings pre-existing, no fix). Merged 4b009c21. Released in v10.5.2 (merge 4b009c21 is an ancestor of v10.5.2). |
432
432
  | DEP-07 | SHA-pin every remaining tag-pinned action already on its latest major (anchore/sbom-action, anthropics/claude-code-action, contributor-assistant/github-action, oven-sh/setup-bun) with a version comment | .github/workflows/*.yml (those uses: lines only) | LOW | every uses: is a full SHA with a vX comment; actionlint rc=0; PR run | released@2026-09-28T22:02Z | Source: DEP-01 (D35). Serialize after DEP-02/DEP-03 merge (same files). Dispatched 21:18Z sonnet (founder 17:10 staffing directive). Tech Lead APPROVE b2c49a12 (4 SHAs match current tag targets; only uses lines changed). Merged 3da32438. Released in v10.5.2 (merge 3da32438 is an ancestor of v10.5.2). |
433
433
  | G-01 | Usage governor (D39): scripts/usage-governor.py sums usage (output, input, cache read, cache write) from ~/.claude/projects/**/*.jsonl per model, role (from workflow labels and agent types where recorded) and hour; stores founder plan-percentage readings (docs/v10/usage-readings.tsv) and fits tokens-per-percent as a labelled estimate; projects 5-hour window and weekly usage; outputs max engineers for the next hour; checks and records whether Claude Code exposes plan usage directly (statusline input rate-limit fields, /usage) and uses it when it does | scripts/usage-governor.py, docs/v10/usage-readings.tsv, tests/test-usage-governor.sh | HIGH | fixture jsonl plus readings gives a stated projection and max-engineer number; missing readings reads "uncalibrated", never a number presented as fact | released@2026-09-28T21:01Z | Source: founder 17:44Z. First in the queue; everything obeys it. r2 de8e1f76 opus REJECT: weekly reset 1h off across DST; fixes 2 and 4 unguarded. r3 dispatched 19:00Z. r3 fa279532 opus APPROVE (DST reset fixed; fixes 2 and 4 mutation-guarded by T14/T15); merged c2ae4347; governor 25/0, logger 16/0, run-shellcheck.sh passes, shard coverage 19/0, drift 6/0. Open non-blocking: weekly tokens counted from computed Wednesday not live resets_at-7d; no test for live-reset preference; "uncalibrated" label when idle. Released in v10.5.0 (merge c2ae4347 is an ancestor of v10.5.0). |
@@ -569,7 +569,7 @@ not push.
569
569
 
570
570
  ## Generated bundles (Captain rebuilds after every merge touching sources)
571
571
 
572
- `loki-ts/dist/loki.js`, `dashboard/static/index.html`, `dashboard-ui/dist/*`,
572
+ `loki-ts/dist/loki.js`, `legacy-ui-static/index.html`, `legacy-ui/dist/*`,
573
573
  `web-app/dist/*`.
574
574
 
575
575
  ## Wave log
@@ -650,7 +650,7 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
650
650
  | D51-B11 | D51 Phase B B11 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | merged@2026-10-03T04:49Z | needs B09/B10 04:45Z: deps met by worktree_prep.py (D61-07) and workspace.py (D65-MULTI); still unbuilt. Built c09dfd1eb+933ecc9fc; TL APPROVE r2 (r1 BLOCK: CHANGELOG x279, body perms); test-workspace 14/0 on main. |
651
651
  | D51-B12 | D51 Phase B B12 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked | needs B08 Superseded 04:45Z: delivered by D65-MULTI 5d9e6b341, C8 089ca0e9e, D61-07 6bf2c7799 (workspace.py runner/after/SKIPPED/killpg/integration.json/task_for, worktree_prep lock+deps, cmd_workspace). |
652
652
  | D51-B13 | D51 Phase B B13 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked@2026-10-03T09:52Z | superseded by D51-B13r (integration.json, no group.json) |
653
- | D51-B14 | D51 Phase B B14 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked@2026-10-03T09:52Z | superseded by D51-B14r |
653
+ | D51-B14 | D51 Phase B B14 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked@2026-10-03T09:52Z | superseded by D51-B14r |
654
654
  | D51-B15 | D51 Phase B B15 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked@2026-10-03T09:40Z | Superseded by PO-WS-METRICS-1 (624b5d964, merged): integration.json timestamps plus workspace_metrics.py. |
655
655
  | D51-B16 | D51 Phase B B16 (flag LOKI_WORKSPACES, docs/v10/D51-PHASE-B.md): 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 | parked@2026-10-03T09:52Z | superseded by D51-B16r (flag flip already landed, D63 C8) |
656
656
  | INTEL-1 | Standards-based receipts (competitive intel 2026-10-01): emit the Seal as an in-toto Statement in a DSSE envelope, verifiable by stock tools (in-toto verify, cosign verify-blob) as well as loki verify; V10-VISION names this stack | loki-ts/src/engine10 seal and receipt export, loki keys, tests, dist | a stock tool verifies a real receipt in a test; a tampered envelope fails both the stock tool and loki verify | HIGH | merged@2026-10-03T08:35Z | main c3031c9aa, opus APPROVE (14 probes, dsse+verify_cmd 44/0); dist rebuilt, guard 13/0; follow-ups in INTEL-1b |
@@ -788,18 +788,18 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
788
788
  | PO-HELP-1 | CLI help: add loki help answer and --export-dsse to loki help verify | autonomy/loki (help functions only) | help answer exits 0 and shows --text; help verify mentions dsse; bash -n; help tests pass | MEDIUM | merged@2026-10-03T09:24Z | merged ef50958a5 (TL APPROVE; help-no-recursion 9/0 on main, red 7/2 at parent) |
789
789
  | SEC-SCAN-1 | tests/test-secret-scan.sh 5/1 on main (real AWS key -> got pass/VERIFIED/0, expected fail/BLOCKED/2) | tests/test-secret-scan.sh and the secret-scan gate it exercises | suite green on main; root cause named (host gitleaks dependence vs real gate regression); no gate weakened | MEDIUM | merged@2026-10-03T09:22Z | merged 04f62ff4e (TL APPROVE; root cause: fixture AKIAIOSFODNN7EXAMPLE is gitleaks-allowlisted; 6/0 with and without gitleaks; mutation 3/3 red) |
790
790
  | PO-AUDIT-CLI-1 | S-221 re-cut: python3 dashboard/audit.py verify exits 0 on an empty or pre-hash audit dir though it checked nothing; exit 2 with status not_verified, keep valid field and tip untouched | dashboard/audit.py (_unified_cli verify branch and docstring only), tests/dashboard/test_audit_verify_cli_nothing_checked.py (new), docs/audit-logging.md (exit codes), CHANGELOG.md | python3 -m pytest -q tests/dashboard/test_audit_verify_cli_nothing_checked.py (empty dir 2, valid chain 0, tampered 1, tip on empty dir still 0; red on current main); python3 -m pytest -q tests/dashboard/test_audit_verify_nothing_checked.py; bash tests/test-audit-chain-honesty.sh; bash tests/test-audit-js-suites.sh | MEDIUM | merged@2026-10-03T09:27Z | main db276a24e; TL APPROVE (tampered=1, empty=2 nothing_checked); pytest 11 passed |
791
- | PO-DASH-HONEST-1 | S-222 + S-223 re-cut: skill-session WebSocket push hardcodes running_agents 0; notification triggers panel says No triggers configured after a failed read | dashboard/server.py (skill-session payload near line 1042 and get_notification_triggers only), dashboard-ui/components/loki-notification-center.js (_loadTriggers and empty branch only), tests/dashboard/test_skill_session_ws_running_agents.py (new), tests/dashboard/test_notification_triggers_unreadable.py (new), dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs (new), CHANGELOG.md | pytest on the two new files red then green (running_agents None when unmeasured, triggers null plus error on a corrupt file, [] on a missing one); node --test dashboard-ui/tests/loki-notification-triggers-error.node.test.mjs (error text lacks No triggers configured, empty list keeps it); python3 -m pytest -q tests/dashboard -k "notification or skill_session" | LOW | merged@2026-10-03T09:30Z | main 99674923f; TL APPROVE; pytest 7 passed, node 3/0 |
791
+ | PO-DASH-HONEST-1 | S-222 + S-223 re-cut: skill-session WebSocket push hardcodes running_agents 0; notification triggers panel says No triggers configured after a failed read | dashboard/server.py (skill-session payload near line 1042 and get_notification_triggers only), legacy-ui/components/loki-notification-center.js (_loadTriggers and empty branch only), tests/dashboard/test_skill_session_ws_running_agents.py (new), tests/dashboard/test_notification_triggers_unreadable.py (new), legacy-ui/tests/loki-notification-triggers-error.node.test.mjs (new), CHANGELOG.md | pytest on the two new files red then green (running_agents None when unmeasured, triggers null plus error on a corrupt file, [] on a missing one); node --test legacy-ui/tests/loki-notification-triggers-error.node.test.mjs (error text lacks No triggers configured, empty list keeps it); python3 -m pytest -q tests/dashboard -k "notification or skill_session" | LOW | merged@2026-10-03T09:30Z | main 99674923f; TL APPROVE; pytest 7 passed, node 3/0 |
792
792
  | PO-WEB-COST-1 | S-224 re-cut: web-app Evidence Receipt Cost field and Metrics cost trend show a partly priced run (cost_partial true) as a complete cost | web-app/src/components/EvidenceReceiptPanel.tsx (Cost field only), web-app/src/api/client.ts (ProofDetail cost type and cost/timeline runs type only), web-app/src/pages/MetricsPage.tsx (costTrend only), web-app/src/components/EvidenceReceiptPanel.cost.test.mjs (new), CHANGELOG.md | node --test web-app/src/components/EvidenceReceiptPanel.cost.test.mjs (cost_partial true renders at least $1.20, absent keeps $1.20, partial trend label carries (partial); red before); cd web-app && npx tsc -b rc 0 | MEDIUM | merged@2026-10-03T09:27Z | main 4a429626b; TL APPROVE; node 4/0; shard markers fixed 8106e6a72 |
793
- | PO-STANDALONE-COST-1 | S-225 re-cut: standalone receipts list shows a partly priced run as a complete cost | dashboard-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg), CHANGELOG.md | bash tests/test-receipts-panel.sh rc 0 with the new leg asserting at least $X.XX only when cost_partial is true (red before); bash tests/test-budget-banner-dedup.sh rc 0 | LOW | merged@2026-10-03T09:27Z | main f99c8cc64; TL APPROVE; receipts-panel 21/0 |
793
+ | PO-STANDALONE-COST-1 | S-225 re-cut: standalone receipts list shows a partly priced run as a complete cost | legacy-ui/scripts/build-standalone.js (loadReceipts cost cell only), tests/test-receipts-panel.sh (one new leg), CHANGELOG.md | bash tests/test-receipts-panel.sh rc 0 with the new leg asserting at least $X.XX only when cost_partial is true (red before); bash tests/test-budget-banner-dedup.sh rc 0 | LOW | merged@2026-10-03T09:27Z | main f99c8cc64; TL APPROVE; receipts-panel 21/0 |
794
794
  | PO-WEB-DEPLOY-1 | S-228 re-cut: DeployConnections connect and disconnect handlers push synthesized default not-connected statuses upward after their own fetch failed | web-app/src/components/DeployConnections.tsx (connect and disconnect handlers only, lines 395-440), web-app/src/components/DeployConnections.propagate.test.mjs (new), CHANGELOG.md | node --test web-app/src/components/DeployConnections.propagate.test.mjs (no synthesized statuses reach onStatusChange after a failed fetch; red before); node --test web-app/src/components/DeployConnections.state.test.mjs; cd web-app && npx tsc -b rc 0 | LOW | merged@2026-10-03T09:30Z | main fd92d52f0 (r2 3ade22ae1 adds runner+shard row, the sole TL finding; CoS verified shard-coverage 19/0, drift 6/0) |
795
795
  | PO-WEB-WORKSPACE-1 | S-229 + S-230 re-cut: preview header says Detecting project type forever after a failed preview-info fetch; unknown phases label building and Replay Build can never show (buildPhase returns idle when not building, so the complete branch is unreachable) | web-app/src/components/ProjectWorkspace.tsx (getPreviewInfo call and the two Detecting project type branches ~1877 and ~2093; buildPhase memo ~1401-1410 and Replay Build condition ~1488 only), web-app/src/components/ProjectWorkspace.preview.test.mjs (new), web-app/src/components/ProjectWorkspace.phase.test.mjs (new), CHANGELOG.md | node --test on both new files (rejected fetch renders Could not detect project type; unrecognized phase is not building; completed idle session shows Replay Build; red before); node --test web-app/src/components/ProjectWorkspace.panels.test.mjs; cd web-app && npx tsc -b rc 0 | LOW | merged@2026-10-03T09:30Z | main 38ae6a29c; TL APPROVE; node 16/0 with DEPLOY tests |
796
796
  | PO-WS-METRICS-1 | D51-B15 re-cut (its gate B07 was superseded and there is no group.json; runs record only integration.json): record per-repo started_at and finished_at in integration.json, add workspace_metrics.py reporting PRs per wall-clock hour and per attention minute; runs lacking timestamps are reported as unmeasured, never counted as zero | autonomy/lib/workspace.py (run loop and integration.json write only), autonomy/lib/workspace_metrics.py (new), tests/workspace/95-metrics.sh (new, register in the runner and a shard row, timeout -k, shellcheck), docs/WORKSPACES.md, CHANGELOG.md | bash tests/workspace/95-metrics.sh (fixture run gives the hand-computed rate; an old integration.json without timestamps prints unmeasured; red before); bash tests/workspace/50-run.sh and 00-smoke.sh rc 0; structural-checks.sh and shard registration guards rc 0 | MEDIUM | merged@2026-10-03T09:30Z | main 624b5d964; TL APPROVE; test-workspace 19/0 |
797
797
  | PO-SESSION-COMMIT-1 | S-219 + S-220 re-cut (legacy run.sh): a failed git add -A makes the session commit silently commit nothing; the untrack step's global git reset drops force-staged agent files from the session commit | autonomy/run.sh (commit_session_changes add block ~11065 and _loki_untrack_agent_committed_user_files ~10985 only), tests/test-session-commit-add-failure.sh (new), tests/test-untrack-keeps-force-staged.sh (new), both registered in the runner with shard rows, CHANGELOG.md | both new tests rc 0 and red when the rc check or git reset -q is restored in a scratch copy; bash tests/test-branch-lifecycle.sh rc 0; bash -n autonomy/run.sh; shellcheck on changed files; structural-checks.sh rc 0 | MEDIUM | merged@2026-10-03T09:40Z | 939e23126. TL APPROVE (exit 128 aborts the add, index restore reproduced, both mutants red). On main: new tests 7/0 and 5/0, bash -n ok, shard 19/0, drift 6/0. |
798
- | PO-COUNCIL-LABEL-TEST-1 | S-213 re-cut: the Council vote header in cost.html and the council prefix plus title on the proofs.html badge have no test of their own | dashboard-ui/tests/static-council-vote-label.node.test.mjs (new; reads dashboard/static/proofs.html and cost.html, edits neither) | node --test dashboard-ui/tests/static-council-vote-label.node.test.mjs passes (proofs.html line 152 prefix and title, cost.html line 308 header); renaming the header or dropping the title in a scratch copy fails it | LOW | merged@2026-10-03T09:35Z | c331cde1a (r2 23f2c4e5f: content-anchored matching, shard row). CoS verified on main: node --test 2/0, shard coverage 19/0, drift 6/0. Test-only, no CHANGELOG. |
798
+ | PO-COUNCIL-LABEL-TEST-1 | S-213 re-cut: the Council vote header in cost.html and the council prefix plus title on the proofs.html badge have no test of their own | legacy-ui/tests/static-council-vote-label.node.test.mjs (new; reads legacy-ui-static/proofs.html and cost.html, edits neither) | node --test legacy-ui/tests/static-council-vote-label.node.test.mjs passes (proofs.html line 152 prefix and title, cost.html line 308 header); renaming the header or dropping the title in a scratch copy fails it | LOW | merged@2026-10-03T09:35Z | c331cde1a (r2 23f2c4e5f: content-anchored matching, shard row). CoS verified on main: node --test 2/0, shard coverage 19/0, drift 6/0. Test-only, no CHANGELOG. |
799
799
  | PO-P7-SINKS-1 | E-138: P7 no-fabricated-data scanner misses optional-call sinks and one-hop aliases (setRows?.([...]), window[k]?.(rows), const s = setRows; s(rows), a memo that forwards a fabricator result) | tests/moat/p7-no-fabricated-data.sh (and its red and green fixtures under tests/moat/ only) | bash tests/moat/p7-no-fabricated-data.sh with a red and a green fixture per form, each red before the change; the existing fixtures keep their verdicts; moat suite 4/9 or better unchanged | HIGH | merged@2026-10-03T09:46Z | b2b592b29. Opus APPROVE: 13 added findings, 0 removed, real tree 0 findings, each arm mutation-red. On main all four P7 cases PASS. Advisory: SCALAR_READ exclusion has no pinning fixture. |
800
800
  | A-04d | A-04c follow-up (opus r5 advisories A1, A3): loki-seal Known limits must name empty body or early return, an assertion only in a helper declared after the test, same-name or keyword collisions across files, and forged runner-format lines printed by a test; fix the README sentence the matched test body must contain an assertion | packages/loki-seal/README.md, packages/loki-seal/skills/loki-seal/SKILL.md, CHANGELOG.md | grep finds each of the four limits in README Known limits; bash packages/loki-seal/test/run.sh 72/0; no code change | LOW | merged@2026-10-03T09:46Z | aa4770f57; seal suite 72/0. Plus 0b-fix: escaped U+2714/U+2716 marks in an A-04c fixture that turned structural-checks emoji scan red on main. |
801
801
  | D51-B13r | Read-only workspace runs API over integration.json (runs never produce group.json) | dashboard/api_workspaces.py (new), dashboard/api_operator.py (2 GET routes only), tests/dashboard/test_api_workspaces.py (new) | `python3 -m pytest tests/dashboard/test_api_workspaces.py -q` (red: module absent) | MEDIUM | merged@2026-10-03T10:14Z | merged 6d927b5c6 (TL approve; cherry-pick of 4fbb99b40), wall shard 19/0 drift 6/0 |
802
- | D51-B14r | Start page "Workspace runs" card: per-repo rows, integration row, stale badge; an unreadable run shows an error, never an empty card | dashboard/static/start.html, dashboard-ui/tests/start-workspace-card.node.test.mjs (new), run-all-tests.sh line | `node --test dashboard-ui/tests/start-workspace-card.node.test.mjs` (red: no card) | LOW | merged@2026-10-03T10:50Z | 1280b2781 + 7329ab5f1 on main (TL APPROVE r2, node 5/0, red 4/1) |
802
+ | D51-B14r | Start page "Workspace runs" card: per-repo rows, integration row, stale badge; an unreadable run shows an error, never an empty card | legacy-ui-static/start.html, legacy-ui/tests/start-workspace-card.node.test.mjs (new), run-all-tests.sh line | `node --test legacy-ui/tests/start-workspace-card.node.test.mjs` (red: no card) | LOW | merged@2026-10-03T10:50Z | 1280b2781 + 7329ab5f1 on main (TL APPROVE r2, node 5/0, red 4/1) |
803
803
  | D51-B16r | E2E through the real CLI routes, plus the "verify a workspace run" doc | tests/workspace/99-e2e.sh (new), docs/WORKSPACES.md | `bash tests/test-workspace.sh` (red: 99-e2e asserts absent) | MEDIUM | merged@2026-10-03T10:14Z | merged 4341f84a5 (approve; cherry-pick of ef73d6c6d), test-workspace 33/0 |
804
804
  | WS-INTERRUPT | SIGTERM/SIGINT writes integration.json status=interrupted; status lists an unreadable run as "unreadable" | autonomy/lib/workspace.py (stop, _runs, status only), tests/workspace/55-interrupt.sh (new) | `bash tests/test-workspace.sh` | MEDIUM | merged@2026-10-03T10:14Z | merged 52f510d71 (approve; cherry-pick of e70cdcc6d) |
805
805
  | WS-PREP-BOUND | Bound the prep lock to 120s then FAILED; refuse relative-symlink escape and source-path shebangs | autonomy/lib/worktree_prep.py, tests/test-worktree-prep.py | `python3 tests/test-worktree-prep.py` | MEDIUM | merged@2026-10-03T10:14Z | merged 7c37faa8d (approve; cherry-pick of a2f2718d3), test-worktree-prep OK |
@@ -807,7 +807,7 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
807
807
  | S-215r | proof-pr.sh python cannot be shadowed by a cwd json.py | autonomy/lib/proof-pr.sh (render_evidence_receipt_md), tests/test-proof-pr-no-cwd-shadow.sh (new) | the new test (red on main) | HIGH | merged@2026-10-03T10:14Z | merged c6536dfe2 (opus approve; cherry-pick of b4176f42e). On main checkout proof-pr suite 5/1 only on the .loki/state/provider leg: the gitignored file predates the slice (Sep 30 17:58), environmental; builder worktree 6/0. CoS decision 10:14Z |
808
808
  | S-216r | verify.sh python readers are isolated from cwd shadowing | autonomy/verify.sh (reader sites 190,591,1269,1271,1295,1337,1339,1441), tests/test-verify-no-cwd-shadow.sh (new) | the new test | HIGH | merged@2026-10-03T10:35Z | r3 opus APPROVE; cherry-picked 100535de2 f38a93966 77b84becc; main: cwd-shadow 20/0, test-verify 25/0; test now flags only a provider file created during the run (6185c5249); CHANGELOG deduped. Advisories: label no-interpreter as inconclusive, add a dynamic leg for line 3117 |
809
809
  | S-218r | _loki_untracked_status cannot run a repo-local fsmonitor | autonomy/run.sh (_loki_untracked_status only), tests/test-untracked-status-fsmonitor.sh (new) | the new test | HIGH | merged@2026-10-03T10:56Z | r5 opus APPROVE (version spoofs, nonce, B1 retry all fail closed); main 0b6604fd9 + CHANGELOG collapse 1ff144efb; fsmonitor 21/0, branch-lifecycle 83/83; advisories A1 digit-length cap, A2 two-call race; in train/95 |
810
- | HONEST-READ-1 | A corrupt or denied file gives 503 or an error row, never an empty list | dashboard/server.py (list_proofs, memory patterns/episodes/skills/index only), dashboard/static/proofs.html, tests/dashboard/test_unreadable_not_empty.py (new) | `python3 -m pytest tests/dashboard/test_unreadable_not_empty.py -q` | LOW | merged@2026-10-03T10:14Z | merged 05c0940e9 (approve; cherry-pick of a29956235), pytest 12 passed |
810
+ | HONEST-READ-1 | A corrupt or denied file gives 503 or an error row, never an empty list | dashboard/server.py (list_proofs, memory patterns/episodes/skills/index only), legacy-ui-static/proofs.html, tests/dashboard/test_unreadable_not_empty.py (new) | `python3 -m pytest tests/dashboard/test_unreadable_not_empty.py -q` | LOW | merged@2026-10-03T10:14Z | merged 05c0940e9 (approve; cherry-pick of a29956235), pytest 12 passed |
811
811
  | S-226r | An unmeasured cost reads "unmeasured", not $0.00, in stats and status on both routes (absorbs S-227) | autonomy/loki (cmd_stats, cmd_status budget block), loki-ts/src/commands/stats.ts, loki-ts/src/commands/status.ts (readBudgetField), tests/test-stats-unmeasured-cost.sh + tests/test-status-budget-unmeasured.sh (new) | both new tests plus `cd loki-ts && bun test` | MEDIUM | merged@2026-10-03T10:14Z | merged e2c283a40 (approve; cherry-pick of 72df5665e), stats 8/0 status 8/0 |
812
812
  | S-231r | Rename the CI moat job to what it proves | .github/workflows/test.yml (job name and summary echo only) | `git grep -n "name: Moat suite" -- .github` prints nothing | LOW | merged@2026-10-03T11:19Z | d8cb2bc9c on main; TL APPROVE (job id kept, no display-name consumer; CoS verified no protection or ruleset context) |
813
813
  | PO-TEST-1 | Tests for scripts/metrics-usage-append.py | tests/test-metrics-usage-append.sh (new), runner and shard registration | red-then-green, shellcheck, structural guards; never writes the real METRICS.md | LOW | merged@2026-10-03T09:01Z | merged 41103e5c3 (TL APPROVE; suite + shard/registration guards green)|
@@ -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