loki-mode 7.129.5 → 8.0.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/README.md +81 -5
- package/SKILL.md +66 -5
- package/VERSION +1 -1
- package/autonomy/app-runner.sh +37 -0
- package/autonomy/completion-council.sh +862 -28
- package/autonomy/council-v2.sh +39 -0
- package/autonomy/crash.sh +3 -2
- package/autonomy/grill.sh +42 -0
- package/autonomy/hooks/validate-bash.sh +301 -4
- package/autonomy/lib/cockpit-render.sh +8 -2
- package/autonomy/lib/cr-rematerialize.py +101 -4
- package/autonomy/lib/deadline.py +957 -0
- package/autonomy/lib/dependency-setup.sh +205 -0
- package/autonomy/lib/done-recognition.sh +45 -0
- package/autonomy/lib/efficiency_cost.py +13 -6
- package/autonomy/lib/no_mock_scan.py +793 -0
- package/autonomy/lib/prd-enrich.sh +42 -0
- package/autonomy/lib/proof-analytics-props.py +69 -0
- package/autonomy/lib/proof-generator.py +282 -95
- package/autonomy/lib/proof-template.html +15 -12
- package/autonomy/lib/proof-verify.py +151 -102
- package/autonomy/lib/requirements_contract.py +848 -0
- package/autonomy/lib/sdk-mode.sh +103 -0
- package/autonomy/lib/secret-scan.sh +139 -0
- package/autonomy/lib/spec-expand.sh +208 -0
- package/autonomy/lib/tree_digest.py +266 -0
- package/autonomy/lib/voter-agents.sh +58 -8
- package/autonomy/lib/workspace_diff.py +124 -0
- package/autonomy/loki +189 -17
- package/autonomy/playwright-verify.sh +501 -0
- package/autonomy/prd-checklist.sh +17 -8
- package/autonomy/provider-offer.sh +111 -0
- package/autonomy/run.sh +4417 -676
- package/autonomy/sandbox.sh +42 -0
- package/autonomy/spec-interrogation.sh +148 -5
- package/autonomy/spec.sh +118 -1
- package/autonomy/telemetry.sh +133 -7
- package/autonomy/verify.sh +107 -0
- package/bin/loki +110 -3
- package/completions/_loki +10 -0
- package/completions/loki.bash +1 -1
- package/dashboard/__init__.py +1 -1
- package/dashboard/audit.py +96 -7
- package/dashboard/build_supervisor.py +1619 -0
- package/dashboard/control.py +8 -0
- package/dashboard/prompt_optimizer.py +7 -0
- package/dashboard/server.py +577 -22
- package/dashboard/static/trust.html +1 -1
- package/docs/ARCHITECTURE-OVERVIEW.md +207 -0
- package/docs/AUTONOMI-ECOSYSTEM.md +107 -0
- package/docs/INSTALLATION.md +19 -2
- package/docs/MODEL-EQUIVALENCE-HARNESS-PLAN.md +70 -0
- package/docs/PLANS-INDEX.md +33 -0
- package/docs/PRIVACY.md +29 -1
- package/docs/SIGNED-RECEIPTS.md +102 -0
- package/docs/SONNET5-DEFAULT-PLAN.md +1 -1
- package/docs/V8-ACCEPTANCE-TRIAGE-2026-07-24.md +114 -0
- package/docs/V8-AGENT-SDK-PLAN.md +692 -0
- package/docs/V8-COMPLEXITY-AUDIT-2026-07-24.md +45 -0
- package/docs/V8-MAJOR-RELEASE-PLAN.md +137 -0
- package/docs/V8-OVERNIGHT-PLAN-2026-07-25.md +82 -0
- package/docs/V8-RUNTIME-TRUTH-2026-07-25.md +232 -0
- package/docs/V8-SDK-RESEARCH-RAW.md +129 -0
- package/docs/alternative-installations.md +4 -4
- package/loki-ts/dist/loki.js +674 -285
- package/loki-ts/package.json +2 -0
- package/mcp/__init__.py +1 -1
- package/package.json +7 -6
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/claude.sh +75 -0
- package/providers/codex.sh +85 -13
- package/references/sdk-mode.md +106 -0
- package/skills/model-selection.md +1 -1
- package/skills/quality-gates.md +22 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
# Prepare deterministic Node dependencies for Loki-owned verification gates.
|
|
4
|
+
# The model may produce a valid app without installing host dependencies because
|
|
5
|
+
# hosted previews use an isolated Docker volume. Verification must not mistake a
|
|
6
|
+
# missing host node_modules directory for an application defect.
|
|
7
|
+
|
|
8
|
+
loki_dependency_input_sha256() {
|
|
9
|
+
local tree="$1"
|
|
10
|
+
python3 - "$tree/package.json" "$tree/package-lock.json" <<'PYEOF'
|
|
11
|
+
import hashlib
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
digest = hashlib.sha256()
|
|
15
|
+
for path in sys.argv[1:]:
|
|
16
|
+
with open(path, "rb") as handle:
|
|
17
|
+
digest.update(handle.read())
|
|
18
|
+
digest.update(b"\0")
|
|
19
|
+
print(digest.hexdigest())
|
|
20
|
+
PYEOF
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
loki_dependency_install_fingerprint() {
|
|
24
|
+
local tree="$1"
|
|
25
|
+
python3 - "$tree" <<'PYEOF'
|
|
26
|
+
import hashlib
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
import pathlib
|
|
30
|
+
import subprocess
|
|
31
|
+
import sys
|
|
32
|
+
|
|
33
|
+
tree = pathlib.Path(sys.argv[1])
|
|
34
|
+
hidden_lock = tree / "node_modules" / ".package-lock.json"
|
|
35
|
+
try:
|
|
36
|
+
raw = hidden_lock.read_bytes()
|
|
37
|
+
packages = json.loads(raw).get("packages")
|
|
38
|
+
if not isinstance(packages, dict):
|
|
39
|
+
raise ValueError("missing packages map")
|
|
40
|
+
for name in packages:
|
|
41
|
+
path = pathlib.PurePosixPath(name)
|
|
42
|
+
if not name or path.is_absolute() or path.parts[0] != "node_modules" \
|
|
43
|
+
or any(part in ("", ".", "..") for part in path.parts):
|
|
44
|
+
raise ValueError("invalid installed package path")
|
|
45
|
+
if not os.path.lexists(tree.joinpath(*path.parts)):
|
|
46
|
+
raise ValueError("missing installed package")
|
|
47
|
+
print("lock:" + hashlib.sha256(raw).hexdigest())
|
|
48
|
+
except FileNotFoundError:
|
|
49
|
+
result = subprocess.run(
|
|
50
|
+
["npm", "ls", "--all", "--json"], cwd=tree,
|
|
51
|
+
stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=False,
|
|
52
|
+
)
|
|
53
|
+
if result.returncode:
|
|
54
|
+
raise SystemExit(1)
|
|
55
|
+
listing = json.loads(result.stdout)
|
|
56
|
+
canonical = json.dumps(listing, sort_keys=True, separators=(",", ":")).encode()
|
|
57
|
+
print("tree:" + hashlib.sha256(canonical).hexdigest())
|
|
58
|
+
except (OSError, TypeError, ValueError, json.JSONDecodeError):
|
|
59
|
+
raise SystemExit(1)
|
|
60
|
+
PYEOF
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
loki_publish_dependency_marker() {
|
|
64
|
+
local marker_file="$1" input_sha="$2" install_sha="$3" temporary
|
|
65
|
+
temporary="$(mktemp "${marker_file}.tmp.XXXXXX")" || return 1
|
|
66
|
+
if ! printf 'v1 %s %s\n' "$input_sha" "$install_sha" > "$temporary" \
|
|
67
|
+
|| ! mv -f "$temporary" "$marker_file"; then
|
|
68
|
+
rm -f "$temporary" 2>/dev/null || true
|
|
69
|
+
return 1
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
loki_write_dependency_setup_result() {
|
|
74
|
+
local output="$1" status="$2" command="$3" exit_code="$4" input_sha="$5"
|
|
75
|
+
_LOKI_DEP_OUT="$output" \
|
|
76
|
+
_LOKI_DEP_STATUS="$status" \
|
|
77
|
+
_LOKI_DEP_COMMAND="$command" \
|
|
78
|
+
_LOKI_DEP_EXIT="$exit_code" \
|
|
79
|
+
_LOKI_DEP_SHA="$input_sha" \
|
|
80
|
+
python3 - <<'PYEOF'
|
|
81
|
+
import json
|
|
82
|
+
import os
|
|
83
|
+
import tempfile
|
|
84
|
+
from datetime import datetime, timezone
|
|
85
|
+
|
|
86
|
+
target = os.environ["_LOKI_DEP_OUT"]
|
|
87
|
+
raw_exit = os.environ.get("_LOKI_DEP_EXIT", "")
|
|
88
|
+
record = {
|
|
89
|
+
"timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
90
|
+
"status": os.environ.get("_LOKI_DEP_STATUS", "failed"),
|
|
91
|
+
"command": os.environ.get("_LOKI_DEP_COMMAND") or None,
|
|
92
|
+
"exit_code": int(raw_exit) if raw_exit.isdigit() else None,
|
|
93
|
+
"input_sha256": os.environ.get("_LOKI_DEP_SHA") or None,
|
|
94
|
+
"lifecycle_scripts": "disabled",
|
|
95
|
+
}
|
|
96
|
+
directory = os.path.dirname(target)
|
|
97
|
+
os.makedirs(directory, exist_ok=True)
|
|
98
|
+
fd, temporary = tempfile.mkstemp(dir=directory, suffix=".json")
|
|
99
|
+
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
100
|
+
json.dump(record, handle, indent=2, sort_keys=True)
|
|
101
|
+
handle.write("\n")
|
|
102
|
+
os.replace(temporary, target)
|
|
103
|
+
PYEOF
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
loki_prepare_project_dependencies() {
|
|
107
|
+
local tree="${TARGET_DIR:-.}"
|
|
108
|
+
local quality_dir="$tree/.loki/quality"
|
|
109
|
+
local state_dir="$tree/.loki/state"
|
|
110
|
+
local result_file="$quality_dir/dependency-setup.json"
|
|
111
|
+
local marker_file="$state_dir/dependency-input.sha256"
|
|
112
|
+
local command_text="npm ci --ignore-scripts --no-audit --no-fund"
|
|
113
|
+
mkdir -p "$quality_dir" "$state_dir" || return 1
|
|
114
|
+
|
|
115
|
+
if [ ! -f "$tree/package.json" ]; then
|
|
116
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
117
|
+
"not_applicable" "" "" ""
|
|
118
|
+
return 0
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
if [ ! -f "$tree/package-lock.json" ]; then
|
|
122
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
123
|
+
"failed" "$command_text" "1" ""
|
|
124
|
+
log_warn "Dependency setup requires package-lock.json for reproducible npm verification"
|
|
125
|
+
return 1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
local input_sha
|
|
129
|
+
input_sha="$(loki_dependency_input_sha256 "$tree" 2>/dev/null)" || input_sha=""
|
|
130
|
+
if [ -z "$input_sha" ]; then
|
|
131
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
132
|
+
"failed" "$command_text" "1" ""
|
|
133
|
+
log_warn "Dependency setup could not fingerprint package.json and package-lock.json"
|
|
134
|
+
return 1
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
local marker_version marker_input_sha marker_install_fingerprint install_fingerprint
|
|
138
|
+
if [ -f "$marker_file" ]; then
|
|
139
|
+
read -r marker_version marker_input_sha marker_install_fingerprint < "$marker_file" || true
|
|
140
|
+
if [ "$marker_version" = "v1" ] \
|
|
141
|
+
&& [ "$marker_input_sha" = "$input_sha" ] \
|
|
142
|
+
&& install_fingerprint="$(loki_dependency_install_fingerprint "$tree" 2>/dev/null)" \
|
|
143
|
+
&& [ "$marker_install_fingerprint" = "$install_fingerprint" ]; then
|
|
144
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
145
|
+
"verified" "$command_text" "0" "$input_sha"
|
|
146
|
+
log_info "Dependency setup: reusing the verified lockfile installation"
|
|
147
|
+
return 0
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
if ! rm -f "$marker_file"; then
|
|
152
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
153
|
+
"failed" "$command_text" "1" "$input_sha"
|
|
154
|
+
log_warn "Dependency setup could not invalidate its previous verification marker"
|
|
155
|
+
return 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
if ! command -v npm >/dev/null 2>&1; then
|
|
159
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
160
|
+
"failed" "$command_text" "127" "$input_sha"
|
|
161
|
+
log_warn "Dependency setup requires npm but npm is unavailable"
|
|
162
|
+
return 1
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
local setup_timeout="${LOKI_DEPENDENCY_SETUP_TIMEOUT:-60}"
|
|
166
|
+
case "$setup_timeout" in
|
|
167
|
+
''|*[!0-9]*) setup_timeout=60 ;;
|
|
168
|
+
esac
|
|
169
|
+
[ "$setup_timeout" -gt 0 ] 2>/dev/null || setup_timeout=60
|
|
170
|
+
|
|
171
|
+
local rc=0
|
|
172
|
+
if type _loki_with_deadline >/dev/null 2>&1; then
|
|
173
|
+
(cd "$tree" && LOKI_DEADLINE_IDLE_TIMEOUT=0 \
|
|
174
|
+
_loki_with_deadline "$setup_timeout" npm ci \
|
|
175
|
+
--ignore-scripts --no-audit --no-fund) || rc=$?
|
|
176
|
+
else
|
|
177
|
+
(cd "$tree" && npm ci --ignore-scripts --no-audit --no-fund) || rc=$?
|
|
178
|
+
fi
|
|
179
|
+
if [ "$rc" -ne 0 ]; then
|
|
180
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
181
|
+
"failed" "$command_text" "$rc" "$input_sha"
|
|
182
|
+
log_warn "Dependency setup failed with exit $rc"
|
|
183
|
+
return 1
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
install_fingerprint="$(loki_dependency_install_fingerprint "$tree" 2>/dev/null)" \
|
|
187
|
+
|| install_fingerprint=""
|
|
188
|
+
if [ -z "$install_fingerprint" ]; then
|
|
189
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
190
|
+
"failed" "$command_text" "1" "$input_sha"
|
|
191
|
+
log_warn "Dependency setup produced an incomplete npm installation"
|
|
192
|
+
return 1
|
|
193
|
+
fi
|
|
194
|
+
if ! loki_publish_dependency_marker \
|
|
195
|
+
"$marker_file" "$input_sha" "$install_fingerprint"; then
|
|
196
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
197
|
+
"failed" "$command_text" "1" "$input_sha"
|
|
198
|
+
log_warn "Dependency setup could not publish its verification marker"
|
|
199
|
+
return 1
|
|
200
|
+
fi
|
|
201
|
+
loki_write_dependency_setup_result "$result_file" \
|
|
202
|
+
"verified" "$command_text" "0" "$input_sha"
|
|
203
|
+
log_info "Dependency setup: reproducible npm installation verified"
|
|
204
|
+
return 0
|
|
205
|
+
}
|
|
@@ -50,6 +50,51 @@
|
|
|
50
50
|
# needs a real command, not a shell function.
|
|
51
51
|
_loki_done_recog_invoke() {
|
|
52
52
|
local prompt="$1"
|
|
53
|
+
|
|
54
|
+
# v8 RAW-SDK JUDGE PATH (opt-in LOKI_SDK_DONE_RECOG=1). Runs this one-shot
|
|
55
|
+
# judge via the pure-HTTPS @anthropic-ai/sdk (no claude binary) through the
|
|
56
|
+
# loki-ts `internal sdk-judge` bridge. This is the first end-to-end SDK
|
|
57
|
+
# adoption -- CLAUDE-ONLY site, one prompt -> one schema-constrained JSON
|
|
58
|
+
# object, already inconclusive-safe. Fail-closed: on ANY miss (flag off, no
|
|
59
|
+
# ANTHROPIC_API_KEY, bun/entrypoint absent, non-zero, empty) we fall straight
|
|
60
|
+
# through to the existing claude/deterministic paths below -- zero behavior
|
|
61
|
+
# change when off or unavailable. Same schema, same output shape (a JSON
|
|
62
|
+
# object parse_object consumes), so parity holds by construction.
|
|
63
|
+
if [ "${LOKI_SDK_DONE_RECOG:-0}" = "1" ]; then
|
|
64
|
+
local _sdk_root _sdk_loki _sdk_schema _sdk_prompt_f _sdk_out _sdk_rc
|
|
65
|
+
_sdk_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
66
|
+
_sdk_loki="${_sdk_root}/bin/loki"
|
|
67
|
+
_sdk_schema="${_sdk_root}/loki-ts/data/done-recognition-schema.json"
|
|
68
|
+
if [ -x "$_sdk_loki" ] && [ -f "$_sdk_schema" ] && command -v bun >/dev/null 2>&1; then
|
|
69
|
+
_sdk_prompt_f="$(mktemp 2>/dev/null)" || _sdk_prompt_f=""
|
|
70
|
+
if [ -n "$_sdk_prompt_f" ]; then
|
|
71
|
+
printf '%s' "$prompt" > "$_sdk_prompt_f"
|
|
72
|
+
_sdk_rc=0
|
|
73
|
+
# OS-level ceiling around the whole bun subprocess (council review:
|
|
74
|
+
# --timeout-ms only bounds the in-process HTTP call; a bun cold-start
|
|
75
|
+
# / DNS stall could hang the command substitution otherwise). Mirror
|
|
76
|
+
# the claude path's `timeout` wrap, with a small buffer over the
|
|
77
|
+
# in-process budget. Degrade to no-cap only if neither timeout binary
|
|
78
|
+
# is present.
|
|
79
|
+
local _sdk_to_s=$(( ${LOKI_DONE_RECOG_TIMEOUT:-180} + 15 ))
|
|
80
|
+
local _sdk_wrap
|
|
81
|
+
if command -v timeout >/dev/null 2>&1; then _sdk_wrap="timeout ${_sdk_to_s}"
|
|
82
|
+
elif command -v gtimeout >/dev/null 2>&1; then _sdk_wrap="gtimeout ${_sdk_to_s}"
|
|
83
|
+
else _sdk_wrap=""; fi
|
|
84
|
+
_sdk_out="$($_sdk_wrap "$_sdk_loki" internal sdk-judge \
|
|
85
|
+
--prompt-file "$_sdk_prompt_f" --schema-file "$_sdk_schema" \
|
|
86
|
+
--model "${LOKI_SDK_JUDGE_MODEL:-claude-haiku-4-5}" --effort low \
|
|
87
|
+
--timeout-ms "$(( ${LOKI_DONE_RECOG_TIMEOUT:-180} * 1000 ))" 2>/dev/null)" || _sdk_rc=$?
|
|
88
|
+
rm -f "$_sdk_prompt_f" 2>/dev/null || true
|
|
89
|
+
if [ "$_sdk_rc" -eq 0 ] && [ -n "$_sdk_out" ]; then
|
|
90
|
+
printf '%s' "$_sdk_out"
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
# fall through to the claude/deterministic paths (fail-closed)
|
|
96
|
+
fi
|
|
97
|
+
|
|
53
98
|
command -v claude >/dev/null 2>&1 || return 1
|
|
54
99
|
|
|
55
100
|
# STRUCTURED VERDICT (v8.x): when the CLI supports --json-schema, force valid
|
|
@@ -13,6 +13,7 @@ Behavior contract (preserved from the R1 proof generator):
|
|
|
13
13
|
- cost.usd is None when NO valid efficiency record was read (cost was never
|
|
14
14
|
collected for this run). A skeptic seeing "$0.00" assumes the artifact is
|
|
15
15
|
fake; "cost not recorded" is the honest signal.
|
|
16
|
+
- Token counts are also None and available is False when no record exists.
|
|
16
17
|
- A genuine 0.0 (records existed but summed to zero) is preserved as 0.0.
|
|
17
18
|
- usd is rounded to 4 decimals only when records were collected.
|
|
18
19
|
|
|
@@ -76,10 +77,10 @@ def collect_efficiency(loki_dir):
|
|
|
76
77
|
|
|
77
78
|
Returns (cost dict, best-effort model name (last non-empty seen)).
|
|
78
79
|
|
|
79
|
-
Credibility: cost
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
Credibility: unavailable cost and token values are None when NO valid
|
|
81
|
+
efficiency record was read. A skeptic seeing "$0.00" assumes the artifact
|
|
82
|
+
is fake; "cost not recorded" is the honest signal. A genuine 0.0 from a
|
|
83
|
+
present record is preserved as 0.0.
|
|
83
84
|
"""
|
|
84
85
|
cost = {
|
|
85
86
|
"usd": 0.0,
|
|
@@ -87,6 +88,7 @@ def collect_efficiency(loki_dir):
|
|
|
87
88
|
"output_tokens": 0,
|
|
88
89
|
"cache_read_tokens": 0,
|
|
89
90
|
"cache_creation_tokens": 0,
|
|
91
|
+
"available": False,
|
|
90
92
|
}
|
|
91
93
|
model = ""
|
|
92
94
|
collected = False
|
|
@@ -113,9 +115,14 @@ def collect_efficiency(loki_dir):
|
|
|
113
115
|
# Round usd to a sane precision but keep it precise (anti-pattern:
|
|
114
116
|
# round suspiciously-clean numbers). 4 decimals preserves odd values.
|
|
115
117
|
cost["usd"] = round(cost["usd"], 4)
|
|
118
|
+
cost["available"] = True
|
|
116
119
|
else:
|
|
117
|
-
# No
|
|
118
|
-
|
|
120
|
+
# No record means unavailable, never an observed zero.
|
|
121
|
+
for key in (
|
|
122
|
+
"usd", "input_tokens", "output_tokens",
|
|
123
|
+
"cache_read_tokens", "cache_creation_tokens",
|
|
124
|
+
):
|
|
125
|
+
cost[key] = None
|
|
119
126
|
return cost, model
|
|
120
127
|
|
|
121
128
|
|