loki-mode 7.129.5 → 8.0.1

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 (75) hide show
  1. package/README.md +121 -9
  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 +326 -92
  20. package/autonomy/lib/proof-template.html +15 -12
  21. package/autonomy/lib/proof-verify.py +169 -105
  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 +141 -0
  29. package/autonomy/loki +196 -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 +4587 -671
  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/providers.md +42 -0
  75. package/skills/quality-gates.md +22 -0
@@ -42,6 +42,40 @@
42
42
  # precedent at autonomy/lib/voter-agents.sh:259.
43
43
  _loki_prd_enrich_invoke() {
44
44
  local prompt="$1"
45
+ # v8 RAW-SDK TEXT PATH (opt-in LOKI_SDK_PRD_ENRICH=1). Free-form enrichment
46
+ # via the pure-HTTPS @anthropic-ai/sdk (no claude binary) through the loki-ts
47
+ # `internal sdk-text` bridge. Runs BEFORE the claude-binary guard so the
48
+ # no-binary deploy win holds. Fail-closed: on ANY miss (flag off, no key,
49
+ # bun/entrypoint absent, non-zero, empty) fall straight through to the claude
50
+ # path below -- zero behavior change when off or unavailable. The output is
51
+ # free-form text the caller consumes verbatim, same as the claude path.
52
+ if [ "${LOKI_SDK_PRD_ENRICH:-0}" = "1" ]; then
53
+ local _pe_root _pe_loki _pe_pf _pe_out _pe_rc
54
+ _pe_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
55
+ _pe_loki="${_pe_root}/bin/loki"
56
+ if [ -x "$_pe_loki" ] && command -v bun >/dev/null 2>&1; then
57
+ _pe_pf="$(mktemp 2>/dev/null)" || _pe_pf=""
58
+ if [ -n "$_pe_pf" ]; then
59
+ printf '%s' "$prompt" > "$_pe_pf"
60
+ _pe_rc=0
61
+ local _pe_to_s="${LOKI_PRD_ENRICH_TIMEOUT:-180}"
62
+ local _pe_wrap
63
+ if command -v timeout >/dev/null 2>&1; then _pe_wrap="timeout $(( _pe_to_s + 15 ))"
64
+ elif command -v gtimeout >/dev/null 2>&1; then _pe_wrap="gtimeout $(( _pe_to_s + 15 ))"
65
+ else _pe_wrap=""; fi
66
+ _pe_out="$($_pe_wrap "$_pe_loki" internal sdk-text \
67
+ --prompt-file "$_pe_pf" \
68
+ --model "${LOKI_SDK_PRD_ENRICH_MODEL:-claude-sonnet-5}" --effort medium \
69
+ --timeout-ms "$(( _pe_to_s * 1000 ))" 2>/dev/null)" || _pe_rc=$?
70
+ rm -f "$_pe_pf" 2>/dev/null || true
71
+ if [ "$_pe_rc" -eq 0 ] && [ -n "$_pe_out" ]; then
72
+ printf '%s' "$_pe_out"
73
+ return 0
74
+ fi
75
+ fi
76
+ fi
77
+ # fall through to the claude path (fail-closed)
78
+ fi
45
79
  command -v claude >/dev/null 2>&1 || return 1
46
80
  local rc=0
47
81
  local out=""
@@ -65,6 +99,14 @@ _loki_prd_enrich_invoke() {
65
99
  _loki_prd_enrich_provider_ok() {
66
100
  [ "${LOKI_PROVIDER:-claude}" = "claude" ] || return 1
67
101
  [ "${PROVIDER_DEGRADED:-false}" != "true" ] || return 1
102
+ # v8: the raw-SDK enrich path (LOKI_SDK_PRD_ENRICH=1) needs no claude binary,
103
+ # so attempt is viable when that path is usable (bridge + bun). The invoke fn
104
+ # still fails closed to claude on an SDK miss.
105
+ if [ "${LOKI_SDK_PRD_ENRICH:-0}" = "1" ] \
106
+ && [ -x "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/bin/loki" ] \
107
+ && command -v bun >/dev/null 2>&1; then
108
+ return 0
109
+ fi
68
110
  command -v claude >/dev/null 2>&1 || return 1
69
111
  return 0
70
112
  }
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env python3
2
+ """Emit the FIXED analytics allowlist from a finished proof.json as key=value
3
+ lines, one per line, for loki_emit_build_verified (autonomy/telemetry.sh).
4
+
5
+ This is the SINGLE authoritative allowlist for opt-in build-outcome analytics.
6
+ Only already-computed scalars are ever emitted -- never code, spec/PRD text,
7
+ paths, or file names. Anything not named here is never read, so a proof.json
8
+ schema change cannot silently start leaking a new field.
9
+
10
+ Free-text-shaped fields are excluded on purpose:
11
+ - headline is a bounded enum (VERIFIED / VERIFIED WITH GAPS / NOT VERIFIED),
12
+ computed deterministically from facts -- never spec/project text.
13
+ - files_changed is emitted as a COUNT only, never the paths list.
14
+
15
+ Usage: proof-analytics-props.py <proof.json>
16
+ Fail-open: any error prints nothing and exits non-zero; the caller drops it.
17
+ """
18
+ import json
19
+ import sys
20
+
21
+
22
+ def main():
23
+ if len(sys.argv) < 2:
24
+ return 1
25
+ try:
26
+ p = json.load(open(sys.argv[1]))
27
+ except Exception:
28
+ return 1
29
+
30
+ honesty = p.get("honesty") or {}
31
+ council = p.get("council") or {}
32
+ facts = p.get("facts") or {}
33
+ qg = p.get("quality_gates") or {}
34
+ fc = p.get("files_changed") or {}
35
+
36
+ gates_passed = qg.get("passed")
37
+ gates_total = qg.get("total")
38
+ try:
39
+ rate = round(int(gates_passed) / int(gates_total), 3) if gates_total else None
40
+ except Exception:
41
+ rate = None
42
+
43
+ out = {
44
+ "headline": str(honesty.get("headline") or ""), # bounded enum only
45
+ "evidence_gate_verdict": str(
46
+ honesty.get("evidence_gate_verdict")
47
+ or (facts.get("evidence_gate") or {}).get("verdict")
48
+ or ""
49
+ ),
50
+ "final_verdict": str(council.get("final_verdict") or ""),
51
+ "iterations": p.get("iterations"),
52
+ "files_changed_count": fc.get("count") if isinstance(fc, dict) else None,
53
+ "wall_clock_sec": p.get("wall_clock_sec"),
54
+ "gates_passed": gates_passed,
55
+ "gates_total": gates_total,
56
+ "gate_pass_rate": rate,
57
+ }
58
+
59
+ for k, v in out.items():
60
+ if v is None or v == "":
61
+ continue
62
+ # key=value; sanitize so a value can never inject a second pair or a newline.
63
+ v = str(v).replace("\n", " ").replace("=", "-")
64
+ sys.stdout.write("%s=%s\n" % (k, v))
65
+ return 0
66
+
67
+
68
+ if __name__ == "__main__":
69
+ sys.exit(main())