loki-mode 9.56.0 → 9.57.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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/run.sh +22 -3
- package/dashboard/__init__.py +1 -1
- package/docs/dev/architecture-reference.md +99 -0
- package/docs/dev/project-structure.md +134 -0
- package/docs/dev/release-checklist.md +157 -0
- package/docs/dev/research-foundation.md +29 -0
- package/docs/dev/tmp-cleanup.md +157 -0
- package/docs/v10/BOARD.md +88 -75
- package/docs/v10/OPERATING-MODEL.md +47 -0
- package/docs/v10/PROGRESS.md +162 -0
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
package/docs/v10/BOARD.md
CHANGED
|
@@ -33,17 +33,17 @@ merge (all touch trust-core or security-relevant surfaces), oldest first.
|
|
|
33
33
|
| ID | Owner | Branch @ SHA | File set (summary) | Tier | Status | Notes |
|
|
34
34
|
|---|---|---|---|---|---|---|
|
|
35
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
36
|
+
| GF-2 | P5 slice | main @ c7b2d8b4 | providers/loader.sh, autonomy/loki, bin/loki, docs/air-gapped.md, docs/enterprise/*, README.md, tests/moat/p5-*.sh, tests/test-doctor-json-sentrux.sh | HIGH | released@2026-09-27T15:00Z | Rebased onto current main (past S-11), 4 conflicts resolved (cloud-tag detection + OLLAMA_HOST override are complementary, merged with cloud-tag checked first). HIGH review APPROVE. P5 PROVEN (9/9), pushed. Moat is now 3 of 9 (P5, P6, P7). CORRECTION: the `.loki/state/provider` issue found during verification was NOT a local-only false alarm -- it is a real CI-breaking cross-test contamination bug (test-iteration-grace.sh writes it, poisoning every later test in the same CI shard's shared checkout, including test-airgap-ollama-host.sh); it genuinely broke `Tests` (shard 3/4) on `ba6610dc`. See BACKLOG 126 for the corrected root cause and the fix (shipped, see PROGRESS.md/BACKLOG 126). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
37
|
+
| GF-3 | P9 slice | main @ 4c15ef5b | .github/workflows/*.yml, .github/actions/issue-to-pr, autonomy/run.sh (github_token wrap), loki-ts/src/runner/github_token.ts, autonomy/lib/proof-check.sh, action.yml, docs/environment-variables.md, tests/moat/p9-rule-of-two.sh, tests/test-issue-to-pr-action.sh, loki-ts/tests/runner/github_token_withheld.test.ts, loki-ts/dist/loki.js | HIGH | released@2026-09-27T15:00Z | Rebased cleanly (0 conflicts) onto current main; 4/4 P9 moat cases re-verified fresh at every step, never trusted from a stale note. Full 4-reviewer HIGH-tier quorum, effectively unanimous: 2/4 clean APPROVE, 1/4 APPROVE-with-precondition (found and live-reproduced a real TOCTOU gap via a planted git hook, correctly bucket-(b) per D21, filed BACKLOG 138/139), 1/4 CONCERN citing the same dist-staleness gap independently via commit-timestamp comparison. Fixed by rebuilding loki-ts/dist (confirmed new env-var literals present in the built artifact) and re-verifying: P9 genuinely PROVEN, 4 of 9 moat properties overall (a clean superset of main, zero regressions once `npm ci` corrected an environment gap in review worktrees), 6/6 Bun tests, clean tsc. BACKLOG 140/141 filed for two more non-blocking follow-ups. Per D22, ships alone (release.yml touched: 3 no-cache additions, verified minimal through every review round) -- pushed, its own triggered CI run being watched to green before anything else merges. S-18 and S-37 (duplicate) now unblocked to re-cut once this CI run is confirmed green. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
38
|
+
| GF-4 | P4 slice | main @ 0f214c3f | providers/model_catalog.json, loki-ts/src/commands/start.ts, loki-ts/src/runner/providers.ts, tests/moat/pending.txt | MEDIUM | released@2026-09-27T15:00Z | Both reviewers landed APPROVE (reviewer 2 conditional on the commit-message fix, already applied at cd07adb2; reviewer 1 independently traced bash/Bun parity end to end and found the same commit-message defect). Re-rebased onto main post-S-41, re-verified moat clean (P4.catalog-has-top-model promoted, P7 PROVEN, 4/9) on the real checkout with deps installed. Merged. Correction: this row was left at `review@` after the actual merge -- caught by the pulse's REVIEW_STALE violation, a repeat of the same status-tracking-lag class as S-30/S-32. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
39
|
+
| GF-5 | verdict/security fix | worktree-agent-a9b8124e8cfc6809a @ 399e1f3a | web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-audit-viewer.js, dashboard/audit.py, dashboard/server.py (get_proof), dashboard/auth.py | HIGH | released@2026-09-27T15:00Z | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
40
40
|
|
|
41
41
|
## Priority out-of-band fix (severity: kills unrelated user sessions)
|
|
42
42
|
|
|
43
43
|
| ID | Owner | Branch @ SHA | File set | Tier | Status | Notes |
|
|
44
44
|
|---|---|---|---|---|---|---|
|
|
45
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 |
|
|
46
|
+
| PF-2 | P7 scanner gap fix | main @ fa5de15f | tests/moat/p7-no-fabricated-data.sh | HIGH | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
47
47
|
|
|
48
48
|
## Fixed on main already (not slices; recorded for PO context)
|
|
49
49
|
|
|
@@ -61,88 +61,101 @@ set is declared to avoid overlap with those and with each other.
|
|
|
61
61
|
|
|
62
62
|
| ID | Owner | File set | Tier | Acceptance checks (Wall) | Status | Notes |
|
|
63
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 |
|
|
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 |
|
|
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 |
|
|
64
|
+
| S-45 | BACKLOG 111: pytest "1 passed, 1 error" parses as failed_count 0 and passes | autonomy/run.sh (bd39d359's summary parser only), its test | MEDIUM | red: a pytest run with 1 passed + 1 error exits 0 from the parser's perspective; green: the error count is counted, gate does not pass | released@2026-09-27T15:00Z | Isolated to the pytest summary regex; does not touch any GH-token/withhold code the in-flight security rework owns. Merged 52179cf4 (auto-merged cleanly onto S-44's run.sh diff, different region), 44/44 reconfirmed on main. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
65
|
+
| S-46 | BACKLOG 115: status inference presents a guess as a state | web-app/server.py (`_infer_session_status` only), cockpit/useCockpitState.ts (completed fallback + checklist scoping) | MEDIUM | red: a paused/failed run older than 5 min reads "completed"; green: an explicit unknown/stale status is possible and surfaced | released@2026-09-27T15:00Z | File set disjoint from any moat scanner or run.sh trust-core path. Merged 18013159, 11/11 reconfirmed on main. Terminal statuses trusted regardless of file age; a stale active-looking status or a bare source file now falls through to an honest 'unknown' instead of guessed 'completed'. Also fixed the checklist-scoping bug (a historical session no longer shows the globally-running project's live checklist). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
66
|
+
| S-47 | BACKLOG 116: key misreads hide or zero real data (GitHubPRsPanel statusCheckRollup/state case, EvidenceReceiptPanel cost_usd/files_changed keys, memory-browser camelCase mismatch) | web-app/src/components/GitHubPRsPanel.tsx, web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-memory-browser.js, dashboard-ui/components/loki-overview.js | MEDIUM | red: each named field misreads and shows a false empty/zero; green: each reads the real emitted key, one test per site | released@2026-09-27T15:00Z | EvidenceReceiptPanel.tsx already touched by GF-5 (merged) for a different concern (classify()); this slice is the cost_usd/files_changed key-path only, disjoint lines. Merged 11a3e7fb (auto-merged onto loki-overview.js cleanly, different function), 34/34 reconfirmed on main; builder verified every key against the real writer/API source, not the backlog description alone. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
67
67
|
| S-48 | BACKLOG 128: stale docs assert a `{"runner":"none","pass":true}` writer shape that does not exist (D20 already corrected the real shape) | references/core-workflow.md, docs/VERIFIED-COMPLETION-PLAN.md, tests/test-council-devils-advocate.sh, tests/test-da-veto.sh, tests/test-council-convergence-floor.sh | LOW | docs describe the real writer shape (`pass:"inconclusive"` string); the 3 named test fixtures use the real shape instead of a synthetic `pass:true` | released@2026-09-27T10:58Z | STALE DUPLICATE, already fixed: builder found all 5 target locations already correct (commit c06b50ee, "S-33"), verified directly against `enforce_test_coverage` in run.sh and re-ran all 3 test suites clean (6/6, 9/9, 40/40). No new commit needed. Marking released since the underlying fix already shipped in main. One non-blocking follow-up noted: `test-council-convergence-floor.sh` NEGATIVE-B passes even without the `runner!='none'` guard, since `pass:"inconclusive"` alone already fails `pass===True` -- candidate for a future assertion-hardening slice, not filed as a new backlog item yet. |
|
|
68
|
-
| 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 |
|
|
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 | review@2026-09-27T15:46Z | Disjoint from S-18/BACKLOG 149's run.sh GH-token work and from S-17's vote-text assertions (already merged, different lines in the same file -- verify no line-range collision before editing). Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 6b276aaf (wf_29a75a9c-652-1): 3 readers via _loki_snapshot_py_tool -I -S, new P2 case red pre-fix and green after, mutation red. 2 HIGH reviewers dispatched 15:16. Reviewer B APPROVE; reviewer A CONCERN (reproduced): queue readers at ~3769/~4050 still use bare python3 -E, so a .pth flips the verdict. Rework sent 15:28. Rework 17eeb940+8ce7f1b1: queue and convergence readers isolated and fail closed, no-interpreter veto, byte-identity test. Re-review (HIGH) dispatched 15:40. |
|
|
69
69
|
| S-50 | BACKLOG 137: S-02's dynamic-repo-root fix breaks P7's own sed-workaround for the same bug | tests/moat/p7-no-fabricated-data.sh (lines 477-501, the client-route helper invocation only) | MEDIUM | red: P7.webapp-client-routes-exist fails post-S-02 because the sed target no longer exists; green: helpers run in place or receive the root explicitly, case passes again | 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) |
|
|
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 |
|
|
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) | released@2026-09-27T15: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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
72
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 | review@2026-09-27T15:46Z | NOTE: S-41 (merged 8a714c73) may have already partially addressed this exact split for .github/actions/issue-to-pr/action.yml -- builder must read S-41's actual merged diff first via `git show 8a714c73` and confirm what remains before starting, to avoid redundant or conflicting work. If S-41 already fully closed this, report back as a stale duplicate rather than editing. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 9c64533b: the fix was already in S-41 (8a714c73), so it adds only a step-level test (17 failures on pre-S-41 files, 0 now, 2 mutations red). HIGH reviewer dispatched 15:16. CONCERN: hand-listed action files; detection misses npx loki-mode@ver, path or variable calls and scripts. Rework sent 15:28. Rework 2b81483d: globbed actions, wider detector; it blanked tokens in 3 production steps (incl. Run Quality Review). HIGH re-review is checking whether that breaks PR commenting. |
|
|
74
|
+
| S-55 | Found by S-44's reviewer 1: `.github/workflows/test.yml`'s `Tests` workflow has no `paths-ignore`, so every docs-only `docs/v10/**` push (BOARD.md/BACKLOG.md/PROGRESS.md status bookkeeping) retriggers the full sharded suite and cancels any in-flight run via `cancel-in-progress` -- confirmed as the majority cause of this session's own repeated shard-2 "hangs" (self-inflicted, not a product bug) | .github/workflows/test.yml (paths-ignore only) | LOW | red: a docs/v10/BOARD.md-only push currently retriggers Tests and can cancel an in-flight run; green: a docs/v10/**-only push (and ideally other pure-doc paths) does not trigger Tests, verified by pushing a real docs-only commit and confirming no new Tests run starts | parked@2026-09-27T14:21Z | High value, low risk: directly stops the self-cancellation pattern this session hit repeatedly (including twice from the Captain's own BOARD.md bookkeeping pushes this turn). Do not broaden paths-ignore beyond doc-only globs -- must not accidentally skip Tests on a real code change that happens to touch a doc in the same commit (paths-ignore is all-or-nothing per push: verify no historical commit mixed docs/v10/** with code changes in the same push before landing, or scope the exclusion pattern more conservatively if any did). Built 0ec9c251, never merged. Parked: superseded by S-80 (main runs no longer cancel) and it conflicts with verdict reuse (S-84): a docs-only commit with no Tests run leaves a later release nothing to reuse. |
|
|
75
|
+
| 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 | merged@2026-09-27T14:21Z | Read the BACKLOG 119 fix (dashboard/auth.py validate_token) first to avoid duplicating or conflicting with it -- this slice only wires up the already-written cleanup function, does not touch the security-relevant rejection logic. Also found and fixed a latent crash (bare datetime.fromisoformat instead of the fail-closed _deadline_passed helper validate_token already uses -- would have 500'd on any bad timestamp once wired live). Merged e3c27c6d, 32/32 reconfirmed on main. Correction: this row was stale at building@. Merged as e3c27c6d (ancestor of main, verified with git merge-base --is-ancestor), shipped in v9.56.0. |
|
|
76
|
+
| S-57 | BACKLOG 120: two dashboard-ui test files do not test the shipped code (`ui-components.test.js` asserts hand-copied stale logic and is never run by any test runner; `loki-overview-issue-journey.node.test.mjs` fails 0/5 and is registered nowhere) | dashboard-ui/tests/ui-components.test.js, dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs, tests/run-all-tests.sh (registration only, coordinate: S-44 also touched this file -- rebase onto post-S-44-merge main first) | MEDIUM | ui-components.test.js imports and asserts against the REAL shipped functions (formatGateTime, summarizeGates, formatRunDuration), not hand-copied logic; the journey test is fixed (sets `_data.connected` per the known cause) and passes 5/5; both are registered in a real runner and actually execute in CI | released@2026-09-27T15:00Z | Merged 21a539df, 23/23 + 6/6 reconfirmed on main. Found the real drift: shipped formatGateTime/summarizeGates/formatRunDuration had all changed behavior since the hand-copied test was written; rewrote to dynamically import the real functions after a DOM stub (needed since the components extend LokiElement at class-definition time). Journey test's 6 (not 5) failing cases all traced to one root cause (_data.connected never set), fixed once in the shared mounted() helper. Both registered in run-all-tests.sh, additive alongside S-44's timeout wrapping. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
77
|
+
| S-58 | BACKLOG 114 (scoped subset): false-empty-on-failed-fetch in the cockpit -- `cockpit/useCockpitState.ts` swallows git-status and checkpoint failures, so ChangeReview.tsx says "The working tree is clean" and RiskPanel.tsx says "No checkpoints were recorded" on a FAILED fetch, not a real empty result | cockpit/useCockpitState.ts (the git status / checkpoint fetch error handling only), web-app/src/components/ChangeReview.tsx, web-app/src/components/RiskPanel.tsx | MEDIUM | red: a failed git-status/checkpoint fetch (simulate a 500 or network error) renders the same copy as a genuine empty result; green: a failed fetch renders "Could not load..." distinctly from a genuine empty state, one test per component | released@2026-09-27T15:00Z | Merged 14d80a54, 22/22 (11 pre-existing S-46 + 11 new) reconfirmed on main, no conflict with S-46's earlier changes to the same file. Verified against the real server responses first (a genuine empty case returns HTTP 200, never a rejection) before implementing, confirming the fix's premise; a `settle()` helper now distinguishes resolved-empty from rejected. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
78
|
+
| S-59 | BACKLOG 71: `evidence-gate-details` `tests.ok` stays true for an inconclusive test axis -- `surface_evidence_gate_details` prints `tests_ok=True` next to `tests_inconclusive` | autonomy/lib/proof-generator.py or wherever surface_evidence_gate_details lives (grep first), its test | LOW | red: an inconclusive test axis (zero-test or no-runner) still shows tests_ok=True in evidence-gate-details.json; green: tests_ok is false or absent when the axis is inconclusive, with a test | released@2026-09-27T15:00Z | Real bug, correctly located: `surface_evidence_gate_details` lives in autonomy/run.sh:13966 (not proof-generator.py, which is a different already-correct consumer). Reused the existing 'inconclusive dominates ok' convention already established in proof-generator.py's _classify_func_axis rather than inventing a new pattern. Merged 72afa3e9, 15/15 reconfirmed on main. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
79
|
+
| S-60 | BACKLOG 92: receipt path bases mix under a subdirectory TARGET_DIR -- tracked entries are repo-top-relative, untracked and preexisting_modified entries are cwd-relative, so a receipt read from a subdirectory build shows inconsistent path bases | autonomy/lib/proof-generator.py (path normalization only), its test | MEDIUM | red: a receipt generated with TARGET_DIR set to a subdirectory has tracked-entry paths repo-relative and untracked-entry paths cwd-relative in the same receipt; green: both use a single consistent base (repo-relative preferred, matching the tracked-entry convention), with a test | released@2026-09-27T15:00Z | Merged 6148446f, 76/76 reconfirmed on main. Root cause: git itself reports --numstat repo-relative but ls-files --others TARGET_DIR-relative; fixed by reusing the already-computed prefix/key at one shared point. Builder honestly flagged that a pre-fix receipt from a subdirectory build will now fail hash_ok on re-verify (expected: the old receipts were internally inconsistent). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
83
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 |
|
|
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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
85
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) |
|
|
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 |
|
|
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) | merged@2026-09-27T15:34Z | 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. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built ae200f0c. Reviewer dispatched 15:16. 1/1 APPROVE: red to green confirmed; -z handles spaces and newlines, mutation red. Cherry-picked 8f2d58b0. |
|
|
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 | merged@2026-09-27T15:34Z | 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. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 963dcca5. Reviewer dispatched 15:16. 1/1 APPROVE. Cherry-picked f626cfb4. |
|
|
88
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
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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) |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 | merged@2026-09-27T14:58Z | 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). Reviewer 1/2 APPROVE (12 new tests fail pre-fix, 0 at 5c9a16f2). 2/2 APPROVE (both Tech Leads; mutation-tested). Merges alone at b8f43d08 in train 2; S-75 stacked on it is rejected separately. Train 2: cherry-picked onto main as 59118705. |
|
|
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 | released@2026-09-27T14:31Z | 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). Cleanup done, no repo change: 64 worktrees removed with plain git worktree remove (no --force), 23G -> 11G (du -sh before/after), 30 merged branches deleted with branch -d. 71 remain; 10 not reachable safely: 27 hold commits not on main (git cherry + lines), 21 live or approved, 7 uncommitted edits, 4 created under 2h ago, 3 locked by this session. Pulse violation split to S-94. Classification: scratchpad/s72-classification.tsv. |
|
|
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 | merged@2026-09-27T15:34Z | 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. REJECT (HIGH reviewer 2): 6 reproduced gaps (git add -A never implemented; commit -am and git rm of BOARD.md pass rule 3; git -C checks the wrong repo; --force-with-lease=; xargs kill). Rework dispatched 14:17 from 47179bb3. Rework eb534e96: all 12 gaps from both HIGH reviews addressed (timeout/nice/sudo wrappers, shell keywords, RULE6 git add -A, -am, git rm/mv, git -C resolution, --force-with-lease=, xargs/bash -c unwrapping, VERSION by path, rm -rf of a root, heredoc false block, fail-closed on crash). 78/78, 14 mutations killed. Back with both original HIGH reviewers 14:51. Round 3 sent 14:57. Reviewer 1 REJECT (heredoc strip deletes the rest of the opener line: git commit -F - <<EOF && git push --force returns 0; rc was 2 at 47179bb3) and reviewer 2 CONCERN (kill redirect tokens read as PIDs; $(cat f)/xargs < f not source-checked; if/while/until missing from keywords). Round 3 fixes hold, but both HIGH reviewers REJECT: an unterminated heredoc marker (here-string <<<, a grep for "<<EOF", arithmetic with a space, # comments, CRLF, EOF-X) drops the rest of the command. Round 4 sent 15:16. Round 4 75bfa51d: 2/2 HIGH APPROVE (both reran every round-3 repro; about 190 commands diffed, 0 regressions, 0 false blocks). Cherry-picked db51311a..e9170698. Installed as a local PreToolUse hook in .claude/settings.local.json at 15:33; smoke test: pkill -f, push --force, git add -A and echo > VERSION rc=2; git status and kill PID 2>/dev/null rc=0. Follow-ups (non-blocking): quote state carried across lines; exact terminator whitespace. |
|
|
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 | merged@2026-09-27T15:34Z | 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. CONCERN (reviewer 2): clean-check prints CLEAN and exits 0 when git status itself fails (reproduced). Rework dispatched 14:19 from 94b8d3a6. Round 2 d44a56d0: token allow-list, CRLF-preserving, atomic temp+replace, disk re-read with restore on mismatch (mutation-tested), clean-check exit 2 on git failure; 31/31. 2 re-reviewers dispatched 14:28. Re-review 1: all 6 prior blockers closed; 2 regressions from the atomic write (mode 644 -> 600, symlink replaced instead of written through). Round 3 sent 14:36. Round 3 e5dc3d28: re-reviewer 1 APPROVE; re-reviewer 2 CONCERN (fails closed): header-index lookup refuses the 30 real rows that have one fewer cell than their header. Round 4 sent 14:49 with a full-board sweep test. Round 4 9f8389b9: fallback cell locator for short or long rows, 79-row real-BOARD sweep, 48/48, mutation 34 red. Tech Lead re-review dispatched 14:56. Round 5 4ba139f6 (position rule). 1/1 APPROVE: independent 103-row sweep, 101 flips and 2 safe refusals (S-29, S-36), 0 wrong-cell writes; 52/52 under both shells. Cherry-picked 9ff5e41e..f1a26981. tests/test-v10-ops.sh 52/52 on main. |
|
|
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) | merged@2026-09-27T14:58Z | 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. Reviewer 1/2 APPROVE (S-75 delta isolated: 7 tests fail on S-71-only script). REJECT (reviewer 2): a malformed building@ timestamp (e.g. 2026-99-99T99:99Z) crashes the whole pulse (unguarded parse_time_value -> PULSE ERROR, no status block). Rework dispatched 14:21. Rework 339cd6aa: parse_time_value returns None on an impossible date; bad rows report UNKNOWN in both loops; 48/48 under 3 shells; T22/T23 go red without the guard. Re-reviewer dispatched 14:27. Re-review REJECT: guard only catches a bad month (calendar.timegm), so T24:61, day 99 and Feb 30 pass as parsed (false green or fabricated 300480-min violation). Round 2 sent to the same engineer 14:35. Round 2 f285c138: full-tuple datetime validation, T25-T28 (8 assertions) red on round 1, 56/56 under 3 shells. Back with the original re-reviewer 14:40. APPROVED: re-reviewer re-ran all 5 malformed-timestamp repros on f285c138, all UNKNOWN, no fabricated violation; 8 new assertions red on round 1; other callers fall back safely. Reviewer 1 approved the unchanged code. Merge the stack b8f43d08 (S-71) + 5c9a16f2 + 339cd6aa + f285c138 in train 2. HIGH-builder budget still assumed 60 min pending CEO. Train 2: cherry-picked as c16d875f/ceacd964/03c78213. Live in the main checkout pulse (flagged S-87/S-91 at 14:56). |
|
|
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 | review@2026-09-27T15:46Z | 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. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 30ed0f19 (GUARDS.md + UNEVIDENCED_CLAIM). Reviewer dispatched 15:16. REJECT: GUARDS.md claims the S-16 mode guard is merged (254c3c85 is only on a side branch); the regex counts a bare "exit" or a date as evidence. Rework sent 15:28. Rework 17bb5573: S-16 marked PENDING after merge-base checks; stricter evidence regex. Re-review dispatched 15:40. |
|
|
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 | review@2026-09-27T15:46Z | 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. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built c437ea4a. Reviewer dispatched 15:16. CONCERN: test not registered in run-all-tests.sh. Rework sent 15:28. Rework 06648ac1: test registered. Re-review dispatched 15:40. |
|
|
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 | merged@2026-09-27T14:58Z | Engineer dispatched 14:09 (sonnet). Built 330bcafb: CLAUDE.md 756->150 lines, OPERATING-MODEL.md cmp-identical, 7 doc/regression suites pass. AGENTS.md is gitignored (local-only), so a 74-line draft waits for review before being applied to the main checkout; the live AGENTS.md still instructs pkill -f and rm -rf /tmp/loki-* (D14/D15 patterns). Reviewer dispatched 14:26. 1/1 on the commit: 45 MUST/NEVER rules traced to a home, 99 pointers resolve, no contradiction survives, cmp identical, 4 regression suites pass. The one blocker was in the uncommitted AGENTS.md draft (evidence rule relied on the @ import, unverified for non-Claude tools); fixed by adding it as literal text plus the harness invariants, then applied to the local-only AGENTS.md (542 -> 80 lines, live pkill -f and git add -A instructions gone; backup in TMPDIR). Commit 330bcafb ships in train 2. Train 2: e481bab5. CLAUDE.md conflict was only main's v9.56.0 version line; S-78 text taken (no test reads that line: grep of tests/, scripts/ and workflows found 0). |
|
|
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 | approved@2026-09-27T15:49Z | Engineer dispatched 14:09 (sonnet). Saves 17-23 min per Tests run. Built and committed 81c52fcb: Linux argmax suite 383 ms (was about 22 min); required Wall check reproduced (b842a332^ = ef218d74: small fixture still exits 126; fixed tree passes 3/3). Full scale weekly in integrity-audit.yml. Override removal is in the same commit. 2 opus HIGH reviewers dispatched 14:49 (incl. 64K-page arm64 MAX_ARG_STRLEN check). Merge before or with S-81. Reviewer 2 APPROVE, reviewer 1 CONCERN (hardcoded 4K-page ceiling; the weekly run behind continue-on-error). Round 2 sent 15:12: restore the full-scale fixture (4-9s now). Round 2 28e6b605: full fixture restored everywhere, knob and workflow change reverted, fork removal kept; docker arm64: pre-fix exit 126 (326s), post-fix 3/3 in 7.1s. Re-review by reviewer 1 dispatched 15:40. Round 2 28e6b605: reviewer 1 APPROVE (pre-fix exit 126 at 329s; post-fix 3/3 in 4.3s, and 8.9s at ARG_MAX 4 MiB; diff vs c31cb1e8 touches only loki and run-all-tests.sh). Reviewer 2 approved round 1 and recommended exactly this change. 2/2. Ships with S-81 in train 3. |
|
|
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 | merged@2026-09-27T14:58Z | Built 3bd01787. 2 Tech Lead reviewers dispatched 14:12. Supersedes S-69. 2/2 APPROVE (Tech Leads). Follow-up, non-blocking: a weekly cron and a release push landing on the same SHA would queue, not cancel; strictly narrower than before. Ships in train 2; Release Manager verifies with one real push. Train 2: d5d6bfa7. The train 2 push is its one real-push verification. |
|
|
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 | approved@2026-09-27T14:46Z | Engineer dispatched 14:09 (sonnet). Supersedes S-70. Built dd08f821: duration table for all 496 suites (one CI run), greedy longest-first packing, LOKI_TEST_LIST mode, 17/17 coverage tests incl. n=8. Projected max shard 197s vs 451s today. Reviewers told to recompute the "all 8 exactly 197s" claim themselves. 2 dispatched 14:33. 2/2 APPROVE. Reviewer 1 recomputed the 8 shard totals from the table: 197s each, true; exactly-once at n=4 and n=8; deterministic across bash 5, bash 3.2 and mawk. The 197s assumes S-79 shrinks argmax (real today 1186s, which would sit alone in one shard at about 19.8 min); a second CI sample moves the max shard to 240s. MERGE ORDER: S-79 and S-81 in the same train, S-79 first. Follow-ups: no drift detector for the duration table; T4 recomputes a static count instead of driving the runner. |
|
|
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 | approved@2026-09-27T14:18Z | 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. 1/1 APPROVE. Data: shards 0 and 2 run up to 30 min today; python/bun/node max 5m21s. MERGE HELD until S-79 and S-81 land and a real run shows every shell shard under 10 min. |
|
|
102
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-84 | CEO Part C items 3+5: release verdict reuse (required-ci accepts the parent's success when parent..release touches only version-bump files; select the completed successful run, not head -1 at :143; update the promise comment at :89-93) and drop needs: gate from required-ci plus gate's duplicate pytest | release.yml required-ci and gate jobs only | HIGH | a VERSION-only bump on a verified parent releases without a new Tests run; any non-allowlisted file in parent..release forces a full verdict; loki-ts/dist changes qualify only if the diff is version-string-only | building@2026-09-27T15:46Z | Loki-approved. release.yml: ships in its own train (D22). Built 6f71e7d1 (harness drove the real required-ci script: 5/5 cases; builder caught its own debugId substring bug). Only 2 of the last 8 release commits would qualify (the rest also touched docs/wiki/docs-v10; v9.56.0 dist had stale-build rename noise). Release process must therefore make the bump commit pure, on a dist-fresh verified parent. 2 opus HIGH reviewers dispatched 14:47. Own train (D22). HIGH reviewer 2 REJECT: only dist/loki.js is content-checked; package.json files[] drop, import-time code in mcp/__init__.py and a Dockerfile RUN line all released on the parent verdict even with the release SHA Tests red. Goal case (0.33s) and all 13 error paths fail closed are verified. Round 2 sent 14:53: version-only compare on every allowlisted file, and a red run at the release SHA always fails. HIGH reviewer 1 also REJECT with the same 2 findings plus loki.js.map; addendum sent with their 18-scenario harness. Round 2 c22503dd: every allowlisted file content-checked (CHANGELOG exempt), red run at release SHA fails, .map dropped, 4 wiki/docs files added; 18-scenario harness matches. Builder claims reuse rarely fires (non-deterministic loki.js); contradicts my earlier determinism check, so reviewers must measure it. 2 HIGH re-reviewers dispatched 15:12. Round 2: reviewer A REJECT (line splitting hides \r/U+2028 swaps; a Dockerfile USER line dropped, the image runs as root, confirmed by docker build), reviewer B CONCERN (cancelled counted as failure). Both measured the build as deterministic; reuse fails because of the map debugId plus a stale parent dist. Round 3 sent 15:14. Round 3 55abbebd+f14b2f6e: raw-byte compare, fixed decision order, map JSON compare, semver, --raw modes, CHANGELOG insert-only; 25/25; real b651b98d replay ELIGIBLE with a fresh parent dist. 2 HIGH re-reviewers dispatched 15:34. Round 3 verified by both HIGH reviewers (code), but the tests never drive the real poll loop: reordering branches keeps 25/25 green (reproduced). Round 4 (tests only, plus a leading-zero semver fix) sent 15:43. |
|
|
104
|
+
| S-85 | CEO Part C item 8: Docker arm64 on a native ubuntu-24.04-arm runner instead of QEMU (release.yml:665-687); no gha cache in publish jobs (:54-56) | release.yml publish-docker job and cache config | MEDIUM | multi-arch image still published for amd64 and arm64; publish jobs restore no cache | approved@2026-09-27T14:35Z | release.yml: own train (D22). Different region from S-84 and S-83. Built and committed d8f98328 (native amd64/arm64 by digest plus manifest merge job, qemu removed, cache-binary false; provenance 11/11, SBOM 9/9, P9 4/4). 2 reviewers dispatched 14:29. Own train (D22). 2/2 APPROVE. Manifest-digest technique checked against a real multi-arch index (alpine:latest): sha256 of imagetools --raw equals the registry index digest. Missing arch fails closed (needs + count guard). Non-blocking: stale comment in publish-npm names publish-docker for the dist assert (now in publish-docker-build). Only a real release proves the arm64 runner and timing. |
|
|
105
|
+
| S-86 | CEO Part C item 9: pytest -n auto (test.yml:73), all 4 Python versions still required; fix any order-dependent tests it exposes | test.yml python job, the tests it exposes | MEDIUM | python job wall time drops; 4 versions still required; no test skipped to get green | merged@2026-09-27T14:58Z | Built 0b82b63e: python suite 261.9s serial -> 79-82s with -n auto (14 cores, 3 runs, identical counts 3469/22); one racy test given a private TMPDIR, assertion unchanged. 2 reviewers dispatched 14:37 (asked to verify at -n 4, the CI core count). 2/2 APPROVE: assertion mutation-tested (still red when the tool leaks a scratch dir); no other shared-tempdir hazards; -n 4 x3 deterministic (109-121s on 14 cores). Follow-ups: local-ci/pre-push still serial; pytest-xdist unpinned (matches file convention). Train 2: 6c35aac0. |
|
|
106
|
+
| S-87 | CEO Part C item 10a: remove built-in waits (review-tail stub blocks on a FIFO and drop the 4x scale at :388-390; mock vectors setup in test-e2e-features.sh:344; go-gate stub sleep 60 to 2s; test-dashboard-multiproject.sh:160 poll instead of sleep 25; pytest-gate fixture sleep 10 to 1) | the named test files only | MEDIUM | each named suite is faster, measured before and after; none weakened (mutation check per change) | merged@2026-09-27T15:34Z | OVER BUDGET 14:56 (33.5 min vs 30): told to stop and commit; the rest gets re-sliced. Committed 7935ed68 (worktree-agent-a6e52768add598d70) at 38 min, over budget: 4 of 5 waits cut (go-cargo 24.9s to 12.9s, pytest-gate 13.3s to 2.0s, multiproject 27.3s to 16.9s, e2e 26.6s to 22.2s; each mutation-checked). Remainder re-sliced as S-95. MEDIUM review (with a load-flake check) dispatched 15:05. 1/1 APPROVE: 4 mutations red; 12 runs under 4-way CPU load, 0 flakes. Cherry-picked 11c9df0c. |
|
|
107
|
+
| S-88 | CEO Part C item 10b: parallelize moat P6, P9 and P5 internally | tests/moat/p6-*.sh, p9-rule-of-two.sh, p5-*.sh | MEDIUM | moat suite wall time drops; same cases, same verdicts | ready@2026-09-27T14:21Z | SEQUENCING: p9-rule-of-two.sh is in S-18's file set; start only after S-18 merges. |
|
|
108
|
+
| S-89 | CEO Part C item 11: pip and bun install caches on read-only test jobs | test.yml cache steps only | LOW | cache hits on a second run; never on a job holding a write token or publish secret (P9) | review@2026-09-27T15:46Z | Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built e85a23d4. Reviewer dispatched 15:16. CONCERN: the fixed -A5 permissions window misses a late contents: write. Rework sent 15:28 (parse the YAML). Rework ab32c540: YAML-parsed permissions, 15/15. Re-review dispatched 15:40. |
|
|
109
|
+
| S-90 | CEO Part C item 12: move bun=latest, macOS bun and hyperfine to nightly (test.yml:303-312, 390-400) | test.yml those jobs, a nightly workflow | LOW | those jobs no longer run on push; they run on a nightly schedule | merged@2026-09-27T14:58Z | Built 93482497 (bun matrix 4->1 on push; nightly.yml runs the other 3 plus hyperfine). Reviewer dispatched 14:24. 1/1 APPROVE. Non-blocking: release gate now requires only the pinned bun combo (intended); hyperfine no longer runs for the pinned combo anywhere; macOS-only branches in a few test files now run nightly only. Train 2: 329882d7. |
|
|
110
|
+
| S-91 | CEO Part C item 13: Tier A diff-selected tests with selection rules R0-R7; anything touching tests/lib, run-all-tests.sh, package.json, requirements*, loki-ts/dist, VERSION or .github/workflows runs everything | a selection script, a Tier A workflow or job | MEDIUM | Tier A finishes in 2 min or less on a typical change; the run-everything triggers are honored; Tier A never replaces Tier B | review@2026-09-27T15:46Z | OVER BUDGET 14:56 (33.5 min vs 30): told to stop and commit; the rest gets re-sliced. Committed cb8ddb07 at 39 min (over budget): R0-R7 done, 29/29, P9 4/4 on tier-a.yml, real-commit runs 25s/86s/5s. Remainder re-sliced as S-96. Tech Lead review dispatched 15:08. REJECT: the .py-suffixed grep misses Python imports (workspace_diff.py, fast_verify.py moat miss); R5 targets tests/dashboard only; no dashboard-ui rule. Round 2 sent 15:23. Round 2 52a58e86: import needles, dashboard-ui rule, node match kind; 38/38. Re-review dispatched 15:46. |
|
|
111
|
+
| S-92 | CEO Part C item 14: tests/quarantine.txt (suite, owner, expiry max 7 days, issue); quarantined suites still run but do not block; moat and review suites can never be quarantined; no retry loops | tests/quarantine.txt, tests/run-all-tests.sh (quarantine handling) | LOW | a listed suite's failure is reported but non-blocking; an expired or moat entry is rejected | building@2026-09-27T15:49Z | SEQUENCING: after S-79 and S-81 merge (same runner file). Dispatched 15:49 on top of S-79+S-81. |
|
|
112
|
+
| S-93 | CEO Part C item 15: the 38 unregistered test files: register each or delete it with a reason | tests/run-all-tests.sh registrations, the files | LOW | zero unregistered test files; each deletion has a stated reason | building@2026-09-27T15:49Z | SEQUENCING: after S-79 and S-81 merge (same runner file). Dispatched 15:49 on top of S-79+S-81. |
|
|
113
|
+
| S-94 | Worktree follow-up: triage the 27 worktrees whose branches hold commits not on main (merge, record in BOARD, or discard with a reason), check the 3 with an uncommitted edit to tests/moat/p7-no-fabricated-data.sh, and add a pulse violation for more than 15 worktrees | scripts/v10-pulse.sh, tests/test-v10-pulse.sh (violation only); triage is a Captain decision per branch | LOW | worktree count at or below 10 with no unmerged work lost; the new violation fires above 15 with a fixture | review-blocked@2026-09-27T15:28Z | SEQUENCING: the pulse change waits for S-75 (same file). Triage list: scratchpad/s72-classification.tsv. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built ad60e018 (WORKTREE_COUNT violation). Reviewer dispatched 15:16; worktree triage still pending (orchestrator). CONCERN: git merge-tree with S-76 (30ed0f19) conflicts in both files (adjacent inserts). Rebase onto S-76 after its rework lands. |
|
|
114
|
+
| S-95 | S-87 remainder (CEO Part C item 10): tests/test-review-assurance-tail.sh, which did not finish in 120s on its own (rc=124). Replace the DA-block poll with a FIFO wake, check for orphaned sleep 30/120 children, and drop the 4x LOKI_TEST_SHARD scale only if it is proven safe under 4-way contention | tests/test-review-assurance-tail.sh only | MEDIUM | the suite finishes under 60s alone and under 4-way load 3 times in a row; mutating the code under test still turns it red | building@2026-09-27T15:49Z | Known load-flaky (memory: review-assurance-tail). Measure before optimizing. Dispatched 15:49. |
|
|
115
|
+
| S-96 | S-91 remainder: re-collect the last-10-main-code-commits Tier A selection report (time and selected tests per commit), add bun/pip/npm install caches to tier-a.yml, and set an explicit timeout-minutes on its R0 full-suite path | .github/workflows/tier-a.yml, docs/v10/METRICS.md | LOW | the METRICS.md table shows 10 real commits each under 120s or labeled R0; caches never on a job with write permissions or secrets (P9) | ready@2026-09-27T15:08Z | After S-91 merges. |
|
|
103
116
|
| 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 |
|
|
117
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
105
118
|
| 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 |
|
|
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 |
|
|
119
|
+
| 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 | released@2026-09-27T15:00Z | Merged 7a13b816, test registered f0f51587, pushed. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
120
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
108
121
|
| 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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
122
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
123
|
+
| 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 | released@2026-09-27T15:00Z | Merged bbe307d8, pushed; unanimous 2/2 APPROVE. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
124
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
125
|
+
| 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 | released@2026-09-27T15:00Z | Confirmed on main directly at 368332cf (this row was stale: BOARD said `review` but the commit was already an ancestor of origin/main). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
126
|
+
| 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 | released@2026-09-27T15:00Z | 698ce1c8, pushed; ships in next release cut. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
114
127
|
| 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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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-
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
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 |
|
|
128
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
129
|
+
| 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 | released@2026-09-27T15:00Z | `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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
130
|
+
| 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 | released@2026-09-27T15:00Z | Main since 34198ff4. Round 1 found the first draft factually wrong (missed the nopubkey unconditional-exit-1 override), corrected and re-approved. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
131
|
+
| 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 | review@2026-09-27T15:46Z | 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. Correction: stale building@ with no live agent and no commit of its own (git log --all --grep found none). Re-cut to ready. Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 9bf1ddda (test-release-sh.sh). Reviewer dispatched 15:16 to verify the mode-preservation fix. CONCERN: tests/test-release-sh.sh is never invoked. Rework sent 15:28 (register it). Rework 12f2d681: test registered (mode fix 59fcbaa3 is in the branch). Re-review dispatched 15:40. |
|
|
132
|
+
| 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 | released@2026-09-27T15:00Z | 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).** Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
133
|
+
| 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 | review@2026-09-27T15:40Z | **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. Round 3 built 3af8cdac (stack 6e38257c, 94f8b26a, b8c0eccf): SSH_AUTH_SOCK unset and GIT_SSH_COMMAND=false in the withheld window with a trusted re-grant, Bun git-floor warning, P9 SSH tier mutation-tested. Disclosed residual: direct ssh -i <key>. 2 opus HIGH reviewers dispatched 14:26. Ships in its own train once unanimous (D25). Round 3 HIGH reviewer 1: SSH blocker CLOSED (synthetic agent), re-grant/depth/login shells verified; REJECT for a new reproduced Bun-route bypass: 5 bare git spawns (council.ts:178,:190,:401, prd_reuse.ts:161-175) inherit the startup env with real GH_TOKEN/SSH_AUTH_SOCK, so an agent core.fsmonitor script runs with operator creds. Round 4 sent 14:43. Round 4 9cb330cb: Bun start-env spawn leak, nested run fails closed, SSH re-grant test. 2 HIGH reviewers dispatched 15:05. Round 4 closed all round-3 findings, but both HIGH reviewers REJECT: the trusted push in on_run_complete (default on) and create_session_pr runs an agent-planted pre-push hook or core.sshCommand with every withheld channel restored (reproduced with synthetic creds). Round 5 sent 15:16: push from a Loki-owned temp repo. CEO decision pending: a Loki-spawned nested run fails closed and cannot push. Round 5 7d5b7fb4: the push goes from a fresh private repo (origin validated as github.com), gh runs from / with GH_REPO; new 38-check test and P9 planted scenario with a positive control; mutation red. Incidents during the build: a glob rm in the shared scratchpad root and 4 synthetic insteadOf lines written to the real ~/.gitconfig (removed; grep of ~/.gitconfig for loki-test/insteadOf found none at 15:40). 2 HIGH reviewers dispatched 15:40. |
|
|
134
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
135
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
136
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
137
|
+
| 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 | released@2026-09-27T15:00Z | **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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
138
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
139
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
140
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
141
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
142
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
143
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
144
|
+
| 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 | released@2026-09-27T15:00Z | 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).** Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
145
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
146
|
+
| 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-27T15:49Z | Correction: stale building@ with no live agent and no commit of its own (git log --all --grep found none). Re-cut to ready. Dispatched 15:49 (S-29 released). |
|
|
147
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
148
|
+
| 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 | ready@2026-09-27T14:21Z | 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). Correction: stale building@ with no live agent and no commit of its own (git log --all --grep found none). Re-cut to ready. |
|
|
149
|
+
| 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 | building@2026-09-27T15:49Z | 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. Rebase onto post-S-29 main dispatched 15:49. |
|
|
150
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
151
|
+
| 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 | released@2026-09-27T15:00Z | 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).** Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
152
|
+
| 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 | released@2026-09-27T15:00Z | 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).** Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
153
|
+
| 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 | released@2026-09-27T15:00Z | 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).** Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
154
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
155
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
156
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
144
157
|
| 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 |
|
|
158
|
+
| 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 | released@2026-09-27T15:00Z | 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. Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|
|
146
159
|
|
|
147
160
|
Every slice above: implement with red-then-green tests, run diff-scoped tests
|
|
148
161
|
plus `bash tests/moat/run.sh` in your own worktree, never touch `main`,
|
|
@@ -188,4 +201,4 @@ numeric rollup.
|
|
|
188
201
|
|
|
189
202
|
| ID | Owner | Branch | File set | Tier | Status | Notes |
|
|
190
203
|
|---|---|---|---|---|---|---|
|
|
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 |
|
|
204
|
+
| 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 | released@2026-09-27T15:00Z | 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). Shipped in v9.56.0 (merged before the 14:16:24Z release push of b651b98d; on npm 15:00:06Z). |
|