instar 1.3.570 → 1.3.572

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA8/btE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAkH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAsBtD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,OAAO,CAUT;AAyID,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAg4CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAyoctE;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuD5E"}
@@ -3423,6 +3423,69 @@ export async function startServer(options) {
3423
3423
  // answer to "who is my verified operator?" (only the local authenticated setOperator binds it).
3424
3424
  const { TOPIC_OPERATOR_KIND_REGISTRATION } = await import('../core/TopicOperatorReplicatedStore.js');
3425
3425
  replicatedKindRegistry.register(TOPIC_OPERATOR_KIND_REGISTRATION);
3426
+ // ── WS2 SEND-SIDE wiring (docs/specs/WS2-SEND-SIDE-EMISSION-SPEC.md). The
3427
+ // substrate above ships the registry + receive/serve machinery + advert; THIS
3428
+ // wires the SEND half that was deferred ("the journal-backed emitter is attached
3429
+ // in a later rollout stage"). Three pieces, all KIND-AGNOSTIC: (1) inject the
3430
+ // now-populated registry into the journal writer + the applier so a registered
3431
+ // `*-record` kind validates/accepts on BOTH ends (without it a peer's record
3432
+ // suspect-flags the stream — the receive-only gap); (2) the peer-stream reader
3433
+ // that materializes own + peer journal streams into the union's per-origin
3434
+ // records (makes a received record READABLE) + the snapshot loadOwnEntries
3435
+ // source + the emitter's `observed`-witness source; (3) the author-side HLC
3436
+ // clock. All require the coherence journal (the emit sink + the streams to read);
3437
+ // when it is dark these stay undefined and every consumer degrades to its
3438
+ // existing single-machine no-op. The generic record emitter is constructed below
3439
+ // (it also needs the resolved stateSync flags).
3440
+ let replicatedPeerStreamReader;
3441
+ let replicatedRecordEmitter;
3442
+ let replicatedHlcClock;
3443
+ if (coherenceJournal && cjOwnMachineId) {
3444
+ try {
3445
+ coherenceJournal.setReplicatedKindRegistry(replicatedKindRegistry);
3446
+ journalSyncApplier?.setReplicatedKindRegistry(replicatedKindRegistry);
3447
+ const { ReplicatedPeerStreamReader } = await import('../core/ReplicatedPeerStreamReader.js');
3448
+ replicatedPeerStreamReader = new ReplicatedPeerStreamReader({
3449
+ stateDir: config.stateDir,
3450
+ registry: replicatedKindRegistry,
3451
+ selfMachineId: cjOwnMachineId,
3452
+ });
3453
+ // Author-side HLC clock — persisted under the journal dir (atomic temp+rename)
3454
+ // so the merge total order survives restarts (§3.5). node = this machine's id.
3455
+ const { HybridLogicalClock } = await import('../core/HybridLogicalClock.js');
3456
+ const hlcSafeId = cjOwnMachineId.replace(/[^A-Za-z0-9_.-]/g, '_');
3457
+ const hlcPath = path.join(config.stateDir, 'state', 'coherence-journal', `hlc-${hlcSafeId}.json`);
3458
+ replicatedHlcClock = new HybridLogicalClock({
3459
+ node: cjOwnMachineId,
3460
+ now: () => Date.now(),
3461
+ persist: {
3462
+ load: () => {
3463
+ try {
3464
+ const o = JSON.parse(fs.readFileSync(hlcPath, 'utf-8'));
3465
+ return o && typeof o.physical === 'number' ? o : null;
3466
+ }
3467
+ catch { /* @silent-fallback-ok: absent/corrupt hlc file = fresh clock (first boot) — the clock starts at 0, never throws. */
3468
+ return null;
3469
+ }
3470
+ },
3471
+ save: (t) => {
3472
+ try {
3473
+ fs.mkdirSync(path.dirname(hlcPath), { recursive: true });
3474
+ const tmp = `${hlcPath}.tmp-${process.pid}`;
3475
+ fs.writeFileSync(tmp, JSON.stringify(t));
3476
+ fs.renameSync(tmp, hlcPath);
3477
+ }
3478
+ catch { /* @silent-fallback-ok: a failed hlc persist degrades to in-memory-only (the clock still advances this run); replication merge order is best-effort durable, never a boot blocker. */ }
3479
+ },
3480
+ },
3481
+ });
3482
+ }
3483
+ catch (e) { /* @silent-fallback-ok: the SEND-side wiring must never endanger boot — a failure leaves replication dark (undefined seams), exactly the pre-WS2-send behavior. */
3484
+ replicatedPeerStreamReader = undefined;
3485
+ replicatedHlcClock = undefined;
3486
+ console.log(pc.dim(` [ws2-send] emitter wiring skipped: ${e instanceof Error ? e.message : String(e)}`));
3487
+ }
3488
+ }
3426
3489
  // Snapshot-then-tail engine (Component 4 / build-order step 3,
3427
3490
  // multi-machine-replicated-store-foundation §6). The cache (FIXED ceiling,
3428
3491
  // §8.2 — NOT pool-scaled), the per-peer rebuild breaker (§6.3), and the engine
@@ -3443,10 +3506,12 @@ export async function startServer(options) {
3443
3506
  cache: snapshotCache,
3444
3507
  breaker: snapshotRebuildBreaker,
3445
3508
  seams: {
3446
- // Step-3 substrate: no concrete store kind is registered yet, so there are
3447
- // no contributing own-streams to load. A consumer PR (WS2.1) replaces this
3448
- // with a loader that reads the CoherenceJournal own streams for its kind(s).
3449
- loadOwnEntries: () => ({}),
3509
+ // WS2 send-side: read the OWN journal streams for the store's registered
3510
+ // kind(s) so a snapshot serve returns real entries (replaces the no-op stub).
3511
+ // Single-origin is enforced inside the reader (it serves only this machine's
3512
+ // own stream). When the journal is dark the reader is undefined ⇒ `{}` (the
3513
+ // correct no-store no-op; serveSnapshot then answers 'no-entries').
3514
+ loadOwnEntries: (store, origin) => replicatedPeerStreamReader ? replicatedPeerStreamReader.loadOwnEntries(store, origin) : {},
3450
3515
  now: () => Date.now(),
3451
3516
  },
3452
3517
  maxSnapshotBytes: stateSync.maxCacheBytes,
@@ -3461,6 +3526,26 @@ export async function startServer(options) {
3461
3526
  // `enabled === true` semantics but now see a live flag on a dev agent. An explicit
3462
3527
  // operator `enabled` in config still wins (force-dark false / fleet-flip true).
3463
3528
  const _stateSyncStoresResolved = resolveStateSyncStores(config);
3529
+ // WS2 send-side: the generic journal-backed record emitter (the concrete emitter
3530
+ // the per-store managers' emit hooks call). Needs the journal sink, the HLC clock,
3531
+ // the registry (store → kind), this machine's origin id, the resolved stateSync
3532
+ // flags (the dark gate — read via a getter so a live flip is honored), and the
3533
+ // peer-stream reader as the `observed`-witness source. Constructed only when the
3534
+ // journal + clock + reader exist (all gated on the coherence journal being live);
3535
+ // otherwise it stays undefined and every per-store emit adapter is simply never
3536
+ // attached (the managers' hooks stay no-ops, the pre-WS2-send behavior).
3537
+ if (coherenceJournal && replicatedHlcClock && replicatedPeerStreamReader) {
3538
+ const { ReplicatedRecordEmitter } = await import('../core/ReplicatedRecordEmitter.js');
3539
+ replicatedRecordEmitter = new ReplicatedRecordEmitter({
3540
+ journal: coherenceJournal,
3541
+ clock: replicatedHlcClock,
3542
+ registry: replicatedKindRegistry,
3543
+ origin: cjOwnMachineId,
3544
+ stores: () => _stateSyncStoresResolved,
3545
+ loadWitness: (store, recordKey) => replicatedPeerStreamReader.loadWitness(store, recordKey),
3546
+ log: (event, detail) => console.log(pc.dim(` [ws2-send] ${event} ${JSON.stringify(detail)}`)),
3547
+ });
3548
+ }
3464
3549
  const selfStateSyncReceive = () => {
3465
3550
  const out = {};
3466
3551
  const stores = _stateSyncStoresResolved;
@@ -3558,7 +3643,7 @@ export async function startServer(options) {
3558
3643
  // (= that one local record). tierOf returns HIGH (append-both-and-flag never
3559
3644
  // silently clobbers two divergent people). Consulted by the relationships peer-read
3560
3645
  // surface ONLY when stateSync.relationships.enabled is true.
3561
- const { relationshipTierOf, relationshipToOriginRecord, deriveRelationshipRecordKey, mergeUnionToRelationships, renderForeignRelationshipContext, RELATIONSHIP_STORE_KEY } = await import('../core/RelationshipsReplicatedStore.js');
3646
+ const { relationshipTierOf, relationshipToOriginRecord, deriveRelationshipRecordKey, buildRelationshipRecordData, buildRelationshipTombstoneData, mergeUnionToRelationships, renderForeignRelationshipContext, RELATIONSHIP_STORE_KEY } = await import('../core/RelationshipsReplicatedStore.js');
3562
3647
  const relationshipsUnionReader = new ReplicatedStoreReader({
3563
3648
  registry: replicatedKindRegistry,
3564
3649
  stores: _stateSyncStoresResolved, // gate-resolved (dev-live / fleet-dark) per operator directive 2026-06-13
@@ -7843,37 +7928,58 @@ export async function startServer(options) {
7843
7928
  // and-flag never silently clobbers two divergent lessons; the READ layer is advisory,
7844
7929
  // injecting both variants as hints rather than blocking — fork #2). Consulted by a
7845
7930
  // learnings peer-read surface ONLY when stateSync.learnings.enabled is true.
7846
- const { learningTierOf, learningToOriginRecord, deriveLearningRecordKey, LEARNING_STORE_KEY } = await import('../core/LearningsReplicatedStore.js');
7931
+ const { learningTierOf, deriveLearningRecordKey, buildLearningRecordData, buildLearningTombstoneData, LEARNING_STORE_KEY, } = await import('../core/LearningsReplicatedStore.js');
7847
7932
  const learningsUnionReader = new ReplicatedStoreReader({
7848
7933
  registry: replicatedKindRegistry,
7849
7934
  stores: _stateSyncStoresResolved, // gate-resolved (dev-live / fleet-dark) per operator directive 2026-06-13
7850
7935
  tierOf: learningTierOf,
7851
- loadOriginRecords: (store, recordKey) => {
7852
- if (store !== LEARNING_STORE_KEY || _meshSelfId === null)
7853
- return [];
7854
- for (const l of evolution.listLearnings()) {
7855
- if (deriveLearningRecordKey(l.title, l.category, l.source) === recordKey) {
7856
- const o = learningToOriginRecord(l, _meshSelfId);
7857
- return o ? [o] : [];
7858
- }
7859
- }
7860
- return [];
7861
- },
7862
- listRecordKeys: (store) => {
7863
- if (store !== LEARNING_STORE_KEY)
7864
- return [];
7865
- const keys = [];
7866
- for (const l of evolution.listLearnings()) {
7867
- const k = deriveLearningRecordKey(l.title, l.category, l.source);
7868
- if (k !== null)
7869
- keys.push(k);
7870
- }
7871
- return keys;
7872
- },
7936
+ // WS2 send-side: the union now reads OWN + PEER journal streams (each record's
7937
+ // authoritative emit-time HLC) via the peer-stream reader — so a learning
7938
+ // replicated FROM a peer is READABLE here, not just the local one. Dark / no
7939
+ // journal reader undefined ⇒ [] (isLive already gates a disabled store to a
7940
+ // strict no-op, so this never changes single-machine behavior).
7941
+ loadOriginRecords: (store, recordKey) => store === LEARNING_STORE_KEY && replicatedPeerStreamReader
7942
+ ? replicatedPeerStreamReader.loadOriginRecords(store, recordKey)
7943
+ : [],
7944
+ listRecordKeys: (store) => store === LEARNING_STORE_KEY && replicatedPeerStreamReader
7945
+ ? replicatedPeerStreamReader.listRecordKeys(store)
7946
+ : [],
7873
7947
  droppedOrigins: droppedOriginRegistry,
7874
7948
  conflictStore,
7875
7949
  });
7876
- void learningsUnionReader; // consumed by the learnings peer-read surface + the journal-apply rollout stage (WS2.2+)
7950
+ void learningsUnionReader; // consumed by the learnings peer-read surface (the E2E reads through it) + future session-context injection
7951
+ // WS2 SEND-SIDE: attach the journal-backed emitter to the EvolutionManager's
7952
+ // learning hooks. The call sites already fire emitPut/emitDelete on every
7953
+ // saveLearnings (prune→emitDelete, survivor→emitPut); the adapter maps the
7954
+ // manager's emit signature to the store's build*RecordData. The emitter owns the
7955
+ // dark gate, HLC tick, `observed` witness, and journal append. Attached only when
7956
+ // the emitter exists (journal live); when dark the hooks stay no-ops (byte-
7957
+ // identical single-machine behavior — the local LRN-NNN id never crosses the wire).
7958
+ if (replicatedRecordEmitter) {
7959
+ const emitter = replicatedRecordEmitter;
7960
+ evolution.setLearningReplicationEmitter({
7961
+ emitPut: (rec) => emitter.emit(LEARNING_STORE_KEY, deriveLearningRecordKey(rec.title, rec.category, rec.source), (hlc, origin, observed) => buildLearningRecordData({ record: rec, hlc, origin, observed })),
7962
+ emitDelete: (title, category, source, deletedAt) => emitter.emit(LEARNING_STORE_KEY, deriveLearningRecordKey(title, category, source), (hlc, origin, observed) => buildLearningTombstoneData({ title, category, source, hlc, origin, deletedAt, observed })),
7963
+ });
7964
+ }
7965
+ // WS2.3 SEND-SIDE: attach the journal-backed emitter to the RelationshipManager's
7966
+ // replication hooks. The manager already fires emitPut on every saved person and
7967
+ // emitDelete on erase/merge (RelationshipManager.setReplicationEmitter); the adapter
7968
+ // maps the manager's emit signature to the relationship build*RecordData projection.
7969
+ // The generic emitter owns the dark gate, HLC tick, `observed` witness, journal
7970
+ // append, and ALL the safety guards (null recordKey ⇒ skip, null projection ⇒ skip,
7971
+ // over-cap throw ⇒ counted no-op) — so the adapter mirrors learnings with no extra
7972
+ // guarding. Attached only when the emitter exists (journal live) AND the manager is
7973
+ // constructed; when stateSync.relationships is dark the hooks stay no-ops (byte-
7974
+ // identical single-machine behavior — the local UUID id never crosses; only the
7975
+ // disclosure-minimized, channel-keyed projection does — REQ-M4).
7976
+ if (replicatedRecordEmitter && relationships) {
7977
+ const emitter = replicatedRecordEmitter;
7978
+ relationships.setReplicationEmitter({
7979
+ emitPut: (rec) => emitter.emit(RELATIONSHIP_STORE_KEY, deriveRelationshipRecordKey(rec.channels), (hlc, origin, observed) => buildRelationshipRecordData({ record: rec, hlc, origin, observed })),
7980
+ emitDelete: (channels, deletedAt) => emitter.emit(RELATIONSHIP_STORE_KEY, deriveRelationshipRecordKey(channels), (hlc, origin, observed) => buildRelationshipTombstoneData({ channels, hlc, origin, deletedAt, observed })),
7981
+ });
7982
+ }
7877
7983
  // WS2.4 — the bypass-proof union reader for the `knowledge` store + the emit seam on
7878
7984
  // the KnowledgeManager. The KnowledgeManager reads the local catalog.json (cheap, no
7879
7985
  // background work); we construct one here scoped to the replication wiring. The union