instar 1.3.499 → 1.3.501
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 +407 -6
- package/dist/commands/server.js.map +1 -1
- package/dist/config/ConfigDefaults.d.ts.map +1 -1
- package/dist/config/ConfigDefaults.js +10 -0
- package/dist/config/ConfigDefaults.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 +69 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ReapGuard.d.ts +24 -0
- package/dist/core/ReapGuard.d.ts.map +1 -1
- package/dist/core/ReapGuard.js +62 -0
- package/dist/core/ReapGuard.js.map +1 -1
- package/dist/core/SessionManager.d.ts +32 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +74 -2
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/WorkEvidence.d.ts +45 -0
- package/dist/core/WorkEvidence.d.ts.map +1 -0
- package/dist/core/WorkEvidence.js +88 -0
- package/dist/core/WorkEvidence.js.map +1 -0
- package/dist/core/componentCategories.d.ts.map +1 -1
- package/dist/core/componentCategories.js +3 -0
- package/dist/core/componentCategories.js.map +1 -1
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +5 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/types.d.ts +50 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/messaging/NotificationBatcher.d.ts +12 -0
- package/dist/messaging/NotificationBatcher.d.ts.map +1 -1
- package/dist/messaging/NotificationBatcher.js +36 -0
- package/dist/messaging/NotificationBatcher.js.map +1 -1
- package/dist/messaging/pending-relay-store.d.ts +67 -8
- package/dist/messaging/pending-relay-store.d.ts.map +1 -1
- package/dist/messaging/pending-relay-store.js +151 -14
- package/dist/messaging/pending-relay-store.js.map +1 -1
- package/dist/messaging/reap-notice-delivery-id.d.ts +37 -0
- package/dist/messaging/reap-notice-delivery-id.d.ts.map +1 -0
- package/dist/messaging/reap-notice-delivery-id.js +52 -0
- package/dist/messaging/reap-notice-delivery-id.js.map +1 -0
- package/dist/monitoring/QuotaManager.d.ts +6 -0
- package/dist/monitoring/QuotaManager.d.ts.map +1 -1
- package/dist/monitoring/QuotaManager.js +11 -0
- package/dist/monitoring/QuotaManager.js.map +1 -1
- package/dist/monitoring/ReapLog.d.ts +39 -4
- package/dist/monitoring/ReapLog.d.ts.map +1 -1
- package/dist/monitoring/ReapLog.js +54 -4
- package/dist/monitoring/ReapLog.js.map +1 -1
- package/dist/monitoring/ReapNoticeDrain.d.ts +113 -0
- package/dist/monitoring/ReapNoticeDrain.d.ts.map +1 -0
- package/dist/monitoring/ReapNoticeDrain.js +231 -0
- package/dist/monitoring/ReapNoticeDrain.js.map +1 -0
- package/dist/monitoring/ReapNotifier.d.ts +89 -18
- package/dist/monitoring/ReapNotifier.d.ts.map +1 -1
- package/dist/monitoring/ReapNotifier.js +329 -22
- package/dist/monitoring/ReapNotifier.js.map +1 -1
- package/dist/monitoring/ResumeQueue.d.ts +223 -0
- package/dist/monitoring/ResumeQueue.d.ts.map +1 -0
- package/dist/monitoring/ResumeQueue.js +600 -0
- package/dist/monitoring/ResumeQueue.js.map +1 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts +151 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts.map +1 -0
- package/dist/monitoring/ResumeQueueDrainer.js +420 -0
- package/dist/monitoring/ResumeQueueDrainer.js.map +1 -0
- package/dist/monitoring/SessionMigrator.d.ts +10 -0
- package/dist/monitoring/SessionMigrator.d.ts.map +1 -1
- package/dist/monitoring/SessionMigrator.js +43 -1
- package/dist/monitoring/SessionMigrator.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +1 -0
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +5 -0
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel.d.ts.map +1 -1
- package/dist/monitoring/delivery-failure-sentinel.js +7 -3
- package/dist/monitoring/delivery-failure-sentinel.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +4 -3
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +5 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +3 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/routes.d.ts +8 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +94 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/skills/spec-converge/SKILL.md +23 -0
- package/src/data/builtin-manifest.json +65 -65
- package/src/data/state-coherence-registry.json +14 -1
- package/src/scaffold/templates.ts +4 -3
- package/upgrades/1.3.500.md +43 -0
- package/upgrades/1.3.501.md +51 -0
- package/upgrades/side-effects/conformance-gate-autoinvoke.md +58 -0
- package/upgrades/side-effects/reap-notify-resume-queue.md +89 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAyG7D,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;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgCH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAS3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAuBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAyG7D,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;AAyyCD,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,CAwVN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA+rXtE;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"}
|
package/dist/commands/server.js
CHANGED
|
@@ -100,7 +100,7 @@ import { MessageProcessingLedger } from '../messaging/MessageProcessingLedger.js
|
|
|
100
100
|
import { recoverStuckMessages } from '../messaging/stuckMessageRecovery.js';
|
|
101
101
|
import { ReplyMarkerTransport } from '../core/ReplyMarkerTransport.js';
|
|
102
102
|
import { decryptFromSync, encryptForSync } from '../core/SecretStore.js';
|
|
103
|
-
import { createPrivateKey, createPublicKey } from 'node:crypto';
|
|
103
|
+
import { createPrivateKey, createPublicKey, createHash } from 'node:crypto';
|
|
104
104
|
import { sign as signEd25519, verify as verifyEd25519 } from '../core/MachineIdentity.js';
|
|
105
105
|
import { ProjectMapper } from '../core/ProjectMapper.js';
|
|
106
106
|
import { CartographerTree } from '../core/CartographerTree.js';
|
|
@@ -516,7 +516,11 @@ async function spawnSessionForTopic(sessionManager, telegram, sessionName, topic
|
|
|
516
516
|
/** Subscription & Auth Standard P1.3 (additive): launch under this account's
|
|
517
517
|
* config home + record its id (the quota-aware account-swap mechanism).
|
|
518
518
|
* Omitted = unchanged behaviour. */
|
|
519
|
-
accountSwap
|
|
519
|
+
accountSwap,
|
|
520
|
+
/** Reap-notify spec R2.8 / L13 — explicit per-spawn working directory (the
|
|
521
|
+
* resume-queue drainer passes a queue entry's recorded cwd so interrupted
|
|
522
|
+
* worktree work resumes in ITS tree). Omitted = module project dir. */
|
|
523
|
+
spawnOpts) {
|
|
520
524
|
const msg = latestMessage || 'Session started — send a message to continue.';
|
|
521
525
|
// If memory is elevated/critical and we have the reaper, try to free memory
|
|
522
526
|
// by cleaning orphans before spawning. Interactive sessions are NEVER blocked
|
|
@@ -787,6 +791,8 @@ accountSwap) {
|
|
|
787
791
|
// this account's config home + record its id. Unset = unchanged.
|
|
788
792
|
...(accountSwap?.configHome ? { configHome: accountSwap.configHome } : {}),
|
|
789
793
|
...(accountSwap?.accountId ? { subscriptionAccountId: accountSwap.accountId } : {}),
|
|
794
|
+
// R2.8/L13: per-spawn cwd from the resume-queue entry. Unset = projectDir.
|
|
795
|
+
...(spawnOpts?.cwd ? { cwd: spawnOpts.cwd } : {}),
|
|
790
796
|
});
|
|
791
797
|
// Clear the resume entry after successful spawn to prevent stale reuse
|
|
792
798
|
if (resumeSessionId) {
|
|
@@ -5422,6 +5428,28 @@ export async function startServer(options) {
|
|
|
5422
5428
|
const { ReapLog } = await import('../monitoring/ReapLog.js');
|
|
5423
5429
|
const { ReapNotifier } = await import('../monitoring/ReapNotifier.js');
|
|
5424
5430
|
const reapLog = new ReapLog(config.stateDir, () => (coordinator.enabled ? coordinator.identity?.machineId : undefined));
|
|
5431
|
+
// ── Durable notice lane (reap-notify spec R1.3) ──
|
|
5432
|
+
// The notifier enqueues notices as `reap-notify:<id>` rows in the shared
|
|
5433
|
+
// PendingRelayStore; the ALWAYS-ON ReapNoticeDrain (started after the
|
|
5434
|
+
// Telegram adapter exists, below) delivers them — independent of the
|
|
5435
|
+
// default-OFF DeliveryFailureSentinel. A store open failure degrades the
|
|
5436
|
+
// notifier to its loud direct-send fallback (R1.3 enqueue-failed path).
|
|
5437
|
+
let reapNoticeStore = null;
|
|
5438
|
+
try {
|
|
5439
|
+
const { PendingRelayStore, assertSqliteAvailable } = await import('../messaging/pending-relay-store.js');
|
|
5440
|
+
if (assertSqliteAvailable().ok) {
|
|
5441
|
+
reapNoticeStore = PendingRelayStore.open(config.projectName, config.stateDir);
|
|
5442
|
+
}
|
|
5443
|
+
}
|
|
5444
|
+
catch (err) {
|
|
5445
|
+
// @silent-fallback-ok — not silent: warns with full context here, and the
|
|
5446
|
+
// notifier's enqueue-failed path reports via DegradationReporter (R1.3).
|
|
5447
|
+
console.warn('[reap-notify] pending-relay store unavailable — notices fall back to direct send:', err);
|
|
5448
|
+
reapNoticeStore = null;
|
|
5449
|
+
}
|
|
5450
|
+
// Wired by the resume-queue boot block (Part B) once the queue exists;
|
|
5451
|
+
// stays false (no "restart queued" lines) until then or in dry-run.
|
|
5452
|
+
let resumeQueuedForSession = () => false;
|
|
5425
5453
|
const reapNotifier = new ReapNotifier({
|
|
5426
5454
|
resolveTopic: (tmuxSession) => {
|
|
5427
5455
|
const t = telegram?.getTopicForSession(tmuxSession);
|
|
@@ -5431,14 +5459,353 @@ export async function startServer(options) {
|
|
|
5431
5459
|
return Number.isFinite(n) ? n : null;
|
|
5432
5460
|
},
|
|
5433
5461
|
lifelineTopic: () => telegram?.getLifelineTopicId() ?? null,
|
|
5434
|
-
//
|
|
5435
|
-
// aware). The notifier already coalesces
|
|
5462
|
+
// Legacy + fallback transport → through the formatter/tone-gate
|
|
5463
|
+
// (HTML-escaped, quiet-hours aware). The notifier already coalesces.
|
|
5436
5464
|
send: (topicId, text) => notify('SUMMARY', 'session-reap', text, topicId),
|
|
5465
|
+
enqueueNotice: reapNoticeStore
|
|
5466
|
+
? (input) => reapNoticeStore.enqueue({
|
|
5467
|
+
delivery_id: input.delivery_id,
|
|
5468
|
+
topic_id: input.topic_id,
|
|
5469
|
+
text_hash: createHash('sha256').update(input.text).digest('hex'),
|
|
5470
|
+
text: input.text,
|
|
5471
|
+
next_attempt_at: input.next_attempt_at,
|
|
5472
|
+
})
|
|
5473
|
+
: undefined,
|
|
5474
|
+
recordNotify: (e) => reapLog.recordNotify(e),
|
|
5475
|
+
quietHoursEndAt: (now) => notificationBatcher.quietHoursEndAt(now),
|
|
5476
|
+
summaryReleaseAt: (now) => notificationBatcher.nextSummaryReleaseAt(now),
|
|
5477
|
+
resumeQueuedFor: (tmuxSession) => resumeQueuedForSession(tmuxSession),
|
|
5478
|
+
reportDegradation: (reason, impact) => {
|
|
5479
|
+
try {
|
|
5480
|
+
DegradationReporter.getInstance().report({
|
|
5481
|
+
feature: 'reap-notice-enqueue',
|
|
5482
|
+
primary: 'durable reap-notice delivery via PendingRelayStore + ReapNoticeDrain',
|
|
5483
|
+
fallback: 'one direct send attempt (fire-and-forget)',
|
|
5484
|
+
reason,
|
|
5485
|
+
impact,
|
|
5486
|
+
});
|
|
5487
|
+
}
|
|
5488
|
+
catch { /* @silent-fallback-ok — guard around the degradation REPORTER itself; the degradation it describes was already logged by the caller */ }
|
|
5489
|
+
},
|
|
5437
5490
|
}, {
|
|
5438
5491
|
enabled: config.monitoring?.reapNotify?.enabled ?? true,
|
|
5439
5492
|
coalesceWindowMs: config.monitoring?.reapNotify?.coalesceWindowMs ?? 60_000,
|
|
5493
|
+
perTopic: config.monitoring?.reapNotify?.perTopic ?? true,
|
|
5494
|
+
maxImmediatePerFlush: config.monitoring?.reapNotify?.maxImmediatePerFlush ?? 5,
|
|
5495
|
+
drainEnabled: config.monitoring?.reapNotify?.drainEnabled ?? true,
|
|
5440
5496
|
});
|
|
5497
|
+
// ReapNoticeDrain — the always-on delivery loop over the reap-notify lane
|
|
5498
|
+
// (R1.3; independent of the default-OFF DeliveryFailureSentinel). The
|
|
5499
|
+
// telegram adapter is referenced lazily: it does not exist yet at this
|
|
5500
|
+
// point in boot, and a tick with no adapter simply retries on backoff.
|
|
5501
|
+
let reapNoticeDrain = null;
|
|
5502
|
+
if (reapNoticeStore && (config.monitoring?.reapNotify?.drainEnabled ?? true)) {
|
|
5503
|
+
const { ReapNoticeDrain } = await import('../monitoring/ReapNoticeDrain.js');
|
|
5504
|
+
const { getCurrentBootId } = await import('../server/boot-id.js');
|
|
5505
|
+
reapNoticeDrain = new ReapNoticeDrain({
|
|
5506
|
+
store: reapNoticeStore,
|
|
5507
|
+
sendToTopic: async (topicId, text) => {
|
|
5508
|
+
if (!telegram)
|
|
5509
|
+
throw new Error('telegram adapter not available');
|
|
5510
|
+
await telegram.sendToTopic(topicId, text);
|
|
5511
|
+
},
|
|
5512
|
+
recordNotify: (e) => reapLog.recordNotify(e),
|
|
5513
|
+
emitAttention: async (item) => {
|
|
5514
|
+
if (!telegram)
|
|
5515
|
+
return;
|
|
5516
|
+
await telegram.createAttentionItem({
|
|
5517
|
+
id: item.id,
|
|
5518
|
+
title: item.title,
|
|
5519
|
+
summary: item.summary ?? item.title,
|
|
5520
|
+
description: item.description,
|
|
5521
|
+
category: item.category ?? 'delivery',
|
|
5522
|
+
priority: item.priority === 'high' ? 'HIGH' : item.priority === 'low' ? 'LOW' : 'NORMAL',
|
|
5523
|
+
sourceContext: item.sourceContext,
|
|
5524
|
+
});
|
|
5525
|
+
},
|
|
5526
|
+
bootId: getCurrentBootId() ?? `boot-${Date.now().toString(36)}`,
|
|
5527
|
+
});
|
|
5528
|
+
reapNoticeDrain.start();
|
|
5529
|
+
console.log(pc.green(' ReapNoticeDrain started (always-on durable reap-notice delivery)'));
|
|
5530
|
+
}
|
|
5441
5531
|
sessionManager.setAwakeChecker(() => !coordinator.enabled || coordinator.isAwake);
|
|
5532
|
+
// Pressure-tier provider for the evidence fallback (reap-notify R2.1):
|
|
5533
|
+
// the SAME shared HostPressureSampler definition the reaper and the
|
|
5534
|
+
// resume-queue drainer read — one definition of "pressure", never two.
|
|
5535
|
+
const { sampleHostPressure: samplePressureShared } = await import('../monitoring/HostPressureSampler.js');
|
|
5536
|
+
const reaperPressureCfg = config.monitoring?.sessionReaper;
|
|
5537
|
+
const sharedPressureTier = () => samplePressureShared({
|
|
5538
|
+
cpuModerateLoadPerCore: reaperPressureCfg?.cpuModerateLoadPerCore ?? 1.0,
|
|
5539
|
+
cpuCriticalLoadPerCore: reaperPressureCfg?.cpuCriticalLoadPerCore ?? 1.5,
|
|
5540
|
+
}).tier;
|
|
5541
|
+
sessionManager.setPressureTierProvider(sharedPressureTier);
|
|
5542
|
+
// ── ResumeQueue + drainer (reap-notify spec Part B, R2.2–R2.11) ──
|
|
5543
|
+
// Ships enabled + dryRun (observe-only) as CODE defaults — deliberately
|
|
5544
|
+
// not in ConfigDefaults so the later fleet flip of the shipped default
|
|
5545
|
+
// takes effect. Classified in DARK_GATE_EXCLUSIONS (cost-bearing).
|
|
5546
|
+
const rqCfg = config.monitoring?.resumeQueue ?? {};
|
|
5547
|
+
let resumeQueue = null;
|
|
5548
|
+
let resumeDrainer = null;
|
|
5549
|
+
// Operator-stop record for the drainer's R2.6 validation (in-memory map +
|
|
5550
|
+
// the durable autonomous-emergency-stop flag file's mtime as global stop).
|
|
5551
|
+
const operatorStopsByTopic = new Map();
|
|
5552
|
+
let globalOperatorStopAt = 0;
|
|
5553
|
+
const recordOperatorStop = (topicId) => {
|
|
5554
|
+
if (topicId == null)
|
|
5555
|
+
globalOperatorStopAt = Date.now();
|
|
5556
|
+
else
|
|
5557
|
+
operatorStopsByTopic.set(topicId, Date.now());
|
|
5558
|
+
};
|
|
5559
|
+
if (rqCfg.enabled ?? true) {
|
|
5560
|
+
const { ResumeQueue } = await import('../monitoring/ResumeQueue.js');
|
|
5561
|
+
const { ResumeQueueDrainer } = await import('../monitoring/ResumeQueueDrainer.js');
|
|
5562
|
+
// Decision-transition audit sink: logs/resume-queue.jsonl, 5MB×2 rotation.
|
|
5563
|
+
const resumeAuditPath = path.join(_projectDir, 'logs', 'resume-queue.jsonl');
|
|
5564
|
+
const auditResumeQueue = (event) => {
|
|
5565
|
+
try {
|
|
5566
|
+
fs.mkdirSync(path.dirname(resumeAuditPath), { recursive: true });
|
|
5567
|
+
try {
|
|
5568
|
+
const st = fs.statSync(resumeAuditPath);
|
|
5569
|
+
if (st.size > 5 * 1024 * 1024) {
|
|
5570
|
+
fs.renameSync(resumeAuditPath, `${resumeAuditPath}.1`); // 5MB×2: .1 replaced each rotation
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
catch { /* no file yet */ }
|
|
5574
|
+
fs.appendFileSync(resumeAuditPath, JSON.stringify(event) + '\n');
|
|
5575
|
+
}
|
|
5576
|
+
catch { /* the audit sink never endangers the queue */ }
|
|
5577
|
+
};
|
|
5578
|
+
// ALL give-up classes fold into ONE rolling deduped attention item (P17).
|
|
5579
|
+
const resumeAggregate = { counts: new Map(), recent: [] };
|
|
5580
|
+
const raiseResumeAggregated = (kind, detail) => {
|
|
5581
|
+
try {
|
|
5582
|
+
resumeAggregate.counts.set(kind, (resumeAggregate.counts.get(kind) ?? 0) + 1);
|
|
5583
|
+
resumeAggregate.recent.push(`[${kind}] ${detail}`);
|
|
5584
|
+
if (resumeAggregate.recent.length > 8)
|
|
5585
|
+
resumeAggregate.recent.shift();
|
|
5586
|
+
if (!telegram)
|
|
5587
|
+
return;
|
|
5588
|
+
const total = [...resumeAggregate.counts.values()].reduce((a, b) => a + b, 0);
|
|
5589
|
+
const breakdown = [...resumeAggregate.counts.entries()].map(([k, c]) => `${k}×${c}`).join(', ');
|
|
5590
|
+
void telegram.createAttentionItem({
|
|
5591
|
+
id: 'resume-queue:aggregate',
|
|
5592
|
+
title: `Resume queue: ${total} notice${total === 1 ? '' : 's'} (${breakdown})`,
|
|
5593
|
+
summary: detail,
|
|
5594
|
+
description: resumeAggregate.recent.join('\n'),
|
|
5595
|
+
category: 'sessions',
|
|
5596
|
+
priority: 'NORMAL', // per-entry HIGH items are forbidden (P17)
|
|
5597
|
+
sourceContext: 'resume-queue',
|
|
5598
|
+
}).catch(() => { });
|
|
5599
|
+
}
|
|
5600
|
+
catch { /* never endanger the caller */ }
|
|
5601
|
+
};
|
|
5602
|
+
resumeQueue = new ResumeQueue({
|
|
5603
|
+
stateDir: path.join(_projectDir, '.instar'),
|
|
5604
|
+
audit: auditResumeQueue,
|
|
5605
|
+
raiseAggregated: raiseResumeAggregated,
|
|
5606
|
+
}, {
|
|
5607
|
+
enabled: rqCfg.enabled ?? true,
|
|
5608
|
+
dryRun: rqCfg.dryRun ?? true, // shipped observe-only (decision 2)
|
|
5609
|
+
maxAttempts: rqCfg.maxAttempts ?? 3,
|
|
5610
|
+
maxResurrections: rqCfg.maxResurrections ?? 2,
|
|
5611
|
+
entryTtlHours: rqCfg.entryTtlHours ?? 24,
|
|
5612
|
+
maxQueueSize: rqCfg.maxQueueSize ?? 50,
|
|
5613
|
+
includeOperatorKills: rqCfg.includeOperatorKills ?? false,
|
|
5614
|
+
});
|
|
5615
|
+
const queueStarted = resumeQueue.start();
|
|
5616
|
+
if (!queueStarted) {
|
|
5617
|
+
console.log(pc.yellow(` ResumeQueue disabled: ${resumeQueue.isDisabled()}`));
|
|
5618
|
+
}
|
|
5619
|
+
else {
|
|
5620
|
+
// Feed the notifier's "restart is queued" line (live, non-dry-run only).
|
|
5621
|
+
const rq = resumeQueue;
|
|
5622
|
+
resumeQueuedForSession = (tmuxSession) => rq.hasLiveQueuedEntryFor(tmuxSession);
|
|
5623
|
+
const resolveTopicForTmux = (tmuxSession) => {
|
|
5624
|
+
try {
|
|
5625
|
+
const t = telegram?.getTopicForSession(tmuxSession);
|
|
5626
|
+
if (t == null)
|
|
5627
|
+
return null;
|
|
5628
|
+
const n = typeof t === 'number' ? t : Number(t);
|
|
5629
|
+
return Number.isFinite(n) ? n : null;
|
|
5630
|
+
}
|
|
5631
|
+
catch {
|
|
5632
|
+
// @silent-fallback-ok — null = "unbound": the notifier then routes
|
|
5633
|
+
// the session to the lifeline index line, never a dropped notice.
|
|
5634
|
+
return null;
|
|
5635
|
+
}
|
|
5636
|
+
};
|
|
5637
|
+
resumeDrainer = new ResumeQueueDrainer({
|
|
5638
|
+
queue: rq,
|
|
5639
|
+
pressureTier: sharedPressureTier,
|
|
5640
|
+
canSpawnSession: () => (quotaManager ? quotaManager.canSpawnSession().allowed : true),
|
|
5641
|
+
sessionCountOk: () => sessionManager.listRunningSessions().length <
|
|
5642
|
+
(config.maxSessions ?? 10),
|
|
5643
|
+
// No catch: a throwing dep resolves to the SAFE side (blocked)
|
|
5644
|
+
// inside the drainer's gate — wrapping it here would flip the
|
|
5645
|
+
// failure to the lenient side.
|
|
5646
|
+
migrationInFlight: () => quotaManager?.isMigrationInFlight() ?? false,
|
|
5647
|
+
liveSessionForTopic: (topicId) => sessionManager
|
|
5648
|
+
.listRunningSessions()
|
|
5649
|
+
.some((s) => resolveTopicForTmux(s.tmuxSession) === topicId),
|
|
5650
|
+
currentResumeUuid: (topicId) => _topicResumeMap?.get(topicId) ?? null,
|
|
5651
|
+
topicOwnerElsewhere: (topicId) => {
|
|
5652
|
+
// Pool not wired → single-machine → always local. No catch: a
|
|
5653
|
+
// registry error propagates to the drainer's validateReality,
|
|
5654
|
+
// which resolves a throwing dep to the SAFE side (invalidated).
|
|
5655
|
+
const reg = sessionOwnershipRegistry;
|
|
5656
|
+
const self = _meshSelfId;
|
|
5657
|
+
if (!reg || !self)
|
|
5658
|
+
return false;
|
|
5659
|
+
const owner = reg.ownerOf(String(topicId));
|
|
5660
|
+
return !!owner && owner !== self;
|
|
5661
|
+
},
|
|
5662
|
+
topicBindingMatches: (topicId, cwd) => {
|
|
5663
|
+
const bindings = scopeVerifier?.loadTopicBindings?.();
|
|
5664
|
+
const binding = bindings?.[String(topicId)];
|
|
5665
|
+
if (!binding?.projectDir)
|
|
5666
|
+
return true; // unbound topic → default project
|
|
5667
|
+
return path.resolve(cwd).startsWith(path.resolve(binding.projectDir));
|
|
5668
|
+
},
|
|
5669
|
+
operatorStopSince: (topicId, sinceIso) => {
|
|
5670
|
+
const since = Date.parse(sinceIso);
|
|
5671
|
+
const perTopic = operatorStopsByTopic.get(topicId) ?? 0;
|
|
5672
|
+
let flagAt = 0;
|
|
5673
|
+
try {
|
|
5674
|
+
flagAt = fs.statSync(path.join(_projectDir, '.instar', 'autonomous-emergency-stop')).mtimeMs;
|
|
5675
|
+
}
|
|
5676
|
+
catch { /* no flag */ }
|
|
5677
|
+
return Math.max(perTopic, globalOperatorStopAt, flagAt) > since;
|
|
5678
|
+
},
|
|
5679
|
+
jobCheck: (slug, queuedAtIso) => {
|
|
5680
|
+
if (!scheduler)
|
|
5681
|
+
return { ok: false, why: 'scheduler-unavailable' };
|
|
5682
|
+
const job = scheduler.getJobs().find((j) => j.slug === slug);
|
|
5683
|
+
if (!job)
|
|
5684
|
+
return { ok: false, why: 'job-missing' };
|
|
5685
|
+
// 'disabled' also covers CrashLoopPauser-paused jobs — the
|
|
5686
|
+
// pauser's mechanism IS setting enabled=false (+ provenance note).
|
|
5687
|
+
if (!job.enabled)
|
|
5688
|
+
return { ok: false, why: 'job-disabled' };
|
|
5689
|
+
const lastRun = state.getJobState(slug)?.lastRun;
|
|
5690
|
+
if (lastRun && Date.parse(lastRun) > Date.parse(queuedAtIso)) {
|
|
5691
|
+
return { ok: false, why: 'job-ran-since' };
|
|
5692
|
+
}
|
|
5693
|
+
return { ok: true };
|
|
5694
|
+
},
|
|
5695
|
+
pathExists: (p) => fs.existsSync(p),
|
|
5696
|
+
respawnTopic: async (entry, continuationPrompt) => {
|
|
5697
|
+
if (!telegram)
|
|
5698
|
+
throw new Error('telegram adapter not available');
|
|
5699
|
+
return await spawnSessionForTopic(sessionManager, telegram, entry.sessionName, entry.topicId, continuationPrompt, topicMemory, undefined, undefined, undefined, { cwd: entry.worktreePath ?? entry.cwd });
|
|
5700
|
+
},
|
|
5701
|
+
triggerJob: async (slug) => {
|
|
5702
|
+
if (!scheduler)
|
|
5703
|
+
return 'skipped';
|
|
5704
|
+
return await scheduler.triggerJob(slug, 'resume-queue');
|
|
5705
|
+
},
|
|
5706
|
+
spawnAliveAfterGrace: async (tmuxSession) => {
|
|
5707
|
+
await new Promise((resolve) => {
|
|
5708
|
+
const t = setTimeout(resolve, 15_000);
|
|
5709
|
+
if (typeof t.unref === 'function')
|
|
5710
|
+
t.unref();
|
|
5711
|
+
});
|
|
5712
|
+
return sessionManager.isSessionAlive(tmuxSession);
|
|
5713
|
+
},
|
|
5714
|
+
notifyResumed: (entry) => {
|
|
5715
|
+
// R2.11 — honest wording: "restarted", never a transcript-resume
|
|
5716
|
+
// claim (--resume can fall back to a fresh conversation in-pane).
|
|
5717
|
+
if (entry.topicId == null)
|
|
5718
|
+
return;
|
|
5719
|
+
notify('SUMMARY', 'session-resume', `🔁 I restarted this session to pick the work back up after it was shut down mid-work.`, entry.topicId);
|
|
5720
|
+
},
|
|
5721
|
+
raiseAggregated: raiseResumeAggregated,
|
|
5722
|
+
audit: auditResumeQueue,
|
|
5723
|
+
tier1Check: async (entry) => {
|
|
5724
|
+
// Observe-only Tier 1 sanity check via the shared LlmQueue
|
|
5725
|
+
// (P7). Throws when the LLM substrate is unavailable — the
|
|
5726
|
+
// drainer audits that as supervision:'shed'.
|
|
5727
|
+
const q = sharedLlmQueue;
|
|
5728
|
+
const intel = _sharedIntelligence;
|
|
5729
|
+
if (!q || !intel)
|
|
5730
|
+
throw new Error('llm-unavailable');
|
|
5731
|
+
const reasonLiteral = entry.reason.slice(0, 200).replace(/`/g, "'");
|
|
5732
|
+
const prompt = `A session was shut down mid-work and is queued for automatic restart. Given ONLY these ` +
|
|
5733
|
+
`recorded fields, is restarting it sensible? Look for internal contradictions (a "mid-work" ` +
|
|
5734
|
+
`entry whose reason describes completed work; a resurrection history that reads as a crash loop).\n` +
|
|
5735
|
+
`Recorded reason (literal data): \`${reasonLiteral}\`\n` +
|
|
5736
|
+
`Work signals: ${entry.workEvidence.join(', ') || '(none)'}\n` +
|
|
5737
|
+
`Queued: ${entry.queuedAt}; attempts so far: ${entry.attempts}.\n` +
|
|
5738
|
+
`Reply with JSON only: {"sensible": true|false, "reasoning": "<one sentence>"}`;
|
|
5739
|
+
const raw = await q.enqueue('background', (signal) => intel.evaluate(prompt, {
|
|
5740
|
+
model: 'fast',
|
|
5741
|
+
maxTokens: 150,
|
|
5742
|
+
temperature: 0,
|
|
5743
|
+
signal,
|
|
5744
|
+
attribution: { component: 'ResumeQueueDrainer' }, // attribution for /metrics/features
|
|
5745
|
+
}));
|
|
5746
|
+
try {
|
|
5747
|
+
const t = String(raw).trim();
|
|
5748
|
+
const j = t.startsWith('```') ? t.replace(/^```(?:json)?\n?/, '').replace(/\n?```$/, '') : t;
|
|
5749
|
+
const parsed = JSON.parse(j);
|
|
5750
|
+
return { sensible: parsed.sensible !== false, reasoning: parsed.reasoning };
|
|
5751
|
+
}
|
|
5752
|
+
catch {
|
|
5753
|
+
return { sensible: true, reasoning: 'unparseable verdict — treated as no-concern (observe-only)' };
|
|
5754
|
+
}
|
|
5755
|
+
},
|
|
5756
|
+
}, {
|
|
5757
|
+
drainIntervalSec: rqCfg.drainIntervalSec ?? 60,
|
|
5758
|
+
requiredCalmTicks: rqCfg.requiredCalmTicks ?? 3,
|
|
5759
|
+
maxAttempts: rqCfg.maxAttempts ?? 3,
|
|
5760
|
+
breakerThreshold: rqCfg.breakerThreshold ?? 3,
|
|
5761
|
+
breakerCooldownMin: rqCfg.breakerCooldownMin ?? 30,
|
|
5762
|
+
tier1Check: rqCfg.tier1Check ?? true,
|
|
5763
|
+
});
|
|
5764
|
+
resumeDrainer.start();
|
|
5765
|
+
console.log(pc.green(` ResumeQueue started (${rqCfg.dryRun ?? true ? 'dry-run observe-only' : 'LIVE'}; drainer ${rqCfg.drainIntervalSec ?? 60}s tick)`));
|
|
5766
|
+
// Boot reconciliation half 2 (R2.4): re-enqueue recent mid-work reaps
|
|
5767
|
+
// the queue lost to a crash window. Deferred 30s so the Telegram
|
|
5768
|
+
// adapter (topic resolution) exists; topic-bound candidates only —
|
|
5769
|
+
// job entries rely on cron recurrence and opt-in we cannot
|
|
5770
|
+
// reconstruct from the reap-log.
|
|
5771
|
+
const reconcileTimer = setTimeout(() => {
|
|
5772
|
+
try {
|
|
5773
|
+
const ttlMs = (rqCfg.entryTtlHours ?? 24) * 3600_000;
|
|
5774
|
+
const cutoff = Date.now() - ttlMs;
|
|
5775
|
+
const candidates = reapLog
|
|
5776
|
+
.read(1000)
|
|
5777
|
+
.filter((en) => en.type === 'reaped' &&
|
|
5778
|
+
en.midWork === true &&
|
|
5779
|
+
en.disposition === 'terminal' &&
|
|
5780
|
+
en.origin === 'autonomous' &&
|
|
5781
|
+
Date.parse(en.ts) > cutoff)
|
|
5782
|
+
.map((en) => {
|
|
5783
|
+
const topicId = resolveTopicForTmux(en.tmuxSession);
|
|
5784
|
+
return {
|
|
5785
|
+
sessionName: en.session,
|
|
5786
|
+
tmuxSession: en.tmuxSession,
|
|
5787
|
+
topicId,
|
|
5788
|
+
resumeUuid: topicId != null ? (_topicResumeMap?.get(topicId) ?? null) : null,
|
|
5789
|
+
cwd: _projectDir,
|
|
5790
|
+
reason: en.reason,
|
|
5791
|
+
disposition: 'terminal',
|
|
5792
|
+
origin: 'autonomous',
|
|
5793
|
+
workEvidence: en.workEvidence ?? [],
|
|
5794
|
+
};
|
|
5795
|
+
});
|
|
5796
|
+
const enqueued = rq.reconcileFromReapLog(candidates);
|
|
5797
|
+
if (enqueued > 0) {
|
|
5798
|
+
console.log(`[resume-queue] boot reconciliation re-enqueued ${enqueued} lost mid-work reap(s) from the reap-log`);
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
catch (err) {
|
|
5802
|
+
console.warn('[resume-queue] boot reconciliation failed (non-fatal):', err);
|
|
5803
|
+
}
|
|
5804
|
+
}, 30_000);
|
|
5805
|
+
if (typeof reconcileTimer.unref === 'function')
|
|
5806
|
+
reconcileTimer.unref();
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5442
5809
|
sessionManager.on('sessionReaped', (e) => {
|
|
5443
5810
|
reapLog.recordReaped({
|
|
5444
5811
|
session: e.session.name,
|
|
@@ -5453,8 +5820,42 @@ export async function startServer(options) {
|
|
|
5453
5820
|
// which billing lane the reaped session ran on so the soak can confirm
|
|
5454
5821
|
// rerouted sessions reach their completion from the reap-log too.
|
|
5455
5822
|
...(e.session.launchLane ? { launchLane: e.session.launchLane } : {}),
|
|
5823
|
+
// Mid-work stamp (reap-notify spec R2.1) — evidence clamped at the
|
|
5824
|
+
// chokepoint; the reap-log row is the boot-reconciliation source of truth.
|
|
5825
|
+
...(e.midWork !== undefined ? { midWork: e.midWork } : {}),
|
|
5826
|
+
...(e.workEvidence && e.workEvidence.length > 0 ? { workEvidence: e.workEvidence } : {}),
|
|
5456
5827
|
});
|
|
5457
|
-
|
|
5828
|
+
// Enqueue hook (reap-notify R2.2): every terminal autonomous reap is
|
|
5829
|
+
// OFFERED to the resume queue; eligibility (evidence classes, job
|
|
5830
|
+
// opt-in, operator exclusion, resurrection cap) is decided inside.
|
|
5831
|
+
// Runs BEFORE the notifier so the "restart is queued" line can see the
|
|
5832
|
+
// fresh entry. Never endangers the kill path.
|
|
5833
|
+
try {
|
|
5834
|
+
if (resumeQueue && !resumeQueue.isDisabled()) {
|
|
5835
|
+
const rawTopic = telegram?.getTopicForSession(e.session.tmuxSession);
|
|
5836
|
+
const topicId = rawTopic == null ? null : Number.isFinite(Number(rawTopic)) ? Number(rawTopic) : null;
|
|
5837
|
+
const jobDef = e.session.jobSlug
|
|
5838
|
+
? scheduler?.getJobs().find((j) => j.slug === e.session.jobSlug)
|
|
5839
|
+
: undefined;
|
|
5840
|
+
resumeQueue.considerEnqueue({
|
|
5841
|
+
sessionName: e.session.name,
|
|
5842
|
+
tmuxSession: e.session.tmuxSession,
|
|
5843
|
+
topicId,
|
|
5844
|
+
jobSlug: e.session.jobSlug,
|
|
5845
|
+
jobResumeOptIn: jobDef?.resumeOnReap === true,
|
|
5846
|
+
resumeUuid: topicId != null ? (_topicResumeMap?.get(topicId) ?? null) : null,
|
|
5847
|
+
cwd: e.session.cwd ?? _projectDir,
|
|
5848
|
+
reason: e.reason,
|
|
5849
|
+
disposition: e.disposition ?? 'terminal',
|
|
5850
|
+
origin: e.origin ?? 'autonomous',
|
|
5851
|
+
workEvidence: e.workEvidence ?? [],
|
|
5852
|
+
});
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
catch (err) {
|
|
5856
|
+
console.warn('[resume-queue] enqueue hook raised (non-fatal):', err);
|
|
5857
|
+
}
|
|
5858
|
+
reapNotifier.onReaped({ session: e.session, reason: e.reason, disposition: e.disposition, origin: e.origin, midWork: e.midWork, workEvidence: e.workEvidence });
|
|
5458
5859
|
// Coherence journal 'reaped' (§3.3): emitted HERE, alongside the
|
|
5459
5860
|
// reap-log append it references — never derived in the saveSession
|
|
5460
5861
|
// funnel (which records the plain killed/completed transition).
|
|
@@ -12763,7 +13164,7 @@ export async function startServer(options) {
|
|
|
12763
13164
|
carrier: _topicProfileCarrier,
|
|
12764
13165
|
}
|
|
12765
13166
|
: null;
|
|
12766
|
-
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographer: cartographer ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
13167
|
+
const server = new AgentServer({ config, sessionManager, state, scheduler, telegram, relationships, feedback, feedbackAnomalyDetector, dispatches, updateChecker, autoUpdater, autoDispatcher, quotaTracker, quotaManager, publisher, viewer, tunnel, evolution, watchdog, topicMemory, triageNurse, projectMapper, cartographer: cartographer ?? undefined, coherenceGate: scopeVerifier, contextHierarchy, canonicalState, operationGate, sentinel, adaptiveTrust, memoryMonitor, orphanReaper, coherenceMonitor, commitmentTracker, subscriptionPool, quotaPoller, quotaAwareScheduler: _quotaAwareScheduler ?? undefined, proactiveSwapMonitor: _proactiveSwapMonitor ?? undefined, inUseAccountResolver, enrollmentWizard, semanticMemory, activitySentinel, rateLimitSentinel, releaseReadinessSentinel: releaseReadinessSentinel ?? undefined, messageRouter, summarySentinel, spawnManager, systemReviewer, capabilityMapper, selfKnowledgeTree, coverageAuditor, topicResumeMap: _topicResumeMap ?? undefined, topicProfile: _topicProfileCtx ?? undefined, sessionRefresh: _sessionRefresh ?? undefined, autonomyManager, trustElevationTracker, autonomousEvolution, coordinator: coordinator.enabled ? coordinator : undefined, localSigningKeyPem, leaseTransport, onLeasePullRequest: () => leaseCoordinatorRef?.currentLease() ?? null, liveTailReceiver, handoffWireTransport, onHandoffBegin, onHandoffInitiate: handoffInitiate, handoffInProgress: handoffSentinelInProgress, messageLedger, currentInboundByTopic, replyMarkerTransport, onReplyMarker: messageLedger ? (marker) => { const m = marker; messageLedger.applyRemoteReplyMarker(m.dedupeKey, { platform: m.platform, replyIdempotencyKey: m.replyIdempotencyKey, epoch: m.epoch, topic: m.topic ?? null }); } : undefined, whatsapp: whatsappAdapter, slack: slackAdapter, imessage: imessageAdapter, whatsappBusinessBackend, messageBridge, hookEventReceiver, worktreeMonitor, subagentTracker, instructionsVerifier, handshakeManager: threadlineHandshake, threadlineRouter, conversationStore, warrantsReplyGate, collaborationSurfacer, threadResumeMap, topicLinkageHandler: topicLinkageHandler ?? undefined, threadlineRelayClient, threadlineReplyWaiters, listenerManager: listenerManager ?? undefined, a2aDeliveryTracker: a2aDeliveryTracker ?? undefined, responseReviewGate, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, streamTicketStore: _streamTicketStore ?? undefined, poolStreamAllowRemoteInput: config.dashboard?.poolStream?.allowRemoteInput ?? false, poolStreamConnector: _poolStreamConnector ?? undefined, secretSync: _secretSyncHandle ?? undefined, meshSelfId: _meshSelfId ?? undefined, resolveRouterUrl: _resolveRouterUrl ?? undefined, resolvePeerUrls: _resolvePeerUrls ?? undefined, guardRegistry, listPoolMachines: _listPoolMachines ?? undefined, sessionPoolE2EResultStore, proxyCoordinator, topicIntentStore, topicIntentArcCheck, usherSignalStore, intelligence: sharedIntelligence ?? undefined, telegramBridgeConfig, telegramBridge: telegramBridge ?? undefined, threadlineObservability, briefDeps, workingMemory, taskFlowRegistry, threadlineFlowBridge, sessionReaper, agentWorktreeReaper, mcpProcessReaper, geminiLoopRunner, sleepController, agentActivityState, reapLog, resumeQueue, resumeDrainer, operatorStopRecorder: recordOperatorStop, sleepWakeDetector, unjustifiedStopGate, stopGateDb, stopNotifier });
|
|
12767
13168
|
// Resolve the late-bound topic-operator getter (increment 2e): routing was
|
|
12768
13169
|
// wired before the server existed; from here on inbound binds use the
|
|
12769
13170
|
// server's own store instance.
|