instar 1.3.714 → 1.3.716
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.
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +599 -4
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +35 -0
- package/dist/config/ConfigDefaults.js.map +1 -1
- package/dist/core/CoherenceJournal.d.ts +1 -1
- package/dist/core/CoherenceJournal.d.ts.map +1 -1
- package/dist/core/CoherenceJournal.js +9 -2
- package/dist/core/CoherenceJournal.js.map +1 -1
- package/dist/core/FencedLease.d.ts +47 -1
- package/dist/core/FencedLease.d.ts.map +1 -1
- package/dist/core/FencedLease.js +58 -1
- package/dist/core/FencedLease.js.map +1 -1
- package/dist/core/LeaseCoordinator.d.ts +25 -1
- package/dist/core/LeaseCoordinator.d.ts.map +1 -1
- package/dist/core/LeaseCoordinator.js +66 -0
- package/dist/core/LeaseCoordinator.js.map +1 -1
- package/dist/core/LeaseHandbackReconciler.d.ts +212 -0
- package/dist/core/LeaseHandbackReconciler.d.ts.map +1 -0
- package/dist/core/LeaseHandbackReconciler.js +416 -0
- package/dist/core/LeaseHandbackReconciler.js.map +1 -0
- package/dist/core/MeshRpc.d.ts +6 -1
- package/dist/core/MeshRpc.d.ts.map +1 -1
- package/dist/core/MeshRpc.js +9 -0
- package/dist/core/MeshRpc.js.map +1 -1
- package/dist/core/MultiMachineCoordinator.d.ts +20 -0
- package/dist/core/MultiMachineCoordinator.d.ts.map +1 -1
- package/dist/core/MultiMachineCoordinator.js +30 -0
- package/dist/core/MultiMachineCoordinator.js.map +1 -1
- package/dist/core/OwnershipReconciler.d.ts +42 -2
- package/dist/core/OwnershipReconciler.d.ts.map +1 -1
- package/dist/core/OwnershipReconciler.js +100 -2
- package/dist/core/OwnershipReconciler.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts +1 -0
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +31 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/StaleOwnerReleaseEngine.d.ts +290 -0
- package/dist/core/StaleOwnerReleaseEngine.d.ts.map +1 -0
- package/dist/core/StaleOwnerReleaseEngine.js +645 -0
- package/dist/core/StaleOwnerReleaseEngine.js.map +1 -0
- package/dist/core/TopicClaimAnnotationStore.d.ts +121 -0
- package/dist/core/TopicClaimAnnotationStore.d.ts.map +1 -0
- package/dist/core/TopicClaimAnnotationStore.js +234 -0
- package/dist/core/TopicClaimAnnotationStore.js.map +1 -0
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +11 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/handbackLatch.d.ts +28 -0
- package/dist/core/handbackLatch.d.ts.map +1 -0
- package/dist/core/handbackLatch.js +73 -0
- package/dist/core/handbackLatch.js.map +1 -0
- package/dist/core/ropeHealth.d.ts +26 -0
- package/dist/core/ropeHealth.d.ts.map +1 -0
- package/dist/core/ropeHealth.js +32 -0
- package/dist/core/ropeHealth.js.map +1 -0
- package/dist/core/types.d.ts +51 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/InputClassifier.d.ts.map +1 -1
- package/dist/monitoring/InputClassifier.js +6 -1
- package/dist/monitoring/InputClassifier.js.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.d.ts +5 -0
- package/dist/monitoring/StrandedTopicSentinel.d.ts.map +1 -1
- package/dist/monitoring/StrandedTopicSentinel.js +8 -0
- package/dist/monitoring/StrandedTopicSentinel.js.map +1 -1
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +45 -0
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/monitoring/strandedTopicDecision.d.ts +11 -0
- package/dist/monitoring/strandedTopicDecision.d.ts.map +1 -1
- package/dist/monitoring/strandedTopicDecision.js +12 -1
- package/dist/monitoring/strandedTopicDecision.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +2 -1
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +9 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +2 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +9 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +76 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +65 -65
- package/src/scaffold/templates.ts +2 -1
- package/upgrades/1.3.715.md +92 -0
- package/upgrades/1.3.716.md +32 -0
- package/upgrades/side-effects/input-classifier-unsure-contract.md +76 -0
- package/upgrades/side-effects/u4-stale-owner-release-lease-handback.md +87 -0
package/dist/commands/server.js
CHANGED
|
@@ -28,6 +28,7 @@ import { SingleInstanceLock, installReleaseHandlers } from '../core/SingleInstan
|
|
|
28
28
|
import { resolveDevAgentGate, resolveStateSyncStores } from '../core/devAgentGate.js';
|
|
29
29
|
import { shouldReleaseOnComplete, planClaimOnSpawn, ownershipNonce } from '../core/ownershipFollowsLiveWork.js';
|
|
30
30
|
import { PrHandLease } from '../core/PrHandLease.js';
|
|
31
|
+
import { claimSuspensionExcludesPin } from '../core/TopicClaimAnnotationStore.js';
|
|
31
32
|
import { parseProfileTrigger, platformMessageIdFrom } from '../core/topicProfileIngress.js';
|
|
32
33
|
import { slugifyChannelName } from '../messaging/slack/sanitize.js';
|
|
33
34
|
import { TopicProfileOrchestrator, resolvedToApplied, } from '../core/TopicProfileOrchestrator.js';
|
|
@@ -705,6 +706,45 @@ let _sessionRefresh = null;
|
|
|
705
706
|
// the `/pool/reconciler` readout (status + per-topic explain) can reach it. Null until the
|
|
706
707
|
// pool block constructs it (single-machine / dark → stays null → the route 503s).
|
|
707
708
|
let _ownershipReconciler = null;
|
|
709
|
+
// U4.2 stale-owner release — the evidence-upgraded Case C engine, hoisted so the
|
|
710
|
+
// GET /pool/stale-owner-release route + the reconciler dep can reach it. Null
|
|
711
|
+
// until the pool block constructs it (single-machine / dark → the route 503s).
|
|
712
|
+
let _staleOwnerEngine = null;
|
|
713
|
+
// U4.4 lease hand-back — the F4 reconciler, hoisted so the lease pull tick hook
|
|
714
|
+
// (constructed early) and the /pool surfaces (constructed late) can reach it.
|
|
715
|
+
let _leaseHandbackReconciler = null;
|
|
716
|
+
// U4.4 — the /pool/lease-handback route surface (status + the R-r2-5 operator
|
|
717
|
+
// latch levers), assembled where the reconciler is constructed.
|
|
718
|
+
let _leaseHandbackCtx = null;
|
|
719
|
+
// U4.2 evidence-5 mirror freshness — stamped whenever a journal-sync exchange
|
|
720
|
+
// with a peer SUCCEEDS (an empty delta is still a successful sync). Null until
|
|
721
|
+
// the first success; a mirror never synced inside the window classifies
|
|
722
|
+
// AMBIGUITY (fail closed) in the evidence bar.
|
|
723
|
+
let _journalSyncLastOkMs = null;
|
|
724
|
+
// U4.2 evidence seams, assigned in the lease-transport block (which owns the
|
|
725
|
+
// identity manager + the authenticated dial machinery) and read late-bound by
|
|
726
|
+
// the engine. Null = the mesh substrate is absent → the engine fails closed.
|
|
727
|
+
let _staleOwnerAdvertSet = null;
|
|
728
|
+
// U4.2 §2.4/§2.3 — the merged claim-suspension view (engine-gated: empty while the
|
|
729
|
+
// feature is dark). Assigned at reconciler construction; consulted BOTH by the
|
|
730
|
+
// reconciler's effectivePins() and by the SessionReaper closeout's pin-conflict
|
|
731
|
+
// veto (a SUSPENDED pin is not "the reconciler bringing the topic back", so it
|
|
732
|
+
// must not veto the returned owner's post-claim teardown).
|
|
733
|
+
let _sorClaimSuspensionsRead = null;
|
|
734
|
+
let _staleOwnerProbeEndpoint = null;
|
|
735
|
+
let _staleOwnerSelfProof = null;
|
|
736
|
+
let _hasDurableLeaseAuthority = null;
|
|
737
|
+
// Attention seam shared by U4.2 (ambiguity escalation / P19 give-ups) and U4.4
|
|
738
|
+
// (deferral-ceiling / episode-cap notices); assigned where the telegram adapter
|
|
739
|
+
// exists. Items are episode-keyed and deduped by the attention store.
|
|
740
|
+
let _meshAttentionRaise = null;
|
|
741
|
+
// U4.4 offer transport (assigned where the MeshRpcClient exists). Null = no
|
|
742
|
+
// mesh client yet → sendOffer reports 'timeout' and the holder keeps holding.
|
|
743
|
+
// U4.4 — used consent-token keys on the RECEIVING side (single-use; the token
|
|
744
|
+
// TTL is 60s so a bounded in-memory set suffices) + the delivery canary seam.
|
|
745
|
+
const _handbackSeenTokens = new Set();
|
|
746
|
+
let _handbackCanary = null;
|
|
747
|
+
let _handbackSendOffer = null;
|
|
708
748
|
// Subscription & Auth Standard P1.3 — quota-aware account-swap scheduler. Null
|
|
709
749
|
// until wired (requires SessionRefresh + the subscription pool).
|
|
710
750
|
let _quotaAwareScheduler = null;
|
|
@@ -3396,6 +3436,9 @@ export async function startServer(options) {
|
|
|
3396
3436
|
stateDir: config.stateDir,
|
|
3397
3437
|
multiMachine: config.multiMachine,
|
|
3398
3438
|
developmentAgent: config.developmentAgent,
|
|
3439
|
+
// U4.4 — the hand-back reconciler's observation rides the existing lease
|
|
3440
|
+
// pull tick (late-bound: the reconciler is constructed after boot wiring).
|
|
3441
|
+
onLeasePullTick: () => _leaseHandbackReconciler?.observe(),
|
|
3399
3442
|
});
|
|
3400
3443
|
const machineRole = coordinator.start();
|
|
3401
3444
|
if (coordinator.enabled) {
|
|
@@ -3613,6 +3656,32 @@ export async function startServer(options) {
|
|
|
3613
3656
|
// not range-validated; with none on, the foundation is inert.
|
|
3614
3657
|
const stateSync = assertStateSyncInvariants(config.multiMachine);
|
|
3615
3658
|
void stateSync; // foundation knobs are consumed by the store PRs (WS2.1+)
|
|
3659
|
+
// U4.2 (§2.3 TTL-ordering invariant, R-r2-3) — "expired implies self-fenced
|
|
3660
|
+
// by construction" holds ONLY when deathEvidenceMs > selfFenceTtlMs + one
|
|
3661
|
+
// reconciler tick + clock-skew slack. A violating combination is REJECTED at
|
|
3662
|
+
// startup (the reject-nonsensical-combinations pattern), never degraded
|
|
3663
|
+
// silently. U4.4 (§5 enable chokepoint) — dryRun:false with pollFollowsLease
|
|
3664
|
+
// still dry-run is REFUSED loudly (a lease/ingress split).
|
|
3665
|
+
{
|
|
3666
|
+
const { validateStaleOwnerReleaseInvariants, DEFAULT_STALE_OWNER_RELEASE_CONFIG } = await import('../core/StaleOwnerReleaseEngine.js');
|
|
3667
|
+
const sorCfg = config.multiMachine?.sessionPool?.staleOwnerRelease ?? {};
|
|
3668
|
+
const tickMs = Math.max(5000, config.multiMachine?.seamlessness?.ws13TickMs ?? 30000);
|
|
3669
|
+
const skewSlackMs = 2 * (config.multiMachine?.sessionPool?.maxExpectedNtpDriftMs ?? 250);
|
|
3670
|
+
const sorErr = validateStaleOwnerReleaseInvariants({
|
|
3671
|
+
deathEvidenceMs: sorCfg.deathEvidenceMs ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.deathEvidenceMs,
|
|
3672
|
+
selfFenceTtlMs: sorCfg.selfFenceTtlMs ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.selfFenceTtlMs,
|
|
3673
|
+
}, tickMs, skewSlackMs);
|
|
3674
|
+
if (sorErr)
|
|
3675
|
+
throw new Error(sorErr);
|
|
3676
|
+
const { validateHandbackEnableChokepoint } = await import('../core/LeaseHandbackReconciler.js');
|
|
3677
|
+
const hbCfg = config.multiMachine?.leaseSelfHeal?.preferredCaptainHandback ?? {};
|
|
3678
|
+
const pollLive = resolveDevAgentGate(config.multiMachine?.pollFollowsLease?.enabled, config) &&
|
|
3679
|
+
config.multiMachine?.pollFollowsLease?.dryRun === false;
|
|
3680
|
+
const hbErr = validateHandbackEnableChokepoint({ enabled: hbCfg.enabled === true, dryRun: hbCfg.dryRun !== false }, pollLive,
|
|
3681
|
+
/* hasPollerSplit — conservative: any instar install runs the lifeline poller split */ true);
|
|
3682
|
+
if (hbErr)
|
|
3683
|
+
throw new Error(hbErr);
|
|
3684
|
+
}
|
|
3616
3685
|
// The replicated-kind registry (Component 2). Ships EMPTY in this step — the
|
|
3617
3686
|
// first concrete store (WS2.1) registers its kind onto it. Constructed here so
|
|
3618
3687
|
// the substrate is wired and the per-store stateSyncReceive advert can be
|
|
@@ -3734,6 +3803,15 @@ export async function startServer(options) {
|
|
|
3734
3803
|
// the store-enable flag (ws13PinReplicate), so a single-machine / dark agent is a no-op.
|
|
3735
3804
|
const { TOPIC_PIN_KIND_REGISTRATION } = await import('../core/TopicPinReplicatedStore.js');
|
|
3736
3805
|
replicatedKindRegistry.register(TOPIC_PIN_KIND_REGISTRATION);
|
|
3806
|
+
// U4.2 (docs/specs/u4-2-stale-owner-release.md §2.4, R-r3-1) — register the
|
|
3807
|
+
// `topic-claim-annotation` kind (claim suspension + per-topic claim budget +
|
|
3808
|
+
// declined-demote pins; epoch-INDEPENDENT, generic-envelope-validated). A new
|
|
3809
|
+
// registered KIND is additive — pre-U4.2 peers never register it and simply
|
|
3810
|
+
// never sync it (no unknown-FIELD surface on any stream they consume).
|
|
3811
|
+
// Registration is INERT; emission stays gated behind the staleOwnerRelease
|
|
3812
|
+
// feature gate below.
|
|
3813
|
+
const { TOPIC_CLAIM_ANNOTATION_KIND_REGISTRATION } = await import('../core/TopicClaimAnnotationStore.js');
|
|
3814
|
+
replicatedKindRegistry.register(TOPIC_CLAIM_ANNOTATION_KIND_REGISTRATION);
|
|
3737
3815
|
// ── WS2 SEND-SIDE wiring (docs/specs/WS2-SEND-SIDE-EMISSION-SPEC.md). The
|
|
3738
3816
|
// substrate above ships the registry + receive/serve machinery + advert; THIS
|
|
3739
3817
|
// wires the SEND half that was deferred ("the journal-backed emitter is attached
|
|
@@ -3849,13 +3927,20 @@ export async function startServer(options) {
|
|
|
3849
3927
|
// rest of WS1.3). When OFF the entry is absent ⇒ the emitter's enabled-check fails ⇒ no pin
|
|
3850
3928
|
// record ever crosses (a dark/single-machine agent is a strict no-op).
|
|
3851
3929
|
const _pinReplicateEnabled = resolveDevAgentGate(config.multiMachine?.seamlessness?.ws13PinReplicate, config);
|
|
3930
|
+
// U4.2 — the `topicClaimAnnotations` store gates on the staleOwnerRelease
|
|
3931
|
+
// feature (dev-live-in-dryRun / fleet-dark; `enabled` omitted from defaults).
|
|
3932
|
+
// Emission additionally requires the annotation writes themselves (claim /
|
|
3933
|
+
// decline transitions), so a dark agent never emits the kind.
|
|
3934
|
+
const _staleOwnerReleaseResolved = resolveDevAgentGate(config.multiMachine?.sessionPool?.staleOwnerRelease?.enabled, config);
|
|
3852
3935
|
const _stateSyncStoresResolved = (() => {
|
|
3853
3936
|
let s = _stateSyncStoresBase ?? {};
|
|
3854
3937
|
if (_accountFollowMeEnabled)
|
|
3855
3938
|
s = { ...s, subscriptionAccountMeta: { enabled: true } };
|
|
3856
3939
|
if (_pinReplicateEnabled)
|
|
3857
3940
|
s = { ...s, topicPins: { enabled: true } };
|
|
3858
|
-
|
|
3941
|
+
if (_staleOwnerReleaseResolved)
|
|
3942
|
+
s = { ...s, topicClaimAnnotations: { enabled: true } };
|
|
3943
|
+
return _accountFollowMeEnabled || _pinReplicateEnabled || _staleOwnerReleaseResolved || _stateSyncStoresBase ? s : _stateSyncStoresBase;
|
|
3859
3944
|
})();
|
|
3860
3945
|
// WS2 send-side: the generic journal-backed record emitter (the concrete emitter
|
|
3861
3946
|
// the per-store managers' emit hooks call). Needs the journal sink, the HLC clock,
|
|
@@ -4389,6 +4474,215 @@ export async function startServer(options) {
|
|
|
4389
4474
|
});
|
|
4390
4475
|
coordinator.attachLeaseCoordinator(leaseCoordinator);
|
|
4391
4476
|
leaseCoordinatorRef = leaseCoordinator;
|
|
4477
|
+
// ── U4.2 evidence seams (docs/specs/u4-2-stale-owner-release.md §2.2) ──
|
|
4478
|
+
// Advert-set provenance (R-r2-5b): endpoints recorded ONLY by the
|
|
4479
|
+
// PeerEndpointRecorder out of the signed lease RPC (bound to the
|
|
4480
|
+
// cryptographically-verified sender), read back from the identity
|
|
4481
|
+
// registry's per-peer entry. The git registry's lastKnownUrl is NOT
|
|
4482
|
+
// acceptable disproof input and is deliberately not consulted here.
|
|
4483
|
+
_staleOwnerAdvertSet = (machineId) => {
|
|
4484
|
+
const eps = (idMgr.getMachineEndpoints(machineId) ?? []);
|
|
4485
|
+
// Freshness bound: the peer must still be a registered, non-revoked
|
|
4486
|
+
// machine with a durable heartbeat newer than the staleness ceiling
|
|
4487
|
+
// (an ancient advert set — the owner may have moved networks — is
|
|
4488
|
+
// ambiguity, never disproof).
|
|
4489
|
+
let fresh = false;
|
|
4490
|
+
try {
|
|
4491
|
+
const reg = idMgr.loadRegistry();
|
|
4492
|
+
const entry = (reg.machines ?? {})[machineId];
|
|
4493
|
+
const lastSeenMs = entry?.lastSeen ? Date.parse(entry.lastSeen) : NaN;
|
|
4494
|
+
fresh = !!entry && !entry.revokedAt && Number.isFinite(lastSeenMs) && Date.now() - lastSeenMs < 7 * 24 * 3_600_000;
|
|
4495
|
+
}
|
|
4496
|
+
catch {
|
|
4497
|
+
fresh = false; /* @silent-fallback-ok — an unreadable registry reads as not-fresh ⇒ the evidence bar classifies AMBIGUITY (fail closed), never disproof */
|
|
4498
|
+
}
|
|
4499
|
+
return { endpoints: eps.filter((e) => typeof e?.url === 'string' && typeof e?.kind === 'string'), fresh };
|
|
4500
|
+
};
|
|
4501
|
+
// Authenticated signed-handshake probe of ONE advertised transport: an
|
|
4502
|
+
// identity-verified /api/lease/pull round-trip (the same dial the lease
|
|
4503
|
+
// wire uses; verifyLeaseAckIdentity binds the responder).
|
|
4504
|
+
_staleOwnerProbeEndpoint = async (machineId, endpoint, _timeoutMs) => {
|
|
4505
|
+
if (!leaseTransport?.pullPeer)
|
|
4506
|
+
return false;
|
|
4507
|
+
try {
|
|
4508
|
+
const lease = await leaseTransport.pullPeer({
|
|
4509
|
+
machineId,
|
|
4510
|
+
url: endpoint.url,
|
|
4511
|
+
endpoints: [endpoint],
|
|
4512
|
+
publicKeyPem: idMgr.getSigningPublicKeyPem(machineId),
|
|
4513
|
+
meshAckCapable: !!idMgr.getSigningPublicKeyPem(machineId),
|
|
4514
|
+
});
|
|
4515
|
+
return lease !== null;
|
|
4516
|
+
}
|
|
4517
|
+
catch {
|
|
4518
|
+
return false; /* @silent-fallback-ok — an errored probe is unreachability EVIDENCE for this endpoint, consumed by a fail-closed evidence bar */
|
|
4519
|
+
}
|
|
4520
|
+
};
|
|
4521
|
+
// Claimant self-connectivity proof (evidence 4): an authenticated probe
|
|
4522
|
+
// of a THIRD peer; 2-machine case → verified reach of the durable lease
|
|
4523
|
+
// authority (git). A claimer with a broken NIC must never claim.
|
|
4524
|
+
_hasDurableLeaseAuthority = () => !!gitSyncRef;
|
|
4525
|
+
_staleOwnerSelfProof = async () => {
|
|
4526
|
+
try {
|
|
4527
|
+
const reg = idMgr.loadRegistry();
|
|
4528
|
+
const peers = Object.entries(reg.machines ?? {}).filter(([id, e]) => id !== selfMachineId && !e.revokedAt);
|
|
4529
|
+
if (peers.length >= 2 && leaseTransport?.pullPeer) {
|
|
4530
|
+
// Probe any OTHER peer (the engine excludes the suspect owner by
|
|
4531
|
+
// probing it separately; reaching ANY peer proves our egress).
|
|
4532
|
+
for (const [id, e] of peers) {
|
|
4533
|
+
const entry = e;
|
|
4534
|
+
const url = entry.lastKnownUrl ?? entry.endpoints?.[0]?.url;
|
|
4535
|
+
if (!url)
|
|
4536
|
+
continue;
|
|
4537
|
+
const lease = await leaseTransport.pullPeer({
|
|
4538
|
+
machineId: id,
|
|
4539
|
+
url,
|
|
4540
|
+
endpoints: entry.endpoints,
|
|
4541
|
+
publicKeyPem: idMgr.getSigningPublicKeyPem(id),
|
|
4542
|
+
meshAckCapable: (entry.endpoints?.length ?? 0) > 0 && !!idMgr.getSigningPublicKeyPem(id),
|
|
4543
|
+
});
|
|
4544
|
+
if (lease !== null)
|
|
4545
|
+
return true;
|
|
4546
|
+
}
|
|
4547
|
+
return false;
|
|
4548
|
+
}
|
|
4549
|
+
// 2-machine mesh: verified reach of the durable lease authority.
|
|
4550
|
+
if (gitSyncRef) {
|
|
4551
|
+
const read = leaseStore.read();
|
|
4552
|
+
return read !== null && read !== undefined;
|
|
4553
|
+
}
|
|
4554
|
+
return false; // 2-machine git-less: no self-proof source (claim path disabled upstream)
|
|
4555
|
+
}
|
|
4556
|
+
catch {
|
|
4557
|
+
return false; /* @silent-fallback-ok — a failed self-proof means WE may be the partitioned one; the evidence bar refuses the claim (fail closed) */
|
|
4558
|
+
}
|
|
4559
|
+
};
|
|
4560
|
+
// ── U4.4 lease hand-back reconciler (docs/specs/u4-4-lease-handback.md) ──
|
|
4561
|
+
// Constructed here (the lease block owns every authority input); its
|
|
4562
|
+
// observation rides the coordinator's lease pull tick via the
|
|
4563
|
+
// onLeasePullTick hook wired at coordinator construction. Ships
|
|
4564
|
+
// HARD-DARK (enabled:false + dryRun:true — DARK_GATE_EXCLUSIONS).
|
|
4565
|
+
{
|
|
4566
|
+
const { LeaseHandbackReconciler, DEFAULT_LEASE_HANDBACK_CONFIG, HANDBACK_CONSENT_TTL_MS } = await import('../core/LeaseHandbackReconciler.js');
|
|
4567
|
+
void HANDBACK_CONSENT_TTL_MS;
|
|
4568
|
+
const { readHandbackLatchUntilMs } = await import('../core/handbackLatch.js');
|
|
4569
|
+
const { ropeReachableOnAnyRope } = await import('../core/ropeHealth.js');
|
|
4570
|
+
const { getFeatureMetricsRecorder } = await import('../core/CircuitBreakingIntelligenceProvider.js');
|
|
4571
|
+
const hbCfgRead = () => {
|
|
4572
|
+
const c = config.multiMachine?.leaseSelfHeal?.preferredCaptainHandback ?? {};
|
|
4573
|
+
return {
|
|
4574
|
+
enabled: c.enabled === true,
|
|
4575
|
+
dryRun: c.dryRun !== false,
|
|
4576
|
+
healthWindowMs: c.healthWindowMs ?? DEFAULT_LEASE_HANDBACK_CONFIG.healthWindowMs,
|
|
4577
|
+
deferralCeilingMs: c.deferralCeilingMs ?? DEFAULT_LEASE_HANDBACK_CONFIG.deferralCeilingMs,
|
|
4578
|
+
operatorLatchMs: c.operatorLatchMs ?? DEFAULT_LEASE_HANDBACK_CONFIG.operatorLatchMs,
|
|
4579
|
+
maxPerWindow: c.maxPerWindow ?? DEFAULT_LEASE_HANDBACK_CONFIG.maxPerWindow,
|
|
4580
|
+
windowMs: c.windowMs ?? DEFAULT_LEASE_HANDBACK_CONFIG.windowMs,
|
|
4581
|
+
};
|
|
4582
|
+
};
|
|
4583
|
+
_leaseHandbackReconciler = new LeaseHandbackReconciler({
|
|
4584
|
+
config: hbCfgRead,
|
|
4585
|
+
selfMachineId: () => selfMachineId,
|
|
4586
|
+
// F4's ONE authority — the SAME config field shouldDeferToPreferred
|
|
4587
|
+
// reads (multiMachine.leaseSelfHeal.preferredAwakeMachineId).
|
|
4588
|
+
preferredAwakeMachineId: () => config.multiMachine?.leaseSelfHeal?.preferredAwakeMachineId ?? null,
|
|
4589
|
+
holdsLease: () => coordinator.holdsLease(),
|
|
4590
|
+
currentEpoch: () => leaseCoordinator.currentEpoch(),
|
|
4591
|
+
preferredHealth: (machineId) => {
|
|
4592
|
+
const cap = (() => {
|
|
4593
|
+
try {
|
|
4594
|
+
return machinePoolRegistry?.getCapacities().find((c) => c.machineId === machineId);
|
|
4595
|
+
}
|
|
4596
|
+
catch {
|
|
4597
|
+
return undefined; /* @silent-fallback-ok — no pool view reads as not-healthy → defer (the safe direction) */
|
|
4598
|
+
}
|
|
4599
|
+
})();
|
|
4600
|
+
return {
|
|
4601
|
+
heartbeatFresh: cap?.online === true,
|
|
4602
|
+
// U4.3 rope-health snapshot seam (R-r2-7): absent record/provider
|
|
4603
|
+
// reads NOT-healthy → defer. U4.3 registers the real provider.
|
|
4604
|
+
ropeReachable: ropeReachableOnAnyRope(machineId),
|
|
4605
|
+
leaseEligible: !!cap,
|
|
4606
|
+
quotaOk: cap?.quotaState?.blocked !== true,
|
|
4607
|
+
};
|
|
4608
|
+
},
|
|
4609
|
+
cleanBoundary: () => {
|
|
4610
|
+
const counts = (() => {
|
|
4611
|
+
try {
|
|
4612
|
+
return _inboundQueue?.snapshot().counts;
|
|
4613
|
+
}
|
|
4614
|
+
catch {
|
|
4615
|
+
return undefined; /* @silent-fallback-ok — an unreadable queue reads as quiet=false via queuedInbound 1 below */
|
|
4616
|
+
}
|
|
4617
|
+
})();
|
|
4618
|
+
const queuedInbound = counts ? (counts.queued ?? 0) + (counts.claimed ?? 0) : 0;
|
|
4619
|
+
let msSinceLastIngress = null;
|
|
4620
|
+
try {
|
|
4621
|
+
const st = fs.statSync(path.join(config.stateDir, 'state', 'serve-progress.json'));
|
|
4622
|
+
msSinceLastIngress = Date.now() - st.mtimeMs;
|
|
4623
|
+
}
|
|
4624
|
+
catch {
|
|
4625
|
+
msSinceLastIngress = null; /* @silent-fallback-ok — no serve-progress signal = no recent-ingress evidence; the other two boundary signals still gate */
|
|
4626
|
+
}
|
|
4627
|
+
return {
|
|
4628
|
+
inFlightForwards: (currentInboundByTopic?.size ?? 0) > 0,
|
|
4629
|
+
queuedInbound,
|
|
4630
|
+
msSinceLastIngress,
|
|
4631
|
+
};
|
|
4632
|
+
},
|
|
4633
|
+
kickInboundDrain: () => {
|
|
4634
|
+
// One event-triggered drain pass (the existing durable inbound-queue
|
|
4635
|
+
// semantics). The step-down stays deferred until counts read 0.
|
|
4636
|
+
try {
|
|
4637
|
+
void _inboundQueue?.onMachineOnline();
|
|
4638
|
+
}
|
|
4639
|
+
catch { /* @silent-fallback-ok — drain kick is best-effort; the boundary re-checks next tick */ }
|
|
4640
|
+
},
|
|
4641
|
+
splitBrainActive: () => {
|
|
4642
|
+
try {
|
|
4643
|
+
return coordinator.getSyncStatus().splitBrainState !== 'clear';
|
|
4644
|
+
}
|
|
4645
|
+
catch {
|
|
4646
|
+
return true; /* @silent-fallback-ok — an unreadable sync status reads as split-brain-active → suppress (the safe direction) */
|
|
4647
|
+
}
|
|
4648
|
+
},
|
|
4649
|
+
churnLatched: () => coordinator.churnBreakerLatched(),
|
|
4650
|
+
// Hand-backs COUNT as flips: the step-down role transition feeds the
|
|
4651
|
+
// breaker via the coordinator's reconcileRoleToLease recordFlip path
|
|
4652
|
+
// (a second explicit record here would double-count one hand-back).
|
|
4653
|
+
recordChurnFlip: () => { },
|
|
4654
|
+
operatorLatchUntilMs: () => readHandbackLatchUntilMs(config.stateDir),
|
|
4655
|
+
mintConsentToken: (target, ttlMs) => leaseCoordinator.mintHandbackConsent(target, ttlMs),
|
|
4656
|
+
sendOffer: async (target, offer) => {
|
|
4657
|
+
if (!_handbackSendOffer)
|
|
4658
|
+
return 'timeout';
|
|
4659
|
+
return _handbackSendOffer(target, offer);
|
|
4660
|
+
},
|
|
4661
|
+
metric: (event) => {
|
|
4662
|
+
try {
|
|
4663
|
+
getFeatureMetricsRecorder()?.record({ feature: 'lease-handback', kind: 'event', outcome: event === 'failure' ? 'error' : 'fired', verdictId: event });
|
|
4664
|
+
}
|
|
4665
|
+
catch { /* metrics never gate */ }
|
|
4666
|
+
},
|
|
4667
|
+
notify: (key, title, body) => {
|
|
4668
|
+
try {
|
|
4669
|
+
_meshAttentionRaise?.({ id: key, title, body, priority: 'medium', sourceContext: 'lease-handback' });
|
|
4670
|
+
}
|
|
4671
|
+
catch { /* notice is best-effort */ }
|
|
4672
|
+
},
|
|
4673
|
+
logger: (m) => console.log(pc.dim(` ${m}`)),
|
|
4674
|
+
});
|
|
4675
|
+
// The /pool/lease-handback route surface (status + the R-r2-5 operator
|
|
4676
|
+
// latch levers). latchWrite is the flip-action's POST step — the
|
|
4677
|
+
// configured operatorLatchMs is the TTL (default 24h).
|
|
4678
|
+
const { writeHandbackLatch, clearHandbackLatch, readHandbackLatchRecord } = await import('../core/handbackLatch.js');
|
|
4679
|
+
_leaseHandbackCtx = {
|
|
4680
|
+
status: () => _leaseHandbackReconciler.status(),
|
|
4681
|
+
latchWrite: (reason) => writeHandbackLatch(config.stateDir, hbCfgRead().operatorLatchMs, reason),
|
|
4682
|
+
latchClear: () => clearHandbackLatch(config.stateDir),
|
|
4683
|
+
latchRecord: () => readHandbackLatchRecord(config.stateDir),
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4392
4686
|
// G3 — lease-gated spawn: wire the "do I hold the lease?" accessor so the
|
|
4393
4687
|
// spawn gate can fire. Setting this non-null also flips the gate out of its
|
|
4394
4688
|
// single-machine no-op (it now consults the real lease). The flag accessor
|
|
@@ -15068,11 +15362,24 @@ export async function startServer(options) {
|
|
|
15068
15362
|
// WS1.3: pin-conflict do-not-act — a pin naming THIS machine while the
|
|
15069
15363
|
// owner is elsewhere means the reconciler is bringing the topic back;
|
|
15070
15364
|
// the closeout holds instead of attacking the session the pin wants here.
|
|
15365
|
+
// U4.2 §2.3 exception: a pin SUSPENDED by a live stale-owner claim
|
|
15366
|
+
// annotation is NOT being brought back (effectivePins excludes it), so
|
|
15367
|
+
// it must not veto the returned owner's teardown — the same comparison
|
|
15368
|
+
// authority the reconciler uses (claimSuspensionExcludesPin). Feature
|
|
15369
|
+
// dark ⇒ the suspension view is empty ⇒ byte-identical veto behavior.
|
|
15071
15370
|
topicPinnedHere: (topicId) => {
|
|
15072
15371
|
try {
|
|
15073
15372
|
const self = _meshSelfId;
|
|
15074
15373
|
const pin = _topicPinStore?.get(String(topicId));
|
|
15075
|
-
|
|
15374
|
+
if (!self || !pin || !pin.pinned || pin.preferredMachine !== self)
|
|
15375
|
+
return false;
|
|
15376
|
+
const suspension = _sorClaimSuspensionsRead?.().get(Number(topicId));
|
|
15377
|
+
if (suspension) {
|
|
15378
|
+
const pinHlc = pin.hlc ?? { physical: Date.parse(pin.updatedAt) || 0, logical: 0, node: self };
|
|
15379
|
+
if (claimSuspensionExcludesPin(pinHlc, suspension))
|
|
15380
|
+
return false;
|
|
15381
|
+
}
|
|
15382
|
+
return true;
|
|
15076
15383
|
}
|
|
15077
15384
|
catch {
|
|
15078
15385
|
return false; /* @silent-fallback-ok — no pin signal → hold not applied, closeout behaves as before */
|
|
@@ -16253,6 +16560,7 @@ export async function startServer(options) {
|
|
|
16253
16560
|
const { mergeUnionToPins, compareHlc, TOPIC_PIN_RECORD_KIND } = await import('../core/TopicPinReplicatedStore.js');
|
|
16254
16561
|
const { CoherenceJournalReader: PinAdvReader } = await import('../core/CoherenceJournalReader.js');
|
|
16255
16562
|
const pinAdvisoryReader = new PinAdvReader({ stateDir: config.stateDir });
|
|
16563
|
+
const { mergeUnionToClaimAnnotations, TOPIC_CLAIM_ANNOTATION_KIND, TOPIC_CLAIM_ANNOTATION_STORE_KEY, buildClaimAnnotationPut, deriveClaimAnnotationRecordKey } = await import('../core/TopicClaimAnnotationStore.js');
|
|
16256
16564
|
const reconciler = new OwnershipReconciler({
|
|
16257
16565
|
// DEV-AGENT DARK GATE (operator directive 2026-06-13, topic 13481):
|
|
16258
16566
|
// read ws13Reconcile through resolveDevAgentGate so the reconcile loop
|
|
@@ -16286,16 +16594,37 @@ export async function startServer(options) {
|
|
|
16286
16594
|
ownership: ownReg,
|
|
16287
16595
|
machines: () => {
|
|
16288
16596
|
try {
|
|
16597
|
+
// U4.2 R-r2-5a (named prerequisite fix): Case C's staleness feed is the
|
|
16598
|
+
// ROUTER/OBSERVER-stamped arrival time (routerReceivedAt), NEVER the
|
|
16599
|
+
// machine's self-reported wall clock — MachinePoolRegistry's own §L2
|
|
16600
|
+
// header forbids the self-reported input ("a fast-clocked machine must
|
|
16601
|
+
// not appear fresher than it is").
|
|
16289
16602
|
return (machinePoolRegistry?.getCapacities() ?? []).map((c) => ({
|
|
16290
16603
|
machineId: c.machineId,
|
|
16291
16604
|
online: !!c.online,
|
|
16292
|
-
lastSeenMs: c.
|
|
16605
|
+
lastSeenMs: c.routerReceivedAt ? Date.parse(c.routerReceivedAt) || 0 : 0,
|
|
16293
16606
|
}));
|
|
16294
16607
|
}
|
|
16295
16608
|
catch {
|
|
16296
16609
|
return []; /* @silent-fallback-ok — no pool view → module's single-machine strict no-op */
|
|
16297
16610
|
}
|
|
16298
16611
|
},
|
|
16612
|
+
staleOwnerEngine: () => _staleOwnerEngine,
|
|
16613
|
+
claimSuspensions: (_sorClaimSuspensionsRead = () => {
|
|
16614
|
+
try {
|
|
16615
|
+
if (!_staleOwnerEngine?.isActive())
|
|
16616
|
+
return new Map();
|
|
16617
|
+
const res = pinAdvisoryReader.query({ kind: TOPIC_CLAIM_ANNOTATION_KIND, limit: 2000 });
|
|
16618
|
+
const merged = mergeUnionToClaimAnnotations(res.entries.map((e) => ({ data: e.data, origin: typeof e.data.origin === 'string' ? e.data.origin : '' })));
|
|
16619
|
+
const out = new Map();
|
|
16620
|
+
for (const [topic, a] of merged)
|
|
16621
|
+
out.set(topic, { suspended: a.suspended, hlc: a.hlc });
|
|
16622
|
+
return out;
|
|
16623
|
+
}
|
|
16624
|
+
catch {
|
|
16625
|
+
return new Map(); /* @silent-fallback-ok — an unreadable annotation view reads as no suspensions this tick; the next tick retries */
|
|
16626
|
+
}
|
|
16627
|
+
}),
|
|
16299
16628
|
isTopicBusy: (sessionKey) => {
|
|
16300
16629
|
try {
|
|
16301
16630
|
// Conservative safe-point signal: an inbound for this topic is
|
|
@@ -16334,6 +16663,143 @@ export async function startServer(options) {
|
|
|
16334
16663
|
logger: (m) => console.log(pc.dim(` ${m}`)),
|
|
16335
16664
|
});
|
|
16336
16665
|
_ownershipReconciler = reconciler; // hoist for the /pool/reconciler readout
|
|
16666
|
+
// ── U4.2 stale-owner release engine (docs/specs/u4-2-stale-owner-release.md) ──
|
|
16667
|
+
// Case C's evidence upgrade, invoked FROM reconciler.tick() (one actor;
|
|
16668
|
+
// claims funnel through reconciler.actStaleOwnerForceClaim). Dev-gate:
|
|
16669
|
+
// dev-live-in-dryRun / dark fleet; subordinate to sessionPool live AND
|
|
16670
|
+
// ≥2 machines (the engine's own gates).
|
|
16671
|
+
{
|
|
16672
|
+
const { StaleOwnerReleaseEngine, DEFAULT_STALE_OWNER_RELEASE_CONFIG } = await import('../core/StaleOwnerReleaseEngine.js');
|
|
16673
|
+
const { MachineHeartbeat: SorHeartbeatReader } = await import('../core/MachineHeartbeat.js');
|
|
16674
|
+
const sorHeartbeatReader = new SorHeartbeatReader({ stateDir: config.stateDir, machineId: 'stale-owner-release-reader' });
|
|
16675
|
+
const sorCfgRead = () => {
|
|
16676
|
+
const c = config.multiMachine?.sessionPool?.staleOwnerRelease ?? {};
|
|
16677
|
+
const poolLive = config.multiMachine?.sessionPool?.enabled === true &&
|
|
16678
|
+
(config.multiMachine?.sessionPool?.stage ?? 'dark') !== 'dark';
|
|
16679
|
+
return {
|
|
16680
|
+
enabled: resolveDevAgentGate(c.enabled, config) && poolLive,
|
|
16681
|
+
dryRun: c.dryRun !== false,
|
|
16682
|
+
deathEvidenceMs: c.deathEvidenceMs ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.deathEvidenceMs,
|
|
16683
|
+
probeTimeoutMs: c.probeTimeoutMs ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.probeTimeoutMs,
|
|
16684
|
+
ambiguityCeilingMultiple: c.ambiguityCeilingMultiple ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.ambiguityCeilingMultiple,
|
|
16685
|
+
maxClaimsPerTick: c.maxClaimsPerTick ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.maxClaimsPerTick,
|
|
16686
|
+
bootstrapNonObservationMultiple: c.bootstrapNonObservationMultiple ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.bootstrapNonObservationMultiple,
|
|
16687
|
+
selfFenceTtlMs: c.selfFenceTtlMs ?? DEFAULT_STALE_OWNER_RELEASE_CONFIG.selfFenceTtlMs,
|
|
16688
|
+
};
|
|
16689
|
+
};
|
|
16690
|
+
const sorMachines = () => {
|
|
16691
|
+
try {
|
|
16692
|
+
return (machinePoolRegistry?.getCapacities() ?? []).map((c) => ({
|
|
16693
|
+
machineId: c.machineId,
|
|
16694
|
+
online: !!c.online,
|
|
16695
|
+
// R-r2-5a: OBSERVER-stamped arrival time, never self-reported.
|
|
16696
|
+
observerLastSeenMs: c.routerReceivedAt ? Date.parse(c.routerReceivedAt) || 0 : 0,
|
|
16697
|
+
}));
|
|
16698
|
+
}
|
|
16699
|
+
catch {
|
|
16700
|
+
return []; /* @silent-fallback-ok — no pool view → the engine's single-machine strict no-op */
|
|
16701
|
+
}
|
|
16702
|
+
};
|
|
16703
|
+
const sorReadAnnotations = () => {
|
|
16704
|
+
const res = pinAdvisoryReader.query({ kind: TOPIC_CLAIM_ANNOTATION_KIND, limit: 2000 });
|
|
16705
|
+
return mergeUnionToClaimAnnotations(res.entries.map((e) => ({ data: e.data, origin: typeof e.data.origin === 'string' ? e.data.origin : '' })));
|
|
16706
|
+
};
|
|
16707
|
+
const sorTracePath = path.join(config.stateDir, '..', 'logs', 'stale-owner-release.jsonl');
|
|
16708
|
+
_staleOwnerEngine = new StaleOwnerReleaseEngine({
|
|
16709
|
+
enabled: () => sorCfgRead().enabled,
|
|
16710
|
+
dryRun: () => sorCfgRead().dryRun,
|
|
16711
|
+
config: sorCfgRead,
|
|
16712
|
+
selfMachineId: () => _meshSelfId,
|
|
16713
|
+
machines: sorMachines,
|
|
16714
|
+
holdsLease: () => {
|
|
16715
|
+
try {
|
|
16716
|
+
return coordinator.holdsLease();
|
|
16717
|
+
}
|
|
16718
|
+
catch {
|
|
16719
|
+
return false; /* @silent-fallback-ok — an unreadable lease reads as not-holder → the claim arbiter refuses (fail closed) */
|
|
16720
|
+
}
|
|
16721
|
+
},
|
|
16722
|
+
listOwnershipRecords: () => {
|
|
16723
|
+
try {
|
|
16724
|
+
return ownReg.all();
|
|
16725
|
+
}
|
|
16726
|
+
catch {
|
|
16727
|
+
return []; /* @silent-fallback-ok — no records → nothing to evaluate this tick */
|
|
16728
|
+
}
|
|
16729
|
+
},
|
|
16730
|
+
durableLastKnownHeartbeatMs: (machineId) => {
|
|
16731
|
+
try {
|
|
16732
|
+
const rec = sorHeartbeatReader.read(machineId);
|
|
16733
|
+
const t = rec ? Date.parse(rec.lastHeartbeatAt) : NaN;
|
|
16734
|
+
return Number.isFinite(t) ? t : null;
|
|
16735
|
+
}
|
|
16736
|
+
catch {
|
|
16737
|
+
return null; /* @silent-fallback-ok — no durable heartbeat = null; the bootstrap rule treats it as its tie-breaker's long-dead arm */
|
|
16738
|
+
}
|
|
16739
|
+
},
|
|
16740
|
+
advertSet: (machineId) => (_staleOwnerAdvertSet ? _staleOwnerAdvertSet(machineId) : { endpoints: [], fresh: false }),
|
|
16741
|
+
probeEndpoint: (machineId, endpoint, timeoutMs) => _staleOwnerProbeEndpoint ? _staleOwnerProbeEndpoint(machineId, endpoint, timeoutMs) : Promise.resolve(false),
|
|
16742
|
+
selfConnectivityProof: () => (_staleOwnerSelfProof ? _staleOwnerSelfProof() : Promise.resolve(false)),
|
|
16743
|
+
hasDurableLeaseAuthority: () => (_hasDurableLeaseAuthority ? _hasDurableLeaseAuthority() : false),
|
|
16744
|
+
evidenceMirror: () => ({
|
|
16745
|
+
lastSyncOkMs: _journalSyncLastOkMs,
|
|
16746
|
+
lastOwnerSideEffectMs: (machineId) => {
|
|
16747
|
+
try {
|
|
16748
|
+
let newest = null;
|
|
16749
|
+
for (const kind of ['topic-placement', 'session-lifecycle']) {
|
|
16750
|
+
const res = pinAdvisoryReader.query({ kind, machine: machineId, limit: 1 });
|
|
16751
|
+
const st = res.streams[machineId];
|
|
16752
|
+
const t = st?.lastTs ? Date.parse(st.lastTs) : NaN;
|
|
16753
|
+
if (Number.isFinite(t))
|
|
16754
|
+
newest = newest === null ? t : Math.max(newest, t);
|
|
16755
|
+
}
|
|
16756
|
+
return newest;
|
|
16757
|
+
}
|
|
16758
|
+
catch {
|
|
16759
|
+
return null; /* @silent-fallback-ok — an unreadable mirror yields null; combined with the sync-freshness gate this stays fail-closed */
|
|
16760
|
+
}
|
|
16761
|
+
},
|
|
16762
|
+
}),
|
|
16763
|
+
claimAnnotations: () => {
|
|
16764
|
+
try {
|
|
16765
|
+
return sorReadAnnotations();
|
|
16766
|
+
}
|
|
16767
|
+
catch {
|
|
16768
|
+
return new Map(); /* @silent-fallback-ok — an unreadable annotation view reads as empty budgets; claims still capped per tick */
|
|
16769
|
+
}
|
|
16770
|
+
},
|
|
16771
|
+
actForceClaim: (sessionKey, episodeId) => reconciler.actStaleOwnerForceClaim(sessionKey, episodeId),
|
|
16772
|
+
emitClaimAnnotation: (input) => {
|
|
16773
|
+
const recordKey = deriveClaimAnnotationRecordKey(input.topic, input.episodeId);
|
|
16774
|
+
if (!recordKey || !replicatedRecordEmitter)
|
|
16775
|
+
return;
|
|
16776
|
+
replicatedRecordEmitter.emit(TOPIC_CLAIM_ANNOTATION_STORE_KEY, recordKey, buildClaimAnnotationPut(input));
|
|
16777
|
+
},
|
|
16778
|
+
pullWorkingSet: (topic) => {
|
|
16779
|
+
try {
|
|
16780
|
+
workingSetPullCoordinator?.onTopicAccepted(topic);
|
|
16781
|
+
}
|
|
16782
|
+
catch { /* @silent-fallback-ok — the carrier queues durably; a failed kick is retried by its own sweep */ }
|
|
16783
|
+
},
|
|
16784
|
+
onClaimed: (topic, episodeId, prevOwner) => {
|
|
16785
|
+
console.log(pc.yellow(` [StaleOwnerRelease] claimed topic ${topic} from ${prevOwner} (episode ${episodeId}) — resume rides the paced queue`));
|
|
16786
|
+
},
|
|
16787
|
+
trace: (entry) => {
|
|
16788
|
+
try {
|
|
16789
|
+
fs.mkdirSync(path.dirname(sorTracePath), { recursive: true });
|
|
16790
|
+
fs.appendFileSync(sorTracePath, JSON.stringify(entry) + '\n');
|
|
16791
|
+
}
|
|
16792
|
+
catch { /* trace is observability — never gates a verdict */ }
|
|
16793
|
+
},
|
|
16794
|
+
raiseAttention: (item) => {
|
|
16795
|
+
try {
|
|
16796
|
+
_meshAttentionRaise?.(item);
|
|
16797
|
+
}
|
|
16798
|
+
catch { /* attention raise is best-effort; the trace already recorded the escalation */ }
|
|
16799
|
+
},
|
|
16800
|
+
logger: (m) => console.log(pc.dim(` ${m}`)),
|
|
16801
|
+
});
|
|
16802
|
+
}
|
|
16337
16803
|
const tickMs = Math.max(5000, ws13Cfg().ws13TickMs ?? 30000);
|
|
16338
16804
|
const ws13Timer = setInterval(() => {
|
|
16339
16805
|
try {
|
|
@@ -17249,6 +17715,72 @@ export async function startServer(options) {
|
|
|
17249
17715
|
...outcome,
|
|
17250
17716
|
};
|
|
17251
17717
|
},
|
|
17718
|
+
// U4.4 — handback-offer (PREFERRED-CAPTAIN side). RBAC already proved
|
|
17719
|
+
// the SENDER is the current lease holder; the LOAD-BEARING authority is
|
|
17720
|
+
// the holder-signed consent token presented at acquire time (the
|
|
17721
|
+
// handbackOpts branch — fail-closed on expiry/replay/reuse). Typed
|
|
17722
|
+
// declines; on 'accept' the claim + delivery-canary run async
|
|
17723
|
+
// (claim-before-release: the holder keeps holding until the higher
|
|
17724
|
+
// epoch lands; a silent claim changes nothing).
|
|
17725
|
+
'handback-offer': async (cmd, sender) => {
|
|
17726
|
+
const c = cmd;
|
|
17727
|
+
const { decideHandbackOffer } = await import('../core/LeaseHandbackReconciler.js');
|
|
17728
|
+
const { getFeatureMetricsRecorder: hbMetrics } = await import('../core/CircuitBreakingIntelligenceProvider.js');
|
|
17729
|
+
const hb = config.multiMachine?.leaseSelfHeal?.preferredCaptainHandback ?? {};
|
|
17730
|
+
const token = c.consentToken;
|
|
17731
|
+
const tokenKey = `${token?.holder ?? ''}:${token?.nonce ?? ''}`;
|
|
17732
|
+
const decision = decideHandbackOffer({
|
|
17733
|
+
// Receiving-side authority gate: accepting moves REAL serving
|
|
17734
|
+
// authority, so dry-run also declines (the graduated ladder).
|
|
17735
|
+
enabled: hb.enabled === true && hb.dryRun === false,
|
|
17736
|
+
selfMachineId: meshSelfId,
|
|
17737
|
+
preferredAwakeMachineId: config.multiMachine?.leaseSelfHeal?.preferredAwakeMachineId ?? null,
|
|
17738
|
+
churnLatched: coordinator?.churnBreakerLatched() ?? false,
|
|
17739
|
+
quotaBlocked: machinePoolRegistry?.getCapacity(meshSelfId)?.quotaState?.blocked === true,
|
|
17740
|
+
tokenAlreadyUsed: _handbackSeenTokens.has(tokenKey),
|
|
17741
|
+
});
|
|
17742
|
+
if (decision === 'accept') {
|
|
17743
|
+
_handbackSeenTokens.add(tokenKey);
|
|
17744
|
+
if (_handbackSeenTokens.size > 512)
|
|
17745
|
+
_handbackSeenTokens.clear(); // bounded; token TTL is 60s
|
|
17746
|
+
void (async () => {
|
|
17747
|
+
try {
|
|
17748
|
+
const res = await coordinator.acquireLeaseOnHandbackConsent(token);
|
|
17749
|
+
if (!res.ok) {
|
|
17750
|
+
console.log(pc.yellow(` [LeaseHandback] consent claim did not land (${res.reason}) — old holder keeps holding`));
|
|
17751
|
+
return;
|
|
17752
|
+
}
|
|
17753
|
+
// Post-hand-back verification (Runtime End-to-End Proof): one
|
|
17754
|
+
// delivery-canary round-trip through the REAL signed mesh RPC
|
|
17755
|
+
// back to the OLD holder + a live lease check on this side.
|
|
17756
|
+
let canaryOk = false;
|
|
17757
|
+
try {
|
|
17758
|
+
canaryOk = (await _handbackCanary?.(sender)) === true;
|
|
17759
|
+
}
|
|
17760
|
+
catch {
|
|
17761
|
+
canaryOk = false; /* @silent-fallback-ok — a canary fault IS a canary failure; escalated loudly below, never silent */
|
|
17762
|
+
}
|
|
17763
|
+
try {
|
|
17764
|
+
hbMetrics()?.record({ feature: 'lease-handback', kind: 'event', outcome: canaryOk ? 'fired' : 'error', verdictId: canaryOk ? 'canary-verify-ok' : 'canary-verify-fail' });
|
|
17765
|
+
}
|
|
17766
|
+
catch { /* metrics never gate */ }
|
|
17767
|
+
if (!canaryOk) {
|
|
17768
|
+
_meshAttentionRaise?.({
|
|
17769
|
+
id: `lease-handback-canary:${Date.now()}`,
|
|
17770
|
+
title: 'Lease hand-back completed but the delivery canary FAILED',
|
|
17771
|
+
body: `This machine claimed the serving lease back from ${sender} but could not verify an end-to-end mesh round-trip afterward. Ingress may be degraded — check /pool and the mesh ropes.`,
|
|
17772
|
+
priority: 'high',
|
|
17773
|
+
sourceContext: 'lease-handback',
|
|
17774
|
+
});
|
|
17775
|
+
}
|
|
17776
|
+
}
|
|
17777
|
+
catch (err) {
|
|
17778
|
+
console.log(pc.yellow(` [LeaseHandback] consent claim error: ${err instanceof Error ? err.message : String(err)}`));
|
|
17779
|
+
}
|
|
17780
|
+
})();
|
|
17781
|
+
}
|
|
17782
|
+
return { response: decision };
|
|
17783
|
+
},
|
|
17252
17784
|
'secret-share': (cmd, sender) => _secretShareHandler
|
|
17253
17785
|
? _secretShareHandler.handle(cmd, sender)
|
|
17254
17786
|
: { ok: false, reason: 'secret-sync disabled' },
|
|
@@ -17352,6 +17884,45 @@ export async function startServer(options) {
|
|
|
17352
17884
|
});
|
|
17353
17885
|
const peerUrl = (machineId) => meshIdMgr.getActiveMachines().find((m) => m.machineId === machineId)?.entry.lastKnownUrl ?? null;
|
|
17354
17886
|
_meshSelfId = meshSelfId;
|
|
17887
|
+
// U4.4 — the offer transport (HOLDER side) + the post-hand-back delivery
|
|
17888
|
+
// canary (PREFERRED side), both over the signed mesh RPC.
|
|
17889
|
+
_handbackSendOffer = async (target, offer) => {
|
|
17890
|
+
const url = peerUrl(target);
|
|
17891
|
+
if (!url)
|
|
17892
|
+
return 'timeout';
|
|
17893
|
+
try {
|
|
17894
|
+
const res = await meshClient.send({ machineId: target, url }, { type: 'handback-offer', proposedEpoch: offer.proposedEpoch, consentToken: offer.consentToken, expiresAt: offer.expiresAt }, 0, { timeoutMs: 15_000 });
|
|
17895
|
+
if (res.ok) {
|
|
17896
|
+
const r = (res.result ?? {});
|
|
17897
|
+
if (r.response === 'accept')
|
|
17898
|
+
return 'accept';
|
|
17899
|
+
if (r.response === 'declined:churn-latched' || r.response === 'declined:quota' || r.response === 'declined:legacy-peer')
|
|
17900
|
+
return r.response;
|
|
17901
|
+
return 'declined:other';
|
|
17902
|
+
}
|
|
17903
|
+
// Version skew (R-r2-2): 403 handback-offer-unauthorized / 501
|
|
17904
|
+
// no-handler ⇒ peer-cannot-hand-back → the sender stops re-offering
|
|
17905
|
+
// for the episode (degrade to today's sticky behavior).
|
|
17906
|
+
if (res.reason === 'no-handler' || res.reason === 'handback-offer-unauthorized')
|
|
17907
|
+
return 'declined:legacy-peer';
|
|
17908
|
+
return 'declined:other';
|
|
17909
|
+
}
|
|
17910
|
+
catch {
|
|
17911
|
+
return 'timeout'; /* @silent-fallback-ok — a transport fault reads as timeout: the holder KEEPS HOLDING (claim-before-release, the safe direction) */
|
|
17912
|
+
}
|
|
17913
|
+
};
|
|
17914
|
+
_handbackCanary = async (oldHolder) => {
|
|
17915
|
+
// One identity-authenticated round-trip through the REAL mesh RPC to
|
|
17916
|
+
// the old holder, plus a live lease check on THIS side — proves the
|
|
17917
|
+
// new holder's mesh path is genuinely serving after the hand-back.
|
|
17918
|
+
if (!(coordinator?.holdsLease() ?? false))
|
|
17919
|
+
return false;
|
|
17920
|
+
const url = peerUrl(oldHolder);
|
|
17921
|
+
if (!url)
|
|
17922
|
+
return false;
|
|
17923
|
+
const res = await meshClient.send({ machineId: oldHolder, url }, { type: 'session-status' }, 0, { timeoutMs: 10_000 });
|
|
17924
|
+
return res.ok === true;
|
|
17925
|
+
};
|
|
17355
17926
|
// WS5.2 R4a — operator/issuer leg: deliver an R4a-signed account-follow-me mandate to a
|
|
17356
17927
|
// REMOTE target over the signed mesh `account-follow-me-mandate-deliver` verb. Every
|
|
17357
17928
|
// failure shape maps to an explicit outcome the issue-for-machine route surfaces honestly
|
|
@@ -18410,6 +18981,8 @@ export async function startServer(options) {
|
|
|
18410
18981
|
requestJournalDelta: async (machineId, url, kind, fromSeq) => {
|
|
18411
18982
|
try {
|
|
18412
18983
|
const res = await meshClient.send({ machineId, url }, { type: 'journal-sync', request: { machineId, kind, fromSeq } }, 0);
|
|
18984
|
+
if (res.ok)
|
|
18985
|
+
_journalSyncLastOkMs = Date.now(); // U4.2 evidence-5 mirror freshness (an empty delta is still a successful sync)
|
|
18413
18986
|
if (res.ok && res.result && typeof res.result === 'object' && 'batch' in res.result) {
|
|
18414
18987
|
const b = res.result.batch;
|
|
18415
18988
|
if (Array.isArray(b) && b.length > 0) {
|
|
@@ -18895,6 +19468,23 @@ export async function startServer(options) {
|
|
|
18895
19468
|
// Lease-holder is the sole actor; single-machine = strict no-op. GET /guards.
|
|
18896
19469
|
// Wired here (late) because it depends on machinePoolRegistry +
|
|
18897
19470
|
// sessionOwnershipRegistry + _meshSelfId, all assigned during pool boot.
|
|
19471
|
+
// U4.2 / U4.4 shared attention seam — episode-keyed, deduped by the
|
|
19472
|
+
// attention store; created topics ride the existing flood budgets.
|
|
19473
|
+
_meshAttentionRaise = (item) => {
|
|
19474
|
+
if (!telegram)
|
|
19475
|
+
return;
|
|
19476
|
+
void telegram.createAttentionItem({
|
|
19477
|
+
id: item.id,
|
|
19478
|
+
title: item.title,
|
|
19479
|
+
summary: item.title,
|
|
19480
|
+
description: item.body,
|
|
19481
|
+
category: 'agent-health',
|
|
19482
|
+
priority: item.priority === 'high' ? 'HIGH' : 'NORMAL',
|
|
19483
|
+
sourceContext: item.sourceContext,
|
|
19484
|
+
lane: 'agent-health',
|
|
19485
|
+
healthKey: item.id,
|
|
19486
|
+
});
|
|
19487
|
+
};
|
|
18898
19488
|
const _strandedEnabled = resolveDevAgentGate(config.monitoring?.strandedTopicSentinel?.enabled, config);
|
|
18899
19489
|
if (_strandedEnabled && machinePoolRegistry && sessionOwnershipRegistry) {
|
|
18900
19490
|
try {
|
|
@@ -18923,6 +19513,11 @@ export async function startServer(options) {
|
|
|
18923
19513
|
});
|
|
18924
19514
|
},
|
|
18925
19515
|
nicknameOf: _nickById,
|
|
19516
|
+
// U4.2 R-r2-1: the DETECTION + ESCALATION path is hosted on ANY
|
|
19517
|
+
// quorum member when stale-owner release is active — a
|
|
19518
|
+
// no-lease-holder mesh still reaches the operator. The CLAIM stays
|
|
19519
|
+
// lease-holder-only (OwnershipReconciler).
|
|
19520
|
+
escalationQuorumHosted: () => _staleOwnerEngine?.isActive() === true,
|
|
18926
19521
|
now: () => Date.now(),
|
|
18927
19522
|
}, { ...config.monitoring?.strandedTopicSentinel, enabled: _strandedEnabled });
|
|
18928
19523
|
strandedSentinel.start();
|
|
@@ -19036,7 +19631,7 @@ export async function startServer(options) {
|
|
|
19036
19631
|
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, accountFollowMePeerViews: async () => { const nickById = new Map((_listPoolMachines?.() ?? []).map((m) => [m.machineId, m.nickname ?? m.machineId])); let peers = (_resolvePeerUrls?.() ?? []).map((p) => ({ machineId: p.machineId, nickname: nickById.get(p.machineId) ?? p.machineId, url: p.url })); if (peers.length === 0) {
|
|
19037
19632
|
peers = (_listPoolMachines?.() ?? []).filter((m) => m.machineId !== _meshSelfId && !!m.lastKnownUrl).map((m) => ({ machineId: m.machineId, nickname: m.nickname ?? m.machineId, url: m.lastKnownUrl }));
|
|
19038
19633
|
} if (peers.length === 0)
|
|
19039
|
-
return []; const { fetchPeerSubscriptionViews } = await import('../core/fetchPeerSubscriptionViews.js'); return fetchPeerSubscriptionViews({ peers: () => peers, fetchImpl: fetch, authToken: config.authToken ?? '' }); }, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, accountFollowMeRevocation, 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, meshBindActive: coordinator.managers.identityManager.hasIdentity() && config.multiMachine?.meshTransport?.enabled !== false, localSigningKeyPem, leaseTransport, peerEndpointRecorder, getSelfMeshEndpoints, 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, ropeHealthMonitor, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, ownershipReconciler: _ownershipReconciler ?? 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, deliverMandateToMachine: _deliverMandateToMachine ?? 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, enforcedTerminationStatus: () => enforcedTerminationWatchdog?.guardStatus() ?? null, prHandLease: prHandLease ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx }); // Resolve the late-bound topic-operator getter (increment 2e): routing was
|
|
19634
|
+
return []; const { fetchPeerSubscriptionViews } = await import('../core/fetchPeerSubscriptionViews.js'); return fetchPeerSubscriptionViews({ peers: () => peers, fetchImpl: fetch, authToken: config.authToken ?? '' }); }, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, accountFollowMeRevocation, 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, meshBindActive: coordinator.managers.identityManager.hasIdentity() && config.multiMachine?.meshTransport?.enabled !== false, localSigningKeyPem, leaseTransport, peerEndpointRecorder, getSelfMeshEndpoints, 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, ropeHealthMonitor, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, ownershipReconciler: _ownershipReconciler ?? undefined, staleOwnerEngine: _staleOwnerEngine ?? undefined, leaseHandback: _leaseHandbackCtx ?? 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, deliverMandateToMachine: _deliverMandateToMachine ?? 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, enforcedTerminationStatus: () => enforcedTerminationWatchdog?.guardStatus() ?? null, prHandLease: prHandLease ?? undefined, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier, liveTestGate, liveTestGateMode, liveTestRunnerCtx }); // Resolve the late-bound topic-operator getter (increment 2e): routing was
|
|
19040
19635
|
// wired before the server existed; from here on inbound binds use the
|
|
19041
19636
|
// server's own store instance.
|
|
19042
19637
|
_agentServerRef = server;
|