loki-mode 8.5.2 → 8.6.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.
@@ -39,12 +39,23 @@
39
39
  # 2 BLOCKED
40
40
  # 3 verifier error (could not complete; never silently passes)
41
41
  #
42
- # NOTE on exit-code divergence from the spec: spec Section 1.1 lists
43
- # 0=VERIFIED, 1=BLOCKED, 2=CONCERNS, 3=error (BLOCKED and CONCERNS swapped
44
- # vs this implementation). This module follows the explicit BUILD TASK
45
- # ordering (0/1/2 = VERIFIED/CONCERNS/BLOCKED). A human must reconcile the
46
- # two before the GitHub App (Phase 2) consumes exit codes. The divergence is
47
- # surfaced in `loki verify --help`.
42
+ # EXIT-CODE ORDERING, RECONCILED. An early draft spec listed
43
+ # 0=VERIFIED, 1=BLOCKED, 2=CONCERNS, and this header used to say a human must
44
+ # reconcile the two before the GitHub App consumed exit codes. That is now
45
+ # done, in favor of THIS implementation: 0/1/2/3 =
46
+ # VERIFIED/CONCERNS/BLOCKED/error.
47
+ #
48
+ # Why this ordering wins. The code is authoritative and always has been
49
+ # (VERIFY_EXIT_* below), `loki verify --help` documents it, and
50
+ # wiki/CLI-Reference.md documents it. The draft spec that said otherwise is not
51
+ # in this repository and has no consumers. Renumbering working code to match an
52
+ # absent document would break every existing caller to satisfy nothing.
53
+ #
54
+ # It is also the ordering an integrator expects: severity rises with the code,
55
+ # so `[ $rc -ge 2 ]` means "at least blocked". The reverse would make 1 more
56
+ # severe than 2, which no one guesses correctly.
57
+ #
58
+ # See docs/exit-codes.md for the exit codes of every command.
48
59
 
49
60
  set -uo pipefail
50
61
 
@@ -1810,6 +1821,7 @@ verify_emit_evidence() {
1810
1821
  _VERIFY_GATES="$_VERIFY_GATES_FILE" \
1811
1822
  _V_VERDICT="$VERIFY_VERDICT" \
1812
1823
  _V_EXIT="$VERIFY_EXIT" \
1824
+ _V_JSON_STDOUT="${VERIFY_JSON:-0}" \
1813
1825
  _V_SCHEMA="$VERIFY_SCHEMA_VERSION" \
1814
1826
  _V_TOOLVER="$tool_version" \
1815
1827
  _V_REPO="$repo_name" \
@@ -1833,7 +1845,7 @@ verify_emit_evidence() {
1833
1845
  _V_SCOPE_MAX_FILES="${VERIFY_SCOPE_MAX_FILES:-}" \
1834
1846
  _V_SCOPE_MAX_NET="${VERIFY_SCOPE_MAX_NET_LINES:-}" \
1835
1847
  python3 - <<'PYEOF'
1836
- import json, os, hashlib
1848
+ import json, os, hashlib, sys
1837
1849
 
1838
1850
  out_dir = os.environ["_VERIFY_OUT_DIR"]
1839
1851
  findings_file = os.environ["_VERIFY_FINDINGS"]
@@ -1959,6 +1971,27 @@ with open(ev_path, "w") as f:
1959
1971
  json.dump(doc, f, indent=2)
1960
1972
  f.write("\n")
1961
1973
 
1974
+ # --json emits the SAME document to stdout. Deliberately the same `doc` rather
1975
+ # than a second serializer: two writers of one contract drift, and the drift
1976
+ # shows up as a caller trusting a field the file no longer has. The evidence
1977
+ # file is still written either way, so --json adds a pipe without removing the
1978
+ # artifact.
1979
+ #
1980
+ # Written to FD 3, not stdout. The caller redirects this function's stdout to
1981
+ # /dev/null (it emits progress chatter the human path does not want), so a
1982
+ # plain stdout write here is discarded. FD 3 is opened by the caller only under
1983
+ # --json and routed to the real stdout.
1984
+ if os.environ.get("_V_JSON_STDOUT") == "1":
1985
+ try:
1986
+ with os.fdopen(os.dup(3), "w") as _jf:
1987
+ _jf.write(json.dumps(doc, indent=2) + "\n")
1988
+ except OSError:
1989
+ # FD 3 not open: --json was requested but the caller did not wire it.
1990
+ # Fail loudly rather than exit 0 having emitted nothing, which would
1991
+ # look to a pipeline like a verify that produced an empty document.
1992
+ sys.stderr.write("verify: --json requested but FD 3 is not open\n")
1993
+ raise SystemExit(3)
1994
+
1962
1995
  # ----- Markdown report -----
1963
1996
  def sev_rank(s):
1964
1997
  return {"Critical": 0, "High": 1, "Medium": 2, "Low": 3, "Info": 4}.get(s, 5)
@@ -2050,6 +2083,11 @@ OPTIONS:
2050
2083
  Default: critical,high (one notch looser than the
2051
2084
  Loki build loop, which also blocks on medium).
2052
2085
  --no-llm Accepted for forward-compat; LLM is already off in MVP.
2086
+ --json Emit the evidence document to stdout so it can be piped
2087
+ (`loki verify --json | jq .verdict`). The same document
2088
+ is still written to <out>/evidence.json. The human
2089
+ VERDICT banner moves to stderr so stdout stays valid
2090
+ JSON. The verdict and exit code are unchanged.
2053
2091
  --explain Print a one-screen, skeptic-legible trust proof: every
2054
2092
  gate that ran, its status, the runner/scanner that
2055
2093
  produced the evidence, whether it is reproducible, plus
@@ -2093,16 +2131,16 @@ VERDICT MODEL:
2093
2131
  Uncommitted working-tree changes are not verified; commit them first. An
2094
2132
  empty diff yields CONCERNS (nothing to verify), never VERIFIED.
2095
2133
 
2096
- EXIT CODES (this implementation):
2134
+ EXIT CODES:
2097
2135
  0 VERIFIED
2098
2136
  1 CONCERNS
2099
2137
  2 BLOCKED
2100
2138
  3 verifier error (could not complete; never silently passes)
2101
2139
 
2102
- NOTE: the verification spec (Section 1.1) lists 1=BLOCKED, 2=CONCERNS.
2103
- This implementation follows the build-task ordering (1=CONCERNS,
2104
- 2=BLOCKED). A human must reconcile the two before the GitHub App consumes
2105
- these codes.
2140
+ Severity rises with the code, so `[ $rc -ge 2 ]` means "at least blocked".
2141
+ An early draft spec listed 1=BLOCKED, 2=CONCERNS; that ordering was
2142
+ rejected and is not used anywhere. See docs/exit-codes.md for every
2143
+ command's codes.
2106
2144
 
2107
2145
  OUTPUT:
2108
2146
  <out>/evidence.json consolidated machine-readable evidence (schema 1.0)
@@ -2620,6 +2658,8 @@ verify_main() {
2620
2658
  # verify does NOT re-run gates: it reads a prior evidence.json and fails
2621
2659
  # closed if the repo has drifted since that evidence was graded.
2622
2660
  VERIFY_CHECK_FRESH=0
2661
+ # Opt-in machine-readable stdout (--json). Default 0 = exactly today.
2662
+ VERIFY_JSON=0
2623
2663
 
2624
2664
  # Fail-closed defaults. These globals are read at the end of this function
2625
2665
  # (the VERDICT banner and the function return code). verify_compute_verdict()
@@ -2644,6 +2684,16 @@ verify_main() {
2644
2684
  block_on="$(printf '%s' "${2:-}" | tr '[:upper:]' '[:lower:]')"; shift 2 ;;
2645
2685
  --no-llm)
2646
2686
  shift ;;
2687
+ --json)
2688
+ # Emit the evidence document to STDOUT so a caller can pipe it.
2689
+ # The same document is still written to <out>/evidence.json --
2690
+ # this adds a pipe, it does not move the artifact.
2691
+ #
2692
+ # Implies --quiet-banner: stdout must be JSON and nothing else,
2693
+ # or `loki verify --json | jq` breaks on the human banner. The
2694
+ # banner still goes to stderr, so an operator watching a
2695
+ # terminal loses nothing.
2696
+ VERIFY_JSON=1; shift ;;
2647
2697
  --explain)
2648
2698
  # Render a one-screen, skeptic-legible trust proof: every gate
2649
2699
  # that ran, its status, the runner/scanner that produced the
@@ -2793,10 +2843,21 @@ verify_main() {
2793
2843
 
2794
2844
  completed_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
2795
2845
 
2796
- verify_emit_evidence "$out_dir" "$started_at" "$completed_at" "$block_on" >/dev/null || {
2797
- _verify_err "failed to emit evidence document"
2798
- return $VERIFY_EXIT_ERROR
2799
- }
2846
+ # stdout is discarded (the emitter's own chatter is not wanted on the human
2847
+ # path). Under --json, FD 3 is opened onto the REAL stdout so the emitter
2848
+ # can write the evidence document there while everything else stays
2849
+ # suppressed -- that is what keeps `loki verify --json | jq` parseable.
2850
+ if [ "${VERIFY_JSON:-0}" = "1" ]; then
2851
+ verify_emit_evidence "$out_dir" "$started_at" "$completed_at" "$block_on" 3>&1 >/dev/null || {
2852
+ _verify_err "failed to emit evidence document"
2853
+ return $VERIFY_EXIT_ERROR
2854
+ }
2855
+ else
2856
+ verify_emit_evidence "$out_dir" "$started_at" "$completed_at" "$block_on" >/dev/null || {
2857
+ _verify_err "failed to emit evidence document"
2858
+ return $VERIFY_EXIT_ERROR
2859
+ }
2860
+ fi
2800
2861
 
2801
2862
  # Opt-in (--hosted): fold the embedded Autonomi Verify engine's verdict
2802
2863
  # fields into the just-written evidence.json. Fully additive and fail-open:
@@ -2814,9 +2875,14 @@ verify_main() {
2814
2875
  _verify_render_explain "$started_at" "$completed_at" "$VERIFY_VERDICT"
2815
2876
  fi
2816
2877
 
2817
- printf 'VERDICT: %s\n' "$VERIFY_VERDICT"
2818
- printf 'Evidence: %s/evidence.json\n' "$out_dir"
2819
- printf 'Report: %s/report.md\n' "$out_dir"
2878
+ # Under --json stdout carries the evidence document alone, so the human
2879
+ # banner is redirected to stderr rather than dropped: an operator watching a
2880
+ # terminal still sees the verdict, and `| jq` still parses.
2881
+ _v_banner_fd=1
2882
+ [ "${VERIFY_JSON:-0}" = "1" ] && _v_banner_fd=2
2883
+ printf 'VERDICT: %s\n' "$VERIFY_VERDICT" >&$_v_banner_fd
2884
+ printf 'Evidence: %s/evidence.json\n' "$out_dir" >&$_v_banner_fd
2885
+ printf 'Report: %s/report.md\n' "$out_dir" >&$_v_banner_fd
2820
2886
  # --hosted only: surface the enrichment in human output so the extra signal
2821
2887
  # is visible without parsing JSON. Printed solely when a fold succeeded;
2822
2888
  # the default path never sets VERIFY_HOSTED_SUMMARY, so it stays byte-identical.
package/completions/_loki CHANGED
@@ -153,6 +153,7 @@ function _loki_commands {
153
153
  'memory:Memory commands'
154
154
  'compound:Knowledge compounding commands'
155
155
  'checkpoint:Snapshot and restore session state'
156
+ 'cp:Snapshot and restore session state (alias of checkpoint)'
156
157
  'council:Completion council commands'
157
158
  'dogfood:Self-development statistics'
158
159
  'projects:Project registry commands'
@@ -5,7 +5,7 @@ _loki_completion() {
5
5
  _init_completion || return
6
6
 
7
7
  # Main subcommands (must match autonomy/loki main case statement)
8
- local main_commands="start quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own doctor watchdog audit metrics syslog onboard share proof explain plan report cost kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash open otel preview quickstart rc rollback self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help"
8
+ local main_commands="start quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt explain plan report cost kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash open otel preview quickstart rc rollback self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help"
9
9
 
10
10
  # 1. If we are on the first argument (subcommand)
11
11
  if [[ $cword -eq 1 ]]; then
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "8.5.2"
10
+ __version__ = "8.6.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -154,6 +154,34 @@ expose something the CLI does not. If a competitor does ship output
154
154
  verification, this test is how we would find out, and the claim above would be
155
155
  corrected rather than defended.
156
156
 
157
+ ## 7. Headless latency, five trials per tool
158
+
159
+ Same task, same machine, artifact verified by content, five trials each:
160
+
161
+ | CLI | Success | Median | Range |
162
+ | --- | --- | --- | --- |
163
+ | opencode 1.18.9 | 5/5 | 11s | 4s to 265s |
164
+ | codex-cli 0.146.0 | 4/5 | 69s | 48s to 80s (one 300s timeout) |
165
+
166
+ **Read the range, not just the median.** opencode's first trial took 265
167
+ seconds and the next four took 4 to 12. A new user experiences the 265, not the
168
+ 11. Reporting only the median would hide the thing they will actually feel.
169
+
170
+ **The timeout is kept in.** Dropping codex's one failure would turn 4-of-5 into
171
+ an implied 5-of-5 and overstate reliability.
172
+
173
+ **Five trials, not one, and that is the point.** An earlier single-shot run of
174
+ this same codex command timed out, and publishing it would have recorded
175
+ "codex: timeout" as a fact about a competitor when the identical command
176
+ completed in 51 seconds minutes later. The spread is the finding.
177
+
178
+ **What this does not measure.** One trivial file-creation task is not a proxy
179
+ for build quality, multi-iteration work, or brownfield capability. It measures
180
+ headless invocation latency and nothing else. aider, Claude Code and
181
+ cursor-agent have not been run on this task; Devin and Replit Agent ship no
182
+ local CLI. Cost is not compared: codex ran on a free tier and opencode's
183
+ per-call cost was not recorded.
184
+
157
185
  ---
158
186
 
159
187
  ## What we do not have
package/docs/PRIVACY.md CHANGED
@@ -114,10 +114,33 @@ it sits below the base telemetry gate, every telemetry opt-out (`loki telemetry
114
114
  off` / `LOKI_TELEMETRY=off` / `DO_NOT_TRACK=1`) also disables it -- opt-out
115
115
  always wins.
116
116
 
117
+ ### 5. First-run blocker (anonymous, STRICT opt-in, default OFF)
118
+
119
+ A `first_run_blocked` event naming which CLASS of dependency stopped a first
120
+ run, sent at most ONCE per install. It sits behind the same strict second
121
+ opt-in as build-outcome analytics above (`LOKI_ANALYTICS=on`), so it is off by
122
+ default even with telemetry enabled.
123
+
124
+ It exists because we could see that a first run was ATTEMPTED and nothing about
125
+ whether it succeeded, which made "why does a trial not convert" unanswerable.
126
+ A real example we found and fixed: on a machine with no AI provider CLI, one
127
+ route ended with a dead end instead of pointing at `loki tour` (which needs no
128
+ provider, no key and no spend). Nobody could see that happening.
129
+
130
+ The ONLY field is `blocker`, clamped to this fixed enum:
131
+
132
+ no_provider | node | python3 | jq | git | curl | disk | skill_symlink | other
133
+
134
+ Anything not on that list becomes `other`. It is deliberately coarse: `node` is
135
+ enough to act on, and a version string or an install path would be a leak. It
136
+ NEVER sends paths, versions, hostnames, spec text, or command lines -- a test
137
+ (`tests/test-first-run-blocked-signal.sh`) feeds a filesystem path through the
138
+ real emitter and fails the build if anything but `other` reaches the payload.
139
+
117
140
  This document and the first-run notice describe ALL paths. The model is unified:
118
141
  opt-out always wins and disables everything; crash reporting and usage telemetry
119
- opt in together (default ON for individuals); build-outcome analytics needs its
120
- own explicit second opt-in on top (default OFF).
142
+ opt in together (default ON for individuals); build-outcome analytics and the
143
+ first-run blocker each need an explicit second opt-in on top (default OFF).
121
144
 
122
145
  ## What is collected (the whitelist)
123
146
 
@@ -0,0 +1,124 @@
1
+ # Two-year adoption strategy
2
+
3
+ Written 2026-07-31 from measured inputs: registry download data, competitor
4
+ documentation fetched the same day, and benchmark results from this repository.
5
+ Where a claim is inference rather than measurement, it says so.
6
+
7
+ ## The one number that matters
8
+
9
+ **Floor: ~94 downloads/day. Peak: 1,263.** The 13x swing tracks our own
10
+ release activity -- eight releases landed on 07-30. A curve that rises when we
11
+ publish and falls when we stop is CI and mirrors, not word of mouth.
12
+
13
+ Organic growth is a **rising floor**. Everything below is judged against that
14
+ single number, measured on days we ship nothing.
15
+
16
+ Two years from now the question is not "how many releases did we cut." It is
17
+ "what is the floor, and does it rise when we are quiet."
18
+
19
+ ## What we actually sell, stated so it survives a demo
20
+
21
+ Competitor documentation, fetched 2026-07-31:
22
+
23
+ - **Lovable** runs a security scan on every publish and admins can block the
24
+ publish outright.
25
+ - **Claude Code** has a review step that checks findings against actual code
26
+ behavior.
27
+ - **Replit** says its agent tests its own work.
28
+
29
+ So **"we verify and they don't" is false**, and a founder demo against Lovable
30
+ would expose it. That framing is retired.
31
+
32
+ What is true and unoccupied across all seven competitors: **nobody ships a
33
+ persisted, portable, diff-bound artifact.** Theirs live in a dashboard --
34
+ Lovable's is a findings count in a dialog, Claude Code's check run is
35
+ deliberately non-blocking. Ours is a file: bound to a diff by `diff_sha256`,
36
+ recording what was NOT proven as prominently as what was, verifiable by someone
37
+ who never installed us.
38
+
39
+ That is the sentence. Portable, diff-bound, honest about gaps.
40
+
41
+ ## The second thing we sell, now measured
42
+
43
+ **The harness carries quality, not the model.** On `hard-2-ledger`, a task
44
+ authored so a bare model fails it:
45
+
46
+ | arm | result | cost |
47
+ |---|---|---|
48
+ | haiku, harness off | 1/4 passed | $0.86 |
49
+ | haiku, harness on | 1/1 passed | $0.54 |
50
+
51
+ Same model. Same prompt. The harness is the only variable. A correct
52
+ implementation cost **less** than the failing ones, because a cheap failure is
53
+ not cheap.
54
+
55
+ Caveat, stated because it will be checked: n is small and trials are still
56
+ accumulating. This demonstrates the mechanism. The rate needs more trials, and
57
+ those are now worth buying -- before this task existed, the baseline passed
58
+ everything and more trials bought precision around a ceiling.
59
+
60
+ ## Where we win, and where we should not fight
61
+
62
+ **Do not fight on:** hosted preview URLs, visual editing, zero-install browser
63
+ onboarding, managed backend primitives. Those are structural properties of a
64
+ hosted product. Lovable publishes to `[name].lovable.app` free at zero credit
65
+ balance; we cannot and should not try.
66
+
67
+ **Win on the three axes competitors structurally cannot occupy:**
68
+
69
+ 1. **Air-gapped operation.** Measured with egress severed: `version`, `doctor`,
70
+ `plan --json`, `proof verify`, `heal --assess` all return real results. No
71
+ competitor can do this -- "Devin's brain always resides within Cognition's
72
+ Cloud." For defence, government, and regulated banking this is winnable on
73
+ this axis alone. One required egress (model inference), disclosed.
74
+
75
+ 2. **In-place brownfield.** Lovable **cannot import an existing repository at
76
+ all**. Replit and Cursor import into *their* environment. For a private
77
+ monorepo with internal dependencies, that is frequently not permitted. We
78
+ run where the code already lives.
79
+
80
+ 3. **Cost per correct result.** Haiku-plus-harness beat opus-baseline in the
81
+ aggregate at roughly an eighth the cost. If that holds under more trials, it
82
+ is a procurement argument, not a benchmark curiosity.
83
+
84
+ ## The two-year sequence
85
+
86
+ **Year 1, first half -- earn the floor.** Every item judged by whether a first
87
+ run reaches a result. Ship `first_run_blocked` (done, v8.6.0), read what it
88
+ says, fix the top blocker, repeat. The floor is the scoreboard.
89
+
90
+ Concretely already done and testable: 43 of 112 commands were unreachable from
91
+ `loki help` including `loki proof`; a first-run dead end on provider-less hosts;
92
+ `loki proof md` so the receipt travels into a PR or Slack.
93
+
94
+ **Year 1, second half -- make the receipt the artefact people forward.** A
95
+ receipt in a PR is a person showing a colleague. That is the only word-of-mouth
96
+ mechanic available to a CLI, and it costs no infrastructure.
97
+
98
+ **Year 2 -- enterprise pull, not push.** Air-gapped + in-place brownfield +
99
+ signed provenance is a procurement story no competitor can match today. It sells
100
+ to the buyer who cannot use the others at all, and those buyers talk to each
101
+ other.
102
+
103
+ ## What would falsify this
104
+
105
+ Stated so it is checkable rather than reassuring:
106
+
107
+ - **The floor does not rise** over the next quarter despite first-run fixes ->
108
+ the bottleneck is not discoverability, and this plan is wrong.
109
+ - **`first_run_blocked` shows trials dying on something we did not predict** ->
110
+ follow the data, not this document.
111
+ - **The harness lift does not survive more trials** -> the cost argument
112
+ collapses and the differentiator narrows to portability alone.
113
+ - **A competitor ships a portable signed receipt** -> the wedge is gone and we
114
+ compete on cost and air-gap only.
115
+
116
+ ## What is deliberately not here
117
+
118
+ No 80-item backlog. The items that exist are the ones with a measured
119
+ mechanism. Padding this list to look comprehensive would be the fabrication
120
+ this project has already paid for once.
121
+
122
+ Release cadence is explicitly **not** a growth lever: eight releases in one day
123
+ produced a 1,263 spike and a 94 floor. If the floor is the goal, cadence is
124
+ noise.
@@ -0,0 +1,84 @@
1
+ # Adoption baseline, 2026-07-31
2
+
3
+ The first numbers in this project taken from the registry rather than from
4
+ intuition. Recorded so the next measurement has something to compare against.
5
+
6
+ ## What we actually have
7
+
8
+ **4,456 npm downloads in the last 7 days.** Daily:
9
+
10
+ | Day | Downloads |
11
+ |---|---|
12
+ | 07-24 | 863 |
13
+ | 07-25 | 1,160 |
14
+ | 07-26 | 196 |
15
+ | 07-27 | 94 |
16
+ | 07-28 | 386 |
17
+ | 07-29 | 494 |
18
+ | 07-30 | 1,263 |
19
+
20
+ Two things follow, and the second matters more than the first.
21
+
22
+ **1. We have users.** Roughly 4.5k downloads a week is not a project nobody
23
+ has heard of. Every strategy discussion in this repo has proceeded as though
24
+ adoption were hypothetical. It is not.
25
+
26
+ **2. The shape is release-driven, not organic.** The 13x swing between 07-27
27
+ (94) and 07-30 (1,263) tracks publishing activity -- eight releases landed on
28
+ 07-30 alone. A curve that rises when we publish and falls when we stop is
29
+ mirrors and CI, not word of mouth. Organic growth would show a floor that
30
+ rises over time; this shows a floor near 94.
31
+
32
+ **Do not read 4,456 as 4,456 humans.** npm counts mirrors, CI, and Docker
33
+ layer pulls. The honest statement is that the ceiling is real and the floor is
34
+ what needs to move.
35
+
36
+ ## Why the floor is the metric
37
+
38
+ The founder's goal is word-of-mouth growth over two years. The number that
39
+ measures it is the **trough**, not the peak: how many installs happen on a day
40
+ we publish nothing. Today that is ~94.
41
+
42
+ Peaks are bought with releases. Floors are earned by people telling other
43
+ people. Every adoption item should be judged against whether it moves the
44
+ floor.
45
+
46
+ ## What we still cannot see, and what changed today
47
+
48
+ Until v8.6.0 shipped this morning, we could see that a first run was ATTEMPTED
49
+ and nothing about whether it succeeded. `first_run_blocked` (v8.6.0) now names
50
+ the class of dependency that stops a first run -- enum-clamped, once per
51
+ install, strict opt-in.
52
+
53
+ That data does not exist yet: the release is hours old and the telemetry is
54
+ off by default behind a second opt-in. It will accumulate slowly and from a
55
+ minority of users, which is the correct trade for not exfiltrating anyone's
56
+ environment.
57
+
58
+ So the sequence is: floor today ~94/day -> ship things that plausibly move it
59
+ -> watch the floor, not the peak.
60
+
61
+ ## The three things measured this session that plausibly move it
62
+
63
+ Ranked by how directly they affect someone's first ten minutes:
64
+
65
+ 1. **43 of 112 commands were unreachable from `loki help`**, including
66
+ `loki proof` -- the Evidence Receipt, the thing the product argues on. Fixed
67
+ and gated. A user who cannot find the differentiator does not repeat it to
68
+ anyone.
69
+ 2. **A first-run dead end on hosts with no provider CLI.** One route named the
70
+ blockers and pointed at `loki tour` (no provider, no key, no spend); the
71
+ other said "some required prerequisites are missing" and stopped. That is
72
+ the exact moment an evaluator decides whether to continue.
73
+ 3. **`loki proof md`** puts the receipt in a form a person can paste into a PR
74
+ or a Slack message. Competitors' verification output lives in their
75
+ dashboard; a file is the only artifact that travels.
76
+
77
+ None of these is proven to move the floor. They are the candidates with a
78
+ plausible mechanism, and the floor is now being watched.
79
+
80
+ ## Reproduce
81
+
82
+ ```sh
83
+ curl -s "https://api.npmjs.org/downloads/range/last-week/loki-mode"
84
+ ```
@@ -0,0 +1,91 @@
1
+ # Running without egress
2
+
3
+ If your code cannot leave your network, most of this category is unavailable to
4
+ you regardless of what the sales conversation suggests.
5
+
6
+ ## Where the tools actually stand
7
+
8
+ Verified from vendor documentation, 2026-07-31:
9
+
10
+ | Tool | Air-gapped |
11
+ |---|---|
12
+ | Devin | **No.** Single-tenant VPC via AWS PrivateLink, customer-managed KMS, a federal docs tree -- but "Devin's brain... always resides within Cognition's Cloud." |
13
+ | Cursor | No. Cloud service; embeddings are uploaded (obfuscated and encrypted). |
14
+ | Claude Code | Partly. Runs against Bedrock / Vertex / Foundry in your own cloud, so data residency is yours -- but a model endpoint is still required. |
15
+ | Lovable, Replit, Emergent | No. Browser products on their infrastructure. |
16
+ | opencode | Structurally yes (MIT, self-hostable) -- but no SOC2, SSO, audit logs, or support. |
17
+
18
+ Devin's is the strongest enterprise packaging in the category and it still
19
+ cannot run disconnected. That is a structural property of a hosted control
20
+ plane, not an oversight.
21
+
22
+ ## What we measured
23
+
24
+ Executed 2026-07-31 with outbound HTTP forced through an unroutable proxy --
25
+ not a flag, not an assumption. Every one of these returned a real result with
26
+ egress severed:
27
+
28
+ | Command | Result |
29
+ |---|---|
30
+ | `loki version` | works |
31
+ | `loki doctor --json` | works |
32
+ | `loki plan <spec> --json` | works -- full cost and complexity estimate |
33
+ | `loki proof list` | works |
34
+ | `loki proof verify <id>` | works, and correctly reported `tree_drift: true` |
35
+ | `loki heal <repo> --assess --json` | works -- maturity, ranked targets, runtime |
36
+
37
+ The whole evaluate-before-you-buy path runs disconnected. You can assess a
38
+ legacy codebase, estimate what a build would cost, and verify an existing
39
+ receipt without a single packet leaving the machine.
40
+
41
+ `loki proof verify` deserves emphasis: an auditor can re-check a receipt against
42
+ the repository offline and get a genuine verdict, including detecting drift.
43
+ That is the property competitors' dashboard-bound verification cannot have.
44
+
45
+ ## The one required egress, stated plainly
46
+
47
+ ```sh
48
+ loki doctor --airgap
49
+ ```
50
+
51
+ prints the egress inventory. Today it reports exactly one REQUIRED point:
52
+
53
+ ```
54
+ REQUIRED model inference -> https://api.anthropic.com
55
+ Set ANTHROPIC_BASE_URL to an in-network gateway, or switch to a
56
+ local-weights provider.
57
+ optional telemetry [off] disable: loki telemetry off (default off)
58
+ ```
59
+
60
+ **We cannot run a build with no model at all.** Nobody can. What we can do is
61
+ let you point at a model you host: set `ANTHROPIC_BASE_URL` to an in-network
62
+ gateway, or run a provider with local weights. The engine abstracts over CLIs
63
+ rather than over one vendor's API.
64
+
65
+ Telemetry is off by default and every opt-out wins (`DO_NOT_TRACK=1`,
66
+ `LOKI_TELEMETRY=off`, `~/.loki/config`). The adoption instrumentation added in
67
+ v8.6.0 requires a second explicit opt-in on top of that -- see
68
+ [PRIVACY.md](./PRIVACY.md).
69
+
70
+ ## Why `unknown` is the right answer offline
71
+
72
+ `loki heal --assess` reports `dependency_staleness: unknown` and always will
73
+ without a network call. We know your manifest pins lodash 3.x; we do not know
74
+ what is current upstream, and we will not guess.
75
+
76
+ That refusal is what makes the assessment trustworthy inside a disconnected
77
+ network. A tool that fabricates a staleness number offline is more dangerous
78
+ than one that declines.
79
+
80
+ ## Honest limits
81
+
82
+ - **A model endpoint is required.** If you have no model at all -- not local,
83
+ not in-network -- we cannot build anything, and neither can anyone else.
84
+ - **The five mutating healing phases need a provider.** Only `--assess` is
85
+ genuinely zero-dependency.
86
+ - **Not measured here:** a full disconnected build against a local-weights
87
+ provider. The commands above were measured; that one was not, and this page
88
+ does not claim it.
89
+
90
+ See [Kubernetes air-gapped install](../deploy/helm/README.md) for the
91
+ cluster-side path.