loki-mode 8.32.0 → 8.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md 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 v8.32.0
6
+ # Loki Mode v8.34.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -469,4 +469,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
469
469
 
470
470
  ---
471
471
 
472
- **v8.32.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
472
+ **v8.34.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 8.32.0
1
+ 8.34.0
package/autonomy/run.sh CHANGED
@@ -14330,6 +14330,43 @@ reviewers = mandatory + [
14330
14330
  }
14331
14331
  for name in installed_selected
14332
14332
  ]
14333
+ # TOTAL council cap (LOKI_REVIEW_MAX_REVIEWERS). The tier map sizes the
14334
+ # SPECIALIST slots ({simple:2, standard:2, complex:4}), but installed agents and
14335
+ # the dependency-analyst append AFTER that sizing, so nothing bounded the total.
14336
+ # Measured consequence, from real code_review_start/complete pairs:
14337
+ #
14338
+ # 3 reviewers -> 31s 6 reviewers -> 177s
14339
+ # 7 reviewers -> 280s 7 reviewers -> 502s
14340
+ #
14341
+ # Dispatch is already concurrent, so this superlinearity is the max-of-N tail
14342
+ # plus contention on one provider -- a scoped issue was drawing a 7-member
14343
+ # council (including two overlapping security reviewers) and paying 9-16x the
14344
+ # 3-member wall clock for it.
14345
+ #
14346
+ # TRIMMING ORDER IS A SAFETY PROPERTY. Mandatory reviewers
14347
+ # (requirements-verifier, architecture-strategist, maintainer-mergeability) are
14348
+ # NEVER dropped: each carries a mandate no keyword-selected specialist has, and
14349
+ # shrinking a council must never be able to manufacture an approval. Only the
14350
+ # appended tail (installed agents, then keyword specialists beyond the floor) is
14351
+ # trimmed, and the cap can never cut below the mandatory set.
14352
+ #
14353
+ # Default 0 = uncapped, preserving today's behaviour exactly. This is a knob to
14354
+ # be turned on deliberately per route, not a silent change to every council.
14355
+ try:
14356
+ _cap = int(os.environ.get("LOKI_REVIEW_MAX_REVIEWERS", "0") or "0")
14357
+ except ValueError:
14358
+ _cap = 0
14359
+ if _cap > 0 and len(reviewers) > _cap:
14360
+ _mandatory_names = {r["name"] for r in mandatory}
14361
+ _keep = [r for r in reviewers if r["name"] in _mandatory_names]
14362
+ for _r in reviewers:
14363
+ if len(_keep) >= _cap:
14364
+ break
14365
+ if _r["name"] not in _mandatory_names:
14366
+ _keep.append(_r)
14367
+ # Never below the mandatory set, even if the cap is set lower than it.
14368
+ reviewers = _keep if len(_keep) >= len(_mandatory_names) else reviewers
14369
+
14333
14370
  if os.environ.get("LOKI_REVIEW_REQUIREMENTS_ONLY") == "1":
14334
14371
  reviewers = [
14335
14372
  reviewer for reviewer in reviewers
@@ -22839,8 +22876,37 @@ if __name__ == "__main__":
22839
22876
  log_warn "Invariant gate FAILED ($inv_count consecutive) - CRITICAL/HIGH invariant/property violations (advisory; surfaced to next iteration)"
22840
22877
  fi
22841
22878
  fi
22879
+ # SKIP THE COUNCIL WHEN A DETERMINISTIC GATE ALREADY FAILED
22880
+ # (LOKI_REVIEW_SKIP_ON_GATE_FAIL, default off).
22881
+ #
22882
+ # Measured: the council costs 31s at 3 reviewers and 280-502s at 6-7.
22883
+ # The gates above cost ~6s COMBINED (static_analysis 5s, security_scan
22884
+ # 1s, lsp_diagnostics 1s, test_suite <1s). When one of them has already
22885
+ # failed, the iteration cannot be accepted no matter what the council
22886
+ # says -- gate_failures is non-empty and feeds the same completion
22887
+ # decision -- so the review is spending 280-502s to produce advice on
22888
+ # code that is already going back for another pass.
22889
+ #
22890
+ # WHAT THIS IS NOT. It does not weaken any gate: a skipped review is
22891
+ # recorded as skipped, never as a PASS, and the failing gate still
22892
+ # blocks exactly as before. It cannot turn a rejection into an
22893
+ # approval -- it only declines to spend five minutes describing a
22894
+ # rejection that is already decided.
22895
+ #
22896
+ # DEFAULT OFF. Review findings are also next-iteration STEERING
22897
+ # (LOKI_INJECT_FINDINGS), so skipping trades some guidance for a large
22898
+ # latency win. That trade is a per-route decision, not a silent
22899
+ # global one.
22900
+ local _skip_review=false
22901
+ if [ "${LOKI_REVIEW_SKIP_ON_GATE_FAIL:-false}" = "true" ] \
22902
+ && [ -n "${gate_failures:-}" ]; then
22903
+ _skip_review=true
22904
+ fi
22905
+ if [ "$_skip_review" = "true" ]; then
22906
+ log_warn "Code review SKIPPED: deterministic gates already failed (${gate_failures%,}). The iteration is already going back; not spending a full council on it. Unset LOKI_REVIEW_SKIP_ON_GATE_FAIL to always review."
22907
+ emit_stage_complete "code_review" "skipped" "$(date +%s 2>/dev/null)"
22842
22908
  # Code review gate (upgraded from advisory, with escalation)
22843
- if [ "$PHASE_CODE_REVIEW" = "true" ] && [ "$ITERATION_COUNT" -gt 0 ]; then
22909
+ elif [ "$PHASE_CODE_REVIEW" = "true" ] && [ "$ITERATION_COUNT" -gt 0 ]; then
22844
22910
  log_info "Quality gate: code review..."
22845
22911
  local _stg_t0=$(date +%s 2>/dev/null); local _stg_ok=pass
22846
22912
  if run_code_review; then
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "8.32.0"
10
+ __version__ = "8.34.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -0,0 +1,155 @@
1
+ # One JSON file to update when a provider ships a model
2
+
3
+ Founder ask (2026-08-01): a simple JSON we define at packaging time, so
4
+ updating for new model releases is easy.
5
+
6
+ ## The shape
7
+
8
+ `providers/model_registry.json` -- ONE file, flat, no cross-references. To adopt
9
+ a new model you edit one line.
10
+
11
+ ```json
12
+ {
13
+ "registry_version": "2026-08-01.1",
14
+ "_howto": "Edit a value below and ship. Nothing else needs to change.",
15
+
16
+ "tiers": {
17
+ "frontier": {
18
+ "anthropic": "opus",
19
+ "openai": "gpt-5.6",
20
+ "google": "gemini-3.1-pro-preview"
21
+ },
22
+ "balanced": {
23
+ "anthropic": "sonnet",
24
+ "openai": "gpt-5.6-terra",
25
+ "google": "gemini-3.6-flash"
26
+ },
27
+ "fast": {
28
+ "anthropic": "haiku",
29
+ "openai": "gpt-5.6-luna",
30
+ "google": "gemini-flash-latest"
31
+ }
32
+ },
33
+
34
+ "pinned": {
35
+ "_comment": "Optional. Set to override an alias with an exact snapshot.",
36
+ "anthropic": {},
37
+ "openai": {},
38
+ "google": {}
39
+ }
40
+ }
41
+ ```
42
+
43
+ That is the whole contract. Three tiers x three providers.
44
+
45
+ ## The one design decision that matters: ALIAS, not snapshot
46
+
47
+ The `anthropic` column holds `opus` / `sonnet` / `haiku`, not
48
+ `claude-opus-5` / `claude-sonnet-5` / `claude-haiku-4-5`.
49
+
50
+ **Verified against the live CLI on 2026-08-01:**
51
+
52
+ | passed | resolves to | note |
53
+ |---|---|---|
54
+ | `opus` | `claude-opus-5` | tracks latest automatically |
55
+ | `best` | `claude-fable-5` | Anthropic's most capable GA model |
56
+ | `haiku` | `claude-haiku-4-5-20251001` | |
57
+ | `claude-haiku-4-6` | **REJECTED** | "may not exist or you may not have access" |
58
+
59
+ Two facts fall out of that table, and both argue for aliases:
60
+
61
+ 1. **Aliases self-update.** When Anthropic ships Opus 6, `opus` follows it with
62
+ zero edits to this file. A snapshot id would need a release to track it --
63
+ which is exactly how our catalog ended up pinned to `claude-opus-4-8` while
64
+ Opus 5 shipped (fixed in v8.31.0).
65
+ 2. **Snapshot ids are account-scoped.** `claude-haiku-4-6` may exist on the API
66
+ and still be unreachable on a given account/CLI. Hardcoding it ships a
67
+ broken default to whoever lacks access.
68
+
69
+ That second point is not theoretical. We already have a scar:
70
+ `tests/test-codex-model-trusted.sh` records that pinning `gpt-5.3-codex` broke
71
+ **every ChatGPT-account user**, because codex-cli rejects it on that tier -- and
72
+ Codex ships free with every ChatGPT plan. The safe landing spot was "send no
73
+ model and let the provider choose."
74
+
75
+ **Rule: prefer a provider alias. Use an exact id only in `pinned`, only
76
+ deliberately.**
77
+
78
+ ## Why `pinned` exists
79
+
80
+ Anthropic's docs are explicit that Claude 4.6-generation dateless identifiers
81
+ are still **pinned snapshots, not evergreen pointers**. And Claude Code's
82
+ `best` / `opus` / `sonnet` are *Claude Code routing aliases* -- not a portable
83
+ contract in the raw Messages API.
84
+
85
+ So: aliases are right for the CLI providers we drive, and `pinned` is the escape
86
+ hatch for anyone who needs reproducibility or is calling an API directly.
87
+ Empty by default.
88
+
89
+ ## What "frontier" maps to for Anthropic
90
+
91
+ `best` resolves to `claude-fable-5` today, and Anthropic positions Fable as most
92
+ capable generally, with `claude-opus-5` aimed specifically at complex agentic
93
+ coding and enterprise work.
94
+
95
+ **We map `frontier` -> `opus`, not `best`.** Our workload IS agentic coding, and
96
+ `fable` is advisory-only in this codebase: the runner collapses it to opus, so
97
+ offering it as an execution model would be a cost surprise. That reasoning
98
+ predates this file and is unchanged.
99
+
100
+ ## What this replaces, and what it does not
101
+
102
+ `providers/model_catalog.json` stays. It carries per-provider metadata this file
103
+ deliberately does not (validation prefixes, tier fallbacks, aider's litellm
104
+ strings, the `models[]` ordering that the resolver depends on).
105
+
106
+ `model_registry.json` is the **editable surface**: the file a human opens when a
107
+ provider ships something. The catalog becomes derived where they overlap, and
108
+ `tests/test-model-catalog-single-source.sh` already fails when derived mirrors
109
+ disagree with their source -- that mechanism extends to cover this.
110
+
111
+ ## Rollout, matching the lifecycle in the founder's note
112
+
113
+ The note's recommended lifecycle is right, and one step already exists here:
114
+
115
+ ```
116
+ provider release detected <- tools/probe-model-catalog.py (exists, reads live docs)
117
+ v
118
+ add as frontier candidate <- edit model_registry.json
119
+ v
120
+ run coding-agent eval suite <- benchmarks/ (exists)
121
+ v
122
+ canary <- NOT built; needs traffic splitting we do not have
123
+ v
124
+ promote alias <- edit one line
125
+ v
126
+ keep previous as fallback <- pinned{} holds the old id
127
+ ```
128
+
129
+ **Honest gap:** we have no traffic-splitting layer, so 5% canary is not
130
+ implementable today. Do not put it in a release note as though it were.
131
+ Aliases blunt the need -- the provider is the one rolling the model forward,
132
+ and our eval suite plus the previous id in `pinned` is the realistic control.
133
+
134
+ ## Resolution order (must stay identical on both routes)
135
+
136
+ ```
137
+ LOKI_<PROVIDER>_MODEL (trusted verbatim -- fine-tunes, org models)
138
+ -> pinned[provider][tier] (deliberate snapshot)
139
+ -> tiers[tier][provider] (the alias -- the normal path)
140
+ -> provider default (may legitimately be EMPTY: see codex/ChatGPT)
141
+ ```
142
+
143
+ The last line is load-bearing. Empty means "send no `--model` and let the
144
+ provider pick," which is correct whenever we cannot know an id is valid for that
145
+ account. Never replace it with a guess.
146
+
147
+ ## Acceptance
148
+
149
+ - Adding a model is a one-line edit to `model_registry.json`.
150
+ - `tests/test-model-catalog-current-flagship.sh` (v8.31.0) already fails when a
151
+ tier points at a superseded same-family model; extend it to this file.
152
+ - A mutation flipping any alias back to a hardcoded snapshot must turn a test
153
+ red.
154
+ - No test may assert an exact snapshot id that this account cannot dispatch --
155
+ the `claude-haiku-4-6` result above is the reason.
@@ -0,0 +1,239 @@
1
+ # Fastest First-Pass Completion: measured plan
2
+
3
+ Goal (founder, 2026-08-01): **fastest first-pass full completion** -- highest
4
+ quality output, no waiting through a second iteration, faster than Cursor /
5
+ Cognition / Replit on the axis a user actually feels.
6
+
7
+ This plan is built on measurement first, competitor research second, and it
8
+ DISCARDS the intuition I started with.
9
+
10
+ ---
11
+
12
+ ## 1. What the competition actually does (researched, not assumed)
13
+
14
+ | Vendor | Speed mechanism | Reachable for us? |
15
+ |---|---|---|
16
+ | **Cursor** | Composer: in-house MoE model, ~250 tok/s (~4x GPT-5/Sonnet). MXFP8 training, no post-train quant. Compaction-in-the-loop RL cuts context errors 50%. | **No.** Custom frontier model. |
17
+ | **Cognition** | SWE-1.6 at ~950 tok/s; SWE-bench 51.5%. | **No.** Custom model. |
18
+ | **Replit** | Agent 3: ~2 min to visual preview, ~10 min to first app version. Design Mode <2 min. 2-3x gains across 2025. | **Partly.** Their edge is product/lifecycle, not model. |
19
+
20
+ **The strategic conclusion.** Cursor and Cognition bought speed by TRAINING
21
+ THEIR OWN MODELS. We cannot copy that and should stop pretending the gap is
22
+ closable that way. Replit's edge is time-to-first-visible-thing, which IS
23
+ reachable, because it is a product and lifecycle property.
24
+
25
+ The industry-wide numbers that matter for us, from the latency research:
26
+
27
+ - **Tool execution is 35-61% of total agent request time.** Harness, not model.
28
+ - Parallel tool calling / speculative execution deliver **2-5x latency
29
+ reduction while preserving correctness**.
30
+ - Prompt caching turns repeated-prefix attention from O(n^2) to O(n).
31
+
32
+ That 35-61% is our lane. It is won by architecture, and it does not require a
33
+ frontier lab.
34
+
35
+ ## 2. What we actually cost, MEASURED (this is the surprise)
36
+
37
+ Real `stage_complete` events from builds on this machine (n=35):
38
+
39
+ | stage | n | median s | max s | total s |
40
+ |---|---:|---:|---:|---:|
41
+ | **code_review** | 3 | **281** | **504** | **1055** |
42
+ | static_analysis | 5 | 5 | 14 | 26 |
43
+ | security_scan | 5 | 1 | 2 | 4 |
44
+ | lsp_diagnostics | 4 | 1 | 1 | 2 |
45
+ | test_suite | 4 | 0 | 1 | 1 |
46
+ | mutation_integrity | 4 | 0 | 1 | 1 |
47
+ | mock_integrity | 4 | 0 | 0 | 0 |
48
+ | doc_coverage | 3 | 0 | 0 | 0 |
49
+ | magic_debate | 3 | 0 | 0 | 0 |
50
+ | **TOTAL** | | | | **1089** |
51
+
52
+ **`code_review` is 97% of all measured gate time.** Everything else combined is
53
+ 34 seconds.
54
+
55
+ ### Two intuitions this killed
56
+
57
+ **First:** I was about to propose parallelizing the seven sequential gates at
58
+ `run.sh:22616-22980`. They ARE sequential and mostly independent. The change
59
+ would have been clean, defensible, and worth **about 20 seconds**.
60
+
61
+ **Second, and worse:** I then proposed parallelizing the reviewer council --
62
+ which was **already parallel**. I had grepped the wrong line range, got no
63
+ match, and treated that silence as evidence. A plan whose headline item was a
64
+ no-op.
65
+
66
+ Both were caught by going back to data instead of trusting the story. The
67
+ standing rule for this document:
68
+
69
+ > **No optimization ships without a before-number from this table, and no
70
+ > claim about how the code behaves ships without reading the code that does
71
+ > it.**
72
+
73
+ An absent grep match is not evidence of absence -- it is evidence the grep did
74
+ not match.
75
+
76
+ ### Where the real time goes
77
+
78
+ Code review dominates, and the driver is **council size**, not sequential
79
+ dispatch (see the correction in P0 -- my first reading of this was wrong).
80
+
81
+ Measured: 3 reviewers finish in 31s; 6-7 reviewers take 177-502s. The council
82
+ is already concurrent, so what grows is the max-of-N tail plus contention on a
83
+ single provider.
84
+
85
+ This explains the founder's "21 minutes for a simple GitHub issue" better than
86
+ any other measurement taken today: a scoped issue was drawing a 7-member
87
+ council containing two overlapping security reviewers.
88
+
89
+ ---
90
+
91
+ ## 3. The plan, ranked by measured seconds returned
92
+
93
+ ### P0 -- CORRECTED: the council is ALREADY parallel. The cost is its SIZE.
94
+
95
+ **This section originally claimed reviewers ran sequentially and proposed
96
+ parallelizing them. That was wrong, and the correction is recorded here rather
97
+ than quietly edited out.**
98
+
99
+ `run_code_review` forks every reviewer with `) &` (run.sh:14803), collects PIDs,
100
+ and `wait`s on each (run.sh:14880). It has been parallel all along. My first
101
+ grep searched the wrong line range, returned nothing, and I read that silence as
102
+ proof of absence -- the same mistake class this codebase has been punishing all
103
+ session.
104
+
105
+ **What the data actually says.** Pairing `code_review_start` with
106
+ `code_review_complete` across every recorded review:
107
+
108
+ | reviewers | seconds | verdict |
109
+ |---:|---:|---|
110
+ | 7 | 502 | 0 pass / 7 fail |
111
+ | 7 | 280 | 1 pass / 6 fail |
112
+ | 6 | 177 | 0 pass / 5 fail |
113
+ | **3** | **31** | 2 pass / 1 fail |
114
+
115
+ **3 reviewers = 31s. 7 reviewers = 280-502s.** Roughly 2x the council for 9-16x
116
+ the wall clock. Since dispatch is already concurrent, that superlinearity is not
117
+ the count itself -- it is that a larger council pulls in slower reviewers and
118
+ contends for the same provider, so the max-of-N tail dominates.
119
+
120
+ **And the 7-member council is partly redundant:**
121
+
122
+ ```
123
+ architecture-strategist, maintainer-mergeability,
124
+ security-sentinel, review-security, <- TWO security reviewers
125
+ performance-oracle, eng-qa, dependency-analyst
126
+ ```
127
+
128
+ `security-sentinel` and `review-security` overlap. `eng-qa` and
129
+ `dependency-analyst` are appended agents, not part of the sized battery.
130
+
131
+ **The real P0, in priority order:**
132
+
133
+ 1. **Deduplicate overlapping reviewers.** Two security reviewers on one diff is
134
+ paying the tail cost twice for one signal. Collapse by mandate, not by name.
135
+ 2. **Cap the effective council for scoped changes.** The tier map is
136
+ `{simple: 2, standard: 2, complex: 4}` specialists + 2 mandatory. Appended
137
+ agents bypass that sizing entirely, which is how 4 becomes 7. Bound the
138
+ TOTAL, not just the specialist slots.
139
+ 3. **Bound the tail, not the mean.** One slow reviewer sets the whole council's
140
+ latency. A per-reviewer deadline that records a non-vote (never a silent
141
+ pass) converts a 502s worst case into a bounded one.
142
+
143
+ Expected: the 6-7 member case moves toward the measured 3-member behaviour
144
+ (31s) for scoped work, while `complex` keeps its deeper battery.
145
+
146
+ **Fail-safe direction is load-bearing:** a dropped or deadlined reviewer must
147
+ count as a NON-VOTE exactly as today, never as a pass. Shrinking a council must
148
+ never be able to manufacture approval. Guard with a test asserting the verdict
149
+ is identical for the same fixture at any council size, and that a deadlined
150
+ reviewer never contributes a PASS.
151
+
152
+ ### P1 -- Do not run the full council on iteration 1 of a scoped change
153
+
154
+ The 8-gate council exists to catch regressions in a large build. On a scoped
155
+ GitHub-issue fix, running a 3-reviewer council before the change is even
156
+ verified is spending 281s to review something a test run would disprove in 1s.
157
+
158
+ - Order: cheap deterministic gates FIRST (test_suite, static_analysis,
159
+ lsp_diagnostics -- 6s combined), council only if those pass.
160
+ - A failing test means the council would have rejected anyway; running it first
161
+ is strictly wasted wall-clock.
162
+ - Expected: on a failing first pass, ~281s saved outright.
163
+
164
+ ### P2 -- Time-to-first-signal (the Replit lesson)
165
+
166
+ Replit shows a visual preview in ~2 minutes. We show nothing until an iteration
167
+ completes. Even when our total time is competitive, the FELT time is worse.
168
+
169
+ - Emit a first-signal event as soon as the agent's first file write lands.
170
+ - `.loki/app-runner/first-preview.json` already exists (write-once, bash route)
171
+ -- surface it, and extend to the non-preview case as "first artifact".
172
+ - This is perception, not throughput, and it is cheap.
173
+
174
+ ### P3 -- First-pass correctness (the actual "no second iteration" ask)
175
+
176
+ Research finding: success now hinges on **specification quality and dynamic
177
+ context**, not static upfront planning. Notably, auto-generated context files
178
+ REDUCED success ~3% while human-written ones improved it ~4%, both raising cost
179
+ 20%+. So "generate a big context file" is measurably the wrong move.
180
+
181
+ What the evidence supports:
182
+ - ACE (ICLR 2026): generate -> reflect -> curate as an evolving context loop:
183
+ **+10.6% on coding benchmarks**.
184
+ - We already have the seam: `LOKI_INJECT_FINDINGS` feeds structured per-finding
185
+ records into the next iteration.
186
+ - The lever is making iteration 1's prompt carry what iteration 2 would have
187
+ learned -- which the existing first-pass-excellence work began and which
188
+ measured 2.8x cheaper with correctness held.
189
+
190
+ **Do not** add a static generated context file. The data says it hurts.
191
+
192
+ ### P4 -- Prompt-cache discipline (already partly built, verify it holds)
193
+
194
+ `[CACHE_BREAKPOINT]` splits a cache-stable prefix from a volatile tail. Cache
195
+ reads price at 0.1x input. Any always-on instruction added to the wrong side
196
+ busts the cache every iteration.
197
+
198
+ - Add a regression test asserting no volatile content crosses the breakpoint.
199
+ - This is a cost lever primarily, and a TTFT lever secondarily.
200
+
201
+ ---
202
+
203
+ ## 4. What we do NOT do
204
+
205
+ - **Do not train a model.** Cursor and Cognition's speed is bought with custom
206
+ MoE models at 250-950 tok/s. That is not a gap we close with harness work,
207
+ and claiming otherwise would be dishonest.
208
+ - **Do not parallelize the seven cheap gates as a headline.** Measured worth:
209
+ ~20s. Do it opportunistically inside P1's reordering, never sold as the win.
210
+ - **Do not add static generated context files.** Measured -3% success, +20%
211
+ cost.
212
+
213
+ ## 5. How we know it worked
214
+
215
+ Every item ships with a before/after from the same `stage_complete` telemetry
216
+ that produced the table above. The acceptance number for the founder's
217
+ complaint:
218
+
219
+ > a scoped GitHub issue completes in **under 5 minutes**, first pass,
220
+ > with the council verdict intact.
221
+
222
+ Current measured critical path for that case is dominated by 281s of
223
+ sequential code review. P0 + P1 target exactly that.
224
+
225
+ ## 6. Honest competitive position after this plan
226
+
227
+ - **vs Cursor** on raw interactive latency: still behind. Different category.
228
+ - **vs Replit** on time-to-first-visible: reachable with P2.
229
+ - **vs Cognition** on trust: ahead, and that is the moat -- the Evidence
230
+ Receipt, now that the gates behind it actually run (v8.24.0-v8.31.0).
231
+
232
+ The wedge is **verified-and-fast**, not fastest-in-absolute. We should say that
233
+ plainly rather than claim a speed crown we cannot hold.
234
+
235
+ ---
236
+
237
+ Sources: Cursor Composer blog, VentureBeat Composer coverage, Cognition
238
+ SWE-1.6 reporting, Replit Agent 3 reviews, Zylos speculative-execution/parallel
239
+ tool-calling research, ACE (ICLR 2026), 2026 context-engineering surveys.
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.32.0";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=t_(e_(import.meta.url)),Q=eK(X);h5=o_(r_(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var HQ=p(()=>{G8()});var bO={};l0(bO,{runOrThrow:()=>Of,run:()=>E0,readStreamCapped:()=>UQ,commandVersion:()=>Af,commandExists:()=>X9,ShellError:()=>Z$,MAX_STDOUT_BYTES:()=>yO});async function UQ(Z,X=yO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function E0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([UQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Of(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new Z$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Lf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Lf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Af(Z,X="--version"){if(!await X9(Z))return null;let Y=await E0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var yO=16777216,Z$;var x9=p(()=>{Z$=class Z$ extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function o7(Z){return jf?"":Z}var jf,L0,k8,p0,ZV0,i0,H8,Q9,v;var S6=p(()=>{jf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),k8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),ZV0=o7("\x1B[0;34m"),i0=o7("\x1B[0;36m"),H8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as xf}from"fs";async function E7(){if(k4!==void 0)return k4;let Z="/opt/homebrew/bin/python3.12";if(xf(Z))return k4=Z,Z;let X=await X9("python3.12");if(X)return k4=X,X;let Q=await X9("python3");return k4=Q,Q}async function Y7(Z,X={}){let Q=await E7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return E0([Q,"-c",Z],X)}var k4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Yh});import{existsSync as Y9,readFileSync as v3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as sf}from"path";import{homedir as nf}from"os";function sO(Z){let X=Math.trunc(Z);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 nO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*NQ/X);if(J>NQ)J=NQ;let z=NQ-J,K=k8;if(Y>=80)K=L0;else if(Y>=50)K=p0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=sO(Z),V=sO(X);return` ${H8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function rf(){if(await X9("jq"))return!0;return process.stdout.write(`${L0}Error: jq is required but not installed.${v}
2
+ var h_=Object.create;var{getPrototypeOf:v_,defineProperty:rK,getOwnPropertyNames:g_}=Object;var m_=Object.prototype.hasOwnProperty;function u_(Z){return this[Z]}var p_,d_,c_=(Z,X,Q)=>{var Y=Z!=null&&typeof Z==="object";if(Y){var J=X?p_??=new WeakMap:d_??=new WeakMap,z=J.get(Z);if(z)return z}Q=Z!=null?h_(v_(Z)):{};let K=X||!Z||!Z.__esModule?rK(Q,"default",{value:Z,enumerable:!0}):Q;for(let $ of g_(Z))if(!m_.call(K,$))rK(K,$,{get:u_.bind(Z,$),enumerable:!0});if(Y)J.set(Z,K);return K};var qQ=(Z,X)=>()=>(X||Z((X={exports:{}}).exports,X),X.exports);var l_=(Z)=>Z;function i_(Z,X){this[Z]=l_.bind(null,X)}var l0=(Z,X)=>{for(var Q in X)rK(Z,Q,{get:X[Q],enumerable:!0,configurable:!0,set:i_.bind(X,Q)})};var p=(Z,X)=>()=>(Z&&(X=Z(Z=0)),X);var e0=import.meta.require;var kO={};l0(kO,{lokiDir:()=>j0,homeLokiDir:()=>P4,findRepoRootForVersion:()=>eK,REPO_ROOT:()=>r0});import{resolve as n7,dirname as tK}from"path";import{fileURLToPath as a_}from"url";import{existsSync as GQ}from"fs";import{homedir as s_}from"os";function n_(){let Z=RO;for(let X=0;X<6;X++){if(GQ(n7(Z,"VERSION"))&&GQ(n7(Z,"autonomy/run.sh")))return Z;let Q=tK(Z);if(Q===Z)break;Z=Q}return n7(RO,"..","..","..")}function eK(Z){let X=Z;for(let Q=0;Q<6;Q++){if(GQ(n7(X,"VERSION"))&&GQ(n7(X,"autonomy/run.sh")))return X;let Y=tK(X);if(Y===X)break;X=Y}return n7(Z,"..","..","..")}function j0(){return process.env.LOKI_DIR??n7(process.cwd(),".loki")}function P4(){return n7(s_(),".loki")}var RO,r0;var G8=p(()=>{RO=tK(a_(import.meta.url));r0=n_()});import{readFileSync as o_}from"fs";import{resolve as r_,dirname as t_}from"path";import{fileURLToPath as e_}from"url";function f3(){if(h5!==null)return h5;let Z="8.34.0";if(typeof Z==="string"&&Z.length>0)return h5=Z,h5;try{let X=t_(e_(import.meta.url)),Q=eK(X);h5=o_(r_(Q,"VERSION"),"utf-8").trim()}catch{h5="unknown"}return h5}var h5=null;var HQ=p(()=>{G8()});var bO={};l0(bO,{runOrThrow:()=>Of,run:()=>E0,readStreamCapped:()=>UQ,commandVersion:()=>Af,commandExists:()=>X9,ShellError:()=>Z$,MAX_STDOUT_BYTES:()=>yO});async function UQ(Z,X=yO){let Q=Z.getReader(),Y=new TextDecoder,J="",z=0;try{while(z<X){let{done:K,value:$}=await Q.read();if(K)break;if(!$)continue;if(z+=$.byteLength,z>X){let W=$.byteLength-(z-X);J+=Y.decode($.subarray(0,W),{stream:!0});break}J+=Y.decode($,{stream:!0})}J+=Y.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function E0(Z,X={}){let Q=Bun.spawn({cmd:[...Z],stdout:"pipe",stderr:"pipe",env:X.env?{...process.env,...X.env}:process.env,cwd:X.cwd}),Y,J;if(X.timeoutMs&&X.timeoutMs>0)Y=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},X.timeoutMs);try{let[z,K,$]=await Promise.all([UQ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:z,stderr:K,exitCode:$}}finally{if(Y)clearTimeout(Y);if(J)clearTimeout(J)}}async function Of(Z,X={}){let Q=await E0(Z,X);if(Q.exitCode!==0)throw new Z$(`command failed (${Q.exitCode}): ${Z.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function X9(Z){let X=Lf(Z),Q=await E0(["sh","-c",`command -v ${X}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Lf(Z){if(!/^[A-Za-z0-9._/-]+$/.test(Z))throw Error(`refused to shell-escape suspect token: ${Z}`);return Z}async function Af(Z,X="--version"){if(!await X9(Z))return null;let Y=await E0([Z,X],{timeoutMs:5000});if(Y.exitCode!==0)return null;return((Y.stdout||Y.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var yO=16777216,Z$;var x9=p(()=>{Z$=class Z$ extends Error{message;exitCode;stdout;stderr;constructor(Z,X,Q,Y){super(Z);this.message=Z;this.exitCode=X;this.stdout=Q;this.stderr=Y;this.name="ShellError"}}});function o7(Z){return jf?"":Z}var jf,L0,k8,p0,ZV0,i0,H8,Q9,v;var S6=p(()=>{jf=(process.env.NO_COLOR??"").length>0;L0=o7("\x1B[0;31m"),k8=o7("\x1B[0;32m"),p0=o7("\x1B[1;33m"),ZV0=o7("\x1B[0;34m"),i0=o7("\x1B[0;36m"),H8=o7("\x1B[1m"),Q9=o7("\x1B[2m"),v=o7("\x1B[0m")});import{existsSync as xf}from"fs";async function E7(){if(k4!==void 0)return k4;let Z="/opt/homebrew/bin/python3.12";if(xf(Z))return k4=Z,Z;let X=await X9("python3.12");if(X)return k4=X,X;let Q=await X9("python3");return k4=Q,Q}async function Y7(Z,X={}){let Q=await E7();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return E0([Q,"-c",Z],X)}var k4;var r7=p(()=>{x9()});var ZL={};l0(ZL,{runStatus:()=>Yh});import{existsSync as Y9,readFileSync as v3,readdirSync as iO,statSync as aO}from"fs";import{resolve as h8,basename as sf}from"path";import{homedir as nf}from"os";function sO(Z){let X=Math.trunc(Z);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 nO(Z,X,Q){if(X===0)return null;let Y=Math.trunc(Z*100/X),J=Math.trunc(Z*NQ/X);if(J>NQ)J=NQ;let z=NQ-J,K=k8;if(Y>=80)K=L0;else if(Y>=50)K=p0;let $="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,z)),W=sO(Z),V=sO(X);return` ${H8}${Q}${v} ${K}[${$}]${v} ${Y}% (${W} / ${V})`}async function rf(){if(await X9("jq"))return!0;return process.stdout.write(`${L0}Error: jq is required but not installed.${v}
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)
@@ -1222,4 +1222,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1222
1222
  `),2}case"start":{let{runStart:Y}=await Promise.resolve().then(() => (b_(),y_));return Y(Q)}default:return process.stderr.write(`Unknown command: ${X}
1223
1223
  `),process.stderr.write(__),2}}cO();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var fW0=await _W0(Bun.argv.slice(2));process.exit(fW0);
1224
1224
 
1225
- //# debugId=E73CE71EDB93AD7A64756E2164756E21
1225
+ //# debugId=651C52085A3FC1C964756E2164756E21
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '8.32.0'
78
+ __version__ = '8.34.0'
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": "8.32.0",
4
+ "version": "8.34.0",
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": "8.32.0",
5
+ "version": "8.34.0",
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",