instar 1.3.729 → 1.3.731
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 +254 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/core/CoherenceGate.d.ts +119 -0
- package/dist/core/CoherenceGate.d.ts.map +1 -1
- package/dist/core/CoherenceGate.js +342 -19
- package/dist/core/CoherenceGate.js.map +1 -1
- package/dist/core/CoherenceReviewer.d.ts +30 -0
- package/dist/core/CoherenceReviewer.d.ts.map +1 -1
- package/dist/core/CoherenceReviewer.js +14 -0
- package/dist/core/CoherenceReviewer.js.map +1 -1
- package/dist/core/FileClassifier.d.ts.map +1 -1
- package/dist/core/FileClassifier.js +7 -0
- package/dist/core/FileClassifier.js.map +1 -1
- package/dist/core/ModelSwapService.d.ts +13 -0
- package/dist/core/ModelSwapService.d.ts.map +1 -1
- package/dist/core/ModelSwapService.js +11 -0
- package/dist/core/ModelSwapService.js.map +1 -1
- package/dist/core/ModelTierEscalation.d.ts +10 -0
- package/dist/core/ModelTierEscalation.d.ts.map +1 -1
- package/dist/core/ModelTierEscalation.js +4 -0
- package/dist/core/ModelTierEscalation.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 +43 -0
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/core/ProactiveSwapMonitor.d.ts +74 -20
- package/dist/core/ProactiveSwapMonitor.d.ts.map +1 -1
- package/dist/core/ProactiveSwapMonitor.js +349 -28
- package/dist/core/ProactiveSwapMonitor.js.map +1 -1
- package/dist/core/QuotaAwareScheduler.d.ts +70 -3
- package/dist/core/QuotaAwareScheduler.d.ts.map +1 -1
- package/dist/core/QuotaAwareScheduler.js +100 -16
- package/dist/core/QuotaAwareScheduler.js.map +1 -1
- package/dist/core/ResponseReviewDecisionLog.d.ts +45 -0
- package/dist/core/ResponseReviewDecisionLog.d.ts.map +1 -0
- package/dist/core/ResponseReviewDecisionLog.js +85 -0
- package/dist/core/ResponseReviewDecisionLog.js.map +1 -0
- package/dist/core/SessionManager.d.ts +28 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +102 -0
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SessionRefresh.d.ts +116 -1
- package/dist/core/SessionRefresh.d.ts.map +1 -1
- package/dist/core/SessionRefresh.js +280 -17
- package/dist/core/SessionRefresh.js.map +1 -1
- package/dist/core/SwapAntiThrash.d.ts +329 -0
- package/dist/core/SwapAntiThrash.d.ts.map +1 -0
- package/dist/core/SwapAntiThrash.js +1025 -0
- package/dist/core/SwapAntiThrash.js.map +1 -0
- package/dist/core/SwapLedger.d.ts +168 -0
- package/dist/core/SwapLedger.d.ts.map +1 -0
- package/dist/core/SwapLedger.js +275 -0
- package/dist/core/SwapLedger.js.map +1 -0
- package/dist/core/SwapWorkGate.d.ts +100 -0
- package/dist/core/SwapWorkGate.d.ts.map +1 -0
- package/dist/core/SwapWorkGate.js +175 -0
- package/dist/core/SwapWorkGate.js.map +1 -0
- package/dist/core/WriteDomainRegistry.d.ts.map +1 -1
- package/dist/core/WriteDomainRegistry.js +21 -0
- package/dist/core/WriteDomainRegistry.js.map +1 -1
- package/dist/core/conversationContextWiring.d.ts +51 -0
- package/dist/core/conversationContextWiring.d.ts.map +1 -0
- package/dist/core/conversationContextWiring.js +78 -0
- package/dist/core/conversationContextWiring.js.map +1 -0
- package/dist/core/devGatedFeatures.d.ts.map +1 -1
- package/dist/core/devGatedFeatures.js +6 -0
- package/dist/core/devGatedFeatures.js.map +1 -1
- package/dist/core/reviewers/conversational-tone.d.ts.map +1 -1
- package/dist/core/reviewers/conversational-tone.js +15 -1
- package/dist/core/reviewers/conversational-tone.js.map +1 -1
- package/dist/core/types.d.ts +102 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/untrustedConversationContext.d.ts +77 -0
- package/dist/core/untrustedConversationContext.d.ts.map +1 -0
- package/dist/core/untrustedConversationContext.js +134 -0
- package/dist/core/untrustedConversationContext.js.map +1 -0
- package/dist/monitoring/ReviewCanaryBattery.d.ts +160 -0
- package/dist/monitoring/ReviewCanaryBattery.d.ts.map +1 -0
- package/dist/monitoring/ReviewCanaryBattery.js +416 -0
- package/dist/monitoring/ReviewCanaryBattery.js.map +1 -0
- package/dist/monitoring/guardManifest.d.ts.map +1 -1
- package/dist/monitoring/guardManifest.js +40 -1
- package/dist/monitoring/guardManifest.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +6 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/AgentServer.d.ts +4 -0
- package/dist/server/AgentServer.d.ts.map +1 -1
- package/dist/server/AgentServer.js +20 -0
- package/dist/server/AgentServer.js.map +1 -1
- package/dist/server/CapabilityIndex.d.ts.map +1 -1
- package/dist/server/CapabilityIndex.js +1 -0
- package/dist/server/CapabilityIndex.js.map +1 -1
- package/dist/server/routes.d.ts +5 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +72 -4
- 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/jobs/instar/review-canary-battery.md +31 -0
- package/src/scaffold/templates.ts +6 -0
- package/upgrades/1.3.730.md +112 -0
- package/upgrades/1.3.731.md +97 -0
- package/upgrades/side-effects/context-aware-outbound-review.md +62 -0
- package/upgrades/side-effects/swap-continuity-antithrash.md +118 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgDH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAyBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA6H7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAgFtD;;;;;;;;;;;;;;;;;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;AAu/CD,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,CAijBN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ykBtE;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
|
@@ -26,6 +26,7 @@ import { SpawningTopicsRegistry } from '../core/SpawningTopicsRegistry.js';
|
|
|
26
26
|
import { TopicReachabilityVerifier } from '../monitoring/TopicReachabilityVerifier.js';
|
|
27
27
|
import { SingleInstanceLock, installReleaseHandlers } from '../core/SingleInstanceLock.js';
|
|
28
28
|
import { resolveDevAgentGate, resolveStateSyncStores } from '../core/devAgentGate.js';
|
|
29
|
+
import { resolveAntiThrashKnobs, readingValidity } from '../core/SwapAntiThrash.js';
|
|
29
30
|
import { shouldReleaseOnComplete, planClaimOnSpawn, ownershipNonce } from '../core/ownershipFollowsLiveWork.js';
|
|
30
31
|
import { PrHandLease } from '../core/PrHandLease.js';
|
|
31
32
|
import { claimSuspensionExcludesPin } from '../core/TopicClaimAnnotationStore.js';
|
|
@@ -760,6 +761,12 @@ let _quotaAwareScheduler = null;
|
|
|
760
761
|
// Subscription & Auth Standard P1.3 — pre-limit proactive swap monitor. Null
|
|
761
762
|
// until wired (requires the scheduler; gated behind subscriptionPool.proactiveSwap).
|
|
762
763
|
let _proactiveSwapMonitor = null;
|
|
764
|
+
// swap-continuity-antithrash §3/§4 — the anti-thrash spine. The ledger + engine
|
|
765
|
+
// load and hydrate UNCONDITIONALLY at boot (R4-L3: reactive rows append
|
|
766
|
+
// regardless of antiThrash.enabled, so the index is warm at a mid-run flag
|
|
767
|
+
// flip). Null only when construction itself failed (non-fatal).
|
|
768
|
+
let _swapAntiThrashEngine = null;
|
|
769
|
+
let _swapWorkGate = null;
|
|
763
770
|
async function spawnSessionForTopic(sessionManager, telegram, sessionName, topicId, latestMessage, topicMemory, userProfile, precomputedContext,
|
|
764
771
|
/** Subscription & Auth Standard P1.3 (additive): launch under this account's
|
|
765
772
|
* config home + record its id (the quota-aware account-swap mechanism).
|
|
@@ -14360,17 +14367,96 @@ export async function startServer(options) {
|
|
|
14360
14367
|
// even without ANTHROPIC_API_KEY. Falls back to direct Anthropic API if a key is set
|
|
14361
14368
|
// and no intelligence is available.
|
|
14362
14369
|
let responseReviewGate;
|
|
14370
|
+
let reviewCanaryBattery;
|
|
14363
14371
|
if (config.responseReview?.enabled) {
|
|
14364
14372
|
if (sharedIntelligence) {
|
|
14365
14373
|
const { CoherenceGate } = await import('../core/CoherenceGate.js');
|
|
14374
|
+
const { buildConversationContext } = await import('../core/conversationContextWiring.js');
|
|
14375
|
+
// Context-aware reviewers (context-aware-outbound-review §D10): the
|
|
14376
|
+
// WIRING layer resolves the dev-gate (resolveDevAgentGate needs the
|
|
14377
|
+
// top-level developmentAgent flag, which the gate never receives) and
|
|
14378
|
+
// hands the gate a PRE-RESOLVED conversationalContext block through
|
|
14379
|
+
// the LIVE getter — the kill-switch (`conversationalContext.enabled:
|
|
14380
|
+
// false`) then takes effect at the NEXT evaluate, no restart.
|
|
14381
|
+
const resolveConversationalContext = () => {
|
|
14382
|
+
const cc = liveConfig.get('responseReview.conversationalContext', config.responseReview?.conversationalContext) ?? {};
|
|
14383
|
+
const dev = liveConfig.get('developmentAgent', config.developmentAgent);
|
|
14384
|
+
return {
|
|
14385
|
+
enabled: resolveDevAgentGate(typeof cc.enabled === 'boolean' ? cc.enabled : undefined, { developmentAgent: dev }),
|
|
14386
|
+
maxMessages: typeof cc.maxMessages === 'number' ? cc.maxMessages : undefined,
|
|
14387
|
+
maxCharsPerMessage: typeof cc.maxCharsPerMessage === 'number' ? cc.maxCharsPerMessage : undefined,
|
|
14388
|
+
maxTotalChars: typeof cc.maxTotalChars === 'number' ? cc.maxTotalChars : undefined,
|
|
14389
|
+
injectReviewers: Array.isArray(cc.injectReviewers) ? cc.injectReviewers : undefined,
|
|
14390
|
+
};
|
|
14391
|
+
};
|
|
14366
14392
|
responseReviewGate = new CoherenceGate({
|
|
14367
14393
|
config: config.responseReview,
|
|
14368
14394
|
stateDir: config.stateDir,
|
|
14369
14395
|
intelligence: sharedIntelligence,
|
|
14370
14396
|
relationships: relationships ?? undefined,
|
|
14371
14397
|
adaptiveTrust: adaptiveTrust ?? undefined,
|
|
14398
|
+
// LIVE config getter (round-1 M2 build items 1+2): carries BOTH the
|
|
14399
|
+
// CMT-1794 fail-closed kill-switch AND the resolved
|
|
14400
|
+
// conversationalContext block. Reads through LiveConfig so a config
|
|
14401
|
+
// edit applies at the next evaluate without a restart.
|
|
14402
|
+
liveConfig: () => ({
|
|
14403
|
+
failClosedOnCriticalAbstain: liveConfig.get('responseReview.failClosedOnCriticalAbstain', config.responseReview?.failClosedOnCriticalAbstain),
|
|
14404
|
+
conversationalContext: resolveConversationalContext(),
|
|
14405
|
+
}),
|
|
14406
|
+
// §D1 conversation source: TopicMemory rows + the topic's verified
|
|
14407
|
+
// operator binding, distilled by the wiring-layer principal
|
|
14408
|
+
// computation (buildConversationContext — Know Your Principal). Any
|
|
14409
|
+
// throw here is caught at acquisition inside the gate (§D5).
|
|
14410
|
+
conversationContextProvider: (topicId, limit) => {
|
|
14411
|
+
if (!topicMemory)
|
|
14412
|
+
return { messages: [], askLicenseMode: 'weak-corroboration-only' };
|
|
14413
|
+
const rows = topicMemory.getRecentMessages(topicId, limit);
|
|
14414
|
+
const operator = _agentServerRef?.getTopicOperatorStore()?.getOperator(topicId) ?? null;
|
|
14415
|
+
return buildConversationContext(rows, operator);
|
|
14416
|
+
},
|
|
14372
14417
|
});
|
|
14373
14418
|
console.log(pc.green(` Response review pipeline: enabled via shared IntelligenceProvider (${Object.keys(config.responseReview.reviewers ?? {}).length} reviewers configured)`));
|
|
14419
|
+
if (resolveConversationalContext().enabled) {
|
|
14420
|
+
console.log(pc.green(' Response review conversational context: LIVE (context-aware reviewers — dev-gate resolved)'));
|
|
14421
|
+
}
|
|
14422
|
+
else {
|
|
14423
|
+
console.log(pc.dim(' Response review conversational context: dark (dev-gate resolved off)'));
|
|
14424
|
+
}
|
|
14425
|
+
// §D9.4b canary-battery driver — replays through the Bearer-gated
|
|
14426
|
+
// /review/test route (the SAME plumbing real reviews use; no auth-less
|
|
14427
|
+
// bypass seam) and writes its per-run summary through the gate's §D8
|
|
14428
|
+
// writer. The trigger route 503s while the feature is dark.
|
|
14429
|
+
if (topicMemory) {
|
|
14430
|
+
const { ReviewCanaryBattery } = await import('../monitoring/ReviewCanaryBattery.js');
|
|
14431
|
+
const gateForBattery = responseReviewGate;
|
|
14432
|
+
reviewCanaryBattery = new ReviewCanaryBattery({
|
|
14433
|
+
topicMemory,
|
|
14434
|
+
callReviewTest: async (body) => {
|
|
14435
|
+
const resp = await fetch(`http://127.0.0.1:${config.port}/review/test`, {
|
|
14436
|
+
method: 'POST',
|
|
14437
|
+
headers: {
|
|
14438
|
+
'Content-Type': 'application/json',
|
|
14439
|
+
Authorization: `Bearer ${config.authToken ?? ''}`,
|
|
14440
|
+
},
|
|
14441
|
+
body: JSON.stringify(body),
|
|
14442
|
+
});
|
|
14443
|
+
let parsed = null;
|
|
14444
|
+
try {
|
|
14445
|
+
parsed = (await resp.json());
|
|
14446
|
+
}
|
|
14447
|
+
catch {
|
|
14448
|
+
// @silent-fallback-ok — a non-JSON body is reported as a null
|
|
14449
|
+
// body; the driver records the arm as an error (inconclusive),
|
|
14450
|
+
// never a silent skip.
|
|
14451
|
+
}
|
|
14452
|
+
return { status: resp.status, body: parsed };
|
|
14453
|
+
},
|
|
14454
|
+
writeDecisionRow: (row) => gateForBattery.appendDecisionRow(row),
|
|
14455
|
+
isFeatureLive: () => resolveConversationalContext().enabled,
|
|
14456
|
+
isObserveOnly: () => liveConfig.get('responseReview.observeOnly', config.responseReview?.observeOnly) === true,
|
|
14457
|
+
isTestEndpointEnabled: () => liveConfig.get('responseReview.testEndpointDisabled', config.responseReview?.testEndpointDisabled) !== true,
|
|
14458
|
+
});
|
|
14459
|
+
}
|
|
14374
14460
|
}
|
|
14375
14461
|
else {
|
|
14376
14462
|
console.warn(pc.yellow(` Response review pipeline: configured but no IntelligenceProvider available (path-constraints.md Rule 2 forbids direct API path)`));
|
|
@@ -14962,6 +15048,94 @@ export async function startServer(options) {
|
|
|
14962
15048
|
divergenceChecker = undefined;
|
|
14963
15049
|
}
|
|
14964
15050
|
}
|
|
15051
|
+
// ── Swap-continuity anti-thrash spine (swap-continuity-antithrash §3/§4) ──
|
|
15052
|
+
// SwapLedger + SwapAntiThrashEngine + SwapWorkGate. Constructed and
|
|
15053
|
+
// hydrated UNCONDITIONALLY (R4-L3): the ledger loads at every boot
|
|
15054
|
+
// regardless of antiThrash.enabled so the in-memory index (dwell /
|
|
15055
|
+
// reversal / breaker / frequency) is warm the moment the flag flips on
|
|
15056
|
+
// mid-run — the §7.1 half-enable trap closed for this key. All antiThrash
|
|
15057
|
+
// knobs are read LIVE per tick via the getter (the config object is
|
|
15058
|
+
// shared + mutated in place by config PATCHes).
|
|
15059
|
+
const antiThrashKnobsGetter = () => resolveAntiThrashKnobs(config.subscriptionPool?.proactiveSwap?.antiThrash, {
|
|
15060
|
+
thresholdPct: config.subscriptionPool?.proactiveSwap?.thresholdPct,
|
|
15061
|
+
tickMs: config.subscriptionPool?.proactiveSwap?.tickMs,
|
|
15062
|
+
});
|
|
15063
|
+
// swapContinuity (Piece 2, the work gate): the `enabled` KEY IS OMITTED
|
|
15064
|
+
// from shipped config on purpose — omission routes it through the
|
|
15065
|
+
// dev-agent gate (live on a dev agent, dark on the fleet; the #1001
|
|
15066
|
+
// anti-mechanism). `enabled` is RESTART-REQUIRED (§7.1 — the gate wiring
|
|
15067
|
+
// into SessionRefresh is constructor-injected); dryRun + numeric knobs
|
|
15068
|
+
// are read live per evaluation via the getters below.
|
|
15069
|
+
const swapContinuityEnabled = resolveDevAgentGate(config.subscriptionPool?.swapContinuity?.enabled, config);
|
|
15070
|
+
const swapContinuityKnobs = () => {
|
|
15071
|
+
const c = config.subscriptionPool?.swapContinuity;
|
|
15072
|
+
return {
|
|
15073
|
+
enabled: swapContinuityEnabled,
|
|
15074
|
+
dryRun: c?.dryRun ?? true,
|
|
15075
|
+
deferralCeilingMs: c?.deferralCeilingMs ?? 1_800_000,
|
|
15076
|
+
reactiveGraceMs: c?.reactiveGraceMs ?? 120_000,
|
|
15077
|
+
recheckMs: c?.recheckMs ?? 10_000,
|
|
15078
|
+
};
|
|
15079
|
+
};
|
|
15080
|
+
try {
|
|
15081
|
+
const { SwapLedger } = await import('../core/SwapLedger.js');
|
|
15082
|
+
const { SwapAntiThrashEngine, retentionBoundMs, crossKnobWarnings } = await import('../core/SwapAntiThrash.js');
|
|
15083
|
+
const { SwapWorkGate } = await import('../core/SwapWorkGate.js');
|
|
15084
|
+
const swapLedger = new SwapLedger({
|
|
15085
|
+
filePath: path.join(config.stateDir, 'state', 'swap-ledger.jsonl'),
|
|
15086
|
+
windowMs: () => retentionBoundMs(antiThrashKnobsGetter()),
|
|
15087
|
+
// Counts supplied at outage-resume time (the ledger-lost refusals the
|
|
15088
|
+
// writer itself could not record — §3.5/I5).
|
|
15089
|
+
outageRefusalCount: () => _swapAntiThrashEngine?.ledgerLostRefusalCount() ?? 0,
|
|
15090
|
+
machineId: _meshSelfId ?? 'local',
|
|
15091
|
+
logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
|
|
15092
|
+
});
|
|
15093
|
+
_swapAntiThrashEngine = new SwapAntiThrashEngine({
|
|
15094
|
+
ledger: swapLedger,
|
|
15095
|
+
getKnobs: antiThrashKnobsGetter,
|
|
15096
|
+
machineId: _meshSelfId ?? 'local',
|
|
15097
|
+
// P17: episode-deduped attention (the engine dedupes on episodeId;
|
|
15098
|
+
// the id passed here is the stable per-episode dedupe key).
|
|
15099
|
+
raiseAttention: (id, title, body) => {
|
|
15100
|
+
void telegram
|
|
15101
|
+
?.createAttentionItem({
|
|
15102
|
+
id,
|
|
15103
|
+
title,
|
|
15104
|
+
summary: body,
|
|
15105
|
+
category: 'subscription-pool',
|
|
15106
|
+
priority: 'HIGH',
|
|
15107
|
+
sourceContext: 'subscription-pool:swap-antithrash',
|
|
15108
|
+
})
|
|
15109
|
+
.catch(() => {
|
|
15110
|
+
/* @silent-fallback-ok: attention is best-effort; the ledger row is the durable trace */
|
|
15111
|
+
});
|
|
15112
|
+
},
|
|
15113
|
+
logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
|
|
15114
|
+
});
|
|
15115
|
+
_swapAntiThrashEngine.hydrate();
|
|
15116
|
+
// Cross-knob coherence warnings (§7, R4-L2 — warn-only, once at boot).
|
|
15117
|
+
// 15 min = the QuotaPoller's default cadence (pollIntervalMs ?? 15*60_000).
|
|
15118
|
+
for (const w of crossKnobWarnings(antiThrashKnobsGetter(), 15 * 60_000))
|
|
15119
|
+
console.warn(w);
|
|
15120
|
+
_swapWorkGate = new SwapWorkGate({
|
|
15121
|
+
checkSessionWorkState: (tmux) => sessionManager.checkSessionWorkState(tmux),
|
|
15122
|
+
getClaudeSessionId: (tmux) => state.listSessions({ status: 'running' }).find((s) => s.tmuxSession === tmux)?.claudeSessionId ?? null,
|
|
15123
|
+
hasActiveSubagents: (id) => subagentTracker.hasActiveSubagents(id),
|
|
15124
|
+
getActiveSubagents: (id) => subagentTracker.getActiveSubagents(id).map((r) => ({
|
|
15125
|
+
agentType: r.agentType,
|
|
15126
|
+
startedAt: r.startedAt,
|
|
15127
|
+
...(r.transcriptPath ? { transcriptPath: r.transcriptPath } : {}),
|
|
15128
|
+
})),
|
|
15129
|
+
});
|
|
15130
|
+
}
|
|
15131
|
+
catch (err) {
|
|
15132
|
+
// @silent-fallback-ok: cascade-isolation — a spine construction failure
|
|
15133
|
+
// must never 503 the server; behavior degrades to pre-brake semantics
|
|
15134
|
+
// (the legacy path) and re-attempts next boot.
|
|
15135
|
+
console.warn('[instar] swap-continuity anti-thrash spine init failed (non-fatal):', err);
|
|
15136
|
+
_swapAntiThrashEngine = null;
|
|
15137
|
+
_swapWorkGate = null;
|
|
15138
|
+
}
|
|
14965
15139
|
// SessionRefresh — agent-initiated session respawn. Requires a Telegram
|
|
14966
15140
|
// adapter (v1 scope: Telegram-bound sessions only). The respawner closure
|
|
14967
15141
|
// captures `topicMemory` by reference, so even if topicMemory is wired up
|
|
@@ -14979,6 +15153,43 @@ export async function startServer(options) {
|
|
|
14979
15153
|
state,
|
|
14980
15154
|
telegram: telegramRef,
|
|
14981
15155
|
topicResumeMap: _topicResumeMap,
|
|
15156
|
+
// swap-continuity-antithrash §4.2 — the in-flight work gate, bound at
|
|
15157
|
+
// THIS primitive (the funnel every session-killing mutation flows
|
|
15158
|
+
// through). Constructor-injected on purpose: `swapContinuity.enabled`
|
|
15159
|
+
// is restart-required (§7.1); dryRun + numeric knobs read live via
|
|
15160
|
+
// getKnobs. Null when the feature is dark on this install ⇒
|
|
15161
|
+
// byte-for-byte today's behavior (unconditional kill).
|
|
15162
|
+
workGateCtx: swapContinuityEnabled && _swapWorkGate
|
|
15163
|
+
? {
|
|
15164
|
+
probe: (tmux) => _swapWorkGate.probe(tmux),
|
|
15165
|
+
getKnobs: () => {
|
|
15166
|
+
const k = swapContinuityKnobs();
|
|
15167
|
+
return { enabled: k.enabled, dryRun: k.dryRun, reactiveGraceMs: k.reactiveGraceMs, recheckMs: k.recheckMs };
|
|
15168
|
+
},
|
|
15169
|
+
recordProceeded: (args) => _swapAntiThrashEngine?.recordProceeded(args),
|
|
15170
|
+
recordInteractiveRefusal: (args) => _swapAntiThrashEngine?.recordInteractiveRefusal(args),
|
|
15171
|
+
// §4.3(2) — Q4: v1 reads the in-memory exactly-once map (set on
|
|
15172
|
+
// inbound, cleared on reply); 'unknown' = the map/ledger is
|
|
15173
|
+
// unavailable (post-restart, or exactly-once ingress dark).
|
|
15174
|
+
// `messageLedger`/`currentInboundByTopic` are declared later in
|
|
15175
|
+
// this boot function and captured by reference — every call
|
|
15176
|
+
// happens post-boot, so the binding is initialized by then.
|
|
15177
|
+
resolveUnansweredInbound: (topicId) => {
|
|
15178
|
+
if (!messageLedger || !currentInboundByTopic)
|
|
15179
|
+
return 'unknown';
|
|
15180
|
+
const dedupeKey = currentInboundByTopic.get(String(topicId));
|
|
15181
|
+
if (!dedupeKey)
|
|
15182
|
+
return 'none';
|
|
15183
|
+
const entry = messageLedger.get(dedupeKey);
|
|
15184
|
+
if (!entry || entry.inputSnapshot === null)
|
|
15185
|
+
return 'unknown';
|
|
15186
|
+
const from = entry.senderEnvelope?.username ??
|
|
15187
|
+
entry.senderEnvelope?.firstName ??
|
|
15188
|
+
(entry.senderEnvelope?.userId !== undefined ? String(entry.senderEnvelope.userId) : 'unknown sender');
|
|
15189
|
+
return { body: entry.inputSnapshot, from, at: entry.receivedAt };
|
|
15190
|
+
},
|
|
15191
|
+
}
|
|
15192
|
+
: null,
|
|
14982
15193
|
// §10.5 Slack binding — SlackAdapter satisfies SlackRefreshBinding
|
|
14983
15194
|
// structurally (getChannelForSession / removeChannelResume /
|
|
14984
15195
|
// resolveChannelForSessionFromDisk). Null ⇒ Telegram-only, unchanged.
|
|
@@ -15042,6 +15253,30 @@ export async function startServer(options) {
|
|
|
15042
15253
|
_quotaAwareScheduler = new QuotaAwareScheduler({
|
|
15043
15254
|
listAccounts: () => subscriptionPool.list(),
|
|
15044
15255
|
softThresholdPct: config.subscriptionPool?.swapSoftThresholdPct,
|
|
15256
|
+
// swap-continuity-antithrash — the anti-thrash observation + execute-time
|
|
15257
|
+
// revalidation hooks. Reactive decision behavior is untouched (I6):
|
|
15258
|
+
// these only OBSERVE reactive swaps (dwell clock-start, hop alerts,
|
|
15259
|
+
// failed rows) and revalidate PROACTIVE explicit-target calls (§3.3).
|
|
15260
|
+
antiThrash: _swapAntiThrashEngine
|
|
15261
|
+
? {
|
|
15262
|
+
readingValid: (acct, nowMs) => readingValidity(acct, nowMs, antiThrashKnobsGetter().quotaFreshnessMs).valid,
|
|
15263
|
+
getKnobs: () => {
|
|
15264
|
+
const k = antiThrashKnobsGetter();
|
|
15265
|
+
return { thresholdPct: k.thresholdPct, targetHeadroomPct: k.targetHeadroomPct, minImprovementPct: k.minImprovementPct };
|
|
15266
|
+
},
|
|
15267
|
+
resolveCurrentAccountId: (sessionName) => state.listSessions({ status: 'running' }).find((s) => s.tmuxSession === sessionName)?.subscriptionAccountId ?? null,
|
|
15268
|
+
onReactiveExecuted: (a) => _swapAntiThrashEngine?.recordReactiveExecuted(a),
|
|
15269
|
+
onReactiveFailed: (a) => _swapAntiThrashEngine?.recordExecFailure({
|
|
15270
|
+
session: a.session,
|
|
15271
|
+
from: a.from,
|
|
15272
|
+
...(a.to ? { to: a.to } : {}),
|
|
15273
|
+
kind: 'reactive',
|
|
15274
|
+
errorClass: a.errorClass,
|
|
15275
|
+
nowMs: a.nowMs,
|
|
15276
|
+
}),
|
|
15277
|
+
onReactiveRateCapRefusal: (s, n) => _swapAntiThrashEngine?.noteReactiveRateCapRefusal(s, n),
|
|
15278
|
+
}
|
|
15279
|
+
: undefined,
|
|
15045
15280
|
refreshFn: async (o) => {
|
|
15046
15281
|
if (!_sessionRefresh)
|
|
15047
15282
|
return false;
|
|
@@ -15050,8 +15285,13 @@ export async function startServer(options) {
|
|
|
15050
15285
|
reason: o.reason,
|
|
15051
15286
|
configHome: o.configHome,
|
|
15052
15287
|
accountId: o.accountId,
|
|
15288
|
+
// I11: callerClass set ONLY server-internally — the scheduler is
|
|
15289
|
+
// the one caller that knows its lane (proactive funnel vs reactive).
|
|
15290
|
+
callerClass: o.callerClass,
|
|
15053
15291
|
});
|
|
15054
|
-
|
|
15292
|
+
// Object form: surfaces the structured refusal code so the
|
|
15293
|
+
// anti-thrash observation layer can classify failures (§3.1/§3.6).
|
|
15294
|
+
return r.ok ? { ok: true } : { ok: false, code: r.code };
|
|
15055
15295
|
},
|
|
15056
15296
|
onNoAlternate: (sessionName, exhaustedAccountId) => {
|
|
15057
15297
|
void telegramRef.createAttentionItem({
|
|
@@ -15133,6 +15373,18 @@ export async function startServer(options) {
|
|
|
15133
15373
|
maxSwapsPerCycle: proactiveCfg.maxSwapsPerCycle,
|
|
15134
15374
|
cooldownMs: proactiveCfg.cooldownMs,
|
|
15135
15375
|
tickMs: proactiveCfg.tickMs,
|
|
15376
|
+
// swap-continuity-antithrash §3 — the brake engine at the proactive
|
|
15377
|
+
// DECISION chokepoint. Knobs read LIVE per tick (§7.1). dryRun keeps
|
|
15378
|
+
// the legacy decision path byte-identical while the engine logs
|
|
15379
|
+
// would-refuse shadow rows (the rung-2 soak).
|
|
15380
|
+
antiThrash: _swapAntiThrashEngine
|
|
15381
|
+
? { engine: _swapAntiThrashEngine, getKnobs: antiThrashKnobsGetter }
|
|
15382
|
+
: undefined,
|
|
15383
|
+
// §4 — the in-flight work gate (proactive arm: defer, ceiling-drop).
|
|
15384
|
+
// The monitor owns the deferral lifecycle; the gate is stateless.
|
|
15385
|
+
workGate: _swapWorkGate
|
|
15386
|
+
? { probe: (s) => _swapWorkGate.probe(s), getContinuity: swapContinuityKnobs }
|
|
15387
|
+
: undefined,
|
|
15136
15388
|
logger: { log: (m) => console.log(m), warn: (m) => console.warn(m) },
|
|
15137
15389
|
});
|
|
15138
15390
|
_proactiveSwapMonitor.start();
|
|
@@ -19977,7 +20229,7 @@ export async function startServer(options) {
|
|
|
19977
20229
|
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) {
|
|
19978
20230
|
peers = (_listPoolMachines?.() ?? []).filter((m) => m.machineId !== _meshSelfId && !!m.lastKnownUrl).map((m) => ({ machineId: m.machineId, nickname: m.nickname ?? m.machineId, url: m.lastKnownUrl }));
|
|
19979
20231
|
} if (peers.length === 0)
|
|
19980
|
-
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, writeAdmission: writeAdmission ?? undefined, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, topicPinSkewQuarantine: _topicPinSkewQuarantine ?? undefined, topicPinFoldView: _topicPinFoldView ?? 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
|
|
20232
|
+
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, reviewCanaryBattery, messagingToneGate, outboundDedupGate, telemetryHeartbeat, pasteManager, featureRegistry, discoveryEvaluator, completionEvaluator, unifiedTrust, liveConfig, sharedStateLedger, ledgerSessionRegistry, worktreeManager, oidcEnrolledRepos: parallelDevConfig?.oidcEnrolledRepos, initiativeTracker, projectRoundRunner, projectDriftChecker, machineHeartbeat, machinePoolRegistry, ropeHealthMonitor, writeAdmission: writeAdmission ?? undefined, getInboundQueue: () => _inboundQueue, meshRpcDispatcher, workingSetPullCoordinator, commitmentReplicaStore, preferenceReplicaStore, replicatedRecordEmitter, conflictStore, rollbackUnmerge, droppedOriginRegistry, preferencesUnionReader, forwardCommitmentMutate, sessionOwnershipRegistry, topicPinStore: _topicPinStore ?? undefined, topicPinSkewQuarantine: _topicPinSkewQuarantine ?? undefined, topicPinFoldView: _topicPinFoldView ?? 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
|
|
19981
20233
|
// wired before the server existed; from here on inbound binds use the
|
|
19982
20234
|
// server's own store instance.
|
|
19983
20235
|
_agentServerRef = server;
|