instar 1.3.558 → 1.3.560
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 +59 -5
- package/dist/commands/server.js.map +1 -1
- package/dist/core/AutonomousSessions.d.ts +12 -0
- package/dist/core/AutonomousSessions.d.ts.map +1 -1
- package/dist/core/AutonomousSessions.js +23 -0
- package/dist/core/AutonomousSessions.js.map +1 -1
- package/dist/core/WorkEvidence.d.ts +13 -0
- package/dist/core/WorkEvidence.d.ts.map +1 -1
- package/dist/core/WorkEvidence.js +13 -0
- package/dist/core/WorkEvidence.js.map +1 -1
- package/dist/monitoring/ReapNotifier.d.ts +19 -0
- package/dist/monitoring/ReapNotifier.d.ts.map +1 -1
- package/dist/monitoring/ReapNotifier.js +65 -3
- package/dist/monitoring/ReapNotifier.js.map +1 -1
- package/dist/monitoring/ResumeQueueDrainer.d.ts +9 -0
- package/dist/monitoring/ResumeQueueDrainer.d.ts.map +1 -1
- package/dist/monitoring/ResumeQueueDrainer.js +14 -0
- package/dist/monitoring/ResumeQueueDrainer.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.559.md +48 -0
- package/upgrades/1.3.560.md +57 -0
- package/upgrades/side-effects/honest-session-recycle.md +140 -0
- package/upgrades/side-effects/resume-idle-autonomous-on-reap.md +146 -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;AAiCH,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;AAiH7D,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;AAy3CD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,cAAc,EAAE,cAAc,EAC9B,YAAY,CAAC,EAAE,YAAY,EAC3B,WAAW,CAAC,EAAE,WAAW,EACzB,WAAW,CAAC,EAAE,WAAW,EACzB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EAGvE,UAAU,CAAC,EAAE,MAAM,OAAO,8BAA8B,EAAE,WAAW,GAAG,IAAI,EAK5E,qBAAqB,CAAC,EAAE,MAAM,OAAO,gCAAgC,EAAE,kBAAkB,GAAG,IAAI,EAKhG,mBAAmB,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACpD,IAAI,CA8eN;AA2lBD,wBAAsB,WAAW,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAg5btE;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
|
@@ -22,7 +22,8 @@ import { TopicProfileOrchestrator, resolvedToApplied, } from '../core/TopicProfi
|
|
|
22
22
|
import { CodexResumeMap } from '../core/CodexResumeMap.js';
|
|
23
23
|
import { paneIdleWithEmptyInput } from '../core/ModelSwapService.js';
|
|
24
24
|
import { escalatedModelIds, normalizeTierEscalationConfig } from '../core/ModelTierEscalation.js';
|
|
25
|
-
import { activeAutonomousJobs } from '../core/AutonomousSessions.js';
|
|
25
|
+
import { activeAutonomousJobs, autonomousRunRemainingForTopic } from '../core/AutonomousSessions.js';
|
|
26
|
+
import { AGE_LIMIT_ACTIVE_RUN_REASON } from '../core/WorkEvidence.js';
|
|
26
27
|
import { TopicProfileTransferCarrier, createTopicProfilePullHandler } from '../core/TopicProfileTransferCarrier.js';
|
|
27
28
|
import { closeAllSqlite } from '../core/SqliteRegistry.js';
|
|
28
29
|
import { SessionManager } from '../core/SessionManager.js';
|
|
@@ -6049,6 +6050,24 @@ export async function startServer(options) {
|
|
|
6049
6050
|
quietHoursEndAt: (now) => notificationBatcher.quietHoursEndAt(now),
|
|
6050
6051
|
summaryReleaseAt: (now) => notificationBatcher.nextSummaryReleaseAt(now),
|
|
6051
6052
|
resumeQueuedFor: (tmuxSession) => resumeQueuedForSession(tmuxSession),
|
|
6053
|
+
// Honest-recycle (honest-session-recycle-spec): tell ReapNotifier whether
|
|
6054
|
+
// this session's topic has an ACTIVE autonomous run (and how long is left),
|
|
6055
|
+
// so an age-limit RECYCLE of a still-active run reads as a continuation
|
|
6056
|
+
// instead of a "reached its maximum allowed runtime" death. Read here at
|
|
6057
|
+
// the wiring layer (which has the autonomous state) — SessionManager's kill
|
|
6058
|
+
// chokepoint is untouched. Returns null ⇒ legacy death copy (safe default).
|
|
6059
|
+
autonomousRunActiveFor: (tmuxSession) => {
|
|
6060
|
+
try {
|
|
6061
|
+
const t = telegram?.getTopicForSession(tmuxSession);
|
|
6062
|
+
if (t == null)
|
|
6063
|
+
return null;
|
|
6064
|
+
return autonomousRunRemainingForTopic(config.stateDir, t);
|
|
6065
|
+
}
|
|
6066
|
+
catch {
|
|
6067
|
+
// Fail toward the legacy death copy — never silence the notice.
|
|
6068
|
+
return null;
|
|
6069
|
+
}
|
|
6070
|
+
},
|
|
6052
6071
|
reportDegradation: (reason, impact) => {
|
|
6053
6072
|
try {
|
|
6054
6073
|
DegradationReporter.getInstance().report({
|
|
@@ -6179,7 +6198,13 @@ export async function startServer(options) {
|
|
|
6179
6198
|
raiseAggregated: raiseResumeAggregated,
|
|
6180
6199
|
}, {
|
|
6181
6200
|
enabled: rqCfg.enabled ?? true,
|
|
6182
|
-
|
|
6201
|
+
// Live-on-dev (no-dark-on-dev directive, topic 13481): the queue ships
|
|
6202
|
+
// observe-only (dryRun:true) fleet-wide, but resolves to LIVE
|
|
6203
|
+
// (dryRun:false) on a development agent so the resume-idle-autonomous
|
|
6204
|
+
// fix is genuinely exercised on Echo. An explicit operator
|
|
6205
|
+
// monitoring.resumeQueue.dryRun still wins; the resume-queue keys stay
|
|
6206
|
+
// CODE-defaulted (never frozen into ConfigDefaults — preserves the fleet flip).
|
|
6207
|
+
dryRun: rqCfg.dryRun ?? !resolveDevAgentGate(undefined, config),
|
|
6183
6208
|
maxAttempts: rqCfg.maxAttempts ?? 3,
|
|
6184
6209
|
maxResurrections: rqCfg.maxResurrections ?? 2,
|
|
6185
6210
|
entryTtlHours: rqCfg.entryTtlHours ?? 24,
|
|
@@ -6250,6 +6275,15 @@ export async function startServer(options) {
|
|
|
6250
6275
|
catch { /* no flag */ }
|
|
6251
6276
|
return Math.max(perTopic, globalOperatorStopAt, flagAt) > since;
|
|
6252
6277
|
},
|
|
6278
|
+
// Resume-idle-autonomous fix (spec: resume-idle-autonomous-on-reap.md):
|
|
6279
|
+
// drain-time liveness re-check for an entry admitted via the
|
|
6280
|
+
// age-limit-active-run path. Returns true (= run FINISHED) when the topic's
|
|
6281
|
+
// autonomous run is no longer active (completed OR window elapsed) since
|
|
6282
|
+
// enqueue → the drainer invalidates `autonomous-run-finished`, never a
|
|
6283
|
+
// spawn. Reads the LOCAL autonomous-run state file (same vantage that
|
|
6284
|
+
// admitted the entry). A throw resolves to NOT-finished inside the drainer's
|
|
6285
|
+
// safeBool (SAFE side — the revival still passes the other reality gates).
|
|
6286
|
+
autonomousRunFinished: (topicId) => autonomousRunRemainingForTopic(config.stateDir, topicId) == null,
|
|
6253
6287
|
jobCheck: (slug, queuedAtIso) => {
|
|
6254
6288
|
if (!scheduler)
|
|
6255
6289
|
return { ok: false, why: 'scheduler-unavailable' };
|
|
@@ -6363,7 +6397,7 @@ export async function startServer(options) {
|
|
|
6363
6397
|
tier1Check: rqCfg.tier1Check ?? true,
|
|
6364
6398
|
});
|
|
6365
6399
|
resumeDrainer.start();
|
|
6366
|
-
console.log(pc.green(` ResumeQueue started (${rqCfg.dryRun ??
|
|
6400
|
+
console.log(pc.green(` ResumeQueue started (${(rqCfg.dryRun ?? !resolveDevAgentGate(undefined, config)) ? 'dry-run observe-only' : 'LIVE'}; drainer ${rqCfg.drainIntervalSec ?? 60}s tick)`));
|
|
6367
6401
|
// Boot reconciliation half 2 (R2.4): re-enqueue recent mid-work reaps
|
|
6368
6402
|
// the queue lost to a crash window. Deferred 30s so the Telegram
|
|
6369
6403
|
// adapter (topic resolution) exists; topic-bound candidates only —
|
|
@@ -6438,6 +6472,26 @@ export async function startServer(options) {
|
|
|
6438
6472
|
const jobDef = e.session.jobSlug
|
|
6439
6473
|
? scheduler?.getJobs().find((j) => j.slug === e.session.jobSlug)
|
|
6440
6474
|
: undefined;
|
|
6475
|
+
// Resume-idle-autonomous fix (spec: resume-idle-autonomous-on-reap.md):
|
|
6476
|
+
// an age-limit reap fires precisely when an autonomous session is IDLE
|
|
6477
|
+
// between turns, so its process-based work evidence is empty by
|
|
6478
|
+
// construction → it is never enqueued for revival, and an away-operator's
|
|
6479
|
+
// run sits dead until the next message. When the reaped topic still has an
|
|
6480
|
+
// ACTIVE autonomous run, the live run IS the work evidence: append the TRUE
|
|
6481
|
+
// `build-or-autonomous-active` strong signal (re-clamped by considerEnqueue)
|
|
6482
|
+
// and tag the reason so the drainer can re-verify liveness at drain time.
|
|
6483
|
+
// Guard ordering is load-bearing: the cold-path autonomousRunRemainingForTopic
|
|
6484
|
+
// read runs ONLY on the literal `age-limit` reason (every other reap pays
|
|
6485
|
+
// zero added cost), and the whole block sits inside the existing try/catch so
|
|
6486
|
+
// a throw fails toward NO injection (status-quo no-revive), never a spawn.
|
|
6487
|
+
let candidateReason = e.reason;
|
|
6488
|
+
let candidateWorkEvidence = e.workEvidence ?? [];
|
|
6489
|
+
if (e.reason === 'age-limit' &&
|
|
6490
|
+
topicId != null &&
|
|
6491
|
+
autonomousRunRemainingForTopic(config.stateDir, topicId) != null) {
|
|
6492
|
+
candidateReason = AGE_LIMIT_ACTIVE_RUN_REASON;
|
|
6493
|
+
candidateWorkEvidence = [...candidateWorkEvidence, 'build-or-autonomous-active'];
|
|
6494
|
+
}
|
|
6441
6495
|
resumeQueue.considerEnqueue({
|
|
6442
6496
|
sessionName: e.session.name,
|
|
6443
6497
|
tmuxSession: e.session.tmuxSession,
|
|
@@ -6446,10 +6500,10 @@ export async function startServer(options) {
|
|
|
6446
6500
|
jobResumeOptIn: jobDef?.resumeOnReap === true,
|
|
6447
6501
|
resumeUuid: topicId != null ? (_topicResumeMap?.get(topicId) ?? null) : null,
|
|
6448
6502
|
cwd: e.session.cwd ?? _projectDir,
|
|
6449
|
-
reason:
|
|
6503
|
+
reason: candidateReason,
|
|
6450
6504
|
disposition: e.disposition ?? 'terminal',
|
|
6451
6505
|
origin: e.origin ?? 'autonomous',
|
|
6452
|
-
workEvidence:
|
|
6506
|
+
workEvidence: candidateWorkEvidence,
|
|
6453
6507
|
});
|
|
6454
6508
|
}
|
|
6455
6509
|
}
|