loki-mode 9.54.2 → 9.56.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.
- package/.github/actions/issue-to-pr/action.yml +165 -29
- package/.github/workflows/loki-issue-to-pr.yml +137 -24
- package/README.md +1 -1
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +110 -34
- package/autonomy/crash.sh +6 -6
- package/autonomy/lib/done-recognition.sh +7 -0
- package/autonomy/lib/prd-enrich.sh +7 -0
- package/autonomy/lib/proof-check.sh +9 -0
- package/autonomy/lib/proof-generator.py +12 -3
- package/autonomy/lib/proof-verify.py +93 -21
- package/autonomy/lib/voter-agents.sh +7 -0
- package/autonomy/lib/workspace_diff.py +18 -7
- package/autonomy/loki +537 -122
- package/autonomy/quickstart.sh +7 -0
- package/autonomy/run.sh +956 -37
- package/autonomy/verify.sh +114 -8
- package/bin/loki +12 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_keys.py +12 -5
- package/dashboard/build_supervisor.py +25 -1
- package/dashboard/server.py +46 -24
- package/dashboard/static/index.html +57 -57
- package/docs/INSTALLATION.md +6 -5
- package/docs/VERIFIED-COMPLETION-PLAN.md +7 -5
- package/docs/air-gapped.md +39 -17
- package/docs/enterprise/security.md +10 -13
- package/docs/environment-variables.md +2 -0
- package/docs/exit-codes.md +76 -2
- package/docs/v10/BACKLOG.md +56 -0
- package/docs/v10/BOARD.md +118 -32
- package/docs/v10/CONTROL.md +36 -0
- package/docs/v10/DECISIONS.md +74 -0
- package/docs/v10/METRICS.md +78 -1
- package/docs/v10/PROGRESS.md +928 -0
- package/loki-ts/dist/loki.js +331 -327
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/claude.sh +1 -1
- package/providers/loader.sh +10 -0
- package/providers/model_catalog.json +12 -5
- package/providers/models.sh +1 -1
- package/references/core-workflow.md +1 -1
- package/tools/receipt-attest.py +1 -1
- package/web-app/dist/assets/{AdminPage-CZrBkzRF.js → AdminPage-Oyx-w2Ch.js} +1 -1
- package/web-app/dist/assets/{Avatar-gQIp6FBI.js → Avatar-D60m65JB.js} +1 -1
- package/web-app/dist/assets/{Badge-D2_fBTFY.js → Badge-CqfZNaem.js} +1 -1
- package/web-app/dist/assets/{Button-D5qDd2ef.js → Button-BqjzE4fz.js} +1 -1
- package/web-app/dist/assets/CockpitPage-Czk7o_ou.js +47 -0
- package/web-app/dist/assets/ComparePage-BEfTrTb1.js +1 -0
- package/web-app/dist/assets/{ErrorBoundary-BRABI-BT.js → ErrorBoundary-BrLk5nkO.js} +1 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-9vEpi5ir.js +1 -0
- package/web-app/dist/assets/{GitHubIssuesPanel-BC5GzKUN.js → GitHubIssuesPanel-D6izZx0w.js} +1 -1
- package/web-app/dist/assets/GitHubPRsPanel-BTkG2FgA.js +17 -0
- package/web-app/dist/assets/{HomePage-D_CDMoen.js → HomePage-nsr4kpN1.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BBNA_N9t.js → LoginPage-BVblQrr9.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CnFRZCMx.js → MagicPage-CmnSyLq7.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CPfLMRlh.js → MetricsPage-BVfwU81j.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-lA0XSGTz.js → NotFoundPage-AYQ6uqqI.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CNAPbr9z.js → ProjectPage-DMnbw9X9.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-CMtm8goN.js → ProjectsPage-CNVTAF2N.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BhIjVMYE.js → SettingsPage-D1_qasFD.js} +3 -3
- package/web-app/dist/assets/{ShowcasePage-BndtGeYo.js → ShowcasePage-2dBCjLXn.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-euXI-KXE.js → SystemSettingsPage-Djo6IE4u.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-ClUKecun.js → TeamsPage-CY8p-yxD.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BWHWVk0L.js → TemplatesPage-B6iFgH6t.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-Cv3N3Szf.js → TerminalOutput-B3yzZe-h.js} +1 -1
- package/web-app/dist/assets/{activity-dEhz-bXR.js → activity-CNfAjtRv.js} +1 -1
- package/web-app/dist/assets/{bell-B3XUMq1t.js → bell-CMETsHPH.js} +1 -1
- package/web-app/dist/assets/{bot-X-ssNlwR.js → bot-C9kXvk1i.js} +1 -1
- package/web-app/dist/assets/{check-C_9Nx7kb.js → check-BRK-zLB5.js} +1 -1
- package/web-app/dist/assets/{chevron-left-tvNswo3A.js → chevron-left-CxI5uD4g.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CSB88nEs.js → circle-alert-CVFRPWpv.js} +1 -1
- package/web-app/dist/assets/{clock-C8p2e4NI.js → clock-CLYV8a_x.js} +1 -1
- package/web-app/dist/assets/{cloud-CKp2ZvhG.js → cloud-CiISiIOa.js} +1 -1
- package/web-app/dist/assets/{code-xml-dY70LCHD.js → code-xml-DHsgqwV-.js} +1 -1
- package/web-app/dist/assets/{database-DObn5fmn.js → database-DbvUqtz3.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DSu6n3K3.js → dollar-sign-Ct0lRPHw.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DpCnS73z.js → file-code-corner-D1sjFEh7.js} +1 -1
- package/web-app/dist/assets/{file-plus-D3IPKCf1.js → file-plus-DnmX18Fi.js} +1 -1
- package/web-app/dist/assets/{globe-C9QXkgH_.js → globe-bSpDNgoA.js} +1 -1
- package/web-app/dist/assets/{hammer-D_FtWe1y.js → hammer-Bj41Kvlq.js} +1 -1
- package/web-app/dist/assets/{index-CI54rara.css → index-BfQ0f3-S.css} +1 -1
- package/web-app/dist/assets/{index-Cz7q1bvC.js → index-CxajNJVu.js} +3 -3
- package/web-app/dist/assets/{layers-DsW7jnJX.js → layers-BNtBwYER.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B3HspjKR.js → loader-circle-YY_VZofG.js} +1 -1
- package/web-app/dist/assets/{lock-DSI29pct.js → lock-rpjEPVoC.js} +1 -1
- package/web-app/dist/assets/{package-CLNxtA2x.js → package-desXU6XA.js} +1 -1
- package/web-app/dist/assets/{plus-DyI4WC4_.js → plus-7AoOU-I9.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-D2dv0xA0.js → refresh-cw-oNj-Xn4B.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CBvihA-a.js → rotate-ccw-DeiFjfVO.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DvoOvAl_.js → scroll-text-Q9AzWiNV.js} +1 -1
- package/web-app/dist/assets/{server-DenWvSUt.js → server-DKgVwfek.js} +1 -1
- package/web-app/dist/assets/{shield-alert-40cX_FvG.js → shield-alert-G6x-bS-I.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BrjZ6QuV.js → thumbs-up-Qhk0yvw0.js} +1 -1
- package/web-app/dist/assets/{trash-2-C6evwkEH.js → trash-2-D23gvznl.js} +1 -1
- package/web-app/dist/assets/{trending-down-CfbZis3O.js → trending-down-CSQClPrr.js} +1 -1
- package/web-app/dist/assets/{trending-up-DWuEK3WC.js → trending-up-sjMSd1wc.js} +1 -1
- package/web-app/dist/assets/{upload-B9DFBcPG.js → upload-Dchovhld.js} +1 -1
- package/web-app/dist/assets/{usePolling-BryVC-T1.js → usePolling-DwLceXwF.js} +1 -1
- package/web-app/dist/assets/{user-DMRXwZiw.js → user-BqZM8CmD.js} +1 -1
- package/web-app/dist/index.html +2 -2
- package/web-app/server.py +52 -17
- package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +0 -47
- package/web-app/dist/assets/ComparePage-NMLyE1xL.js +0 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +0 -1
- package/web-app/dist/assets/GitHubPRsPanel-BSlmoVTS.js +0 -17
package/docs/v10/BOARD.md
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
# Board
|
|
2
2
|
|
|
3
3
|
Written only by the Product Owner and the Release Captain. One row per
|
|
4
|
-
slice.
|
|
5
|
-
|
|
4
|
+
slice. See `docs/v10/SWARM.md`.
|
|
5
|
+
|
|
6
|
+
## Status format (normalized for `scripts/v10-pulse.sh`)
|
|
7
|
+
|
|
8
|
+
Every row's `Status` cell is exactly one token, an `@`, and a UTC timestamp
|
|
9
|
+
(`<token>@YYYY-MM-DDTHH:MMZ`) -- the time the status last changed. Prose,
|
|
10
|
+
history, and caveats move to `Notes`; `Status` itself must stay
|
|
11
|
+
machine-parseable with no free text. Tokens, in the lifecycle order the pulse
|
|
12
|
+
script expects:
|
|
13
|
+
|
|
14
|
+
`ready` -> `building` -> `review` -> `review-blocked` (returns to `building`)
|
|
15
|
+
-> `approved` -> `merged` -> `released`. Side states: `blocked` (needs a
|
|
16
|
+
Captain/PO decision), `rejected` (sent back, will be re-cut), `parked`
|
|
17
|
+
(deliberately shelved).
|
|
18
|
+
|
|
19
|
+
`merged` here means "the Captain landed it on main" -- a slice sits at
|
|
20
|
+
`merged` until the Captain flips it to `released` on the next version bump
|
|
21
|
+
that ships it. The pulse script does NOT trust this field for its own
|
|
22
|
+
"merged-but-unreleased age" computation: it derives that directly from git
|
|
23
|
+
(`git log` on main after the last release tag) since a table cell can go
|
|
24
|
+
stale between edits. This field still matters for humans and for the
|
|
25
|
+
ready/building/review/blocked counts, which git cannot derive.
|
|
6
26
|
|
|
7
27
|
## Grandfathered slices (in flight before the swarm existed)
|
|
8
28
|
|
|
@@ -12,18 +32,18 @@ merge (all touch trust-core or security-relevant surfaces), oldest first.
|
|
|
12
32
|
|
|
13
33
|
| ID | Owner | Branch @ SHA | File set (summary) | Tier | Status | Notes |
|
|
14
34
|
|---|---|---|---|---|---|---|
|
|
15
|
-
| GF-1 | cycle-4 (main) | main @ 779c50e5 (v9.54.1) | cycle 4 + verdict fix + XSS fix + pkill-scoping fix (D15/D16/D17, RELEASED) + D8-D17 | HIGH |
|
|
16
|
-
| GF-2 | P5 slice |
|
|
17
|
-
| GF-3 | P9 slice |
|
|
18
|
-
| GF-4 | P4 slice |
|
|
19
|
-
| 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 | merged | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. |
|
|
35
|
+
| GF-1 | cycle-4 (main) | main @ 779c50e5 (v9.54.1) | cycle 4 + verdict fix + XSS fix + pkill-scoping fix (D15/D16/D17, RELEASED) + D8-D17 | HIGH | blocked@2026-09-27T01:33Z | PF-2 (P7 scanner gap fix) finished at ecfd9578, ready for review. Full council re-run required once merged (D12). PF-1 shipped separately as v9.54.1, ahead of GF-1. |
|
|
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 | merged@2026-09-27T01:33Z | 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). |
|
|
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 | merged@2026-09-27T06:20Z | 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. |
|
|
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 | merged@2026-09-27T07:30Z | 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. |
|
|
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 | merged@2026-09-27T01:33Z | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. |
|
|
20
40
|
|
|
21
41
|
## Priority out-of-band fix (severity: kills unrelated user sessions)
|
|
22
42
|
|
|
23
43
|
| ID | Owner | Branch @ SHA | File set | Tier | Status | Notes |
|
|
24
44
|
|---|---|---|---|---|---|---|
|
|
25
|
-
| PF-1 | pkill-scoping fix | main @ 9cd51d1a | autonomy/run.sh (kill_provider_child), tests/test-kill-provider-child-scoping.sh, docs/v10/DECISIONS.md (D15) | HIGH |
|
|
26
|
-
| PF-2 | P7 scanner gap fix |
|
|
45
|
+
| PF-1 | pkill-scoping fix | main @ 9cd51d1a | autonomy/run.sh (kill_provider_child), tests/test-kill-provider-child-scoping.sh, docs/v10/DECISIONS.md (D15) | HIGH | released@2026-09-27T01:33Z | Founder-reported: every loki-mode session ending via signal (supervisor signal, double Ctrl+C, Ctrl+C in perpetual mode) ran an unscoped `pkill -f` matching ANY process on the machine by command-line substring, terminating unrelated Claude Code sessions. Fixed to scope by process group. Shipped as v9.54.1, ahead of the swarm queue. |
|
|
46
|
+
| PF-2 | P7 scanner gap fix | main @ fa5de15f | tests/moat/p7-no-fabricated-data.sh | HIGH | merged@2026-09-27T01:33Z | Round 5, unanimous 4/4 APPROVE under a corrected scoping rule (only a regression/false-positive/weakening introduced by the diff blocks; a pre-existing gap the diff doesn't worsen is a new slice, not a veto). Rebased onto current main, merged fa5de15f, pushed. 10 candidate follow-up slices recorded below (B-1..B-8 plus 2 more from the review). |
|
|
27
47
|
|
|
28
48
|
## Fixed on main already (not slices; recorded for PO context)
|
|
29
49
|
|
|
@@ -39,24 +59,90 @@ Cut against BACKLOG items not already owned by an in-flight slice (PF-1, PF-2,
|
|
|
39
59
|
GF-2 P5, GF-3 P9, GF-4 P4, the repo-wide kill-scan agent). Each slice's file
|
|
40
60
|
set is declared to avoid overlap with those and with each other.
|
|
41
61
|
|
|
42
|
-
| ID | Owner | File set | Tier | Acceptance checks (Wall) | Status |
|
|
43
|
-
|
|
44
|
-
| S-
|
|
45
|
-
| S-
|
|
46
|
-
| S-
|
|
47
|
-
| S-
|
|
48
|
-
| S-
|
|
49
|
-
| S-
|
|
50
|
-
| S-
|
|
51
|
-
| S-
|
|
52
|
-
| S-
|
|
53
|
-
| S-
|
|
54
|
-
| S-
|
|
55
|
-
| S-
|
|
56
|
-
| S-
|
|
57
|
-
| S-
|
|
58
|
-
| S-
|
|
59
|
-
| S-
|
|
62
|
+
| ID | Owner | File set | Tier | Acceptance checks (Wall) | Status | Notes |
|
|
63
|
+
|---|---|---|---|---|---|---|
|
|
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 | merged@2026-09-27T11:42Z | 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. |
|
|
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 | merged@2026-09-27T11:57Z | 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). |
|
|
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 | merged@2026-09-27T11:42Z | 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. |
|
|
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
|
+
| 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 | ready@2026-09-27T10:50Z | 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). |
|
|
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 | ready@2026-09-27T10:50Z | 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. |
|
|
70
|
+
| S-51 | BACKLOG 117: stale or false static copy (version numbers, license, Gemini support, gate counts, invented testimonial) | web-app/src/components/WhatsNew.tsx (actual path, not pages/ as originally listed), web-app/src/components/Footer.tsx, web-app/src/pages/SettingsPage.tsx, web-app/src/pages/ComparePage.tsx, web-app/src/components/BenefitCards.tsx, web-app/src/components/TrustedBy.tsx | LOW | grep confirms each named false claim is gone (version bumped to current, MIT replaced with BUSL-1.1, Gemini removed, gate count corrected to 8, invented testimonial line removed) | merged@2026-09-27T11:00Z | Merged 7ad546a7, clean cherry-pick, direct Captain review (LOW tier, pure copy diff, verified against VERSION/LICENSE/CLAUDE.md source of truth). TrustedBy.tsx reviewed and left unchanged (no fabricated content found). BenefitCards.tsx's Gemini removal also dropped it from Multi-AI copy (not just the gate count). Follow-ups flagged, not filed as new backlog yet: SettingsPage.tsx build date still hardcoded (2026-03-24, out of scope for a copy-only slice since deriving it live is a logic change); PROVIDERS array still lists Gemini as active (behavior, not copy); DocsSidebar.tsx/ContextualHelp.tsx/CostEstimator.tsx/ProjectWorkspace.tsx/SystemSettingsPage.tsx also reference Gemini or stale gate counts, out of this slice's file set; WhatsNew.tsx/Footer.tsx versions are not in CLAUDE.md's release version-bump checklist so will drift stale again next release. |
|
|
71
|
+
| S-52 | BACKLOG 122: receipt field `first_result_verified_patch` is True for any first code change, naming a verification that did not run | autonomy/lib/proof-generator.py (the named field only) | LOW | field is renamed additively (`first_result_kind` already exists) or set only from an actually-verified result, with a test; no consumer of the old field silently breaks | merged@2026-09-27T11:29Z | Direct fix chosen over additive rename (advisor-caught: a new field would duplicate first_result_kind byte-for-byte, since no producer anywhere ever sets this field True). Full consumer survey done; found and fixed a real bug the fix would otherwise have caused (loki-overview.js's "Plan only" label, repointed at first_result_kind). Merged 0380ad6f, 21/21 + 11/11 reconfirmed on main. Direct Captain review (LOW tier). |
|
|
72
|
+
| S-53 | BACKLOG 138 fix direction: trusted git push/PR calls should ignore agent-controlled hooks/config (planted pre-push hook, credential.helper, core.fsmonitor, core.sshCommand can see GH_TOKEN during Loki's own trusted push) | autonomy/run.sh (create_session_pr / the trusted push call sites only, not the withhold function itself which S-18/BACKLOG-149's rework owns) | HIGH | red: a planted `.git/hooks/pre-push` sees GH_TOKEN during Loki's trusted push (reproduce reviewer 3's GF-3 finding); green: the trusted push explicitly neutralizes hooksPath/credential.helper/sshCommand for that one invocation, hook sees nothing | ready@2026-09-27T10:58Z | Sequencing note: wait for S-18/BACKLOG 149's rework to land first (touches nearby withhold/re-grant code in the same file); rebase onto that before starting to avoid a conflict. Do not touch the withhold function itself, only the push-call invocation. |
|
|
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 | ready@2026-09-27T10:58Z | 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. |
|
|
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 | building@2026-09-27T11:19Z | 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). |
|
|
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 | building@2026-09-27T11:44Z | 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. |
|
|
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 | merged@2026-09-27T12:17Z | 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. |
|
|
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 | merged@2026-09-27T12:27Z | 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. |
|
|
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 | merged@2026-09-27T12:21Z | 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. |
|
|
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 | merged@2026-09-27T12:26Z | 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). |
|
|
80
|
+
| S-61 | BACKLOG 21 (D5): the seatbelt test `tests/dashboard/test_build_supervisor.py::BuildSupervisorTests::test_host_seatbelt_blocks_docker_ports_and_sibling_reads` fails deterministically on this host/macOS version (exit 32, not 0) -- confirmed pre-existing (reproduces identically at v9.55.0), used twice this session as a documented pre-push skip (D24) rather than investigated | tests/dashboard/test_build_supervisor.py (investigation + fix, or documented host-scoping if it's genuinely unfixable on this platform), the seatbelt-invoking code it exercises if the bug turns out to be there instead of the test | MEDIUM | red: the test fails with exit 32 on this host as it does today; green: either the test passes (root cause found and fixed) or it is correctly skipped/xfailed ONLY on the specific unsupported platform/macOS-version combination, with the skip reason documented and never silently masking a real regression on a supported platform | merged@2026-09-27T12:39Z | ROOT CAUSE FOUND: on macOS 27.0, sandbox-exec's `(deny network-bind (local tcp "*:PORT"))` silently never matches an actual bind -- `tcp4` denies it correctly. A genuine bug in the generated seatbelt profile, not a test bug or an unfixable platform gap. Verified via direct sandbox-exec reproduction, ruled out rule ordering, self-caught and corrected an initial misdiagnosis (advisor-caught via a positive control), bisected across filter keyword forms. Confirmed the real production gate (smoke_probe_host_seatbelt) already failed CLOSED before this fix (refused to advertise confinement rather than silently exposing it) -- an availability bug, not a live exposure. IPv6 (tcp6/ip6) has the same underlying gap, pre-existing, out of scope, documented in-code (no IPv6 usage today). Merged 46bd86a1, 37/37 reconfirmed on main -- the test that failed identically 5+ times this session (D24's basis) now genuinely passes. This retires the D24 skip pattern going forward. |
|
|
81
|
+
| S-62 | BACKLOG 118 (scoped subset): council-state fallback `total_votes: 0` and a corrupt `notifications/active.json` read as a zero summary -- both server-side zero sentinels the dashboard cannot distinguish from a genuine zero | dashboard/server.py (the two named fallback sites only), its test | LOW | red: a council-state read error or a corrupt notifications file returns a zero/empty summary indistinguishable from a real zero; green: an error/corrupt-read case returns an explicit null/error marker instead, with a test | merged@2026-09-27T12:29Z | Merged 1e708115, 7/7 reconfirmed on main. Genuinely-missing-file and corrupt-file cases correctly distinguished (only the latter returns the new error envelope); also fixed a small contained frontend consumer (loki-notification-center.js) that treated any HTTP 200 as success. Mutation-tested: reverted both except branches, confirmed exactly 3 tests went red. |
|
|
82
|
+
| S-63 | BACKLOG 78: leading-directory pathspec mismatch -- a pre-existing untracked file `a` also matches `a/b` in the literal reset, but `workspace_diff._covered` only treats `a/` (trailing-slash) entries as covering children, so the commit omits `a/b` while the receipt lists it (the receipt is the honest side, the commit behavior is the bug) | autonomy/lib/workspace_diff.py (`_covered` or equivalent) or wherever the literal reset happens (grep first), its test | MEDIUM | red: an untracked file `a` (no trailing slash) does not cover `a/b` in the reset, so `a/b` stays committed although the receipt says it's the user's; green: a bare-file snapshot entry `a` correctly covers `a/b` the same way a directory entry `a/` does, matching the receipt | merged@2026-09-27T13:10Z | Merged 5f53a1fc, 78/78 reconfirmed on main, confirmed no interaction with S-60's earlier path-normalization change to the same file (different function). Root cause: `_covered`'s prefix check only tested the directory form (parent + "/"), never the bare-file form; fixed to check both, with a false-positive control (a vs ab) added alongside the real fix. |
|
|
83
|
+
| S-64 | BACKLOG 90: `LOKI_BRANCH_PROTECTION=false` on a leftover `loki/session-*` branch returns before any snapshot is taken, then `commit_session_changes` commits using the EARLIER session's stale snapshot, so a file the user made since is committed and lost from disk on checkout of the base | autonomy/run.sh (the branch-protection-off early-return path and commit_session_changes' snapshot-freshness check only), its test | HIGH | red: with LOKI_BRANCH_PROTECTION=false and a leftover loki/session-* branch, a file created by the user AFTER that branch was minted gets swept into the session commit and lost on a later base checkout; green: commit_session_changes refuses to commit (or re-snapshots) when no snapshot was taken THIS run | released@2026-09-27T13:18Z | STALE DUPLICATE, already fixed and released: commit d298ca60 (2026-09-26) already implements exactly this fix (the _LOKI_SNAPSHOT_THIS_RUN gate in commit_session_changes), confirmed an ancestor of origin/main. Builder verified thoroughly: ran the full 81/81 test-branch-lifecycle.sh suite (including the exact BACKLOG-90 regression test), mutation-tested the gate itself to confirm it's non-vacuous, swept for un-gated sibling commit sites (none found), and confirmed no Bun-route duplicate implementation exists. No code change needed. |
|
|
84
|
+
| S-65 | BACKLOG 116 remainder: `dashboard/server.py`'s `gh pr view` (PR detail endpoint) doesn't request `statusCheckRollup` or several other fields S-47 already fixed the READER side for, so the detail-view status-checks section stays empty even after S-47's merge | dashboard/server.py (the gh pr view field-list only), its test | LOW | red: the PR detail endpoint's gh invocation omits statusCheckRollup from its --json field list, so the already-fixed frontend reader has nothing to read; green: the field list includes statusCheckRollup (and any other fields S-47's fix now expects), a real PR detail response includes it | merged@2026-09-27T13:12Z | Merged 52b4dda0, reconfirmed on main. Builder correctly found the file set in the original ticket was wrong (dashboard/server.py has no PR routes; the real site is web-app/server.py's github_get_pr) and fixed there instead, disclosing the correction rather than silently working around it. Added statusCheckRollup + 4 other missing fields matching the sibling list endpoint's already-correct field set. Also flagged, not fixed (out of scope): 2 duplicate function definitions in web-app/server.py. |
|
|
85
|
+
| S-66 | BACKLOG 116 remainder: `dashboard/server.py`'s PR list endpoint likely has the same missing-field gap as the detail endpoint (S-65) -- verify and fix if so | dashboard/server.py (the gh pr list field-list only, if distinct from the view endpoint), its test | LOW | red: the PR list gh invocation also omits fields S-47's reader fix expects (if confirmed distinct from S-65's site); green: fixed, with a test | released@2026-09-27T13:14Z | Investigated thoroughly, no fix needed: the PR list endpoint (github_list_prs) is a genuinely separate call site from S-65's fix target, but its field list already includes all 13 fields the frontend list view actually reads (enumerated against PRCard and the GitHubPR TypeScript interface directly). This gap never existed on the list side. Marked released since no code change was needed; nothing new to ship. |
|
|
86
|
+
| S-67 | BACKLOG 88: old git (< 2.18) receipt attribution -- a failed mint snapshot deletes the list, so the receipt names every user untracked file as the run's work | autonomy/lib/workspace_diff.py or wherever the mint-snapshot failure path lives (grep first), its test | LOW | red: on a git < 2.18 (or simulated failure of the mint snapshot), the receipt attributes every pre-existing untracked file to the session's own work; green: an `ls-files --others --exclude-standard` fallback list is kept for the receipt even when the primary snapshot mechanism fails, names and counts only (the commit path still fails closed) | ready@2026-09-27T13:11Z | Check the git version floor already established elsewhere in this session's work (S-18's rework added a similar floor check for GIT_CONFIG_COUNT) for the established pattern to follow. |
|
|
87
|
+
| S-68 | BACKLOG 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 | autonomy/run.sh (the file's write site and lifecycle only), its test | LOW | red: the file persists indefinitely across sessions even when a later session finds no agent-committed user files; green: it's read and correctly cleared/rotated when appropriate, with a test proving the lifecycle | ready@2026-09-27T13:11Z | Low-risk housekeeping; read BACKLOG 108's reader requirement first (create_session_pr is supposed to read this file per that item) to confirm this isn't already partially addressed. |
|
|
88
|
+
| S-69 | Founder directive D25 part 3: `.github/workflows/test.yml`'s `cancel-in-progress` must apply ONLY to pull_request events, never to a push to main -- this is the direct fix for the 10-of-12-cancelled-runs pattern this session repeatedly hit and disclosed piecemeal | .github/workflows/test.yml (the concurrency block only) | MEDIUM | red: a push to main while a prior main-triggered Tests run is still in progress currently cancels it; green: a push to main never cancels an in-progress main-triggered run, while two PRs against the same branch still correctly cancel each other's stale run; verified with one real push per the founder's own instruction | parked@2026-09-27T14:13Z | Founder-specified fix shape: `cancel-in-progress: ${{ github.event_name == 'pull_request' }}`. Verify the exact syntax is valid GitHub Actions expression syntax before landing, and that the concurrency GROUP key doesn't also need adjusting (a shared group across push and PR could still cause unwanted interaction even with cancel-in-progress scoped). Superseded by S-80 (CEO Part C item 2: per-SHA group key in all 3 gating workflows, not just cancel-in-progress in test.yml). Commit 8cfa1eae not merged. |
|
|
89
|
+
| S-70 | Founder directive D25 part 4: measure real per-shard Tests durations, then rebalance/increase sharding (4 to 8, or whatever balances best) so a Tests run completes in under 15 minutes; record before/after numbers in METRICS.md | .github/workflows/test.yml (shard count/matrix), tests/run-all-tests.sh (shard-assignment logic if it needs updating for a new shard count), METRICS.md (new before/after entry) | MEDIUM | red: current Tests run takes 26-34 minutes per the founder's own measurement; green: a real Tests run on the new shard count completes under 15 minutes, with the actual before/after wall-clock numbers recorded in METRICS.md, not estimated | parked@2026-09-27T14:13Z | This is what raises the release-train ceiling toward 60/day per the founder's own framing -- get real per-shard timing data first (do not guess a shard count), and confirm the shard-index partition still covers 100% of the suite (index-based, as documented elsewhere in this repo's release notes) after rebalancing. Superseded by S-81 (CEO Part C item 4: duration-balanced 8 shards). Its measured timing data (c6000cb9) feeds S-81. |
|
|
90
|
+
| S-71 | Founder directive D25 part 5: `scripts/v10-pulse.sh` blind spots -- add CI_CANCELLED_STREAK (3+ consecutive cancelled Tests runs on main), MERGED_UNRELEASED (45+ min even when main CI reads UNKNOWN), and fix main-CI-UNKNOWN currently suppressing other violations that should fire independently | scripts/v10-pulse.sh, tests/test-v10-pulse.sh (fixture tests for each new violation) | LOW | red: 3+ consecutive cancelled runs, or a 45+ min unreleased-merge age, currently produce no violation when main CI reads UNKNOWN; green: both fire correctly, and a fixture test proves neither is suppressed by an UNKNOWN main-CI reading, nor does it suppress any OTHER already-existing violation | review@2026-09-27T14:13Z | Read scripts/v10-pulse.sh's current UNKNOWN-handling logic first to find exactly where/why it currently suppresses other checks before fixing -- this is likely one shared early-return or short-circuit, not three separate bugs. Built b8f43d08. 2 Tech Lead reviewers dispatched 14:09 (stacked with S-75). |
|
|
91
|
+
| S-72 | Founder directive D25 part 6: `.claude/worktrees` holds 112 worktrees (~20GB) -- remove every worktree whose slice is merged/released/rejected/parked on BOARD.md after confirming its branch is fully merged (or its work is otherwise recorded), keep at most 10, and add a pulse violation for more than 15 worktrees | scripts/v10-pulse.sh (new violation only), a cleanup pass (not a code file -- direct git worktree operations, done carefully and verified per-worktree, not a blanket rm) | LOW | red: 112 worktrees exist today, no pulse violation fires above 15; green: worktree count is at or below 10 after a verified cleanup pass, and the new pulse violation fires correctly above 15 | ready@2026-09-27T13:16Z | HIGH CARE REQUIRED: verify each worktree's branch tip is actually an ancestor of main (or its work is otherwise fully captured in a merged commit) via `git merge-base --is-ancestor` before removing it with `git worktree remove` -- never blanket-delete by directory listing alone, and never remove a worktree currently in active use by a running agent (cross-check against ListAgents' active subagents first). |
|
|
92
|
+
| S-73 | Founder directive D26 guard 1: PreToolUse Bash guard hook (scripts/v10-guard.sh, wired via LOCAL-ONLY .claude/settings.local.json, never committed) blocking pkill/killall by name, git push --force/-f or reset --hard on main, git add -A/git add ., a BOARD.md commit dropping existing rows (the D18 incident), rm -rf outside safe roots, VERSION writes outside scripts/release.sh | scripts/v10-guard.sh (new), a fixture test file, .claude/settings.local.json (LOCAL ONLY -- must not be committed to the repo) | HIGH | red: each named dangerous pattern is currently allowed; green: each is blocked with exit 2 and a clear message, with one blocked-case and one allowed-case fixture per rule | review@2026-09-27T14:13Z | CRITICAL: .claude/settings.local.json is local machine config, never a repo file -- if it's gitignored confirm that; if not, add it to .gitignore as part of this slice, and never stage or commit it. The guard script itself (scripts/v10-guard.sh) IS a normal repo file and goes through review. Read the actual PreToolUse hook JSON contract (stdin format, exit-code semantics) from Claude Code's own hook documentation before implementing -- do not guess the interface. Built and committed 47179bb3 (25/25 fixtures). 2 opus HIGH reviewers dispatched 14:09. |
|
|
93
|
+
| S-74 | Founder directive D26 guard 2: no subagents for trivial orchestration (commit messages, git status/clean checks, BOARD.md row updates, version/CI checks) -- these go through the orchestrator directly or a new scripts/v10-ops.sh, never a dispatched Agent call | scripts/v10-ops.sh (new, subcommands for the named trivial operations), docs/v10/CONTROL.md or SWARM.md (a short binding rule addition, if line budget allows) | MEDIUM | red: this session dispatched full subagents that spent 22 minutes/229k tokens writing a commit message and 16 minutes/182k tokens checking a clean tree (cited by the founder as observed incidents); green: the same operations are one-line orchestrator actions or v10-ops.sh subcommand calls, no Agent dispatch | review@2026-09-27T14:13Z | This is a PROCESS rule as much as a script -- the script gives the orchestrator a fast path, but the actual fix is behavioral (the Captain/PO/orchestrator role must stop dispatching subagents for these). Keep the script itself minimal: thin wrappers around git/gh one-liners, not a framework. Built and committed 94b8d3a6 (16/16 tests). 2 Tech Lead reviewers dispatched 14:09. |
|
|
94
|
+
| S-75 | Founder directive D26 guard 3: per-role agent time budgets (LOW 15m, MEDIUM 30m, reviewer 30m, HIGH adversarial 60m, any shell command 10m under timeout, background long ones with a recorded PID) plus a new AGENT_OVER_BUDGET pulse violation | scripts/v10-pulse.sh (new violation), docs/v10/CONTROL.md or SWARM.md (the budget table itself, if line budget allows -- otherwise a new short reference doc), a fixture test | MEDIUM | red: an agent exceeding its tier's budget currently produces no violation and no automatic stop; green: AGENT_OVER_BUDGET fires when an agent's recorded runtime exceeds its tier's budget, with a fixture proving it (a synthetic over-budget record fires, an under-budget one does not) | review@2026-09-27T14:13Z | Coordinate file-set with S-71 (already merged locally, held for train 2) which also touches scripts/v10-pulse.sh -- rebase onto that commit first to avoid a conflict, since S-71 already restructured how violations are detected and named. Built 5c9a16f2, stacked on S-71 (must merge with or after it). 45/45 tests. HIGH-builder budget set to 60 min by symmetry, needs CEO confirmation. Reviewed together with S-71. |
|
|
95
|
+
| S-76 | Founder directive D26 guards 4-5: evidence-or-it-did-not-happen (a BOARD.md/PROGRESS.md/commit claim of verified/green/fixed/confirmed/no-fix-needed must cite the exact command and its exit code or output line) plus the new UNEVIDENCED_CLAIM pulse check over the last 20 doc changes, plus backfilling docs/v10/GUARDS.md with the 6 named incidents (D14/D15 pkill, D18 BOARD.md-emptied, CI self-cancellation/D25, pulse UNKNOWN-suppression/S-71, the hung worktree classifier, over-budget trivial agents) | docs/v10/GUARDS.md (new file), scripts/v10-pulse.sh (UNEVIDENCED_CLAIM check), a fixture test | MEDIUM | red: none of the 6 named incidents has a GUARDS.md entry today, and no pulse check flags an evidence-free claim; green: all 6 incidents have a 4-field GUARDS.md entry (incident, root cause with evidence, the guard, the test proving it fires) and each incident's guard+test genuinely already exists (cite them, do not invent new ones just to close the entry), plus UNEVIDENCED_CLAIM fires on a fixture claim with no cited command/exit-code | ready@2026-09-27T13:38Z | For each of the 6 incidents, the guard it names must ALREADY EXIST (S-71's pulse fix, D25's cancel-in-progress fix once S-69 lands, this slice's own new evidence check, the worktree-classifier lesson likely just needs a documented timeout+batch-approach guard rather than new code) -- do not fabricate a guard reference that doesn't correspond to real code. |
|
|
96
|
+
| S-77 | Founder directive D26 guard 6: small, fresh subagent context -- a slice card of at most 60 lines (goal, file set, Wall checks, commands to run, budget) instead of full conversation history when dispatching a builder/reviewer | docs/v10/SWARM.md or CONTROL.md (the slice-card template and the binding rule that the orchestrator dispatches from it, not from raw history) | LOW | the swarm's own dispatch documentation names a concrete 60-line-max slice-card template and states the orchestrator keeps only CONTROL.md/pulse-block/BOARD.md in its own live view, deferring everything else to on-demand file reads | ready@2026-09-27T13:38Z | This is primarily a documentation/process slice (the Agent tool's own dispatch prompts already tend toward focused briefs in this session's practice, per BOARD.md's own file-set-per-slice convention) -- codify the existing good practice into a named template rather than inventing new mechanics. |
|
|
97
|
+
| S-78 | CEO Part B: docs/v10/OPERATING-MODEL.md (verbatim), CLAUDE.md and AGENTS.md trimmed to <=150 lines with the @ import first, the rest moved to docs/dev/*.md with a removal ledger | docs/v10/OPERATING-MODEL.md, CLAUDE.md, AGENTS.md, docs/dev/*.md | LOW | wc -l limits met; cmp of OPERATING-MODEL.md against the CEO text is 0; every removed rule listed with where it moved or why it was deleted | building@2026-09-27T14:13Z | Engineer dispatched 14:09 (sonnet). |
|
|
98
|
+
| S-79 | CEO Part C item 1: size the argmax fixture on Linux to max(4000, 2*131072/72) (MAX_ARG_STRLEN, not ARG_MAX), replace per-item subshells in autonomy/loki, drop the 2400s override, full-scale fixture to nightly | tests/test-ci-json-argmax.sh, autonomy/loki (two sites), tests/run-all-tests.sh (override only) | HIGH | at the parent of b842a332, on Linux, the smaller fixture still exits rc=126; passes on the fixed tree | building@2026-09-27T14:13Z | Engineer dispatched 14:09 (sonnet). Saves 17-23 min per Tests run. |
|
|
99
|
+
| S-80 | CEO Part C item 2: per-SHA concurrency group on push, cancel only on PRs, in test.yml, bun-parity.yml, security-audit.yml | the three concurrency blocks | MEDIUM | a push to main never cancels or supersedes a main run; PRs still cancel their own stale runs; verified by one real push | review@2026-09-27T14:13Z | Built 3bd01787. 2 Tech Lead reviewers dispatched 14:12. Supersedes S-69. |
|
|
100
|
+
| S-81 | CEO Part C item 4: 8 shards balanced by measured duration, checked-in duration table, 5 heavy suites in distinct shards | test.yml shell-tests matrix, run-all-tests.sh shard selection, tests/shard-durations table, tests/test-shard-coverage.sh, docs/v10/METRICS.md | MEDIUM | test-shard-coverage.sh proves every suite runs exactly once at n=8; projected max shard reported | building@2026-09-27T14:13Z | Engineer dispatched 14:09 (sonnet). Supersedes S-70. |
|
|
101
|
+
| S-82 | CEO Part C item 6: timeout-minutes 10 on shell, python, node, bun jobs in test.yml | test.yml job-level timeout-minutes only | LOW | every listed job has timeout-minutes 10 | review@2026-09-27T14:13Z | Built 22e1bd4d. Reviewer dispatched 14:12. MERGE HELD until S-79 and S-81 land and a real run shows every shell shard under 10 min. |
|
|
102
|
+
| S-83 | CEO Part C item 7: update-homebrew needs only [release] | release.yml update-homebrew needs line | LOW | job reads only needs.release outputs | approved@2026-09-27T14:14Z | Built 53251c1b in 40s. Reviewer dispatched 14:11. release.yml change ships in its own train (D22). 1/1 APPROVE (Tech Lead): only needs.release outputs used; Homebrew asset is the hash-verified GitHub Release tarball, so npm/Docker failures cannot break it. Advisory: channels may now differ in version briefly. Ships in its own train (D22). |
|
|
103
|
+
| S-01 | BACKLOG 22: orphaned `sleep 300` resource monitor | autonomy/run.sh (resource-monitor spawn/cleanup only, not kill_provider_child), one new test | MEDIUM | red: `loki start` then interrupt leaves a `sleep 300` orphan (ps shows it after exit); green: it is reaped or never orphaned, by PID recorded at spawn | released@2026-09-27T01:33Z | 027ec085 confirmed ancestor of origin/main; note corrected, was stale. |
|
|
104
|
+
| S-02 | BACKLOG 23: client-route test hardcodes main checkout path | tests/lib-extract-client-paths.mjs, tests/lib-match-client-routes.py, tests/test-verify-client-routes.sh | LOW | merged@2026-09-27T06:50Z | 1/1 APPROVE: reviewer reproduced from 2 independent real worktrees, mutation-tested both new WORKTREE GUARD assertions independently, confirmed the disclosed BACKLOG 137 interaction (P7's own sed-workaround breaking) is expected, not a surprise. **Merged to main.** S-39/BACKLOG 137 now unblocked -- but note: this merge makes `tests/moat/run.sh` read a live FAIL on `P7.webapp-client-routes-exist` until S-39 lands (an unlisted-in-pending.txt regression per the ratchet), since P7's own copy-and-sed workaround can no longer find the literal it targets. S-39 should be prioritized promptly to close this gap, or a temporary pending.txt entry considered if S-39 doesn't land quickly. |
|
|
105
|
+
| S-03 | BACKLOG 25: `loki ci --report` "Argument list too long" on a large diff | autonomy/loki (cmd_ci report path only), one new test | MEDIUM | red: a synthetic diff over the ARG_MAX threshold, exit 126; green: same diff passed via stdin/file, exit 0 | rejected@2026-09-27T01:33Z | Real crash site (export-based ARG_MAX) misdiagnosed and left unfixed; sent back to builder. |
|
|
106
|
+
| S-04 | BACKLOG 26: Bun Parity `doctor-json` flake (disk.available_gb 94 vs 95) | .github/workflows/bun-parity.yml, tests/test-bun-parity-disk-tolerance.sh (new) | LOW | red: two consecutive doctor --json calls disagree on disk.available_gb and the parity check flags it; green: normalized (rounded/bucketed) or excluded from strict comparison, documented why | merged@2026-09-27T01:33Z | Merged 7a13b816, test registered f0f51587, pushed. |
|
|
107
|
+
| S-05 | BACKLOG 31: `proof-verify.py` "drift unverifiable" reads 1 (tampered) instead of 2 (could not check) | autonomy/lib/proof-verify.py, its test | MEDIUM | red: a genuinely-unverifiable drift case reads 1; green: it reads 2 | merged@2026-09-27T01:33Z | Merged 1a02bab1, pushed; quorum topped up 2/2 APPROVE. Fixed the receipt-attest.py substring-lookup break from the rename, plus documented an accepted ceiling (a hand-forged, re-hashed receipt with a stripped diff stat is indistinguishable from an honestly-unverifiable one; unreachable from any honestly-generated receipt). |
|
|
108
|
+
| S-06 | BACKLOG 32: docs tell npm users to run `doctor --airgap`, which the default (Bun) route rejects | docs/air-gapped.md, deploy/helm/README.md | LOW | the doc now says `LOKI_LEGACY_BASH=1 loki doctor --airgap` (or notes the Bun-route gap) until P5.airgap-audit-default-route ships; grep confirms the old bare command is gone from both files | released@2026-09-27T01:33Z | In main since c83732b2 / v9.54.2. |
|
|
109
|
+
| S-07 | BACKLOG 33: council `runner=none` counts as a positive signal, a zero-test suite does not -- pick one rule | autonomy/completion-council.sh (the specific vote-reading site only), its test | MEDIUM | merged@2026-09-26T23:10Z | Confirmed on main directly at ad47a2ec (this row was stale: BOARD said `review` but the commit was already an ancestor of origin/main; no separate merge commit was needed). Rework #2. Round 1 (regression from rework #1's pass:true narrowing) fixed by dropping the narrowing entirely -- runner=='none' unconditional again (matches the real writer, run.sh:12691-12692, which writes pass as the STRING "inconclusive", never boolean true), while keeping the correct status-first ordering fix. Unanimous 2/2 APPROVE: both reviewers independently confirmed status is checked unconditionally before runner=='none' in both parsers (a crafted runner:none+status:no_tests_run record cannot bypass), original bug and rework-#1 regression both verified fixed with independent fixtures. 78/78, 24/24, 41/41, 5/5 across the 4 regression suites. |
|
|
110
|
+
| S-08 | BACKLOG 39: attestation edge labels (`{"keys": []}` reads FAILED not NOT CHECKED; `attestation: false` inconsistent local vs remote) | autonomy/receipt_jwt.py or the relevant attestation renderer, its test | MEDIUM | red: an empty keyset and a false-attestation receipt each render a misleading label on one route; green: both read NOT CHECKED consistently on both routes | merged@2026-09-27T01:33Z | Merged bbe307d8, pushed; unanimous 2/2 APPROVE. |
|
|
111
|
+
| S-09 | BACKLOG 40: `P3.implementer-prompt-has-no-check-authoring` is phrase-based only | tests/moat/p3-*.sh (add a behavioral assertion; do not weaken the existing phrase check) | MEDIUM | merged@2026-09-27T07:33Z | 3 rework rounds, full history preserved in git log (601d1739 and its ancestors). Round 1 CONCERN found+fixed a line-boundary blind spot (multi-line prose defeated the detector) and an undisclosed array-literal false positive. Round 2 CONCERN found+fixed a double-period regression the round-1 fix introduced (switched from a "." -join trick to a real newline join). Round 3 investigated a described CRLF false-negative, found it did NOT reproduce, and instead found+fixed the real bug (CRLF blank lines read as bare `\r`, not empty) -- disclosed transparently rather than silently implementing the wrong framing. Final quorum: unanimous 2/2 APPROVE; the one blocking note (a stale header comment + an `[^.]` awk/grep mislabeling) fixed directly by the Captain (97bfaa84) rather than a 4th rework round, since both reviewers independently confirmed the underlying code was already fully correct. One non-blocking follow-up logged: whitespace-only blank lines not yet treated as paragraph breaks. |
|
|
112
|
+
| S-10 | BACKLOG 41: `P1.different-tree-fails` lacks an in-script no-edit control | tests/moat/p1-*.sh | LOW | add the control described (an unedited copy verifies 0 / clean); case still passes, control documented inline | merged@2026-09-26T21:22Z | Confirmed on main directly at 368332cf (this row was stale: BOARD said `review` but the commit was already an ancestor of origin/main). |
|
|
113
|
+
| S-11 | BACKLOG 42: `doctor --airgap` "local" is a loose substring match, ignores remote `OLLAMA_HOST` | autonomy/loki (airgap audit only) or loki-ts doctor.ts, its test | MEDIUM | red: `OLLAMA_HOST=https://remote.example.com` still reads as local because the string contains "ollama"; green: a remote OLLAMA_HOST counts as required egress | merged@2026-09-27T01:33Z | 698ce1c8, pushed; ships in next release cut. |
|
|
114
|
+
| S-12 | BACKLOG 46: P2 advisory-only case's positive control differs from the probe in two variables | tests/moat/p2-*.sh | LOW | control now uses an exogenous gate with no tests, matching the probe's other variable exactly; case still passes | released@2026-09-27T01:33Z | 0a59f420 confirmed ancestor of origin/main; note corrected, was stale. |
|
|
115
|
+
| S-13 | BACKLOG 48: same-class D7 hardening -- `loki outcomes canary verify`, `proof share`/`show` heredocs, empty PATH component | autonomy/loki (the specific inline python3 sites named), its test | MEDIUM | merged@2026-09-27T01:33Z | Merged bb99e675, pushed; quorum topped up 2/2 APPROVE. RED leg pins a literal parent SHA (reachability-checked, SKIP on a shallow clone) instead of HEAD, confirmed to survive being merged. `loki_verify_tool_path()` rejects any non-absolute PATH entry. Quorum reviewer confirmed all 5 hardened call sites fail closed (hard error), never silently fall back to a bare unscoped python3. |
|
|
116
|
+
| S-14 | BACKLOG 49: verifier stdout still says `ok: true` on ABSENT/NOT CHECKED while exit is 1/2 | autonomy/loki (`cmd_proof verify)` case), its test | MEDIUM | merged@2026-09-27T09:24Z | `TAMPERED if attestation=="FAILED" or hash_ok is False`; both JSON and `--human` share one verdict computation. Unanimous 2/2 APPROVE. Reviewer 2 independently isolated the hash-only-corrupted case (a scenario reviewer 1's body-mutation approach couldn't architecturally produce, since receipt_sha256 and verification.hash are the same canonical digest by design) and confirmed the `or`'s hash_ok disjunct correctly fires TAMPERED there too. Both reviewers confirmed the `--human` residual gap is real but non-blocking (exit code and stderr both correct; a pure-stdout consumer sees a weaker finding). f8deb64a. |
|
|
117
|
+
| S-15 | BACKLOG 50: remote NOT CHECKED returns 0, local returns 2 -- align or document | the remote verifier path, docs/exit-codes.md | LOW | either the remote exit is changed to 2 with a test proving it, or docs/exit-codes.md documents the divergence explicitly with the reason; pick one and record which in the commit message | merged@2026-09-27T01:33Z | Main since 34198ff4. Round 1 found the first draft factually wrong (missed the nopubkey unconditional-exit-1 override), corrected and re-approved. |
|
|
118
|
+
| S-16 | BACKLOG 22 follow-on / housekeeping: `scripts/release.sh` only bumps 3 of the 14 files CLAUDE.md's release checklist requires (VERSION, package.json, vscode-extension/package.json) | scripts/release.sh | MEDIUM | building@2026-09-27T07:02Z | Rebased to ed565709. Fixed the subshell-scoping bug (`--dry-run`/`--help` silently broken) and switched to anchored per-format sed slots for drift-safety. 2/2 reviewers ran independently: reviewer 1 (Opus) APPROVE, one non-blocking permissions note. Reviewer 2 (Sonnet) CONCERN, blocking: `apply_sed()`'s mktemp+mv silently narrows all 14 touched files from 644 to 600 on every release (mktemp always creates 600, mv keeps the temp file's mode, not the original's) -- confirmed live on a real bump run. Fix (`cp -p` after mktemp, before the sed redirect) dispatched as rework; full verification suite (subshell fix, drift-detection, idempotency, fail-closed assert, plus the new permissions check) to be re-run before a fresh quorum. |
|
|
119
|
+
| S-17 | BACKLOG 43: council/runner test-result readers (`completion-council.sh`'s 4 `python3 -c` sites) can be shadowed by a committed `hashlib.py`/`json.py` in the agent's own repo (cwd module shadowing, honest-verdict, HIGH) | autonomy/completion-council.sh (the 4 named `python3 -c` test-results readers only, not the S-07 vote site), its test | HIGH | merged@2026-09-27T05:15Z | Rebased onto current main in worktree-agent-a5422f6f162d3dd2f (now at 23025a09), NOT yet merged -- HIGH tier requires 3+1 unanimous APPROVE (D12/D13) before merge, which has not run against this diff. Found the CODE fix already shipped in 3bc40efb (all 43 inline python3 sites in this file, including all 4 named readers, already have the D7 pattern) -- this slice is test-coverage-only, no production code changed. Extended tests/moat/p2-honest-verdict.sh's existing P2.council-readers-not-shadowed case to drive the 3 previously-untested readers (council_heuristic_review, council_evaluate_member, council_devils_advocate_review) via mutation-cycle verification (stripped each site's filter, confirmed shadow fired/verdict flipped, restored, reconfirmed clean). No cases.txt/pending.txt change (no new case ID). Solo-verified (not a substitute for quorum): moat matches main (3 of 9, no rule failed), shellcheck clean (one pre-existing unrelated SC2034 warning). Full 4-reviewer HIGH-tier quorum: 3/4 APPROVE, 1/4 CONCERN -- NOT unanimous, rework needed. Reviewer 3 (Opus) found a real, more severe, OUT-OF-SCOPE bypass in the SAME file's reader hardening (bucket-(b) per D21, not a veto on this test-coverage-only slice): the readers' `python3 -E -c` calls have no `-I`/`-S`/fixed-path resolution, lighter than BACKLOG 129's equivalent fix; reproduced live via a planted `.pth` flipping a genuinely-failing verdict to CONFIRMED_COMPLETE. Filed as BACKLOG 134. Reviewer 4 (Sonnet) CONCERN, blocking, reproduced live: the 3 new call sites (`tests/moat/p2-honest-verdict.sh:802-804`) discard rc/stdout and rely only on a shared marker file staying empty -- a typo'd function name (verified: renaming `council_heuristic_review` to a nonexistent name) still reports PASS, since a nonexistent-function call never touches the marker either. Fix: assert rc/vote-text differs between the fail and green legs for each of the 3 new calls (reviewer already confirmed each site's distinct fail/green vote text: council_heuristic_review -> VOTE:REJECT/VOTE:APPROVE; council_evaluate_member -> CONTINUE.../COMPLETE...; council_devils_advocate_review -> OVERRIDE_CONTINUE/CONFIRMED_COMPLETE). Same reviewer also found a 6th reader, `council_managed_should_stop` (already D7-hardened, gated behind 3 default-false experimental flags, not currently exploitable) not covered by this case -- filed as BACKLOG 135, non-blocking follow-up, not part of this rework. Rework commit 4df70b2d (rebased): `council_call_args` now captures and asserts each call's actual vote-text output against the pattern the file's pre-existing 2-reader loop already uses, matching each site's real fail-leg/green-leg strings verified against completion-council.sh source directly. Also fixed a subtler fixture-contamination bug found during rework: `council_heuristic_review`'s original fixture file independently drove REJECT via a separate grep check regardless of whether the D7-guarded reader even ran; switched to a neutral empty file so the assertion depends only on the reader under test. Typo-reproduction re-verified for all 3 sites (before: silent PASS; after: loud FAIL naming the broken site). Full mutation cycle re-verified. Fresh 4-reviewer HIGH-tier quorum: reviewer 1/4 (Opus) APPROVE, independently confirmed the typo test both ways (renamed the test's call AND separately renamed the production function), verified every expected vote string against completion-council.sh source directly, independently reproduced that the neutral-fixture fix is genuinely necessary (the original evidence file's own text content drives REJECT via the role's own grep check, masking a stripped D7 filter at the heuristic reader specifically), and ran the full mutation cycle per-site and combined. No blocking findings. Reviewer 3/4 (Opus) also APPROVE: confirmed the vote-text comparison is exact-match (not a fooled-by-prefix risk), found one genuine limit (the devil's-advocate result-WRITER site at completion-council.sh:4058 is uncaptured stdout, so a decoy vote there could theoretically slip past the vote-text check alone -- but confirmed via its own mutation that the marker check independently catches this case, proving the two checks are complementary, not redundant), reproduced the typo test on 2 of 3 sites, and confirmed the case's own claims stay within what it actually tests (does not overclaim coverage of the separate BACKLOG 134 gap). Flagged (and I confirmed clean, transient) a worktree hygiene note: other review agents' own scratch scripts briefly appeared in this shared worktree's tests/moat/ directory during concurrent review, causing a spurious DUPLICATE SCRIPT moat failure for one reviewer -- verified via git status that nothing persisted or got tracked. Reviewer 4/4 (Sonnet, the original round-1 CONCERN-finder re-checking their own finding) also APPROVE: reproduced the original bug fresh against the pre-rework file for all 3 functions (confirmed the gap was not limited to just one), confirmed all 3 typos now fail loudly against the reworked file, and went further than the original ask by testing a stronger variant not explicitly claimed by the commit -- swapping one function's definition to occupy ANOTHER's name (wrong-function-called-instead-of-missing) -- and confirmed the assertion catches that too, since all 3 sites' vote vocabularies are pairwise distinct. Reviewer 2/4 (Sonnet) also APPROVE: confirmed the 6th-reader scope from BACKLOG 135 still holds and is unchanged, found a real but genuinely out-of-scope bypass (a stub function redefined inside the test harness's own subshell can fool the vote-text check -- requires editing the test itself, not achievable via the actual PYTHONPATH-shadow threat model this test defends against), and caught its own FIRST mutation-cycle attempt was too weak (only proved the marker fired, not the vote-text check specifically) -- consulted the advisor, redid it per-site, and confirmed all 3 vote-text brackets genuinely fire on their own, not just the marker. **Unanimous 4/4 APPROVE. Merged to main (410046ce).** |
|
|
120
|
+
| S-18 | BACKLOG 149 (escalated from BACKLOG 44, real production gap not just test-coverage): the GH CLI's own `hosts.yml` credential file is completely unprotected by Rule-of-Two's env-var withhold -- an injected prompt can just run real `gh`, which resolves credentials from `$HOME` regardless of the withheld env vars | autonomy/run.sh (the withhold call site), loki-ts/src/runner/github_token.ts (Bun equivalent), tests/moat/p9-rule-of-two.sh | HIGH | building@2026-09-27T13:37Z | **ROUND 2 REJECT (new reviewer), a different and more severe bypass than round 1**: round 1's fix (env sentinel + GH_CONFIG_DIR + git credential.helper reset via GIT_CONFIG_COUNT/KEY/VALUE) correctly closes both round-1-confirmed bypasses -- verified independently by BOTH round-2 reviewers (one APPROVE, one REJECT, but the REJECT's own verification of the round-1 fixes is itself a clean pass). The REJECT is for a THIRD, previously undisclosed and unhandled vector: **SSH transport is completely unhandled**. Every round-1 mechanism (token sentinel, GH_CONFIG_DIR, credential.helper reset) covers only HTTPS-based git/gh credential resolution -- none touch SSH_AUTH_SOCK, GIT_SSH_COMMAND, core.sshCommand, or ~/.ssh. Reproduced live, read-only: `ssh-add -l` exits 0 (the provider session's live, untouched $HOME/env always has a reachable SSH agent by the fix's own design), and `ssh -T git@github.com` completes full auth as the real account, completely unaffected by every round-1 mitigation. An agent can simply `git remote set-url origin git@github.com:<owner>/<repo>.git && git push` and authenticate exactly as an unrestricted session -- simpler than the already-disclosed `gh auth token -u <username>` gap (no username lookup, no keychain tooling, just the operator's normal always-on ssh-agent). The P9 test's own PASS assertion text is unqualified and false for this case. Fix path per the reviewer: extend the existing capture/apply/restore/depth-counter architecture (already correct for the HTTPS vars) to also sentinel SSH_AUTH_SOCK and override GIT_SSH_COMMAND/core.sshCommand for the withheld session -- a bounded addition to an already-sound design, not a redesign. Two secondary non-blocking findings folded into the rework: (1) `env -u GH_TOKEN -u GITHUB_TOKEN gh auth token` is an undisclosed sibling of the already-disclosed username-lookup gap, needs naming; (2) the Bun/TS route has no git-version floor check the bash route already added, silently no-oping the credential.helper reset on git < 2.31 with no operator signal. Per the founder's D25 directive, this does NOT block the current release train -- the vulnerability this slice fixes (both round-1 and this newly-found SSH gap) is already live in published v9.55.0 either way; S-18 ships in its own train the moment its review reaches unanimous APPROVE. Rework dispatched. |
|
|
121
|
+
| S-41 | BACKLOG 139 (top-ranked GF-3 follow-up): shipped composite GitHub Actions (`.github/actions/issue-to-pr/action.yml`, root `action.yml`) still put `GH_TOKEN` in the SAME step as the agent invocation -- an agent can read another process's environment via `/proc/<ppid>/environ` on hosted Linux regardless of its own env | .github/actions/issue-to-pr/action.yml, root action.yml | MEDIUM | merged@2026-09-27T07:26Z | Root action.yml was already correct (3 agent-invoking steps never had GH_TOKEN); the real violation was `.github/actions/issue-to-pr/action.yml`'s single fetch-and-run step, split into a token-holding fetch step (writes a PRD file via `gh issue view`) and a token-free `loki start <file>` step (file-mode). Also blanks all 4 token vars on root action.yml's 3 agent steps as defense-in-depth. Unanimous 2/2 APPROVE, both fully independent and adversarial (output-tampering, argument-injection, PRD-content-leak angles all checked clean). One non-blocking follow-up filed: an owner/repo parsing divergence on refs with extra slashes (cosmetic, `gh` rejects either way). 8a714c73 (cherry-picked onto local main, pending push). |
|
|
122
|
+
| S-42 | BACKLOG 140: `docs/environment-variables.md`'s `LOKI_ALLOW_AGENT_GITHUB_TOKEN` description is imprecise -- says tokens are "used only by Loki's own push and PR steps," but omits the Bun route (drops the token outright, no push/PR step), the `gh` CLI and proof-check.sh re-grant sites, and the 2 enterprise-token variables entirely | docs/environment-variables.md | LOW | merged@2026-09-27T07:07Z | Docs-only, single table cell, skip-rule per SDLC fleet pattern (no review quorum needed). All 4 re-grant sites and both routes' behavior grep-verified against actual source before writing. 32d914f0 (cherry-picked onto local main, pending push). |
|
|
123
|
+
| S-43 | BACKLOG 133: `scripts/v10-pulse.sh`'s `PULSE_MOAT_RESULT` file isn't tied to the commit it was measured against -- a stale capture from an earlier commit would read as clean today | scripts/v10-pulse.sh (moat-regression check only), its test | LOW | merged@2026-09-27T07:39Z | Sidecar-file convention (`<PULSE_MOAT_RESULT>.sha`, written before the suite runs) compared against `$PULSE_MAIN_REF`'s resolved HEAD; 3 fail-closed paths all demote to UNKNOWN, never false-clean. Rejected a read-time env-var alternative that would have reintroduced the exact bug. 1/1 APPROVE with 2 non-blocking wording nits, one applied directly (the no-provenance error message now says "BEFORE running the suite" instead of the more ambiguous "alongside"). 34/34 tests pass on bash and real bash 3.2.57. 7dd23bcb. |
|
|
124
|
+
| S-44 | BACKLOG 143 (escalated from watch-item to active fix after 4 confirmed occurrences, all the same shard index): CI's "Shell tests (shard 2/4)" hangs past its 20min timeout-minutes with no other shard affected | tests/run-all-tests.sh | MEDIUM | merged@2026-09-27T11:41Z | **CORRECTS THE WHOLE SESSION'S FRAMING: shard 2/4 was never hanging.** `test-ci-json-argmax.sh` legitimately takes 5-22 minutes (builds a real ~29K-116K "except:" finding diff to exercise ARG_MAX handling); the workflow's `cancel-in-progress` concurrency group killed it mid-run every time a new push landed first -- confirmed via `gh run view --log` on all cancelled runs, cut off inside argmax every time. This is the same push-storm-cancels-CI pattern this session already knew about at commit level, just never connected to the "shard 2 hangs" symptom until now. Fix: per-suite START/END timestamp logging + a `timeout` wrapper (450s default, named overrides for argmax at 2400s and the trust-core mutation-probe suite at 900s) so a suite that TRULY hangs fails loudly and names itself, instead of consuming the whole shard silently. Caught and fixed 2 self-introduced regressions (wrong PID captured for signal delivery when backing `timeout` through a bash function; SIGINT/SIGQUIT pre-ignored by backgrounding, breaking real Ctrl-C). 2 full 4-shard runs, 489/494 pass both times, same 5 pre-existing environment-specific failures independent of the runner. Did NOT touch test.yml's timeout-minutes (shard 2's legitimate runtime, ~33min, exceeds any reasonable job timeout to add one). Headline caveat: does not stop cancel-in-progress from killing shard 2 on a fast push cadence -- that needs a follow-up shrinking/relocating the argmax fixture. Unanimous 2/2 APPROVE, exceptionally thorough (both reviewers independently reproduced every mechanism from scratch with self-written fixtures, ran real suites across multiple shards, confirmed exact-match named-override safety). Merged 41db33c4, 44/44 reconfirmed on main. |
|
|
125
|
+
| S-19 | BACKLOG 45: `P4.three-setups-resolve`'s pass bar lets a documented spelling silently dispatch the wrong model (e.g. `--session-model high` sending sonnet) with only a note, not a failure | tests/moat/p4-*.sh (the three-setups case only) | MEDIUM | red: construct the silent-wrong-dispatch scenario, confirm the case currently notes it but still passes; green: the case fails when a documented spelling dispatches a different model than documented | merged@2026-09-27T01:33Z | 885b1c1d @ worktree-agent-acb0607e467ebc729, unanimous 2/2 APPROVE, merged. IMPORTANT: found that GF-4 (still unmerged) would falsely claim P4.three-setups-resolve is promotable under GF-4's own catalog changes when it actually still silently mis-resolves high/small under this stricter bar -- GF-4's reviewer must re-check this before GF-4 merges, or the merge will look like a ratchet regression. |
|
|
126
|
+
| S-20 | BACKLOG 47: moat bootstrap is not refused on a hotfix/release branch once any moat release already exists on origin (a branch cut before the first carrying tag runs in bootstrap, unratcheted) | tests/moat/run.sh (the bootstrap-detection logic only) | MEDIUM | merged@2026-09-27T09:42Z | Mirrors `read_baselines()`'s `-l`/`-L` pair, fixes a newest-tag naming collapse, distinguishes grep error from no-match. Unanimous 2/2 APPROVE; reviewer 2 stress-tested at 1001 unreached tags (no perf/correctness issue) and found a real, pre-existing (not introduced here) blind spot shared with `read_baselines()`: a symlinked pending.txt at an unreached tag is invisible to `git grep -l`/`-L`, filed as a non-blocking BACKLOG follow-up. f064ce61, verified locally: 54/54, real moat suite byte-identical, 4/9 proven, no rule failed. |
|
|
127
|
+
| S-21 | BACKLOG 61: `evidence-block.json` writes the raw `$test_pass` in the block path, so `tests.pass` can read true for an inconclusive test axis when another axis blocks | autonomy/completion-council.sh (the evidence-block.json write site only, ~line 2792), its test | MEDIUM | merged@2026-09-27T01:33Z | Merged 8431bb39, pushed; quorum topped up 2/2 APPROVE. Same defect class BACKLOG 55 already fixed for evidence-gate-details.json, mirrored to this sibling write site. 60/60 on test-evidence-gate.sh (was 51/51). |
|
|
128
|
+
| S-22 | BACKLOG 63: `council_augment_from_managed_memory` runs `python3 -m memory.managed_memory.retrieve` after `cd "${PROJECT_DIR:-$(pwd)}"`; with PROJECT_DIR unset this can run the AGENT's own repo's memory/ package into the council prompt | autonomy/completion-council.sh (this one function only), its test | HIGH | merged@2026-09-27T01:33Z | Merged a8e749be, pushed; quorum now 3/4 APPROVE + 1 CONCERN, the CONCERN scoped to the sibling `council_should_stop` function this diff doesn't touch, tracked separately as BACKLOG 127/S-25 and now also fixed and merged. PROJECT_DIR unset now returns 0 immediately (fail-closed no-op), matching the existing D7 pattern in council_managed_should_stop. Production unaffected (run.sh always sets PROJECT_DIR before sourcing this file). BACKLOG 127's sibling shadow-write RCE fix (56eb866f) separately re-verified from scratch by 2 fresh reviewers (unanimous APPROVE, no blocking findings), settling an earlier quorum-count discrepancy; independent RED/GREEN/control repro confirmed real on both bash 3.2 and bash 5.3. BACKLOG 132 opened for a bash-3.2-only mutant-detection gap the reviewers found in that fix's own test. |
|
|
129
|
+
| S-23 | BACKLOG 68: the resume union never prunes entries that became tracked -- a file the user committed between sessions is still unstaged by the session commit while the receipt lists it as modified | autonomy/run.sh (the resume-union logic only), its test | MEDIUM | merged@2026-09-27T01:33Z | Merged 0bff408e, pushed. Two follow-up fixes combined on top of 5610cebb: (1) bash 3.2 syntax (5 apostrophe-in-comment instances, verified against a real 3.2.57 binary); (2) marker-clear bug (turn-in-flight cleared even on anchor-write failure, silently reintroducing the fail-unsafe scenario -- gated on write success). Merging this into main (which already had S-24's tamper-detection seal) surfaced a REAL interaction bug neither fix's own review could see in isolation: 6 test cases used `resume_log="$(setup_agent_branch ...)"`, a command-substitution subshell whose `_LOKI_SNAPSHOT_SEAL` update never reaches the parent shell -- a stale seal then mismatched the live (correctly pruned) files and fired a false SNAPSHOT_TAMPERED warning, blocking every commit. Confirmed test-only (production calls setup_agent_branch directly, never in `$(...)`); fixed by redirecting to a file instead, matching a pattern one existing test case already used with a comment documenting the exact hazard. 55/55 passing. Lesson: full-suite verification AFTER combining independently-reviewed fixes is not optional when they share mutable state. Follow-up review batch (marker-clear fix, merge-conflict resolution, 6-test-site subshell fix) closed: unanimous 2/2 APPROVE, no blocking findings, 62/62 and moat unchanged. Non-blocking notes recorded as BACKLOG follow-ups (stray stderr on failed tmp-write, a contrived directory-as-anchor edge case that still fails safe, no warning when the marker stays stuck). |
|
|
130
|
+
| S-24 | BACKLOG 70: the snapshot/hash state lives in agent-writable `.loki/state` -- an adversarial agent can add entries (hide/uncommit files) or delete the hash file (suppress preexisting_modified disclosure) | autonomy/run.sh (snapshot/hash file location and read/write guards only), its test | HIGH | merged@2026-09-27T01:33Z | Merged c983c4fc + the awk-bypass fix c315cbe9, both pushed; quorum now 4/4 APPROVE on the awk fix. In-memory seal, checked at 3 read sites; a mismatch forces the existing fail-closed "commit nothing" path. Two rounds of adversarial review found and closed two real bypasses (`.pth`-file hijack, then a relocated `awk`-on-PATH bypass in the fix for the first). Digest computation now uses only fixed-path system tools and pure shell string handling, with hex validation. 51/51 regression, moat unchanged. BACKLOG 129/130 track the remaining follow-ups (writer/reader paths still bare python3 -E, audit-log digest values, session-created.z unsealed); BACKLOG 129's writer/reader hardening (merge 3e374500) now at full 4/4 HIGH-tier APPROVE quorum. Both bypass classes independently re-reproduced and re-confirmed closed by the top-up reviewers (.pth in Homebrew's own site-packages, fake git on PATH); legitimate-case output confirmed byte-identical pre/post fix. Non-blocking: BACKLOG 131 corrected for an undercounted/misattributed git-call inventory and a missing core.worktree mention; BACKLOG 132 opened for a bash-3.2-only mutant-detection gap in the shadow-write fix's own test (unrelated slice, found during the same top-up pass). |
|
|
131
|
+
| S-26 | Founder directive: `scripts/v10-pulse.sh`, the anti-drift status/violation reporter (docs/v10/CONTROL.md). See docs/v10/BACKLOG.md for the full spec. | scripts/v10-pulse.sh (new), tests/test-v10-pulse.sh (new), tests/run-all-tests.sh (registration) | MEDIUM | merged@2026-09-27T03:57Z | Rework commit 169d7cbb (worktree-agent-a612cc8e14bb1265a, rebased onto current main) addresses all 3 original CONCERN findings: (1) git calls now explicitly pinned to `$PULSE_MAIN_REF` (6 call sites, verified by grep -- no bare git describe/log/show/rev-parse remain that should be pinned); (2) `--first-parent` added to the tag..MAIN_REF walk, verified against real repo history (128 commits without vs. 80 with, ~32min difference from swarm merge patterns) and a synthetic backdated-branch fixture; (3) MOAT_REGRESSION redesigned around `PULSE_MOAT_RESULT` (a file path to a captured `tests/moat/run.sh` output) as the sole trusted source -- a live suite FAIL is now always a violation regardless of count, a count-only drop fires separately, and with no result supplied the check reports UNKNOWN rather than a false clean. Real behavior change, disclosed by the builder: a default run with no `PULSE_MOAT_RESULT` can no longer exit 0 for this specific check. 31/31 own tests pass (both bash and real bash 3.2.57), shellcheck clean. Re-review: 2/2 APPROVE. Reviewer 2/2 (Sonnet) independently verified all 3 fixes via mutation testing (reverting each fix flips exactly its own test(s)), fed PULSE_MOAT_RESULT 5 different input shapes (real output, hand-crafted fixture, garbage, empty, nonexistent path) all degrading correctly to UNKNOWN or a true parse, confirmed the diff is scoped exactly to the 3 fixes with no regression elsewhere (31/31 full suite, bash -n and shellcheck clean on both bash versions, exit-code/BOARD/CONTROL.md checks all still correct against the real repo), and found one non-blocking documentation-precision nit (header comment doesn't mention the deliberate COULD-NOT-CHECK exclusion, though the actual code and its test T16b handle it correctly). Reviewer 1/2 (Opus) independently confirmed all 3 fixes with its own live/synthetic fixtures (cloned repo with HEAD pinned to an older tag to prove MAIN_REF pinning; a backdated-branch-merged-later fixture for --first-parent; a real `bash tests/moat/run.sh` run fed through PULSE_MOAT_RESULT showing the true 2-of-9-FAIL state where the original code claimed 3-of-9-clean) and flagged one good forward-looking note (the moat-result file isn't yet tied to a commit SHA -- tracked as BACKLOG 133 for the hook-wiring work, not blocking this merge). Unanimous 2/2 APPROVE. **Merged to main (3c3da457).** |
|
|
132
|
+
| S-27 | BACKLOG 125 B-1: P7 scanner reassignment-fallback bypass -- `let rows = data; if (!rows.length) rows = [rows]; setRows(rows);` -- `DECL_ARR` only matches the declaration form, never a later bare `x = [` assignment | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | merged@2026-09-27T07:55Z | New `REASSIGN_ARR` regex + `DECL_KEYWORD` guard catches a fabricated array reassigned after declaration. Unanimous 2/2 APPROVE, both reviewers independently reproduced the bypass with their own fixtures. Non-blocking flag for whoever merges S-28 second: on a destructuring/parameter-default fixture that ALSO flows to a setter (untested by either slice today), whichever arm runs first wins the finding's MESSAGE (correct detection either way, just message-attribution -- "reassigned" vs "parameter default"). Recommend reordering DEFAULT_ARR ahead of REASSIGN_ARR when S-28 merges. 94137535. |
|
|
133
|
+
| S-28 | BACKLOG 125 B-2: P7 scanner destructuring/parameter-default bypass -- `const { rows = [rows] } = data;` or `function load(rows = [rows]) {}` -- neither is a `name = [` declaration the scanner recognizes | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | building@2026-09-27T04:02Z | |
|
|
134
|
+
| S-29 | BACKLOG 125 B-5: P7 scanner module-level named fallback table -- `const FALLBACK_ROWS = [rows];` at column 0, referenced later via `data.length ? data : FALLBACK_ROWS` -- the column-0 exemption plus identifier-branch ternary both let it through unless the name matches sample/mock/demo/fake/placeholder | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | merged@2026-09-27T11:20Z | Unanimous review across 6 rounds; round 6 (ab72ba3f) got a thorough final APPROVE that extended the discrimination check to 2 other call sites. Merge was non-trivial (S-29's chain predates S-27/S-32's own merges to this same file); a dedicated merge-pass agent reconciled all three lineages (5 conflict hunks, 2 mid-heredoc splices manually repaired), and a dedicated adversarial reviewer independently verified the reconciliation (read the full ~1364-line diff, confirmed heredoc balance, no duplicate definitions, all 3 lineages' fixtures intact, scanner and moat suite clean, built its own combined 3-lineage fixture confirming no shadowing). VOTE: APPROVE. Merged as 418b8f2f (a real 2-parent merge commit, content taken verbatim from the reviewed merge-pass commit cd0e5124 since main had not moved on this file since the merge-pass agent's own base -- confirmed via `git diff` before applying, avoiding a second unreviewed reconciliation attempt). Disclosed residual gap, not fixed here: an enclosing-paren confusion class (`(x || TABLE) && other` etc.), documented with a `ponytail:` comment for a future AST rewrite. |
|
|
135
|
+
| S-30 | BACKLOG 125 B-6: P7 scanner ternary-against-null bypass -- `const r = loading ? null : [rows];` -- `is_literal(null)` is true so the both-branches-literal exemption suppresses it; should only treat an array/object literal, never null/undefined/empty-string, as the "literal other branch" | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | building@2026-09-27T08:15Z | 1/1 CONCERN: fix only closes half the bypass class. `is_exempting_sibling()`'s `ABSENT` set (null/undefined/''/"") is correct but incomplete -- reviewer independently confirmed `false`/`0`/`{}`/`true` as the exempting sibling ALSO still produce zero findings, same fabrication shape, still invisible. Reviewer's suggested fix (confirmed to close all cases while preserving legitimate exemptions): require the exempting sibling itself be an array literal (`is_literal(v) and v.strip().startswith('[')`), not merely "not one of 4 named absence values." Also: line 920 (the `[rows] : X` ordering) ships with no fixture exercising `is_exempting_sibling` at all -- its own committed fixtures accidentally test the pre-existing identifier-branch path instead. Rework: switch to the array-literal-allowlist approach, add a `[rows] : null`-shaped fixture for line 920's own coverage. Sequences after S-29 per the shared-file note; S-29's own rework will need to route through whichever final helper S-30 ships (not the current is_exempting_sibling if it's replaced). |
|
|
136
|
+
| S-31 | BACKLOG 125 B-7: P7 scanner fabricated-return-from-helper bypass -- `function getRows(d) { if (!d) return [rows]; return d; } setRows(getRows(d))` -- no scanner arm follows a function's return value back to a fabricated literal | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | approved@2026-09-27T09:58Z | Unanimous 2/2 APPROVE (mechanism + corrected comment, independently verified across two review rounds). Merge-base (10e09a98) is behind S-29's still-in-flight, much larger rework chain on this SAME file -- holding merge until S-29 lands to avoid a bad conflict, per the established shared-file sequencing convention. Will need a rebase pass onto post-S-29 main before merge, not a blind cherry-pick. |
|
|
137
|
+
| S-32 | BACKLOG 125 B-8: P7 scanner `Array.from` generator bypass -- `Array.from({ length: 3 }, (_, i) => ({ id: i, action: 'Deployed', user: 'Admin' }))` invents field values inside a generator callback; the existing `Array.from` arm only checks a literal first argument | tests/moat/p7-no-fabricated-data.sh (scanner rule + a new red/green case; never weaken an existing arm) | MEDIUM | merged@2026-09-27T08:26Z | New arm fires on `{length: N}` + concise-object-returning arrow, substitutes arrow params with 0 before reusing `is_literal`, requires >=1 literal string field post-substitution. Unanimous 2/2 APPROVE, both reviewers independently reproduced with distinct fixtures; reviewer 2 verified the 3-way merge onto current main via `git merge-file` before I merged it (zero conflicts, purely additive) and found a new non-blocking gap (nested Array.from generators losing an outer scope's loop variable through substitution) filed as BACKLOG 145. d49b26d7. |
|
|
138
|
+
| S-33 | BACKLOG 128: stale docs assert a `{"runner":"none","pass":true}` writer shape that doesn't exist (D20 corrected this; the real writer, `enforce_test_coverage` at run.sh:13250, writes `pass:"inconclusive"`, a string, never boolean true) | 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 (fixture shapes only; do not touch any assertion logic) | LOW | merged@2026-09-27T04:20Z | Not behaviorally load-bearing (harmless today since runner=='none' is unconditional at every reading site), but honesty/documentation-drift cleanup. Found and fixed a 4th documentation occurrence beyond the original bug report's scope. Confirmed a genuinely interesting residual coverage gap in test-council-convergence-floor.sh's NEGATIVE-B (correctly disclosed, not fixed -- out of this fixture-only slice's scope). 1/1 APPROVE. **Merged to main (90e26308).** |
|
|
139
|
+
| S-34 | BACKLOG 131(b): `_loki_snapshot_digest`'s python3 fallback (used only when neither sha256sum nor shasum resolves anywhere) is not yet routed through `_loki_snapshot_py_tool`/`-S`; a reviewer already reproduced that Homebrew python3 `-I` alone still fires a `.pth` planted in its own site-packages, so this is a confirmed real gap, not theoretical | autonomy/run.sh (`_loki_snapshot_digest`'s python3 fallback branch only), its test | MEDIUM | merged@2026-09-27T04:52Z | Rebased to 0b1293d4 (worktree-agent-a63c48ba10e0c4eb0). Routes the fallback through `_loki_snapshot_py_tool` with `-I -S`, matching the BACKLOG 129 calling convention exactly. RED/GREEN/mutation-verified: reproduced the bypass on the old bare-`python3 -I` shape, confirmed the fix catches it, and separately confirmed `-S` specifically (not just the resolver routing) is load-bearing by testing routing-with-`-I`-only as its own mutation. Legitimate-case output confirmed byte-identical to an independent sha256sum/shasum oracle. Resolver-failure return code changed 0->1 (confirmed behavior-neutral for both real callers). 66/66 on test-branch-lifecycle.sh. Reviewer 1/2 (Opus) APPROVE: independently reproduced every claim in a fresh venv (the .pth-under-`-I`-fires/-under-`-I -S`-inert distinction, the RED/GREEN/mutation cycle, byte-identical legitimate-case output vs. an independent shasum oracle), confirmed the resolver-failure return-code change is behavior-neutral for both real callers with one factual correction (old code returned 127 on a fully-missing python3, not "0 silently" as the builder's note said; conclusion unchanged), and reported the real count is 68/68 (grew from 66 after S-35 also landed), not a discrepancy. No blocking findings; 2 minor non-blocking suggestions (a caller-comment clarification, an optional hex-format check on the fallback's own output). Reviewer 2/2 (Sonnet) also APPROVE: traced the full resolver fallback chain end to end (fail-closed confirmed at both seal and verify time), independently reproduced the .pth proof in an isolated venv, confirmed no completeness gap (grepped the full function body, only one python3 invocation remains and it's routed), confirmed no accidental overlap with S-35's `_loki_snapshot_verify` changes, and self-corrected one review-time framing error via advisor consultation before finalizing. 2/2 unanimous APPROVE. **Merged to main (ef204e24).** |
|
|
140
|
+
| S-35 | BACKLOG 130(a): `_loki_snapshot_verify`'s `SNAPSHOT_TAMPERED` audit log doesn't record the live vs. sealed digest values, so an operator can't distinguish a genuine content change from a flaky hash-tool failure (both produce the identical message) | autonomy/run.sh (`_loki_snapshot_verify`'s audit-log write site only), its test | LOW | merged@2026-09-27T04:31Z | Both digest values added to the audit line; the audit call reordered to read the sealed digest before it gets cleared two lines later (confirmed necessary via direct reproduction, by both the builder and the reviewer independently). No decision logic changed. 1/1 APPROVE. 64/64 on test-branch-lifecycle.sh. **Merged to main (8e46535e).** |
|
|
141
|
+
| S-36 | BACKLOG 130(c): `.loki/state/session-created.z` is not covered by S-24's tamper-detection seal at all -- an agent could add a user's pre-existing files to it, causing a later resume to leave those files out of the snapshot and commit them as session work | autonomy/run.sh (session-created.z write/read sites only), its test | MEDIUM | merged@2026-09-27T11:27Z | Two rounds. Round 1 (d2bf15c7) fixed the seal-failure sentinel to re-arm the guard (`"-"` not `""`). Round 2 (4da1f0d4) closed a FIFO/dangling-symlink substitution bypass found in round 1's review: a pre-check returning a distinct `"?"` sentinel for any non-regular, non-absent path, checked before the existing `[ -f ]` absent-check. HIGH-tier 3-reviewer unanimous APPROVE: reviewer 1 independently reproduced the pre-fix bypass and post-fix closure from scratch, traced the `-e`/`-L` dangling-symlink POSIX semantics precisely (`-e` false, `-L` true, confirming the `[ -L ] ||` half is load-bearing), tested real bash 3.2.57. Reviewer 2 independently confirmed the same, checked an internal TOCTOU angle and directory substitution (both fail safe). Reviewer 3 found a genuinely new angle (an intra-digest TOCTOU between the guard's two separate stat calls), reproduced it as a real race on both bash 5 and 3.2.57, then rigorously traced that it is strictly dominated by the already-disclosed, already-accepted verify-to-merge window at every real call site -- not a new bypass, just the same accepted race class. Merged as 7fd57df5 + 471a0cda (clean cherry-picks, no conflicts), 81/81 tests reconfirmed directly on main post-merge. |
|
|
142
|
+
| S-39 | BACKLOG 137: `tests/moat/p7-no-fabricated-data.sh`'s own workaround for the S-02 hardcoded-path bug (copy-and-sed-rewrite of `tests/lib-extract-client-paths.mjs`/`tests/lib-match-client-routes.py`) is now broken, since S-02 removed the hardcoded literal the sed relied on | tests/moat/p7-no-fabricated-data.sh (lines ~477-501 only) | LOW | merged@2026-09-27T07:13Z | Fixed: `case_webapp_routes` now invokes the two helpers directly from `$REPO_ROOT`, no copy/sed. 1/1 APPROVE (reviewer reproduced the live bug, confirmed fix, ran a false-green check, confirmed `bash tests/moat/run.sh` restores 4/9 proven with P7 PROVEN). bf9776fb (cherry-picked onto local main, pending push). Confirmed locally: moat suite re-run shows P7 PROVEN, 4/9, no rule failed. |
|
|
143
|
+
| S-40 | BACKLOG 141 + 142: GF-3's P9 injection moat case unsets `LOKI_SDK_LOOP`/`LOKI_SDK_MODE`, no Bun-route coverage; found and fixed a real production Rule-of-Two leak in `claude_flags.ts` | tests/moat/p9-rule-of-two.sh, loki-ts/src/providers/claude_flags.ts, loki-ts/dist/loki.js(.map) | MEDIUM | merged@2026-09-27T07:39Z | Fixed `ensureClaudeHelpCache()`'s bare `Bun.spawn` (no `env`, so Bun's startup snapshot bypassed the token-withholding delete) -- now passes `env: {...process.env}`. 1/1 APPROVE (reviewer independently rebuilt dist from source via git-archive and byte-diffed to confirm the shipped artifact is genuinely current, independently reproduced the mutation test showing a real injected push succeeding pre-fix, found additional out-of-scope spawn sites in doctor.ts/quality_gates.ts and confirmed they're unreachable from withholdGithubTokens()'s call path). P9 PROVEN on both routes post-merge, verified locally. 2f506f3e. |
|
|
144
|
+
| S-37 | BACKLOG 3: P9 Rule of Two gaps -- `loki-issue-to-pr.yml` holds issue text, secrets and push in one step; no `author_association` gate on `/loki`; checkout persists credentials; provider env keeps `GH_TOKEN` | .github/workflows/loki-issue-to-pr.yml, tests/moat/p9-rule-of-two.sh | HIGH | parked@2026-09-27T05:18Z | **Duplicate of GF-3** (same BACKLOG 3, same P9 files: .github/workflows/*.yml, tests/moat/p9-rule-of-two.sh). Caught before this was independently dispatched -- parked rather than run in parallel with GF-3 to avoid two agents solving the identical problem on the same files. Un-park only if GF-3 turns out to cover a narrower scope than this row once GF-3's actual diff is reviewed. |
|
|
145
|
+
| S-38 | Founder directive follow-through: wire `.claude/settings.local.json` (local-only, never committed) with SessionStart + UserPromptSubmit hooks running `scripts/v10-pulse.sh`, plus `scripts/v10-drift-audit-counter.sh` for the every-6th-turn drift audit signal | .claude/settings.local.json (gitignored, not a repo file -- no PR/merge, tracked here for visibility only), scripts/v10-drift-audit-counter.sh (new, in-repo, this row's real deliverable) | LOW | merged@2026-09-27T05:47Z | Verified hook exit-code semantics with claude-code-guide before wiring (exit 1/2 on UserPromptSubmit do NOT block, only exit 2 does; pass-through with no wrapper is correct). Combined pulse+counter output is 23-24 lines, under the 40-line budget. Confirmed FIRING FOR REAL via an actual UserPromptSubmit invocation (not just a manual test), captured verbatim in PROGRESS.md. Counter tested standalone across 7 simulated turns, correctly signals on turn 6. Committed `scripts/v10-drift-audit-counter.sh` directly (LOW tier, single new file, no production code path); `.claude/settings.local.json` itself is local config, not committed, per its own gitignore rule. |
|
|
60
146
|
|
|
61
147
|
Every slice above: implement with red-then-green tests, run diff-scoped tests
|
|
62
148
|
plus `bash tests/moat/run.sh` in your own worktree, never touch `main`,
|
|
@@ -73,10 +159,10 @@ not push.
|
|
|
73
159
|
|
|
74
160
|
`tests/moat/cases.txt`, `tests/moat/pending.txt`, `CHANGELOG.md`,
|
|
75
161
|
`docs/v10/BACKLOG.md`, `docs/v10/BOARD.md`, `docs/v10/PROGRESS.md`,
|
|
76
|
-
`docs/v10/METRICS.md`, `
|
|
77
|
-
`VERSION`, `package.json`, `SKILL.md`, `Dockerfile`,
|
|
78
|
-
`plugins/loki-mode/.claude-plugin/plugin.json`,
|
|
79
|
-
`dashboard/__init__.py`, `mcp/__init__.py`, `CLAUDE.md`.
|
|
162
|
+
`docs/v10/METRICS.md`, `docs/v10/CONTROL.md`, `scripts/local-ci.sh`,
|
|
163
|
+
`tests/run-all-tests.sh`, `VERSION`, `package.json`, `SKILL.md`, `Dockerfile`,
|
|
164
|
+
`Dockerfile.sandbox`, `plugins/loki-mode/.claude-plugin/plugin.json`,
|
|
165
|
+
`server.json`, `dashboard/__init__.py`, `mcp/__init__.py`, `CLAUDE.md`.
|
|
80
166
|
|
|
81
167
|
## Generated bundles (Captain rebuilds after every merge touching sources)
|
|
82
168
|
|
|
@@ -102,4 +188,4 @@ numeric rollup.
|
|
|
102
188
|
|
|
103
189
|
| ID | Owner | Branch | File set | Tier | Status | Notes |
|
|
104
190
|
|---|---|---|---|---|---|---|
|
|
105
|
-
| PF-3 | kill-scan sweep |
|
|
191
|
+
| PF-3 | kill-scan sweep | main @ b539391d | autonomy/loki, autonomy/verify.sh, .github, dashboard harness scripts, scripts/cleanup-test-processes.sh, tests/test-runtime-gate.sh, tests/test-backend-floor.sh, 8 new scoping tests | HIGH | merged@2026-09-27T01:33Z | Round 6 fixed the port-overflow bug (narrowed range); unanimous 2/2 APPROVE. Merged to main via --no-ff (b539391d, 21 commits). All 9 new test files verified passing directly and registered in tests/run-all-tests.sh (6560ca95), pushed to origin (5b785b51..6560ca95). No version bump in this push; on main, not yet in a tagged release (latest tag is still v9.54.2 as of this correction). |
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Control
|
|
2
|
+
|
|
3
|
+
Mission: ship correct, reviewed, verified slices to npm continuously, faster
|
|
4
|
+
than drift can accumulate.
|
|
5
|
+
|
|
6
|
+
Priority order when anything conflicts: moat > seal accuracy > delivered
|
|
7
|
+
accuracy > cost > speed. Never trade a higher one for a lower one.
|
|
8
|
+
|
|
9
|
+
## Decisions (one line each; full text and Why/Reverse in DECISIONS.md)
|
|
10
|
+
|
|
11
|
+
- D12: unanimous APPROVE required; a reproduced blocking finding always
|
|
12
|
+
vetoes; a bucket-(b) pre-existing gap the diff doesn't worsen is a new
|
|
13
|
+
slice, never a veto (D21).
|
|
14
|
+
- D13: every review agent pins its model, never inherits the session's.
|
|
15
|
+
- D14-D17: root-caused session terminations to an unscoped `pkill -f`;
|
|
16
|
+
fixed by scoping to the process group; the regression test itself
|
|
17
|
+
twice reintroduced the bug (unsafe decoys, shared process group) until
|
|
18
|
+
self-recorded PIDs, unique tokens, and self-isolation closed it.
|
|
19
|
+
- D18: a hot file was emptied by a scripted write with no read-back
|
|
20
|
+
guard; Read-then-Edit or diff-verify before any scripted hot-file write.
|
|
21
|
+
- D19: a "confirmed solid" verdict only covers what was tested.
|
|
22
|
+
|
|
23
|
+
## Velocity targets
|
|
24
|
+
|
|
25
|
+
- Releases: at least 1 every 90 minutes once CI is green; 30-60/day at
|
|
26
|
+
steady state.
|
|
27
|
+
- Ready slices: at least 8 at all times.
|
|
28
|
+
- Active builders: at least 6 while ready slices exist.
|
|
29
|
+
- Review-pending age: fix or escalate past 45 minutes.
|
|
30
|
+
- Merged-but-unreleased age: cut a release past 30 minutes while CI is
|
|
31
|
+
green.
|
|
32
|
+
|
|
33
|
+
## Rule
|
|
34
|
+
|
|
35
|
+
The first action of every turn addresses the top VIOLATION from
|
|
36
|
+
`scripts/v10-pulse.sh`, before anything else.
|