loki-mode 7.103.0 → 7.104.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +29 -15
- package/autonomy/run.sh +65 -9
- package/autonomy/verify.sh +185 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +137 -24
- package/dashboard/static/index.html +57 -5
- package/docs/INSTALLATION.md +1 -1
- package/docs/SONNET5-DEFAULT-PLAN.md +157 -0
- package/loki-ts/data/model-pricing.json +3 -3
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +2 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/claude.sh +15 -9
- package/providers/model_catalog.json +20 -19
- package/vendor/autonomi-verify/LICENSE +39 -0
- package/vendor/autonomi-verify/README.md +58 -0
- package/vendor/autonomi-verify/embed.js +8 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Sonnet 5 Default - Implementation Plan
|
|
2
|
+
|
|
3
|
+
Status: PLAN (no code written). Worktree: `../loki-sonnet5-wt` (branch `feat/sonnet5-default`).
|
|
4
|
+
Board decision: `strategy/roadmap/13-BOARD-2026-06-30.md`. Verified facts: `reference-sonnet5-model-ids` memory.
|
|
5
|
+
Release class: MINOR (new default execution model for every user). Full local-ci + council 3/3 + release ladder.
|
|
6
|
+
|
|
7
|
+
## 1. Goal (founder directive, 2026-06-30)
|
|
8
|
+
|
|
9
|
+
Make Sonnet 5 the DEFAULT execution model for Loki runs. Advisor stays Opus (opt-in / when needed).
|
|
10
|
+
User can set all tiers to haiku|sonnet|opus from the dashboard at start, and hot-switch mid-run without
|
|
11
|
+
interrupting executions. Protect the "never lies about done" trust moat: the switch must NOT weaken the
|
|
12
|
+
verdict.
|
|
13
|
+
|
|
14
|
+
## 2. Ground truth (verified against source 2026-06-30)
|
|
15
|
+
|
|
16
|
+
- Live model resolver: `resolve_model_for_tier()` (providers/claude.sh:390) reads
|
|
17
|
+
`PROVIDER_MODEL_{PLANNING,DEVELOPMENT,FAST}` (claude.sh:65-67) which chain from `CLAUDE_DEFAULT_*`
|
|
18
|
+
(claude.sh:55-57). Today: PLANNING=opus, DEVELOPMENT=opus (comment "was sonnet"), FAST=sonnet.
|
|
19
|
+
- `get_provider_tier_param` case block (run.sh:~2447) with hardcoded `development) echo opus` is the
|
|
20
|
+
INERT legacy fallback, reachable only when claude.sh is unsourced (guard run.sh:2414). Flip anyway
|
|
21
|
+
for consistency.
|
|
22
|
+
- Trust-gate code-review reviewers: `_dispatch_reviewer()` (run.sh:~10148) sets
|
|
23
|
+
`_rv_argv=("--dangerously-skip-permissions")` and deliberately passes NO `--model` -> reviewers run
|
|
24
|
+
on the ACCOUNT DEFAULT model = non-deterministic, config-dependent. The in-code comment (run.sh:~10164)
|
|
25
|
+
explicitly says a future `--model` here "must be pinned to opus, never fable" (Fable refuses cyber
|
|
26
|
+
content, ends -p turn with stop_reason refusal). Bun route mirrors this: quality_gates.ts:28 + :1223.
|
|
27
|
+
- Hot-switch mid-run EXISTS: `.loki/state/model-override` read each iteration (run.sh:16007-16070),
|
|
28
|
+
written by dashboard `POST /api/session/model` (server.py:2852), allowlist haiku|sonnet|opus|fable,
|
|
29
|
+
clamped by `loki_apply_max_tier_clamp` (claude.sh:347). Fresh `claude -p` per iteration = clean switch.
|
|
30
|
+
- Sonnet 5 = alias `claude-sonnet-5` (CLI resolves aliases to latest; loki passes alias verbatim at
|
|
31
|
+
claude.sh:334). Opus 4.8 = `claude-opus-4-8`. Pricing (server.py:6174, run.sh:4847/12153): sonnet
|
|
32
|
+
$3/$15, opus $5/$25, haiku $1/$5, fable $10/$50 - all correct. model_catalog.json has stale IDs
|
|
33
|
+
opus-4-7, sonnet-4-6.
|
|
34
|
+
- Parity-locked: `tests/test-model-override.sh` + dashboard estimator (`_clamp_to_max_tier`, `_max_tier`)
|
|
35
|
+
are byte-locked to the resolver. Flipping defaults MOVES the quote -> expected values must update.
|
|
36
|
+
- Dashboard-ui: no start-time model picker (grep empty). mid-run switcher UI also appears absent
|
|
37
|
+
(POST endpoint exists, no UI consumer found).
|
|
38
|
+
|
|
39
|
+
## 3. Tier -> model mapping AFTER the change
|
|
40
|
+
|
|
41
|
+
| Tier (RARV phase) | Today | After |
|
|
42
|
+
|--------------------------|--------------------------|----------------------------------------|
|
|
43
|
+
| planning (REASON) | opus | sonnet (Opus opt-in via advisor path) |
|
|
44
|
+
| development (ACT/REFLECT)| opus | sonnet |
|
|
45
|
+
| fast (VERIFY) | sonnet | sonnet (haiku via LOKI_ALLOW_HAIKU) |
|
|
46
|
+
| trust gate (council/review)| account default (float)| account default (UNCHANGED); opus via OPT-IN `LOKI_ADVISOR_MODEL` |
|
|
47
|
+
| advisor / reviewer pin | (does not exist) | `LOKI_ADVISOR_MODEL` (default unset = today's behavior; set=opus) |
|
|
48
|
+
| Opus-for-execution | default | opt-in (dashboard "all opus" / env) |
|
|
49
|
+
|
|
50
|
+
### CORRECTION (advisor review 2026-06-30) - D2 is OPT-IN, not always-on
|
|
51
|
+
|
|
52
|
+
The original board D2 ("always pin reviewers to --model opus") is REJECTED as written, for four reasons:
|
|
53
|
+
1. NOT causally forced by the Sonnet flip: `_dispatch_reviewer` reads neither `tier_param` nor
|
|
54
|
+
`CLAUDE_DEFAULT_*`, so flipping the builder default does NOT change the reviewer model. The judge
|
|
55
|
+
floating with the account default is a PRE-EXISTING condition, not something this PR exposes.
|
|
56
|
+
2. UNCOSTED: pinning 3 reviewers + devil's-advocate + security-sentinel to Opus ADDS Opus-priced tokens
|
|
57
|
+
on top of the builder savings. Opus ~1.7x sonnet. This could eat or exceed the "~40% cheaper" story.
|
|
58
|
+
Net cost is UNKNOWN until we measure reviewer-token vs builder-token volume for a typical `loki start`.
|
|
59
|
+
3. CONTRADICTS the founder's words: "advisor will be opus IF NEEDED OR USER OPTED" = conditional/opt-in.
|
|
60
|
+
Always-on removes the implicit cost control users have today (account default) - opposite of the
|
|
61
|
+
adoption/cost intent.
|
|
62
|
+
4. "Deterministic verdict" is the wrong framing: LLM reviewers are never deterministic; this is a
|
|
63
|
+
consistency/quality argument, not determinism.
|
|
64
|
+
|
|
65
|
+
Moat guarantee (corrected): default behavior of the trust gate is UNCHANGED by this release (no
|
|
66
|
+
cost regression, no surprise). Users who want a strong, consistent Opus judge set `LOKI_ADVISOR_MODEL=opus`
|
|
67
|
+
(or the dashboard "advisor: Opus" toggle), which pins the reviewer/override-judge to Opus. This is the
|
|
68
|
+
founder's "opus if needed or user opted", made real and opt-in. Lane B and Lane C COLLAPSE into this one
|
|
69
|
+
opt-in advisor path.
|
|
70
|
+
|
|
71
|
+
## 4. Per-file change list (disjoint lanes for parallel principal engineers)
|
|
72
|
+
|
|
73
|
+
### Lane A - Execution default flip (providers/claude.sh) [engineer 1]
|
|
74
|
+
- claude.sh:56 `CLAUDE_DEFAULT_DEVELOPMENT="opus"` -> `"sonnet"`.
|
|
75
|
+
- claude.sh:55 `CLAUDE_DEFAULT_PLANNING="opus"` -> `"sonnet"` (see open question Q1 - founder may want
|
|
76
|
+
planning to stay opus; design so this one line is a trivial revert).
|
|
77
|
+
- claude.sh:57 FAST stays sonnet.
|
|
78
|
+
- Trace + document the clamp ripple: `loki_apply_max_tier_clamp` (claude.sh:347) resolves planning/fable
|
|
79
|
+
DOWN to `PROVIDER_MODEL_DEVELOPMENT`. With dev=sonnet, `LOKI_MAX_TIER=sonnet` now genuinely pins
|
|
80
|
+
sonnet (previously it clamped to opus). Update the comment block at claude.sh:383-386 which currently
|
|
81
|
+
documents the opposite. This is a BEHAVIOR clarification, verify against the parity ports (Lane E).
|
|
82
|
+
- run.sh:~2447 legacy fallback `development) echo opus` -> `sonnet` (inert but consistent).
|
|
83
|
+
|
|
84
|
+
### Lane B+C (COLLAPSED) - OPT-IN advisor/reviewer Opus pin [engineer 2]
|
|
85
|
+
- Introduce `LOKI_ADVISOR_MODEL` (unset default = TODAY'S behavior, no change; set to `opus` = pin).
|
|
86
|
+
- Bash: `_dispatch_reviewer()` (run.sh:~10148): IF `LOKI_ADVISOR_MODEL` is a valid allowlisted alias,
|
|
87
|
+
add `("--model" "$LOKI_ADVISOR_MODEL")` to `_rv_argv`; else leave unset (current behavior). Honor the
|
|
88
|
+
existing comment (opus ok, never fable - validate the alias is not fable). The override/architect paths
|
|
89
|
+
(which rewrite tier_param, NOT this dispatch) still cannot touch it.
|
|
90
|
+
- Bun: `quality_gates.ts` reviewer dispatch (near :1223): mirror the same opt-in read. BOTH routes match.
|
|
91
|
+
- Update the "reviewers deliberately do NOT pass --model" comments to: default no --model; opt-in pin
|
|
92
|
+
via LOKI_ADVISOR_MODEL; rationale = consistent/strong judge when the user wants it (NOT determinism).
|
|
93
|
+
- Devil's-advocate + security-sentinel inherit the opt-in pin (same dispatch).
|
|
94
|
+
- Dashboard: an "Advisor model" toggle (default: account default; option: Opus) writes LOKI_ADVISOR_MODEL
|
|
95
|
+
into the run env / a state file the dispatch reads. This IS the founder's "opus if needed or user opted".
|
|
96
|
+
- DO NOT make this always-on. Default behavior of the trust gate is unchanged (no cost regression).
|
|
97
|
+
|
|
98
|
+
### Lane D - Dashboard model selection [engineer 4] (follows frontend-ui-engineering skill)
|
|
99
|
+
- Backend: confirm `POST /api/session/model` (server.py:2852) writes `.loki/state/model-override`
|
|
100
|
+
with allowlist haiku|sonnet|opus|fable (already does). Add start-time selection: `start_build`
|
|
101
|
+
(server.py:3234) accepts an optional `model` that writes the override file BEFORE launch (so iteration
|
|
102
|
+
1 picks it up). Validate against the same allowlist + clamp.
|
|
103
|
+
- Frontend (dashboard-ui/src): add an accessible model selector (haiku/sonnet/opus) on the start/new-run
|
|
104
|
+
surface AND a mid-run switcher that calls POST /api/session/model. Real design-system tokens, keyboard
|
|
105
|
+
accessible, no AI-aesthetic. Show current effective model + that switch applies at next iteration.
|
|
106
|
+
Rebuild dashboard/static per CLAUDE.md release step 2.
|
|
107
|
+
|
|
108
|
+
### Lane E - Catalog IDs, pricing note, parity tests [engineer 5]
|
|
109
|
+
- model_catalog.json: opus-4-7 -> claude-opus-4-8 (3 occurrences), sonnet-4-6 -> claude-sonnet-5
|
|
110
|
+
(5 occurrences). Keep the alias->tier structure.
|
|
111
|
+
- Pricing: LEAVE the cost NUMBERS at standing $3/$15 for sonnet (over-estimate is the safe direction;
|
|
112
|
+
avoids date-expiry logic that silently breaks after Aug 31 2026). ADD a one-line intro-price NOTE in
|
|
113
|
+
the dashboard pricing display / label ("Sonnet 5 intro $2/$10 through Aug 31 2026") - display only,
|
|
114
|
+
not a computed rate. Update labels "Sonnet (latest)" -> "Sonnet 5".
|
|
115
|
+
- codex gpt-5.3-codex $1.50/$12: UNVERIFIED external number. WebFetch OpenAI pricing to confirm or leave
|
|
116
|
+
with a "verify" note; do not propagate a guess as fact.
|
|
117
|
+
- Confirm gemini fully absent from pricing (deprecated v7.5.18).
|
|
118
|
+
- Parity tests: update `tests/test-model-override.sh` expected values (dev tier now sonnet). Update
|
|
119
|
+
dashboard estimator expected quotes. Any Bun parity test for the resolver. Run the parity matrix.
|
|
120
|
+
|
|
121
|
+
## 5. Test / parity changes enumerated
|
|
122
|
+
- tests/test-model-override.sh: dev-tier resolution + LOKI_MAX_TIER=sonnet clamp expectations flip.
|
|
123
|
+
- Dashboard estimator parity test: per-iteration quote changes (opus->sonnet dev cost).
|
|
124
|
+
- New: a test asserting the trust-gate reviewer dispatch includes `--model opus` on BOTH routes
|
|
125
|
+
(grep/behavioral) - locks the moat guarantee so a future edit can't silently un-pin.
|
|
126
|
+
- New: start_build with model param writes a valid override; invalid model rejected.
|
|
127
|
+
- CLI-invariance: existing `loki verify` / `loki start` still run (no crash); default model differs
|
|
128
|
+
(that IS the intended change - do NOT assert byte-identical default output here).
|
|
129
|
+
|
|
130
|
+
## 6. Calibration protocol (CEO gate - before ship)
|
|
131
|
+
- Pick 5-10 representative specs from benchmarks/ or internal fixtures spanning easy->hard.
|
|
132
|
+
- Run each on Sonnet-default vs current Opus-default (real model calls; NOT in CI - documented manual
|
|
133
|
+
step). Record: iterations-to-council-APPROVE, BLOCK count, wall-clock, and NET cost (builder tokens +
|
|
134
|
+
reviewer tokens, so the "~40% cheaper" claim is verified NET, not just on the builder tier). Append to
|
|
135
|
+
a calibration log under artifacts/sonnet5-calibration/.
|
|
136
|
+
- SHIP criterion: Sonnet-default does not materially increase iterations-to-APPROVE or BLOCK-rate on
|
|
137
|
+
hard specs AND the net cost genuinely drops. If iterations/BLOCK regress: keep the pre-built escape
|
|
138
|
+
hatch (planning->opus one-line revert; dev stays sonnet) and re-measure. Never silently keep Opus -
|
|
139
|
+
make the escalation legible. If net cost does NOT drop as claimed, correct the marketing claim to the
|
|
140
|
+
measured number - never ship an unverified "~40% cheaper".
|
|
141
|
+
|
|
142
|
+
## 7. Release (per CLAUDE.md)
|
|
143
|
+
- Version bump all files (MINOR). Loud CHANGELOG entry: "Default execution model changed Opus -> Sonnet 5.
|
|
144
|
+
~40% cheaper builds. Trust-gate reviewers pinned to Opus (deterministic verdict). Override any model
|
|
145
|
+
from the dashboard." Never claim "same accuracy" (no controlled study).
|
|
146
|
+
- bash scripts/local-ci.sh (must be green). Council 3/3 (2 Opus + 1 Sonnet reviewers that RUN tests).
|
|
147
|
+
- Rebuild dashboard frontend (Lane D). Merge worktree to main, tag via CI, verify 4 channels.
|
|
148
|
+
- NEVER run a loki build from the worktree (self-delete trap). Verify engine changes by function
|
|
149
|
+
extraction to scratch repos.
|
|
150
|
+
|
|
151
|
+
## 8. Open questions for the founder (do NOT block starting)
|
|
152
|
+
- Q1: Should PLANNING tier also default to Sonnet (full flatten), or stay Opus (architecture quality)?
|
|
153
|
+
Plan flattens both per plain reading; Lane A makes planning a one-line revert either way.
|
|
154
|
+
- Q2: "advisor" scope - is it the completion-council override judge (recommended, minimal) or a
|
|
155
|
+
distinct advisory role you envision elsewhere?
|
|
156
|
+
- Q3: Sonnet 5 intro pricing - display-only note (planned) vs actually bill the $2/$10 in estimates
|
|
157
|
+
(rejected: date-expiry bug risk). Confirm display-only is acceptable.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema_version": 1,
|
|
3
3
|
"_comment": "Rolling pricing table consumed by loki-ts/src/runner/budget.ts. Update this file when Anthropic / OpenAI / others publish new prices; no code change required. Pricing is USD per 1 million tokens. Aliases (opus/sonnet/haiku) point to the latest model of that family per providers/model_catalog.json.",
|
|
4
|
-
"_updated": "2026-
|
|
5
|
-
"_source": "https://www.anthropic.com/pricing + provider docs",
|
|
4
|
+
"_updated": "2026-06-30",
|
|
5
|
+
"_source": "https://www.anthropic.com/pricing + provider docs. sonnet=claude-sonnet-5 (list $3/$15; intro $2/$10 through 2026-08-31). opus=claude-opus-4-8. codex=gpt-5.3-codex standard tier.",
|
|
6
6
|
"pricing": {
|
|
7
7
|
"fable": { "input": 10.0, "output": 50.0 },
|
|
8
8
|
"opus": { "input": 5.0, "output": 25.0 },
|
|
9
9
|
"sonnet": { "input": 3.0, "output": 15.0 },
|
|
10
10
|
"haiku": { "input": 1.0, "output": 5.0 },
|
|
11
|
-
"gpt-5.3-codex": { "input": 1.
|
|
11
|
+
"gpt-5.3-codex": { "input": 1.75, "output": 14.0 }
|
|
12
12
|
}
|
|
13
13
|
}
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)z8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:K8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var y1={};b(y1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as t,dirname as i$}from"path";import{fileURLToPath as q8}from"url";import{existsSync as E$}from"fs";import{homedir as J8}from"os";function V8(){let $=h1;for(let Q=0;Q<6;Q++){if(E$(t($,"VERSION"))&&E$(t($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return t(h1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(E$(t(Q,"VERSION"))&&E$(t(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function P(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(J8(),".loki")}var h1,h;var C=L(()=>{h1=i$(q8(import.meta.url));h=V8()});import{readFileSync as W8}from"fs";import{resolve as U8,dirname as H8}from"path";import{fileURLToPath as G8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.
|
|
2
|
+
var z8=Object.defineProperty;var X8=($)=>$;function K8($,Q){this[$]=X8.bind(null,Q)}var b=($,Q)=>{for(var Z in Q)z8($,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:K8.bind(Q,Z)})};var L=($,Q)=>()=>($&&(Q=$($=0)),Q);var J$=import.meta.require;var y1={};b(y1,{lokiDir:()=>P,homeLokiDir:()=>T$,findRepoRootForVersion:()=>e$,REPO_ROOT:()=>h});import{resolve as t,dirname as i$}from"path";import{fileURLToPath as q8}from"url";import{existsSync as E$}from"fs";import{homedir as J8}from"os";function V8(){let $=h1;for(let Q=0;Q<6;Q++){if(E$(t($,"VERSION"))&&E$(t($,"autonomy/run.sh")))return $;let Z=i$($);if(Z===$)break;$=Z}return t(h1,"..","..","..")}function e$($){let Q=$;for(let Z=0;Z<6;Z++){if(E$(t(Q,"VERSION"))&&E$(t(Q,"autonomy/run.sh")))return Q;let z=i$(Q);if(z===Q)break;Q=z}return t($,"..","..","..")}function P(){return process.env.LOKI_DIR??t(process.cwd(),".loki")}function T$(){return t(J8(),".loki")}var h1,h;var C=L(()=>{h1=i$(q8(import.meta.url));h=V8()});import{readFileSync as W8}from"fs";import{resolve as U8,dirname as H8}from"path";import{fileURLToPath as G8}from"url";function N$(){if(Q$!==null)return Q$;let $="7.104.0";if(typeof $==="string"&&$.length>0)return Q$=$,Q$;try{let Q=H8(G8(import.meta.url)),Z=e$(Q);Q$=W8(U8(Z,"VERSION"),"utf-8").trim()}catch{Q$="unknown"}return Q$}var Q$=null;var $1=L(()=>{C()});var u1={};b(u1,{runOrThrow:()=>x8,run:()=>F,readStreamCapped:()=>f1,commandVersion:()=>N8,commandExists:()=>f,ShellError:()=>Q1,MAX_STDOUT_BYTES:()=>m1});async function f1($,Q=m1){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 F($,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([f1(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 x8($,Q={}){let Z=await F($,Q);if(Z.exitCode!==0)throw new Q1(`command failed (${Z.exitCode}): ${$.join(" ")}`,Z.exitCode,Z.stdout,Z.stderr);return Z}async function f($){let Q=E8($),Z=await F(["sh","-c",`command -v ${Q}`],{timeoutMs:5000});if(Z.exitCode===0)return Z.stdout.trim()||null;return null}function E8($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function N8($,Q="--version"){if(!await f($))return null;let z=await F([$,Q],{timeoutMs:5000});if(z.exitCode!==0)return null;return((z.stdout||z.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var m1=16777216,Q1;var d=L(()=>{Q1=class Q1 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 S8?"":$}var S8,T,S,_,lZ,I,k,y,J;var c=L(()=>{S8=(process.env.NO_COLOR??"").length>0;T=r("\x1B[0;31m"),S=r("\x1B[0;32m"),_=r("\x1B[1;33m"),lZ=r("\x1B[0;34m"),I=r("\x1B[0;36m"),k=r("\x1B[1m"),y=r("\x1B[2m"),J=r("\x1B[0m")});import{existsSync as u8}from"fs";async function Z$(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(u8($))return A$=$,$;let Q=await f("python3.12");if(Q)return A$=Q,Q;let Z=await f("python3");return A$=Z,Z}async function z$($,Q={}){let Z=await Z$();if(!Z)return{stdout:"",stderr:"python3 not found",exitCode:127};return F([Z,"-c",$],Q)}var A$;var V$=L(()=>{d()});var q0={};b(q0,{runStatus:()=>W3});import{existsSync as v,readFileSync as U$,readdirSync as i1,statSync as e1}from"fs";import{resolve as D,basename as $3}from"path";import{homedir as Q3}from"os";function $0($){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 Q0($,Q,Z){if(Q===0)return null;let z=Math.trunc($*100/Q),X=Math.trunc($*D$/Q);if(X>D$)X=D$;let q=D$-X,K=S;if(z>=80)K=T;else if(z>=50)K=_;let W="=".repeat(Math.max(0,X))+" ".repeat(Math.max(0,q)),V=$0($),U=$0(Q);return` ${k}${Z}${J} ${K}[${W}]${J} ${z}% (${V} / ${U})`}async function z3(){if(await f("jq"))return!0;return process.stdout.write(`${T}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)
|
|
@@ -802,4 +802,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
802
802
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
803
803
|
`),process.stderr.write(Z8),2}}r1();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var FZ=await jZ(Bun.argv.slice(2));process.exit(FZ);
|
|
804
804
|
|
|
805
|
-
//# debugId=
|
|
805
|
+
//# debugId=A8E5D35BB99B83EF64756E2164756E21
|
package/mcp/__init__.py
CHANGED
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.
|
|
4
|
+
"version": "7.104.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",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
".claude-plugin/marketplace.json",
|
|
72
72
|
"autonomy/",
|
|
73
73
|
"providers/",
|
|
74
|
+
"vendor/autonomi-verify/",
|
|
74
75
|
"agents/",
|
|
75
76
|
"skills/",
|
|
76
77
|
"references/",
|
|
@@ -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.
|
|
5
|
+
"version": "7.104.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",
|
package/providers/claude.sh
CHANGED
|
@@ -52,8 +52,13 @@ PROVIDER_MAX_PARALLEL=10
|
|
|
52
52
|
# sonnet -> latest Sonnet (e.g. claude-sonnet-4-6)
|
|
53
53
|
# haiku -> latest Haiku (e.g. claude-haiku-4-5)
|
|
54
54
|
# Override per tier with LOKI_CLAUDE_MODEL_PLANNING, _DEVELOPMENT, _FAST.
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
# v7.104.0: Sonnet 5 is the default execution model (was opus for planning+dev).
|
|
56
|
+
# Cheaper + faster near-frontier builder; the trust gate is unchanged by default
|
|
57
|
+
# and a strong Opus judge is opt-in via LOKI_ADVISOR_MODEL (see _dispatch_reviewer).
|
|
58
|
+
# To restore Opus execution: LOKI_CLAUDE_MODEL_DEVELOPMENT=opus (and _PLANNING=opus),
|
|
59
|
+
# or the dashboard "set all to opus". Planning-on-Opus is a one-line revert here.
|
|
60
|
+
CLAUDE_DEFAULT_PLANNING="sonnet"
|
|
61
|
+
CLAUDE_DEFAULT_DEVELOPMENT="sonnet"
|
|
57
62
|
CLAUDE_DEFAULT_FAST="sonnet"
|
|
58
63
|
|
|
59
64
|
if [ "${LOKI_ALLOW_HAIKU:-false}" = "true" ]; then
|
|
@@ -379,13 +384,14 @@ loki_apply_max_tier_clamp() {
|
|
|
379
384
|
# Resolves a capability tier to a concrete model name at runtime.
|
|
380
385
|
# Respects LOKI_MAX_TIER to cap cost via loki_apply_max_tier_clamp. NOTE the
|
|
381
386
|
# ceiling clamps DOWN to the provider's configured tier model, not to the alias
|
|
382
|
-
# named by the cap
|
|
383
|
-
#
|
|
384
|
-
# PROVIDER_MODEL_DEVELOPMENT, which is
|
|
385
|
-
# ceiling
|
|
386
|
-
#
|
|
387
|
-
#
|
|
388
|
-
#
|
|
387
|
+
# named by the cap. As of v7.104.0 the stock config is
|
|
388
|
+
# CLAUDE_DEFAULT_DEVELOPMENT=sonnet, so LOKI_MAX_TIER=sonnet resolves
|
|
389
|
+
# planning/fable DOWN to PROVIDER_MODEL_DEVELOPMENT, which is now sonnet - the
|
|
390
|
+
# ceiling genuinely pins sonnet with the stock config (previously it clamped to
|
|
391
|
+
# opus because dev defaulted to opus). To cap harder, LOKI_MAX_TIER=haiku pins
|
|
392
|
+
# everything to PROVIDER_MODEL_FAST. This is intentional and is mirrored
|
|
393
|
+
# byte-for-byte by the dashboard/estimator ports (parity-locked in
|
|
394
|
+
# tests/test-model-override.sh).
|
|
389
395
|
# Capability aliases: "best" -> planning tier, "fast" -> fast tier, "balanced" -> development tier
|
|
390
396
|
resolve_model_for_tier() {
|
|
391
397
|
local tier="$1"
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Canonical model catalog. Update this single file when a provider ships a new model. Providers/web-app/docs read from here.",
|
|
3
3
|
"schema_version": 1,
|
|
4
|
-
"updated": "2026-
|
|
4
|
+
"updated": "2026-06-30",
|
|
5
5
|
"providers": {
|
|
6
6
|
"claude": {
|
|
7
|
-
"latest_planning": "claude-opus-4-
|
|
8
|
-
"latest_development": "claude-
|
|
9
|
-
"latest_fast": "claude-sonnet-
|
|
7
|
+
"latest_planning": "claude-opus-4-8",
|
|
8
|
+
"latest_development": "claude-sonnet-5",
|
|
9
|
+
"latest_fast": "claude-sonnet-5",
|
|
10
10
|
"cli_aliases": {
|
|
11
11
|
"fable": "claude-fable-5",
|
|
12
|
-
"opus": "claude-opus-4-
|
|
13
|
-
"sonnet": "claude-sonnet-
|
|
12
|
+
"opus": "claude-opus-4-8",
|
|
13
|
+
"sonnet": "claude-sonnet-5",
|
|
14
14
|
"haiku": "claude-haiku-4-5"
|
|
15
15
|
},
|
|
16
16
|
"models": [
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"notes": "Top-tier advisory model. Pricing 2x Opus ($10/$50 per MTok). Doc-supported for architecture/root-cause; opt-in only (cost). Refuses cyber content, so NOT used for security review."
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
"id": "claude-opus-4-
|
|
26
|
+
"id": "claude-opus-4-8",
|
|
27
27
|
"alias": "opus",
|
|
28
28
|
"tier": "planning",
|
|
29
29
|
"context_window": 1000000,
|
|
@@ -31,11 +31,12 @@
|
|
|
31
31
|
"notes": "Adaptive thinking, xhigh effort for agentic coding"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"id": "claude-sonnet-
|
|
34
|
+
"id": "claude-sonnet-5",
|
|
35
35
|
"alias": "sonnet",
|
|
36
36
|
"tier": "development",
|
|
37
37
|
"context_window": 1000000,
|
|
38
|
-
"max_output": 64000
|
|
38
|
+
"max_output": 64000,
|
|
39
|
+
"notes": "Default execution model as of v7.104.0. Intro price $2/$10 per MTok through 2026-08-31; list price $3/$15 per MTok."
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
"id": "claude-haiku-4-5",
|
|
@@ -58,22 +59,22 @@
|
|
|
58
59
|
"notes": "Codex uses a single model with effort level (xhigh/high/low) for tier differentiation"
|
|
59
60
|
},
|
|
60
61
|
"cline": {
|
|
61
|
-
"latest_planning": "claude-opus-4-
|
|
62
|
-
"latest_development": "claude-
|
|
63
|
-
"latest_fast": "claude-sonnet-
|
|
62
|
+
"latest_planning": "claude-opus-4-8",
|
|
63
|
+
"latest_development": "claude-sonnet-5",
|
|
64
|
+
"latest_fast": "claude-sonnet-5",
|
|
64
65
|
"models": [
|
|
65
|
-
{ "id": "claude-opus-4-
|
|
66
|
-
{ "id": "claude-sonnet-
|
|
66
|
+
{ "id": "claude-opus-4-8", "tier": "planning" },
|
|
67
|
+
{ "id": "claude-sonnet-5", "tier": "development" },
|
|
67
68
|
{ "id": "gpt-4.1", "tier": "development" }
|
|
68
69
|
]
|
|
69
70
|
},
|
|
70
71
|
"aider": {
|
|
71
|
-
"latest_planning": "claude-opus-4-
|
|
72
|
-
"latest_development": "claude-
|
|
73
|
-
"latest_fast": "claude-sonnet-
|
|
72
|
+
"latest_planning": "claude-opus-4-8",
|
|
73
|
+
"latest_development": "claude-sonnet-5",
|
|
74
|
+
"latest_fast": "claude-sonnet-5",
|
|
74
75
|
"models": [
|
|
75
|
-
{ "id": "claude-opus-4-
|
|
76
|
-
{ "id": "claude-sonnet-
|
|
76
|
+
{ "id": "claude-opus-4-8", "tier": "planning" },
|
|
77
|
+
{ "id": "claude-sonnet-5", "tier": "development" },
|
|
77
78
|
{ "id": "gpt-4.1", "tier": "development" },
|
|
78
79
|
{ "id": "ollama_chat/deepseek-coder", "tier": "fast" }
|
|
79
80
|
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
AUTONOMI VERIFY - COMMERCIAL LICENSE NOTICE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Autonomi. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This directory contains a pre-built, dependency-free bundle ("the Bundle") of
|
|
6
|
+
the Autonomi Verify engine. The Bundle is proprietary commercial software of
|
|
7
|
+
Autonomi and is provided to you ONLY as an embedded component of Loki Mode.
|
|
8
|
+
|
|
9
|
+
This Commercial License Notice is SEPARATE FROM and DISTINCT FROM the Business
|
|
10
|
+
Source License 1.1 (BUSL-1.1) that governs the rest of the Loki Mode
|
|
11
|
+
repository. The BUSL-1.1 terms do NOT apply to the Bundle. The Bundle is not
|
|
12
|
+
open source.
|
|
13
|
+
|
|
14
|
+
PERMITTED USE
|
|
15
|
+
You may execute the Bundle solely as invoked by Loki Mode for the purpose of
|
|
16
|
+
verifying your own changes (the `loki verify --hosted` path). No other use is
|
|
17
|
+
granted.
|
|
18
|
+
|
|
19
|
+
RESTRICTIONS
|
|
20
|
+
Except as expressly permitted above, you may NOT:
|
|
21
|
+
- copy, redistribute, sublicense, sell, or host the Bundle as a service;
|
|
22
|
+
- reverse engineer, decompile, or disassemble the Bundle, or attempt to
|
|
23
|
+
derive its source code, except to the limited extent applicable law
|
|
24
|
+
expressly permits despite this restriction;
|
|
25
|
+
- remove or alter this notice.
|
|
26
|
+
|
|
27
|
+
NO SOURCE GRANT
|
|
28
|
+
The source code of the Autonomi Verify engine is NOT included in this
|
|
29
|
+
repository and is NOT licensed to you. Only the built Bundle is distributed
|
|
30
|
+
here.
|
|
31
|
+
|
|
32
|
+
NO WARRANTY
|
|
33
|
+
THE BUNDLE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
36
|
+
AUTONOMI BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM,
|
|
37
|
+
OUT OF, OR IN CONNECTION WITH THE BUNDLE OR ITS USE.
|
|
38
|
+
|
|
39
|
+
For licensing inquiries beyond the permitted use above, contact Autonomi.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Autonomi Verify (embedded bundle)
|
|
2
|
+
|
|
3
|
+
This directory contains a single pre-built, dependency-free JavaScript bundle of
|
|
4
|
+
the Autonomi Verify deterministic verification engine.
|
|
5
|
+
|
|
6
|
+
- `embed.js` - the bundled engine (runtime: `bun`). Built from the PRIVATE
|
|
7
|
+
Autonomi Verify source repository; only the built artifact is committed here.
|
|
8
|
+
The TypeScript source is NOT included and is NOT part of this repository.
|
|
9
|
+
- `LICENSE` - the COMMERCIAL license notice covering `embed.js`. This is
|
|
10
|
+
distinct from the Business Source License 1.1 that governs the rest of
|
|
11
|
+
Loki Mode. `embed.js` is proprietary and is not open source.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
`embed.js` observes a local git working directory read-only and runs the
|
|
16
|
+
Autonomi Verify evidence gate, printing the verdict fields as one JSON object on
|
|
17
|
+
stdout. It performs NO network access and NEVER executes the project's tests
|
|
18
|
+
(that is reserved for the hosted/sandboxed Phase 2 surface).
|
|
19
|
+
|
|
20
|
+
Invocation contract:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
bun vendor/autonomi-verify/embed.js --dir <path> [--base <ref>] [--head <ref>]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Output (stdout, on a produced verdict, exit 0):
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"engine": "autonomi-verify",
|
|
31
|
+
"engine_version": "<version>",
|
|
32
|
+
"verified": true,
|
|
33
|
+
"inconclusive": false,
|
|
34
|
+
"inconclusive_reason": null,
|
|
35
|
+
"evidence": {
|
|
36
|
+
"diff_nonempty": true,
|
|
37
|
+
"diff_files_changed": 1,
|
|
38
|
+
"diff_base_sha": "<sha>",
|
|
39
|
+
"tests_ran": false,
|
|
40
|
+
"tests_passed": true,
|
|
41
|
+
"test_runner": "none"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
On a genuine observation failure (git missing, path absent) it exits nonzero and
|
|
47
|
+
prints nothing parseable on stdout. The caller (`loki verify --hosted`) treats a
|
|
48
|
+
nonzero exit, a missing bundle, or a missing `bun` as "engine unusable" and
|
|
49
|
+
falls open to the deterministic bash verdict. It never turns an unusable engine
|
|
50
|
+
into a silent pass.
|
|
51
|
+
|
|
52
|
+
## How it is used by `loki verify`
|
|
53
|
+
|
|
54
|
+
`loki verify` (no flags) does NOT touch this bundle and is byte-identical to its
|
|
55
|
+
prior behavior. Only the opt-in `loki verify --hosted` path probes for `bun` and
|
|
56
|
+
this bundle and, when both are present, folds the engine's verdict fields into
|
|
57
|
+
`evidence.json` under a `hosted` key. The bash deterministic verdict remains
|
|
58
|
+
authoritative for the exit code.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
function D(j){let z=new Set;for(let A of[j.committed,j.unstaged,j.staged,j.untracked])for(let J of A){if(J==="")continue;if(/^\.loki\//.test(J))continue;z.add(J)}return z.size}function Z(j){let z=!1,A=0,J=!1,K="";if(!j.diff.is_git_repo)J=!0,K="no_git_repo";else if(!j.diff.base_sha)J=!0,K="no_run_start_sha";else if(A=D(j.diff.sources),A===0)z=!0;let X=!1,H="none",$=!0,C=!1,Y="";if(j.tests!==null){let L=j.tests.runner??"none",G=j.tests.pass??!0;if(H=L,L==="none")$=!0,C=!0,Y="no_test_runner";else if(G===!1)$=!1,X=!0;else $=!0}else H="none",$=!0,C=!0,Y="no_test_results";let U=z||X,W=null;if(U)if(z&&X)W="empty_diff_and_tests_red";else if(z)W="empty_diff";else W="tests_red";return{verdict:U?"block":"pass",gate_return_code:U?1:0,block_reason:W,diff:{ok:!z,base_sha:j.diff.base_sha??"",files_changed:A,inconclusive:J,inconclusive_reason:K},tests:{ok:!X,runner:H,pass:$,inconclusive:C,inconclusive_reason:Y}}}function q(j){return{diff_nonempty:j.diff.files_changed>0,diff_files_changed:j.diff.files_changed,diff_base_sha:j.diff.base_sha,tests_ran:j.tests.runner!=="none"&&!j.tests.inconclusive,tests_passed:j.tests.pass,test_runner:j.tests.runner}}function B(j){switch(j){case"no_git_repo":return"no_git_repo";case"no_run_start_sha":case"no_base_sha":return"no_base_sha";case"":return null;default:return null}}import{spawnSync as S}from"node:child_process";import{existsSync as N,statSync as V}from"node:fs";var k="unsigned:phase2-signing-pending";async function T(j,z){if(!z)throw Error("verifyCompletion: sandbox observation is Phase 2; supply a VerifyContext with pre-observed evidence to run the engine");let A=Z(z.observed),J=q(A),K=A.diff.inconclusive,X=B(A.diff.inconclusive_reason),H=A.verdict==="pass"&&!K;if(K&&j.options?.fail_on_inconclusive)H=!1;return{...{verification_id:z.verification_id??crypto.randomUUID(),verified:H,evidence:J,council_verdict:{ran:!1,verdict:null,reviewers:[]},cost_honesty_check:{ran:!1,quoted_model:null,dispatched_model:null,honest:null},inconclusive:K,inconclusive_reason:X,created_at:z.created_at??new Date().toISOString()},signature:k}}class Q extends Error{constructor(j){super(j);this.name="VerifyInputError"}}function x(j){return typeof j.dir==="string"}function M(j,z){let A=S("git",j,{cwd:z,encoding:"utf8"});if(A.error){let J=A.error;if(J.code==="ENOENT")throw new Q("cannot observe evidence: the `git` executable was not found on PATH");throw new Q(`cannot observe evidence: git ${j.join(" ")} failed: ${J.message}`)}return{status:A.status??1,stdout:(A.stdout||"").trim(),stderr:(A.stderr||"").trim()}}function P(j){if(!j)return[];return j.split("\x00").filter((z)=>z.length>0)}function h(j){let z=j.dir;if(!N(z))throw new Q(`cannot observe evidence: path does not exist: ${z}`);if(!V(z).isDirectory())throw new Q(`cannot observe evidence: not a directory: ${z}`);let A={committed:[],unstaged:[],staged:[],untracked:[]},J=M(["rev-parse","--is-inside-work-tree"],z);if(J.status!==0||J.stdout!=="true")return{is_git_repo:!1,base_sha:null,sources:A};if(!j.base)return{is_git_repo:!0,base_sha:null,sources:A};let K=M(["rev-parse","--verify","--quiet",j.base],z);if(K.status!==0||!K.stdout)return{is_git_repo:!0,base_sha:null,sources:A};let X=K.stdout,H=j.head??"HEAD",$=M(["diff","--name-only","-z",`${X}..${H}`],z);if($.status!==0)throw new Q(`cannot observe evidence: git diff ${X}..${H} failed: ${$.stderr}`);let C=P($.stdout),Y=M(["diff","--name-only","-z","--cached"],z),U=Y.status===0?P(Y.stdout):[],W=M(["diff","--name-only","-z"],z),L=W.status===0?P(W.stdout):[],G=M(["ls-files","--others","--exclude-standard","-z"],z),_=G.status===0?P(G.stdout):[];return{is_git_repo:!0,base_sha:X,sources:{committed:C,staged:U,unstaged:L,untracked:_}}}async function O(j){let z,A;if(x(j))z={diff:h(j),tests:j.tests??null},A=j.repo??"local";else{if(!j.observed)throw new Q("verify: provide either `observed` (pre-observed evidence) or `dir` (a local git working directory to observe)");z=j.observed,A=j.repo??"preobserved"}let J={repo:A,base_sha:z.diff.base_sha??"",options:j.options};return T(J,{observed:z,verification_id:j.verification_id,created_at:j.created_at})}function m(j){let z={};for(let A=0;A<j.length;A++){let J=j[A];if(J==="--dir")z.dir=j[++A];else if(J==="--base")z.base=j[++A];else if(J==="--head")z.head=j[++A];else if(J==="--version"||J==="-v")process.stdout.write(w+`
|
|
4
|
+
`),process.exit(0);else throw Error(`unknown argument: ${J}`)}if(!z.dir)throw Error("--dir is required");return z}var w="1.0.0";async function y(){let j;try{j=m(process.argv.slice(2))}catch(z){return process.stderr.write(`[embed] ${z.message}
|
|
5
|
+
`),2}try{let z=await O({dir:j.dir,base:j.base,head:j.head}),A={engine:"autonomi-verify",engine_version:w,verified:z.verified,inconclusive:z.inconclusive,inconclusive_reason:z.inconclusive_reason,evidence:{diff_nonempty:z.evidence.diff_nonempty,diff_files_changed:z.evidence.diff_files_changed,diff_base_sha:z.evidence.diff_base_sha,tests_ran:z.evidence.tests_ran,tests_passed:z.evidence.tests_passed,test_runner:z.evidence.test_runner}};return process.stdout.write(JSON.stringify(A)+`
|
|
6
|
+
`),0}catch(z){let A=z instanceof Q?"input":"error";return process.stderr.write(`[embed][${A}] ${z.message}
|
|
7
|
+
`),1}}y().then((j)=>process.exit(j),(j)=>{process.stderr.write(`[embed][fatal] ${j.message}
|
|
8
|
+
`),process.exit(1)});
|