@ashlr/hub 3.2.7 → 3.3.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 (149) hide show
  1. package/CHANGELOG.md +268 -0
  2. package/README.md +4 -1
  3. package/dist/build-identity.json +2 -2
  4. package/dist/cli/activation.d.ts +41 -0
  5. package/dist/cli/activation.js +485 -0
  6. package/dist/cli/activation.js.map +1 -0
  7. package/dist/cli/audit.js +18 -0
  8. package/dist/cli/audit.js.map +1 -1
  9. package/dist/cli/backlog.d.ts +0 -5
  10. package/dist/cli/backlog.js +18 -0
  11. package/dist/cli/backlog.js.map +1 -1
  12. package/dist/cli/comms.js +20 -0
  13. package/dist/cli/comms.js.map +1 -1
  14. package/dist/cli/completions.d.ts +6 -1
  15. package/dist/cli/completions.js +35 -11
  16. package/dist/cli/completions.js.map +1 -1
  17. package/dist/cli/daemon.js +10 -3
  18. package/dist/cli/daemon.js.map +1 -1
  19. package/dist/cli/demo.d.ts +0 -27
  20. package/dist/cli/demo.js +17 -0
  21. package/dist/cli/demo.js.map +1 -1
  22. package/dist/cli/help.js +19 -3
  23. package/dist/cli/help.js.map +1 -1
  24. package/dist/cli/inbox.d.ts +14 -2
  25. package/dist/cli/inbox.js +137 -23
  26. package/dist/cli/inbox.js.map +1 -1
  27. package/dist/cli/index.d.ts +1 -0
  28. package/dist/cli/index.js +10 -0
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/cli/onboard.d.ts +0 -13
  31. package/dist/cli/onboard.js +20 -0
  32. package/dist/cli/onboard.js.map +1 -1
  33. package/dist/cli/resources.js +15 -0
  34. package/dist/cli/resources.js.map +1 -1
  35. package/dist/cli/run.js +1 -1
  36. package/dist/cli/run.js.map +1 -1
  37. package/dist/cli/sandbox.js +43 -0
  38. package/dist/cli/sandbox.js.map +1 -1
  39. package/dist/cli/tui.d.ts +0 -6
  40. package/dist/cli/tui.js +14 -0
  41. package/dist/cli/tui.js.map +1 -1
  42. package/dist/core/config.js +70 -0
  43. package/dist/core/config.js.map +1 -1
  44. package/dist/core/daemon/activation-permit.d.ts +268 -33
  45. package/dist/core/daemon/activation-permit.js +1111 -106
  46. package/dist/core/daemon/activation-permit.js.map +1 -1
  47. package/dist/core/daemon/loop.d.ts +13 -1
  48. package/dist/core/daemon/loop.js +192 -9
  49. package/dist/core/daemon/loop.js.map +1 -1
  50. package/dist/core/daemon/runtime-activation-resident-start-protocol.d.ts +141 -0
  51. package/dist/core/daemon/runtime-activation-resident-start-protocol.js +462 -0
  52. package/dist/core/daemon/runtime-activation-resident-start-protocol.js.map +1 -0
  53. package/dist/core/daemon/runtime-activation-resident-start-runtime.d.ts +27 -0
  54. package/dist/core/daemon/runtime-activation-resident-start-runtime.js +28 -0
  55. package/dist/core/daemon/runtime-activation-resident-start-runtime.js.map +1 -0
  56. package/dist/core/daemon/runtime-activation-stopped-consumer.d.ts +139 -0
  57. package/dist/core/daemon/runtime-activation-stopped-consumer.js +995 -0
  58. package/dist/core/daemon/runtime-activation-stopped-consumer.js.map +1 -0
  59. package/dist/core/daemon/runtime-activation-stopped-runtime.d.ts +36 -0
  60. package/dist/core/daemon/runtime-activation-stopped-runtime.js +134 -0
  61. package/dist/core/daemon/runtime-activation-stopped-runtime.js.map +1 -0
  62. package/dist/core/daemon/runtime-activation-transaction.d.ts +41 -17
  63. package/dist/core/daemon/runtime-activation-transaction.js +80 -11
  64. package/dist/core/daemon/runtime-activation-transaction.js.map +1 -1
  65. package/dist/core/daemon/runtime-release-dependency-inventory.js +1 -0
  66. package/dist/core/daemon/runtime-release-dependency-inventory.js.map +1 -1
  67. package/dist/core/daemon/service-install-authority.d.ts +0 -4
  68. package/dist/core/daemon/service-install-authority.js +18 -3
  69. package/dist/core/daemon/service-install-authority.js.map +1 -1
  70. package/dist/core/dashboard.d.ts +10 -0
  71. package/dist/core/dashboard.js +103 -28
  72. package/dist/core/dashboard.js.map +1 -1
  73. package/dist/core/effective-config.js +7 -0
  74. package/dist/core/effective-config.js.map +1 -1
  75. package/dist/core/fleet/automerge-pass.js +33 -0
  76. package/dist/core/fleet/automerge-pass.js.map +1 -1
  77. package/dist/core/fleet/decisions-ledger.js +35 -12
  78. package/dist/core/fleet/decisions-ledger.js.map +1 -1
  79. package/dist/core/fleet/external-skill-git-capture.js +9 -1
  80. package/dist/core/fleet/external-skill-git-capture.js.map +1 -1
  81. package/dist/core/fleet/judge-decision-metadata.d.ts +8 -1
  82. package/dist/core/fleet/judge-decision-metadata.js +14 -1
  83. package/dist/core/fleet/judge-decision-metadata.js.map +1 -1
  84. package/dist/core/fleet/manager.d.ts +15 -1
  85. package/dist/core/fleet/manager.js +108 -30
  86. package/dist/core/fleet/manager.js.map +1 -1
  87. package/dist/core/fleet/post-merge-credit.d.ts +134 -9
  88. package/dist/core/fleet/post-merge-credit.js +350 -10
  89. package/dist/core/fleet/post-merge-credit.js.map +1 -1
  90. package/dist/core/fleet/self-improve.d.ts +34 -1
  91. package/dist/core/fleet/self-improve.js +106 -1
  92. package/dist/core/fleet/self-improve.js.map +1 -1
  93. package/dist/core/fleet/skill-library.d.ts +21 -2
  94. package/dist/core/fleet/skill-library.js +54 -12
  95. package/dist/core/fleet/skill-library.js.map +1 -1
  96. package/dist/core/fleet/status.js +1 -0
  97. package/dist/core/fleet/status.js.map +1 -1
  98. package/dist/core/fleet/worked-ledger.d.ts +22 -0
  99. package/dist/core/fleet/worked-ledger.js +32 -0
  100. package/dist/core/fleet/worked-ledger.js.map +1 -1
  101. package/dist/core/foundry/automerge-scope-policy.d.ts +2 -2
  102. package/dist/core/foundry/automerge-scope-policy.js +9 -2
  103. package/dist/core/foundry/automerge-scope-policy.js.map +1 -1
  104. package/dist/core/goals/store.js +18 -4
  105. package/dist/core/goals/store.js.map +1 -1
  106. package/dist/core/inbox/apply.js +5 -2
  107. package/dist/core/inbox/apply.js.map +1 -1
  108. package/dist/core/inbox/merge.d.ts +94 -1
  109. package/dist/core/inbox/merge.js +349 -16
  110. package/dist/core/inbox/merge.js.map +1 -1
  111. package/dist/core/integrations/github.d.ts +2 -0
  112. package/dist/core/integrations/github.js +2 -1
  113. package/dist/core/integrations/github.js.map +1 -1
  114. package/dist/core/learn/reflect.d.ts +42 -4
  115. package/dist/core/learn/reflect.js +56 -5
  116. package/dist/core/learn/reflect.js.map +1 -1
  117. package/dist/core/run/engines.d.ts +8 -0
  118. package/dist/core/run/engines.js +9 -1
  119. package/dist/core/run/engines.js.map +1 -1
  120. package/dist/core/run/learned-router.js +28 -3
  121. package/dist/core/run/learned-router.js.map +1 -1
  122. package/dist/core/run/orchestrator.d.ts +7 -2
  123. package/dist/core/run/orchestrator.js +86 -60
  124. package/dist/core/run/orchestrator.js.map +1 -1
  125. package/dist/core/swarm/rollback.d.ts +11 -0
  126. package/dist/core/swarm/rollback.js +54 -0
  127. package/dist/core/swarm/rollback.js.map +1 -1
  128. package/dist/core/swarm/runner.js +94 -8
  129. package/dist/core/swarm/runner.js.map +1 -1
  130. package/dist/core/types.d.ts +100 -1
  131. package/dist/core/types.js.map +1 -1
  132. package/dist/core/web/api.js +105 -7
  133. package/dist/core/web/api.js.map +1 -1
  134. package/dist/core/web/control.d.ts +20 -0
  135. package/dist/core/web/control.js +44 -32
  136. package/dist/core/web/control.js.map +1 -1
  137. package/dist/core/web/fleet-status-cache.d.ts +68 -0
  138. package/dist/core/web/fleet-status-cache.js +120 -0
  139. package/dist/core/web/fleet-status-cache.js.map +1 -0
  140. package/dist/core/web/public/next/assets/index-CY0U241s.css +1 -0
  141. package/dist/core/web/public/next/assets/index-Ct0mf8n4.js +69 -0
  142. package/dist/core/web/public/next/assets/index-Ct0mf8n4.js.map +1 -0
  143. package/dist/core/web/public/next/index.html +15 -0
  144. package/dist/release-dependency-inventory.json +1 -1
  145. package/docs/RUNTIME_ACTIVATION_AUTHORITY.md +126 -21
  146. package/docs/contracts/CONTRACT-M521.md +102 -0
  147. package/package.json +20 -3
  148. package/schema/config.schema.json +800 -5
  149. package/node_modules/which/CHANGELOG.md +0 -166
package/CHANGELOG.md CHANGED
@@ -11,6 +11,274 @@ hub (M1–M20). Entries below detail each milestone; dates are merge dates into
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [3.3.0] — 2026-08-17 — Fleet activation, autonomous merge, and the operator console
15
+
16
+ ### 2026-08-16 — Fleet activation unblocked, autonomous merge wired, learning loop closed
17
+
18
+ Nine threads landed together: the daemon activation-authority system that had
19
+ been unconditionally denying itself was replaced with a real granted-scope
20
+ check, and the bug that made it self-invalidate every permit was fixed; the
21
+ previously dead-code autonomous-merge revocation protocol got its first
22
+ caller; the fleet's self-improvement loop went from recording zero lessons on
23
+ rejection to recording them from every rejection; a test-isolation escape that
24
+ had corrupted the operator's real `~/.ashlr/daemon.json` for 11 days was
25
+ closed fail-closed; and a new React operator console shipped alongside the
26
+ untouched legacy dashboard. Milestone-level detail and today's newly
27
+ discovered ID collision are in
28
+ [`docs/MILESTONE-INDEX.md`](docs/MILESTONE-INDEX.md); the mechanics of
29
+ turning any of this on — including four non-obvious gates that block
30
+ unattended activation even after a grant — are in
31
+ [`docs/RUNTIME-FLEET-ACTIVATION.md`](docs/RUNTIME-FLEET-ACTIVATION.md).
32
+
33
+ - **Daemon activation authority replaces its own denials (M470 — see
34
+ collision note below).** Five hard-coded refusals — `DAEMON_ACTIVATION_TRUST_ROOTS`
35
+ frozen empty, `liveConductorActivationAuthorized()` returning a literal
36
+ `false`, `assertResidentServiceInstallAuthorized()` throwing
37
+ unconditionally, and two more in the same family — are replaced by a real
38
+ check against an operator-owned trust-root store (`~/.ashlr/activation/`,
39
+ 0700/0600, owner-checked, fail-closed on missing/malformed to the
40
+ *identical* prior denial) and Ed25519-signed, expiring, revocable standing
41
+ grants across nine scopes: `once`, `resident`, `residentStanding`,
42
+ `conductor`, `automerge`, `repair`, `deploy`, `install`, `proposalOnly`
43
+ (`src/core/daemon/activation-permit.ts:121-131`). `residentStanding` is
44
+ new — the scope that lets the daemon restart unattended; it is not implied
45
+ by `resident` and must be granted explicitly.
46
+
47
+ Root-cause bug fixed in the same change: `daemonActivationAuthorityStateDigest()`
48
+ folded `~/.ashlr`'s own directory mtime into the digest a permit is
49
+ checked against, but `daemon start`'s `acquireDaemonLock()`
50
+ (`src/core/daemon/state.ts`) creates `~/.ashlr/daemon.lock` — a new direct
51
+ child of `~/.ashlr` — *before* the permit is ever consumed, bumping that
52
+ same mtime. Every freshly minted permit self-invalidated, 100%
53
+ reproducibly, before it could be used — the fleet could never have
54
+ activated unattended even with a valid grant. Fixed to key the digest on
55
+ the directory's `dev`+`ino` instead, which survive ordinary child churn
56
+ (`src/core/daemon/activation-permit.ts:961-997`).
57
+
58
+ **ID collision introduced today:** `test/m470.activation-authority.test.ts`
59
+ reuses milestone number M470, which was already assigned to the
60
+ already-shipped "proposal capture candidate identity"
61
+ (`test/m470.proposal-capture-candidate-identity.test.ts`; see the M464–M503
62
+ entry below). Recorded as a new row in `docs/MILESTONE-INDEX.md` §2.
63
+
64
+ - **Autonomous PR merge gets its first caller (M504, M505).** The durable
65
+ merge-revocation protocol (`src/core/autonomy/host-merge-revocation-protocol.ts`)
66
+ existed with zero callers before today; it is now invoked from
67
+ `attemptHostAutoMerge()` (`src/core/merge.ts:2845-2901`), gated behind
68
+ `foundry.autoMerge.hostAutoMerge`, which **defaults to `false`**
69
+ (`src/core/merge.ts:2795`; `test/m505.host-auto-merge.test.ts` pins the
70
+ default-off behavior). A `failureCategory`
71
+ (`'code' | 'tool' | 'timeout' | 'infra' | 'cancelled' | 'invalid-command'`,
72
+ `src/core/run/verify-commands.ts:86-92`) is now threaded through
73
+ verify-commands, verify, run-tests, merge, the detached post-merge
74
+ runner/verification, the regression sentinel, and self-heal — exit 127
75
+ (missing binary) now classifies as `'tool'`, not a broken diff. `git apply
76
+ --3way` is now used in both `verifyProposal` and `attemptHostAutoMerge`
77
+ (`src/core/merge.ts:2313, 2984`) so a stale base no longer reads as a real
78
+ conflict. The self-eval parity gate — previously a single flaky
79
+ invariant-test failure was a GLOBAL merge blocker — now retries up to
80
+ `SELF_EVAL_PARITY_RETRY_ATTEMPTS = 2` times with a 500ms delay before
81
+ failing (`src/core/merge.ts:265-267`).
82
+
83
+ - **Learning loop closed; judge parse failures stop posing as verdicts.**
84
+ `hasReleasedPostMergeCredit()` (`src/core/fleet/post-merge-credit.ts:137-150`)
85
+ no longer hardcodes `false` — it verifies an HMAC-signed, timing-safe-compared
86
+ token — unblocking consumers across `learned-router.ts`,
87
+ `skill-attestation.ts`, `feedback.ts`, `quality-metrics.ts`,
88
+ `judge-trace.ts`, and `post-merge-credit.ts` itself. `learnFromRejection`
89
+ is no longer reachable only when auto-merge is on: a new
90
+ `sweepRejectionLearning()` (`src/core/fleet/self-improve.ts`) reads the
91
+ decisions ledger directly and learns from rejections regardless of the
92
+ auto-merge flag. (The commit message cites 672 rejections the fleet had
93
+ never learned from while auto-merge defaulted off; that figure is the
94
+ author's estimate, not a value stored or checked anywhere in `src/` or
95
+ `test/` — do not repeat it as a verified count.) `curateAntiPlaybooks()`
96
+ (`src/core/fleet/self-improve.ts:284-322`), previously unreferenced, now
97
+ has a caller in `src/core/fleet/orchestrator.ts:1338`. Separately, a July
98
+ refactor had given every real judge verdict a reason code but not the
99
+ parse-failure fallback — parse failures were structurally indistinguishable
100
+ from considered reviews and incremented `judgeNonShipCount`, pushing good
101
+ proposals toward auto-archive. Parse failures now get their own
102
+ `'judge-parse-failure'` reason code (`src/core/fleet/judge-decision-metadata.ts:20`)
103
+ and are excluded from `judgeNonShipCount` entirely
104
+ (`src/core/fleet/automerge-pass.ts:335-337`).
105
+
106
+ - **Test isolation: HOME escape closed fail-closed.** On 2026-08-05 a vitest
107
+ run escaped HOME isolation and wrote the operator's real
108
+ `~/.ashlr/daemon.json`, leaving the daemon unstartable for 11 days. Cause:
109
+ `test/setup/home.ts` fell back to the real `os.homedir()` whenever
110
+ `process.env.HOME` was unset — fail-open. It now throws immediately if
111
+ `HOME` is unset or resolves to the real developer home
112
+ (`test/setup/home.ts:52-65`).
113
+
114
+ - **Fleet-status cache correction.** `GET /api/fleet` no longer performs
115
+ API-side response recomposition (`src/core/web/api.ts`, pinned by
116
+ `test/build-identity.test.ts`) — a response-shape fix, landed today. The
117
+ shared TTL cache for `buildFleetStatus()`
118
+ (`src/core/web/fleet-status-cache.ts`: 5s TTL, stale-while-refresh to 60s,
119
+ in-flight dedup) landed with the new console earlier this week, not today.
120
+ **The "32.5s cold → 4.0s cold / 0ms warm" figures reported for this work do
121
+ not appear anywhere in the code, tests, or the cache module's own
122
+ documentation and could not be verified — do not repeat them.** The cache
123
+ module's comment instead cites a worse pre-fix baseline (`/api/snapshot`
124
+ 2.4s idle → 69.4s under load; `/api/control` similarly degraded). Call-site
125
+ count is also imprecise across sources: the cache module's comment says
126
+ six, a test comment says seven, a source grep finds eleven — the true
127
+ count depends on what "independent call site" means and isn't settled.
128
+
129
+ - **New operator console (`src/web-ui/`).** React 19 + Vite 6, served at
130
+ `/next/` alongside the untouched legacy vanilla-JS SPA at `/`
131
+ (`vite.config.web.ts:11-26`, `src/core/web/static.ts:87-88`). **16 views**
132
+ (not the 13 originally reported), a chart layer
133
+ (`src/web-ui/components/charts/`), a work journal
134
+ (`src/web-ui/routes/journal/`), live run streaming
135
+ (`src/web-ui/components/stream/`, `useRunStream.ts`), and a notification
136
+ centre (`src/web-ui/components/notifications/`). Backend changes were
137
+ minimal and additive — query-param filtering on `src/core/web/api.ts` for
138
+ the inbox history view — not a rewrite; `server.ts`/`static.ts` routing is
139
+ unchanged.
140
+
141
+ - **Two activation designs now formally coexist; the guard protecting the
142
+ boundary between them was strengthened, not weakened.**
143
+ `conductor-permit` (`src/core/daemon/goal-conductor-permit-operator.ts`,
144
+ offline cold-custody, used by the goal conductor — M516–M518) and
145
+ `activation` (`src/core/daemon/activation-permit.ts`, on-machine standing
146
+ grants, M470 above) are separate modules with non-overlapping imports. The
147
+ test protecting this boundary used to check that a file
148
+ (`src/cli/activation.ts`) did not exist by name — a check that would have
149
+ broken the moment that file needed to exist for a legitimate, unrelated
150
+ reason. It now asserts the real invariant: the daemon activation CLI's
151
+ source text must not match any conductor-authority symbol name
152
+ (`test/m518.goal-conductor-permit-operator.test.ts:924-926`) — conductor
153
+ authority must be unreachable from the daemon surface, not merely absent
154
+ from a filename.
155
+
156
+ ### 2026-08-16 — Live-data web UI crash and TITRR proposal-quality fixes
157
+
158
+ - **`/work/swarms` crashed on real fleet data; a route error boundary now
159
+ contains that class of bug.** `SwarmsView` and `SwarmDetailView` read
160
+ `sw.plan.tasks.length` and `sw.usage.tokensIn` unguarded; two of eighty real
161
+ swarm records (legacy smoke-test runs) carry neither field, so the view
162
+ threw, React unmounted the root, and the screen went blank with no recovery
163
+ short of a hard reload. Both reads are now guarded, and a new
164
+ `RouteErrorBoundary` (`src/web-ui/components/primitives/RouteErrorBoundary.tsx`)
165
+ wraps the route outlet so a failing view renders an inline error card with
166
+ retry while the sidebar, topbar, and command palette stay alive — the
167
+ durable fix; the optional chaining is the specific one.
168
+ - **Crushed tables got their column widths back.** The inbox proposal table
169
+ had no fixed layout, so auto-layout divided space evenly across seven
170
+ columns and crushed `Title` to roughly one word per line. The same pattern
171
+ — traced to the Fleet Dashboard's Recent Runs panel, which `DESIGN.md`
172
+ names as the reference other views copy — also affected Runs' goal column,
173
+ where a single multi-paragraph prompt could balloon one row past the
174
+ viewport. All three (`src/web-ui/routes/inbox/ProposalList.tsx`,
175
+ `src/web-ui/routes/fleet-dashboard/RunsPanel.tsx`,
176
+ `src/web-ui/routes/work/runs/RunsView.tsx`) now use fixed layout with
177
+ explicit column widths and a shared two-line clamp utility. GenomeView's
178
+ plain "Loading…" text was also swapped for the SkeletonRow convention used
179
+ everywhere else, noticeable because that endpoint takes ~6s for 2014
180
+ entries.
181
+ - **TITRR stopped filing proposals it already knew had failed verification.**
182
+ `TITRR_MAX_ATTEMPTS` was hardcoded to 2 ("1 initial + 1 repair"); on
183
+ exhausting it with tests still failing, the loop unconditionally filed the
184
+ diff anyway via `captureTitrrProposal({isPartial:true,
185
+ forceGateBlockReason})` — the root cause of `[partial]` proposals that
186
+ could never pass verification, and, per the fix commit's own estimate (not
187
+ a value stored or checked anywhere in `src/` or `test/` — do not repeat it
188
+ as a verified count), a large share of the 672 proposals the fleet had
189
+ never merged. `TITRR_MAX_ATTEMPTS` is raised to 4, and exhaustion now drops
190
+ with no proposal at all rather than filing an unverifiable one; the
191
+ annotation is kept on the run for audit but nothing reaches the inbox.
192
+
193
+ ### M464–M503 — daemon durability, post-merge verification pipeline, Mission OS extensions
194
+
195
+ Forty milestones landed on `master` with no CHANGELOG entry; this backfills
196
+ them by theme. Full per-milestone detail, file:line citations, and the four
197
+ that warrant a standalone contract are indexed in
198
+ [`docs/MILESTONE-INDEX.md`](docs/MILESTONE-INDEX.md) §5. Gaps M474, M483,
199
+ M489, M499, M500 have no corresponding test file or milestone.
200
+
201
+ - **Daemon crash-safety and recovery (M486, M487, M490, M501, M488, M476).**
202
+ Daemon accounting writes now cross an fsync power-loss barrier (temp write +
203
+ fsync, rename, directory fsync) before being reported durable (M486). A new
204
+ authorized quarantine flow hard-links crash-suspect daemon state into
205
+ immutable evidence with a signed receipt and a 10-minute plan expiry (M487),
206
+ and a paired resolution flow consumes that receipt to produce fresh state
207
+ that conservatively carries forward same-day spend accounting when it can
208
+ be verified (never silently resets a daily budget to zero), refusing while
209
+ service activity or execution retries are in flight (M501). Both are wired into the CLI as explicit, authorization-gated
210
+ subcommands (`recover-state` / `resolve-state`, M490). Runtime-release
211
+ canary/rollback pairs get an observation-only signature and digest check
212
+ with no deployment authority (M488). Release-tip observations are recorded
213
+ in an immutable, HMAC-sealed, no-clobber sequence ledger — not a
214
+ transparency log or release authority (M476).
215
+
216
+ - **Detached post-merge verification pipeline (M465, M466, M467, M468, M472,
217
+ M478, M482).** Auto-merge canary promotion readiness is evaluated
218
+ observation-only against verification coverage, release evidence, and
219
+ post-merge cohorts — it never grants activation (M465). Diff scope for
220
+ auto-merge is measured with fail-closed rejection of symlinks, gitlinks,
221
+ and malformed patch headers, alongside a durable prepared→armed→revoked
222
+ host-merge cancellation state machine (M466). Post-merge verification
223
+ cohorts are recorded as signed, immutable, metadata-only records —
224
+ explicitly excluding prompts, diffs, and command output — and can neither
225
+ authorize merge nor rollback (M467). A runner checks out one exact commit
226
+ into a scratch worktree, runs the repo's own verification profile, and
227
+ records only bounded pass/fail metadata before cleanup (M468), scheduled by
228
+ an observation-only orchestrator that emits at most one work ticket per
229
+ invocation (M472). Root verification contracts are detected read-only from
230
+ each repo's own manifests (`package.json`, `tsconfig.json`,
231
+ `vitest.config.ts`, …) without ever spawning a package manager (M478).
232
+ Release artifacts get a dependency-inventory + manifest-integrity contract
233
+ with hard size caps (M482).
234
+
235
+ - **Proposal funnel + capture identity (M464, M469, M470, M471, M473,
236
+ M475).** Agent work lifecycle transitions are now recorded as a
237
+ metadata-only, cryptographically-chained audit trail with a closed
238
+ vocabulary of phases/transitions/triggers — no raw prompts, diffs, or file
239
+ paths (M464). Proposal-funnel metrics (attempts, capture errors, policy
240
+ suppressions, gate blocks) are scrubbed before aggregation and withheld on
241
+ unstable snapshots rather than guessed (M469). Proposal capture now binds a
242
+ durable candidate identity from sandboxed execution (M470), settled through
243
+ a transactional claim/settle/reconcile task store with compare-and-swap
244
+ leases (M471). A new verifier-execution-authority layer admits signed,
245
+ data-only capsule statements against caller-pinned trust policies (M473),
246
+ gated by a separate crypto-only policy-approval observation that itself
247
+ signs, persists, or executes nothing (M475).
248
+
249
+ - **Mission OS extensions (M485, M491, M492, M493, M494, M495, M496, M497,
250
+ M502).** The mission compiler reconciles goals from briefings — respecting
251
+ dependencies, active-goal caps, and human gates, rejecting cycles — behind
252
+ a read-only operator briefing UI (M485). Ecosystem-wide mission graphs
253
+ compile deterministically into one cycle-checked, digested structure bounded
254
+ to 24 nodes (M491), projected through a fail-closed, mutation-free "outcome
255
+ room" view (M492). Mission state can now be captured into a signed,
256
+ durable observation receipt carrying no execution authority (M493), and a
257
+ shadow reconciler suggests — but never creates — up to 16 candidate goals
258
+ per preview, verified against that receipt (M494). External ecosystem
259
+ inputs (Cortex mission candidates, Locus identity evidence) get bounded,
260
+ fail-closed-on-expiry validation schemas that import no authority (M495).
261
+ Mission observations are captured only from authenticated, realized-merge
262
+ proposals (M496), and both the read-only shadow observer (M502) and its
263
+ CLI entry point (`vision shadow`, M497) prove the whole planning loop can
264
+ run end-to-end with zero effect.
265
+
266
+ - **Supply-chain and dashboard hardening (M477, M480, M481, M479, M498,
267
+ M503, M484).** Public JSON payloads are scrubbed of secret-shaped strings
268
+ and home-directory paths and de-recursed before they reach the dashboard or
269
+ API (M477). The dashboard's mobile shell keeps navigation in one
270
+ horizontally-scrollable row (M480). Every action in every CI workflow is
271
+ now pinned to a reviewed immutable commit (M481), and the npm release
272
+ workflow additionally validates the release tag's target commit is in
273
+ protected `master` history before `npm publish --provenance` runs (M479).
274
+ Best-of-N's `-n` CLI flag is validated before config or model loading —
275
+ rejecting non-integers, floats, zero, negative, and unsafe-integer values
276
+ with exit code 2 (M498). The dashboard gained a read-only auth mode that
277
+ permits SSE and reads but blocks all mutating endpoints (M503). PR stack
278
+ topology (linearity, dependency correctness, convergence declarations) is
279
+ now shadow-observed read-only against GitHub with no mutation capability
280
+ (M484).
281
+
14
282
  ## [3.2.7] — 2026-08-16 — Immutable candidate supersession
15
283
 
16
284
  - Carries forward the immutable 3.2.6 candidate and all subsequently merged
package/README.md CHANGED
@@ -548,7 +548,8 @@ preflight soft-warns *consider locus.firm for production* (non-blocking).
548
548
  | **v2** (M21–M30) | Autonomous org — sandboxed swarms, Approval Inbox, enrollment, kill-switch | Shipped |
549
549
  | **v2.1** (H1–H8) | Harden and prove — adversarial test suite, safety invariants proven by tests | Shipped |
550
550
  | **v2.2** (M31–M33) | Agent-native — plugin system, Raycast, update channel | Shipped |
551
- | **v3** (M34–M44) | Team + Local Weapon — multi-machine inbox, adaptive prompts, verify→repair, eval | Shipped |
551
+ | **v3-Weapon** (M41–M44) | Local Weapon — adaptive model-sized prompts, sandboxed engineer tool surface, verify→repair, eval | Shipped |
552
+ | **v3-Team** (M34–M40) | Team Command Center — multi-machine inbox, coordinated daemons, team visibility | **Spec'd, not built** — see [`docs/SPEC-V3-TEAM.md`](docs/SPEC-V3-TEAM.md) |
552
553
  | **v4** (M45–M49) | Foundry — multi-backend engines, backend router, tiered-trust merge gate, HMAC provenance, fleet supervisor | Shipped |
553
554
  | **v5** (M50–M55) | Open Fleet — declarative engine registry, tri-tier trust, OS confinement, fleet intelligence, self-improving fleet, goal/loop conductor | Shipped |
554
555
  | **v5.1** (M320–M324) | Claude 5 Model Intelligence — Sonnet 5 workhorse routing, Fable 5 judge with Opus fallback, per-model ROI telemetry, cost-aware learned routing | Shipped |
@@ -572,9 +573,11 @@ See [`docs/ECOSYSTEM-MAP.md`](docs/ECOSYSTEM-MAP.md) for the full capability map
572
573
  | Doc | What it covers |
573
574
  |-----|----------------|
574
575
  | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Module map, the autonomous loop, engine tiers, safety gates, the `~/.ashlr/` layout |
576
+ | [`docs/MILESTONE-INDEX.md`](docs/MILESTONE-INDEX.md) | Authoritative milestone ID → subject → status lookup (M2–M519), incl. confirmed ID collisions (spec-vs-shipped and shipped-vs-shipped) |
575
577
  | [`docs/MISSION-OS.md`](docs/MISSION-OS.md) | Mission DAG, receipts, shadow workflow, Cortex/Locus boundaries, privacy, and troubleshooting |
576
578
  | [`docs/ELITE-AGENT-EFFICIENCY.md`](docs/ELITE-AGENT-EFFICIENCY.md) | Current primary-source research translated into Hub efficiency priorities and measurable autonomy gates |
577
579
  | [`docs/RUNTIME_ACTIVATION_AUTHORITY.md`](docs/RUNTIME_ACTIVATION_AUTHORITY.md) | Signed read-only resident activation admission, explicit mutation refusal, and native launchd v2 requirements |
580
+ | [`docs/RUNTIME-FLEET-ACTIVATION.md`](docs/RUNTIME-FLEET-ACTIVATION.md) | How to actually turn on an unattended, resident fleet — operator standing grants (`ashlr activation`) and the four gates that block it even after a grant |
578
581
  | [`docs/ECOSYSTEM-MAP.md`](docs/ECOSYSTEM-MAP.md) | The 13-repo platform and composition bets |
579
582
  | [`docs/QUICKSTART.md`](docs/QUICKSTART.md) | Step-by-step first activation |
580
583
  | [`docs/LOCUS-FIRM-FLEET.md`](docs/LOCUS-FIRM-FLEET.md) | Production fleet checklist — `locus.firm`, `LOCUS_ENFORCE`, `LOCUS_CI_BINDING` (default off) |
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "3.2.7",
4
- "revision": "73931bdd31b3b4e4d905a30b5112e4cd712f7844",
3
+ "packageVersion": "3.3.0",
4
+ "revision": "d07f6a96eda664d865b9255f71c6f56e8cd9d7c7",
5
5
  "dirty": false,
6
6
  "provenance": "git"
7
7
  }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `ashlr activation` — operator authority for the autonomous fleet (M470).
3
+ *
4
+ * The daemon, goal/simple conductors, and resident-service install are all
5
+ * held shut by hard-coded denials until an operator EXPLICITLY grants
6
+ * authority here. Doing nothing keeps today's exact behavior: everything
7
+ * denied. This command group is how an operator opts in, on their own
8
+ * terms, with a real signed/expiring/revocable authorization trail.
9
+ *
10
+ * Subcommands:
11
+ * activation init [--label <text>] [--force] [--yes] [--json]
12
+ * Generate an Ed25519 keypair on this machine (private key never
13
+ * leaves it) and register the public half as a trust root. Grants
14
+ * NOTHING by itself — run `activation grant` next.
15
+ * activation status [--json]
16
+ * Trust roots, pending one-shot permit, standing grants, and what is
17
+ * currently authorized, right now, and why.
18
+ * activation grant <scope...> [--ttl <duration>] [--yes] [--json]
19
+ * Mint a scoped, signed, expiring authorization. `once`/`resident`
20
+ * mint a single-use permit for `ashlr daemon start`, good for a fixed
21
+ * 2-minute window; any of `residentStanding`/`conductor`/`automerge`/
22
+ * `repair`/`deploy`/`install`/`proposalOnly` mint a standing grant
23
+ * checked on every use until it expires (30d cap) or is revoked.
24
+ * `residentStanding` is what lets a resident daemon started by
25
+ * launchd/systemd/Task Scheduler after a reboot authorize itself with
26
+ * no operator present — grant it once, ahead of time, alongside
27
+ * whichever of `automerge`/`repair`/`deploy` the resident loop should
28
+ * also carry for its whole run.
29
+ * activation revoke --root <keyId> | --grant <grantId> [--yes] [--json]
30
+ * Immediately invalidate a trust root or a standing grant.
31
+ *
32
+ * Every subcommand supports --help. Mutating subcommands (init/grant/revoke)
33
+ * refuse to run unattended in a non-TTY session without --yes — the same
34
+ * confirm-gate convention as `ashlr inbox approve`.
35
+ */
36
+ /**
37
+ * `ashlr activation [init|status|grant|revoke] [flags]`
38
+ *
39
+ * Returns a process exit code (0 = success, non-zero = error/usage).
40
+ */
41
+ export declare function cmdActivation(args: string[]): Promise<number>;