loki-mode 9.71.0 → 9.73.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/completion-council.sh +20 -3
  4. package/autonomy/run.sh +5 -2
  5. package/dashboard/__init__.py +1 -1
  6. package/dashboard/server.py +4 -0
  7. package/dashboard/static/cost.html +6 -1
  8. package/dashboard/static/index.html +113 -101
  9. package/dashboard/static/proofs.html +6 -1
  10. package/docs/INSTALLATION.md +1 -1
  11. package/docs/v10/ARCHITECT-CUTS.md +245 -0
  12. package/docs/v10/BOARD.md +45 -25
  13. package/docs/v10/TODO.md +3 -1
  14. package/loki-ts/dist/loki.js +2 -2
  15. package/mcp/__init__.py +1 -1
  16. package/package.json +1 -1
  17. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  18. package/web-app/dist/assets/{AdminPage-5-i7dYRv.js → AdminPage-B11jqriL.js} +1 -1
  19. package/web-app/dist/assets/{Avatar-DOgXkiA5.js → Avatar-vmIEiL2U.js} +1 -1
  20. package/web-app/dist/assets/{Badge-BBCAEx-v.js → Badge-DxtrDGcl.js} +1 -1
  21. package/web-app/dist/assets/{Button-mrjJiIzX.js → Button-BiPlRkkg.js} +1 -1
  22. package/web-app/dist/assets/{CockpitPage-DO1BqQtR.js → CockpitPage-DXKAc0jc.js} +1 -1
  23. package/web-app/dist/assets/{ComparePage-CttX-p4A.js → ComparePage-B4ddvt9J.js} +1 -1
  24. package/web-app/dist/assets/{ErrorBoundary-DrXZPl7W.js → ErrorBoundary-BIJy59N_.js} +1 -1
  25. package/web-app/dist/assets/{EvidenceReceiptPanel-DsHfSljL.js → EvidenceReceiptPanel-C4-Phh1f.js} +1 -1
  26. package/web-app/dist/assets/{GitHubIssuesPanel-DXDCz06W.js → GitHubIssuesPanel-CVIG0uwi.js} +1 -1
  27. package/web-app/dist/assets/{GitHubPRsPanel-3qECbDiA.js → GitHubPRsPanel-B_VHTB-t.js} +1 -1
  28. package/web-app/dist/assets/{HomePage-vb55Jnnw.js → HomePage-cxONjTSm.js} +2 -2
  29. package/web-app/dist/assets/{LoginPage-C1wouCAg.js → LoginPage-D49p6aVy.js} +1 -1
  30. package/web-app/dist/assets/{MagicPage-Ccf2TzsX.js → MagicPage-C5GUEIuM.js} +1 -1
  31. package/web-app/dist/assets/{MetricsPage-DxpjKBlD.js → MetricsPage-I-OXi9kG.js} +1 -1
  32. package/web-app/dist/assets/{NotFoundPage-BjesliCI.js → NotFoundPage-Do19cbOP.js} +1 -1
  33. package/web-app/dist/assets/{ProjectPage-OLJv91Fm.js → ProjectPage-TRyzTIFH.js} +69 -69
  34. package/web-app/dist/assets/ProjectsPage-BLSDhtVb.js +6 -0
  35. package/web-app/dist/assets/{SettingsPage-B92ofTn5.js → SettingsPage-BvixtAw7.js} +1 -1
  36. package/web-app/dist/assets/ShowcasePage-By96BMJz.js +1 -0
  37. package/web-app/dist/assets/{SystemSettingsPage-DQ7y1jJw.js → SystemSettingsPage-AvVujpIo.js} +1 -1
  38. package/web-app/dist/assets/{TeamsPage-DvI2Ysar.js → TeamsPage-BiT3N4px.js} +1 -1
  39. package/web-app/dist/assets/{TemplatesPage-qkFTI361.js → TemplatesPage-Y_m-dzfd.js} +1 -1
  40. package/web-app/dist/assets/{TerminalOutput-Bbi5Qsu1.js → TerminalOutput-oPTCcEGy.js} +1 -1
  41. package/web-app/dist/assets/{activity-B6_UNFP3.js → activity-DCa9Pi7k.js} +1 -1
  42. package/web-app/dist/assets/{bell-D9bRY83l.js → bell-Br7Xsjam.js} +1 -1
  43. package/web-app/dist/assets/{bot-B9XE8rVE.js → bot-BsQKlSP5.js} +1 -1
  44. package/web-app/dist/assets/{check-CIlNFVu7.js → check-Cb49hCzQ.js} +1 -1
  45. package/web-app/dist/assets/{chevron-left-sqTwkCti.js → chevron-left-Cs63FOmY.js} +1 -1
  46. package/web-app/dist/assets/{circle-alert-ClR-8eiz.js → circle-alert-C8A636Wl.js} +1 -1
  47. package/web-app/dist/assets/{clock-DhrLudbQ.js → clock-DhlnHjQI.js} +1 -1
  48. package/web-app/dist/assets/{cloud-CbY5ijES.js → cloud-uOYQxGRY.js} +1 -1
  49. package/web-app/dist/assets/{code-xml-DGN0zQOT.js → code-xml-9O9XlVo9.js} +1 -1
  50. package/web-app/dist/assets/{database-CFkV71Ae.js → database-D9Oek2JS.js} +1 -1
  51. package/web-app/dist/assets/{dollar-sign-t0__nc7_.js → dollar-sign-CHetUBPR.js} +1 -1
  52. package/web-app/dist/assets/{file-code-corner-V4yaRoxs.js → file-code-corner-oTJV_ce4.js} +1 -1
  53. package/web-app/dist/assets/{file-plus-BTdcA9zR.js → file-plus-vuloOqQB.js} +1 -1
  54. package/web-app/dist/assets/{globe-DJ8UlFt2.js → globe-DMVdf8bk.js} +1 -1
  55. package/web-app/dist/assets/{hammer-DSpaXtqP.js → hammer-15WRQJ1o.js} +1 -1
  56. package/web-app/dist/assets/index-Cx7e1d6w.css +1 -0
  57. package/web-app/dist/assets/{index-aYgURGFC.js → index-SRKz3Imw.js} +2 -2
  58. package/web-app/dist/assets/{layers-cbPS7UG9.js → layers-C-QQQP9K.js} +1 -1
  59. package/web-app/dist/assets/{loader-circle-CciQSsBx.js → loader-circle-DqoJevCK.js} +1 -1
  60. package/web-app/dist/assets/{lock-JtWoEayV.js → lock-B68yfqau.js} +1 -1
  61. package/web-app/dist/assets/{package-Dcv0g9iv.js → package-DAxTtm-S.js} +1 -1
  62. package/web-app/dist/assets/{plus-R_7Xr4PC.js → plus-BSbdI5QI.js} +1 -1
  63. package/web-app/dist/assets/{refresh-cw-6MdZdvHz.js → refresh-cw-DlvFuI3J.js} +1 -1
  64. package/web-app/dist/assets/{rotate-ccw-Dcteu0jr.js → rotate-ccw-BF03pKE0.js} +1 -1
  65. package/web-app/dist/assets/{scroll-text-Xcw2I15b.js → scroll-text-QFZ1JdTD.js} +1 -1
  66. package/web-app/dist/assets/{server-BhMeLqV8.js → server-tyIvmSke.js} +1 -1
  67. package/web-app/dist/assets/{shield-alert-Y7birYk_.js → shield-alert-DHeqbtBK.js} +1 -1
  68. package/web-app/dist/assets/{thumbs-up-B9I1RzAj.js → thumbs-up-CRag1Tn5.js} +1 -1
  69. package/web-app/dist/assets/{trash-2-FrJ_zeQ_.js → trash-2-B0n4x-Ds.js} +1 -1
  70. package/web-app/dist/assets/{trending-down-DA-YY1yX.js → trending-down-DC4Aqzso.js} +1 -1
  71. package/web-app/dist/assets/{trending-up-CC7ghXOa.js → trending-up-DFG157ke.js} +1 -1
  72. package/web-app/dist/assets/{upload-Btyqt4Cn.js → upload-BdWQ4cWx.js} +1 -1
  73. package/web-app/dist/assets/{usePolling-CTqGbMeS.js → usePolling-DMgD-dJ5.js} +1 -1
  74. package/web-app/dist/assets/{user-AWsEaMJm.js → user-DXaZeAe4.js} +1 -1
  75. package/web-app/dist/index.html +2 -2
  76. package/web-app/dist/assets/ProjectsPage-Bd0VWUNT.js +0 -6
  77. package/web-app/dist/assets/ShowcasePage-Ben4Ud4y.js +0 -1
  78. package/web-app/dist/assets/index-BfQ0f3-S.css +0 -1
@@ -114,6 +114,11 @@
114
114
  else if (s.split(".")[1].length === 1) s += "0";
115
115
  return "$" + s;
116
116
  }
117
+ // A partly priced run's cost is a lower bound; say so only when a number prints.
118
+ function atLeastUsd(n, partial) {
119
+ var s = fmtUsd(n);
120
+ return (partial === true && s.charAt(0) === "$") ? "at least " + s : s;
121
+ }
117
122
  function badgeClass(v) {
118
123
  v = String(v || "").toUpperCase();
119
124
  if (v.indexOf("APPROVE") === 0 || v === "PASS" || v === "PASSED") return "b-approve";
@@ -142,7 +147,7 @@
142
147
  for (var i = 0; i < proofs.length; i++) {
143
148
  var p = proofs[i];
144
149
  var rid = esc(p.run_id);
145
- var usd = (p.cost_usd !== null && p.cost_usd !== undefined) ? fmtUsd(p.cost_usd) : "";
150
+ var usd = (p.cost_usd !== null && p.cost_usd !== undefined) ? atLeastUsd(p.cost_usd, p.cost_partial) : "";
146
151
  var fc = (p.files_changed !== null && p.files_changed !== undefined) ? (p.files_changed + " files") : "";
147
152
  var verdict = p.final_verdict ? '<span class="badge ' + badgeClass(p.final_verdict) + '" title="Recorded council vote, not a verification result">council ' + esc(p.final_verdict) + "</span>" : "";
148
153
  var ver = p.loki_version ? ("v" + esc(p.loki_version)) : "";
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v9.71.0
5
+ **Version:** v9.73.0
6
6
 
7
7
  ---
8
8
 
@@ -87,3 +87,248 @@ Candidates I dropped because they are already fixed or would not help:
87
87
  - Waiting on a slice in this set: BACKLOG 127 remainder (`run.sh` auto_capture_episode, `cd "$PROJECT_DIR"` with no unset guard, ~21361) after S-140; BACKLOG 38 after S-141; BACKLOG 133 after S-139.
88
88
 
89
89
  I edited no files. The only temp file was a log saved under `$TMPDIR` and deleted in the same command. I started no background processes.
90
+
91
+ ## 19:10Z cut (S-154..S-173)
92
+
93
+ I edited no files and started no background processes. Each red condition below comes from reading or grepping the current tree at e952e1ae. Two numbers were measured on this host (load average about 9):
94
+ - `python3 tests/lib/scan-unreachable-shipped.py` ran in 47s, rc 0.
95
+ - `EVENT_NAME=push SHA=8d17be2b bash scripts/ci/version-bump-only.sh check` printed `normalizer: not on the allowlist: web-app/src/components/Footer.tsx`, rc 1.
96
+
97
+ `tests/test-sentrux-init-rules.sh` ran once for timing. It removed its own mktemp dir through its EXIT trap: `ls -d /tmp/loki-test-sentrux-init-*` found 0 entries. The working tree shows only the Chief of Staff's uncommitted BOARD.md and TODO.md edits.
98
+
99
+ Rules that apply to every row:
100
+ - No file set includes a hot file.
101
+ - Any new test file is registered in `tests/run-all-tests.sh` by the Captain.
102
+ - Dashboard-ui rows need the Captain to rebuild `dashboard/static/index.html`. Web-app rows need a `web-app/dist` rebuild.
103
+ - UI walls follow the pattern already in the repo. Web-app rows pull the copy decision into a named pure function tested with `node --test`, like `web-app/src/cockpit/useCockpitState.derive-view.test.mjs`. Dashboard-ui rows drive the real component class against a DOM stub, like `dashboard-ui/tests/loki-empty-vs-error.node.test.mjs`.
104
+ - Each UI wall includes a negative assertion: the error render must not contain the empty-state sentence. A grep for the absence of a string is not accepted as a wall.
105
+
106
+ ### S-154: prune-worktrees.sh treats a cherry-picked branch as merged (GUARDS 5, TODO item 8)
107
+ - Files: scripts/prune-worktrees.sh, tests/test-prune-worktrees.sh (new)
108
+ - Tier: MEDIUM (it removes worktrees)
109
+ - Red: the script counts a worktree as merged only through `git merge-base --is-ancestor`. The Chief of Staff lands slices by cherry-pick, so no slice branch is ever an ancestor of main, and the dry run lists 0 of them. That is why pruning is still manual (TODO item 8: "count now 7 of 15"). No test file for the script exists (`ls tests | grep -i prune` shows only checkpoint tests).
110
+ - Green, on a fixture repo:
111
+ - A branch whose commits are all patch-equivalent on main (`git cherry main <branch>` shows no `+` lines) is listed as removable.
112
+ - A branch with one `+` commit is kept.
113
+ - A locked worktree is kept, and so is a dirty one.
114
+ - `--apply` removes only through `git worktree remove`.
115
+ - The test also greps the script and fails on any `stat`, `mtime`, `-mmin` or `-newer` token, so GUARDS 5 finally has a checked-in test.
116
+ - Wall: `bash tests/test-prune-worktrees.sh` exits 0 with every case PASS. A mutation that drops the `git cherry` branch makes the cherry-picked fixture case FAIL.
117
+
118
+ ### S-155: shipped-module reachability scan under 10s, same verdicts (velocity)
119
+ - Files: tests/lib/scan-unreachable-shipped.py (referenced_from_runtime and its caller only)
120
+ - Tier: LOW
121
+ - Red: the scan takes 47s locally and 95s on CI (`tests/shard-durations.tsv`: "shipped modules have a recorded reachability verdict 95"). It is the 4th slowest suite. Every module runs one large alternation regex over every corpus file, including a `(node|bun)\s+[^\n]*` arm, and nothing filters the files first.
122
+ - Green:
123
+ - The builder first measures where the time goes (regex or I/O) and puts the numbers in the commit.
124
+ - Then add a substring prefilter: skip any corpus file that does not contain the module's stem. This is sound because every pattern alternative contains the stem literally. Also compile the regex once per module.
125
+ - stdout and rc are byte-identical to a capture taken before the change.
126
+ - Wall: the scan runs in under 10s wall time. `bash tests/test-no-unreachable-shipped.sh` shows 4 passed, 0 failed. A mutation that removes one real require of a listed module still gets reported (rc 1).
127
+
128
+ ### S-156: auto-capture shadow_write runs the agent repo's memory package when PROJECT_DIR is unset, and splices importance into python source (BACKLOG 127 remainder)
129
+ - Files: autonomy/run.sh (the managed-memory auto-capture block, found by grepping `shadow_write`, about line 21380-21396 only), tests/test-autocapture-shadow-write-guard.sh (new)
130
+ - Tier: HIGH (code execution on a verdict-adjacent path)
131
+ - Red: `cd "$PROJECT_DIR" 2>/dev/null && ... python3 -m memory.managed_memory.shadow_write` has no `-n PROJECT_DIR` guard. On bash 3.2, `cd ""` succeeds silently and the cwd stays inside the agent repo. Also, `python3 -c "print('yes' if float('$_ep_imp') >= 0.6 else 'no')"` interpolates an episode-file value straight into the python source.
132
+ - Green:
133
+ - The block is skipped when PROJECT_DIR is empty.
134
+ - `importance` is passed through argv or env and never spliced into source.
135
+ - A planted `memory/managed_memory/shadow_write.py` in the cwd writes no marker file, run under `/bin/bash` and under bash 5.
136
+ - An importance value of `0.7'); open('PWNED','w'); ('` writes no PWNED file.
137
+ - The builder names who writes `episode_path_file`.
138
+ - Wall: `bash tests/test-autocapture-shadow-write-guard.sh` exits 0, and `bash tests/test-trust-core-tests-detect.sh` still passes. Reverting either guard makes its case FAIL.
139
+
140
+ ### S-157: council member vote and convergence floor read pass:true as green whatever failed_count says (BACKLOG 98 remainder, 89)
141
+ - Files: autonomy/completion-council.sh (council_evaluate_member's test-results parser and `_council_convergence_evidence_green` only), tests/test-council-failed-count-honesty.sh (new)
142
+ - Tier: HIGH (council verdict)
143
+ - Red: both parsers test `passed is True` and never read `failed_count`. The convergence reader is `print('yes' if (runner != 'none' and passed is True and d.get('status') != 'no_tests_run') ...`. So `{"runner":"jest","pass":true,"failed_count":2}` reads green at both sites. The evidence gate at ~2014 already treats failed_count as winning.
144
+ - Green:
145
+ - At both sites, failed_count above 0 means not green, using the same rule as the evidence gate.
146
+ - A real `{"pass":true,"failed_count":0}` stays green (positive control).
147
+ - `runner=none` behaviour is unchanged.
148
+ - Wall: `bash tests/test-council-failed-count-honesty.sh` exits 0, and `bash tests/test-trust-core-tests-detect.sh` and `bash tests/test-council-convergence-floor.sh` pass. A mutation that reverts either site makes its case FAIL.
149
+
150
+ ### S-158: per-run cost_partial is dropped by /api/cost/timeline runs[] and /api/proofs (BACKLOG 118)
151
+ - Files: dashboard/server.py (the runs.append in `_compute_cost_timeline` about line 8351, and the /api/proofs row builder about line 12538 only), dashboard/static/cost.html, dashboard/static/proofs.html, tests/dashboard/test_cost_partial_surfaced.py (new)
152
+ - Tier: MEDIUM (response shape change)
153
+ - Red: `autonomy/lib/efficiency_cost.py:209` writes `cost.cost_partial` into proof.json, but both endpoints copy only `cost.usd`. A partly priced run therefore shows as a complete total.
154
+ - Green:
155
+ - Both endpoints carry `cost_partial` (a missing key becomes false).
156
+ - Both pages render a partial run as "at least $X".
157
+ - A fully priced run renders as today.
158
+ - The builder names every consumer of the two endpoints that was checked.
159
+ - Wall: `python3 -m pytest tests/dashboard/test_cost_partial_surfaced.py -q` passes. A fixture proof.json with `cost_partial: true` gives `runs[0].cost_partial == true`, and a mutation that drops the key fails the test.
160
+
161
+ ### S-159: NLSearch says "No results found" when the search request failed (BACKLOG 114)
162
+ - Files: web-app/src/components/NLSearch.tsx, web-app/src/components/NLSearch.state.test.mjs (new)
163
+ - Tier: LOW
164
+ - Red: the catch at ~140 does `setResults([])` ("show empty results gracefully"), so a failed API call renders "No results found. Try a different query." (~261).
165
+ - Green:
166
+ - The failure is kept in state and renders "Search failed: <reason>".
167
+ - A real empty result still says "No results found".
168
+ - The branch decision lives in an exported pure function.
169
+ - Wall: `node --test web-app/src/components/NLSearch.state.test.mjs` passes, including the negative assertion. `cd web-app && npx tsc -b` exits 0.
170
+
171
+ ### S-160: CommandPalette file search failure reads as no results (BACKLOG 114)
172
+ - Files: web-app/src/components/CommandPalette.tsx, web-app/src/components/CommandPalette.state.test.mjs (new)
173
+ - Tier: LOW
174
+ - Red: the catch at ~171 does `setFileResults([])`, so a failed `api.searchFiles` renders "No results found" (~392).
175
+ - Green: the error state renders "File search failed", and a genuine empty result keeps "No results found".
176
+ - Wall: `node --test web-app/src/components/CommandPalette.state.test.mjs` passes, and `cd web-app && npx tsc -b` exits 0.
177
+
178
+ ### S-161: ProjectsPage ignores the poll error and says "No projects yet" (BACKLOG 114)
179
+ - Files: web-app/src/pages/ProjectsPage.tsx, web-app/src/pages/ProjectsPage.state.test.mjs (new)
180
+ - Tier: LOW
181
+ - Red: `usePolling` returns `error` (web-app/src/hooks/usePolling.ts:7), but ProjectsPage destructures only `data` and `refresh` (~65). A failed history fetch renders "No projects yet. Start building." (~168).
182
+ - Green:
183
+ - With error set and no data, the page renders "Could not load projects" plus a retry.
184
+ - With data present and a later poll error, the page keeps the data and shows a stale notice.
185
+ - Real empty data still says "No projects yet".
186
+ - Wall: `node --test web-app/src/pages/ProjectsPage.state.test.mjs` passes, and `cd web-app && npx tsc -b` exits 0.
187
+
188
+ ### S-162: SecretsPanel and DocsPanel swallow fetch errors into empty states (BACKLOG 114)
189
+ - Files: web-app/src/components/ProjectWorkspace.tsx (SecretsPanel fetchSecrets ~248-256 with its empty branch ~366-372, and DocsPanel fetchStatus ~432-442 with its empty branch ~589-592 only), web-app/src/components/ProjectWorkspace.panels.test.mjs (new)
190
+ - Tier: LOW
191
+ - Red: both catches are `// ignore`. A failed secrets fetch renders "No secrets configured yet". A failed docs fetch renders "No documentation generated yet". SecretsPanel even declares an `error` state that the catch never sets.
192
+ - Green: each failure renders "Could not load secrets" or "Could not load documentation", and genuine empties are unchanged.
193
+ - Wall: `node --test web-app/src/components/ProjectWorkspace.panels.test.mjs` passes, and `cd web-app && npx tsc -b` exits 0.
194
+
195
+ ### S-163: CICDPanel shows unknown conclusions as "Failed" and unknown statuses as running (BACKLOG 114)
196
+ - Files: web-app/src/components/CICDPanel.tsx (normalizeRunStatus, normalizeJobStatus, normalizeStepStatus and the status style map only), web-app/src/components/CICDPanel.status.test.mjs (new)
197
+ - Tier: LOW
198
+ - Red: all three normalizers map `default: return 'failed'` for a completed item, so `neutral`, `action_required`, `stale` and a null conclusion read as Failed. Any unlisted `status` returns `'running'`.
199
+ - Green:
200
+ - A new `unknown` status with a neutral style.
201
+ - `failure`, `timed_out` and `startup_failure` still map to failed.
202
+ - `success`, `cancelled` and `skipped` are unchanged.
203
+ - Wall: `node --test web-app/src/components/CICDPanel.status.test.mjs` passes and covers each conclusion. `cd web-app && npx tsc -b` exits 0.
204
+
205
+ ### S-164: AIChatPanel prints "Done." for a task that failed with no output (BACKLOG 114)
206
+ - Files: web-app/src/components/AIChatPanel.tsx (the two `|| 'Done.'` fallbacks at ~543 and ~622 only), web-app/src/components/AIChatPanel.result.test.mjs (new)
207
+ - Tier: LOW
208
+ - Red: both completion paths render `content || 'Done.'` whatever `returncode` is, so a non-zero exit with no output reads as success.
209
+ - Green: a non-zero returncode with no output renders "Failed (exit N), no output". Zero with no output renders "Finished with no output". Real output is unchanged.
210
+ - Wall: `node --test web-app/src/components/AIChatPanel.result.test.mjs` passes, and `cd web-app && npx tsc -b` exits 0.
211
+
212
+ ### S-165: TrustedBy asserts a trust claim and ChangelogWidget shows March 2026 v6.x as "Recent Changes" (BACKLOG 117 remainder)
213
+ - Files: web-app/src/components/TrustedBy.tsx, web-app/src/components/ChangelogWidget.tsx
214
+ - Tier: LOW
215
+ - Red: TrustedBy.tsx:70 renders "Trusted by developers building the future" on HomePage and ShowcasePage. ChangelogWidget.tsx hardcodes v6.71.1, v6.70.0 and v6.69.0 (dates Mar 20-24, 2026) under "Recent Changes" while VERSION is 9.x.
216
+ - Green:
217
+ - The headline becomes a factual label (for example "At a glance").
218
+ - The widget either drops the hardcoded list for a link to the changelog, or stops calling it recent.
219
+ - The remaining stats are checked against the code (5 providers, template count) and noted in the commit.
220
+ - Wall: `grep -n "Trusted by developers" web-app/src/components/TrustedBy.tsx` returns rc 1. `grep -n "6.71.1" web-app/src/components/ChangelogWidget.tsx` returns rc 1. `cd web-app && npx tsc -b` exits 0.
221
+
222
+ ### S-166: checkpoint viewer drops a rejected fetch and clears the error (BACKLOG 114)
223
+ - Files: dashboard-ui/components/loki-checkpoint-viewer.js (the load at ~95-110 only), dashboard-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs (new)
224
+ - Tier: LOW
225
+ - Red: `Promise.allSettled` never throws. On `status === 'rejected'` the code keeps the old or empty list and then sets `this._error = null`, so a failed read renders as "no checkpoints".
226
+ - Green: a rejected result sets `_error` and renders a load-failure message. A fulfilled empty result still renders the empty state.
227
+ - Wall: `node --test dashboard-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs` passes, including the negative assertion.
228
+
229
+ ### S-167: council transcripts hide a failed hook-events read as zero events (BACKLOG 114)
230
+ - Files: dashboard-ui/components/loki-council-transcripts.js (the hook events load at ~104-118 only), dashboard-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs (new)
231
+ - Tier: LOW
232
+ - Red: the catch sets `this._hookEvents = []` and records no error, so a failed read renders the same as "no hook events".
233
+ - Green: the failure is recorded and rendered as "Could not load hook events". A real empty list is unchanged.
234
+ - Wall: `node --test dashboard-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs` passes.
235
+
236
+ ### S-168: task board hides a load error whenever local tasks exist (BACKLOG 114)
237
+ - Files: dashboard-ui/components/loki-task-board.js (the catch at ~164-169 and the error render at ~1585 only), dashboard-ui/tests/loki-task-board-fetch-error.node.test.mjs (new)
238
+ - Tier: LOW
239
+ - Red: the render shows the error only when `this._error && this._tasks.length === 0`, and the catch refills `_tasks` with local tasks. A failed server read with any local task therefore shows no error, and the board looks complete.
240
+ - Green: with local tasks present, a server failure still shows a banner ("Server tasks could not be loaded; showing local tasks only") above the local tasks.
241
+ - Wall: `node --test dashboard-ui/tests/loki-task-board-fetch-error.node.test.mjs` passes. `node --test dashboard-ui/tests/loki-task-board-modal-guard.node.test.mjs` still passes.
242
+
243
+ ### S-169: log stream swallows API failures silently (BACKLOG 114)
244
+ - Files: dashboard-ui/components/loki-log-stream.js (the API poll catch at ~179 and the empty render only), dashboard-ui/tests/loki-log-stream-fetch-error.node.test.mjs (new)
245
+ - Tier: LOW
246
+ - Red: the catch body is only the comment `// API not available, will retry on next poll`. A panel that never reached the API looks like a quiet log.
247
+ - Green: consecutive failures set a visible "Log source unreachable, retrying" state, and it clears on the next success. Polling is unchanged.
248
+ - Wall: `node --test dashboard-ui/tests/loki-log-stream-fetch-error.node.test.mjs` passes. `node --test dashboard-ui/tests/loki-poll-registry.node.test.mjs` still passes.
249
+
250
+ ### S-170: API keys panel shows "No API keys configured" under its own load-error banner (BACKLOG 114)
251
+ - Files: dashboard-ui/components/loki-api-keys.js (the table branch at ~568-575 only), dashboard-ui/tests/loki-api-keys-fetch-error.node.test.mjs (new)
252
+ - Tier: LOW
253
+ - Red: a failed load sets `_error = "Failed to load API keys: ..."`, which renders as a banner at ~652. The table branch still falls to `keys.length === 0` and prints "No API keys configured. Create one to get started." Both render together.
254
+ - Green: when the list load failed, the empty-state sentence is not rendered. A real empty list keeps it.
255
+ - Wall: `node --test dashboard-ui/tests/loki-api-keys-fetch-error.node.test.mjs` passes. It asserts that the error render does not contain "No API keys configured".
256
+
257
+ ### S-171: lint for response fields put into innerHTML without escaping (BACKLOG 124)
258
+ - Files: tests/test-no-unescaped-innerhtml.sh (new), tests/lib/scan-unescaped-innerhtml.py (new)
259
+ - Tier: MEDIUM
260
+ - Red: no guard exists. A planted fixture component with ``el.innerHTML = `<b>${data.name}</b>` `` is flagged, rc 1.
261
+ - Green:
262
+ - The scanner covers dashboard-ui/components and dashboard-ui/scripts/build-standalone.js.
263
+ - It flags a template-literal or string interpolation into innerHTML that is not wrapped in the file's escape helper.
264
+ - It must pass on today's tree. Every current offender goes in an in-file ALLOWLIST with a reason of at least 40 characters, the same pattern scan-unreachable-shipped.py uses. Any real XSS found is named in the report and not fixed here.
265
+ - A non-vacuity check asserts that 20 or more files were scanned.
266
+ - Wall: `bash tests/test-no-unescaped-innerhtml.sh` exits 0 on main. The planted fixture case exits 1. An allowlist entry with an empty reason fails.
267
+
268
+ ### S-172: shadow-write mutant check depends on the bash version's `cd ""` behaviour (BACKLOG 132)
269
+ - Files: tests/test-council-shadow-write-project-dir.sh
270
+ - Tier: LOW
271
+ - Red: the mutant that strips only the `-n PROJECT_DIR` guard stays GREEN under bash 5.3, because `cd ""` hard-fails there. It goes RED under /bin/bash 3.2.57. The file runs `bash -c` from `#!/usr/bin/env bash`.
272
+ - Green:
273
+ - The GREEN and mutant runs execute under `/bin/bash` when it exists, and also under the PATH bash.
274
+ - The in-file mutant leg goes red under both interpreters. It asserts on the executed-module marker, not on the result of `cd`.
275
+ - Wall: `bash tests/test-council-shadow-write-project-dir.sh` exits 0. Its mutant leg reports red under both `/bin/bash --version` and the PATH bash, and the two version strings are printed in the output.
276
+
277
+ ### S-173: P2.council-readers-not-shadowed does not drive the 6th reader, council_managed_should_stop (BACKLOG 135)
278
+ - Files: tests/moat/p2-honest-verdict.sh (the council-readers-not-shadowed case only)
279
+ - Tier: HIGH (moat)
280
+ - Red: the case covers 5 readers. `council_managed_should_stop` (completion-council.sh ~4351) reads test-results.json behind `LOKI_EXPERIMENTAL_MANAGED_COUNCIL`/`LOKI_MANAGED_AGENTS` and is never driven.
281
+ - Green:
282
+ - Add a leg that sets those flags and plants a cwd `json.py` or `hashlib.py`. It passes today, because the D7 sys.path filter is present.
283
+ - A scratch-copy mutation that removes that filter turns the case red.
284
+ - Scope is the cwd-shadow class only. This reader is still `python3 -E` with no `-I -S`, so a `.pth` leg would turn a proven case red on main. The `.pth` leg is deferred to the production fix, which is alternate A2 below.
285
+ - Wall: `bash tests/moat/p2-honest-verdict.sh` prints `CASE P2.council-readers-not-shadowed PASS`, and the mutated copy prints FAIL for that case.
286
+
287
+ **Risks and notes**
288
+ 1. **Fold into S-153 now (the biggest velocity finding).**
289
+ - Since S-144, every bump commit rewrites Footer.tsx, and Footer.tsx is on neither allowlist. `version-bump-only.sh check` against the v9.68.0 bump 8d17be2b is rc 1 ("not on the allowlist: web-app/src/components/Footer.tsx"). So S-132's Tests skip, merged at 19:06, cannot fire on any bump.
290
+ - S-153 changes only release.yml STEP 1. The script's header says it is a byte-for-byte copy of STEP 1, and `tests/test-version-bump-only.sh` checks parity against it.
291
+ - S-153's file set should therefore also include `scripts/ci/version-bump-only.sh` and Footer fixtures in `tests/test-version-bump-only.sh`. That also covers any web-app/dist files S-153 adds to the bump. Without both, the skip still never fires; with only one side changed, the parity test goes red.
292
+ 2. **Same-file neighbours.**
293
+ - S-156 (run.sh ~21390) and S-157 (completion-council.sh) are the only rows on those files, in regions far from S-135's test-only rework.
294
+ - Trust-core probes anchor into both files by content, so both walls run `tests/test-trust-core-tests-detect.sh`. If S-135 lands first, rebase.
295
+ 3. **Registration and rebuilds.**
296
+ - 17 rows add a new test file and need the Captain to register it: S-154, S-156, S-157, S-158, S-159 to S-164, S-166 to S-171.
297
+ - S-159 to S-165 need a `web-app/dist` rebuild. S-166 to S-170 need `dashboard/static/index.html` rebuilt.
298
+ 4. **Response shapes.** S-158 adds a field and changes the rendered copy. The builder must name the consumers it checked.
299
+ 5. **Held, not in the 20:**
300
+ - BACKLOG 19 (remote stripped signature from a signing server). `docs/exit-codes.md` documents UNSIGNED as helper return 0. Changing it is an exit-contract change on a verifier (CEO, like BACKLOG 4). A label-only version would need a new JWKS fetch, meaning egress on the verify path.
301
+ - BACKLOG 18, 77, 121, 123 and WhatsNew.tsx, as before.
302
+ - BACKLOG 52 (renaming the "Moat suite" check), because branch protection may key on the check name.
303
+ 6. **Alternates, ready once a file frees up:**
304
+ - A1: BACKLOG 17, the `/api/focus` POST fires with LOKI_DASHBOARD=false (run.sh ~24478). Cut it after S-156.
305
+ - A2: `council_managed_should_stop` still runs `python3 -E` with no `-I -S`, and has `project_dir="${PROJECT_DIR:-$(pwd)}"` (BACKLOG 127c). Cut it after S-157, then add S-173's `.pth` leg.
306
+ - A3: GUARDS 11 as a scripts/v10-guard.sh rule. Cut it after S-152, which owns that file.
307
+ - A4: BACKLOG 112 `/api/cost` tracker fallback and `/metrics` loki_cost_usd. Cut it after S-158 (dashboard/server.py).
308
+ - A5: "VERIFIED WITH GAPS" coloured as success in build-standalone.js. Cut it after S-146.
309
+ 7. **Already fixed, dropped after checking:**
310
+ - BACKLOG 38 (no_pass_recorded exists, completion-council.sh:2099).
311
+ - BACKLOG 56 (the Bun reader handles passed_count/failed_count and reuses the zero-test detector).
312
+ - BACKLOG 81 (python3 -E plus the sys.path filter at run.sh:13783).
313
+ - BACKLOG 116 memory-browser and overview keys (snake_case and `g.blocked` are in place).
314
+
315
+ | S-154 | GUARDS 5 + TODO 8: prune-worktrees.sh treats a cherry-picked branch (git cherry, no + lines) as merged; test forbids mtime signals | scripts/prune-worktrees.sh, tests/test-prune-worktrees.sh (new) | MEDIUM | bash tests/test-prune-worktrees.sh exits 0; cherry-picked fixture listed, one-unique-commit, locked and dirty fixtures kept; dropping the git cherry branch fails the case | ready@2026-09-27T19:10Z | Removes worktrees only via git worktree remove. Captain registers the test. Source: 19:10Z cut. |
316
+ | S-155 | Velocity: reachability scan (95s on CI, 47s local) under 10s via a per-module stem prefilter, identical verdicts | tests/lib/scan-unreachable-shipped.py | LOW | scan wall time under 10s; stdout and rc byte-identical to the pre-change capture; bash tests/test-no-unreachable-shipped.sh 4 passed 0 failed; removing one real require is still reported | ready@2026-09-27T19:10Z | Builder measures regex vs I/O first and records both numbers. Source: 19:10Z cut. |
317
+ | S-156 | BACKLOG 127 remainder: auto-capture shadow_write runs with PROJECT_DIR unset, and float() splices episode importance into python source | autonomy/run.sh (shadow_write auto-capture block about 21380-21396 only), tests/test-autocapture-shadow-write-guard.sh (new) | HIGH | bash tests/test-autocapture-shadow-write-guard.sh exits 0 under /bin/bash and bash 5; no marker from a planted cwd memory package; no file from an injected importance; trust-core suite passes | ready@2026-09-27T19:10Z | Builder names who writes episode_path_file. Only run.sh row in this cut. Source: 19:10Z cut. |
318
+ | S-157 | BACKLOG 98/89: council member vote and _council_convergence_evidence_green read pass:true as green whatever failed_count says | autonomy/completion-council.sh (those 2 parsers only), tests/test-council-failed-count-honesty.sh (new) | HIGH | pass:true with failed_count 2 is not green at both sites; failed_count 0 stays green; trust-core and convergence-floor suites pass; reverting either site fails its case | ready@2026-09-27T19:10Z | Mirrors the evidence gate rule (~2014). Only completion-council.sh row in this cut. Source: 19:10Z cut. |
319
+ | S-158 | BACKLOG 118: per-run cost_partial dropped by /api/cost/timeline runs[] and /api/proofs; pages show a lower bound as a total | dashboard/server.py (runs.append in _compute_cost_timeline and the /api/proofs row only), dashboard/static/cost.html, dashboard/static/proofs.html, tests/dashboard/test_cost_partial_surfaced.py (new) | MEDIUM | pytest test_cost_partial_surfaced.py passes; fixture cost_partial true surfaces in both endpoints and renders as at least $X; dropping the key fails | ready@2026-09-27T19:10Z | Builder names the consumers checked. Source: 19:10Z cut. |
320
+ | S-159 | BACKLOG 114: NLSearch renders No results found when the search request failed | web-app/src/components/NLSearch.tsx, web-app/src/components/NLSearch.state.test.mjs (new) | LOW | node --test NLSearch.state.test.mjs passes incl. the negative assertion; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
321
+ | S-160 | BACKLOG 114: CommandPalette file-search failure reads as No results found | web-app/src/components/CommandPalette.tsx, web-app/src/components/CommandPalette.state.test.mjs (new) | LOW | node --test CommandPalette.state.test.mjs passes; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
322
+ | S-161 | BACKLOG 114: ProjectsPage ignores usePolling error and says No projects yet on a failed fetch | web-app/src/pages/ProjectsPage.tsx, web-app/src/pages/ProjectsPage.state.test.mjs (new) | LOW | node --test ProjectsPage.state.test.mjs passes (error, stale-data and real-empty cases); npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
323
+ | S-162 | BACKLOG 114: SecretsPanel and DocsPanel swallow fetch errors into No secrets / No documentation empty states | web-app/src/components/ProjectWorkspace.tsx (SecretsPanel and DocsPanel fetch and empty branches only), web-app/src/components/ProjectWorkspace.panels.test.mjs (new) | LOW | node --test ProjectWorkspace.panels.test.mjs passes; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
324
+ | S-163 | BACKLOG 114: CICDPanel maps neutral/action_required/stale/null conclusions to Failed and unknown statuses to running | web-app/src/components/CICDPanel.tsx (3 normalizers and status map only), web-app/src/components/CICDPanel.status.test.mjs (new) | LOW | node --test CICDPanel.status.test.mjs passes for every conclusion; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
325
+ | S-164 | BACKLOG 114: AIChatPanel prints Done. for a non-zero exit with no output | web-app/src/components/AIChatPanel.tsx (the two Done. fallbacks only), web-app/src/components/AIChatPanel.result.test.mjs (new) | LOW | node --test AIChatPanel.result.test.mjs passes; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. |
326
+ | S-165 | BACKLOG 117 remainder: TrustedBy asserts Trusted by developers; ChangelogWidget shows March 2026 v6.x as Recent Changes | web-app/src/components/TrustedBy.tsx, web-app/src/components/ChangelogWidget.tsx | LOW | grep for Trusted by developers and 6.71.1 in those files returns rc 1; npx tsc -b exits 0 | ready@2026-09-27T19:10Z | Copy only. Captain rebuilds web-app/dist. Source: 19:10Z cut. |
327
+ | S-166 | BACKLOG 114: checkpoint viewer ignores a rejected allSettled fetch and clears the error | dashboard-ui/components/loki-checkpoint-viewer.js (load block only), dashboard-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes incl. the negative assertion | ready@2026-09-27T19:10Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. |
328
+ | S-167 | BACKLOG 114: council transcripts render a failed hook-events read as zero events | dashboard-ui/components/loki-council-transcripts.js (hook events load only), dashboard-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes | ready@2026-09-27T19:10Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. |
329
+ | S-168 | BACKLOG 114: task board hides a server load error whenever local tasks exist | dashboard-ui/components/loki-task-board.js (catch and error render only), dashboard-ui/tests/loki-task-board-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-task-board-modal-guard test still passes | ready@2026-09-27T19:10Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. |
330
+ | S-169 | BACKLOG 114: log stream swallows API failures with an empty catch | dashboard-ui/components/loki-log-stream.js (API poll catch and empty render only), dashboard-ui/tests/loki-log-stream-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-poll-registry test still passes | ready@2026-09-27T19:10Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. |
331
+ | S-170 | BACKLOG 114: API keys panel renders No API keys configured under its own load-error banner | dashboard-ui/components/loki-api-keys.js (table branch only), dashboard-ui/tests/loki-api-keys-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; error render lacks the empty-state sentence | ready@2026-09-27T19:10Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. |
332
+ | S-171 | BACKLOG 124: lint for response fields interpolated into innerHTML without the escape helper | tests/test-no-unescaped-innerhtml.sh (new), tests/lib/scan-unescaped-innerhtml.py (new) | MEDIUM | passes on main with a reasoned in-file allowlist; planted fixture exits 1; empty-reason entry fails; at least 20 files scanned | ready@2026-09-27T19:10Z | Real XSS found is reported, not fixed here. Captain registers. Source: 19:10Z cut. |
333
+ | S-172 | BACKLOG 132: shadow-write mutant check is green on bash 5.3 and red on /bin/bash 3.2 | tests/test-council-shadow-write-project-dir.sh | LOW | bash tests/test-council-shadow-write-project-dir.sh exits 0; mutant leg red under both /bin/bash and PATH bash, both versions printed | ready@2026-09-27T19:10Z | Test-only. Source: 19:10Z cut. |
334
+ | S-173 | BACKLOG 135: P2.council-readers-not-shadowed does not drive council_managed_should_stop (cwd-shadow class only) | tests/moat/p2-honest-verdict.sh (that case only) | HIGH | p2-honest-verdict.sh prints CASE P2.council-readers-not-shadowed PASS; removing the sys.path filter in a scratch copy prints FAIL | ready@2026-09-27T19:10Z | No .pth leg: that reader is still python3 -E, so a .pth leg would redden a proven case; follows alternate A2. Source: 19:10Z cut. |
package/docs/v10/BOARD.md CHANGED
@@ -66,7 +66,7 @@ set is declared to avoid overlap with those and with each other.
66
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
68
  | S-49 | BACKLOG 134: completion-council.sh's 3 test-result readers use bare PATH python3 -E -c with no -I/-S/fixed-path resolution (same bypass class BACKLOG 129 already closed for run.sh) | autonomy/completion-council.sh (council_heuristic_review, council_evaluate_member, council_devils_advocate_review only), new moat case planting a user-site .pth | HIGH | red: a planted .pth flips a genuinely-failing test-results.json to CONFIRMED_COMPLETE; green: routed through a resolved-interpreter helper matching `_loki_snapshot_py_tool`'s pattern, .pth has no effect | released@2026-09-27T16:40Z | Disjoint from S-18/BACKLOG 149's run.sh GH-token work and from S-17's vote-text assertions (already merged, different lines in the same file -- verify no line-range collision before editing). Dispatched 15:00 (workflow wf_29a75a9c-652, slice-card brief). Built 6b276aaf (wf_29a75a9c-652-1): 3 readers via _loki_snapshot_py_tool -I -S, new P2 case red pre-fix and green after, mutation red. 2 HIGH reviewers dispatched 15:16. Reviewer B APPROVE; reviewer A CONCERN (reproduced): queue readers at ~3769/~4050 still use bare python3 -E, so a .pth flips the verdict. Rework sent 15:28. Rework 17eeb940+8ce7f1b1: queue and convergence readers isolated and fail closed, no-interpreter veto, byte-identity test. Re-review (HIGH) dispatched 15:40. Round 2: HIGH reviewer A APPROVE (the .pth attack fails on every reader in the 3 functions; 7 of 8 mutations red; M3b checklist leg is a test gap, fix holds on a direct probe). Reviewer B approved round 1. Train 4. Follow-up: council readers outside the 3 functions (~1425, ~1564, ~4215-4245). Cherry-picked onto main for train 4 (3 commits); D27 checks green except tests/test-select-tests.sh, which hit the 60s cap (rc=124; CI runs it in full; reviewer ran 38/38). Train 4 release commit 08d64f4e (v9.59.0) pushed 16:07:02Z, ls-remote verified. Released in v9.59.0 (Release run 36332036567 publish-npm success; v9.58.0 itself never published, superseded). |
69
- | 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 | building@2026-09-27T19:10Z | NARROW SCOPE WARNING: this file is the most contended file this session (S-27/S-29/S-30/S-31/S-32 lineage). Builder must rebase onto main AFTER the S-29 merge-pass lands and touch ONLY the named 477-501 invocation block, nothing else in the file. Coordinate with Captain before starting if S-29's merge is still in flight. Batch 5 build (wf_38d4e17c-211). |
69
+ | S-50 | BACKLOG 137: S-02's dynamic-repo-root fix breaks P7's own sed-workaround for the same bug | tests/moat/p7-no-fabricated-data.sh (lines 477-501, the client-route helper invocation only) | MEDIUM | red: P7.webapp-client-routes-exist fails post-S-02 because the sed target no longer exists; green: helpers run in place or receive the root explicitly, case passes again | released@2026-09-27T19:42Z | NARROW SCOPE WARNING: this file is the most contended file this session (S-27/S-29/S-30/S-31/S-32 lineage). Builder must rebase onto main AFTER the S-29 merge-pass lands and touch ONLY the named 477-501 invocation block, nothing else in the file. Coordinate with Captain before starting if S-29's merge is still in flight. Batch 5 build (wf_38d4e17c-211). Review APPROVE found the fix already on main from S-39 bf9776fb (tests/moat/p7-no-fabricated-data.sh:477-497 runs helpers from $REPO_ROOT/tests, no sed); no new commit. Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
70
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
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 | parked@2026-09-27T17:14Z | 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. Delivered by S-18 round 5 (trusted push from a fresh temp repo; the agent repo config is never loaded with credentials). |
@@ -128,17 +128,17 @@ set is declared to avoid overlap with those and with each other.
128
128
  | S-109 | D28: pulse violations HIGH_LOAD (load > 28), ORPHAN_TEST (tests/* process with PPID 1 or etime > 30 min), STRAY_CONTAINER (swarm container older than 1h or with a restart policy), RELEASE_ON_RED (newest VERSION bump whose Tests failed), built on S-104 | scripts/v10-pulse.sh, tests/test-v10-pulse.sh | MEDIUM | fire and no-fire fixture per violation; pulse under 1s from cache | released@2026-09-27T17:53Z | Must resolve the S-76 T30 test-number collision with S-104. First build stopped on the S-104/S-76 T30 collision (as instructed). Re-dispatched 16:48: rebase S-104, then S-109. Cherry-picked (0986ab39) and pushed in cc105687 at 17:05:47Z (ls-remote verified); tests/test-v10-pulse.sh 78/78 on main. In v9.64.0 (Release run 36337270762: publish-npm success). |
129
129
  | S-110 | Fix the 3 suites S-93 newly registered that fail on CI (quarantined until 2026-10-03): test-add-dir-reaches-provider.sh (--add-dir never reaches the provider argv; possibly a real product defect), test-static-analysis-tsconfig.sh (tsc -p . fails on a path-aliased import on CI), test-doctor-json-skills.sh | the three suites and the code each exercises | MEDIUM | each passes on Linux CI (or is deleted with a stated reason) and its quarantine entry is removed | released@2026-09-27T18:12Z | Evidence: Tests run 36334599806, jobs 108662926880 and 108662926920. Batch 1 (build then review), dispatched 17:06. Train 4, pushed 08e4a7d4 at 17:48:38Z (ls-remote verified); approved by review (1/1; HIGH for S-116). P2.council-inconclusive-cannot-exit-zero removed from pending.txt (proven). Quarantine list now empty. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
130
130
  | S-111 | Part C item 9 returns: CI python suite runs pytest -n auto again after S-102 | .github/workflows/test.yml, requirements-test.txt | LOW | 10 of 10 capped-container runs of test_build_supervisor.py with -n 4 under load, 0 failures | released@2026-09-27T18:12Z | Train 5 (51ae52fe). Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
131
- | S-112 | P8 pending: ablation producer writing .loki/quality/ablation.json (load_bearing / not_load_bearing / not_applicable) | autonomy/lib/ablation.py, tests/test-ablation.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | RISKY: rewrites the user working tree in place; needs restore-on-signal. Not wired into run.sh (BACKLOG 34). Held. |
131
+ | S-112 | P8 pending: ablation producer writing .loki/quality/ablation.json (load_bearing / not_load_bearing / not_applicable) | autonomy/lib/ablation.py, tests/test-ablation.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | RISKY: rewrites the user working tree in place; needs restore-on-signal. Not wired into run.sh (BACKLOG 34). Held. Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
132
132
  | S-113 | P8 pending: proof-generator copies ablation.json into facts.ablation; never VERIFIED when not_load_bearing | autonomy/lib/proof-generator.py (collector and _compute_headline), tests/test-proof-ablation-headline.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T17:53Z | Batch 2, dispatched 17:14. In v9.65.0 (release commit 0103adfa, pushed 17:45:33Z; required-ci success). |
133
- | S-114 | P3 pending: check_author.py context (spec-only inputs) | autonomy/lib/check_author.py, tests/test-check-author-context.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | Held: present-but-unwired promotion risk (BACKLOG 34); needs a run.sh wiring slice. |
134
- | S-115 | P3 pending: checklist-verify.py --freeze (definition digest, hash mismatch on edit) | autonomy/checklist-verify.py, tests/test-checklist-freeze.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | Held: unwired (BACKLOG 34). |
133
+ | S-114 | P3 pending: check_author.py context (spec-only inputs) | autonomy/lib/check_author.py, tests/test-check-author-context.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | Held: present-but-unwired promotion risk (BACKLOG 34); needs a run.sh wiring slice. Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
134
+ | S-115 | P3 pending: checklist-verify.py --freeze (definition digest, hash mismatch on edit) | autonomy/checklist-verify.py, tests/test-checklist-freeze.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | Held: unwired (BACKLOG 34). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
135
135
  | S-116 | P2 pending: council must not approve inconclusive evidence on the vote alone | autonomy/completion-council.sh (evidence gate, evaluate), tests/test-council-inconclusive-no-approve.sh | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:12Z | Batch 2, dispatched 17:14. Train 4, pushed 08e4a7d4 at 17:48:38Z (ls-remote verified); approved by review (1/1; HIGH for S-116). P2.council-inconclusive-cannot-exit-zero removed from pending.txt (proven). Quarantine list now empty. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
136
- | S-117 | P4 corpus 1/5: 20 logic-bug seeded defects | benchmarks/seeded-defects/cases/SD-0001..0020, fragments/logic-bug.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision: whether to spend 6 slices on the corpus (S-117..S-122). |
137
- | S-118 | P4 corpus 2/5: 20 spec-miss seeded defects | benchmarks/seeded-defects/cases/SD-0021..0040, fragments/spec-miss.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision (corpus). |
138
- | S-119 | P4 corpus 3/5: 20 test-fitting seeded defects | benchmarks/seeded-defects/cases/SD-0041..0060, fragments/test-fitting.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision (corpus). |
139
- | S-120 | P4 corpus 4/5: 20 mock-abuse seeded defects | benchmarks/seeded-defects/cases/SD-0061..0080, fragments/mock-abuse.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision (corpus). |
140
- | S-121 | P4 corpus 5/5: 20 security seeded defects (hermetic) | benchmarks/seeded-defects/cases/SD-0081..0100, fragments/security.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision (corpus). |
141
- | S-122 | P4 corpus assembler build_manifest.py (schema v2, duplicate/category/count checks) | benchmarks/seeded-defects/build_manifest.py, tests/test-seeded-defects-manifest.sh | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | ready@2026-09-27T17:14Z | CEO decision (corpus). |
136
+ | S-117 | P4 corpus 1/5: 20 logic-bug seeded defects | benchmarks/seeded-defects/cases/SD-0001..0020, fragments/logic-bug.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision: whether to spend 6 slices on the corpus (S-117..S-122). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
137
+ | S-118 | P4 corpus 2/5: 20 spec-miss seeded defects | benchmarks/seeded-defects/cases/SD-0021..0040, fragments/spec-miss.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision (corpus). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
138
+ | S-119 | P4 corpus 3/5: 20 test-fitting seeded defects | benchmarks/seeded-defects/cases/SD-0041..0060, fragments/test-fitting.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision (corpus). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
139
+ | S-120 | P4 corpus 4/5: 20 mock-abuse seeded defects | benchmarks/seeded-defects/cases/SD-0061..0080, fragments/mock-abuse.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision (corpus). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
140
+ | S-121 | P4 corpus 5/5: 20 security seeded defects (hermetic) | benchmarks/seeded-defects/cases/SD-0081..0100, fragments/security.json | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision (corpus). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
141
+ | S-122 | P4 corpus assembler build_manifest.py (schema v2, duplicate/category/count checks) | benchmarks/seeded-defects/build_manifest.py, tests/test-seeded-defects-manifest.sh | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | parked@2026-09-27T20:00Z | CEO decision (corpus). Held for a CEO decision (P3/P4/P8 moat scope), not dispatchable until then. |
142
142
  | S-123 | BACKLOG 20: JWKS must be https (loopback http only) | autonomy/loki (attestation check), tests/test-jwks-https-only.sh | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:55Z | Batch 2, dispatched 17:14. Review CONCERN/REJECT; rework plus re-review dispatched 17:49 (workflow wf_b1414df6-a66) with the reviewer findings. Rework re-review APPROVE (workflow wf_b1414df6-a66); train 6 pushed 0bd45144 at 18:10:14Z (ls-remote verified). Released in v9.67.0 (release commit 7f470727; publish-npm success). |
143
143
  | S-124 | BACKLOG 79: iteration 0 drops a stale static-analysis.pass | autonomy/run.sh (iteration-0 drop block), tests/test-iteration0-drops-static-analysis.sh | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:55Z | Batch 2, dispatched 17:14. Review CONCERN/REJECT; rework plus re-review dispatched 17:49 (workflow wf_b1414df6-a66) with the reviewer findings. Rework re-review APPROVE (workflow wf_b1414df6-a66); train 6 pushed 0bd45144 at 18:10:14Z (ls-remote verified). Released in v9.67.0 (release commit 7f470727; publish-npm success). |
144
144
  | S-125 | BACKLOG 76/89: done-recognition tests_axis zero-test and failed_count honesty | autonomy/lib/done-recognition.sh (tests_axis), tests/test-done-recognition-tests-axis.sh | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:55Z | Batch 2, dispatched 17:14. Review CONCERN/REJECT; rework plus re-review dispatched 17:49 (workflow wf_b1414df6-a66) with the reviewer findings. Rework re-review APPROVE (workflow wf_b1414df6-a66); train 6 pushed 0bd45144 at 18:10:14Z (ls-remote verified). Released in v9.67.0 (release commit 7f470727; publish-npm success). |
@@ -148,28 +148,28 @@ set is declared to avoid overlap with those and with each other.
148
148
  | S-129 | BACKLOG 93: hard-deadline zero-exit leader waits only 0.2s for the PID file | tests/test-hard-deadline-confinement.sh | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:12Z | Batch 2, dispatched 17:14. Train 4, pushed 08e4a7d4 at 17:48:38Z (ls-remote verified); approved by review (1/1; HIGH for S-116). P2.council-inconclusive-cannot-exit-zero removed from pending.txt (proven). Quarantine list now empty. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
149
149
  | S-130 | BACKLOG 117: SettingsPage lists deprecated Gemini and a hardcoded build date | web-app/src/pages/SettingsPage.tsx | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T18:12Z | Batch 2, dispatched 17:14. Train 5, pushed 51ae52fe at 17:52:16Z (ls-remote verified); approved by review. S-88: P9 4/4 in 43s (was about 90s). S-130: web-app dist rebuilt. S-111: pytest -n auto back on after S-102. Released in v9.66.0 (release commit 0a69d19b, pushed 18:03:32Z). |
150
150
  | S-131 | BACKLOG 106 (Bun): budget warns when capped and spend is unmeasured | loki-ts/src/runner/budget.ts, loki-ts/tests/runner/budget.test.ts | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (17:10Z cut) | released@2026-09-27T17:53Z | Batch 2, dispatched 17:14; CEO note: warn-never-pause default. In v9.65.0 (release commit 0103adfa, pushed 17:45:33Z; required-ci success). |
151
- | S-132 | Velocity: skip heavy Tests jobs on a version-bump-only commit whose parent Tests run succeeded (eligibility no looser than release.yml STEP 1) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); cherry-picked 7b328b1f+c50efd15 into train 9, main a39c4995 pushed 19:06:25 (`git ls-remote origin refs/heads/main` = a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
151
+ | S-132 | Velocity: skip heavy Tests jobs on a version-bump-only commit whose parent Tests run succeeded (eligibility no looser than release.yml STEP 1) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); cherry-picked 7b328b1f+c50efd15 into train 9, main a39c4995 pushed 19:06:25 (`git ls-remote origin refs/heads/main` = a39c4995). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
152
152
  | S-133 | Velocity: release.yml required-ci poll 30s to 10s; fix stale publish-npm comment | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed aada49d8 (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
153
- | S-134 | Velocity: rebuild shard-durations.tsv from a recent successful run; drift test | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; abe6a7ae into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
153
+ | S-134 | Velocity: rebuild shard-durations.tsv from a recent successful run; drift test | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; abe6a7ae into train 9 (a39c4995). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
154
154
  | S-135 | Velocity: parallelize trust-core probe mutations (130s) | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Blocked as scoped: probe_case mutates the shared repo in place (50 of 91 sites target autonomy/run.sh); reviewer reproduced the race. Re-scope: a private repo copy per worker plus a target override. Batch 5 build, re-scoped to a private repo copy per worker (wf_38d4e17c-211). |
155
- | S-136 | Velocity: tests/test-select-tests.sh under 30s, same 38 cases | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 7fc63d5b REJECT (mapfile crashes under /bin/bash 3.2); rework dispatched 18:53. cafbf57c re-review APPROVE (38/38 under /bin/bash 3.2, 25.6s); lands after the release 10 bump. Note: two builders converged on the same fix. 7fc63d5b+cafbf57c onto main b61045fd pushed 19:19:39 (`/bin/bash tests/test-select-tests.sh` = 38 passed, 0 failed, 33.6s). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
156
- | S-137 | S-81 follow-up: shard-coverage T4 enumerates the real runner | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 4107e16f into train 9 (a39c4995). Fix-forward 6e48decb: T4 unsharded run inherited LOKI_TEST_SHARD in CI (Tests run 36343130286 shard 7/8: "unsharded real run selected 41 of 564"); `LOKI_TEST_SHARD=6/8 bash tests/test-shard-coverage.sh` 18/1 before, 19/0 after. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
157
- | S-138 | GUARDS 12: lint so test fixtures never write the real ~/.gitconfig | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. 849b655e review REJECT; rework pending. 2f29ad49 re-review REJECT (2nd); rework in batch 5 (wf_38d4e17c-211). |
158
- | S-139 | GUARDS 13 + BACKLOG 136: RELEASED_AHEAD_OF_NPM; UNKNOWN on tag/npm disagreement | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 28d18393 onto main 06bf5406 pushed 19:08:09. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
159
- | S-140 | BACKLOG 103: jest "Test Suites N failed" / vitest "Test Files N failed" count as failures | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Built 6dbfc1e6; review pending. Review APPROVE; 6dbfc1e6 onto main e952e1ae pushed 19:09:04. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
160
- | S-141 | S-49 follow-up: remaining council readers (~1425, ~1564, ~4232) use -I -S | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); 001576f3+958f6548 onto main 06bf5406 pushed 19:08:09. Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
161
- | S-142 | S-48 follow-up: convergence-floor NEGATIVE-C for the runner guard | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 59e32d75 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
162
- | S-143 | BACKLOG 117: drop Gemini/Railway/stale gate counts from 6 web-app files | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 6f901f91 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
155
+ | S-136 | Velocity: tests/test-select-tests.sh under 30s, same 38 cases | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 7fc63d5b REJECT (mapfile crashes under /bin/bash 3.2); rework dispatched 18:53. cafbf57c re-review APPROVE (38/38 under /bin/bash 3.2, 25.6s); lands after the release 10 bump. Note: two builders converged on the same fix. 7fc63d5b+cafbf57c onto main b61045fd pushed 19:19:39 (`/bin/bash tests/test-select-tests.sh` = 38 passed, 0 failed, 33.6s). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
156
+ | S-137 | S-81 follow-up: shard-coverage T4 enumerates the real runner | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 4107e16f into train 9 (a39c4995). Fix-forward 6e48decb: T4 unsharded run inherited LOKI_TEST_SHARD in CI (Tests run 36343130286 shard 7/8: "unsharded real run selected 41 of 564"); `LOKI_TEST_SHARD=6/8 bash tests/test-shard-coverage.sh` 18/1 before, 19/0 after. Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
157
+ | S-138 | GUARDS 12: lint so test fixtures never write the real ~/.gitconfig | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:31Z | Batch 4 (build then review), dispatched 18:17. 849b655e review REJECT; rework pending. 2f29ad49 re-review REJECT (2nd); rework in batch 5 (wf_38d4e17c-211). 7431f5dd 3rd REJECT; simplified rework (fail closed unless a named isolation helper is sourced) in batch 6 (wf_3510293b-09b). |
158
+ | S-139 | GUARDS 13 + BACKLOG 136: RELEASED_AHEAD_OF_NPM; UNKNOWN on tag/npm disagreement | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 28d18393 onto main 06bf5406 pushed 19:08:09. Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
159
+ | S-140 | BACKLOG 103: jest "Test Suites N failed" / vitest "Test Files N failed" count as failures | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Built 6dbfc1e6; review pending. Review APPROVE; 6dbfc1e6 onto main e952e1ae pushed 19:09:04. Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
160
+ | S-141 | S-49 follow-up: remaining council readers (~1425, ~1564, ~4232) use -I -S | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | HIGH | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE (HIGH); 001576f3+958f6548 onto main 06bf5406 pushed 19:08:09. Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
161
+ | S-142 | S-48 follow-up: convergence-floor NEGATIVE-C for the runner guard | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 59e32d75 into train 9 (a39c4995). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
162
+ | S-143 | BACKLOG 117: drop Gemini/Railway/stale gate counts from 6 web-app files | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 6f901f91 into train 9 (a39c4995). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
163
163
  | S-144 | Footer.tsx version joins release.sh --bump-only | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed edb706ed (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
164
164
  | S-145 | BACKLOG 118: GET /api/checklist/waivers returns 500 on a corrupt file | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed 2ef38a2f (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
165
- | S-146 | BACKLOG 118: one id="budget-banner" in the dashboard build | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 569e8cf4 review CONCERN; rework in batch 5 (wf_38d4e17c-211). |
166
- | S-147 | BACKLOG 118: loki metrics --json reports null for unmeasured, no invented time_saved | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | building@2026-09-27T19:10Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). f82eeda0 review CONCERN; rework in batch 5 (wf_38d4e17c-211). |
165
+ | S-146 | BACKLOG 118: one id="budget-banner" in the dashboard build | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | merged@2026-09-27T19:56Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). 569e8cf4 review CONCERN; rework in batch 5 (wf_38d4e17c-211). dc2e45a1 review CONCERN (e2e harness still targets budget-banner); rework in batch 6 (wf_3510293b-09b). Review APPROVE on acdbd03c; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
166
+ | S-147 | BACKLOG 118: loki metrics --json reports null for unmeasured, no invented time_saved | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | MEDIUM | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:47Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). f82eeda0 review CONCERN; rework in batch 5 (wf_38d4e17c-211). Re-review APPROVE; f82eeda0+920b1ae8 onto main c6ed3882 pushed 19:30:18 (`bash tests/test-metrics-json-unmeasured.sh` rc=0). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.71.0. |
167
167
  | S-148 | BACKLOG 118: trust.html says "Not enough history yet" when every axis is insufficient | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:05Z | Batch 4 (build then review), dispatched 18:17. Built 92c0f9d8; review pending. Review APPROVE; cherry-picked for train 8. Released in v9.69.0 (b2444763, `git ls-remote origin refs/tags/v9.69.0^{}` = b2444763). |
168
168
  | S-149 | BACKLOG 118: prompt_optimizer never-ran vs corrupt markers | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed 06eea9ea (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
169
169
  | S-150 | BACKLOG 118: migration progress null (not 0/0) on a corrupt/missing file | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T18:55Z | Batch 4 (build then review), dispatched 18:17. Review APPROVE; train 7 pushed b7a8dd50 (main b7a8dd50 at 18:45:14Z, ls-remote verified). In v9.68.0 (release commit 8d17be2b, pushed 18:54:35Z); released when publish-npm succeeds. |
170
- | S-151 | BACKLOG 118: analytics heatmap shows no-data before the activity window | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:28Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 97f8b6c5 into train 9 (a39c4995). Released in v9.70.0 (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). |
171
- | S-152 | Incident guard: only the Chief of Staff pushes main. A worktree agent pushed 28926937 at 18:35Z. Block `git push` and any commit on main from inside .claude/worktrees (guard hook or a pre-push check in .githooks/pre-push that refuses unless LOKI_RELEASE_MANAGER=1 is set by the orchestrator) | scripts/v10-guard.sh and/or .githooks/pre-push, tests | HIGH | a push from a worktree path is refused with a clear reason; the orchestrator push with the marker still works; fixture per case | building@2026-09-27T19:10Z | Evidence: `git log -1 28926937` author asklokesh 14:35:11; `git ls-remote origin refs/heads/main` = 28926937. f02bcbde review CONCERN (no allowed non-main case); rework in batch 5 (wf_38d4e17c-211). |
172
- | S-153 | Release reuse: add web-app/src/components/Footer.tsx to release.yml required-ci ALLOWLIST with the same version-only compare, so a version-bump commit that now rewrites the Footer (S-144) can still reuse its parent verdict; also rebuild web-app/dist on --bump-only so the shipped footer shows the version | .github/workflows/release.yml (ALLOWLIST), scripts/release.sh, tests/test_release_required_ci.py | HIGH | a bump touching only allowlisted files incl. Footer.tsx is eligible; a Footer change beyond the version string is not; replay of 8d17be2b is eligible | building@2026-09-27T19:10Z | Evidence: v9.68.0 bump 8d17be2b touches Footer.tsx (git show --stat 8d17be2b). Batch 5 build (wf_38d4e17c-211). |
170
+ | S-151 | BACKLOG 118: analytics heatmap shows no-data before the activity window | files per docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | LOW | wall check in docs/v10/ARCHITECT-CUTS.md (18:05Z cut) | released@2026-09-27T19:42Z | Batch 4 (build then review), dispatched 18:17. Batch-4 builder was diverted by a relayed message and built nothing; re-dispatched 18:37 in batch 4b (wf_63d4c91e-86d). Review APPROVE; 97f8b6c5 into train 9 (a39c4995). Tagged v9.70.0, awaiting publish-npm (`git ls-remote origin refs/tags/v9.70.0^{}` = 6c459dfa). Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.70.0. |
171
+ | S-152 | Incident guard: only the Chief of Staff pushes main. A worktree agent pushed 28926937 at 18:35Z. Block `git push` and any commit on main from inside .claude/worktrees (guard hook or a pre-push check in .githooks/pre-push that refuses unless LOKI_RELEASE_MANAGER=1 is set by the orchestrator) | scripts/v10-guard.sh and/or .githooks/pre-push, tests | HIGH | a push from a worktree path is refused with a clear reason; the orchestrator push with the marker still works; fixture per case | merged@2026-09-27T19:56Z | Evidence: `git log -1 28926937` author asklokesh 14:35:11; `git ls-remote origin refs/heads/main` = 28926937. f02bcbde review CONCERN (no allowed non-main case); rework in batch 5 (wf_38d4e17c-211). c9590985 review CONCERN (shellcheck SC2163); rework in batch 6 (wf_3510293b-09b). Review APPROVE on 3b649b51; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
172
+ | S-153 | Release reuse: add web-app/src/components/Footer.tsx to release.yml required-ci ALLOWLIST with the same version-only compare, so a version-bump commit that now rewrites the Footer (S-144) can still reuse its parent verdict; also rebuild web-app/dist on --bump-only so the shipped footer shows the version | .github/workflows/release.yml (ALLOWLIST), scripts/release.sh, tests/test_release_required_ci.py | HIGH | a bump touching only allowlisted files incl. Footer.tsx is eligible; a Footer change beyond the version string is not; replay of 8d17be2b is eligible | released@2026-09-27T19:47Z | Evidence: v9.68.0 bump 8d17be2b touches Footer.tsx (git show --stat 8d17be2b). Batch 5 build (wf_38d4e17c-211). Review APPROVE (HIGH); e11137ad onto main c6ed3882 pushed 19:30:18. Published: `npm view loki-mode version` = 9.71.0; npm time lists 9.71.0. |
173
173
  | 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. |
174
174
  | 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). |
175
175
  | 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. |
@@ -213,6 +213,26 @@ set is declared to avoid overlap with those and with each other.
213
213
  | 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). |
214
214
  | 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. |
215
215
  | 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). |
216
+ | S-154 | GUARDS 5 + TODO 8: prune-worktrees.sh treats a cherry-picked branch (git cherry, no + lines) as merged; test forbids mtime signals | scripts/prune-worktrees.sh, tests/test-prune-worktrees.sh (new) | MEDIUM | bash tests/test-prune-worktrees.sh exits 0; cherry-picked fixture listed, one-unique-commit, locked and dirty fixtures kept; dropping the git cherry branch fails the case | merged@2026-09-27T19:56Z | Removes worktrees only via git worktree remove. Captain registers the test. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on a41e625f; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
217
+ | S-155 | Velocity: reachability scan (95s on CI, 47s local) under 10s via a per-module stem prefilter, identical verdicts | tests/lib/scan-unreachable-shipped.py | LOW | scan wall time under 10s; stdout and rc byte-identical to the pre-change capture; bash tests/test-no-unreachable-shipped.sh 4 passed 0 failed; removing one real require is still reported | merged@2026-09-27T19:56Z | Builder measures regex vs I/O first and records both numbers. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3f786ce0; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
218
+ | S-156 | BACKLOG 127 remainder: auto-capture shadow_write runs with PROJECT_DIR unset, and float() splices episode importance into python source | autonomy/run.sh (shadow_write auto-capture block about 21380-21396 only), tests/test-autocapture-shadow-write-guard.sh (new) | HIGH | bash tests/test-autocapture-shadow-write-guard.sh exits 0 under /bin/bash and bash 5; no marker from a planted cwd memory package; no file from an injected importance; trust-core suite passes | merged@2026-09-27T19:56Z | Builder names who writes episode_path_file. Only run.sh row in this cut. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 71d7a246; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
219
+ | S-157 | BACKLOG 98/89: council member vote and _council_convergence_evidence_green read pass:true as green whatever failed_count says | autonomy/completion-council.sh (those 2 parsers only), tests/test-council-failed-count-honesty.sh (new) | HIGH | pass:true with failed_count 2 is not green at both sites; failed_count 0 stays green; trust-core and convergence-floor suites pass; reverting either site fails its case | building@2026-09-27T19:31Z | Mirrors the evidence gate rule (~2014). Only completion-council.sh row in this cut. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. |
220
+ | S-158 | BACKLOG 118: per-run cost_partial dropped by /api/cost/timeline runs[] and /api/proofs; pages show a lower bound as a total | dashboard/server.py (runs.append in _compute_cost_timeline and the /api/proofs row only), dashboard/static/cost.html, dashboard/static/proofs.html, tests/dashboard/test_cost_partial_surfaced.py (new) | MEDIUM | pytest test_cost_partial_surfaced.py passes; fixture cost_partial true surfaces in both endpoints and renders as at least $X; dropping the key fails | merged@2026-09-27T19:56Z | Builder names the consumers checked. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 931a93b6; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
221
+ | S-159 | BACKLOG 114: NLSearch renders No results found when the search request failed | web-app/src/components/NLSearch.tsx, web-app/src/components/NLSearch.state.test.mjs (new) | LOW | node --test NLSearch.state.test.mjs passes incl. the negative assertion; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on ea5b4462; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
222
+ | S-160 | BACKLOG 114: CommandPalette file-search failure reads as No results found | web-app/src/components/CommandPalette.tsx, web-app/src/components/CommandPalette.state.test.mjs (new) | LOW | node --test CommandPalette.state.test.mjs passes; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3f9873f3; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
223
+ | S-161 | BACKLOG 114: ProjectsPage ignores usePolling error and says No projects yet on a failed fetch | web-app/src/pages/ProjectsPage.tsx, web-app/src/pages/ProjectsPage.state.test.mjs (new) | LOW | node --test ProjectsPage.state.test.mjs passes (error, stale-data and real-empty cases); npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on d2dd3645; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
224
+ | S-162 | BACKLOG 114: SecretsPanel and DocsPanel swallow fetch errors into No secrets / No documentation empty states | web-app/src/components/ProjectWorkspace.tsx (SecretsPanel and DocsPanel fetch and empty branches only), web-app/src/components/ProjectWorkspace.panels.test.mjs (new) | LOW | node --test ProjectWorkspace.panels.test.mjs passes; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 6f6a6207; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
225
+ | S-163 | BACKLOG 114: CICDPanel maps neutral/action_required/stale/null conclusions to Failed and unknown statuses to running | web-app/src/components/CICDPanel.tsx (3 normalizers and status map only), web-app/src/components/CICDPanel.status.test.mjs (new) | LOW | node --test CICDPanel.status.test.mjs passes for every conclusion; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 36052758; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
226
+ | S-164 | BACKLOG 114: AIChatPanel prints Done. for a non-zero exit with no output | web-app/src/components/AIChatPanel.tsx (the two Done. fallbacks only), web-app/src/components/AIChatPanel.result.test.mjs (new) | LOW | node --test AIChatPanel.result.test.mjs passes; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 8aceef56; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
227
+ | S-165 | BACKLOG 117 remainder: TrustedBy asserts Trusted by developers; ChangelogWidget shows March 2026 v6.x as Recent Changes | web-app/src/components/TrustedBy.tsx, web-app/src/components/ChangelogWidget.tsx | LOW | grep for Trusted by developers and 6.71.1 in those files returns rc 1; npx tsc -b exits 0 | merged@2026-09-27T19:56Z | Copy only. Captain rebuilds web-app/dist. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 97ba623f; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
228
+ | S-166 | BACKLOG 114: checkpoint viewer ignores a rejected allSettled fetch and clears the error | dashboard-ui/components/loki-checkpoint-viewer.js (load block only), dashboard-ui/tests/loki-checkpoint-viewer-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes incl. the negative assertion | merged@2026-09-27T19:56Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 4035d21d; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
229
+ | S-167 | BACKLOG 114: council transcripts render a failed hook-events read as zero events | dashboard-ui/components/loki-council-transcripts.js (hook events load only), dashboard-ui/tests/loki-council-transcripts-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes | merged@2026-09-27T19:56Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 3fea74e8; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
230
+ | S-168 | BACKLOG 114: task board hides a server load error whenever local tasks exist | dashboard-ui/components/loki-task-board.js (catch and error render only), dashboard-ui/tests/loki-task-board-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-task-board-modal-guard test still passes | merged@2026-09-27T19:56Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on aa2a64a4; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
231
+ | S-169 | BACKLOG 114: log stream swallows API failures with an empty catch | dashboard-ui/components/loki-log-stream.js (API poll catch and empty render only), dashboard-ui/tests/loki-log-stream-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; loki-poll-registry test still passes | building@2026-09-27T19:57Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. a990a9ce review REJECT; rework dispatched 19:57Z. |
232
+ | S-170 | BACKLOG 114: API keys panel renders No API keys configured under its own load-error banner | dashboard-ui/components/loki-api-keys.js (table branch only), dashboard-ui/tests/loki-api-keys-fetch-error.node.test.mjs (new) | LOW | node --test the new file passes; error render lacks the empty-state sentence | merged@2026-09-27T19:56Z | Captain rebuilds dashboard/static/index.html. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on ab837a75; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
233
+ | S-171 | BACKLOG 124: lint for response fields interpolated into innerHTML without the escape helper | tests/test-no-unescaped-innerhtml.sh (new), tests/lib/scan-unescaped-innerhtml.py (new) | MEDIUM | passes on main with a reasoned in-file allowlist; planted fixture exits 1; empty-reason entry fails; at least 20 files scanned | building@2026-09-27T19:31Z | Any real XSS found is reported only; repairs go to separate slices. Captain registers. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. |
234
+ | S-172 | BACKLOG 132: shadow-write mutant check is green on bash 5.3 and red on /bin/bash 3.2 | tests/test-council-shadow-write-project-dir.sh | LOW | bash tests/test-council-shadow-write-project-dir.sh exits 0; mutant leg red under both /bin/bash and PATH bash, both versions printed | merged@2026-09-27T19:56Z | Test-only. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on e2114d09; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
235
+ | S-173 | BACKLOG 135: P2.council-readers-not-shadowed does not drive council_managed_should_stop (cwd-shadow class only) | tests/moat/p2-honest-verdict.sh (that case only) | HIGH | p2-honest-verdict.sh prints CASE P2.council-readers-not-shadowed PASS; removing the sys.path filter in a scratch copy prints FAIL | merged@2026-09-27T19:56Z | No .pth leg: that reader is still python3 -E, so a .pth leg would redden a proven case; follows alternate A2. Source: 19:10Z cut. Batch 6 (wf_3510293b-09b), build then review. Review APPROVE on 6bc4b5cf; in train 11, main 2a024770 pushed 19:56:04 (`git ls-remote origin refs/heads/main` = 2a024770). |
216
236
 
217
237
  Every slice above: implement with red-then-green tests, run diff-scoped tests
218
238
  plus `bash tests/moat/run.sh` in your own worktree, never touch `main`,
package/docs/v10/TODO.md CHANGED
@@ -16,7 +16,9 @@ Target: 3-5 releases per hour (CEO 2026-09-27 17:05Z), 60 per day.
16
16
  5. [done 19:28:09Z] Release 10 = v9.70.0 from green b61045fd (main and tag 6c459dfa by ls-remote).
17
17
  6. [done 19:19Z] S-136 landed (b61045fd); S-137 fix-forward 6e48decb.
18
18
  7. [running] Batch 5 (wf_38d4e17c-211): reworks S-138, S-146, S-147, S-152; builds S-50, S-153, S-135; Architect cut S-154..S-173.
19
- 8. [pending] Prune each worktree once its slice is merged (count now 7 of 15).
19
+ 8. [running] WORKTREE_COUNT 24 of 15 at 19:37Z: my batch 6 dispatch opened 20 isolated worktrees at once (`git worktree list | grep -c claude/worktrees` = 24, every one owned by a live builder). Prune each as its slice merges; from now on a batch opens at most 15 minus the current count.
20
+ 10. [done 19:37:24Z] Release 11 = v9.71.0 from green c6ed3882 (main and tag 4972a112 by ls-remote).
21
+ 11. [done] Rows released at tag push reverted to merged until publish-npm succeeds (D27).
20
22
  9. [pending] Drift audit every 6 turns; guard review every 50 turns.
21
23
 
22
24
  ## Team members
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var at=Object.create;var{getPrototypeOf:ot,defineProperty:OG,getOwnPropertyNames:st}=Object;var nt=Object.prototype.hasOwnProperty;function rt($){return this[$]}var tt,et,$e=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?tt??=new WeakMap:et??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?at(ot($)):{};let J=X||!$||!$.__esModule?OG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of st($))if(!nt.call(J,q))OG(J,q,{get:rt.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var Zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var Xe=($)=>$;function Qe($,X){this[$]=Xe.bind(null,X)}var B1=($,X)=>{for(var Q in X)OG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:Qe.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var WR={};B1(WR,{lokiDir:()=>h0,homeLokiDir:()=>GQ,findRepoRootForVersion:()=>LG,REPO_ROOT:()=>O1});import{resolve as h2,dirname as jG}from"path";import{fileURLToPath as ze}from"url";import{existsSync as Kq}from"fs";import{homedir as Ze}from"os";function Ke(){let $=HR;for(let X=0;X<6;X++){if(Kq(h2($,"VERSION"))&&Kq(h2($,"autonomy/run.sh")))return $;let Q=jG($);if(Q===$)break;$=Q}return h2(HR,"..","..","..")}function LG($){let X=$;for(let Q=0;Q<6;Q++){if(Kq(h2(X,"VERSION"))&&Kq(h2(X,"autonomy/run.sh")))return X;let z=jG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function GQ(){return h2(Ze(),".loki")}var HR,O1;var k1=s(()=>{HR=jG(ze(import.meta.url));O1=Ke()});import{readFileSync as Je}from"fs";import{resolve as qe,dirname as Ve}from"path";import{fileURLToPath as Ye}from"url";function L9(){if(t3!==null)return t3;let $="9.71.0";if(typeof $==="string"&&$.length>0)return t3=$,t3;try{let X=Ve(Ye(import.meta.url)),Q=LG(X);t3=Je(qe(Q,"VERSION"),"utf-8").trim()}catch{t3="unknown"}return t3}var t3=null;var Jq=s(()=>{k1()});var LR={};B1(LR,{runOrThrow:()=>Re,run:()=>X1,readStreamCapped:()=>qq,commandVersion:()=>we,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>jR});async function qq($,X=jR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function X1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([qq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Re($,X={}){let Q=await X1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=Ie($),Q=await X1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Ie($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function we($,X="--version"){if(!await g5($))return null;let z=await X1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var jR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Pe?"":$}var Pe,p0,$5,Z1,l61,A1,f1,m5,n;var e7=s(()=>{Pe=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),Z1=g2("\x1B[1;33m"),l61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),n=g2("\x1B[0m")});import{existsSync as he}from"fs";async function Z2(){if(BQ!==void 0)return BQ;let $="/opt/homebrew/bin/python3.12";if(he($))return BQ=$,$;let X=await g5("python3.12");if(X)return BQ=X,X;let Q=await g5("python3");return BQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return X1([Q,"-c",$],X)}var BQ;var m2=s(()=>{y8()});var gR={};B1(gR,{runStatus:()=>Y00});import{existsSync as u5,readFileSync as T9,readdirSync as kR,statSync as SR}from"fs";import{resolve as A5,basename as $00}from"path";import{homedir as X00}from"os";function yR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function bR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Yq/X);if(Z>Yq)Z=Yq;let K=Yq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=Z1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=yR($),Y=yR(X);return` ${f1}${Q}${n} ${J}[${q}]${n} ${z}% (${V} / ${Y})`}async function z00(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${n}
2
+ var at=Object.create;var{getPrototypeOf:ot,defineProperty:OG,getOwnPropertyNames:st}=Object;var nt=Object.prototype.hasOwnProperty;function rt($){return this[$]}var tt,et,$e=($,X,Q)=>{var z=$!=null&&typeof $==="object";if(z){var Z=X?tt??=new WeakMap:et??=new WeakMap,K=Z.get($);if(K)return K}Q=$!=null?at(ot($)):{};let J=X||!$||!$.__esModule?OG(Q,"default",{value:$,enumerable:!0}):Q;for(let q of st($))if(!nt.call(J,q))OG(J,q,{get:rt.bind($,q),enumerable:!0});if(z)Z.set($,J);return J};var Zq=($,X)=>()=>(X||$((X={exports:{}}).exports,X),X.exports);var Xe=($)=>$;function Qe($,X){this[$]=Xe.bind(null,X)}var B1=($,X)=>{for(var Q in X)OG($,Q,{get:X[Q],enumerable:!0,configurable:!0,set:Qe.bind(X,Q)})};var s=($,X)=>()=>($&&(X=$($=0)),X);var w5=import.meta.require;var WR={};B1(WR,{lokiDir:()=>h0,homeLokiDir:()=>GQ,findRepoRootForVersion:()=>LG,REPO_ROOT:()=>O1});import{resolve as h2,dirname as jG}from"path";import{fileURLToPath as ze}from"url";import{existsSync as Kq}from"fs";import{homedir as Ze}from"os";function Ke(){let $=HR;for(let X=0;X<6;X++){if(Kq(h2($,"VERSION"))&&Kq(h2($,"autonomy/run.sh")))return $;let Q=jG($);if(Q===$)break;$=Q}return h2(HR,"..","..","..")}function LG($){let X=$;for(let Q=0;Q<6;Q++){if(Kq(h2(X,"VERSION"))&&Kq(h2(X,"autonomy/run.sh")))return X;let z=jG(X);if(z===X)break;X=z}return h2($,"..","..","..")}function h0(){return process.env.LOKI_DIR??h2(process.cwd(),".loki")}function GQ(){return h2(Ze(),".loki")}var HR,O1;var k1=s(()=>{HR=jG(ze(import.meta.url));O1=Ke()});import{readFileSync as Je}from"fs";import{resolve as qe,dirname as Ve}from"path";import{fileURLToPath as Ye}from"url";function L9(){if(t3!==null)return t3;let $="9.73.0";if(typeof $==="string"&&$.length>0)return t3=$,t3;try{let X=Ve(Ye(import.meta.url)),Q=LG(X);t3=Je(qe(Q,"VERSION"),"utf-8").trim()}catch{t3="unknown"}return t3}var t3=null;var Jq=s(()=>{k1()});var LR={};B1(LR,{runOrThrow:()=>Re,run:()=>X1,readStreamCapped:()=>qq,commandVersion:()=>we,commandExists:()=>g5,ShellError:()=>CG,MAX_STDOUT_BYTES:()=>jR});async function qq($,X=jR){let Q=$.getReader(),z=new TextDecoder,Z="",K=0;try{while(K<X){let{done:J,value:q}=await Q.read();if(J)break;if(!q)continue;if(K+=q.byteLength,K>X){let V=q.byteLength-(K-X);Z+=z.decode(q.subarray(0,V),{stream:!0});break}Z+=z.decode(q,{stream:!0})}Z+=z.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return Z}async function X1($,X={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),z,Z;if(X.timeoutMs&&X.timeoutMs>0)z=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}Z=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[K,J,q]=await Promise.all([qq(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:J,exitCode:q}}finally{if(z)clearTimeout(z);if(Z)clearTimeout(Z)}}async function Re($,X={}){let Q=await X1($,X);if(Q.exitCode!==0)throw new CG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function g5($){let X=Ie($),Q=await X1(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Ie($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function we($,X="--version"){if(!await g5($))return null;let z=await X1([$,X],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var jR=16777216,CG;var y8=s(()=>{CG=class CG extends Error{message;exitCode;stdout;stderr;constructor($,X,Q,z){super($);this.message=$;this.exitCode=X;this.stdout=Q;this.stderr=z;this.name="ShellError"}}});function g2($){return Pe?"":$}var Pe,p0,$5,Z1,l61,A1,f1,m5,n;var e7=s(()=>{Pe=(process.env.NO_COLOR??"").length>0;p0=g2("\x1B[0;31m"),$5=g2("\x1B[0;32m"),Z1=g2("\x1B[1;33m"),l61=g2("\x1B[0;34m"),A1=g2("\x1B[0;36m"),f1=g2("\x1B[1m"),m5=g2("\x1B[2m"),n=g2("\x1B[0m")});import{existsSync as he}from"fs";async function Z2(){if(BQ!==void 0)return BQ;let $="/opt/homebrew/bin/python3.12";if(he($))return BQ=$,$;let X=await g5("python3.12");if(X)return BQ=X,X;let Q=await g5("python3");return BQ=Q,Q}async function I4($,X={}){let Q=await Z2();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return X1([Q,"-c",$],X)}var BQ;var m2=s(()=>{y8()});var gR={};B1(gR,{runStatus:()=>Y00});import{existsSync as u5,readFileSync as T9,readdirSync as kR,statSync as SR}from"fs";import{resolve as A5,basename as $00}from"path";import{homedir as X00}from"os";function yR($){let X=Math.trunc($);if(X>=1e6)return`${(Math.trunc(X/1e6*10)/10).toFixed(1)}M`;if(X>=1000)return`${(Math.trunc(X/1000*10)/10).toFixed(1)}K`;return String(X)}function bR($,X,Q){if(X===0)return null;let z=Math.trunc($*100/X),Z=Math.trunc($*Yq/X);if(Z>Yq)Z=Yq;let K=Yq-Z,J=$5;if(z>=80)J=p0;else if(z>=50)J=Z1;let q="=".repeat(Math.max(0,Z))+" ".repeat(Math.max(0,K)),V=yR($),Y=yR(X);return` ${f1}${Q}${n} ${J}[${q}]${n} ${z}% (${V} / ${Y})`}async function z00(){if(await g5("jq"))return!0;return process.stdout.write(`${p0}Error: jq is required but not installed.${n}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
@@ -1349,4 +1349,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1349
1349
  `),2}case"start":{let{runStart:z}=await Promise.resolve().then(() => (ct(),pt));return z(Q)}default:return process.stderr.write(`Unknown command: ${X}
1350
1350
  `),process.stderr.write(lt),2}}ER();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var w61=await I61(Bun.argv.slice(2));process.exit(w61);
1351
1351
 
1352
- //# debugId=F73C88AAE3F1C113C39D0218FE920A8B
1352
+ //# debugId=5996D41402C8FBEF7DCF70CFDB989AAA
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '9.71.0'
78
+ __version__ = '9.73.0'