instar 1.3.575 → 1.3.577

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 (58) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +42 -0
  3. package/dist/commands/server.js.map +1 -1
  4. package/dist/config/ConfigDefaults.d.ts.map +1 -1
  5. package/dist/config/ConfigDefaults.js +14 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CommitmentMutation.d.ts +1 -1
  8. package/dist/core/CommitmentMutation.d.ts.map +1 -1
  9. package/dist/core/CommitmentMutation.js +32 -0
  10. package/dist/core/CommitmentMutation.js.map +1 -1
  11. package/dist/core/CommitmentsSync.d.ts.map +1 -1
  12. package/dist/core/CommitmentsSync.js +20 -1
  13. package/dist/core/CommitmentsSync.js.map +1 -1
  14. package/dist/core/MeshRpc.d.ts +1 -1
  15. package/dist/core/MeshRpc.d.ts.map +1 -1
  16. package/dist/core/MessagingToneGate.d.ts +22 -0
  17. package/dist/core/MessagingToneGate.d.ts.map +1 -1
  18. package/dist/core/MessagingToneGate.js +27 -1
  19. package/dist/core/MessagingToneGate.js.map +1 -1
  20. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  21. package/dist/core/PostUpdateMigrator.js +8 -0
  22. package/dist/core/PostUpdateMigrator.js.map +1 -1
  23. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  24. package/dist/core/devGatedFeatures.js +6 -0
  25. package/dist/core/devGatedFeatures.js.map +1 -1
  26. package/dist/core/internal-id-leak.d.ts +23 -0
  27. package/dist/core/internal-id-leak.d.ts.map +1 -0
  28. package/dist/core/internal-id-leak.js +38 -0
  29. package/dist/core/internal-id-leak.js.map +1 -0
  30. package/dist/core/parked-on-user.d.ts +25 -0
  31. package/dist/core/parked-on-user.d.ts.map +1 -0
  32. package/dist/core/parked-on-user.js +49 -0
  33. package/dist/core/parked-on-user.js.map +1 -0
  34. package/dist/core/ws2SendWiring.d.ts +0 -3
  35. package/dist/core/ws2SendWiring.d.ts.map +1 -1
  36. package/dist/core/ws2SendWiring.js +1 -4
  37. package/dist/core/ws2SendWiring.js.map +1 -1
  38. package/dist/monitoring/CommitmentTracker.d.ts +107 -0
  39. package/dist/monitoring/CommitmentTracker.d.ts.map +1 -1
  40. package/dist/monitoring/CommitmentTracker.js +156 -0
  41. package/dist/monitoring/CommitmentTracker.js.map +1 -1
  42. package/dist/monitoring/PromiseBeacon.d.ts +60 -0
  43. package/dist/monitoring/PromiseBeacon.d.ts.map +1 -1
  44. package/dist/monitoring/PromiseBeacon.js +165 -19
  45. package/dist/monitoring/PromiseBeacon.js.map +1 -1
  46. package/dist/scaffold/templates.d.ts.map +1 -1
  47. package/dist/scaffold/templates.js +10 -0
  48. package/dist/scaffold/templates.js.map +1 -1
  49. package/dist/server/routes.d.ts.map +1 -1
  50. package/dist/server/routes.js +99 -2
  51. package/dist/server/routes.js.map +1 -1
  52. package/package.json +1 -1
  53. package/src/data/builtin-manifest.json +63 -63
  54. package/src/scaffold/templates.ts +10 -0
  55. package/upgrades/1.3.576.md +52 -0
  56. package/upgrades/1.3.577.md +29 -0
  57. package/upgrades/side-effects/agent-owned-followthrough.md +73 -0
  58. package/upgrades/side-effects/ws2-send-2b-userregistry.md +48 -0
@@ -0,0 +1,29 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ **The Agent Carries the Loop (C1+C2)** — the structural enforcement of a new constitution standard (ratified by Justin, 2026-06-13/14): a commitment is the agent's obligation to *act*, never the user's to *remember*. The user is pulled in only for a usable result or a genuine authorization the agent lacks — never to be the agent's memory or to-do list.
9
+
10
+ Commitments now carry two orthogonal fields — `owner` (agent | user) ⟂ `blockedOn` (none | external | user-input | user-authorization). Agent-owned commitments drive the agent (the PromiseBeacon suppresses status pings to the user via a new `emitUserSend()` chokepoint); the user hears from the agent only on a result. Nothing can park silently forever: an external-blocked commitment must record falsifiable dependency-probes (`POST /commitments/:id/probe`), and a forever-wait raises ONE honest Attention dead-letter past a window/ceiling — never a nag, never silence. A terminal failure is rerouted to the dead-letter, never swallowed. Stale promises auto-close ONLY on objective evidence (a superseder reaching terminal-success); "abandoned" is never auto-closed (the CMT-1101 scar). Two signal-only detectors (B19 parked-on-user, B20 internal-id-leak) feed `MessagingToneGate`. A guarded `POST /commitments/:id/transition` allows in-place state changes that re-run the gate.
11
+
12
+ Ships **dark on the fleet / live-in-dry-run on the development agent** (`commitments.agentOwnedFollowthrough`): on a dev agent the owner-gate, governor, and reconciler run the full decision loop and *log* what they would do, but suppress/mutate nothing until a deliberate `dryRun:false` flip. The autonomy ratchet ("Blockers Are Autonomy Opportunities") is carved to a tracked follow-on (`agent-autonomy-ratchet`).
13
+
14
+ ## What to Tell Your User
15
+
16
+ Nothing to announce for fleet users yet — this ships **dark** (off on the fleet) and runs in **dry-run only** on the development agent first (it watches and logs, changing no behavior). It is the groundwork for a real improvement: going forward, when the agent promises to do something, *the agent* owns following through — you'll never be asked to remember or chase it; you'll hear back only when there's a result or a genuine approval only you can give. The behavior change reaches you only after it has soaked safely in dry-run and is deliberately promoted.
17
+
18
+ ## Summary of New Capabilities
19
+
20
+ - `POST /commitments/:id/probe` — record an external-dependency probe (resets the staleness window).
21
+ - `POST /commitments/:id/transition` — guarded in-place owner/blockedOn change (re-runs the well-formedness gate).
22
+ - `owner` / `blockedOn` / `actionClass` / `supersededBy` fields on commitments (back-filled for existing agents).
23
+ - Config: `commitments.agentOwnedFollowthrough` (dark-on-fleet / live-in-dry-run-on-dev; tuning dials for the staleness window/ceiling/sweep).
24
+
25
+ ## Evidence
26
+
27
+ - 244 tests green across the C1+C2 suites: unit (state model, owner-gate chokepoint, external-block governor, evidence-gated reconciler, signal detectors, sync-clamp, transitions) + the E2E "feature is alive" test (probe/transition routes return real results through the production AgentServer; owner/blockedOn round-trip; forward gate returns 400 over HTTP).
28
+ - `npx tsc --noEmit`: 0 errors. Existing suites unaffected (beacon, tone-gate, CommitmentsSync, ConfigDefaults, dev-gate wiring, feature-completeness, standards-registry guards).
29
+ - Converged spec (`docs/specs/agent-owned-followthrough.md`, 5 rounds + cross-model codex/gemini) + side-effects review + independent second-pass concur.
@@ -0,0 +1,73 @@
1
+ # Side-Effects Review — The Agent Carries the Loop (agent-owned-followthrough, C1+C2)
2
+
3
+ **Version / slug:** `agent-owned-followthrough`
4
+ **Date:** 2026-06-14
5
+ **Author:** echo
6
+ **Second-pass reviewer:** required (touches PromiseBeacon / MessagingToneGate / reconciler auto-close) — see Phase 5 appendix.
7
+
8
+ ## Summary of the change
9
+
10
+ Implements C1+C2 of the "The Agent Carries the Loop" spec (converged + operator-ratified 2026-06-14): a commitment is the agent's obligation to act, never the user's to remember; the user is pinged only for a result or a genuine authorization. Adds an `owner` ⟂ `blockedOn` state model to `Commitment` (`CommitmentTracker.ts`) with `record()`/`transitionState()` well-formedness gates + `loadStore()` back-fill; an owner-gated outbound chokepoint `PromiseBeacon.emitUserSend()` (suppresses agent-owned status sends, reroutes terminal failures to the Attention dead-letter); an external-block staleness governor (`sweepExternalBlocks()`) + `POST /commitments/:id/probe` + absolute ceiling; an evidence-gated graveyard reconciler (`reconcileGraveyard()`); a guarded `POST /commitments/:id/transition` route; a `commitments-sync` receive enum-clamp (`CommitmentsSync.applyPage`); two signal-only detectors (`parked-on-user.ts`, `internal-id-leak.ts`) feeding new `MessagingToneGate` rules B19/B20 + a beacon-local B-IDLEAK pass; server wiring of the `agentOwnedFollowthrough` resolver into `PromiseBeacon` (developmentAgent gate, sweeps lease-gated); config defaults + dev-gate registry entry + `migrateClaudeMd`/`generateClaudeMd` + the ratified constitution article. Ships dark-on-fleet / live-in-dryRun-on-dev.
11
+
12
+ ## Decision-point inventory
13
+
14
+ - `MessagingToneGate` B19_PARKED_ON_USER / B20_INTERNAL_ID_LEAK — **add** — signal-driven LLM-authority rules; the brittle detectors only flag.
15
+ - `CommitmentTracker.record()/transitionState()` owner/blockedOn well-formedness gates — **add** — structural validation (enum + named-authorization), never semantic prose classification.
16
+ - `PromiseBeacon.emitUserSend()` owner-gate — **add** — suppresses agent-owned status / reroutes terminal; rollout-gated (no-op when off).
17
+ - External-block staleness governor + reconciler auto-close — **add** — mutating sweeps, lease-gated + feature-gated + dry-run-first.
18
+ - `external-operation-gate` (tool-call side-effect authority) — **pass-through, unchanged** — explicitly NOT modified by C1+C2 (its hardening is the C3 follow-on).
19
+
20
+ ---
21
+
22
+ ## 1. Over-block
23
+
24
+ The two new gate rules are signal-only and favor false-negatives (fail toward sending). **B19 over-block risk:** a legitimate "your call" on a genuine value/taste/spend decision (the human-only set) — explicitly carved out in the rule (do NOT apply when the deferred thing is the user's decision, or is an authorization ask). **B20 over-block risk:** a direct answer to a user who asked for an identifier — carved out (do NOT apply when the user explicitly asked). The owner-gate (`emitUserSend`) only suppresses for `owner:'agent'` commitments AND only when the feature is enabled+live; `owner:'user'` and feature-off always send. No user-facing message is hard-blocked by this change — the gate authority decides with carve-outs, and beacon suppression only drops *agent-owned status pings the user is not supposed to get*.
25
+
26
+ ## 2. Under-block
27
+
28
+ B19/B20 are brittle regex signals — trivially reworded to evade (e.g. "I'll let you handle the restart" dodges the B-PARK phrase list). This is acceptable: they are SIGNALS, not the authority, and the spec is explicit they are a mitigation, not a complete fix. The owner-gate misses a genuinely-stuck `owner:'agent'` commitment only if the agent mis-declares its state — but the single covering invariant + the §4.4 window dead-letter + the §4.5 reconciler ensure no agent-owned non-terminal commitment stays silent past a bound. B20 does NOT replace `redactSecrets`/`guardProxyOutput` (real secret/path disclosure stays enforced by those).
29
+
30
+ ## 3. Level-of-abstraction fit
31
+
32
+ Correct. The detectors (`parked-on-user`, `internal-id-leak`) are low-level brittle SIGNALS; `MessagingToneGate` (the existing full-context LLM) is the AUTHORITY (B19/B20 combine signal + conversational context, with carve-outs). The owner-gate lives INSIDE `PromiseBeacon` (not the tone gate) precisely because beacon sends are `isProxy:true` and bypass the gate. The reconciler reuses the existing `verify()`/`isUnverifiableOneTime` scar machinery rather than re-implementing closure. The ratchet's authority (C3) is deliberately NOT built here — the existing tool-call `external-operation-gate` is the unchanged side-effect authority.
33
+
34
+ ## 4. Signal vs authority compliance
35
+
36
+ **Reference:** docs/signal-vs-authority.md
37
+
38
+ - [x] **No — this change produces a signal consumed by an existing smart gate.** B19/B20 are signal-driven rules; the brittle `parked-on-user`/`internal-id-leak` detectors flag, the full-context `MessagingToneGate` LLM decides (with carve-outs, fail-toward-sending). The `record()` well-formedness gates are structural (enum validity + named-authorization presence) — a deterministic well-formedness check at the right layer (the store), mirroring the operator-binding "blank uid refused" pattern, never a semantic judgment. The owner-gate suppression is a routing decision on the agent's OWN status output (not a user-message block), gated by the feature flag. No brittle logic holds user-message block authority.
39
+
40
+ ## 5. Interactions
41
+
42
+ - **Shadowing:** the owner-gate sits at the beacon's send sites (after the existing snapshot/atRisk/liveness logic); it suppresses the send for `owner:'agent'` but does not shadow `verify()` or the escalation ladder (rung3 still surfaces). B20 is additive to the existing jargon/file-path signals (does not shadow `redactSecrets`).
43
+ - **Double-fire:** the governor + reconciler share the beacon's slow sweep timer (lease-gated, one machine) — they don't race the 60s `verify()` sweep. The governor dedupes via `externalBlockDeadLetteredAt`; the reconciler is bounded by `maxClosesPerPass`.
44
+ - **Existing tests:** beacon (90+), tone-gate (36), CommitmentsSync (17), ConfigDefaults (52), dev-gate wiring (52), feature-completeness (99) all stay green — the feature-off default preserves current behavior byte-for-byte.
45
+
46
+ ## 6. External surfaces
47
+
48
+ New HTTP routes: `POST /commitments/:id/probe`, `POST /commitments/:id/transition` (Bearer-auth, cross-machine routed like `/deliver`). New `Commitment` fields ride the existing `commitments-sync` replication (enum-clamped on receive). The dead-letter reuses the existing `raiseAttention` Attention surface (HIGH-priority, deduped). Mobile-Complete: the user-facing surfaces are an Attention item + plain Telegram messages — phone-complete; no operator CLI/file step introduced. Operator-Surface-Quality: the dead-letter is plain English ("I've been waiting on … want me to keep waiting or drop it?"), no raw internals.
49
+
50
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
51
+
52
+ - `owner`/`blockedOn`/`actionClass`/`lastProbe`/`supersededBy` — **replicated** via the existing `commitments-sync` mesh path (additive on `extends Commitment`), **enum-clamped on receive** (`CommitmentsSync.applyPage`, defaults agent/none). Replicated rows are advisory, never authoritative.
53
+ - The governor + reconciler sweeps — **machine-local execution, lease-gated** (`holdsLease` via `leaseCoordinatorRef`): only the lease-holder runs the mutating sweep, so no cross-machine double-dead-letter / double-close. Single-machine → always runs (safe no-op gate).
54
+ - The probe/transition routes — **proxied to the owning machine** (mirror `/deliver`'s `resolveCommitmentRoute`/`forwardMutation`, new cross-machine `probe`/`transition` ops on `CommitmentMutateOp` + `MeshRpc`).
55
+ - User-facing notices ride the beacon's existing one-voice speakerElection gate.
56
+
57
+ ## 8. Rollback cost
58
+
59
+ Cheap. Ships dark-on-fleet (the developmentAgent gate resolves `enabled` false for the fleet) and live-in-dryRun-on-dev (`dryRun` defaults true → the owner-gate/governor/reconciler LOG what they would do but suppress/mutate nothing). Off-switch: set `commitments.agentOwnedFollowthrough.enabled: false` (or leave the gate's fleet default). A bad behavioral interaction is reverted by flipping `enabled` off (config, no code revert) or `dryRun: true`. No data migration to undo — the new `Commitment` fields are additive/optional and back-filled idempotently; turning the feature off leaves them inert. No destructive credential/state action anywhere in C1+C2.
60
+
61
+ ---
62
+
63
+ ## Phase 5 — Second-pass review verdict
64
+
65
+ **Concur with the review.** An independent reviewer verified all six load-bearing safety properties against the actual code (not the artifact's claims):
66
+ 1. Signal-vs-Authority — the detectors hold zero block authority; B19/B20 are LLM-gate rules (fail-open, favor false-negatives); the owner-gate suppresses only the agent's own `isProxy` status sends, never a user-message block.
67
+ 2. The reconciler closes ONLY on `supersededBy`→terminal-success; no time/"abandoned" auto-close branch exists (CMT-1101 scar intact).
68
+ 3. `emitUserSend` reroutes terminal failures to `raiseAttention` (never swallowed); rollout-gated (off/owner:user → unchanged; dryRun → still sends).
69
+ 4. The governor + reconciler sweeps are lease-gated (`holdsLease()`) AND feature-gated (off → no-op; dryRun → no mutation/dead-letter).
70
+ 5. Genuinely dark-on-fleet / live-in-dryRun-on-dev (`resolveDevAgentGate` + dryRun default true); feature-off path is byte-for-byte prior behavior.
71
+ 6. `external-operation-gate` is NOT in the C1+C2 change set — its fail-posture is unchanged (the hardening is the C3 follow-on).
72
+
73
+ **Non-blocking observation (carried to the C3 follow-on, CMT-1505):** the `CommitmentsSync` receive clamp covers `owner`/`blockedOn` (the routing-significant enums) but not `actionClass`/`lastProbe` — both inert/non-authoritative in C1+C2, so no exploitable branch today; clamp them when `actionClass` becomes load-bearing in the ratchet build.
@@ -0,0 +1,48 @@
1
+ # Side-Effects Review — WS2-SEND-2b: userRegistry send-side replication
2
+
3
+ **Version / slug:** `ws2-send-2b-userregistry`
4
+ **Date:** `2026-06-15`
5
+ **Author:** `Instar Agent (echo)`
6
+ **Second-pass reviewer:** `not required` (no block/allow/lifecycle authority — additive, dark-gated data-replication wiring; see §4)
7
+
8
+ ## Summary of the change
9
+
10
+ Extends WS2 send-side emission to the `userRegistry` store (the SECOND PII kind; WS2-SEND-2b). Unlike the seamed memory stores, `userRegistry` has NO single canonical UserManager — telegram (send-only mode + normal mode) and slack each construct their OWN long-lived `UserManager` against the same `users.json`. So a single shared attacher (`attachUserReplication`, defined in `src/commands/server.ts` right after the emitter is constructed) wires the journal-backed emitter to each long-lived instance at its construction site (`userManagerSendOnly`, `userManager`, `slackUserManager`). `ws2SendWiring.ts` moves `userRegistry` PENDING→WIRED (leaving only `preferences`). The union reader + projection already shipped (WS2.6). New e2e round-trip.
11
+
12
+ Channel-keyed identity — the local `userId` NEVER crosses. `upsertUser→persistUsers` fires emitPut for every surviving user; `removeUser` fires the channel-keyed emitDelete tombstone.
13
+
14
+ ## Decision-point inventory
15
+
16
+ - `ReplicatedRecordEmitter.emit` dark gate (`stateSync.userRegistry.enabled`) — **pass-through** — pre-existing; `userRegistry` becomes a registered emit target. Default false ⇒ no-op.
17
+ - `UserManager.persistUsers` / `removeUser` emit funnels — **pass-through** — already fire; this attaches a real emitter at each long-lived instance.
18
+ - `ws2SendWiring` ratchet — **modify** — `userRegistry` reclassified PENDING→WIRED.
19
+
20
+ ---
21
+
22
+ ## 1. Over-block
23
+ No block/allow surface. The emitter never rejects a user write; null recordKey / null projection / over-cap is a counted no-op and the local write always succeeds.
24
+
25
+ ## 2. Under-block
26
+ Not applicable (no block surface). **Honest capture-scope note** (the load-bearing caveat): the in-process emitter fires on the SERVER-PROCESS user-write paths — telegram (both modes) + slack inbound registration, which are the dominant user-creation paths. TWO secondary paths are NOT covered, by design, and are stated rather than silently dropped:
27
+ 1. The Slack org-permission **admin** route (`buildSlackRegistry` in routes.ts) constructs a per-request UserManager; reaching the emitter there needs RouteContext plumbing disproportionate to a secondary admin flow.
28
+ 2. The `instar user add` **CLI** runs in a SEPARATE PROCESS, so it can never fire the server's in-process emitter; the send-side snapshot reads the journal's own entries, not `users.json`, so a CLI-only user is a known gap.
29
+ This matches the accepted in-process capture scope of relationships/knowledge. A single write funnel (one canonical UserManager) would close both gaps and is a reasonable future refactor; it is out of scope for "identical wiring."
30
+
31
+ ## 3. Level-of-abstraction fit
32
+ Correct layer. A shared attacher at the construction sites is the minimal change that captures the multiple long-lived instances without a refactor. The projection lives in `UserRegistryReplicatedStore` beside the receive-side schema.
33
+
34
+ ## 4. Signal vs authority compliance
35
+ Compliant. No blocking authority. The emitter is additive/best-effort (the funnel swallows + counts faults; a user write can never fail because replication did). **REQ-M14 (Know Your Principal):** a replicated user record is UNTRUSTED peer data and is NEVER the authoritative answer to "who is this inbound sender?" — inbound-principal resolution stays LOCAL-ONLY (the local channel index always wins). The union read is advisory HIGH-tier. Per `docs/signal-vs-authority.md`.
36
+
37
+ ## 5. Interactions
38
+ - Uses server.ts's single `replicatedRecordEmitter` via the shared `attachUserReplication` helper. Distinct store key/kind from the other WS2 stores. No double-fire (each instance rides its own persistUsers funnel; the same person on two instances collapses to one channel-keyed recordKey).
39
+ - Touches `server.ts` + `ws2SendWiring.ts` (the shared WS2-SEND files) → serialized on top of merged topicOperator; no parallel WS2-SEND PRs.
40
+
41
+ ## 6. External surfaces
42
+ Dark by default (`multiMachine.stateSync.userRegistry`). Off ⇒ byte-identical single-machine behavior. On (multi-machine, opt-in): crosses the channel-keyed profile projection (name, channels, permissions) — never the local userId. Same at-rest honesty as relationships (transit encrypted; at-rest plaintext per machine). A received record is quoted `<replicated-untrusted-data>`, advisory only.
43
+
44
+ ## 7. Multi-machine posture (Cross-Machine Coherence)
45
+ **Replicated.** Path: `upsertUser/removeUser → persistUsers → emit → CoherenceJournal.emitReplicatedRecord → peer serve/apply → ReplicatedPeerStreamReader → userRegistryUnionReader`. Identity = channel set (the same person on two machines collapses to one recordKey). removeUser propagates a channel-keyed tombstone (no resurrection). Verified end-to-end by the new e2e (put round-trip + channel-set collapse + removeUser tombstone resolves to no-record).
46
+
47
+ ## 8. Rollback cost
48
+ Trivial. Dark by default. Back-out = revert the server.ts + ws2SendWiring.ts change or set the flag false (instant, no migration). Receive-side + envelope schema already shipped, unaffected.