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.
Files changed (74) hide show
  1. package/README.md +81 -5
  2. package/SKILL.md +66 -5
  3. package/VERSION +1 -1
  4. package/autonomy/app-runner.sh +37 -0
  5. package/autonomy/completion-council.sh +862 -28
  6. package/autonomy/council-v2.sh +39 -0
  7. package/autonomy/crash.sh +3 -2
  8. package/autonomy/grill.sh +42 -0
  9. package/autonomy/hooks/validate-bash.sh +301 -4
  10. package/autonomy/lib/cockpit-render.sh +8 -2
  11. package/autonomy/lib/cr-rematerialize.py +101 -4
  12. package/autonomy/lib/deadline.py +957 -0
  13. package/autonomy/lib/dependency-setup.sh +205 -0
  14. package/autonomy/lib/done-recognition.sh +45 -0
  15. package/autonomy/lib/efficiency_cost.py +13 -6
  16. package/autonomy/lib/no_mock_scan.py +793 -0
  17. package/autonomy/lib/prd-enrich.sh +42 -0
  18. package/autonomy/lib/proof-analytics-props.py +69 -0
  19. package/autonomy/lib/proof-generator.py +282 -95
  20. package/autonomy/lib/proof-template.html +15 -12
  21. package/autonomy/lib/proof-verify.py +151 -102
  22. package/autonomy/lib/requirements_contract.py +848 -0
  23. package/autonomy/lib/sdk-mode.sh +103 -0
  24. package/autonomy/lib/secret-scan.sh +139 -0
  25. package/autonomy/lib/spec-expand.sh +208 -0
  26. package/autonomy/lib/tree_digest.py +266 -0
  27. package/autonomy/lib/voter-agents.sh +58 -8
  28. package/autonomy/lib/workspace_diff.py +124 -0
  29. package/autonomy/loki +189 -17
  30. package/autonomy/playwright-verify.sh +501 -0
  31. package/autonomy/prd-checklist.sh +17 -8
  32. package/autonomy/provider-offer.sh +111 -0
  33. package/autonomy/run.sh +4417 -676
  34. package/autonomy/sandbox.sh +42 -0
  35. package/autonomy/spec-interrogation.sh +148 -5
  36. package/autonomy/spec.sh +118 -1
  37. package/autonomy/telemetry.sh +133 -7
  38. package/autonomy/verify.sh +107 -0
  39. package/bin/loki +110 -3
  40. package/completions/_loki +10 -0
  41. package/completions/loki.bash +1 -1
  42. package/dashboard/__init__.py +1 -1
  43. package/dashboard/audit.py +96 -7
  44. package/dashboard/build_supervisor.py +1619 -0
  45. package/dashboard/control.py +8 -0
  46. package/dashboard/prompt_optimizer.py +7 -0
  47. package/dashboard/server.py +577 -22
  48. package/dashboard/static/trust.html +1 -1
  49. package/docs/ARCHITECTURE-OVERVIEW.md +207 -0
  50. package/docs/AUTONOMI-ECOSYSTEM.md +107 -0
  51. package/docs/INSTALLATION.md +19 -2
  52. package/docs/MODEL-EQUIVALENCE-HARNESS-PLAN.md +70 -0
  53. package/docs/PLANS-INDEX.md +33 -0
  54. package/docs/PRIVACY.md +29 -1
  55. package/docs/SIGNED-RECEIPTS.md +102 -0
  56. package/docs/SONNET5-DEFAULT-PLAN.md +1 -1
  57. package/docs/V8-ACCEPTANCE-TRIAGE-2026-07-24.md +114 -0
  58. package/docs/V8-AGENT-SDK-PLAN.md +692 -0
  59. package/docs/V8-COMPLEXITY-AUDIT-2026-07-24.md +45 -0
  60. package/docs/V8-MAJOR-RELEASE-PLAN.md +137 -0
  61. package/docs/V8-OVERNIGHT-PLAN-2026-07-25.md +82 -0
  62. package/docs/V8-RUNTIME-TRUTH-2026-07-25.md +232 -0
  63. package/docs/V8-SDK-RESEARCH-RAW.md +129 -0
  64. package/docs/alternative-installations.md +4 -4
  65. package/loki-ts/dist/loki.js +674 -285
  66. package/loki-ts/package.json +2 -0
  67. package/mcp/__init__.py +1 -1
  68. package/package.json +7 -6
  69. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  70. package/providers/claude.sh +75 -0
  71. package/providers/codex.sh +85 -13
  72. package/references/sdk-mode.md +106 -0
  73. package/skills/model-selection.md +1 -1
  74. 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.usd is set to None when NO valid efficiency record was
80
- read (cost was never collected for this run). A skeptic seeing "$0.00" on
81
- HN assumes the artifact is fake; "cost not recorded" is the honest signal.
82
- A genuine 0.0 (records existed but summed to zero) is preserved as 0.0.
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 efficiency files were read: cost was not collected for this run.
118
- cost["usd"] = None
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