instar 1.3.589 → 1.3.591

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.
@@ -51,7 +51,14 @@ export interface OwnershipApplierDeps {
51
51
  /** The SAME durable store the SessionOwnershipRegistry reads — so a materialized
52
52
  * record is immediately visible to owner-resolution / routing. */
53
53
  store: SessionOwnershipStore;
54
- selfMachineId: string;
54
+ /**
55
+ * This machine's mesh id — used ONLY for the SELF-vs-peer log label, never for
56
+ * materialization (every placement is adopted regardless of owner). Accepts a
57
+ * **late-bound getter** so a caller can wire the applier before `_meshSelfId` is
58
+ * resolved without capturing a stale `null` (the boot-ordering hazard this fix closes);
59
+ * a plain string still works for callers/tests that already have the id.
60
+ */
61
+ selfMachineId: string | (() => string | null | undefined);
55
62
  /** Max placement entries to scan per tick (bounded cost). Default 1000. */
56
63
  scanLimit?: number;
57
64
  logger?: (msg: string) => void;
@@ -68,6 +75,8 @@ export declare class OwnershipApplier {
68
75
  constructor(deps: OwnershipApplierDeps);
69
76
  private now;
70
77
  private log;
78
+ /** Resolve the (possibly late-bound) self machine id at tick time, for the log label only. */
79
+ private resolveSelf;
71
80
  /**
72
81
  * One pass: adopt the highest-epoch placement per topic into the local store.
73
82
  * Returns counts for observability. Never throws — a read/parse failure degrades
@@ -1 +1 @@
1
- {"version":3,"file":"OwnershipApplier.d.ts","sourceRoot":"","sources":["../../src/core/OwnershipApplier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAE3E,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAC9D,OAAO,EAAE,KAAK,CAAC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACrG,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,MAAM,EAAE,eAAe,CAAC;IACxB;uEACmE;IACnE,KAAK,EAAE,qBAAqB,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAuB;gBAE7B,IAAI,EAAE,oBAAoB;IAItC,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,GAAG;IAIX;;;;OAIG;IACH,IAAI,IAAI,oBAAoB;CAkD7B"}
1
+ {"version":3,"file":"OwnershipApplier.d.ts","sourceRoot":"","sources":["../../src/core/OwnershipApplier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAGH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAE3E,uFAAuF;AACvF,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG;QAC9D,OAAO,EAAE,KAAK,CAAC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACrG,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,MAAM,EAAE,eAAe,CAAC;IACxB;uEACmE;IACnE,KAAK,EAAE,qBAAqB,CAAC;IAC7B;;;;;;OAMG;IACH,aAAa,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAC1D,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAuB;gBAE7B,IAAI,EAAE,oBAAoB;IAItC,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,GAAG;IAIX,8FAA8F;IAC9F,OAAO,CAAC,WAAW;IAKnB;;;;OAIG;IACH,IAAI,IAAI,oBAAoB;CAuD7B"}
@@ -40,6 +40,11 @@ export class OwnershipApplier {
40
40
  log(m) {
41
41
  this.d.logger?.(`[ownership-applier] ${m}`);
42
42
  }
43
+ /** Resolve the (possibly late-bound) self machine id at tick time, for the log label only. */
44
+ resolveSelf() {
45
+ const s = this.d.selfMachineId;
46
+ return typeof s === 'function' ? s() : s;
47
+ }
43
48
  /**
44
49
  * One pass: adopt the highest-epoch placement per topic into the local store.
45
50
  * Returns counts for observability. Never throws — a read/parse failure degrades
@@ -85,8 +90,13 @@ export class OwnershipApplier {
85
90
  const r = this.d.store.casWrite(rec);
86
91
  if (r.ok) {
87
92
  materialized++;
93
+ const self = this.resolveSelf();
88
94
  this.log(`materialized topic ${sessionKey} → owner ${best.owner} @epoch ${best.epoch}` +
89
- (best.owner === this.d.selfMachineId ? ' (SELF — this machine now serves it)' : ' (peer — route forwards there)'));
95
+ (self && best.owner === self
96
+ ? ' (SELF — this machine now serves it)'
97
+ : self
98
+ ? ' (peer — route forwards there)'
99
+ : ''));
90
100
  }
91
101
  }
92
102
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OwnershipApplier.js","sourceRoot":"","sources":["../../src/core/OwnershipApplier.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OwnershipApplier.js","sourceRoot":"","sources":["../../src/core/OwnershipApplier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * durableOwnershipActivation — the pool-consistent activation predicate for the
3
+ * cross-machine durable ownership store (spec:
4
+ * docs/specs/pool-consistent-multimachine-activation.md).
5
+ *
6
+ * The transfer fix's durable store + OwnershipApplier MUST run on every machine that
7
+ * CONSUMES replicated placement journals — otherwise a seat transferred TO a machine
8
+ * whose store is dark never materializes ownership there and the move dies on arrival
9
+ * (the live Laptop↔Mini finding, 2026-06-16: the Mini's echo wasn't a dev agent, so a
10
+ * purely per-machine dev-gate left the store dark there while the Laptop's was live).
11
+ *
12
+ * So activation is the OR of:
13
+ * - the per-machine dev-agent gate (a dev agent opts in to dogfood), AND
14
+ * - the explicit, pool-consistent `multiMachine.coherenceJournal.replication.enabled
15
+ * === true` signal — the SAME one gating the placement-replication applier
16
+ * (`journalSyncApplier`). Invariant: a machine running placement replication runs the
17
+ * ownership applier + durable store too (they consume the same replicated placements).
18
+ *
19
+ * A single-machine agent (no replication, not dev) stays on the in-memory store — a
20
+ * strict no-op.
21
+ */
22
+ /** The replication signal: explicit opt-in (`=== true`); ConfigDefaults leaves it absent. */
23
+ export declare function isPlacementReplicationEnabled(config: unknown): boolean;
24
+ /**
25
+ * Whether to activate the durable ownership store + applier on THIS machine.
26
+ * `isDevAgentGate` is the injected `resolveDevAgentGate` (so this stays pure/testable).
27
+ */
28
+ export declare function shouldActivateDurableOwnership(config: unknown, isDevAgentGate: (flag: any, config: any) => boolean): boolean;
29
+ //# sourceMappingURL=durableOwnershipActivation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durableOwnershipActivation.d.ts","sourceRoot":"","sources":["../../src/core/durableOwnershipActivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,6FAA6F;AAC7F,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAGtE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,OAAO,EAIf,cAAc,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,KAAK,OAAO,GAClD,OAAO,CAIT"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * durableOwnershipActivation — the pool-consistent activation predicate for the
3
+ * cross-machine durable ownership store (spec:
4
+ * docs/specs/pool-consistent-multimachine-activation.md).
5
+ *
6
+ * The transfer fix's durable store + OwnershipApplier MUST run on every machine that
7
+ * CONSUMES replicated placement journals — otherwise a seat transferred TO a machine
8
+ * whose store is dark never materializes ownership there and the move dies on arrival
9
+ * (the live Laptop↔Mini finding, 2026-06-16: the Mini's echo wasn't a dev agent, so a
10
+ * purely per-machine dev-gate left the store dark there while the Laptop's was live).
11
+ *
12
+ * So activation is the OR of:
13
+ * - the per-machine dev-agent gate (a dev agent opts in to dogfood), AND
14
+ * - the explicit, pool-consistent `multiMachine.coherenceJournal.replication.enabled
15
+ * === true` signal — the SAME one gating the placement-replication applier
16
+ * (`journalSyncApplier`). Invariant: a machine running placement replication runs the
17
+ * ownership applier + durable store too (they consume the same replicated placements).
18
+ *
19
+ * A single-machine agent (no replication, not dev) stays on the in-memory store — a
20
+ * strict no-op.
21
+ */
22
+ /** The replication signal: explicit opt-in (`=== true`); ConfigDefaults leaves it absent. */
23
+ export function isPlacementReplicationEnabled(config) {
24
+ const c = config;
25
+ return c?.multiMachine?.coherenceJournal?.replication?.enabled === true;
26
+ }
27
+ /**
28
+ * Whether to activate the durable ownership store + applier on THIS machine.
29
+ * `isDevAgentGate` is the injected `resolveDevAgentGate` (so this stays pure/testable).
30
+ */
31
+ export function shouldActivateDurableOwnership(config,
32
+ // The injected `resolveDevAgentGate` — typed loosely so the real gate
33
+ // (`(boolean|undefined, DevAgentGateConfig|undefined) => boolean`) and test fakes
34
+ // both satisfy it without importing the gate's config type here.
35
+ isDevAgentGate) {
36
+ const c = config;
37
+ const devOn = isDevAgentGate(c?.multiMachine?.durableOwnership?.enabled, config);
38
+ return devOn || isPlacementReplicationEnabled(config);
39
+ }
40
+ // (pool-consistent activation — see docs/specs/pool-consistent-multimachine-activation.md)
41
+ //# sourceMappingURL=durableOwnershipActivation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durableOwnershipActivation.js","sourceRoot":"","sources":["../../src/core/durableOwnershipActivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,6FAA6F;AAC7F,MAAM,UAAU,6BAA6B,CAAC,MAAe;IAC3D,MAAM,CAAC,GAAG,MAAkG,CAAC;IAC7G,OAAO,CAAC,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAC5C,MAAe;AACf,sEAAsE;AACtE,kFAAkF;AAClF,iEAAiE;AACjE,cAAmD;IAEnD,MAAM,CAAC,GAAG,MAAgF,CAAC;IAC3F,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,EAAE,YAAY,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IACjF,OAAO,KAAK,IAAI,6BAA6B,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,2FAA2F"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * ownershipApplierWiring — the testable construction factory for the transfer-fix §7.2
3
+ * OwnershipApplier (spec: docs/specs/ownership-applier-meshself-ordering-fix.md).
4
+ *
5
+ * Why this exists: the applier's construction CONDITION used to live inline in
6
+ * `server.ts` as `if (durableOwnershipStore && _meshSelfId)`. That guard read
7
+ * `_meshSelfId` ~650 lines BEFORE the boot sequence assigns it, so it was always
8
+ * `null` at the check → the applier was never constructed or ticked, on either machine,
9
+ * and a transferred seat never materialized on the destination. The inline condition was
10
+ * also untestable, which is precisely how the ordering bug shipped.
11
+ *
12
+ * The fix (Structure > Willpower): gate construction on the durable store ALONE — the
13
+ * genuinely relevant condition (applying replicated placements is a durable-store concern;
14
+ * the in-memory store has no cross-machine replication to apply) — and pass `selfMachineId`
15
+ * as a LATE-BOUND getter so the (label-only) self id resolves at tick time instead of being
16
+ * captured as a stale `null` at construction. This makes the wiring order-independent and
17
+ * unit-testable without booting the whole server.
18
+ */
19
+ import type { PlacementReader } from './OwnershipApplier.js';
20
+ import { OwnershipApplier } from './OwnershipApplier.js';
21
+ import type { SessionOwnershipStore } from './SessionOwnershipRegistry.js';
22
+ export interface OwnershipApplierWiringDeps {
23
+ /** The durable per-session store, or null when the in-memory store is in use. */
24
+ durableOwnershipStore: SessionOwnershipStore | null;
25
+ /** Reads replicated + own placement entries (CoherenceJournalReader). */
26
+ reader: PlacementReader;
27
+ /**
28
+ * Late-bound resolver for this machine's mesh id. May legitimately return null/undefined
29
+ * at construction time (before the boot sequence assigns it); it is used ONLY for the
30
+ * SELF-vs-peer log label, never for materialization.
31
+ */
32
+ getSelfMachineId: () => string | null | undefined;
33
+ scanLimit?: number;
34
+ logger?: (msg: string) => void;
35
+ now?: () => number;
36
+ }
37
+ /**
38
+ * Build the OwnershipApplier when (and only when) the durable ownership store is active.
39
+ * Returns `null` for the in-memory store (nothing to apply). NEVER gates on the self id —
40
+ * that was the boot-ordering bug. The caller schedules the boot tick + interval on a
41
+ * non-null result.
42
+ */
43
+ export declare function wireOwnershipApplier(deps: OwnershipApplierWiringDeps): OwnershipApplier | null;
44
+ //# sourceMappingURL=ownershipApplierWiring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownershipApplierWiring.d.ts","sourceRoot":"","sources":["../../src/core/ownershipApplierWiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAE3E,MAAM,WAAW,0BAA0B;IACzC,iFAAiF;IACjF,qBAAqB,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACpD,yEAAyE;IACzE,MAAM,EAAE,eAAe,CAAC;IACxB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,0BAA0B,GAAG,gBAAgB,GAAG,IAAI,CAU9F"}
@@ -0,0 +1,20 @@
1
+ import { OwnershipApplier } from './OwnershipApplier.js';
2
+ /**
3
+ * Build the OwnershipApplier when (and only when) the durable ownership store is active.
4
+ * Returns `null` for the in-memory store (nothing to apply). NEVER gates on the self id —
5
+ * that was the boot-ordering bug. The caller schedules the boot tick + interval on a
6
+ * non-null result.
7
+ */
8
+ export function wireOwnershipApplier(deps) {
9
+ if (!deps.durableOwnershipStore)
10
+ return null;
11
+ return new OwnershipApplier({
12
+ reader: deps.reader,
13
+ store: deps.durableOwnershipStore,
14
+ selfMachineId: deps.getSelfMachineId, // getter — resolved per-tick, never captured stale
15
+ scanLimit: deps.scanLimit,
16
+ logger: deps.logger,
17
+ now: deps.now,
18
+ });
19
+ }
20
+ //# sourceMappingURL=ownershipApplierWiring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownershipApplierWiring.js","sourceRoot":"","sources":["../../src/core/ownershipApplierWiring.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAmBzD;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAgC;IACnE,IAAI,CAAC,IAAI,CAAC,qBAAqB;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,IAAI,gBAAgB,CAAC;QAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,qBAAqB;QACjC,aAAa,EAAE,IAAI,CAAC,gBAAgB,EAAE,mDAAmD;QACzF,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG,EAAE,IAAI,CAAC,GAAG;KACd,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instar",
3
- "version": "1.3.589",
3
+ "version": "1.3.591",
4
4
  "description": "Coherence infrastructure for self-evolving AI agents — on the Claude Code or Codex subscription you already have.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "./builtin-manifest.schema.json",
3
3
  "schemaVersion": 1,
4
- "generatedAt": "2026-06-16T04:50:01.235Z",
5
- "instarVersion": "1.3.589",
4
+ "generatedAt": "2026-06-16T06:55:01.483Z",
5
+ "instarVersion": "1.3.591",
6
6
  "entryCount": 201,
7
7
  "entries": {
8
8
  "hook:session-start": {
@@ -0,0 +1,21 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ The cross-machine transfer fix (shipped dark in v1.3.589) was caught half-active by its own live test: the durable ownership store only turned on for a dev-flagged machine, so on a non-dev pool machine it stayed off and a transferred conversation died on arrival. This activates the durable store wherever placement replication is explicitly on (`multiMachine.coherenceJournal.replication.enabled === true`) — the pool-consistent signal — so it comes up on every machine that needs to materialize transferred ownership.
9
+
10
+ ## What to Tell Your User
11
+
12
+ Nothing changes in normal single-machine use. For a multi-machine setup with replication enabled, the cross-machine "move a conversation between machines" feature now actually completes the move on the receiving machine — the gap the live test caught.
13
+
14
+ ## Summary of New Capabilities
15
+
16
+ - `durableOwnership` activates wherever placement replication is on (not only dev machines); single-machine agents unchanged (strict no-op).
17
+ - New testable predicate `src/core/durableOwnershipActivation.ts`.
18
+
19
+ ## Evidence
20
+
21
+ The live Laptop↔Mini proof of v1.3.589 found the Mini's durable store dark (its echo wasn't a dev agent) → ownership never materialized → seat died on arrival. The Mini HAS `coherenceJournal.replication.enabled:true`, so the new predicate activates the durable store there. 7 unit tests (both sides of every boundary) green; the live re-proof (a reply served from the Mini after a transfer) is the acceptance criterion.
@@ -0,0 +1,34 @@
1
+ # Upgrade Guide — vNEXT
2
+
3
+ <!-- assembled-by: assemble-next-md -->
4
+ <!-- bump: patch -->
5
+
6
+ ## What Changed
7
+
8
+ Fixed a boot-ordering bug that left the cross-machine `OwnershipApplier` permanently
9
+ un-wired: a topic moved between machines was reported moved but the destination never took
10
+ ownership, so the conversation went silent on arrival. The applier's on-switch now depends on
11
+ the durable ownership store alone (extracted into a testable `wireOwnershipApplier` factory),
12
+ and the machine id it uses for logging is late-bound, so the wiring can't be broken by code
13
+ reordering. Caught by applying the Live-User-Channel Proof gold standard to a real
14
+ Laptop→Mini transfer (the second, deeper bug after the dev-gate-darkness fix in v1.3.590).
15
+
16
+ ## What to Tell Your User
17
+
18
+ If you move a conversation between your machines, the destination now genuinely takes over and
19
+ answers there. Before this, a moved conversation could report success but then go quiet on the
20
+ new machine, because the new machine never realized it owned the conversation. Single-machine
21
+ setups are unaffected.
22
+
23
+ ## Summary of New Capabilities
24
+
25
+ | Capability | How to Use |
26
+ |-----------|-----------|
27
+ | Moving a conversation between machines actually lands it on the destination | Move a topic to another machine as usual; the destination now takes ownership and serves it |
28
+
29
+ ## Evidence
30
+
31
+ - 6 new unit/wiring tests (`tests/unit/ownershipApplierWiring.test.ts`) + 7 existing applier
32
+ tests stay green; tsc clean.
33
+ - Release gate: a live two-machine re-run asserts the destination materializes the seat and a
34
+ reply serves from it (Telegram + Slack).
@@ -0,0 +1,52 @@
1
+ # Side-Effects Review — OwnershipApplier mesh-self ordering fix
2
+
3
+ **Slug:** ownership-applier-meshself-ordering-fix
4
+ **Spec:** docs/specs/ownership-applier-meshself-ordering-fix.md
5
+ **Parent principle:** Wiring Integrity — a dependency-injected component must actually run, not be a silently-skipped no-op.
6
+
7
+ ## What changed
8
+
9
+ A boot-ordering bug in `src/commands/server.ts` meant the transfer-fix §7.2 `OwnershipApplier`
10
+ was never constructed or ticked at runtime (its guard read `_meshSelfId` ~650 lines before
11
+ the boot sequence assigns it, so the guard was always false). Result: a topic transferred
12
+ between machines was recorded on the SOURCE and replicated to the DESTINATION's journal, but
13
+ the destination never materialized ownership → it never knew it owned the session → the seat
14
+ died on arrival. Caught by applying the Live-User-Channel Proof gold standard to a real
15
+ Laptop→Mini transfer.
16
+
17
+ Fix (order-independent — Structure > Willpower):
18
+ - `src/core/OwnershipApplier.ts` — `selfMachineId` accepts a late-bound getter (label-only;
19
+ materialization never needs it); resolved per-tick instead of captured stale at construction.
20
+ - `src/core/ownershipApplierWiring.ts` (new) — `wireOwnershipApplier()` factory gates
21
+ construction on the durable store ALONE (the correct condition), extracted so the invariant
22
+ is unit-testable (the inline condition was untestable, which is how the bug shipped).
23
+ - `src/commands/server.ts` — calls the factory in place of the inline guard.
24
+
25
+ ## Blast radius
26
+
27
+ - **Multi-machine destinations (the target):** a transferred seat now materializes durable
28
+ ownership on the destination and is served there. This was BROKEN before — net improvement.
29
+ - **Single machine:** the durable store may be active but there are no peer placements; the
30
+ applier ticks and finds nothing — a harmless no-op. No behavior change.
31
+ - **Transfer SOURCE:** unchanged (it writes ownership directly via the tclaim path).
32
+ - **No new route, config flag, state schema, URL, or migration.** Pure internal wiring +
33
+ one new internal module (no agent-facing surface → no CLAUDE.md template change required).
34
+ - **Backward compatibility:** `OwnershipApplier`'s `selfMachineId` still accepts a plain
35
+ string; all existing callers/tests are unaffected (7 existing applier tests stay green).
36
+
37
+ ## Reversibility
38
+
39
+ No flag (it only activates the durable-ownership path that already ships pool-consistent for
40
+ replication-on pools / dark for single-machine). Revertable by reverting the three-file diff;
41
+ no durable state is written that would outlive a revert (ownership records are re-derived from
42
+ the replicated journal on the next tick).
43
+
44
+ ## Risk / monitoring
45
+
46
+ Low. The applier is off the hot path (boot tick + 15s interval), never throws (degrades to
47
+ "materialized fewer this tick"), and fast-forward-CAS guards against clobbering a fresher
48
+ local decision. Observable via `[ownership-applier] materialized …` / `[OwnershipApplier]
49
+ materialized N/M …` in `logs/server.log` — their appearance is itself the proof the wiring is
50
+ now alive (the bug's signature was their total absence). Release gate: the live two-machine
51
+ re-run (deploy both → transfer → assert destination materializes + a reply serves from the
52
+ destination).
@@ -0,0 +1,39 @@
1
+ # Side-Effects Review — Pool-Consistent durableOwnership Activation (PR1: the predicate)
2
+
3
+ **Spec:** docs/specs/pool-consistent-multimachine-activation.md (CONVERGED iter 4, self-approved). **Tracking:** CMT-1568 follow-on. **Parent:** No Silent Degradation to Brittle Fallback.
4
+ **Earned from:** the live Laptop↔Mini transfer-fix proof (v1.3.589) — the fix was half-active because `durableOwnership` is per-machine dev-gated and the Mini's echo isn't dev-flagged.
5
+ **Files:** src/core/durableOwnershipActivation.ts (new), src/commands/server.ts, tests/unit/durableOwnershipActivation.test.ts (new), site/src/content/docs/architecture/live-user-channel-proof.md.
6
+
7
+ ## What changed
8
+
9
+ 1. **durableOwnershipActivation.ts (new):** a pure, testable activation predicate.
10
+ `shouldActivateDurableOwnership(config, resolveDevAgentGate)` = `devGate || isPlacementReplicationEnabled(config)`, where `isPlacementReplicationEnabled` reads the explicit `multiMachine.coherenceJournal.replication.enabled === true` signal (the SAME one gating `journalSyncApplier` at server.ts:16588). Invariant: a machine consuming replicated placements runs the ownership applier + durable store.
11
+ 2. **server.ts:14861:** replaced the inline `resolveDevAgentGate(durableOwnership.enabled)` gate with `shouldActivateDurableOwnership(config, resolveDevAgentGate)`; the boot log names the activation reason (`pool: replication-on` vs `dev-gate`).
12
+ 3. **Tests:** 7 unit tests covering both sides of every boundary (non-dev+replication-on activates [the Mini case]; non-dev+replication-off stays dark; dev activates; single-machine no-op; explicit `=== true` required).
13
+
14
+ ## Blast radius
15
+
16
+ - **Strictly WIDENS activation** from "dev agents only" to "dev agents OR any machine with placement replication explicitly on." A single-machine agent (no replication) is UNCHANGED (stays InMemory — strict no-op). A multi-machine agent that explicitly enabled `coherenceJournal.replication.enabled` now also runs the durable store (which it needs to materialize transferred ownership).
17
+ - The durable store is well-tested (18 tests + the live Laptop-side proof in v1.3.589). Activating it where replication is on is the SET that needs it; it never DEACTIVATES anywhere it was active.
18
+ - No new route, no config schema change, no migration. Reversible: revert the predicate to the dev-only gate.
19
+
20
+ ## Risk + mitigation
21
+
22
+ - **Risk:** a machine activates the durable store but its peer (mid rolling-deploy, old code) doesn't → half-applied transfer. **Mitigation:** the applier already backfills (queries existing placements per tick); the capability-refuse guard (PR2 follow-on) fail-closes the deploy window; the split-active detector (PR3) surfaces residual inconsistency. For PR1 the predicate alone makes a same-version pool consistent.
23
+ - **Risk:** over-promotion past the dev ladder. **Mitigation:** it activates only where the operator EXPLICITLY enabled replication (`=== true`, absent by default) — operator opt-in, not automatic.
24
+
25
+ ## Migration parity
26
+
27
+ - No config default added (the predicate reads existing flags). No CLAUDE.md template change (the durableOwnership awareness shipped with v1.3.589). The new class is documented in the architecture site doc.
28
+
29
+ ## Dark-gate line-map
30
+
31
+ - UNCHANGED. No new `enabled: false` line in ConfigDefaults.ts. `durableOwnership` stays in DEV_GATED_FEATURES; this only BROADENS its activation predicate, it does not change its gate registration.
32
+
33
+ ## Rollback
34
+
35
+ - Revert the predicate to `resolveDevAgentGate(durableOwnership.enabled, config)`. The durable files remain valid; the journal stays the source of truth.
36
+
37
+ ## Evidence
38
+
39
+ - 7 new unit tests (both sides of every boundary), all green; tsc clean; the predicate directly closes the live finding (the Mini has `replication.enabled:true` → the predicate activates the durable store there). The live re-proof (a reply served from the Mini) is the acceptance criterion, run after deploy.