instar 0.28.61 → 0.28.62
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/cli.js +0 -0
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +97 -21
- package/dist/commands/server.js.map +1 -1
- package/dist/core/types.d.ts +26 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/messaging/DeliveryRetryManager.d.ts.map +1 -1
- package/dist/messaging/DeliveryRetryManager.js +6 -4
- package/dist/messaging/DeliveryRetryManager.js.map +1 -1
- package/dist/messaging/MessageStore.d.ts +10 -0
- package/dist/messaging/MessageStore.d.ts.map +1 -1
- package/dist/messaging/MessageStore.js +52 -0
- package/dist/messaging/MessageStore.js.map +1 -1
- package/dist/messaging/SpawnRequestManager.d.ts +224 -19
- package/dist/messaging/SpawnRequestManager.d.ts.map +1 -1
- package/dist/messaging/SpawnRequestManager.js +600 -70
- package/dist/messaging/SpawnRequestManager.js.map +1 -1
- package/dist/messaging/types.d.ts +11 -1
- package/dist/messaging/types.d.ts.map +1 -1
- package/dist/messaging/types.js +7 -0
- package/dist/messaging/types.js.map +1 -1
- package/dist/monitoring/SessionWatchdog.d.ts.map +1 -1
- package/dist/monitoring/SessionWatchdog.js +23 -7
- package/dist/monitoring/SessionWatchdog.js.map +1 -1
- package/dist/monitoring/watchdog-notifications.d.ts +15 -0
- package/dist/monitoring/watchdog-notifications.d.ts.map +1 -0
- package/dist/monitoring/watchdog-notifications.js +24 -0
- package/dist/monitoring/watchdog-notifications.js.map +1 -0
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +56 -0
- package/dist/server/routes.js.map +1 -1
- package/dist/threadline/ThreadlineRouter.d.ts +64 -2
- package/dist/threadline/ThreadlineRouter.d.ts.map +1 -1
- package/dist/threadline/ThreadlineRouter.js +117 -9
- package/dist/threadline/ThreadlineRouter.js.map +1 -1
- package/dist/threadline/client/ThreadlineClient.d.ts +25 -1
- package/dist/threadline/client/ThreadlineClient.d.ts.map +1 -1
- package/dist/threadline/client/ThreadlineClient.js +79 -2
- package/dist/threadline/client/ThreadlineClient.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +50 -50
- package/upgrades/side-effects/threadline-cooldown-prereq-1-undelivered-phase.md +73 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.1-branded-trust-union.md +68 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.1-client-affinity.md +71 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.1-receiver-affinity.md +67 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.2-drain-loop.md +92 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.2-infra-soft-limiter.md +75 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.2-state-refactor.md +78 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.3-envelope-byte-cap.md +66 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.3-envelope-hash.md +71 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.3-truncation-and-global-cap.md +69 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.4-config-plumbing.md +77 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.4-drain-consumer-wiring.md +72 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.4-patch-endpoint.md +72 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.5-degradation-reporter.md +83 -0
- package/upgrades/side-effects/threadline-cooldown-sec4.5-triggeredby-plumbing.md +76 -0
- package/upgrades/side-effects/threadline-cooldown-spec-landing.md +48 -0
- package/upgrades/side-effects/watchdog-user-comfort.md +136 -0
- package/dist/core/InitiativeDigestJob.d.ts +0 -54
- package/dist/core/InitiativeDigestJob.d.ts.map +0 -1
- package/dist/core/InitiativeDigestJob.js +0 -128
- package/dist/core/InitiativeDigestJob.js.map +0 -1
- package/upgrades/NEXT.md +0 -53
- /package/upgrades/{0.28.61.md → 0.28.62.md} +0 -0
- /package/upgrades/side-effects/{scheduler-gate-exit-code.md → 0.28.61.md} +0 -0
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -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;AA4PH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;2DACuD;IACvD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA81CD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAsjJtE;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
|
@@ -45,6 +45,7 @@ import { QuotaNotifier } from '../monitoring/QuotaNotifier.js';
|
|
|
45
45
|
import { QuotaManager } from '../monitoring/QuotaManager.js';
|
|
46
46
|
import { classifySessionDeath } from '../monitoring/QuotaExhaustionDetector.js';
|
|
47
47
|
import { SessionWatchdog } from '../monitoring/SessionWatchdog.js';
|
|
48
|
+
import { formatWatchdogUserMessage } from '../monitoring/watchdog-notifications.js';
|
|
48
49
|
import { StallTriageNurse } from '../monitoring/StallTriageNurse.js';
|
|
49
50
|
import { TriageOrchestrator } from '../monitoring/TriageOrchestrator.js';
|
|
50
51
|
import { SessionMonitor } from '../monitoring/SessionMonitor.js';
|
|
@@ -3156,33 +3157,26 @@ export async function startServer(options) {
|
|
|
3156
3157
|
watchdog = new SessionWatchdog(config, sessionManager, state);
|
|
3157
3158
|
watchdog.intelligence = sharedIntelligence ?? null;
|
|
3158
3159
|
watchdog.on('intervention', (event) => {
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3160
|
+
// Routine recovery (Ctrl+C, SIGTERM) stays as console diagnostics only.
|
|
3161
|
+
// The user only hears when we had to force-kill (SIGKILL / session-kill) —
|
|
3162
|
+
// that's the "actual issue" threshold. See watchdog-notifications.ts.
|
|
3163
|
+
const userMsg = formatWatchdogUserMessage(event);
|
|
3164
|
+
if (!userMsg)
|
|
3165
|
+
return;
|
|
3162
3166
|
if (telegram) {
|
|
3163
3167
|
const topicId = telegram.getTopicForSession(event.sessionName);
|
|
3164
3168
|
if (topicId)
|
|
3165
|
-
telegram.sendToTopic(topicId,
|
|
3169
|
+
telegram.sendToTopic(topicId, userMsg).catch(() => { });
|
|
3166
3170
|
}
|
|
3167
3171
|
if (_slackAdapter) {
|
|
3168
3172
|
const channelId = _slackAdapter.getChannelForSession(event.sessionName);
|
|
3169
3173
|
if (channelId)
|
|
3170
|
-
_slackAdapter.sendToChannel(channelId,
|
|
3171
|
-
}
|
|
3172
|
-
});
|
|
3173
|
-
watchdog.on('recovery', (sessionName, fromLevel) => {
|
|
3174
|
-
const msg = `✅ Watchdog: session recovered (was at escalation level ${fromLevel})`;
|
|
3175
|
-
if (telegram) {
|
|
3176
|
-
const topicId = telegram.getTopicForSession(sessionName);
|
|
3177
|
-
if (topicId)
|
|
3178
|
-
telegram.sendToTopic(topicId, msg).catch(() => { });
|
|
3179
|
-
}
|
|
3180
|
-
if (_slackAdapter) {
|
|
3181
|
-
const channelId = _slackAdapter.getChannelForSession(sessionName);
|
|
3182
|
-
if (channelId)
|
|
3183
|
-
_slackAdapter.sendToChannel(channelId, msg).catch(() => { });
|
|
3174
|
+
_slackAdapter.sendToChannel(channelId, userMsg).catch(() => { });
|
|
3184
3175
|
}
|
|
3185
3176
|
});
|
|
3177
|
+
// Recovery events stay silent to the user. If we didn't announce the
|
|
3178
|
+
// problem (Ctrl+C / SIGTERM are now silent), announcing recovery is
|
|
3179
|
+
// noise. Intervention log still records it for diagnostics.
|
|
3186
3180
|
watchdog.start();
|
|
3187
3181
|
console.log(pc.green(' Session Watchdog enabled'));
|
|
3188
3182
|
}
|
|
@@ -4850,7 +4844,14 @@ export async function startServer(options) {
|
|
|
4850
4844
|
summarySentinel.start();
|
|
4851
4845
|
messageRouter.setSummarySentinel(summarySentinel);
|
|
4852
4846
|
// On-demand session spawning for message delivery (Phase 5)
|
|
4853
|
-
|
|
4847
|
+
// §4.4: spawn knobs are read from config.threadline.spawn — see
|
|
4848
|
+
// ThreadlineSpawnConfig in core/types.ts. All fields are optional and
|
|
4849
|
+
// fall through to manager-level defaults if absent.
|
|
4850
|
+
const spawnConfig = config.threadline?.spawn;
|
|
4851
|
+
// Forward-declared `let` so the onDrainReady callback can reference the
|
|
4852
|
+
// manager it belongs to (for re-entrant evaluate() calls during drain).
|
|
4853
|
+
let spawnManager;
|
|
4854
|
+
spawnManager = new SpawnRequestManager({
|
|
4854
4855
|
maxSessions: config.sessions.maxSessions ?? 5,
|
|
4855
4856
|
getActiveSessions: () => sessionManager.listRunningSessions(),
|
|
4856
4857
|
spawnSession: async (prompt, opts) => {
|
|
@@ -4859,7 +4860,9 @@ export async function startServer(options) {
|
|
|
4859
4860
|
prompt,
|
|
4860
4861
|
model: opts?.model,
|
|
4861
4862
|
maxDurationMinutes: opts?.maxDurationMinutes,
|
|
4862
|
-
|
|
4863
|
+
// §4.5: honor SpawnRequestManager's provenance tag so drain-spawned
|
|
4864
|
+
// sessions are distinguishable from inline-spawned ones in logs/stream.
|
|
4865
|
+
triggeredBy: opts?.triggeredBy ?? 'spawn-request',
|
|
4863
4866
|
});
|
|
4864
4867
|
return session.id;
|
|
4865
4868
|
},
|
|
@@ -4872,7 +4875,74 @@ export async function startServer(options) {
|
|
|
4872
4875
|
onEscalate: (request, reason) => {
|
|
4873
4876
|
notify('IMMEDIATE', 'messaging', `Spawn escalation: ${reason}\n Requester: ${request.requester.agent}\n Target: ${request.target.agent}`);
|
|
4874
4877
|
},
|
|
4878
|
+
// §4.5: emit degradation breadcrumbs on edge transitions.
|
|
4879
|
+
onDegradation: (event) => {
|
|
4880
|
+
try {
|
|
4881
|
+
const reporter = DegradationReporter.getInstance();
|
|
4882
|
+
if (event.kind === 'spawn-penalty-tripped') {
|
|
4883
|
+
reporter.report({
|
|
4884
|
+
feature: 'Threadline.SpawnPenalty',
|
|
4885
|
+
primary: `Open spawn slot for peer "${event.agent}"`,
|
|
4886
|
+
fallback: `Spawn blocked for ${Math.round(event.penaltyMs / 1000)}s after ${event.consecutiveFailures} consecutive agent-attributable failures`,
|
|
4887
|
+
reason: `Peer "${event.agent}" tripped the consecutive-failure penalty (3 strikes)`,
|
|
4888
|
+
impact: 'Peer cannot spawn sessions until penalty clears. Successful inbound spawn from a different peer is unaffected.',
|
|
4889
|
+
});
|
|
4890
|
+
}
|
|
4891
|
+
else if (event.kind === 'spawn-infra-degraded') {
|
|
4892
|
+
reporter.report({
|
|
4893
|
+
feature: 'Threadline.SpawnInfraDegraded',
|
|
4894
|
+
primary: `Full queue admission (cap 10) for peer "${event.agent}"`,
|
|
4895
|
+
fallback: `Degraded admission (cap ${spawnConfig?.degradedMaxQueuedPerAgent ?? 1}) for ${Math.round(event.degradationMs / 60_000)}min`,
|
|
4896
|
+
reason: `Peer "${event.agent}" tripped the infra-failure soft limiter (${event.failureCount} non-attributable failures in 10min)`,
|
|
4897
|
+
impact: 'Peer\'s queue depth is capped; older messages are dropped. No blame attribution.',
|
|
4898
|
+
});
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
catch (err) {
|
|
4902
|
+
console.warn(`[spawn-manager] degradation reporter failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4903
|
+
}
|
|
4904
|
+
},
|
|
4905
|
+
// §4.4: optional knobs from config.
|
|
4906
|
+
cooldownMs: spawnConfig?.cooldownMs,
|
|
4907
|
+
maxDrainsPerTick: spawnConfig?.maxDrainsPerTick,
|
|
4908
|
+
maxEnvelopeBytes: spawnConfig?.maxEnvelopeBytes,
|
|
4909
|
+
maxGlobalQueued: spawnConfig?.maxGlobalQueued,
|
|
4910
|
+
degradedMaxQueuedPerAgent: spawnConfig?.degradedMaxQueuedPerAgent,
|
|
4911
|
+
// §4.4 commit 2 + §4.5: drain-loop consumer wiring.
|
|
4912
|
+
// When the drain loop finds an agent ready (cooldown cleared + queued
|
|
4913
|
+
// messages present), this callback re-invokes evaluate() with a
|
|
4914
|
+
// synthetic SpawnRequest tagged `triggeredBy: 'spawn-request-drain'`.
|
|
4915
|
+
// The real queued context is reattached by SpawnRequestManager.evaluate
|
|
4916
|
+
// via its internal drainQueue() call. Stub session/machine values:
|
|
4917
|
+
// requester.session/machine isn't preserved per-message — those fields
|
|
4918
|
+
// are only used in the spawn prompt template for display.
|
|
4919
|
+
onDrainReady: async (agent) => {
|
|
4920
|
+
try {
|
|
4921
|
+
const result = await spawnManager.evaluate({
|
|
4922
|
+
requester: { agent, session: 'drain', machine: 'drain' },
|
|
4923
|
+
target: { agent: config.projectName, machine: os.hostname() },
|
|
4924
|
+
reason: `Drain re-attempt for queued messages from ${agent}`,
|
|
4925
|
+
priority: 'medium',
|
|
4926
|
+
triggeredBy: 'spawn-request-drain',
|
|
4927
|
+
});
|
|
4928
|
+
if (!result.approved) {
|
|
4929
|
+
console.log(`[spawn-manager] drain re-attempt for ${agent} not approved: ${result.reason}`);
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
catch (err) {
|
|
4933
|
+
console.warn(`[spawn-manager] drain re-attempt for ${agent} threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
4934
|
+
}
|
|
4935
|
+
},
|
|
4875
4936
|
});
|
|
4937
|
+
// §4.4 kill switch: drain loop runs unless explicitly disabled in config.
|
|
4938
|
+
// Wired here so emergency rollback is a config flip, not a code change.
|
|
4939
|
+
if (spawnConfig?.drainEnabled !== false) {
|
|
4940
|
+
spawnManager.start();
|
|
4941
|
+
console.log(`[spawn-manager] drain loop started (tick=${spawnManager.getDrainTickMs()}ms)`);
|
|
4942
|
+
}
|
|
4943
|
+
else {
|
|
4944
|
+
console.log('[spawn-manager] drain loop disabled by config.threadline.spawn.drainEnabled=false');
|
|
4945
|
+
}
|
|
4876
4946
|
// Threadline Router — handles threaded cross-agent conversations via relay
|
|
4877
4947
|
const threadlineRouter = new ThreadlineRouter(messageRouter, spawnManager, threadResumeMap, messageStore, { localAgent: config.projectName, localMachine: os.hostname() }, null, // autonomyGate
|
|
4878
4948
|
messageDelivery);
|
|
@@ -5178,7 +5248,12 @@ export async function startServer(options) {
|
|
|
5178
5248
|
transport: { protocol: 'relay', origin: { agent: senderFingerprint, machine: 'relay' }, nonce: `${crypto.randomUUID()}:${new Date().toISOString()}`, timestamp: new Date().toISOString() },
|
|
5179
5249
|
delivery: { status: 'delivered', attempts: 1, lastAttempt: new Date().toISOString() },
|
|
5180
5250
|
};
|
|
5181
|
-
const relayContext = {
|
|
5251
|
+
const relayContext = {
|
|
5252
|
+
trust: { kind: 'plaintext-tofu', senderFingerprint },
|
|
5253
|
+
senderFingerprint,
|
|
5254
|
+
senderName,
|
|
5255
|
+
trustLevel,
|
|
5256
|
+
};
|
|
5182
5257
|
let result = await threadlineRouter.handleInboundMessage(envelope, relayContext);
|
|
5183
5258
|
// Fallback for threadId-less messages
|
|
5184
5259
|
if (!result.handled && !msg.threadId) {
|
|
@@ -5687,6 +5762,7 @@ export async function startServer(options) {
|
|
|
5687
5762
|
await notificationBatcher.flushAll(); // Drain pending notifications before exit
|
|
5688
5763
|
notificationBatcher.stop();
|
|
5689
5764
|
retryManager.stop();
|
|
5765
|
+
spawnManager.dispose(); // §4.4: stop drain loop + clear DRR state
|
|
5690
5766
|
summarySentinel.stop();
|
|
5691
5767
|
memoryMonitor.stop();
|
|
5692
5768
|
caffeinateManager.stop();
|