instar 1.3.606 → 1.3.608

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 (76) hide show
  1. package/dist/commands/server.d.ts.map +1 -1
  2. package/dist/commands/server.js +333 -32
  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 +38 -0
  6. package/dist/config/ConfigDefaults.js.map +1 -1
  7. package/dist/coordination/CrossMachineMandate.d.ts +53 -0
  8. package/dist/coordination/CrossMachineMandate.d.ts.map +1 -0
  9. package/dist/coordination/CrossMachineMandate.js +76 -0
  10. package/dist/coordination/CrossMachineMandate.js.map +1 -0
  11. package/dist/core/AccountCredentialShare.d.ts +115 -0
  12. package/dist/core/AccountCredentialShare.d.ts.map +1 -0
  13. package/dist/core/AccountCredentialShare.js +113 -0
  14. package/dist/core/AccountCredentialShare.js.map +1 -0
  15. package/dist/core/AccountFollowMeGrants.d.ts +92 -0
  16. package/dist/core/AccountFollowMeGrants.d.ts.map +1 -0
  17. package/dist/core/AccountFollowMeGrants.js +106 -0
  18. package/dist/core/AccountFollowMeGrants.js.map +1 -0
  19. package/dist/core/CoherenceJournal.d.ts +1 -1
  20. package/dist/core/CoherenceJournal.d.ts.map +1 -1
  21. package/dist/core/CoherenceJournal.js +12 -2
  22. package/dist/core/CoherenceJournal.js.map +1 -1
  23. package/dist/core/PairingEpochManager.d.ts +68 -0
  24. package/dist/core/PairingEpochManager.d.ts.map +1 -0
  25. package/dist/core/PairingEpochManager.js +88 -0
  26. package/dist/core/PairingEpochManager.js.map +1 -0
  27. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  28. package/dist/core/PostUpdateMigrator.js +38 -0
  29. package/dist/core/PostUpdateMigrator.js.map +1 -1
  30. package/dist/core/SecretStore.d.ts +44 -0
  31. package/dist/core/SecretStore.d.ts.map +1 -1
  32. package/dist/core/SecretStore.js +126 -0
  33. package/dist/core/SecretStore.js.map +1 -1
  34. package/dist/core/SecretSync.d.ts.map +1 -1
  35. package/dist/core/SecretSync.js +6 -0
  36. package/dist/core/SecretSync.js.map +1 -1
  37. package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts +106 -0
  38. package/dist/core/SubscriptionAccountMetaReplicatedStore.d.ts.map +1 -0
  39. package/dist/core/SubscriptionAccountMetaReplicatedStore.js +263 -0
  40. package/dist/core/SubscriptionAccountMetaReplicatedStore.js.map +1 -0
  41. package/dist/core/SubscriptionPool.d.ts +23 -5
  42. package/dist/core/SubscriptionPool.d.ts.map +1 -1
  43. package/dist/core/SubscriptionPool.js +30 -6
  44. package/dist/core/SubscriptionPool.js.map +1 -1
  45. package/dist/core/devGatedFeatures.d.ts.map +1 -1
  46. package/dist/core/devGatedFeatures.js +12 -0
  47. package/dist/core/devGatedFeatures.js.map +1 -1
  48. package/dist/core/types.d.ts +37 -0
  49. package/dist/core/types.d.ts.map +1 -1
  50. package/dist/core/types.js.map +1 -1
  51. package/dist/monitoring/AutonomousLivenessReconciler.d.ts +278 -0
  52. package/dist/monitoring/AutonomousLivenessReconciler.d.ts.map +1 -0
  53. package/dist/monitoring/AutonomousLivenessReconciler.js +660 -0
  54. package/dist/monitoring/AutonomousLivenessReconciler.js.map +1 -0
  55. package/dist/monitoring/ResumeQueue.d.ts +10 -0
  56. package/dist/monitoring/ResumeQueue.d.ts.map +1 -1
  57. package/dist/monitoring/ResumeQueue.js +12 -0
  58. package/dist/monitoring/ResumeQueue.js.map +1 -1
  59. package/dist/scaffold/templates.d.ts.map +1 -1
  60. package/dist/scaffold/templates.js +7 -0
  61. package/dist/scaffold/templates.js.map +1 -1
  62. package/dist/server/AgentServer.d.ts +1 -0
  63. package/dist/server/AgentServer.d.ts.map +1 -1
  64. package/dist/server/AgentServer.js +6 -0
  65. package/dist/server/AgentServer.js.map +1 -1
  66. package/dist/server/routes.d.ts +4 -0
  67. package/dist/server/routes.d.ts.map +1 -1
  68. package/dist/server/routes.js +10 -0
  69. package/dist/server/routes.js.map +1 -1
  70. package/package.json +1 -1
  71. package/src/data/builtin-manifest.json +64 -64
  72. package/src/scaffold/templates.ts +7 -0
  73. package/upgrades/1.3.607.md +25 -0
  74. package/upgrades/1.3.608.md +29 -0
  75. package/upgrades/side-effects/autonomous-liveness-reconciler.md +39 -0
  76. package/upgrades/side-effects/ws52-account-follow-me-pr1.md +74 -0
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,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,CAq/dtE;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;AAoCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,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,CA+yetE;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"}
@@ -24,7 +24,7 @@ import { TopicProfileOrchestrator, resolvedToApplied, } from '../core/TopicProfi
24
24
  import { CodexResumeMap } from '../core/CodexResumeMap.js';
25
25
  import { paneIdleWithEmptyInput } from '../core/ModelSwapService.js';
26
26
  import { escalatedModelIds, normalizeTierEscalationConfig } from '../core/ModelTierEscalation.js';
27
- import { activeAutonomousJobs, autonomousRunRemainingForTopic } from '../core/AutonomousSessions.js';
27
+ import { activeAutonomousJobs, autonomousRunRemainingForTopic, listAutonomousJobs } from '../core/AutonomousSessions.js';
28
28
  import { AGE_LIMIT_ACTIVE_RUN_REASON, COMMITMENT_ACTIVE_RUN_REASON } from '../core/WorkEvidence.js';
29
29
  import { gapBEligibleForTopic, recentUserMessageFromHistory, resolveGapBInjectionGate, decideGapBInjection } from '../core/gapBCommitmentEvidence.js';
30
30
  import { TopicProfileTransferCarrier, createTopicProfilePullHandler } from '../core/TopicProfileTransferCarrier.js';
@@ -3440,6 +3440,17 @@ export async function startServer(options) {
3440
3440
  // verification-failed propagates as a tombstone (ThreadlinePairingReplicatedStore).
3441
3441
  const { THREADLINE_PAIRING_KIND_REGISTRATION } = await import('../core/ThreadlinePairingReplicatedStore.js');
3442
3442
  replicatedKindRegistry.register(THREADLINE_PAIRING_KIND_REGISTRATION);
3443
+ // WS5.2 Account Follow-Me §6.1a — register the `subscription-account-meta` kind onto the
3444
+ // registry: registry follow-me = METADATA ONLY (a redacted, credential-free projection of a
3445
+ // SubscriptionAccount; configHome + every credential field STRIPPED). Dual-registry's dynamic
3446
+ // half (the static half is CoherenceJournal.JOURNAL_KINDS, which now lists
3447
+ // 'subscription-account-meta'). Registration is INERT — emission/serve/pull stay gated behind
3448
+ // `multiMachine.accountFollowMe.enabled` (default false ⇒ strict no-op, NO account metadata
3449
+ // crosses a machine boundary). The recordKey is the account id (charset-clamped). This kind
3450
+ // carries NO login: the credential half is the SEPARATE account-credential-share verb +
3451
+ // re-mint-per-machine default (Mechanism B); see ws52-account-follow-me-security.md.
3452
+ const { SUBSCRIPTION_ACCOUNT_META_KIND_REGISTRATION } = await import('../core/SubscriptionAccountMetaReplicatedStore.js');
3453
+ replicatedKindRegistry.register(SUBSCRIPTION_ACCOUNT_META_KIND_REGISTRATION);
3443
3454
  // ── WS2 SEND-SIDE wiring (docs/specs/WS2-SEND-SIDE-EMISSION-SPEC.md). The
3444
3455
  // substrate above ships the registry + receive/serve machinery + advert; THIS
3445
3456
  // wires the SEND half that was deferred ("the journal-backed emitter is attached
@@ -3542,7 +3553,17 @@ export async function startServer(options) {
3542
3553
  // `enabled` is already the resolved boolean — the funnels keep their unchanged
3543
3554
  // `enabled === true` semantics but now see a live flag on a dev agent. An explicit
3544
3555
  // operator `enabled` in config still wins (force-dark false / fleet-flip true).
3545
- const _stateSyncStoresResolved = resolveStateSyncStores(config);
3556
+ const _stateSyncStoresBase = resolveStateSyncStores(config);
3557
+ // WS5.2 §6.1a — the `subscriptionAccountMeta` store gates on `multiMachine.accountFollowMe`
3558
+ // (NOT a `stateSync.*` flag). Inject its dev-gate-resolved enabled-state into the SAME
3559
+ // store-flags map the generic emitter + receive-advert consult, so account-meta emission +
3560
+ // the receive capability gate on accountFollowMe (dev-live / fleet-dark) coherently. When the
3561
+ // gate resolves OFF the entry is absent ⇒ the emitter's `enabled===true` check fails ⇒ strict
3562
+ // no-op (no account metadata ever crosses), exactly like the dark stateSync stores.
3563
+ const _accountFollowMeEnabled = resolveDevAgentGate(config.multiMachine?.accountFollowMe?.enabled, config);
3564
+ const _stateSyncStoresResolved = _accountFollowMeEnabled
3565
+ ? { ...(_stateSyncStoresBase ?? {}), subscriptionAccountMeta: { enabled: true } }
3566
+ : _stateSyncStoresBase;
3546
3567
  // WS2 send-side: the generic journal-backed record emitter (the concrete emitter
3547
3568
  // the per-store managers' emit hooks call). Needs the journal sink, the HLC clock,
3548
3569
  // the registry (store → kind), this machine's origin id, the resolved stateSync
@@ -6398,6 +6419,7 @@ export async function startServer(options) {
6398
6419
  const rqCfg = config.monitoring?.resumeQueue ?? {};
6399
6420
  let resumeQueue = null;
6400
6421
  let resumeDrainer = null;
6422
+ let autonomousLivenessReconciler = null;
6401
6423
  let prHandLease = null;
6402
6424
  // GAP-B Part A surface (spec: autonomous-registration-guarantee.md) — the
6403
6425
  // aggregated-attention chokepoint reference, hoisted to the handler's scope.
@@ -6586,31 +6608,50 @@ export async function startServer(options) {
6586
6608
  return null;
6587
6609
  }
6588
6610
  };
6611
+ // ── Shared closures (spec §"Shared closures"): extracted to named consts
6612
+ // and passed by the SAME reference into BOTH the ResumeQueueDrainer and the
6613
+ // AutonomousLivenessReconciler, so "the reaper, the drainer, and the
6614
+ // reconciler agree" is structurally true (no divergent re-created copy —
6615
+ // the operator-stop file-mtime arm in particular cannot be forgotten). ──
6616
+ const sharedCanSpawnSession = () => quotaManager ? quotaManager.canSpawnSession().allowed : true;
6617
+ const sharedSessionCountOk = () => sessionManager.listRunningSessions().length <
6618
+ (config.maxSessions ?? 10);
6619
+ const sharedMigrationInFlight = () => quotaManager?.isMigrationInFlight() ?? false;
6620
+ const sharedLiveSessionForTopic = (topicId) => sessionManager.listRunningSessions().some((s) => resolveTopicForTmux(s.tmuxSession) === topicId);
6621
+ const sharedTopicOwnerElsewhere = (topicId) => {
6622
+ // Pool not wired → single-machine → always local.
6623
+ const reg = sessionOwnershipRegistry;
6624
+ const self = _meshSelfId;
6625
+ if (!reg || !self)
6626
+ return false;
6627
+ const owner = reg.ownerOf(String(topicId));
6628
+ return !!owner && owner !== self;
6629
+ };
6630
+ const sharedOperatorStopSince = (topicId, sinceIso) => {
6631
+ const since = Date.parse(sinceIso);
6632
+ const perTopic = operatorStopsByTopic.get(topicId) ?? 0;
6633
+ let flagAt = 0;
6634
+ try {
6635
+ flagAt = fs.statSync(path.join(_projectDir, '.instar', 'autonomous-emergency-stop')).mtimeMs;
6636
+ }
6637
+ catch { /* no flag */ }
6638
+ return Math.max(perTopic, globalOperatorStopAt, flagAt) > since;
6639
+ };
6589
6640
  resumeDrainer = new ResumeQueueDrainer({
6590
6641
  queue: rq,
6591
6642
  pressureTier: sharedPressureTier,
6592
- canSpawnSession: () => (quotaManager ? quotaManager.canSpawnSession().allowed : true),
6593
- sessionCountOk: () => sessionManager.listRunningSessions().length <
6594
- (config.maxSessions ?? 10),
6643
+ canSpawnSession: sharedCanSpawnSession,
6644
+ sessionCountOk: sharedSessionCountOk,
6595
6645
  // No catch: a throwing dep resolves to the SAFE side (blocked)
6596
6646
  // inside the drainer's gate — wrapping it here would flip the
6597
6647
  // failure to the lenient side.
6598
- migrationInFlight: () => quotaManager?.isMigrationInFlight() ?? false,
6599
- liveSessionForTopic: (topicId) => sessionManager
6600
- .listRunningSessions()
6601
- .some((s) => resolveTopicForTmux(s.tmuxSession) === topicId),
6648
+ migrationInFlight: sharedMigrationInFlight,
6649
+ liveSessionForTopic: sharedLiveSessionForTopic,
6602
6650
  currentResumeUuid: (topicId) => _topicResumeMap?.get(topicId) ?? null,
6603
- topicOwnerElsewhere: (topicId) => {
6604
- // Pool not wired single-machine always local. No catch: a
6605
- // registry error propagates to the drainer's validateReality,
6606
- // which resolves a throwing dep to the SAFE side (invalidated).
6607
- const reg = sessionOwnershipRegistry;
6608
- const self = _meshSelfId;
6609
- if (!reg || !self)
6610
- return false;
6611
- const owner = reg.ownerOf(String(topicId));
6612
- return !!owner && owner !== self;
6613
- },
6651
+ // Shared reference — the reconciler uses the SAME closure (no catch: a
6652
+ // registry error propagates to the drainer's validateReality, which
6653
+ // resolves a throwing dep to the SAFE side (invalidated)).
6654
+ topicOwnerElsewhere: sharedTopicOwnerElsewhere,
6614
6655
  topicBindingMatches: (topicId, cwd) => {
6615
6656
  const bindings = scopeVerifier?.loadTopicBindings?.();
6616
6657
  const binding = bindings?.[String(topicId)];
@@ -6618,16 +6659,7 @@ export async function startServer(options) {
6618
6659
  return true; // unbound topic → default project
6619
6660
  return path.resolve(cwd).startsWith(path.resolve(binding.projectDir));
6620
6661
  },
6621
- operatorStopSince: (topicId, sinceIso) => {
6622
- const since = Date.parse(sinceIso);
6623
- const perTopic = operatorStopsByTopic.get(topicId) ?? 0;
6624
- let flagAt = 0;
6625
- try {
6626
- flagAt = fs.statSync(path.join(_projectDir, '.instar', 'autonomous-emergency-stop')).mtimeMs;
6627
- }
6628
- catch { /* no flag */ }
6629
- return Math.max(perTopic, globalOperatorStopAt, flagAt) > since;
6630
- },
6662
+ operatorStopSince: sharedOperatorStopSince,
6631
6663
  // Resume-idle-autonomous fix (spec: resume-idle-autonomous-on-reap.md):
6632
6664
  // drain-time liveness re-check for an entry admitted via the
6633
6665
  // age-limit-active-run path. Returns true (= run FINISHED) when the topic's
@@ -6806,6 +6838,242 @@ export async function startServer(options) {
6806
6838
  }, 30_000);
6807
6839
  if (typeof reconcileTimer.unref === 'function')
6808
6840
  reconcileTimer.unref();
6841
+ // ── AutonomousLivenessReconciler (spec: autonomous-liveness-reconciler.md) ──
6842
+ // Level-triggered self-heal for a "dead but marked active" autonomous run.
6843
+ // Constructed here (after SessionManager + the ResumeQueueDrainer), inside
6844
+ // the queue-started block where rq + resolveTopicForTmux + the shared
6845
+ // closures are in scope. Gated by the dev-agent gate (enabled OMITTED in
6846
+ // ConfigDefaults). Reuses the SAME shared closures as the drainer.
6847
+ const livenessCfgRaw = config.monitoring?.autonomousLivenessReconciler ?? {};
6848
+ if (resolveDevAgentGate(livenessCfgRaw.enabled, config)) {
6849
+ const { AutonomousLivenessReconciler } = await import('../monitoring/AutonomousLivenessReconciler.js');
6850
+ const livenessAuditPath = path.join(_projectDir, 'logs', 'autonomous-liveness.jsonl');
6851
+ const auditLiveness = (entry) => {
6852
+ try {
6853
+ fs.mkdirSync(path.dirname(livenessAuditPath), { recursive: true });
6854
+ try {
6855
+ const st = fs.statSync(livenessAuditPath);
6856
+ if (st.size > 5 * 1024 * 1024)
6857
+ fs.renameSync(livenessAuditPath, `${livenessAuditPath}.1`);
6858
+ }
6859
+ catch { /* no file yet */ }
6860
+ fs.appendFileSync(livenessAuditPath, JSON.stringify(entry) + '\n');
6861
+ }
6862
+ catch { /* the audit sink never endangers the reconciler */ }
6863
+ };
6864
+ // Durable cap state (separate redie + spawn-failure counters).
6865
+ const livenessCapPath = path.join(_projectDir, 'state', 'autonomous-liveness-cap.json');
6866
+ // Process-local in-memory in-flight-spawn claim map (spec §"in-flight
6867
+ // claim primitive"): NOT a cross-machine lock — criterion 5 ensures only
6868
+ // the owning+lease-holding machine reconciles a topic, so this only
6869
+ // serializes THIS machine's ticks + its own queue/reconciler paths. A
6870
+ // process restart clears it (a claim never outlives its process).
6871
+ const livenessInflight = new Map();
6872
+ // Resolve the agent home for the cwd-escape check (the worktree root is a
6873
+ // legitimate non-project-root path INSIDE the agent home).
6874
+ const agentHomeReal = (() => {
6875
+ try {
6876
+ return fs.realpathSync(path.join(os.homedir(), '.instar', 'agents', config.projectName ?? ''));
6877
+ }
6878
+ catch {
6879
+ // @silent-fallback-ok — no resolvable agent home → resolveCwd falls
6880
+ // back to the project-dir prefix check only (still fail-closed on a
6881
+ // cwd that escapes the project). Never widens the cwd allowlist.
6882
+ return null;
6883
+ }
6884
+ })();
6885
+ const reconciler = new AutonomousLivenessReconciler({
6886
+ now: () => Date.now(),
6887
+ listActiveRuns: () => {
6888
+ // Source of truth = the per-topic run-state files; UNTRUSTED — read
6889
+ // ONLY active+remaining+topicId+started_at (generation key).
6890
+ const out = [];
6891
+ for (const job of listAutonomousJobs(config.stateDir)) {
6892
+ if (job.topic == null)
6893
+ continue;
6894
+ const topicId = Number(job.topic);
6895
+ if (!Number.isFinite(topicId))
6896
+ continue;
6897
+ const remaining = autonomousRunRemainingForTopic(config.stateDir, topicId);
6898
+ if (!remaining)
6899
+ continue; // not active or window over → not a candidate
6900
+ const startedAtMs = job.startedAt ? new Date(job.startedAt).getTime() : NaN;
6901
+ out.push({
6902
+ topicId,
6903
+ remainingSeconds: remaining.remainingSeconds,
6904
+ paused: job.paused,
6905
+ movedTo: null,
6906
+ moveSuspended: false,
6907
+ startedAtMs: Number.isFinite(startedAtMs) ? startedAtMs : null,
6908
+ });
6909
+ }
6910
+ return out;
6911
+ },
6912
+ liveTopicSnapshot: () => {
6913
+ const set = new Set();
6914
+ for (const s of sessionManager.listRunningSessions()) {
6915
+ const t = resolveTopicForTmux(s.tmuxSession);
6916
+ if (t != null)
6917
+ set.add(t);
6918
+ }
6919
+ return set;
6920
+ },
6921
+ queuePaused: () => rq.isPaused(),
6922
+ topicInResumeQueue: (topicId) => rq.list().some((e) => e.topicId === topicId && (e.status === 'queued' || e.status === 'starting')),
6923
+ operatorStoppedSince: sharedOperatorStopSince,
6924
+ topicOwnerElsewhere: sharedTopicOwnerElsewhere,
6925
+ // DEFAULTS TO HELD on a single-machine agent (coordinator.holdsLease()
6926
+ // returns _role==='awake' ⇒ true when no lease coordinator is wired).
6927
+ holdsLease: () => coordinator.holdsLease(),
6928
+ currentGenerationMs: (topicId) => {
6929
+ // Re-read the topic's CURRENT started_at from disk: a newer run on a
6930
+ // reused topic id writes a newer started_at → obsolete prior run rejected.
6931
+ try {
6932
+ const job = listAutonomousJobs(config.stateDir).find((j) => String(j.topic) === String(topicId));
6933
+ if (!job?.startedAt)
6934
+ return null;
6935
+ const ms = new Date(job.startedAt).getTime();
6936
+ return Number.isFinite(ms) ? ms : null;
6937
+ }
6938
+ catch {
6939
+ // @silent-fallback-ok — unreadable generation → null = "no
6940
+ // competing registration"; the reconciler treats the run as
6941
+ // current (the safe side: a missed obsolete-rejection at worst
6942
+ // respawns a run the state file still says is active).
6943
+ return null;
6944
+ }
6945
+ },
6946
+ quotaOk: sharedCanSpawnSession,
6947
+ sessionCountOk: sharedSessionCountOk,
6948
+ migrationInFlight: sharedMigrationInFlight,
6949
+ pressureTier: sharedPressureTier,
6950
+ inflightSpawnStatus: (topicId) => livenessInflight.get(topicId) ?? { state: 'none' },
6951
+ resolveResumeUuid: (topicId) => _topicResumeMap?.get(topicId) ?? null,
6952
+ resolveCwd: (topicId) => {
6953
+ // Authoritative cwd from the topic-binding registry; realpath-resolved
6954
+ // and validated inside the agent home (worktree root is legitimate).
6955
+ try {
6956
+ const bindings = scopeVerifier?.loadTopicBindings?.();
6957
+ const raw = bindings?.[String(topicId)]?.projectDir ?? _projectDir;
6958
+ let real;
6959
+ try {
6960
+ real = fs.realpathSync(raw);
6961
+ }
6962
+ catch {
6963
+ // @silent-fallback-ok — an unresolvable path is REFUSED (null),
6964
+ // never spawned against; the reconciler raises attention.
6965
+ return null;
6966
+ }
6967
+ if (agentHomeReal && !real.startsWith(agentHomeReal) && !real.startsWith(fs.realpathSync(_projectDir))) {
6968
+ // realpath escapes both the agent home AND the project dir → refuse.
6969
+ return null;
6970
+ }
6971
+ return real;
6972
+ }
6973
+ catch {
6974
+ // @silent-fallback-ok — cwd resolution failed → REFUSE (null);
6975
+ // the reconciler raises attention and does NOT spawn against a guess.
6976
+ return null;
6977
+ }
6978
+ },
6979
+ bindingUnambiguous: (topicId) => {
6980
+ // Consistent across the resume map + the running-session list: a
6981
+ // topic resolving to >1 distinct live session is ambiguous.
6982
+ try {
6983
+ const live = sessionManager
6984
+ .listRunningSessions()
6985
+ .filter((s) => resolveTopicForTmux(s.tmuxSession) === topicId);
6986
+ return live.length <= 1; // 0 (orphaned, expected) or 1 → unambiguous
6987
+ }
6988
+ catch {
6989
+ // @silent-fallback-ok — can't resolve the binding → treat as
6990
+ // AMBIGUOUS (false), which routes to attention, never an
6991
+ // auto-respawn (the safe side per criterion 8).
6992
+ return false;
6993
+ }
6994
+ },
6995
+ respawn: async ({ topicId, cwd }) => {
6996
+ if (!telegram)
6997
+ throw new Error('telegram adapter not available');
6998
+ const topicName = `topic-${topicId}`;
6999
+ const newSession = await spawnSessionForTopic(sessionManager, telegram, topicName, topicId, 'Resuming your autonomous run — your previous session had no live process; picking the work back up.', topicMemory, undefined, undefined, undefined, { cwd });
7000
+ // Tag the respawned session midWork so a later reaper kill is offered
7001
+ // to the ResumeQueue (attacking the incident root cause) rather than
7002
+ // re-entering the reconciler's respawn budget.
7003
+ try {
7004
+ const sess = sessionManager.listRunningSessions().find((s) => s.tmuxSession === newSession);
7005
+ if (sess) {
7006
+ sess.endedMidWork = true;
7007
+ state.saveSession(sess);
7008
+ }
7009
+ }
7010
+ catch { /* @silent-fallback-ok: best-effort midWork tag; a failure must never undo the successful respawn (the run is alive, which is the goal). */ }
7011
+ },
7012
+ claimInflight: (topicId) => {
7013
+ if (livenessInflight.has(topicId))
7014
+ return false; // CAS: someone holds it
7015
+ livenessInflight.set(topicId, { state: 'spawning', sinceMs: Date.now() });
7016
+ return true;
7017
+ },
7018
+ releaseClaim: (topicId) => { livenessInflight.delete(topicId); },
7019
+ settleKill: async (topicId) => {
7020
+ // Terminal abort: clear midWork FIRST (so the ResumeQueue does not
7021
+ // revive an operator-stopped topic), then kill — never via revival.
7022
+ try {
7023
+ const sess = sessionManager.listRunningSessions().find((s) => resolveTopicForTmux(s.tmuxSession) === topicId);
7024
+ if (sess) {
7025
+ sess.endedMidWork = false;
7026
+ state.saveSession(sess);
7027
+ sessionManager.killSession(sess.id);
7028
+ }
7029
+ }
7030
+ catch { /* @silent-fallback-ok: settle-kill is best-effort; the operator-stop record already prevents future revival of this topic. */ }
7031
+ },
7032
+ notifyTopic: async (topicId, text) => { notify('SUMMARY', 'autonomous-liveness', text, topicId); },
7033
+ raiseAggregated: (kind, detail) => raiseResumeAggregated(`liveness:${kind}`, detail),
7034
+ audit: auditLiveness,
7035
+ queueResurrectionCount: (topicId) => rq.resurrectionCountForTopic(topicId),
7036
+ loadCapState: () => {
7037
+ try {
7038
+ const raw = fs.readFileSync(livenessCapPath, 'utf8');
7039
+ const parsed = JSON.parse(raw);
7040
+ return { redie: parsed.redie ?? {}, spawnFailure: parsed.spawnFailure ?? {} };
7041
+ }
7042
+ catch {
7043
+ // @silent-fallback-ok — no/corrupt durable cap → start with empty
7044
+ // in-memory counters (a fresh window). The cap is a brake, not a
7045
+ // safety gate; the in-flight claim + recheck prevent over-spawn.
7046
+ return null;
7047
+ }
7048
+ },
7049
+ saveCapState: (st) => {
7050
+ try {
7051
+ fs.mkdirSync(path.dirname(livenessCapPath), { recursive: true });
7052
+ fs.writeFileSync(livenessCapPath, JSON.stringify(st));
7053
+ }
7054
+ catch { /* cap persistence is best-effort */ }
7055
+ },
7056
+ }, {
7057
+ enabled: livenessCfgRaw.enabled,
7058
+ dryRun: livenessCfgRaw.dryRun ?? true, // dryRun-FIRST on dev
7059
+ tickIntervalSec: livenessCfgRaw.tickIntervalSec ?? 120,
7060
+ debounceTicks: livenessCfgRaw.debounceTicks ?? 2,
7061
+ debounceWindowSec: livenessCfgRaw.debounceWindowSec ?? 180,
7062
+ respawnTimeoutMs: livenessCfgRaw.respawnTimeoutMs ?? 45_000,
7063
+ respawnCapPerWindow: livenessCfgRaw.respawnCapPerWindow ?? 3,
7064
+ respawnCapWindowSec: livenessCfgRaw.respawnCapWindowSec ?? 21_600,
7065
+ spawnFailureRetryCeiling: livenessCfgRaw.spawnFailureRetryCeiling ?? 6,
7066
+ maxPressureBlockedTicks: livenessCfgRaw.maxPressureBlockedTicks ?? 10,
7067
+ maxPressureBlockedSec: livenessCfgRaw.maxPressureBlockedSec ?? 1_800,
7068
+ allowFreshFallback: livenessCfgRaw.allowFreshFallback ?? false,
7069
+ inflightSpawnTtlMs: livenessCfgRaw.inflightSpawnTtlMs,
7070
+ notifyUser: livenessCfgRaw.notifyUser ?? true,
7071
+ });
7072
+ reconciler.start();
7073
+ autonomousLivenessReconciler = reconciler;
7074
+ guardRegistry.register('monitoring.autonomousLivenessReconciler.enabled', () => reconciler.guardStatus());
7075
+ console.log(pc.green(` AutonomousLivenessReconciler started (${(livenessCfgRaw.dryRun ?? true) ? 'dry-run observe-only' : 'LIVE'})`));
7076
+ }
6809
7077
  }
6810
7078
  }
6811
7079
  sessionManager.on('sessionReaped', (e) => {
@@ -6892,7 +7160,26 @@ export async function startServer(options) {
6892
7160
  try {
6893
7161
  if (resumeQueue && !resumeQueue.isDisabled()) {
6894
7162
  const rawTopic = telegram?.getTopicForSession(e.session.tmuxSession);
6895
- const topicId = rawTopic == null ? null : Number.isFinite(Number(rawTopic)) ? Number(rawTopic) : null;
7163
+ let topicId = rawTopic == null ? null : Number.isFinite(Number(rawTopic)) ? Number(rawTopic) : null;
7164
+ // ── ROOT-CAUSE FIX (spec §"Root cause"): the session-name→topic map can
7165
+ // be stale/evicted at the kill instant, so getTopicForSession returns
7166
+ // null precisely when an age-limit recycle should be resumed — and the
7167
+ // entire active-autonomous-run injection branch below is skipped, the
7168
+ // run silently dies (the 2026-06-16 incident). FALL BACK to resolving
7169
+ // the topic from the session name (the SAME parse used at the
7170
+ // coherence-journal emit below) and confirm it against the run-state
7171
+ // file, so the autonomousRunRemainingForTopic check still runs.
7172
+ // Confined to the null case (the resolved-topic path is unchanged) and
7173
+ // inside the existing try/catch (a throw fails toward NO injection).
7174
+ if (topicId == null) {
7175
+ const m = /(?:^|[-_])(?:topic|telegram)[-_]?(\d+)(?:$|[-_])/.exec(e.session.name ?? e.session.tmuxSession ?? '');
7176
+ const parsed = m ? Number(m[1]) : NaN;
7177
+ // Only adopt the parsed topic when the run-state file confirms an active
7178
+ // run for it — never resurrect against a guessed-but-unconfirmed id.
7179
+ if (Number.isFinite(parsed) && autonomousRunRemainingForTopic(config.stateDir, parsed) != null) {
7180
+ topicId = parsed;
7181
+ }
7182
+ }
6896
7183
  const jobDef = e.session.jobSlug
6897
7184
  ? scheduler?.getJobs().find((j) => j.slug === e.session.jobSlug)
6898
7185
  : undefined;
@@ -9228,6 +9515,20 @@ export async function startServer(options) {
9228
9515
  if (subscriptionPool.size() > 0) {
9229
9516
  console.log(pc.green(` Subscription pool: ${subscriptionPool.size()} account(s) registered`));
9230
9517
  }
9518
+ // WS5.2 §6.1a — wire cross-machine registry follow-me (METADATA ONLY). When the generic
9519
+ // record emitter exists AND accountFollowMe resolves enabled (the entry was injected into
9520
+ // _stateSyncStoresResolved above), attach the emit adapter so an account add/status/quota
9521
+ // change/remove replicates a REDACTED projection (projectAccountToMeta strips configHome +
9522
+ // every credential field by allowlist). The emitter itself re-checks the store-flag gate, so
9523
+ // a dark/fleet agent is a strict no-op even if the adapter is attached. NO login crosses.
9524
+ if (replicatedRecordEmitter && _accountFollowMeEnabled) {
9525
+ const emitter = replicatedRecordEmitter;
9526
+ const { SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey, buildSubscriptionAccountMetaData, buildSubscriptionAccountMetaTombstoneData, } = await import('../core/SubscriptionAccountMetaReplicatedStore.js');
9527
+ subscriptionPool.setMetaReplicationEmitter({
9528
+ emitPut: (acct) => emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(acct.id), (hlc, origin, observed) => buildSubscriptionAccountMetaData({ account: acct, hlc, origin, observed })),
9529
+ emitDelete: (accountId, deletedAt) => emitter.emit(SUBSCRIPTION_ACCOUNT_META_STORE_KEY, deriveSubscriptionAccountMetaRecordKey(accountId), (hlc, origin, observed) => buildSubscriptionAccountMetaTombstoneData({ accountId, hlc, origin, deletedAt, observed })),
9530
+ });
9531
+ }
9231
9532
  // POOL-AWARE QUOTA THROTTLE wiring (docs/specs/POOL-AWARE-QUOTA-THROTTLE-SPEC.md):
9232
9533
  // give the global quota brake the SAME placeability predicate the placement layer
9233
9534
  // (selectAccount) uses, reading the LIVE SubscriptionPool. Effect: the brake never
@@ -16620,7 +16921,7 @@ export async function startServer(options) {
16620
16921
  carrier: _topicProfileCarrier,
16621
16922
  }
16622
16923
  : null;
16623
- 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, credentialRepointing, 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, threadLog, threadMessageRecorder, 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, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, 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, poolLink: _poolLink ?? undefined, poolPollCache: _poolPollCache ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, orphanedWorkSentinel, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, prHandLease: prHandLease ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx }); // Resolve the late-bound topic-operator getter (increment 2e): routing was
16924
+ 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, credentialRepointing, 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, threadLog, threadMessageRecorder, 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, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, 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, poolLink: _poolLink ?? undefined, poolPollCache: _poolPollCache ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, orphanedWorkSentinel, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, autonomousLivenessReconciler, prHandLease: prHandLease ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx }); // Resolve the late-bound topic-operator getter (increment 2e): routing was
16624
16925
  // wired before the server existed; from here on inbound binds use the
16625
16926
  // server's own store instance.
16626
16927
  _agentServerRef = server;