instar 1.3.511 → 1.3.513

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 (91) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +168 -2
  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 +42 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/core/CoherenceJournal.d.ts +31 -1
  8. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  9. package/dist/core/CoherenceJournal.js +49 -2
  10. package/dist/core/CoherenceJournal.js.map +1 -1
  11. package/dist/core/JournalSyncApplier.d.ts.map +1 -1
  12. package/dist/core/JournalSyncApplier.js +18 -0
  13. package/dist/core/JournalSyncApplier.js.map +1 -1
  14. package/dist/core/MeshRpc.d.ts +6 -0
  15. package/dist/core/MeshRpc.d.ts.map +1 -1
  16. package/dist/core/MeshRpc.js +1 -0
  17. package/dist/core/MeshRpc.js.map +1 -1
  18. package/dist/core/PeerPresencePuller.d.ts +19 -0
  19. package/dist/core/PeerPresencePuller.d.ts.map +1 -1
  20. package/dist/core/PeerPresencePuller.js +7 -0
  21. package/dist/core/PeerPresencePuller.js.map +1 -1
  22. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  23. package/dist/core/PostUpdateMigrator.js +57 -0
  24. package/dist/core/PostUpdateMigrator.js.map +1 -1
  25. package/dist/core/PreferencesManager.d.ts +34 -0
  26. package/dist/core/PreferencesManager.d.ts.map +1 -1
  27. package/dist/core/PreferencesManager.js +74 -0
  28. package/dist/core/PreferencesManager.js.map +1 -1
  29. package/dist/core/PreferencesSync.d.ts +167 -0
  30. package/dist/core/PreferencesSync.d.ts.map +1 -0
  31. package/dist/core/PreferencesSync.js +307 -0
  32. package/dist/core/PreferencesSync.js.map +1 -0
  33. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  34. package/dist/core/devGatedFeatures.js +5 -0
  35. package/dist/core/devGatedFeatures.js.map +1 -1
  36. package/dist/core/types.d.ts +34 -0
  37. package/dist/core/types.d.ts.map +1 -1
  38. package/dist/core/types.js.map +1 -1
  39. package/dist/monitoring/GreenPrAutoMerger.d.ts +188 -0
  40. package/dist/monitoring/GreenPrAutoMerger.d.ts.map +1 -0
  41. package/dist/monitoring/GreenPrAutoMerger.js +393 -0
  42. package/dist/monitoring/GreenPrAutoMerger.js.map +1 -0
  43. package/dist/monitoring/GuardLatchStore.d.ts +134 -0
  44. package/dist/monitoring/GuardLatchStore.d.ts.map +1 -0
  45. package/dist/monitoring/GuardLatchStore.js +255 -0
  46. package/dist/monitoring/GuardLatchStore.js.map +1 -0
  47. package/dist/monitoring/MergeRunner.d.ts +126 -0
  48. package/dist/monitoring/MergeRunner.d.ts.map +1 -0
  49. package/dist/monitoring/MergeRunner.js +296 -0
  50. package/dist/monitoring/MergeRunner.js.map +1 -0
  51. package/dist/monitoring/floorDriftCanary.d.ts +88 -0
  52. package/dist/monitoring/floorDriftCanary.d.ts.map +1 -0
  53. package/dist/monitoring/floorDriftCanary.js +89 -0
  54. package/dist/monitoring/floorDriftCanary.js.map +1 -0
  55. package/dist/monitoring/greenPrAutomergeWiring.d.ts +73 -0
  56. package/dist/monitoring/greenPrAutomergeWiring.d.ts.map +1 -0
  57. package/dist/monitoring/greenPrAutomergeWiring.js +273 -0
  58. package/dist/monitoring/greenPrAutomergeWiring.js.map +1 -0
  59. package/dist/monitoring/greenPrLogic.d.ts +121 -0
  60. package/dist/monitoring/greenPrLogic.d.ts.map +1 -0
  61. package/dist/monitoring/greenPrLogic.js +198 -0
  62. package/dist/monitoring/greenPrLogic.js.map +1 -0
  63. package/dist/monitoring/guardManifest.d.ts.map +1 -1
  64. package/dist/monitoring/guardManifest.js +12 -0
  65. package/dist/monitoring/guardManifest.js.map +1 -1
  66. package/dist/scaffold/templates.d.ts.map +1 -1
  67. package/dist/scaffold/templates.js +1 -0
  68. package/dist/scaffold/templates.js.map +1 -1
  69. package/dist/server/AgentServer.d.ts +5 -0
  70. package/dist/server/AgentServer.d.ts.map +1 -1
  71. package/dist/server/AgentServer.js +3 -0
  72. package/dist/server/AgentServer.js.map +1 -1
  73. package/dist/server/CapabilityIndex.d.ts.map +1 -1
  74. package/dist/server/CapabilityIndex.js +16 -0
  75. package/dist/server/CapabilityIndex.js.map +1 -1
  76. package/dist/server/routes.d.ts +10 -0
  77. package/dist/server/routes.d.ts.map +1 -1
  78. package/dist/server/routes.js +137 -1
  79. package/dist/server/routes.js.map +1 -1
  80. package/dist/server/stopGate.d.ts +45 -0
  81. package/dist/server/stopGate.d.ts.map +1 -1
  82. package/dist/server/stopGate.js +74 -0
  83. package/dist/server/stopGate.js.map +1 -1
  84. package/package.json +1 -1
  85. package/scripts/safe-merge.mjs +449 -59
  86. package/src/data/builtin-manifest.json +64 -64
  87. package/src/scaffold/templates.ts +1 -0
  88. package/upgrades/1.3.512.md +65 -0
  89. package/upgrades/1.3.513.md +61 -0
  90. package/upgrades/side-effects/green-pr-automerge-enforcement.md +171 -0
  91. package/upgrades/side-effects/multi-machine-seamlessness-ws21-preferences-pool.md +116 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,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;AA0G7D,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;AA80CD,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,CAgyYtE;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;AAgCH,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;AA0G7D,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;AA80CD,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,CAm8YtE;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"}
@@ -3103,6 +3103,18 @@ export async function startServer(options) {
3103
3103
  // same explicit replication gate; undefined = dark (verb answers
3104
3104
  // 'disabled', merge layer returns own rows only).
3105
3105
  let commitmentReplicaStore;
3106
+ // Preferences-pool receive side (MULTI-MACHINE-SEAMLESSNESS-SPEC §WS2.1) —
3107
+ // gated on multiMachine.seamlessness.ws21PreferencesPool; undefined = dark
3108
+ // (the verb answers 'disabled', the union read returns own-only rows).
3109
+ let preferenceReplicaStore;
3110
+ // WS2.1 serve-side own store — the PreferencesManager whose advert + records
3111
+ // the `preferences-sync` verb serves. Constructed alongside the replica store
3112
+ // under the same gate; undefined = dark.
3113
+ let _preferencesManagerForSync;
3114
+ // WS2.1 dark gate — read LIVE (mirrors the ws3OneVoice/ws13Reconcile sibling
3115
+ // pattern: a plain seamlessness boolean read off config, NOT resolveDevAgentGate).
3116
+ // Single-machine agents are a strict no-op regardless (no peer ever pages).
3117
+ const ws21PrefsPoolEnabled = () => (config.multiMachine?.seamlessness ?? {}).ws21PreferencesPool === true;
3106
3118
  // P1.5b owner-routed mutation (§3.4): the owner-side replay window, the
3107
3119
  // forwarder-side durable intent queue, and the route-facing forward fn.
3108
3120
  // All undefined while dark.
@@ -11834,6 +11846,72 @@ export async function startServer(options) {
11834
11846
  }
11835
11847
  }
11836
11848
  }
11849
+ // ── GreenPrAutoMerger (green-pr-automerge-enforcement) ──────────────
11850
+ // Repo-gated, action-bearing watcher: only constructed when the install has
11851
+ // an analyzable instar git repo AND scripts/safe-merge.mjs, AND the feature
11852
+ // is enabled in config. On a plain npm install both are absent → null →
11853
+ // routes 503. Started here (interval-driven) so the guarantee survives
11854
+ // session death; the dual-latch gate is read every tick.
11855
+ let greenPrAutoMerger = null;
11856
+ let guardLatchStore = null;
11857
+ {
11858
+ const gpCfg = config.monitoring?.greenPrAutoMerge;
11859
+ const repoPath = process.cwd();
11860
+ const safeMergePath = path.join(repoPath, 'scripts', 'safe-merge.mjs');
11861
+ if (gpCfg?.enabled) {
11862
+ const wiring = await import('../monitoring/greenPrAutomergeWiring.js');
11863
+ if (wiring.isAnalyzableGreenPrRepo(repoPath, safeMergePath)) {
11864
+ const gpMachineId = coordinator.identity?.machineId ?? `m_host_${os.hostname()}`;
11865
+ const agentNamespace = config.projectName || 'agent';
11866
+ const wiringOpts = {
11867
+ repoPath, safeMergePath, stateDir: config.stateDir, machineId: gpMachineId,
11868
+ repo: 'JKHeadley/instar', agentNamespace,
11869
+ mergeTimeoutMs: Number(gpCfg.mergeTimeoutMs) || 1_500_000,
11870
+ mergeKillGraceMs: Number(gpCfg.mergeKillGraceMs) || 60_000,
11871
+ holdsLease: () => (leaseCoordinatorRef ? leaseCoordinatorRef.holdsLease() : true),
11872
+ leaseEpoch: () => (leaseCoordinatorRef ? leaseCoordinatorRef.currentEpoch() : 0),
11873
+ // Single-machine: the durable local file is the authoritative gate.
11874
+ // Multi-machine peer-latch merge is a follow-up read surface.
11875
+ readPeerLatches: () => [],
11876
+ journal: coherenceJournal ? { emitGuardLatch: (d) => coherenceJournal.emitGuardLatch(d) } : undefined,
11877
+ postAttentionAggregate: async (lines) => {
11878
+ if (!telegram)
11879
+ return;
11880
+ try {
11881
+ await telegram.createAttentionItem({
11882
+ id: 'green-pr-automerge:aggregate',
11883
+ title: 'Green-PR auto-merge needs attention',
11884
+ summary: lines.join('\n'),
11885
+ category: 'degradation',
11886
+ priority: 'MEDIUM',
11887
+ });
11888
+ }
11889
+ catch { /* attention delivery is non-fatal */ }
11890
+ },
11891
+ auditPath: path.join(config.stateDir, '..', 'logs', 'green-pr-automerge.jsonl'),
11892
+ };
11893
+ guardLatchStore = wiring.buildGuardLatchStore(wiringOpts);
11894
+ const deps = wiring.buildGreenPrDeps(wiringOpts, guardLatchStore);
11895
+ const { GreenPrAutoMerger } = await import('../monitoring/GreenPrAutoMerger.js');
11896
+ greenPrAutoMerger = new GreenPrAutoMerger(deps, {
11897
+ ...gpCfg,
11898
+ agentNamespace,
11899
+ repo: 'JKHeadley/instar',
11900
+ });
11901
+ if (greenPrAutoMerger.invariantOk) {
11902
+ guardLatchStore.markPoolArmed(); // R7: this pool is deliberately armed
11903
+ greenPrAutoMerger.start();
11904
+ console.log(pc.green(' GreenPrAutoMerger enabled (auto-merges green self-authored PRs — Phase 7 machinery)'));
11905
+ }
11906
+ else {
11907
+ console.log(pc.red(` GreenPrAutoMerger NOT started — timeout invariant violated: ${greenPrAutoMerger.invariantReason}`));
11908
+ }
11909
+ }
11910
+ else {
11911
+ console.log(pc.dim(' GreenPrAutoMerge enabled in config but no analyzable instar repo + safe-merge found — staying inert'));
11912
+ }
11913
+ }
11914
+ }
11837
11915
  // ── Multi-Machine Session Pool registry (§L2) — live MachineCapacity view for GET /pool ──
11838
11916
  // Always instantiated (cheap); the feature stays dark behind the sessionPool stage gate.
11839
11917
  // Self-attests hardware + records a self-heartbeat so GET /pool + the Machines tab show
@@ -12497,7 +12575,13 @@ export async function startServer(options) {
12497
12575
  const commitmentsAdvert = commitmentReplicaStore
12498
12576
  ? commitmentTracker.getReplicationAdvert() ?? undefined
12499
12577
  : undefined;
12500
- return { ...base, journalAdvert, ...(commitmentsAdvert ? { commitmentsAdvert } : {}) };
12578
+ // MULTI-MACHINE-SEAMLESSNESS-SPEC §WS2.1 the preferences advert,
12579
+ // answered from disk (the store is tiny; not a hot path). Omitted
12580
+ // while the layer is dark; old peers ignore the extra field.
12581
+ const preferencesAdvert = (preferenceReplicaStore && _preferencesManagerForSync)
12582
+ ? _preferencesManagerForSync.getReplicationAdvert()
12583
+ : undefined;
12584
+ return { ...base, journalAdvert, ...(commitmentsAdvert ? { commitmentsAdvert } : {}), ...(preferencesAdvert ? { preferencesAdvert } : {}) };
12501
12585
  },
12502
12586
  // Pool Dashboard Streaming (§2.3): mint a single-use bearer ticket
12503
12587
  // for the authenticated peer so it may open a /pool-stream WS to
@@ -12597,6 +12681,26 @@ export async function startServer(options) {
12597
12681
  syncPageBytes: wsCfgC?.syncPageBytes,
12598
12682
  });
12599
12683
  },
12684
+ // MULTI-MACHINE-SEAMLESSNESS-SPEC §WS2.1 — serve OWN learned-
12685
+ // preference records as seq-windowed delta pages (lastMutatedSeq >
12686
+ // sinceSeq), incarnation-fenced, `learning`-field credential-redacted.
12687
+ // Registered always (lockstep with the union+RBAC edits); answers
12688
+ // 'disabled' until the replication gate constructs the layer.
12689
+ 'preferences-sync': async (cmd) => {
12690
+ const c = cmd;
12691
+ if (!preferenceReplicaStore || !_preferencesManagerForSync)
12692
+ return { ok: false, reason: 'preferences-sync disabled' };
12693
+ const syncMod = await import('../core/PreferencesSync.js');
12694
+ // WS2.1 reads its OWN preferences config section, not commitments
12695
+ // (review WS2.1 findings #4/#7). Absent → engine default page size.
12696
+ const wsCfgP = config.multiMachine?.coherenceJournal?.preferences;
12697
+ return syncMod.buildPreferencesSyncPage(c.request, {
12698
+ ownMachineId: cjOwnMachineId ?? meshSelfId,
12699
+ records: _preferencesManagerForSync.getAllForSync(),
12700
+ advert: _preferencesManagerForSync.getReplicationAdvert(),
12701
+ syncPageBytes: wsCfgP?.syncPageBytes,
12702
+ });
12703
+ },
12600
12704
  place: ownAction,
12601
12705
  claim: ownAction,
12602
12706
  transfer: ownAction,
@@ -13192,6 +13296,30 @@ export async function startServer(options) {
13192
13296
  commitmentReplicaStore = undefined;
13193
13297
  console.log(pc.dim(` [commitments-sync] not constructed: ${e instanceof Error ? e.message : String(e)}`));
13194
13298
  }
13299
+ // ── Preferences-pool receive side (MULTI-MACHINE-SEAMLESSNESS-SPEC
13300
+ // §WS2.1) ── Gated on its OWN flag (ws21PreferencesPool), independent
13301
+ // of the working-set/commitments gates. Read-replication only: a
13302
+ // replica store + the own PreferencesManager whose advert/records the
13303
+ // serve verb pages. The drive below pulls delta pages when a peer's
13304
+ // advert is ahead of our cursor. Dark (flag off) → nothing constructed,
13305
+ // the verb answers 'disabled', the union read returns own-only rows.
13306
+ if (ws21PrefsPoolEnabled()) {
13307
+ try {
13308
+ const psMod = await import('../core/PreferencesSync.js');
13309
+ const pmMod = await import('../core/PreferencesManager.js');
13310
+ preferenceReplicaStore = new psMod.PreferenceReplicaStore({
13311
+ stateDir: config.stateDir,
13312
+ logger: (m) => console.log(pc.dim(` [preferences-sync] ${m}`)),
13313
+ });
13314
+ _preferencesManagerForSync = new pmMod.PreferencesManager(config.stateDir);
13315
+ console.log(pc.dim(' [preferences-sync] replica store wired (serve + receive + advert)'));
13316
+ }
13317
+ catch (e) { /* @silent-fallback-ok: preferences-sync construction failure degrades to local-only preferences — never blocks boot (MULTI-MACHINE-SEAMLESSNESS-SPEC §WS2.1) */
13318
+ preferenceReplicaStore = undefined;
13319
+ _preferencesManagerForSync = undefined;
13320
+ console.log(pc.dim(` [preferences-sync] not constructed: ${e instanceof Error ? e.message : String(e)}`));
13321
+ }
13322
+ }
13195
13323
  }
13196
13324
  catch (e) { /* @silent-fallback-ok: working-set pull wiring failure degrades to serve-only (the verb still answers); never blocks server boot (WORKING-SET-HANDOFF-SPEC §4) */
13197
13325
  workingSetPullCoordinator = undefined;
@@ -13681,6 +13809,10 @@ export async function startServer(options) {
13681
13809
  loadAvg: cap.loadAvg,
13682
13810
  journalAdvert,
13683
13811
  ...(cap.commitmentsAdvert ? { commitmentsAdvert: cap.commitmentsAdvert } : {}),
13812
+ // §WS2.1 sibling pass-through (the #930/A2 narrowing lesson): the
13813
+ // peer's preferences advert is served but would be dropped here
13814
+ // without this, so drivePreferencesSync would never fire.
13815
+ ...(cap.preferencesAdvert ? { preferencesAdvert: cap.preferencesAdvert } : {}),
13684
13816
  ...(cap.quotaState ? { quotaState: cap.quotaState } : {}),
13685
13817
  // Guard posture rides the same pass-through (the A2 narrowing
13686
13818
  // lesson): dropping it here would blind the pool to peers' posture.
@@ -13724,6 +13856,40 @@ export async function startServer(options) {
13724
13856
  return;
13725
13857
  }
13726
13858
  },
13859
+ // MULTI-MACHINE-SEAMLESSNESS-SPEC §WS2.1 — pull preference delta pages
13860
+ // when the peer's advert is ahead of our replica cursor; bounded pages
13861
+ // per tick (the remainder rides the next pass). No-op while dark.
13862
+ drivePreferencesSync: async (machineId, url, advert) => {
13863
+ if (!preferenceReplicaStore)
13864
+ return;
13865
+ const cursor = preferenceReplicaStore.cursorFor(machineId);
13866
+ const upToDate = cursor.incarnation === advert.incarnation && cursor.sinceSeq >= advert.replicationSeq;
13867
+ if (upToDate)
13868
+ return;
13869
+ // WS2.1 reads its OWN preferences config section (review #5/#7).
13870
+ const psCfg = config.multiMachine?.coherenceJournal?.preferences;
13871
+ const maxPages = psCfg?.maxSyncPagesPerTick ?? 4;
13872
+ let since = cursor.incarnation === advert.incarnation ? cursor.sinceSeq : 0;
13873
+ let inc = cursor.incarnation;
13874
+ for (let i = 0; i < maxPages; i++) {
13875
+ const res = await meshClient.send({ machineId, url }, { type: 'preferences-sync', request: { sinceSeq: since, ...(inc ? { incarnation: inc } : {}) } }, 0);
13876
+ if (!res.ok || !res.result || typeof res.result !== 'object')
13877
+ return;
13878
+ const page = res.result;
13879
+ if (!page.incarnation)
13880
+ return; // 'disabled' answer shape
13881
+ preferenceReplicaStore.applyPage(machineId, page);
13882
+ if (page.incarnationChanged) {
13883
+ inc = page.incarnation;
13884
+ since = 0;
13885
+ continue;
13886
+ }
13887
+ since = page.nextSinceSeq;
13888
+ inc = page.incarnation;
13889
+ if (page.done)
13890
+ return;
13891
+ }
13892
+ },
13727
13893
  });
13728
13894
  void peerPresencePuller.pullOnce();
13729
13895
  const peerPresenceTimer = setInterval(() => { void peerPresencePuller.pullOnce(); }, 30_000);
@@ -14003,7 +14169,7 @@ export async function startServer(options) {
14003
14169
  carrier: _topicProfileCarrier,
14004
14170
  }
14005
14171
  : null;
14006
- const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographer: cartographer ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
14172
+ const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographer: cartographer ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, greenPrAutoMerger: greenPrAutoMerger ?? undefined, guardLatchStore: guardLatchStore ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, preferenceReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
14007
14173
  // Resolve the late-bound topic-operator getter (increment 2e): routing was
14008
14174
  // wired before the server existed; from here on inbound binds use the
14009
14175
  // server's own store instance.