loki-mode 9.74.0 → 9.75.0

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 (73) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/council-v2.sh +60 -13
  4. package/autonomy/lib/done-recognition.sh +73 -21
  5. package/dashboard/__init__.py +1 -1
  6. package/docs/INSTALLATION.md +1 -1
  7. package/docs/R3-COST-OBSERVABILITY-DESIGN.md +7 -1
  8. package/docs/exit-codes.md +21 -0
  9. package/docs/v10/ARCHITECT-CUTS.md +359 -233
  10. package/docs/v10/BOARD.md +64 -44
  11. package/docs/v10/GUARDS.md +13 -7
  12. package/loki-ts/dist/loki.js +2 -2
  13. package/mcp/__init__.py +1 -1
  14. package/package.json +1 -1
  15. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  16. package/web-app/dist/assets/{AdminPage-DaeYgQSE.js → AdminPage-CMGkmNnt.js} +1 -1
  17. package/web-app/dist/assets/{Avatar-CgwQi58_.js → Avatar-9mn8sJ-2.js} +1 -1
  18. package/web-app/dist/assets/{Badge-Bwq-lpRh.js → Badge-mSFLvvRX.js} +1 -1
  19. package/web-app/dist/assets/{Button-BEf4Nher.js → Button-B1v4CSkD.js} +1 -1
  20. package/web-app/dist/assets/CockpitPage-BW0hYuzC.js +47 -0
  21. package/web-app/dist/assets/{ComparePage-tFbdo90G.js → ComparePage-C1BXuolM.js} +1 -1
  22. package/web-app/dist/assets/{ErrorBoundary-Brewvgm9.js → ErrorBoundary-C2sJyBhb.js} +1 -1
  23. package/web-app/dist/assets/{EvidenceReceiptPanel-h_82QBVa.js → EvidenceReceiptPanel-a1irlBPD.js} +1 -1
  24. package/web-app/dist/assets/{GitHubIssuesPanel-Dcg5xDMm.js → GitHubIssuesPanel-zM-WRxYB.js} +1 -1
  25. package/web-app/dist/assets/{GitHubPRsPanel-DFKzVyA1.js → GitHubPRsPanel-DvRa5Rxq.js} +1 -1
  26. package/web-app/dist/assets/{HomePage-D21cM1Je.js → HomePage-CNwRexp5.js} +2 -2
  27. package/web-app/dist/assets/{LoginPage-DJ9yqMn4.js → LoginPage-HKogNiEX.js} +1 -1
  28. package/web-app/dist/assets/{MagicPage-mwkjJhBy.js → MagicPage-u1mvdkUd.js} +1 -1
  29. package/web-app/dist/assets/{MetricsPage-D2q-PD-s.js → MetricsPage-CThdMJb5.js} +1 -1
  30. package/web-app/dist/assets/{NotFoundPage-BtusJvgS.js → NotFoundPage-B1v3lELS.js} +1 -1
  31. package/web-app/dist/assets/{ProjectPage-CRPALtO8.js → ProjectPage-hDvSsdLF.js} +3 -3
  32. package/web-app/dist/assets/{ProjectsPage-DuzABpfc.js → ProjectsPage-CRAegSM6.js} +1 -1
  33. package/web-app/dist/assets/{SettingsPage-DhJPX-Rf.js → SettingsPage-Dt90bFxo.js} +1 -1
  34. package/web-app/dist/assets/{ShowcasePage-CvgS47nu.js → ShowcasePage-C5a9l8u_.js} +1 -1
  35. package/web-app/dist/assets/{SystemSettingsPage-l3Cv9YjY.js → SystemSettingsPage-DtqsDXbx.js} +1 -1
  36. package/web-app/dist/assets/{TeamsPage-DridGcnR.js → TeamsPage-CooeoWxR.js} +1 -1
  37. package/web-app/dist/assets/{TemplatesPage-CTNsfp03.js → TemplatesPage-CJhTxWrw.js} +1 -1
  38. package/web-app/dist/assets/{TerminalOutput-BuyksqLh.js → TerminalOutput-DvjfbDxb.js} +1 -1
  39. package/web-app/dist/assets/{activity-DM2TKaBi.js → activity-DK6KBQKA.js} +1 -1
  40. package/web-app/dist/assets/{bell-D2PMLbbX.js → bell-Cd8tQpN6.js} +1 -1
  41. package/web-app/dist/assets/{bot-BnN32Jxp.js → bot-Y30w8rML.js} +1 -1
  42. package/web-app/dist/assets/{check-CU128nw_.js → check-B5eUl1j9.js} +1 -1
  43. package/web-app/dist/assets/{chevron-left-ehNW1Do7.js → chevron-left-qyvpFqze.js} +1 -1
  44. package/web-app/dist/assets/{circle-alert-Cpw2gtOC.js → circle-alert-DXtjVPDB.js} +1 -1
  45. package/web-app/dist/assets/{clock-BOZHdPVS.js → clock-dqQis2Q6.js} +1 -1
  46. package/web-app/dist/assets/{cloud-BZ2L9Fzi.js → cloud-CzTURYO9.js} +1 -1
  47. package/web-app/dist/assets/{code-xml-sSo522gu.js → code-xml-DLbw1HTk.js} +1 -1
  48. package/web-app/dist/assets/{database-DrR1xHzS.js → database-BIj38v85.js} +1 -1
  49. package/web-app/dist/assets/{dollar-sign-CHE3T_rh.js → dollar-sign-9bVcHIkD.js} +1 -1
  50. package/web-app/dist/assets/{file-code-corner-CgcssyRQ.js → file-code-corner-D57x6xD1.js} +1 -1
  51. package/web-app/dist/assets/{file-plus-DtwfrxYH.js → file-plus-BXOrz3T5.js} +1 -1
  52. package/web-app/dist/assets/{globe-Dzla77iL.js → globe-Cnq8h4Gt.js} +1 -1
  53. package/web-app/dist/assets/{hammer-BAMdG66t.js → hammer-iiLGlF28.js} +1 -1
  54. package/web-app/dist/assets/{index-mQOnSYoW.js → index-uGGZ1Ij3.js} +2 -2
  55. package/web-app/dist/assets/{layers-DhuyLqmc.js → layers-gcGxxNEN.js} +1 -1
  56. package/web-app/dist/assets/{loader-circle-DclFyQ3B.js → loader-circle-B4Ad11xq.js} +1 -1
  57. package/web-app/dist/assets/{lock-C8v_bXNl.js → lock-DvQNG5RI.js} +1 -1
  58. package/web-app/dist/assets/{package-B4AnjM5D.js → package-BtQBNbq2.js} +1 -1
  59. package/web-app/dist/assets/{plus-DM95CmZI.js → plus-DKLiMXBZ.js} +1 -1
  60. package/web-app/dist/assets/{refresh-cw-CWaauzqX.js → refresh-cw-B4Gu8e2m.js} +1 -1
  61. package/web-app/dist/assets/{rotate-ccw-DxcvylpJ.js → rotate-ccw-DATSPLYS.js} +1 -1
  62. package/web-app/dist/assets/{scroll-text-Dx-V_BpP.js → scroll-text-GA8EtlY4.js} +1 -1
  63. package/web-app/dist/assets/{server-Cj2EfoGN.js → server-DT_3kM4V.js} +1 -1
  64. package/web-app/dist/assets/{shield-alert-OlmWv7sU.js → shield-alert-BEaqZEhO.js} +1 -1
  65. package/web-app/dist/assets/{thumbs-up-CIpJhyTd.js → thumbs-up-DVvA-Fas.js} +1 -1
  66. package/web-app/dist/assets/{trash-2-BIkoZkY6.js → trash-2-BCyT5A9N.js} +1 -1
  67. package/web-app/dist/assets/{trending-down-CI-OcCGt.js → trending-down-BLcNt39o.js} +1 -1
  68. package/web-app/dist/assets/{trending-up-B0dpgKi-.js → trending-up-BqfBp13A.js} +1 -1
  69. package/web-app/dist/assets/{upload-NhOBAjKA.js → upload-BxH0rjQU.js} +1 -1
  70. package/web-app/dist/assets/{usePolling-_QRF6f7x.js → usePolling-CokbBZIQ.js} +1 -1
  71. package/web-app/dist/assets/{user-kRNvOpun.js → user-C_u9mNZM.js} +1 -1
  72. package/web-app/dist/index.html +1 -1
  73. package/web-app/dist/assets/CockpitPage-Bj41Xtg9.js +0 -47
@@ -1,277 +1,403 @@
1
1
 
2
2
 
3
- ## 19:57Z cut (S-174..S-193)
3
+ ## 20:12Z cut (S-194..S-213)
4
4
 
5
- **Checked before cutting.**
6
- - **P2.verify-exit-contract and P2.fast-verify-inconclusive-not-zero.** Both are already listed in `tests/moat/pending.txt` with milestone v10.0.0. `tests/moat/run.sh` accepts them as FAIL, so they are not a regression on main.
7
- - The fix is the breaking renumber of verify exit codes (BACKLOG 4). The 19:10Z cut held that for the CEO, and this cut does not undo that.
8
- - When the renumber lands, the Captain promotes each case by deleting its pending.txt line.
9
- - S-182 does the part that breaks nothing: it documents the current codes, so users stop reading exit 0 from `--fast` as a pass.
10
- - **The run-all-tests missing-argument gap is real.** Probe: `bash -c 'set -euo pipefail; f(){ local a="$1"; local b="$2"; }; f x; echo after'` printed `$2: unbound variable` and exited 1 without printing `after`.
11
- - The missing-script branch's `return 1` also stops the whole runner under `set -e`. That is the same "later suites silently skipped" problem.
12
- - **Already handled, so dropped:**
13
- - BACKLOG 35 (0-byte baseline test in tests/test-moat-runner.sh).
14
- - BACKLOG 60 wording.
15
- - BACKLOG 91 (stage status not_run).
16
- - BACKLOG 116 Close button.
17
- - Standalone VERIFIED WITH GAPS colour and receipt ordering.
18
- - memory-browser null handling.
19
- - learning-dashboard signals.
20
- - GUARDS 13, whose mechanical check is S-139 (released). The PENDING text in GUARDS.md is out of date.
21
- - **A `.catch(() => null)` lint was considered and dropped.** 16 sites match, and most of them already render "Could not load". It would pin nothing.
5
+ **Checked before cutting.** All reads are on main at 8ba7024d (v9.73.0).
6
+ - **Alternates re-read against the code.**
7
+ - **A1 (BACKLOG 108) is real.** `create_session_pr`'s `LOKI_AUTO_PR=1` branch calls `_loki_trusted_push` and never reads `.loki/state/agent-committed-user-files.z`. The only references to that file are the writer comment and the writer itself, inside `_loki_untrack_agent_committed_user_files`.
8
+ - **A2 (BACKLOG 17) is real.** The "Notify dashboard of active project directory" block, about 24477 today, posts to `/api/focus` behind `command -v curl` only. It has no `ENABLE_DASHBOARD` check.
9
+ - **A3 is real and larger than the card says.** run.sh 211 and 239 always set PROJECT_DIR to the Loki install root. So the BACKLOG 127 "guard when unset" would do nothing. The actual defect is that `council_managed_should_stop` runs `git diff --stat` in Loki's own tree, not the target project. Its three readers are still bare `python3 -E`, and p2-honest-verdict.sh (about 858) says so.
10
+ - **A4 (BACKLOG 51) is real.** `grep -c PYTHONUSERBASE autonomy/loki` prints 0. The NOT CHECKED text says "Install python3 cryptography" even to a user who installed it through PYTHONPATH or PYTHONUSERBASE, which `-E` ignores.
11
+ - **A5 is split.**
12
+ - BACKLOG 145 sits in the Array.from generator arm, about 1934-1994. That does not overlap S-180's helper-return arm (about 2081-2170).
13
+ - BACKLOG 147 edits `HELPER_LOCAL_DECL_TMPL`, which is in S-180's region, so it is held.
14
+ - **New class found: every `-E`-only verdict reader outside completion-council.sh (BACKLOG 53 and 54).** These are:
15
+ - autonomy/lib/done-recognition.sh: 16 sites.
16
+ - autonomy/council-v2.sh: 7 sites.
17
+ - autonomy/lib/voter-agents.sh: 3 sites.
18
+ - autonomy/lib/proof-check.sh: 3 sites.
19
+ - autonomy/prd-checklist.sh: about 11 sites.
20
+ - loki-ts/src/commands/proof.ts:606, the Bun `loki proof verify` path.
22
21
 
23
- ### S-174: run_test with a missing or empty argument stops run-all-tests.sh with no summary
24
- - Files: tests/run-all-tests.sh (the run_test guard and the missing-script return only), tests/test-run-all-missing-arg.sh (new)
25
- - Tier: MEDIUM. **Captain-built**, because tests/run-all-tests.sh is a hot file. The Captain also registers the new test.
26
- - Red:
27
- - `run_test "X"` stops the runner with `$2: unbound variable`. There is no summary and every later suite is skipped.
28
- - `run_test "X" ""` passes today: `bash -c ""` exits 0.
29
- - A missing script returns 1, and under `set -e` that stops the run.
30
- - Green:
31
- - Guard on `$# -lt 2` or an empty `$2`.
32
- - Place it after `_shard_index` increments and before the shard skip, so LPT slots do not shift and every shard reports the fault.
33
- - Print the name and the line number from `${BASH_LINENO[0]}` to stderr. The line must contain the word FAILED, so the LOKI_TEST_LIST output stays clean and the local-ci scraper still matches.
34
- - Increment TOTAL_FAILED and return 0.
35
- - Change the missing-script branch to count the failure and return 0.
36
- - The test pulls the real run_test out of run-all-tests.sh with sed; it does not copy it. It drives three legs: one argument, an empty argument, and a missing script. A stub registered after each bad line must still run.
37
- - Wall: `bash tests/test-run-all-missing-arg.sh` exits 0.
38
- - Each leg prints Failed: 1, and the stub's PASSED line appears after the bad line.
39
- - A scratch copy with the guard removed exits 1.
40
- - `bash tests/test-run-all-dispatch.sh` and `LOKI_TEST_LIST=1 bash tests/test-shard-coverage.sh` both exit 0.
22
+ All of them run PATH `python3 -E`. BACKLOG 134 showed that a user-site `.pth` still loads under `-E`.
41
23
 
42
- ### S-175: a LOKI_MONOREPO_TEST_CMD rejected by the whitelist records pass true (BACKLOG 62)
43
- - Files: autonomy/run.sh (the enforce_test_coverage `monorepo-custom-rejected` branch, ~13877, only), tests/test-monorepo-rejected-cmd-inconclusive.sh (new)
44
- - Tier: HIGH
45
- - Red: the rejected branch sets `test_runner=monorepo-custom-rejected` but leaves `test_passed=true`. It skips the `none` path at ~14140, so the record reads pass true and unit-tests.pass is touched.
46
- - **Gate:** the builder must first reproduce pass true plus unit-tests.pass. If that does not reproduce, close the slice as already handled.
47
- - Green: route the rejected command through the same no-runner record as the `none` path.
48
- - `pass:"inconclusive"`, `status:"not_run"`, no unit-tests.pass, `.test-results.iter` stamped, and `_LOKI_TEST_SUITE_STATUS=not_run`.
49
- - Wall: `bash tests/test-monorepo-rejected-cmd-inconclusive.sh` exits 0.
50
- - Fixture: a workspaces monorepo with `LOKI_MONOREPO_TEST_CMD='npm test; true'`.
51
- - Reverting the branch exits 1.
52
- - `bash tests/test-trust-core-tests-detect.sh` exits 0.
53
- - This is the only run.sh row in this cut.
24
+ On `-S` compatibility:
25
+ - The imports I read are stdlib only: swarm/sycophancy.py, autonomy/checklist-verify.py, and autonomy/lib/proof-verify.py (which adds its own directory to sys.path at line 76). So `-I -S` should hold for those.
26
+ - Each builder still audits the imports of the rest of its sites, including the prd-checklist oracle heredoc.
54
27
 
55
- ### S-176: the proof headline reads a stale test-results.json (BACKLOG 98, headline half)
56
- - Files: autonomy/lib/proof-generator.py (`_collect_tests` only), tests/test_proof_tests_freshness.py (new)
57
- - Tier: HIGH
58
- - Red: `_test_results_fresh` (322) gates only `_collect_quality_gates` (381). `_collect_tests` (893) feeds facts.tests and the headline, and has no freshness check.
59
- - Green: when the file is stale, `_collect_tests` returns status not_run. `ITERATION_COUNT` unset keeps the existing reading, matching the helper's ponytail note.
60
- - Wall: `python3 -m pytest -q tests/test_proof_tests_freshness.py` passes.
61
- - ITERATION_COUNT=5 with marker 4: facts.tests.status is not_run, and honesty.headline differs from what the fresh case produces.
62
- - Marker 5 keeps status verified.
63
- - Removing the check fails the stale case.
28
+ Existing tests source each of these files on their own, so each file needs the guarded helper copy. For voter-agents.sh, `.` at completion-council.sh 4245 sources it into the parent shell.
29
+ - **council-v2 fails open on sycophancy.** A detector crash yields `0.000`, then `should_challenge=no`. A unanimous approve then skips the devil's advocate.
30
+ - **Cockpit remainder (BACKLOG 114).**
31
+ - `FinalActions` receives `git=null` after a failed status fetch (the `settle` fallback) and still says "The working tree is clean" and "Nothing to push".
32
+ - A failed `getStatus` (the swallow at useCockpitState.ts:202) makes Pause, Resume and Stop read "No run in progress".
33
+ - A failed `getChecklist` (the swallow at 204) renders "No gate results recorded."
34
+ - **Already handled, so dropped:**
35
+ - BACKLOG 31: proof-verify maps unverifiable drift to 2.
36
+ - BACKLOG 38: `no_pass_recorded`.
37
+ - BACKLOG 49: the `--jwks` output is patched.
38
+ - BACKLOG 16 and 85: `PYTHONDONTWRITEBYTECODE` in `enforce_test_coverage`, plus the py_compile rewrite.
39
+ - BACKLOG 133: `PULSE_MOAT_RESULT` carries a `.sha` sidecar.
40
+ - BACKLOG 140: the environment-variables.md row names all four tokens and both routes.
41
+ - BACKLOG 13: release.sh bumps INSTALLATION.md at 320.
42
+ - BACKLOG 22: the resource monitor backgrounds its sleep.
43
+ - BACKLOG 26: test-bun-parity-disk-tolerance.sh.
44
+ - The unreadable-waivers banner in loki-checklist-viewer is already pinned in loki-unmeasured-panels-honesty.node.test.mjs:319.
45
+ - The GitPanel badge on a null fetch renders nothing.
46
+ - PhaseVisualizer: its only caller passes 'idle'.
47
+ - **Dropped on merit: BACKLOG 69 (snapshot hash size cap).**
48
+ - A size-plus-mtime fingerprint is spoofable, which weakens `preexisting_modified`.
49
+ - It changes the sealed `.sha.z` entries.
50
+ - Nobody has measured the stall.
64
51
 
65
- ### S-177: the Bun npm fallback reads an exit-0 run that prints failures as passed (BACKLOG 98, Bun half)
66
- - Files: loki-ts/src/runner/quality_gates.ts (the `runTestCoverage` npm fallback, ~561-576, only), loki-ts/tests/runner/npm_fallback_summary_failures.test.ts (new)
67
- - Tier: HIGH
68
- - Red: `npm test` exits 0 while printing "Tests: 1 failed, 2 passed", and the fallback returns `passed: true`.
69
- - Green: mirror the bash summary parser (run.sh `_tr_failed_n` awk, ~14268): jest Tests and Test Suites lines, the vitest Test Files line, pytest failed plus errors, mocha failing, and node TAP. Any count above 0 returns passed false.
70
- - Wall: `cd loki-ts && bun test tests/runner/npm_fallback_summary_failures.test.ts` exits 0.
71
- - The three failure shapes (jest, vitest, pytest "1 passed, 1 error") return passed false.
72
- - "Tests: 3 passed" returns passed true.
73
- - Removing the parse fails the three failure legs.
74
- - The Captain rebuilds loki-ts/dist/loki.js.
52
+ ### S-194: LOKI_AUTO_PR pushes a branch whose history still holds user files (BACKLOG 108, A1)
53
+ - Files:
54
+ - autonomy/run.sh: `create_session_pr` only, from its head to the `_loki_trusted_push` call. Anchor on the function name, because S-175 shifts line numbers when it merges.
55
+ - tests/test-auto-pr-agent-committed-refuse.sh (new)
56
+ - Tier: HIGH (secret exposure)
57
+ - Region: this does not overlap S-175 (`enforce_test_coverage`) or S-195 (the focus notify block).
58
+ - Red:
59
+ - With a non-empty agent-committed-user-files.z and `LOKI_AUTO_PR=1`, the stubbed `_loki_trusted_push` gets called.
60
+ - The advisory path prints `git push -u` advice with no cleanup step.
61
+ - Green:
62
+ - When the record is non-empty:
63
+ - Recompute the fork the way `_loki_untrack_agent_committed_user_files` does: the merge base with base-branch.txt, else session-start-sha.
64
+ - Print `git reset --soft <fork> && git commit` before any push advice.
65
+ - Under `LOKI_AUTO_PR=1`, refuse the push: `log_warn` naming the files, and return 1.
66
+ - An empty or absent record leaves both paths byte-identical to today.
67
+ - Gate: the builder first reproduces the stub push call on main. If it does not reproduce, the slice closes as handled.
68
+ - Test rule: `cd` to scratch before sourcing run.sh, and assert that no `.loki/state/provider` appears in the repo (BACKLOG 126).
69
+ - Wall: `bash tests/test-auto-pr-agent-committed-refuse.sh` exits 0. Its legs:
70
+ - Auto path with a record: no push, rc 1, and the cleanup line printed.
71
+ - Advisory path with a record: the cleanup line appears before `git push -u`.
72
+ - Empty record: the push happens.
73
+ - Removing the record read in a scratch copy fails the first leg.
74
+ - `bash tests/test-trusted-push-agent-config.sh` exits 0.
75
75
 
76
- ### S-178: `/api/cost` treats context-tracker tokens without a USD figure as a measured $0 (BACKLOG 112)
77
- - Files: dashboard/server.py (the get_cost context-tracker fallback, ~7925-7950, only), tests/dashboard/test_cost_tracker_fallback_unmeasured.py (new)
76
+ ### S-195: the /api/focus POST fires with the dashboard disabled (BACKLOG 17, A2)
77
+ - Files:
78
+ - autonomy/run.sh: the "Notify dashboard of active project directory" block only.
79
+ - tests/test-focus-post-dashboard-off.sh (new)
78
80
  - Tier: MEDIUM
79
- - Red: tokens greater than 0 set `cost_recorded = True` and `estimated_cost = totals.get("total_cost_usd", 0.0)`. The model defaults to "sonnet" when the provider is absent.
81
+ - Region: this does not overlap S-175 or S-194.
82
+ - Red: with `ENABLE_DASHBOARD=false`, a curl shim on PATH records one POST to `/api/focus`.
80
83
  - Green:
81
- - Tokens count as measured, and cost is null unless total_cost_usd is a number. A recorded 0.0 stays 0.0.
82
- - The model is `unknown` when there is no provider.
83
- - Wall: `python3 -m pytest -q tests/dashboard/test_cost_tracker_fallback_unmeasured.py` passes, and reverting fails the first case.
84
- - `bash tests/moat/p7-no-fabricated-data.sh` prints `CASE P7.unmeasured-cost-never-zero PASS`.
85
- - This is the only dashboard/server.py row.
84
+ - Guard on the runtime `ENABLE_DASHBOARD`, which run.sh sets false at about 19288. Do not guard on `LOKI_DASHBOARD`.
85
+ - Test: extract the block by its comment anchor, as test-autocapture-shadow-write-guard.sh does. No full run.sh source.
86
+ - Wall: `bash tests/test-focus-post-dashboard-off.sh` exits 0.
87
+ - false: the shim log is empty.
88
+ - true: exactly one POST.
89
+ - Removing the guard in a scratch copy fails the false leg.
86
90
 
87
- ### S-179: `loki cost` puts 0.0 in place of unknown spend (BACKLOG 106, bash half)
88
- - Files: autonomy/loki (`cmd_cost`, 28196, only), tests/test-loki-cost-unmeasured.sh (new)
89
- - Tier: MEDIUM
91
+ ### S-196: council_managed_should_stop reads Loki's install tree for its diff and runs -E readers (A3)
92
+ - Files:
93
+ - autonomy/completion-council.sh: `council_managed_should_stop` only.
94
+ - tests/moat/p2-honest-verdict.sh: `case_council_readers_no_user_site_pth`, plus the about-858 comment in `case_council_readers_not_shadowed`.
95
+ - tests/test-council-managed-diff-target.sh (new)
96
+ - Tier: HIGH (moat)
90
97
  - Red:
91
- - `else: budget_used = 0.0` (~28452) contradicts its own comment.
92
- - budget.json always carries `budget_used`, because run.sh check_budget_limit writes it, so a recorded 0 carries no "measured" signal.
93
- - Green: used and percent are null, and the text reads "not recorded", when no efficiency record is measured. Mirror the dashboard's `_record_is_measured` (server.py 7768) or S-131's Bun rule; the builder names which.
94
- - Wall: `bash tests/test-loki-cost-unmeasured.sh` exits 0.
95
- - A cap of 10 with no measured records: `--json` budget used null, percent null.
96
- - Measured 2.50: 2.5 and 25.0.
97
- - Reverting fails the first leg.
98
- - This is the only autonomy/loki row.
98
+ - A stub `providers.managed` records `_CC_DIFF`. It shows install-tree paths, not the target project's change.
99
+ - A planted user-site `.pth` forges the test_summary read.
100
+ - Green:
101
+ - `diff_summary` comes from `${TARGET_DIR:-.}`, the same root as `loki_dir` and `LOKI_TARGET_DIR`.
102
+ - The two inline readers and the heredoc run through `_loki_snapshot_py_tool -I -S`.
103
+ - If no interpreter resolves, test_summary is empty, pending is `[]`, and the function returns 1 (the Bash voting fallback). It never returns 0.
104
+ - The new leg lands in the same commit as the fix, because the case is already proven.
105
+ - Gate: reproduce the install-tree diff with the stub first. Reuse S-173's stub.
106
+ - Wall:
107
+ - `bash tests/moat/p2-honest-verdict.sh` prints `CASE P2.council-readers-no-user-site-pth PASS` and `CASE P2.council-readers-not-shadowed PASS`.
108
+ - `bash tests/test-council-managed-diff-target.sh` exits 0: a file changed only in the target appears in `_CC_DIFF`.
109
+ - Reverting the readers to `python3 -E` in a scratch copy makes the pth case FAIL.
110
+ - `bash tests/moat/run.sh` reports no rule failed.
99
111
 
100
- ### S-180: the P7 helper-return arm misses class methods (BACKLOG 144)
101
- - Files: tests/moat/p7-no-fabricated-data.sh (the helper-return arm only)
112
+ ### S-197: the NOT CHECKED text should name PYTHONPATH and PYTHONUSERBASE (BACKLOG 51, A4)
113
+ - Files:
114
+ - autonomy/loki:
115
+ - `loki_remote_verify_receipt`'s attestation NOT CHECKED branch only.
116
+ - `cmd_proof verify`'s `--jwks` NOT CHECKED echo only.
117
+ - tests/test-proof-verify-jwks.sh (case 4 only)
118
+ - Tier: LOW
119
+ - Region: this does not overlap S-179 (`cmd_cost`).
120
+ - Green:
121
+ - Both messages add that the verifier runs `python3 -E`, so cryptography supplied through PYTHONPATH or PYTHONUSERBASE is not seen.
122
+ - Exit codes are unchanged.
123
+ - Wall:
124
+ - `bash tests/test-proof-verify-jwks.sh` exits 0, and case 4 asserts that the NOT CHECKED output names PYTHONUSERBASE.
125
+ - `grep -c PYTHONUSERBASE autonomy/loki` prints 2 or more (0 today).
126
+ - `bash tests/test-remote-attestation-verdict.sh` exits 0.
127
+
128
+ ### S-198: the P7 Array.from arm loses an outer generator's index when generators nest (BACKLOG 145, A5)
129
+ - Files: tests/moat/p7-no-fabricated-data.sh. Only two regions:
130
+ - the Array.from generator arm, about 1934-1994;
131
+ - one fixture beside the B-8 fixture, about 3301.
102
132
  - Tier: HIGH (moat)
103
- - Red: `_getRows() { return [{id:1,user:'Admin'}]; } ... this._rows = this._getRows();` is caught by no rule.
104
- - **Branch:** run the widened arm against main first.
105
- - On any live hit in dashboard-ui or web-app, the slice becomes report-only. List the hits and let the Captain decide. Never add an allowlist to make it pass.
106
- - cases.txt stays unchanged: no new case ID.
107
- - Wall: `bash tests/moat/p7-no-fabricated-data.sh` prints PASS for every P7 case.
108
- - An in-script planted class-method fixture is flagged.
109
- - Removing the method-head pattern lets that fixture through.
133
+ - Region: this does not overlap S-180's helper-return arm. Do not append fixtures at the file tail.
134
+ - Red: `Array.from({length:2}, (_, r) => Array.from({length:2}, (_, c) => ({ id: r, user: 'Admin' })))` goes through.
135
+ - Green: substitute the enclosing generator's params as well as the inner ones.
136
+ - Branch: run the widened arm on main first.
137
+ - On any live hit in dashboard-ui or web-app, the slice becomes report-only.
138
+ - Never add an allowlist.
139
+ - cases.txt stays unchanged.
140
+ - Wall:
141
+ - `bash tests/moat/p7-no-fabricated-data.sh` prints PASS for every P7 case, and the nested fixture is flagged.
142
+ - Removing the outer substitution lets the fixture through.
110
143
 
111
- ### S-181: GUARDS 11, glob rm in a shared root
112
- - Files: scripts/v10-guard.sh (the Rule 4 region only), tests/test-v10-guard.sh, docs/v10/GUARDS.md (section 11 guard and test lines only)
113
- - Tier: MEDIUM
114
- - Red: Rule 4 checks only recursive plus force rm. `rm -f /tmp/*.log` and an `rm -f` glob in the scratchpad root both go through.
144
+ ### S-199: the py-tool identity test covers every guarded copy
145
+ - Files: tests/test-council-py-tool-identity.sh
146
+ - Tier: LOW
115
147
  - Green:
116
- - Block any rm with a glob target whose literal parent is exactly /tmp, /private/tmp, $TMPDIR, or a directory named `scratchpad`.
117
- - Allow globs one level below such a root.
118
- - Where the parent is an unexpanded variable, allow it, and leave a ponytail comment that names this limit.
119
- - Wall: `bash tests/test-v10-guard.sh` exits 0.
120
- - New cases: `rm -f /tmp/*.log` blocked, `rm -f <scratchpad>/*` blocked, `rm -f /tmp/run-1/*.log` allowed.
121
- - Dropping the new rule fails the blocked cases.
148
+ - Compare every `^_loki_snapshot_py_tool() {` body found by `git grep -l` under autonomy/ against run.sh's.
149
+ - Vacuity guard: at least one copy besides run.sh, and each body at least 10 lines.
150
+ - This is the only row that edits this file. S-200 to S-204 add copies and rely on it.
151
+ - Wall:
152
+ - `bash tests/test-council-py-tool-identity.sh` exits 0 and prints the number of copies compared.
153
+ - A one-byte change to completion-council.sh's copy in a scratch tree exits 1.
122
154
 
123
- ### S-182: docs/exit-codes.md does not mention the verify codes that are pending
124
- - Files: docs/exit-codes.md (the `loki verify` section only)
125
- - Tier: LOW
155
+ ### S-200: done-recognition readers load user-site .pth (BACKLOG 54)
156
+ - Files:
157
+ - autonomy/lib/done-recognition.sh: every python3 site, plus a guarded helper copy.
158
+ - tests/test-done-recognition-no-user-site-pth.sh (new)
159
+ - Tier: HIGH
160
+ - Red: a user-site `.pth` under a scratch HOME changes the verdict read (the about-703 site).
161
+ - Green:
162
+ - All sites run through `_loki_snapshot_py_tool -I -S`.
163
+ - The builder lists each site's result when no interpreter resolves. None of them may read as done or met.
164
+ - Add a byte-identical guarded copy.
165
+ - Gate: reproduce the forged read on main first.
166
+ - Wall:
167
+ - `bash tests/test-done-recognition-no-user-site-pth.sh` exits 0.
168
+ - Reverting one site to `-E` in a scratch copy fails it.
169
+ - `bash tests/test-done-recognition-tests-axis.sh` and `bash tests/test-reuse-done-recognition.sh` exit 0.
170
+
171
+ ### S-201: council-v2 readers load .pth, and a crashed sycophancy check skips the devil's advocate (BACKLOG 54)
172
+ - Files:
173
+ - autonomy/council-v2.sh: its 7 python3 sites and the Step 4 and 5 fallbacks, plus a guarded helper copy.
174
+ - tests/test-council-v2-no-user-site-pth.sh (new)
175
+ - Tier: MEDIUM. The path is opt-in through `LOKI_COUNCIL_VERSION=2`.
126
176
  - Red:
127
- - The section says code 3 "never silently passes".
128
- - `loki verify --fast` (autonomy/loki 18513, which calls fast_verify.py) exits 0 on INCONCLUSIVE and ignores unknown flags.
129
- - Both cases are pending at v10.0.0.
177
+ - A `.pth` forges a vote read.
178
+ - A detector failure yields `0.000`, so a unanimous approve never challenges.
130
179
  - Green:
131
- - Add a "Known gaps until v10.0.0" note. It gives the codes the builder measures on this checkout for four inputs: an empty diff, a non-git directory, an unknown flag, and `--fast` with nothing scanned.
132
- - It names both pending case IDs, and tells users to check stdout for INCONCLUSIVE under `--fast`.
133
- - Wall: `bash tests/test-exit-codes-documented.sh` exits 0.
134
- - `grep -n 'P2.fast-verify-inconclusive-not-zero' docs/exit-codes.md` prints one line.
135
- - The four measured codes are in the builder's report, each with its command.
180
+ - `-I -S` on every site.
181
+ - An unmeasured sycophancy score on a unanimous approve runs the devil's advocate. A resolver failure never yields "no challenge".
182
+ - Gate: reproduce both on main first.
183
+ - Wall:
184
+ - `bash tests/test-council-v2-no-user-site-pth.sh` exits 0, covering the `.pth` leg and the detector-failure leg.
185
+ - Reverting either change fails its leg.
186
+ - `bash tests/test-council-v2-quorum.sh` exits 0.
136
187
 
137
- ### S-183: the migration dashboard renders a failed load as "No migration data available" (BACKLOG 114)
138
- - Files: dashboard-ui/components/loki-migration-dashboard.js (the error render branch, ~599-610, only), dashboard-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs (new)
139
- - Tier: LOW
140
- - Wall: `node --test dashboard-ui/tests/loki-migration-dashboard-fetch-error.node.test.mjs` passes.
141
- - A rejected fetch renders "Could not load migrations" plus the message, and not the empty-state sentence.
142
- - A real empty list still renders "No migrations found".
143
- - The Captain rebuilds dashboard/static/index.html.
188
+ ### S-202: voter-agents readers load user-site .pth (BACKLOG 54)
189
+ - Files:
190
+ - autonomy/lib/voter-agents.sh: its 3 python3 sites, plus a guarded helper copy.
191
+ - tests/test-voter-agents-no-user-site-pth.sh (new)
192
+ - Tier: HIGH
193
+ - Red: a `.pth` changes a parsed voter verdict.
194
+ - Green: `-I -S`. With no interpreter, the dispatch fails, so completion-council's existing fail-closed CONTINUE applies.
195
+ - Gate: reproduce the changed verdict on main first.
196
+ - Wall:
197
+ - `bash tests/test-voter-agents-no-user-site-pth.sh` exits 0, and reverting fails it.
198
+ - `bash tests/test-voter-agents-json.sh` and `bash tests/test-sdk-voter-agents.sh` exit 0.
144
199
 
145
- ### S-184: the managed memory panel ignores a 200 response carrying an error (BACKLOG 114)
146
- - Files: dashboard-ui/components/loki-managed-memory-panel.js (the events load only), dashboard-ui/tests/loki-managed-memory-events-error.node.test.mjs (new)
147
- - Tier: LOW
148
- - Red: server.py ~12145 returns `{"events": [], "count": 0, "error": ...}`, and the panel renders "No managed memory events recorded yet."
149
- - Wall: `node --test dashboard-ui/tests/loki-managed-memory-events-error.node.test.mjs` passes.
150
- - The error payload renders the error line, and not the empty sentence.
151
- - `{events:[],count:0}` still renders the empty sentence.
152
- - The Captain rebuilds dashboard/static/index.html.
200
+ ### S-203: proof-check readers load user-site .pth (BACKLOG 54)
201
+ - Files:
202
+ - autonomy/lib/proof-check.sh: its 3 heredoc readers, plus a guarded helper copy.
203
+ - tests/test-proof-check-no-user-site-pth.sh (new)
204
+ - Tier: MEDIUM
205
+ - Red: a `.pth` forges the headline read.
206
+ - Green: `-I -S`. With no interpreter, the readers print empty, as they do today when python3 is absent.
207
+ - Gate: reproduce the forged headline on main first.
208
+ - Wall:
209
+ - `bash tests/test-proof-check-no-user-site-pth.sh` exits 0, and reverting fails it.
210
+ - `bash tests/test-proven-pr-check.sh` exits 0.
153
211
 
154
- ### S-185: DeployConnections shows "Not connected" rows under its own load error (BACKLOG 114, rendering only)
155
- - Files: web-app/src/components/DeployConnections.tsx (the row status render only), web-app/src/components/DeployConnections.state.test.mjs (new)
156
- - Tier: LOW
157
- - Scope: after a failed fetch, the rows read unknown instead of "Not connected", the same shape as S-170.
158
- - The upward onStatusChange push of the defaults is BACKLOG 121 and stays held.
159
- - Wall: `node --test web-app/src/components/DeployConnections.state.test.mjs` passes.
160
- - After a failed fetch, no row reads "Not connected".
161
- - A real `{connected:false}` still does.
162
- - `cd web-app && npx tsc -b` exits 0.
163
- - The Captain rebuilds web-app/dist.
212
+ ### S-204: checklist verification loads user-site .pth (BACKLOG 53)
213
+ - Files:
214
+ - autonomy/prd-checklist.sh: every python3 site, including the checklist-verify.py call and the oracle heredoc, plus a guarded helper copy.
215
+ - tests/test-prd-checklist-no-user-site-pth.sh (new)
216
+ - Tier: HIGH
217
+ - Red: a `.pth` changes the status_token or the waiver read.
218
+ - Green:
219
+ - `-I -S`. The builder audits the oracle heredoc's imports first.
220
+ - Any site that needs a non-stdlib module stays `-E` with a ponytail note.
221
+ - Resolver failure: the builder lists each site's result. None reads as verified.
222
+ - Gate: reproduce the changed read on main first.
223
+ - Wall:
224
+ - `bash tests/test-prd-checklist-no-user-site-pth.sh` exits 0, and reverting fails it.
225
+ - `bash tests/moat/p2-honest-verdict.sh` prints `CASE P2.checklist-verify-not-shadowed PASS`.
226
+ - `bash tests/test-prd-checklist-interval-w4.sh` exits 0.
227
+
228
+ ### S-205: Bun loki proof verify runs a PATH python3 -E (BACKLOG 48 class, Bun half)
229
+ - Files:
230
+ - loki-ts/src/commands/proof.ts: the verifier spawn only.
231
+ - loki-ts/src/util/python.ts, only to extend the helper that already exists there.
232
+ - loki-ts/tests/commands/proof_verify_interpreter.test.ts (new)
233
+ - Tier: HIGH
234
+ - Red: a user-site `.pth` under a scratch HOME changes verify output, or writes a marker.
235
+ - Green:
236
+ - Resolve like `_loki_snapshot_py_tool`: /usr/bin/python3 and /bin/python3 first, then absolute PATH dirs, each probed with `-I -S -c ''`. Run with `-I -S`.
237
+ - If none resolves, exit 2 as NOT CHECKED.
238
+ - Gate: reproduce the `.pth` effect on main first.
239
+ - Wall:
240
+ - `cd loki-ts && bun test tests/commands/proof_verify_interpreter.test.ts tests/commands/proof_verify_parity.test.ts` exits 0.
241
+ - Reverting to `["python3","-E"]` fails the new test.
242
+ - The Captain rebuilds loki-ts/dist.
164
243
 
165
- ### S-186: the issue list's comment count never shows (BACKLOG 116)
166
- - Files: web-app/src/components/GitHubIssuesPanel.tsx (the list comment badge only), web-app/src/types/api.ts (GitHubIssue.comments only), web-app/src/components/GitHubIssuesPanel.comments.test.mjs (new)
244
+ ### S-206: cockpit actions say "working tree is clean" and "no run in progress" after a failed fetch (BACKLOG 114)
245
+ - Files:
246
+ - web-app/src/cockpit/FinalActions.tsx (disabled reasons only)
247
+ - web-app/src/cockpit/FinalActions.reasons.test.mjs (new)
167
248
  - Tier: LOW
168
- - Red: web-app/server.py 7297 asks gh for `comments`, which gh returns as an array. `issue.comments > 0` is then always false.
169
- - Wall: `node --test web-app/src/components/GitHubIssuesPanel.comments.test.mjs` passes.
170
- - An array of 2 renders 2, and a number 3 renders 3.
249
+ - Green:
250
+ - Export a pure reasons function.
251
+ - `git === null`: commit, push and PR read "Working tree status not loaded".
252
+ - `status === null`: pause, resume and stop read "Run status not loaded".
253
+ - Real data keeps today's copy.
254
+ - Wall:
255
+ - `node --test web-app/src/cockpit/FinalActions.reasons.test.mjs` passes:
256
+ - git null lacks "The working tree is clean" and "Nothing to push";
257
+ - status null lacks "No run in progress";
258
+ - `{ahead:0}` with no files keeps both sentences.
171
259
  - `cd web-app && npx tsc -b` exits 0.
172
260
  - The Captain rebuilds web-app/dist.
173
261
 
174
- ### S-187: CostEstimator uses the whole iteration cap as its estimate (BACKLOG 118)
175
- - Files: web-app/src/components/ProjectWorkspace.tsx (the CostEstimator props, ~2482, only), web-app/src/components/CostEstimator.tsx (export estimateCosts only if needed), web-app/src/components/CostEstimator.estimate.test.mjs (new)
262
+ ### S-207: cockpit evidence says "No gate results recorded" when the checklist request failed (BACKLOG 114)
263
+ - Files:
264
+ - web-app/src/cockpit/useCockpitState.ts: `getChecklist` through `settle`, plus a `checklistError` field.
265
+ - web-app/src/cockpit/EvidencePanel.tsx (empty branch only)
266
+ - web-app/src/cockpit/ExecutionCockpit.tsx (EvidencePanel props only)
267
+ - web-app/src/cockpit/EvidencePanel.state.test.mjs (new)
176
268
  - Tier: LOW
177
- - Red: `estimatedIterations={buildStatus.maxIterations ?? 0}`, so a cap of 1000 is priced as 1000 iterations.
178
- - Wall: `node --test web-app/src/components/CostEstimator.estimate.test.mjs` passes.
179
- - A cap of 1000 does not change the estimate from the complexity default.
180
- - `grep -n 'estimatedIterations={buildStatus.maxIterations' web-app/src/components/ProjectWorkspace.tsx` exits 1.
269
+ - Wall:
270
+ - `node --test web-app/src/cockpit/EvidencePanel.state.test.mjs` passes:
271
+ - an error renders "Could not load gate results" and not "No gate results recorded";
272
+ - `items:[]` with no error keeps that sentence.
273
+ - `node web-app/src/cockpit/run-derive-view-test.mjs` exits 0.
181
274
  - `cd web-app && npx tsc -b` exits 0.
182
275
  - The Captain rebuilds web-app/dist.
183
276
 
184
- ### S-188: no test of its own covers the overview proof card's verdict wording (BACKLOG 123, tests only)
185
- - Files: dashboard-ui/tests/loki-overview-proof-card.node.test.mjs (new)
186
- - Tier: LOW
187
- - Pins loki-overview.js 486-489:
188
- - With no proof, the card reads "Not evaluated".
189
- - With a headline, the meta starts with "Recorded, not re-verified here;".
190
- - gaps null reads "uncertainty not measured".
191
- - Wall: `node --test dashboard-ui/tests/loki-overview-proof-card.node.test.mjs` passes.
192
- - Deleting the recorded-copy prefix in a scratch copy fails it.
277
+ ### S-208: trust trajectory reads any non-pass council verdict as a failure (BACKLOG 118)
278
+ - Files:
279
+ - autonomy/lib/trust_trajectory.py (`_verdict_is_pass` only)
280
+ - tests/test_trust_trajectory_unknown_verdict.py (new)
281
+ - Tier: MEDIUM
282
+ - Red: a verdict such as "UNKNOWN" or "INCONCLUSIVE" maps to 0.0.
283
+ - Green:
284
+ - Only explicit fail tokens map to False. The builder enumerates them from completion-council.sh and proof-generator's writers.
285
+ - Anything else maps to None, meaning the axis has no data point.
286
+ - Gate: find a writer string that is neither pass nor fail. If none exists, close the slice as handled.
287
+ - Wall:
288
+ - `python3 -m pytest -q tests/test_trust_trajectory_unknown_verdict.py tests/test_trust_trajectory.py tests/dashboard/test_trust_trajectory_endpoint.py` passes.
289
+ - An unknown verdict adds no data point, and REJECTED still reads 0.0.
290
+ - Reverting fails the first case.
193
291
 
194
- ### S-189: the learning dashboard renders failed metrics and trends reads as no data (BACKLOG 114)
195
- - Files: dashboard-ui/components/loki-learning-dashboard.js (the metrics and trends load plus `_renderSummaryCards` and `_renderTrendChart` empty branches only), dashboard-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs (new)
196
- - Tier: LOW
197
- - Red: `.catch(() => null)` at 132 and 133 feeds "No metrics available" and "No trend data available".
198
- - Wall: `node --test dashboard-ui/tests/loki-learning-dashboard-fetch-error.node.test.mjs` passes.
199
- - Rejected metrics and trends render "Could not load".
200
- - A real empty trends response still renders "No trend data available".
201
- - `loki-learning-dashboard.test.js` is unaffected.
202
- - The Captain rebuilds dashboard/static/index.html.
292
+ ### S-209: Bun codex, cline and aider get the raw prompt without the commit-hygiene line (BACKLOG 99, Bun half)
293
+ - Files:
294
+ - loki-ts/src/runner/providers.ts: the codex, cline and aider invokers only.
295
+ - loki-ts/tests/runner/provider_commit_hygiene.test.ts (new)
296
+ - loki-ts/tests/runner/providers.test.ts, only where exact-argv assertions move.
297
+ - Tier: MEDIUM
298
+ - Green:
299
+ - Prefix the prompt with the hygiene line plus a blank line, matching the bash `"$PROVIDER_COMMIT_HYGIENE"$'\n\n'"$prompt"`.
300
+ - The test reads the literal from providers/codex.sh; it does not copy it.
301
+ - Wall:
302
+ - `cd loki-ts && bun test tests/runner/provider_commit_hygiene.test.ts tests/runner/providers.test.ts` exits 0.
303
+ - All three argvs carry the bash literal.
304
+ - Claude's prompt is not double-prefixed.
305
+ - Removing the prefix fails the three legs.
306
+ - The Captain rebuilds loki-ts/dist.
203
307
 
204
- ### S-190: the R3 design doc describes project_total_usd as a plain sum (BACKLOG 112 remainder)
205
- - Files: docs/R3-COST-OBSERVABILITY-DESIGN.md
308
+ ### S-210: speed up the two command-probe suites (29s and 30s in shard-durations.tsv)
309
+ - Files: tests/test-help-discoverability.sh, tests/test-completion-coverage.sh (the probe loops only)
206
310
  - Tier: LOW
207
- - Wall: `grep -n 'sum of per-run proof costs' docs/R3-COST-OBSERVABILITY-DESIGN.md` exits 1.
208
- - `grep -n 'project_total_partial' docs/R3-COST-OBSERVABILITY-DESIGN.md` prints at least one line.
209
- - The doc states null when no run is measured, citing dashboard/server.py 8384-8385.
210
-
211
- ### S-191: speed up test-review-assurance-tail.sh (116s in shard-durations.tsv)
212
- - Files: tests/test-review-assurance-tail.sh
213
- - Tier: MEDIUM
214
- - The builder captures the pre-change wall time and pass count under `LOKI_TEST_SHARD=0/8` first.
215
- - Then run independent cases concurrently, each in its own TMPROOT subdirectory.
216
- - Review budgets and timeout values stay unchanged.
217
- - Wall: `time LOKI_TEST_SHARD=0/8 bash tests/test-review-assurance-tail.sh` exits 0 with real time under 60s.
218
- - The pass-count line matches the pre-change capture.
311
+ - Change:
312
+ - The builder captures `real_count` and the pass and fail lines first.
313
+ - Then probe with `xargs -P 8`, each probe in its own scratch cwd, writing one result file per command.
314
+ - Keep the captured-output (never piped) rule noted in the file.
315
+ - Wall:
316
+ - `time bash tests/test-help-discoverability.sh` and `time bash tests/test-completion-coverage.sh` each exit 0 with real time under 10s.
317
+ - `real_count` and the pass counts match the pre-change capture.
219
318
  - The builder reports both timings.
220
319
 
221
- ### S-192: no test drives the web-app WebSocket status push payload (BACKLOG 112)
222
- - Files: web-app/tests/test_status_push_unmeasured.py (new), web-app/server.py (lift the nested status reader, ~6360-6425, to module level only if TestClient cannot drive it)
223
- - Tier: MEDIUM
224
- - Wall: `python3 -m pytest -q web-app/tests/test_status_push_unmeasured.py` passes.
225
- - dashboard-state.json with no tokens: the push has cost null and max_iterations null.
226
- - Priced tokens: cost is a number.
227
- - Forcing the reader to 0.0 in a scratch copy fails the first case.
320
+ ### S-211: register the four suites BACKLOG 75 still leaves unrun (after S-174 merges)
321
+ - Files: tests/run-all-tests.sh (four `run_test` lines only), tests/shard-durations.tsv (four lines)
322
+ - Tier: LOW. **Captain-built after S-174 merges.**
323
+ - Suites: tests/council/test_managed_completion_flag.sh, tests/council/test_managed_review_flag.sh, tests/test-evidence-gate-no-tests.sh, tests/test-voter-agents-json.sh.
324
+ - All four appear only in comments in run-all-tests.sh, so no runner executes them.
325
+ - The evidence-gate suite also appears in scripts/local-ci.sh, which is retired.
326
+ - Gate:
327
+ - Each suite passes 3 of 3 from a scratch cwd and leaves no `.loki/state/provider` in the repo.
328
+ - A suite that fails is reported, not registered, and becomes its own fix slice (the S-110 lesson).
329
+ - Wall:
330
+ - `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 (4 before registration).
331
+ - `bash tests/test-shard-coverage.sh` exits 0.
332
+
333
+ ### S-212: GUARDS 5, 12 and 13 still read PENDING after S-138, S-139 and S-154 landed (after S-181 merges)
334
+ - Files: docs/v10/GUARDS.md (sections 5, 12 and 13 only). This does not overlap S-181's section 11.
335
+ - Tier: LOW
336
+ - Green:
337
+ - Section 12 names tests/test-no-ambient-gitconfig-writes.sh (S-138).
338
+ - Section 13 names the RELEASED_AHEAD_OF_NPM case in tests/test-v10-pulse.sh (S-139). It states that this is a flag, not a refusal.
339
+ - Section 5 names tests/test-prune-worktrees.sh only if that test asserts the no-mtime rule. Otherwise it stays PENDING and says what would close it.
340
+ - Wall:
341
+ - `awk '/^## 12\./,0' docs/v10/GUARDS.md | grep -c 'PENDING, no slice cut'` prints 0.
342
+ - `bash tests/test-no-ambient-gitconfig-writes.sh` and `bash tests/test-v10-pulse.sh` exit 0.
228
343
 
229
- ### S-193: let a batch know its worktree budget before dispatch (TODO item 8)
230
- - Files: scripts/v10-ops.sh (a new worktree-budget subcommand), tests/test-v10-ops.sh
344
+ ### S-213: no test of their own covers the council-vote labels on cost.html and proofs.html (BACKLOG 123, tests only)
345
+ - Files: dashboard-ui/tests/static-council-vote-label.node.test.mjs (new)
231
346
  - Tier: LOW
232
- - Wall: `bash tests/test-v10-ops.sh` exits 0.
233
- - `scripts/v10-ops.sh worktree-budget 15` prints 15 minus the count of `.claude/worktrees` entries in `git worktree list --porcelain`.
234
- - At or over the cap it prints 0 and exits 1.
235
- - Fixtures use a scratch repo only.
347
+ - It pins:
348
+ - proofs.html: the badge reads "council " plus the verdict, with the title "Recorded council vote, not a verification result".
349
+ - cost.html: the runs header reads "Council vote".
350
+ - Wall:
351
+ - `node --test dashboard-ui/tests/static-council-vote-label.node.test.mjs` passes.
352
+ - Renaming the header, or dropping the title, in a scratch copy fails it.
236
353
 
237
354
  **Registration and rebuilds (Captain).**
238
355
  - New tests to register:
239
- - S-175, S-176, S-178, S-179, S-183 to S-189, S-192.
240
- - S-174 is registered by the Captain as part of building it.
356
+ - S-194 to S-198.
357
+ - S-200 to S-209.
358
+ - S-213.
241
359
  - Bundle rebuilds:
242
- - S-177: loki-ts/dist.
243
- - S-183, S-184, S-189: dashboard/static/index.html.
244
- - S-185 to S-187: web-app/dist.
360
+ - S-205 and S-209: loki-ts/dist.
361
+ - S-206 and S-207: web-app/dist.
362
+ - Sequencing:
363
+ - S-211 builds after S-174 merges.
364
+ - S-212 builds after S-181 merges.
365
+ - S-194 and S-195 are the only run.sh rows. They name regions that do not overlap each other or S-175, and merge one at a time.
245
366
 
246
- **Held, not in the 20 (alternates):**
247
- - **A1: BACKLOG 108**, HIGH. `create_session_pr` never reads agent-committed-user-files.z before a LOKI_AUTO_PR push. Its only reference is the writer at run.sh 10914. Cut it the moment S-175 merges, since it is also a run.sh change.
248
- - **A2: BACKLOG 17**, the `/api/focus` POST that fires with LOKI_DASHBOARD=false (run.sh 24481). After S-175.
249
- - **A3: council_managed_should_stop** `-I -S` plus the PROJECT_DIR guard, followed by S-173's `.pth` leg. After S-157.
250
- - **A4: BACKLOG 51**, the NOT CHECKED message should name PYTHONPATH and PYTHONUSERBASE (autonomy/loki ~1270). After S-179.
251
- - **A5: BACKLOG 145 and 147**, P7 arms. After S-180.
252
- - **Too large or held:**
253
- - P1.verification-metadata-signed (a seal.v1 format change).
254
- - The P2 verify renumber (CEO, v10.0.0).
255
- - BACKLOG 18, 52, 121, 123 (audit.py half).
256
- - S-112, S-114, S-115, S-117 to S-122.
367
+ **Held, not in the 20:**
368
+ - BACKLOG 147 (P7 useMemo composed form): wait for S-180.
369
+ - BACKLOG 36 (P7 zero-file scan): wait for S-180 and S-198.
370
+ - BACKLOG 19 (a stripped remote attestation reads UNSIGNED exit 0): same function as S-197, so wait for S-197.
371
+ - The bash `loki proof verify` interpreter (autonomy/loki `cmd_proof`, `python3 -E`): wait for S-179 and S-197.
372
+ - BACKLOG 99, bash half (run.sh main loop): wait for S-175, S-194 and S-195.
373
+ - workspace_diff reports count 0 in a non-git directory: needs a design, because the value lands in the receipt.
374
+ - dashboard/server.py items from BACKLOG 118: wait for S-178. They are:
375
+ - `/cost` pricing at Sonnet rates with no estimate label;
376
+ - council-state `total_votes: 0`;
377
+ - notifications zero summary;
378
+ - `StatusResponse` defaults;
379
+ - skill-session `running_agents: 0`.
380
+ - ProjectWorkspace phase labels and Replay Build: wait for S-187.
381
+ - Speeding up test-autocapture-shadow-write-guard.sh: its negative legs wait on a disowned process and need a design.
382
+ - Carried over: P1.verification-metadata-signed; the P2 verify renumber (CEO); BACKLOG 18, 28, 52, 121, and 123 (the audit.py half); S-112, S-114, S-115, S-117 to S-122.
257
383
 
258
- | S-174 | Guard: run_test with a missing or empty argument stops run-all-tests.sh with no summary and skips later suites | tests/run-all-tests.sh (run_test guard and missing-script return only), tests/test-run-all-missing-arg.sh (new) | MEDIUM | bash tests/test-run-all-missing-arg.sh exits 0 with Failed: 1 per leg (one-arg, empty-arg, missing-script) and the later stub's PASSED line printed; guard removed in a scratch copy exits 1; bash tests/test-run-all-dispatch.sh and LOKI_TEST_LIST=1 bash tests/test-shard-coverage.sh exit 0 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
259
- | S-175 | BACKLOG 62: a whitelist-rejected LOKI_MONOREPO_TEST_CMD records pass true and touches unit-tests.pass | autonomy/run.sh (enforce_test_coverage monorepo-custom-rejected branch only), tests/test-monorepo-rejected-cmd-inconclusive.sh (new) | HIGH | bash tests/test-monorepo-rejected-cmd-inconclusive.sh exits 0: pass is "inconclusive", status not_run, no unit-tests.pass; reverting the branch exits 1; bash tests/test-trust-core-tests-detect.sh exits 0 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
260
- | S-176 | BACKLOG 98: proof headline reads a stale test-results.json (_collect_tests has no .test-results.iter check) | autonomy/lib/proof-generator.py (_collect_tests only), tests/test_proof_tests_freshness.py (new) | HIGH | python3 -m pytest -q tests/test_proof_tests_freshness.py passes: ITERATION_COUNT=5 with marker 4 gives facts.tests.status not_run and a headline unlike the fresh case; marker 5 keeps the prior status; removing the check fails the stale case | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
261
- | S-177 | BACKLOG 98: Bun npm-test fallback reads an exit-0 run that prints failures as passed | loki-ts/src/runner/quality_gates.ts (runTestCoverage npm fallback only), loki-ts/tests/runner/npm_fallback_summary_failures.test.ts (new) | HIGH | cd loki-ts && bun test tests/runner/npm_fallback_summary_failures.test.ts exits 0: jest Tests 1 failed, vitest Test Files 1 failed and pytest 1 passed 1 error all return passed false; Tests 3 passed returns passed true; removing the parse fails the first three | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
262
- | S-178 | BACKLOG 112: /api/cost reads tracker tokens without a USD total as a measured $0 and labels the model sonnet | dashboard/server.py (get_cost context-tracker fallback only), tests/dashboard/test_cost_tracker_fallback_unmeasured.py (new) | MEDIUM | python3 -m pytest -q tests/dashboard/test_cost_tracker_fallback_unmeasured.py passes (tokens without total_cost_usd give cost null; recorded 0.0 stays 0.0; no provider gives model unknown); reverting fails case 1; bash tests/moat/p7-no-fabricated-data.sh prints CASE P7.unmeasured-cost-never-zero PASS | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
263
- | S-179 | BACKLOG 106: loki cost puts 0.0 in place of unknown spend | autonomy/loki (cmd_cost only), tests/test-loki-cost-unmeasured.sh (new) | MEDIUM | bash tests/test-loki-cost-unmeasured.sh exits 0: cap 10 with no measured records gives --json used null and percent null; measured 2.50 gives 2.5 and 25.0; reverting fails the first leg | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
264
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
265
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
266
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
267
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
268
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
269
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
270
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
271
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
272
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
273
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
274
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
275
- | S-191 | Velocity: test-review-assurance-tail.sh (116s) under 60s by running independent cases concurrently, budgets unchanged | tests/test-review-assurance-tail.sh | MEDIUM | time LOKI_TEST_SHARD=0/8 bash tests/test-review-assurance-tail.sh exits 0 with real under 60s and the same pass-count line as the pre-change capture; both timings reported | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
276
- | 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 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
277
- | S-193 | Velocity: v10-ops worktree-budget prints how many worktrees a batch may open before dispatch | scripts/v10-ops.sh (new worktree-budget subcommand), tests/test-v10-ops.sh | LOW | bash tests/test-v10-ops.sh exits 0; scripts/v10-ops.sh worktree-budget 15 prints 15 minus the .claude/worktrees entries in git worktree list --porcelain, and at or over the cap prints 0 and exits 1 | ready@2026-09-27T19:57Z | Source: 19:57Z cut. |
384
+ | S-194 | BACKLOG 108: LOKI_AUTO_PR pushes a branch whose history still holds user files | autonomy/run.sh (create_session_pr only; does not overlap S-175 or S-195), tests/test-auto-pr-agent-committed-refuse.sh (new) | HIGH | bash tests/test-auto-pr-agent-committed-refuse.sh exits 0: auto path with a record makes no push, returns 1 and prints git reset --soft; advisory path prints the cleanup before git push -u; empty record pushes; removing the record read in a scratch copy fails leg 1; bash tests/test-trusted-push-agent-config.sh exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
385
+ | S-195 | BACKLOG 17: /api/focus POST fires with the dashboard disabled | autonomy/run.sh (dashboard focus notify block only; does not overlap S-175 or S-194), tests/test-focus-post-dashboard-off.sh (new) | MEDIUM | bash tests/test-focus-post-dashboard-off.sh exits 0: ENABLE_DASHBOARD=false leaves the curl shim log empty, true records one POST; removing the guard in a scratch copy fails the false leg | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
386
+ | S-196 | council_managed_should_stop diffs Loki's install tree and runs -E readers | autonomy/completion-council.sh (council_managed_should_stop only), tests/moat/p2-honest-verdict.sh (case_council_readers_no_user_site_pth plus the ~858 comment), tests/test-council-managed-diff-target.sh (new) | HIGH | bash tests/moat/p2-honest-verdict.sh prints CASE P2.council-readers-no-user-site-pth PASS and CASE P2.council-readers-not-shadowed PASS; bash tests/test-council-managed-diff-target.sh exits 0 with the target-only file in _CC_DIFF; reverting the readers to -E makes the pth case FAIL; bash tests/moat/run.sh reports no rule failed | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
387
+ | S-197 | BACKLOG 51: NOT CHECKED text should name PYTHONPATH and PYTHONUSERBASE | autonomy/loki (loki_remote_verify_receipt attestation NOT CHECKED branch and cmd_proof --jwks NOT CHECKED echo only; does not overlap S-179), tests/test-proof-verify-jwks.sh (case 4 only) | LOW | bash tests/test-proof-verify-jwks.sh exits 0 with case 4 asserting PYTHONUSERBASE in the NOT CHECKED output; grep -c PYTHONUSERBASE autonomy/loki prints 2 or more; bash tests/test-remote-attestation-verdict.sh exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
388
+ | S-198 | BACKLOG 145: P7 Array.from arm loses an outer generator's index when generators nest | tests/moat/p7-no-fabricated-data.sh (Array.from generator arm ~1934-1994 and one fixture beside the B-8 fixture ~3301 only; does not overlap S-180) | HIGH | bash tests/moat/p7-no-fabricated-data.sh prints PASS for every P7 case and flags the nested fixture; removing the outer substitution lets it through; tests/moat/cases.txt unchanged | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
389
+ | S-199 | py-tool identity test covers every guarded _loki_snapshot_py_tool copy under autonomy/ | tests/test-council-py-tool-identity.sh | LOW | bash tests/test-council-py-tool-identity.sh exits 0 and prints the number of copies compared (at least 1 besides run.sh); a one-byte change to completion-council.sh's copy in a scratch tree exits 1 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
390
+ | S-200 | BACKLOG 54: done-recognition readers load user-site .pth (-E only) | autonomy/lib/done-recognition.sh (python3 sites plus guarded helper copy), tests/test-done-recognition-no-user-site-pth.sh (new) | HIGH | bash tests/test-done-recognition-no-user-site-pth.sh exits 0 and reverting one site to -E in a scratch copy fails it; bash tests/test-done-recognition-tests-axis.sh and bash tests/test-reuse-done-recognition.sh exit 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
391
+ | S-201 | BACKLOG 54: council-v2 readers load .pth; a crashed sycophancy check skips the devil's advocate | autonomy/council-v2.sh (python3 sites, Step 4 and 5 fallbacks, guarded helper copy), tests/test-council-v2-no-user-site-pth.sh (new) | MEDIUM | bash tests/test-council-v2-no-user-site-pth.sh exits 0 (pth leg and detector-failure leg run the devil's advocate on a unanimous approve); reverting either change fails its leg; bash tests/test-council-v2-quorum.sh exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
392
+ | S-202 | BACKLOG 54: voter-agents readers load user-site .pth (-E only) | autonomy/lib/voter-agents.sh (3 python3 sites plus guarded helper copy), tests/test-voter-agents-no-user-site-pth.sh (new) | HIGH | bash tests/test-voter-agents-no-user-site-pth.sh exits 0 and reverting fails it; bash tests/test-voter-agents-json.sh and bash tests/test-sdk-voter-agents.sh exit 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
393
+ | S-203 | BACKLOG 54: proof-check readers load user-site .pth (-E only) | autonomy/lib/proof-check.sh (3 heredoc readers plus guarded helper copy), tests/test-proof-check-no-user-site-pth.sh (new) | MEDIUM | bash tests/test-proof-check-no-user-site-pth.sh exits 0 and reverting fails it; bash tests/test-proven-pr-check.sh exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
394
+ | S-204 | BACKLOG 53: checklist verification loads user-site .pth (-E only) | autonomy/prd-checklist.sh (python3 sites incl. checklist-verify.py call and oracle heredoc, plus guarded helper copy), tests/test-prd-checklist-no-user-site-pth.sh (new) | HIGH | bash tests/test-prd-checklist-no-user-site-pth.sh exits 0 and reverting fails it; bash tests/moat/p2-honest-verdict.sh prints CASE P2.checklist-verify-not-shadowed PASS; bash tests/test-prd-checklist-interval-w4.sh exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
395
+ | S-205 | Bun loki proof verify runs a PATH python3 -E (user-site .pth reaches the verdict) | loki-ts/src/commands/proof.ts (verifier spawn only), loki-ts/src/util/python.ts (extend existing helper only if used), loki-ts/tests/commands/proof_verify_interpreter.test.ts (new) | HIGH | cd loki-ts && bun test tests/commands/proof_verify_interpreter.test.ts tests/commands/proof_verify_parity.test.ts exits 0; reverting to python3 -E fails the new test; no resolvable interpreter exits 2 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
396
+ | S-206 | BACKLOG 114: cockpit actions say working tree is clean and no run in progress after a failed fetch | web-app/src/cockpit/FinalActions.tsx (disabled reasons only), web-app/src/cockpit/FinalActions.reasons.test.mjs (new) | LOW | node --test web-app/src/cockpit/FinalActions.reasons.test.mjs passes: git null lacks The working tree is clean and Nothing to push, status null lacks No run in progress, real data keeps both; cd web-app && npx tsc -b exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
397
+ | S-207 | BACKLOG 114: cockpit evidence says No gate results recorded when the checklist request failed | web-app/src/cockpit/useCockpitState.ts (getChecklist via settle only), web-app/src/cockpit/EvidencePanel.tsx (empty branch only), web-app/src/cockpit/ExecutionCockpit.tsx (EvidencePanel props only), web-app/src/cockpit/EvidencePanel.state.test.mjs (new) | LOW | node --test web-app/src/cockpit/EvidencePanel.state.test.mjs passes: an error renders Could not load gate results, items [] keeps No gate results recorded; node web-app/src/cockpit/run-derive-view-test.mjs exits 0; cd web-app && npx tsc -b exits 0 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
398
+ | S-208 | BACKLOG 118: trust trajectory reads any non-pass council verdict as a failure | autonomy/lib/trust_trajectory.py (_verdict_is_pass only), tests/test_trust_trajectory_unknown_verdict.py (new) | MEDIUM | python3 -m pytest -q tests/test_trust_trajectory_unknown_verdict.py tests/test_trust_trajectory.py tests/dashboard/test_trust_trajectory_endpoint.py passes: an unknown verdict adds no data point, REJECTED stays 0.0; reverting fails case 1 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
399
+ | S-209 | BACKLOG 99 (Bun): codex, cline and aider get the prompt without the commit-hygiene line | loki-ts/src/runner/providers.ts (codex, cline, aider invokers only), loki-ts/tests/runner/provider_commit_hygiene.test.ts (new), loki-ts/tests/runner/providers.test.ts (argv asserts only if moved) | MEDIUM | cd loki-ts && bun test tests/runner/provider_commit_hygiene.test.ts tests/runner/providers.test.ts exits 0: all three argvs carry the providers/codex.sh literal, claude not double-prefixed; removing the prefix fails the three legs | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
400
+ | 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 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
401
+ | 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 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
402
+ | 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 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |
403
+ | 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 | ready@2026-09-27T20:12Z | Source: 20:12Z cut. |