loki-mode 7.121.5 → 7.121.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,7 +15,7 @@ _The free, source-available autonomous coding agent by [Autonomi](https://www.au
15
15
 
16
16
  [Website](https://www.autonomi.dev/) | [Documentation](wiki/Home.md) | [Installation](docs/INSTALLATION.md) | [Changelog](CHANGELOG.md) | [Purple Lab -- deprecated v7.44.0](#purple-lab)
17
17
 
18
- **Current release: v7.121.1**
18
+ **Current release: v7.121.5**
19
19
 
20
20
  </div>
21
21
 
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v7.121.5
6
+ # Loki Mode v7.121.6
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -408,4 +408,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
408
408
 
409
409
  ---
410
410
 
411
- **v7.121.5 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
411
+ **v7.121.6 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.121.5
1
+ 7.121.6
package/api/openapi.yaml CHANGED
@@ -704,7 +704,7 @@ components:
704
704
  nullable: true
705
705
  provider:
706
706
  type: string
707
- enum: [claude, codex, gemini]
707
+ enum: [claude, codex, cline, aider]
708
708
  status:
709
709
  type: string
710
710
  enum: [starting, running, paused, stopping, stopped, failed, completed]
@@ -770,7 +770,7 @@ components:
770
770
  description: Path to PRD file
771
771
  provider:
772
772
  type: string
773
- enum: [claude, codex, gemini]
773
+ enum: [claude, codex, cline, aider]
774
774
  default: claude
775
775
  options:
776
776
  type: object
@@ -837,7 +837,9 @@ components:
837
837
  type: boolean
838
838
  codex:
839
839
  type: boolean
840
- gemini:
840
+ cline:
841
+ type: boolean
842
+ aider:
841
843
  type: boolean
842
844
  activeSession:
843
845
  type: string
@@ -153,7 +153,8 @@ export async function detailedStatus(_req: Request): Promise<Response> {
153
153
  async function checkProviders(): Promise<{
154
154
  claude: boolean;
155
155
  codex: boolean;
156
- gemini: boolean;
156
+ cline: boolean;
157
+ aider: boolean;
157
158
  }> {
158
159
  const checkCommand = async (cmd: string): Promise<boolean> => {
159
160
  try {
@@ -169,13 +170,16 @@ async function checkProviders(): Promise<{
169
170
  }
170
171
  };
171
172
 
172
- const [claude, codex, gemini] = await Promise.all([
173
+ // v7.5.18: gemini removed (runtime deprecated); cline + aider are the real
174
+ // Tier-2/Tier-3 providers. Probe the actually-supported set.
175
+ const [claude, codex, cline, aider] = await Promise.all([
173
176
  checkCommand("claude"),
174
177
  checkCommand("codex"),
175
- checkCommand("gemini"),
178
+ checkCommand("cline"),
179
+ checkCommand("aider"),
176
180
  ]);
177
181
 
178
- return { claude, codex, gemini };
182
+ return { claude, codex, cline, aider };
179
183
  }
180
184
 
181
185
  /**
@@ -38,9 +38,9 @@ export async function startSession(req: Request): Promise<Response> {
38
38
 
39
39
  // Validate provider
40
40
  const provider = data.provider || "claude";
41
- if (!["claude", "codex", "gemini"].includes(provider)) {
41
+ if (!["claude", "codex", "cline", "aider"].includes(provider)) {
42
42
  throw new LokiApiError(
43
- `Invalid provider: ${provider}. Must be one of: claude, codex, gemini`,
43
+ `Invalid provider: ${provider}. Must be one of: claude, codex, cline, aider`,
44
44
  ErrorCodes.VALIDATION_ERROR
45
45
  );
46
46
  }
@@ -51,7 +51,7 @@ export async function startSession(req: Request): Promise<Response> {
51
51
  "provider",
52
52
  provider,
53
53
  {
54
- alternativesRejected: ["claude", "codex", "gemini"].filter((p) => p !== provider),
54
+ alternativesRejected: ["claude", "codex", "cline", "aider"].filter((p) => p !== provider),
55
55
  context: {
56
56
  hasPrd: !!data.prdPath,
57
57
  options: data.options,
package/api/server.js CHANGED
@@ -38,7 +38,7 @@ const DEFAULT_HOST = '127.0.0.1';
38
38
  const PROJECT_DIR = process.env.LOKI_PROJECT_DIR || process.cwd();
39
39
 
40
40
  // Security constants
41
- const VALID_PROVIDERS = ['claude', 'codex', 'gemini'];
41
+ const VALID_PROVIDERS = ['claude', 'codex', 'cline', 'aider'];
42
42
  const MAX_BODY_SIZE = 1024 * 1024; // 1MB limit
43
43
  const MAX_LOG_LINES = 1000;
44
44
  const LOKI_DIR = path.join(PROJECT_DIR, '.loki');
@@ -48,7 +48,7 @@ class CLIBridge {
48
48
  */
49
49
  async startSession(
50
50
  prdPath?: string,
51
- provider: "claude" | "codex" | "gemini" = "claude",
51
+ provider: "claude" | "codex" | "cline" | "aider" = "claude",
52
52
  options: { dryRun?: boolean; verbose?: boolean } = {}
53
53
  ): Promise<Session> {
54
54
  const sessionId = `session_${Date.now()}_${crypto.randomUUID().slice(0, 8)}`;
package/api/types/api.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  export interface Session {
9
9
  id: string;
10
10
  prdPath: string | null;
11
- provider: "claude" | "codex" | "gemini";
11
+ provider: "claude" | "codex" | "cline" | "aider";
12
12
  status: SessionStatus;
13
13
  startedAt: string;
14
14
  updatedAt: string;
@@ -62,7 +62,7 @@ export type TaskStatus =
62
62
  // API Request/Response types
63
63
  export interface StartSessionRequest {
64
64
  prdPath?: string;
65
- provider?: "claude" | "codex" | "gemini";
65
+ provider?: "claude" | "codex" | "cline" | "aider";
66
66
  options?: {
67
67
  dryRun?: boolean;
68
68
  verbose?: boolean;
@@ -116,7 +116,8 @@ export interface HealthResponse {
116
116
  providers: {
117
117
  claude: boolean;
118
118
  codex: boolean;
119
- gemini: boolean;
119
+ cline: boolean;
120
+ aider: boolean;
120
121
  };
121
122
  activeSession: string | null;
122
123
  }
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "7.121.5"
10
+ __version__ = "7.121.6"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -0,0 +1,81 @@
1
+ # Competitive Analysis: Loki vs ralph-tui + zeroshot (2026-07-08, honest)
2
+
3
+ Source: fanned-out research agent, verified against competitor repos/docs + the
4
+ Loki repo. Lead with the uncomfortable truths.
5
+
6
+ ## The uncomfortable truth
7
+ zeroshot (github.com/the-open-engine/zeroshot) has the SAME trust thesis as Loki
8
+ -- "the verifier stays independent from the model that wrote the code": blind
9
+ validators, fail-closed gates, actionable rejections, complexity tiers, SQLite
10
+ resume -- implemented MORE LEGIBLY and more focused. Loki is NOT uniquely "the
11
+ verification tool." Claiming blind-review / independent-verifier as a Loki-only
12
+ differentiator would be fabrication (the founder's #1 forbidden outcome).
13
+
14
+ ralph-tui (github.com/subsy/ralph-tui) is a different animal: a terminal-UI
15
+ orchestrator for Geoff Huntley's "Ralph" loop (`while :; do cat PROMPT.md |
16
+ claude-code; done`). It beats Loki on ERGONOMICS + SIMPLICITY + community
17
+ momentum, NOT verification (Ralph pushes verification onto the operator).
18
+
19
+ ## What they do BETTER than Loki (honest)
20
+ - zeroshot: trust story is TIGHTER + more legible ("blind validation + fail-closed
21
+ + actionable rejections" = one sentence a skeptic trusts). Loki's 8+3+1 gates +
22
+ council + RARV-C is more thorough but far harder to explain/audit.
23
+ - zeroshot: EVIDENCE STALENESS -- fails closed when evidence is stale / older than
24
+ IMPLEMENTATION_READY / lacks usable evidence, with published status/timestamp/
25
+ command/exitCode/output. Better guarantee than Loki's "gates passed."
26
+ - zeroshot: COMPLEXITY-PROPORTIONAL validators (TRIVIAL=0, SIMPLE=1, STANDARD=2,
27
+ CRITICAL=5) -- only pays for verification the task warrants. Cost/speed win.
28
+ - zeroshot: per-run ISOLATION dial (none/worktree/--docker); native GitLab/Jira/
29
+ Azure backends; honest scope discipline ("not for 'make it faster'").
30
+ - ralph-tui: the TUI cockpit, multi-machine WebSocket fleet control, radical
31
+ legibility, 7 agent CLIs, viral community (awesome-ralph, ~2.4k stars).
32
+
33
+ ## What Loki genuinely has that they LACK (verified, not overclaimed)
34
+ - Spec-to-DEPLOYED-PRODUCT scope (both competitors stop at task/issue level).
35
+ - Persistent cross-project MEMORY (episodic/semantic/procedural + RAG). Neither
36
+ has a learning layer (zeroshot's SQLite is run-state, not learned knowledge).
37
+ - Anti-sycophancy Devil's-Advocate re-review triggered by unanimity.
38
+ - Semantic anti-fake-green DETECTORS (mock-integrity, test-mutation) -- dedicated
39
+ deterministic catchers for tautological/fitted tests.
40
+ - Legacy-healing mode (brownfield archaeology/stabilize/modernize).
41
+ NOTE: breadth is also a LIABILITY -- spec-to-product implies Loki handles
42
+ everything, a bigger promise; an over-confident run that fabricates progress on an
43
+ ill-defined task is the WORST outcome for a trust brand.
44
+
45
+ ## Honest gaps (where a user would prefer a competitor)
46
+ 1. Legibility: a skeptic can trust zeroshot/Ralph in minutes; Loki's surface is
47
+ hard to audit. A trust product that is itself hard to trust-verify is a real
48
+ problem.
49
+ 2. Cost/speed proportionality: zeroshot scales 0-5 validators; Loki runs a lot
50
+ for every change.
51
+ 3. Terminal ergonomics: ralph-tui's cockpit.
52
+ 4. Isolation ergonomics: zeroshot's clean --docker dial.
53
+ 5. Community/momentum: Loki is comparatively invisible in the public conversation.
54
+
55
+ ## Prioritized recommendations (impact-ranked; moat-safe)
56
+ 1. [HIGHEST, S-M, zero moat cost] Make the trust layer LEGIBLE + PROVABLE in one
57
+ screen: a one-sentence "why you can trust this" + `loki verify --explain` that
58
+ prints exactly which gates ran, their evidence, freshness, pass/fail. Loki has
59
+ MORE verification than zeroshot but COMMUNICATES/PROVES it worse. This
60
+ STRENGTHENS the moat by making it demonstrable.
61
+ 2. [M, moat REINFORCEMENT] Evidence STALENESS + tool-neutral handoff contract:
62
+ timestamp gate evidence, invalidate on state change, fail closed when stale /
63
+ older than the ready-marker / lacks usable evidence.
64
+ 3. [M, careful] Complexity-proportional verification: wire detect_complexity() to
65
+ scale the gate/council battery like zeroshot's 0/1/2/5 -- but ONLY ADD
66
+ validators for hard tasks, NEVER drop below a hard floor for anything
67
+ shippable. Cost/speed win with the floor as the guard.
68
+ 4. [M, no moat cost] Per-run isolation dial incl. Docker (match none/worktree/docker).
69
+ 5. [S, moat reinforcement] Scope honesty: when "done" is undescribable, say so +
70
+ degrade to inconclusive (never fabricate). Make it first-class + visible.
71
+ 6. [L, nice-to-have] A real terminal cockpit / strong TUI status view.
72
+ 7. [M] Broaden issue backends (GitLab/Jira/Azure) for team parity.
73
+
74
+ ## Single most important move + the one thing NOT to copy
75
+ - DO: make the trust layer provable to a skeptic in 60 seconds (recs 1+2). Loki
76
+ likely has more verification than zeroshot but demonstrates it worse; in a
77
+ market where buyers are skeptical, the tool that PROVES trust fastest wins.
78
+ - DO NOT COPY: Ralph's "operator supplies verification / senior babysits / ~90%
79
+ then human takes over." It is simpler + viral but the OPPOSITE of Loki's thesis.
80
+ Pushing verification back onto the user deletes the moat to chase a crowd that
81
+ was never Loki's.
@@ -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:** v7.121.5
5
+ **Version:** v7.121.6
6
6
 
7
7
  ---
8
8
 
@@ -396,7 +396,7 @@ provider works inside the container. Provide auth with your Anthropic API key:
396
396
  # Run Loki Mode in Docker (Claude provider, API-key auth)
397
397
  docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
398
398
  -v $(pwd):/workspace -w /workspace \
399
- asklokesh/loki-mode:7.121.5 start ./my-spec.md
399
+ asklokesh/loki-mode:7.121.6 start ./my-spec.md
400
400
  ```
401
401
 
402
402
  ##### docker compose + .env (no host install)
@@ -0,0 +1,165 @@
1
+ # RARV-C Efficiency Change Map (apply-and-measure, from lever investigation)
2
+
3
+ Both checks resolve cleanly:
4
+
5
+ **Check 1 (env propagation): CONFIRMED SAFE.** `_base.py:113` does `full_env = dict(os.environ)` then passes it as `env=full_env` to subprocess. The loki adapter (`loki.py:120`) uses `run_env`. So env-prefixing the bench invocation propagates the knob into the loki subprocess, where completion-council.sh:84 reads it at source time. Every `KNOB=x bench run` command in the plan is a real measurement, not a no-op.
6
+
7
+ **Check 2 (iteration counts): CONFIRMED AVAILABLE.** `iterations` is a canonical per-trial field (`loki.py:35-77` counts `iteration_complete` events; `_base.py:34,92` records it in the result row). So the moment the baseline lands, per-spec iteration counts are readable directly from the result JSON, which is exactly the discriminator the advisor flagged.
8
+
9
+ The advisor's arithmetic is decisive: 150s / 14k tokens ≈ 1 iteration, so simple-1 almost certainly already stops at iter ~1 via the fast path. The council-knob interval sweep must be pointed at the highest-iteration spec, not the trivial baseline. Here is the final synthesis.
10
+
11
+ ---
12
+
13
+ # RARV-C EFFICIENCY ARC: ORDERED APPLY-AND-MEASURE CHANGE MAP
14
+
15
+ ## Gate rule (applies to every change below)
16
+ Ships iff it moves >=1 of {iterations, $/build, wall-clock} BEYOND the ~25% noise band AND does not regress verified-pass-rate. Baseline: 5 specs x 3 trials, running now.
17
+
18
+ **Measurement primitive (all changes):**
19
+ `KNOB=val bash benchmarks/bench/run.sh run <spec> --trials 3 --emit-proof` (env-prefix propagates via `_base.py:113` `dict(os.environ)` -> loki subprocess). Read `iterations`, `cost`, `duration_s` per trial from the result JSON; pass = grader `exit==0` (`runner.py:210-254`).
20
+
21
+ **Baseline arithmetic that reshapes the whole plan:** 2.5min ≈ 150s and ~14k tokens ≈ ONE iteration (~130s/~10k each per the other two investigations). So the trivial baseline is almost certainly **already stopping at iter ~1 via the explicit-claim fast path** (`completion-council.sh:3519-3521`) - the exact case the council investigation says needs NO change. The council-knob headroom lives in high-iteration specs (`multifail-1-two-modules`, `tokenheavy-1-crm`), not `simple-1`.
22
+
23
+ ---
24
+
25
+ ## DO THIS FIRST (the moment the baseline lands)
26
+
27
+ **READ per-spec iteration counts from the baseline result JSON** before touching anything. This single read decides whether change #1 (council interval) can ship at all.
28
+
29
+ Then, change #1 is the first thing to **measure** (zero code, pure env var, cannot regress pass-rate - it changes WHEN not WHETHER the council approves):
30
+
31
+ **One-line command:**
32
+ ```
33
+ LOKI_COUNCIL_CHECK_INTERVAL=2 bash benchmarks/bench/run.sh run multifail-1-two-modules --trials 3
34
+ ```
35
+ (Point at whichever spec the baseline shows grinding *past its min-iter floor with no claim*. If NO spec grinds past floor, change #1 is a no-op and does not ship - see #1 below.)
36
+
37
+ ---
38
+
39
+ ## CHANGE TABLE (buckets a -> c -> b)
40
+
41
+ ### BUCKET (a) - constants/gates, no prompt text, no parity blast radius
42
+
43
+ #### #1. Council check-interval sweep (simple tier) [SHIP FIRST if warranted]
44
+ | Field | Value |
45
+ |---|---|
46
+ | Anchor | `completion-council.sh:84` (`COUNCIL_CHECK_INTERVAL=${LOKI_COUNCIL_CHECK_INTERVAL:-5}`); modulo gate `:3523` |
47
+ | Current | 5 |
48
+ | Proposed | 2 or 3 for simple tier only; keep 5 for standard/complex |
49
+ | Bucket | (a) |
50
+ | Metric | wall-clock + iterations, ONLY on no-claim/no-test-suite specs that grind to the interval boundary |
51
+ | Measure | `LOKI_COUNCIL_CHECK_INTERVAL=2 bash benchmarks/bench/run.sh run <highest-iter-spec> --trials 3`; pass = APPROVE verdict unchanged vs baseline, wall-clock down past noise |
52
+ | Effort | Trivial (1 env default) |
53
+ | Risk | Low. Do NOT go to 1 globally (council convenes every iter -> cost rises on genuine multi-iter builds). |
54
+ | **NO-OP GUARD** | If baseline shows every spec stops at iter ~1 (fast path), this moves nothing and FAILS the gate on trivial specs. **Ships only if a spec is empirically grinding past its floor without a claim.** |
55
+
56
+ #### #2. Verify explicit fast-path fires at iter 1 (validation run, not a change)
57
+ | Field | Value |
58
+ |---|---|
59
+ | Anchor | claim detection `completion-council.sh:3601-3605`; bypass `:3519-3521`; runner peek `run.sh:18309-18314` |
60
+ | Current | On (structural) |
61
+ | Proposed | No change - run matrix row C to prove it |
62
+ | Measure | `bash benchmarks/bench/run.sh run simple-1-contact-form --trials 3` with `COMPLETION_REQUESTED` touched at end of iter 1; expect stop at iter 1. If it does NOT, that is a **real claim-wiring bug**, not a knob. |
63
+ | Effort | Trivial | Risk | None (read-only validation) |
64
+
65
+ ### BUCKET (c) - need off-worktree / bench validation (parity or regression guard)
66
+
67
+ #### #3. Complexity -> tier routing (`auto` sentinel)
68
+ | Field | Value |
69
+ |---|---|
70
+ | Anchors | `run.sh:742` (`LOKI_SESSION_MODEL:-sonnet` -> `:-auto`); `run.sh:16932-16943` (case block, add `auto` arm); `_loki_session_pin_opus=1` reuse `run.sh:16953`; parity: estimator `autonomy/loki:15860-15870`, dashboard `server.py:2841,3059` |
71
+ | Current | Session pinned to `sonnet` for whole run; tier NOT complexity-aware |
72
+ | Proposed | `auto` arm: simple->fast+**haiku-enable**, complex->planning+`_loki_session_pin_opus=1`, standard->development. Propagate resolved tier via `.loki/state/session-tier` file for the two parity readers (they lack `DETECTED_COMPLEXITY`). |
73
+ | Bucket | **(c)** - conflicts with task framing (task calls tier-routing a leading "(a)" candidate; its own investigation classified it **(c)** on evidence: 3 parity readers + hard-1 bench guard + gated opus/haiku dispatch). Go with the evidence. |
74
+ | Metric | $/build + tokens (simple drops via haiku); verified-pass-rate must hold (hard-1) |
75
+ | Measure | Bench before/after with auto on: `hard-1-order-api` stays `exit==0` at planning tier; `simple-1`/`simple-2` cost drops AND stays green. If cheap routing drops hard-1 below pass, classifier thresholds (`detect_complexity` 2574-2591) are wrong. |
76
+ | Effort | Medium (~15 lines run.sh + state-file read in 2 ports + parity allowlist for `auto`) |
77
+ | Risk | Med. Silent quality regression if a hard build routes cheap. Guarded by hard-1 held-out acceptance. |
78
+ | **LANDMINES** | L2: `simple->fast` alone == sonnet==sonnet, **zero savings** without `LOKI_ALLOW_HAIKU=true` - the haiku-enable is the load-bearing half. L3: `CURRENT_TIER=planning` dispatches sonnet post-v7.104; must reuse `_loki_session_pin_opus=1` for real opus. |
79
+
80
+ #### #4. Self-heal from run logs (route app.log error signature into prompt)
81
+ | Field | Value |
82
+ |---|---|
83
+ | Anchors | S1 new helper `app-runner.sh` (~15 lines); S2 call sites `app-runner.sh:1756,1823` + `_loki_write_last_error` `run.sh:1103`; S3 injection edit `run.sh:14941-14942` (the `APP_CRASHED` heredoc line - **verified exact**) |
84
+ | Current | Watchdog restarts blindly; prompt gets crash *count* + "check app.log yourself"; `LAST_ERROR.json` is write-only (never read by `build_prompt`) |
85
+ | Proposed | S1: deterministic `tail -60 app.log` + grep first stack frame (Traceback/Error:/panic:/EADDRINUSE/MODULE_NOT_FOUND). S2: persist as `error_class=app_runtime_error`. S3: append signature + targeted-fix instruction to the injection. No new subsystem; reuses 2 existing mechanisms. |
86
+ | Bucket | (c) - orchestration change, provider-agnostic, needs bench validation on crashing specs |
87
+ | Metric | **iterations-to-green / verified-pass-rate on CRASHING specs** (NOT trivial cost - does nothing on the non-crashing baseline; will look like a gate fail if measured on simple-1) |
88
+ | Measure | Unit-test S1 against fixture `app.log` with a Python traceback (asserts signature) and one without (asserts empty, no fabrication). Then bench on `multifail-1-two-modules` (crashes): expect faster convergence / higher pass-rate. |
89
+ | Effort | Small (1 helper + 2 call sites + 1 edit) |
90
+ | Risk | Low. No-fake-green by construction: only routes info into the prompt; fix still flows through health-check + council + 8 gates. Honest-degrade: no signature -> today's behavior. |
91
+
92
+ #### #5. MCP/tool-surface scoping for simple builds (prompt-size Lever A)
93
+ | Field | Value |
94
+ |---|---|
95
+ | Anchors | Provider invocation / MCP mount logic (NOT `build_prompt`); lsp-proxy mount + `mcp/server.py` ~34-tool surface |
96
+ | Current | Full MCP surface (loki-mode ~34 tools + lsp-proxy + Claude built-ins) mounted every build; multiple-k of fixed token floor |
97
+ | Proposed | Gate lsp-proxy mount off when no language server helps; reduced MCP toolset for simple-complexity builds |
98
+ | Bucket | (c) - NOT the low-effort/no-regression "(a)" the task framing implies. Same "dropped a tool the build needed -> regression" risk class as tier-routing; mount-time complexity detection is real work. The prompt-size investigation's "do first" is scoped *within prompt-size*, not the whole arc. |
99
+ | Metric | input tokens/build (biggest single token win, no byte-lock unlock) |
100
+ | Measure | Bench simple-1/simple-2 token delta with reduced surface; hard-1 must stay green (needs its tools). |
101
+ | Effort | Medium (mount gating + complexity signal at invocation) |
102
+ | Risk | Med - underscoping breaks a build that needed a dropped tool. |
103
+
104
+ #### #6. PreToolUse content validation on Write/Edit (Bucket-2 gap, Claude-only)
105
+ | Field | Value |
106
+ |---|---|
107
+ | Anchor | `.claude/settings.json` PreToolUse matcher (mirrors `validate-bash.sh`) |
108
+ | Current | PreToolUse hook exists for Bash command strings only; no content validation on file writes |
109
+ | Proposed | Add `Write|Edit` matcher validating written content (secret patterns, `node --check` syntax) |
110
+ | Bucket | (c) - native hook is right mechanism but **Claude-provider-only** defense-in-depth; real cross-provider containment stays the sandbox (`LOKI_SANDBOX_MODE`) |
111
+ | Metric | Not an efficiency lever - safety. **Does not move any gate metric.** Include only as opportunistic safety, not scored against the efficiency gate. |
112
+ | Effort | Small | Risk | Low (advisory) |
113
+
114
+ ### BUCKET (b) - founder-gated (build_prompt byte-locked + 60-fixture SHA parity)
115
+
116
+ #### #7. Enable prompt caching / activate `[CACHE_BREAKPOINT]` (prompt-size Lever B)
117
+ | Field | Value |
118
+ |---|---|
119
+ | Anchor | `[CACHE_BREAKPOINT]` marker `run.sh:15119` (inert today); no `cache_control` set |
120
+ | Current | Static ~1.6k prefix + tool/system floor re-billed full price every iteration (each iter is a distinct `claude -p` process) |
121
+ | Proposed | Wire real caching for the static prefix |
122
+ | Bucket | (b)-adjacent, and **CONTINGENT** - benefit is 100% caching, hinges on whether Claude Code CLI folds the prefix into a cached breakpoint reusable across per-iteration processes within the 5-min TTL. **Verify against the CLI before committing.** |
123
+ | Metric | $/build on multi-iteration runs (zero token reduction; converts fixed prefix to ~0.1x on cache reads) |
124
+ | Measure | Compare cost on a multi-iteration spec (tokenheavy-1) before/after; caching shows on iter-2+. |
125
+ | Effort | Med (contingent on CLI mechanics) | Risk | Med - may be a no-op if CLI doesn't wire cache_control for the prefix. Flag "verify before committing," not a committed change. |
126
+
127
+ #### #8. Trim static boilerplate in `<loki_system>` prefix (prompt-size Lever C)
128
+ | Field | Value |
129
+ |---|---|
130
+ | Anchors | compose (~290t) + LSP (~286t) + USAGE (~209t) + DOC_SCOPE (~143t) strings in `run.sh` + `build_prompt.ts` |
131
+ | Current | All emitted every build |
132
+ | Proposed | Load-on-demand / shorten (~700-900 tokens recoverable) |
133
+ | Bucket | (b) - byte-locked; each string `MUST stay byte-identical` under 60-fixture SHA parity (`loki-ts/tests/parity/build_prompt.test.ts`). Needs founder unlock + fixture regen + dual-route parity re-verify. |
134
+ | Metric | input tokens (~7-9% of 10k) |
135
+ | Effort | Small code, EXPENSIVE unlock | Risk | Low behavior, high process cost. |
136
+
137
+ ---
138
+
139
+ ## NOT WORTH DOING (ponytail: no no-ops)
140
+
141
+ | Item | Why it's a no-op / not worth it |
142
+ |---|---|
143
+ | `_council_effective_min_iter` simple->1 | **ALREADY SHIPPED** (SaaS #122, verified `completion-council.sh:118-130`). Nothing to do. |
144
+ | `simple->fast` tier route WITHOUT haiku-enable | sonnet==sonnet (L2, `claude.sh:60-62`). Zero savings. The haiku-enable is the only load-bearing half. |
145
+ | Lowering `COUNCIL_STAGNATION_LIMIT` (5->3) for speed | Fires circuit breaker sooner -> force-stop, which is NOT verified-complete (`run.sh:18320-18326`). Pass-rate regression dressed as speedup. Leave at 5. |
146
+ | Council interval on the trivial baseline | If baseline stops at iter ~1 (very likely per arithmetic), lowering the interval moves nothing on simple-1 and fails the gate. Only ships against a spec grinding past floor. |
147
+ | Prompt-size Lever D (move RARV to `--append-system-prompt`) standalone | Saves ZERO without Lever B's caching, and DOUBLE-BILLS if the byte-locked removal half doesn't ship simultaneously. Bundle-with-#7 or drop. Not a standalone change. |
148
+ | Self-heal S5 (dedicated read-only investigate sub-agent) | YAGNI. S3 already gives the RARV agent the error text; RARV's own VERIFY is the remediate half. Add only if S1-S4 measurably under-fix. |
149
+
150
+ ---
151
+
152
+ ## ORDER SUMMARY
153
+ 1. **Read baseline iteration counts per spec** (decides #1 viability).
154
+ 2. **#1 council interval** - measure first, ship iff a spec grinds past floor (bucket a, zero code).
155
+ 3. **#2 fast-path validation** - confirms claimed builds stop at iter 1 (bucket a, read-only).
156
+ 4. **#3 tier routing** (bucket c) - biggest $/build lever; needs parity + hard-1 guard, off-worktree.
157
+ 5. **#4 self-heal** (bucket c) - pass-rate lever on crashing specs; measure on multifail-1, not simple-1.
158
+ 6. **#5 MCP scoping** (bucket c) - biggest token win, but real regression risk; not the "first" the framing suggests.
159
+ 7. **#6 PreToolUse content validation** (bucket c, safety, unscored).
160
+ 8. **#7 caching** (bucket b, contingent - verify CLI before committing).
161
+ 9. **#8 prefix trim** (bucket b, founder-gated - small win, expensive unlock; do LAST, don't spend the unlock for ~300 tokens while ~5k sits in tool schemas).
162
+
163
+ **Two framing conflicts surfaced (evidence wins):** (a) the task calls tier-routing and MCP-scoping leading "(a)" candidates; their own investigations classify both **(c)** on parity/regression-guard evidence. (b) The council-knob is genuinely the first thing to *measure* (pure env var, no regression path) but is a no-op on the trivial baseline - its real target is high-iteration specs.
164
+
165
+ Read-only synthesis; no edits, no processes, no temp files. Clean.
@@ -0,0 +1,465 @@
1
+ # RARV-C Loop-Efficiency Upgrade Plan (ultracode phase)
2
+
3
+ Architect: synthesis of the six cookbook pattern sets against the current
4
+ Loki RARV-C loop. This is a PLAN, not code. Every proposed change carries a
5
+ constraint bucket and a bench-gate. No benchmark numbers are asserted here --
6
+ the harness (Deliverable #1) produces them.
7
+
8
+ Grounded against v7.121.5 source. Line numbers drift; re-verify with grep
9
+ before editing.
10
+
11
+ ---
12
+
13
+ ## 0. The one-line thesis
14
+
15
+ The competitors' edge is INFRASTRUCTURE, not loop rigor. Our proof /
16
+ never-fake-green RARV-C is the moat. So this plan optimizes the loop's
17
+ EFFICIENCY (cost, wall-clock, iterations-to-completion) and NEVER trades away
18
+ verification rigor. The lever that proves it is a bench that measures the
19
+ moat's OUTPUT (verified pass rate, from a deterministic grader) independently
20
+ of the loop's own self-assessment.
21
+
22
+ ---
23
+
24
+ ## 1. The gap split
25
+
26
+ ### 1a. Already-scoped INFRASTRUCTURE (NOT this plan's target)
27
+
28
+ Yesterday's competitor research (reuse, do not re-run) found the
29
+ Replit/Emergent/Bolt advantage is mostly infrastructure: per-build sandbox
30
+ isolation, snapshot/checkpoint, warm pools, fast provisioning. That work is
31
+ already scoped as #2b / #8b / #10 in
32
+ `autonomi-saas/docs/NEXT-AFTER-2026-07-08.md`.
33
+
34
+ The entire `sandboxes-production` cookbook maps 1:1 onto that scoped k8s work.
35
+ Treat it as a reference implementation, do NOT re-derive it, and do NOT rank
36
+ it here:
37
+
38
+ | Cookbook technique | Already-scoped item |
39
+ |---|---|
40
+ | Pod-per-session = blast radius | Per-build isolation (#2b) |
41
+ | Per-session volume + SessionStore mirror (local-first, async, non-fatal) | Snapshot/resume, durability C->A (#10) |
42
+ | Lease + heartbeat + reclaim-on-lapse | dead-run-holds-worker (#14) |
43
+ | Idempotent get-or-create keyed on session id | (implicit in per-build spawn) |
44
+ | Standby warm pool, egress NetworkPolicy, gateway auth, OTel | k8s tier-3 infra |
45
+
46
+ Their loops are NOT more rigorous (Replit ships zero tests). We are ahead on
47
+ verification. Do not re-architect that lead.
48
+
49
+ Three `sandboxes-production` techniques are net-new for Loki but are
50
+ SAFETY/HEALING, not cost/speed/iterations, so they are explicitly OUT of this
51
+ plan's ranked list (name them, do not smuggle them in):
52
+ - Two-phase investigate(read-only) -> remediate(write) split for
53
+ self-heal-from-logs.
54
+ - Narrow-scoped write tools + `PreToolUse` content-validation hooks
55
+ (block-and-let-agent-adapt).
56
+ - archive-vs-delete + optimistic-concurrency version check on state updates.
57
+
58
+ ### 1b. LOOP EFFICIENCY (THIS plan's target)
59
+
60
+ Cost, wall-clock, iterations-to-completion, at constant verified-pass-rate.
61
+ The `managed-agents`, `agent-patterns`, and `evals-observability` cookbooks
62
+ target this. Techniques: evaluator-optimizer to converge in fewer passes,
63
+ outcome-grader discipline to stop early when genuinely done, cheaper model
64
+ routing, root-cause-clustered parallel fix-loops, plan-big-execute-small
65
+ coordinator economics.
66
+
67
+ **Honest caveat up front (ponytail rung 2 -- reuse what exists):** the biggest
68
+ iterations-win is LARGELY ALREADY SHIPPED. The framework already has
69
+ explicit-completion-claim, tunable `COUNCIL_CHECK_INTERVAL`, the tier-aware
70
+ `_council_effective_min_iter` floor (v7.105), and the
71
+ `COUNCIL_STAGNATION_LIMIT` circuit breaker. The cookbook's outcome-grader and
72
+ evaluator-optimizer patterns ARE, structurally, the completion council plus
73
+ findings-injection we already run. So most items below are "TUNE an existing
74
+ knob and let the bench prove the setting," NOT "build a new grader." Proposing
75
+ to build what exists would itself be a fabrication.
76
+
77
+ ---
78
+
79
+ ## 2. Deliverable #1: the metric harness (BUILD THIS FIRST)
80
+
81
+ We cannot claim "least cost / fewer iterations" without measured before/after.
82
+ Founder rule: measurable before/after every commit; an unmeasured claim is a
83
+ fabrication under anti-fake-green. So the harness ships before any loop change.
84
+
85
+ ### 2a. Reuse, do not rebuild (the lazy path is the correct path)
86
+
87
+ Verified against source: the harness is ~95% already built.
88
+
89
+ - `benchmarks/bench/` already has the frozen contract (`bench_schema.py`,
90
+ `SCHEMA_VERSION = "1.0"`), a runner (`runner.py`), a deterministic grader
91
+ (`success = exit==0`, held-out `acceptance.overlay` copied in AFTER the
92
+ agent finishes), a loki adapter (`adapters/loki.py`), a price table
93
+ (`prices.json`), and `loki bench` + `loki bench verify`.
94
+ - `bench_schema.py` ALREADY carries the fields we need: `iterations`
95
+ (`setdefault("iterations", 0)`), `duration_s`, `cost_usd`, `tokens_in/out`,
96
+ `cache_read_tokens`, `success` (grader-set).
97
+ - `adapters/loki.py` ALREADY reads iteration count from `.loki` state
98
+ (`_read_iteration_count`, session.json/autonomy-state.json) and captures
99
+ `duration_s`.
100
+ - The credibility invariant is ENFORCED in code: `validate_adapter_output()`
101
+ REJECTS any adapter dict carrying `success/quality/passed/score/verdict`.
102
+ Only the grader sets outcome. This is exactly the "grade the artifact, never
103
+ the loop's self-assessment" rule -- already a code invariant, not a
104
+ convention.
105
+ - `benchmarks/speed-benchmark.sh` ALREADY parses the target's
106
+ `.loki/events.jsonl` for `act_iterations` and `wall_clock_s` from an
107
+ ISOLATED source copy (never the worktree).
108
+
109
+ So Deliverable #1 is NOT a build. It is: lock a corpus, reconcile one metric
110
+ source, baseline, and wire the gate.
111
+
112
+ ### 2b. The four target metrics -> where each comes from
113
+
114
+ | Metric | Source (already exists) |
115
+ |---|---|
116
+ | verified-pass-rate | grader `success = exit==0` on held-out acceptance -> `success_rate` = n_success/n_trials. NEVER council/`completion_claimed`. |
117
+ | $/build | `cost_usd` per task (adapter tokens x frozen `prices.json`); `cost_usd_per_solved` aggregate already in schema. |
118
+ | iterations-to-completion | `iterations` field, populated by `adapters/loki.py` `_read_iteration_count`. |
119
+ | wall-clock/build | `duration_s` (adapter wall-clock around the subprocess). |
120
+
121
+ ### 2c. The genuine delta (small, concrete)
122
+
123
+ 1. **Reconcile the iterations source (harden, do not duplicate).**
124
+ `adapters/loki.py` reads `iteration` from `session.json`;
125
+ `speed-benchmark.sh` parses `events.jsonl`. These CAN disagree. Pick ONE
126
+ canonical source so both harnesses agree -- prefer the `events.jsonl`
127
+ `iteration_complete` count (it is the real per-session timeline; session
128
+ state can be mid-write). Make `adapters/loki.py` read events.jsonl with
129
+ session.json as fallback. One parser, copied from
130
+ `speed-benchmark.sh` lines ~119-179. Bucket (a).
131
+ 2. **Confirm wall-clock coverage.** `duration_s` already exists; verify it is
132
+ the full subprocess wall-clock, not per-iteration. If it is, no new field
133
+ is needed and we avoid touching the frozen schema at all. If a distinct
134
+ `wall_clock_s` is truly required, it is an ADDITIVE optional field
135
+ (`setdefault`), but the schema header says "do not change without updating
136
+ SCHEMA_VERSION and every slice" -- so treat any field add as a
137
+ SCHEMA_VERSION bump + all-slice update. PREFER reusing `duration_s`.
138
+ 3. **Lock the corpus.** 5-15 fixed specs under `benchmarks/bench/tasks/` (or
139
+ a new `benchmarks/corpus/`), each with machine-checkable held-out
140
+ acceptance (exit code / http status / file exists / regex). Dev on 2, run
141
+ on all. `task_hash` (spec + acceptance + model, already computed) is the
142
+ reproducibility anchor.
143
+ 4. **Ship the 2-spec smoke sanity check:** one spec that MUST pass, one
144
+ deliberately-underspecified that MUST fail; assert
145
+ `verified_pass == [True, False]`. If the grader cannot tell those apart it
146
+ measures nothing. This is the single runnable check the harness leaves
147
+ behind.
148
+
149
+ ### 2d. Reproducibility contract (frozen across every before/after)
150
+
151
+ - Corpus, grader (acceptance harness), and `prices.json` are FROZEN across a
152
+ before/after pair. Changing any of them destroys comparability exactly like
153
+ swapping a grader model would. Adding output fields is safe (`task_hash`
154
+ covers spec+acceptance+model); changing the corpus is not.
155
+ - Every results file persists `loki_version` + `task_hash` + price-table hash
156
+ so any past number is reproducible and its config travels with it
157
+ (`benchmarks/results/<version>-<stamp>.json`, already the pattern).
158
+ - Baseline = N real off-worktree builds = real dollars and hours. Run from an
159
+ isolated source copy with cwd AND `LOKI_TARGET_DIR` pinned to scratch, per
160
+ the never-run-from-worktree rule. Per-build try/except + hard timeout: a
161
+ crashed/hung build scores 0 (fail), never aborts the batch. Retry a build
162
+ only on infra error (network/rate-limit), NEVER on a real failure.
163
+
164
+ ### 2e. The gate rule (operationalizes anchors 1 + 3)
165
+
166
+ > A loop-efficiency change SHIPS iff it improves at least one of
167
+ > {iterations-to-completion, $/build, wall-clock} BEYOND THE BASELINE'S NOISE
168
+ > BAND AND does not regress verified-pass-rate, measured on the frozen corpus
169
+ > vs the committed baseline.
170
+
171
+ No change ships unless the bench moves the right way. That one rule is anchor
172
+ 1 (optimize efficiency, never trade the proof-moat) and anchor 3
173
+ (bench-gated, no unmeasured claims) made mechanical.
174
+
175
+ ### 2e-HARDENING (advisor 2026-07-08 - blocking; decided BEFORE any results)
176
+
177
+ Three holes that make an unhardened bench produce fake-green "wins":
178
+
179
+ 1. **NOISE FLOOR (blocking).** Agentic builds are non-deterministic; iterations
180
+ /$/wall-clock vary run-to-run. "Improves the right direction" with no variance
181
+ threshold ships random noise as a win ~half the time. RULE: the baseline
182
+ reports SPREAD (std dev or min-max across trials), not just means. A change
183
+ ships only if its metric moves BEYOND the baseline's noise band (mean delta >
184
+ baseline trial std, or non-overlapping min-max). If an effect is smaller than
185
+ trial variance at N trials, either raise trials or report "no measurable
186
+ effect" and DO NOT ship. The noise bar is decided now, not rationalized after.
187
+ 2. **RECONCILE-METRICS-FIRST (blocking).** Fix the iterations source (2c.1 ->
188
+ events.jsonl canonical) BEFORE baselining. Baselining on an ambiguous source
189
+ (session.json vs events.jsonl disagree) corrupts every iterations before/after.
190
+ This is a PREREQUISITE step, not parallel.
191
+ 3. **CORPUS FROM DISCRIMINATORS (expensive to reverse - frozen at baseline).**
192
+ Do NOT pick "5-15 representative specs." Derive the corpus BACKWARD from what
193
+ each ranked change must discriminate:
194
+ - Rank 2 (tier routing): MUST include HARD specs that must stay on the strong
195
+ model without pass-rate regression, else the anchor-1 guard (cheap tier must
196
+ not regress hard builds) is untestable and you ship a silent regression.
197
+ - Rank 3 (parallel fix-loops): MUST include specs that produce MULTI-CLUSTER
198
+ failures.
199
+ - Rank 5 (distilled returns): MUST include TOKEN-HEAVY specs.
200
+ Mix: simple + hard + multi-failure + token-heavy. Frozen once baselined (2d).
201
+
202
+ ### 2f. Cost envelope + honesty pre-commit
203
+ - Envelope: ~5-10 specs x 3 trials x (1 baseline + ~7 ranked changes) ~= 120-240
204
+ real builds = real dollars + hours. START SMALL: prove the full pipeline
205
+ (baseline->one change->measure->gate) on a 3-spec corpus FIRST to validate the
206
+ machinery mechanically, THEN build the real discriminator-derived corpus and
207
+ baseline. Grow corpus only if variance demands it.
208
+ - HONESTY PRE-COMMIT: the plan already says most iteration wins are shipped;
209
+ expect single-digit-% to maybe-2x from tuning, NOT 100x. Pre-commit to reporting
210
+ the real number even if unimpressive, and to stating plainly: "the loop is
211
+ near-optimal; the real 100x is the INFRA work (already scoped #2b/#10), not
212
+ here." Do not let the measurement spend create pressure to dress up a small
213
+ delta - that would be fake-green.
214
+
215
+ ---
216
+
217
+ ## 3. Ranked upgrade list
218
+
219
+ Ranked by (impact / effort), bucket-(a) first. Every item names its cookbook
220
+ pattern, expected effect, bucket, bench validation, and rough effort.
221
+
222
+ Bucket key:
223
+ - **(a)** ORCHESTRATION-LEVEL -- changeable now (run.sh model routing, council
224
+ gating, iteration control constants, sub-invocation that does NOT feed the
225
+ next prompt). No `build_prompt()` change.
226
+ - **(b)** NEEDS FOUNDER AUTHORIZATION -- requires unlocking `build_prompt()`
227
+ (60-fixture byte-mirror parity lock).
228
+ - **(c)** NEEDS OFF-WORKTREE REAL-BUILD VALIDATION -- cannot be proven without
229
+ real builds that must NOT run from the worktree.
230
+
231
+ Discriminator for (a) vs (b): *does the change alter `build_prompt()` output
232
+ text?* If it changes what text enters the next prompt (findings, rubric,
233
+ feedback), it is (b). If it only changes WHEN the council convenes, WHICH model
234
+ runs, or a sub-invocation whose output is not concatenated into the next
235
+ prompt, it is (a). Prompt-touching patterns are SPLIT into their (a) and (b)
236
+ halves below -- do not file a whole pattern under one bucket.
237
+
238
+ ---
239
+
240
+ ### Rank 1 -- Tune the completion-council convergence knobs
241
+
242
+ - **Pattern:** outcome-grader "stop early when genuinely done" +
243
+ evaluator-optimizer "PASS gate stops the loop the moment criteria are met"
244
+ (`managed-agents`, `agent-patterns`). We already HAVE the grader (the
245
+ council). This item TUNES it, does not build it.
246
+ - **Concrete:** sweep `COUNCIL_CHECK_INTERVAL` (default 5,
247
+ `completion-council.sh:84`), `_council_effective_min_iter`
248
+ (`:3555`), and `COUNCIL_STAGNATION_LIMIT` (default 5, `:132`) on the corpus;
249
+ pick the settings that cut iterations-to-completion without regressing
250
+ verified-pass-rate. Also verify the explicit-completion-claim fast path
251
+ (`:3601`) fires on the corpus (the v7.105 lever: a done-at-1 build should
252
+ stop near iter 1, not grind to the next interval).
253
+ - **Effect:** fewer wasted idle iterations -> lower $/build + wall-clock.
254
+ Largest iterations lever that is NOT already maxed.
255
+ - **Bucket:** (a). Constants + gating only; no prompt text.
256
+ - **Bench validation:** iterations + $/build must drop, verified-pass-rate
257
+ flat. If pass-rate drops, the interval is too aggressive -- revert.
258
+ - **Effort:** LOW (constant sweep + bench runs). Cost is the real-build $.
259
+
260
+ ### Rank 2 -- Model-tier routing by task complexity
261
+
262
+ - **Pattern:** Routing (`agent-patterns`) -- a cheap classifier routes easy
263
+ inputs to the cheap model, hard ones to the strong model; plan-big-
264
+ execute-small coordinator economics (`managed-agents`).
265
+ - **Concrete:** `LOKI_SESSION_MODEL` is the single largest cost lever
266
+ (`run.sh:16932`) and today it is one pinned tier for the whole run. Wire
267
+ `detect_complexity()` (`run.sh:1338`) -> session tier so simple specs pin
268
+ cheaper (haiku/sonnet) and complex specs pin higher, instead of a flat
269
+ default. Keep it a unified intelligent default (opt-out knob), never a
270
+ fragmented set of flags.
271
+ - **Effect:** direct $/build reduction on the simple-spec majority; strong
272
+ model reserved for the hard tail. Dominant cost lever.
273
+ - **Bucket:** (a). Model selection, no prompt text.
274
+ - **Bench validation:** $/build drops on simple-spec corpus members,
275
+ verified-pass-rate flat across ALL members (guard: cheaper tier must not
276
+ regress pass on the hard ones -- that is the anchor-1 trap).
277
+ - **Effort:** LOW-MED. `detect_complexity` already exists; wire it to the tier
278
+ map and gate on the bench.
279
+
280
+ ### Rank 3 -- Root-cause-clustered parallel fix-loops
281
+
282
+ - **Pattern:** iterate-fix-failing-tests + "cluster before you parallelize"
283
+ (`managed-agents`); Parallelization for independent slices
284
+ (`agent-patterns`).
285
+ - **Concrete:** on a code-review/test BLOCK, bucket failures by root module
286
+ and fan out ONE fix-worker per INDEPENDENT cluster (worktree per cluster),
287
+ then re-run the WHOLE suite once at merge as the independent verify. Do NOT
288
+ fan out per-test -- failures share root causes, per-test workers duplicate
289
+ the same fix and conflict (the cookbook's own `test_mean` caveat).
290
+ - **Effect:** wall-clock collapse on multi-cluster failures (parallel vs
291
+ serial); fewer iterations via root-cause (not symptom) fixes.
292
+ - **Bucket:** (a) for the orchestration (fan-out + merge + whole-suite
293
+ re-verify happen in run.sh / fleet, no prompt-text change). (c) for
294
+ proving it -- parallel worktree fix-loops must be validated off-worktree on
295
+ real multi-failure builds.
296
+ - **Bench validation:** wall-clock drops on corpus members that produce
297
+ multi-cluster failures; verified-pass-rate flat (the merge whole-suite
298
+ re-run is the non-negotiable guard against over-fix/regression).
299
+ - **Effort:** MED. Clustering heuristic + worktree fan-out + merge verify.
300
+
301
+ ### Rank 4 -- Per-role tool-scoping in the SDLC fleet
302
+
303
+ - **Pattern:** coordinate-specialist-team "narrowest tool allowlist per role"
304
+ (`managed-agents`); tool descriptions drive behavior.
305
+ - **Concrete:** give each fleet role (architect, dev, SDET, reviewer) the
306
+ minimal allowed-tools list it needs (reviewer: read-only; researcher:
307
+ web+read only). Claude and Codex both support per-invocation tool
308
+ restriction -- provider-agnostic.
309
+ - **Effect:** fewer wrong-turn iterations (a reviewer cannot wander into
310
+ bash); smaller blast radius. Iterations lever, modest.
311
+ - **Bucket:** (a). Invocation tool lists, no prompt text.
312
+ - **Bench validation:** iterations flat-or-down, verified-pass-rate flat. This
313
+ one mostly de-risks; expect small bench movement. If the bench does not
314
+ move, ship only if it reduces wrong-turn incidents in the transcript
315
+ (secondary signal), else defer (ponytail: do not ship a no-op).
316
+ - **Effort:** LOW.
317
+
318
+ ### Rank 5 -- Structured distilled-return contract for workers (coordinator economics)
319
+
320
+ - **Pattern:** plan-big-execute-small "workers return DISTILLED summaries, not
321
+ raw material" + XML/JSON structured handoff (`managed-agents`,
322
+ `agent-patterns`).
323
+ - **Concrete:** enforce that fleet workers return a small structured payload
324
+ (JSON) up to the coordinator, never dump raw file/log/page content back up
325
+ the chain. Keeps the coordinator context small -> cheaper, sharper
326
+ synthesis. Gate the fan-out on a granularity heuristic (only shard genuinely
327
+ token-heavy INDEPENDENT slices; the cookbook warns over-sharding RAISES the
328
+ bill and narrow tasks do not pay).
329
+ - **Effect:** $/build reduction on token-heavy multi-worker builds; guards
330
+ against the degenerate "one frontier round-trip for nothing" case.
331
+ - **Bucket:** (a) for the worker return contract and fan-out granularity
332
+ gate (fleet orchestration). NOTE: if the distilled summaries are
333
+ concatenated into the NEXT `build_prompt()` iteration, that concatenation
334
+ path is (b) -- keep the contract change on the worker->coordinator hop, not
335
+ the coordinator->next-prompt hop, to stay in (a).
336
+ - **Bench validation:** $/build drops on token-heavy corpus members;
337
+ verified-pass-rate flat (guard: distillation must not summarize away
338
+ nuance the grader checks).
339
+ - **Effort:** MED.
340
+
341
+ ### Rank 6 -- Confidence-calibrated escalation lane (already partly shipped)
342
+
343
+ - **Pattern:** gate-human-in-the-loop decide/escalate calibration
344
+ (`managed-agents`).
345
+ - **Concrete:** the uncertainty-gated escalation is already default-on
346
+ (`run.sh:18236`). This item TUNES the confidence threshold so the confident
347
+ majority stays in the fast/cheap autonomous lane and only the genuinely
348
+ low-confidence + unsafe tail escalates/handoffs (never fake-greens, never
349
+ blocks-to-ask -- honors the no-human-in-loop runtime rule). Route the
350
+ low-confidence tail to a stronger model rather than a human where the action
351
+ is reversible.
352
+ - **Effect:** avoids MAX_ITERATIONS burn on stuck loops (caps wasted
353
+ iterations); reserves expensive lane for the tail.
354
+ - **Bucket:** (a). Threshold + routing, no prompt text.
355
+ - **Bench validation:** iterations drop on corpus members that currently
356
+ thrash toward the cap; verified-pass-rate flat.
357
+ - **Effort:** LOW.
358
+
359
+ ### Rank 7 -- Enriched findings-injection text (FOUNDER-GATED)
360
+
361
+ - **Pattern:** evaluator-optimizer "feed specific feedback + prior attempts
362
+ back to the generator" + outcome-grader rubric discipline
363
+ (`agent-patterns`, `managed-agents`). This is our highest-leverage
364
+ iterations lever AND the most likely to be byte-locked.
365
+ - **Concrete:** `LOKI_INJECT_FINDINGS` already injects structured per-finding
366
+ records into the next prompt (default-on). ENRICHING that injected TEXT
367
+ (better-targeted, rubric-shaped, one-bullet-per-failure format) would make
368
+ each retry more directed and converge in fewer passes. BUT the injected text
369
+ flows through `build_prompt()`, whose output is pinned by the 60-fixture
370
+ SHA-256 parity lock (`loki-ts/tests/parity/build_prompt.test.ts`,
371
+ `loki-ts/src/runner/build_prompt.ts`, gold under
372
+ `loki-ts/tests/fixtures/build_prompt/`).
373
+ - **Split (per anchor 2):**
374
+ - (a) part: tuning WHEN findings are injected / WHICH findings are selected
375
+ (selection logic upstream of the prompt) -- changeable now if it does not
376
+ alter the emitted text bytes.
377
+ - (b) part: changing the injected TEXT / format / rubric wording -- requires
378
+ founder authorization to unlock the byte-lock, then regenerate all 60
379
+ fixtures via `run-bash.sh` and keep bash<->TS parity 60/60.
380
+ - **Effect:** fewer iterations-to-completion (directed retries). Potentially
381
+ large, but gated.
382
+ - **Bucket:** (b) for the text change; (a) for the selection-logic half.
383
+ - **Bench validation:** iterations drop, verified-pass-rate flat-or-up. Prove
384
+ off-worktree (hermetic Bun integration test with stub judge, then real
385
+ builds).
386
+ - **Effort:** MED code + HIGH process (founder unlock + fixture regen +
387
+ full council + local-ci). Do NOT start the (b) half without authorization.
388
+
389
+ ---
390
+
391
+ ## 4. Sequencing for the ultracode phase
392
+
393
+ 1. **Deliverable #1 first: lock the harness + baseline.** Reconcile the
394
+ iterations source (2c.1), confirm wall-clock coverage (2c.2), lock the 5-15
395
+ spec corpus (2c.3), ship the 2-spec smoke check (2c.4), then run the
396
+ baseline: N real off-worktree builds -> committed
397
+ `benchmarks/results/<baseline>.json`. Nothing else ships until this exists.
398
+ 2. **Bucket-(a) wins, ranked, each bench-gated.** In order: Rank 1 (council
399
+ knob sweep) -> Rank 2 (complexity->tier routing) -> Rank 6 (escalation
400
+ threshold) -> Rank 4 (per-role tool scoping) -> Rank 3 orchestration half
401
+ -> Rank 5 worker-return contract. Each one: change, re-run corpus, apply
402
+ the gate rule (2e). If the bench does not move the right way, do not ship
403
+ it (ponytail: no no-ops).
404
+ 3. **Bucket-(c) validation for anything needing real parallel builds** (Rank 3
405
+ fix-loop fan-out): prove off-worktree on real multi-failure builds before
406
+ shipping.
407
+ 4. **Founder-gated items LAST.** Rank 7 (b) half only after: (i) bucket-(a)
408
+ wins are banked and measured, (ii) explicit founder authorization to unlock
409
+ `build_prompt()`, (iii) fixture regen + 60/60 parity + full 3-reviewer
410
+ council + local-ci green. Do the (a) selection-logic half of Rank 7 in
411
+ step 2 if it stands alone.
412
+ 5. **Every ship:** full gate is back (Wednesday 2026-07-08, the 1-week
413
+ relaxation has expired). Runtime/council changes = full 3-reviewer council
414
+ (2 Opus + 1 Sonnet, unanimous APPROVE, loop to 3/3) + `local-ci.sh` green +
415
+ watch all GH workflows. Prove RARV-C changes with hermetic Bun integration
416
+ tests (stub judge, `LOKI_OVERRIDE_REAL_JUDGE=0`, mkdtemp scratch, no token
417
+ cost) -- pattern already established in
418
+ `loki-ts/tests/integration/override_on_block.test.ts`.
419
+
420
+ ---
421
+
422
+ ## 5. Explicit "do NOT do" list
423
+
424
+ Tempting things that re-architect the moat, hit the byte-lock, or fabricate
425
+ numbers:
426
+
427
+ 1. **Do NOT replace the completion council with a single-LLM outcome-grader.**
428
+ That kills the 3-reviewer rigor moat -- the exact thing we are ahead on.
429
+ Lift the rubric DISCIPLINE (checkable criteria, evidence-earned pass,
430
+ one-bullet-per-failure feedback, same-gap non-convergence detection), NOT
431
+ the single-judge architecture.
432
+ 2. **Do NOT add an LLM-judge to the bench grader.** The grader is
433
+ deterministic (`success = exit==0` on held-out acceptance) and the
434
+ credibility invariant is enforced in code
435
+ (`validate_adapter_output` rejects any self-judged key). An LLM judge is a
436
+ second thing you must hold fixed and it breaks the invariant. Specs are
437
+ code -- acceptance is machine-checkable for free.
438
+ 3. **Do NOT trust `completion_claimed` / council APPROVE as the bench pass
439
+ signal.** That is grading the loop's self-assessment -- the fake-green
440
+ failure mode. Pass = independent deterministic acceptance only.
441
+ 4. **Do NOT touch `build_prompt()` output text without founder authorization.**
442
+ 60-fixture SHA-256 byte-mirror parity lock. Any text change = regenerate
443
+ gold + keep bash<->TS 60/60 or CI (`parity-drift`) fails. This gates
444
+ Rank 7's (b) half.
445
+ 5. **Do NOT change the corpus, grader, or price table across a before/after
446
+ pair.** Comparability dies; the number becomes a fabrication. Additive
447
+ output fields are safe; corpus churn is not.
448
+ 6. **Do NOT cite the cookbook's headline numbers as ours.** "~2.5x cheaper /
449
+ ~3x faster" (plan-big-execute-small) and "84-98% billed at worker rate" are
450
+ THEIR task on THEIR corpus. Our numbers come from our harness, later.
451
+ 7. **Do NOT over-shard plan-big-execute-small or fan fix-workers per-test.**
452
+ The cookbook's own caveats: over-sharding RAISES the bill (delegation floor
453
+ cost), narrow tasks do not pay, and per-test workers duplicate shared-root
454
+ fixes and conflict. Cluster by root cause first, then parallelize across
455
+ clusters.
456
+ 8. **Do NOT run a real engine build from the worktree to validate any of
457
+ this.** TARGET_DIR resolves onto the worktree and self-mutates it. Baseline
458
+ and all (c) validation run from an isolated source copy with cwd +
459
+ `LOKI_TARGET_DIR` pinned to scratch (the speed-benchmark.sh discipline).
460
+ 9. **Do NOT re-scope the sandboxes-production infra work here.** It is already
461
+ #2b/#8b/#10 in autonomi-saas. Reference the cookbook as an impl, do not
462
+ re-derive or re-rank it.
463
+ 10. **Do NOT ship a change that does not move the bench the right way.** The
464
+ gate rule (2e) is binding: improve >=1 of {iterations, $/build,
465
+ wall-clock} AND no verified-pass-rate regression, or it does not ship.
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var q8=Object.defineProperty;var J8=($)=>$;function V8($,Q){this[$]=J8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)q8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:V8.bind(Q,Z)})};var P=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var m1={};b(m1,{lokiDir:()=>j,homeLokiDir:()=>T$,findRepoRootForVersion:()=>$1,REPO_ROOT:()=>h});import{resolve as t,dirname as e$}from"path";import{fileURLToPath as W8}from"url";import{existsSync as N$}from"fs";import{homedir as H8}from"os";function G8(){let $=v1;for(let Q=0;Q<6;Q++){if(N$(t($,"VERSION"))&&N$(t($,"autonomy/run.sh")))return $;let Z=e$($);if(Z===$)break;$=Z}return t(v1,"..","..","..")}function $1($){let Q=$;for(let Z=0;Z<6;Z++){if(N$(t(Q,"VERSION"))&&N$(t(Q,"autonomy/run.sh")))return Q;let z=e$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function j(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(H8(),".loki")}var v1,h;var C=P(()=>{v1=e$(W8(import.meta.url));h=G8()});import{readFileSync as U8}from"fs";import{resolve as Y8,dirname as B8}from"path";import{fileURLToPath as M8}from"url";function S$(){if(Q$!==null)return Q$;let $="7.121.5";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=B8(M8(import.meta.url)),Z=$1(Q);Q$=U8(Y8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var Q1=P(()=>{C()});var p1={};b(p1,{runOrThrow:()=>S8,run:()=>R,readStreamCapped:()=>c1,commandVersion:()=>C8,commandExists:()=>u,ShellError:()=>Z1,MAX_STDOUT_BYTES:()=>u1});async function c1($,Q=u1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:W}=await Z.read();if(K)break;if(!W)continue;if(q+=W.byteLength,q>Q){let V=W.byteLength-(q-Q);X+=z.decode(W.subarray(0,V),{stream:!0});break}X+=z.decode(W,{stream:!0})}X+=z.decode()}finally{try{await Z.cancel()}catch{}Z.releaseLock()}return X}async function R($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[q,K,W]=await Promise.all([c1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:W}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function S8($,Q={}){let Z=await R($,Q);if(Z.exitCode!==0)throw new Z1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function u($){let Q=D8($),Z=await R(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function D8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function C8($,Q="--version"){if(!await u($))return null;let z=await R([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var u1=16777216,Z1;var o=P(()=>{Z1=class Z1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function r($){return b8?"":$}var b8,M,S,_,tZ,L,k,y,J;var p=P(()=>{b8=(process.env.NO_COLOR??"").length>0;M=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),tZ=r("\x1B[0;34m"),L=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as l8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(l8($))return A$=$,$;let Q=await u("python3.12");if(Q)return A$=Q,Q;let Z=await u("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return R([Z,"-c",$],Q)}var A$;var V$=P(()=>{o()});var V0={};b(V0,{runStatus:()=>U3});import{existsSync as v,readFileSync as H$,readdirSync as $0,statSync as Q0}from"fs";import{resolve as D,basename as z3}from"path";import{homedir as X3}from"os";function Z0($){let Q=Math.trunc($);if(Q>=1e6)return`${(Math.trunc(Q/1e6*10)/10).toFixed(1)}M`;if(Q>=1000)return`${(Math.trunc(Q/1000*10)/10).toFixed(1)}K`;return String(Q)}function z0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*C$/Q);if(X>C$)X=C$;let q=C$-X,K=S;if(z>=80)K=M;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=Z0($),H=Z0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${H})`}async function q3(){if(await u("jq"))return!0;return process.stdout.write(`${M}Error: jq is required but not installed.${J}
2
+ var q8=Object.defineProperty;var J8=($)=>$;function V8($,Q){this[$]=J8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)q8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:V8.bind(Q,Z)})};var P=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var m1={};b(m1,{lokiDir:()=>j,homeLokiDir:()=>T$,findRepoRootForVersion:()=>$1,REPO_ROOT:()=>h});import{resolve as t,dirname as e$}from"path";import{fileURLToPath as W8}from"url";import{existsSync as N$}from"fs";import{homedir as H8}from"os";function G8(){let $=v1;for(let Q=0;Q<6;Q++){if(N$(t($,"VERSION"))&&N$(t($,"autonomy/run.sh")))return $;let Z=e$($);if(Z===$)break;$=Z}return t(v1,"..","..","..")}function $1($){let Q=$;for(let Z=0;Z<6;Z++){if(N$(t(Q,"VERSION"))&&N$(t(Q,"autonomy/run.sh")))return Q;let z=e$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function j(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(H8(),".loki")}var v1,h;var C=P(()=>{v1=e$(W8(import.meta.url));h=G8()});import{readFileSync as U8}from"fs";import{resolve as Y8,dirname as B8}from"path";import{fileURLToPath as M8}from"url";function S$(){if(Q$!==null)return Q$;let $="7.121.6";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=B8(M8(import.meta.url)),Z=$1(Q);Q$=U8(Y8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var Q1=P(()=>{C()});var p1={};b(p1,{runOrThrow:()=>S8,run:()=>R,readStreamCapped:()=>c1,commandVersion:()=>C8,commandExists:()=>u,ShellError:()=>Z1,MAX_STDOUT_BYTES:()=>u1});async function c1($,Q=u1){let Z=$.getReader(),z=new TextDecoder,X="",q=0;try{while(q<Q){let{done:K,value:W}=await Z.read();if(K)break;if(!W)continue;if(q+=W.byteLength,q>Q){let V=W.byteLength-(q-Q);X+=z.decode(W.subarray(0,V),{stream:!0});break}X+=z.decode(W,{stream:!0})}X+=z.decode()}finally{try{await Z.cancel()}catch{}Z.releaseLock()}return X}async function R($,Q={}){let Z=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Q.env?{...process.env,...Q.env}:process.env,cwd:Q.cwd}),z,X;if(Q.timeoutMs&&Q.timeoutMs>0)z=setTimeout(()=>{try{Z.kill("SIGTERM")}catch{}X=setTimeout(()=>{try{Z.kill("SIGKILL")}catch{}},2000)},Q.timeoutMs);try{let[q,K,W]=await Promise.all([c1(Z.stdout),new Response(Z.stderr).text(),Z.exited]);return{stdout:q,stderr:K,exitCode:W}}finally{if(z)clearTimeout(z);if(X)clearTimeout(X)}}async function S8($,Q={}){let Z=await R($,Q);if(Z.exitCode!==0)throw new Z1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function u($){let Q=D8($),Z=await R(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function D8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function C8($,Q="--version"){if(!await u($))return null;let z=await R([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var u1=16777216,Z1;var o=P(()=>{Z1=class Z1 extends Error{message;exitCode;stdout;stderr;constructor($,Q,Z,z){super($);this.message=$;this.exitCode=Q;this.stdout=Z;this.stderr=z;this.name="ShellError"}}});function r($){return b8?"":$}var b8,M,S,_,tZ,L,k,y,J;var p=P(()=>{b8=(process.env.NO_COLOR??"").length>0;M=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),tZ=r("\x1B[0;34m"),L=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as l8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(l8($))return A$=$,$;let Q=await u("python3.12");if(Q)return A$=Q,Q;let Z=await u("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return R([Z,"-c",$],Q)}var A$;var V$=P(()=>{o()});var V0={};b(V0,{runStatus:()=>U3});import{existsSync as v,readFileSync as H$,readdirSync as $0,statSync as Q0}from"fs";import{resolve as D,basename as z3}from"path";import{homedir as X3}from"os";function Z0($){let Q=Math.trunc($);if(Q>=1e6)return`${(Math.trunc(Q/1e6*10)/10).toFixed(1)}M`;if(Q>=1000)return`${(Math.trunc(Q/1000*10)/10).toFixed(1)}K`;return String(Q)}function z0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*C$/Q);if(X>C$)X=C$;let q=C$-X,K=S;if(z>=80)K=M;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=Z0($),H=Z0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${H})`}async function q3(){if(await u("jq"))return!0;return process.stdout.write(`${M}Error: jq is required but not installed.${J}
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)
@@ -814,4 +814,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
814
814
  `),2}default:return process.stderr.write(`Unknown command: ${Q}
815
815
  `),process.stderr.write(K8),2}}e1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var SZ=await NZ(Bun.argv.slice(2));process.exit(SZ);
816
816
 
817
- //# debugId=F475C3772E2E83E064756E2164756E21
817
+ //# debugId=85EBA4135307848464756E2164756E21
package/mcp/__init__.py CHANGED
@@ -57,4 +57,4 @@ try:
57
57
  except ImportError:
58
58
  __all__ = ['mcp']
59
59
 
60
- __version__ = '7.121.5'
60
+ __version__ = '7.121.6'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "loki-mode",
3
3
  "mcpName": "io.github.asklokesh/loki-mode",
4
- "version": "7.121.5",
4
+ "version": "7.121.6",
5
5
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider).",
6
6
  "keywords": [
7
7
  "agent",
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "loki-mode",
4
4
  "displayName": "Loki Mode",
5
- "version": "7.121.5",
5
+ "version": "7.121.6",
6
6
  "description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
7
7
  "author": {
8
8
  "name": "Autonomi",