instar 1.3.651 → 1.3.652
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 +120 -1
- package/dist/commands/server.js.map +1 -1
- package/dist/core/ReapGuard.d.ts +13 -1
- package/dist/core/ReapGuard.d.ts.map +1 -1
- package/dist/core/ReapGuard.js +86 -30
- package/dist/core/ReapGuard.js.map +1 -1
- package/dist/core/SessionManager.d.ts +11 -0
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +30 -4
- package/dist/core/SessionManager.js.map +1 -1
- 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/gapBCommitmentEvidence.d.ts +9 -0
- package/dist/core/gapBCommitmentEvidence.d.ts.map +1 -1
- package/dist/core/gapBCommitmentEvidence.js +20 -0
- package/dist/core/gapBCommitmentEvidence.js.map +1 -1
- package/dist/core/types.d.ts +11 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/monitoring/SessionReaper.d.ts +118 -7
- package/dist/monitoring/SessionReaper.d.ts.map +1 -1
- package/dist/monitoring/SessionReaper.js +302 -101
- package/dist/monitoring/SessionReaper.js.map +1 -1
- package/dist/monitoring/closeoutLivenessSnapshot.d.ts +143 -0
- package/dist/monitoring/closeoutLivenessSnapshot.d.ts.map +1 -0
- package/dist/monitoring/closeoutLivenessSnapshot.js +207 -0
- package/dist/monitoring/closeoutLivenessSnapshot.js.map +1 -0
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +3 -3
- package/upgrades/1.3.652.md +18 -0
- package/upgrades/side-effects/post-transfer-closeout-correctness.md +43 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0CH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAwH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA+EtD;;;;;;;;;;;;;;;;;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;AAy4CD,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,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA0CH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAU3D,OAAO,EAAE,eAAe,EAAiC,MAAM,iCAAiC,CAAC;AAwBjG,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAGvD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAwH7D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AA+EtD;;;;;;;;;;;;;;;;;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;AAy4CD,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,CA89ftE;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
|
@@ -32,7 +32,7 @@ import { paneIdleWithEmptyInput } from '../core/ModelSwapService.js';
|
|
|
32
32
|
import { escalatedModelIds, normalizeTierEscalationConfig } from '../core/ModelTierEscalation.js';
|
|
33
33
|
import { activeAutonomousJobs, autonomousRunRemainingForTopic, listAutonomousJobs } from '../core/AutonomousSessions.js';
|
|
34
34
|
import { AGE_LIMIT_ACTIVE_RUN_REASON, COMMITMENT_ACTIVE_RUN_REASON } from '../core/WorkEvidence.js';
|
|
35
|
-
import { gapBEligibleForTopic, recentUserMessageFromHistory, resolveGapBInjectionGate, decideGapBInjection } from '../core/gapBCommitmentEvidence.js';
|
|
35
|
+
import { gapBEligibleForTopic, recentUserMessageFromHistory, recentUserMessageAtFromHistory, resolveGapBInjectionGate, decideGapBInjection } from '../core/gapBCommitmentEvidence.js';
|
|
36
36
|
import { TopicProfileTransferCarrier, createTopicProfilePullHandler } from '../core/TopicProfileTransferCarrier.js';
|
|
37
37
|
import { closeAllSqlite } from '../core/SqliteRegistry.js';
|
|
38
38
|
import { SessionManager } from '../core/SessionManager.js';
|
|
@@ -14087,6 +14087,96 @@ export async function startServer(options) {
|
|
|
14087
14087
|
config: { residueDenylist: ysCfg.residueDenylist, cacheTtlMs: ysCfg.dirtyCheckCacheTtlMs },
|
|
14088
14088
|
});
|
|
14089
14089
|
}
|
|
14090
|
+
// ── Post-transfer closeout correctness (F1) ───────────────────────────────
|
|
14091
|
+
// closeoutLivenessGate: when on, the post-transfer closeout no longer
|
|
14092
|
+
// terminates the live local session on a stale/unverified ownership record —
|
|
14093
|
+
// it verifies the owning machine ACTUALLY has a live session for the topic via
|
|
14094
|
+
// a machine-local liveness snapshot before shedding the leftover. Ships dark
|
|
14095
|
+
// fleet-wide, LIVE on a dev agent via resolveDevAgentGate. When OFF the snapshot
|
|
14096
|
+
// is never built and the new deps are left absent (closeout byte-identical).
|
|
14097
|
+
// Spec: docs/specs/post-transfer-closeout-correctness.md.
|
|
14098
|
+
const _closeoutLivenessGate = resolveDevAgentGate(config.monitoring?.sessionReaper?.closeoutLivenessGate, config);
|
|
14099
|
+
let _closeoutSnapshot;
|
|
14100
|
+
// The combined ATOMIC owner read the gated closeout consumes — ONE registry
|
|
14101
|
+
// read returning the STABLE machineId (liveness key) AND the display label
|
|
14102
|
+
// (audit text), guaranteeing they describe the same owner from one instant.
|
|
14103
|
+
const _topicOwnerElsewhereInfo = (topicId) => {
|
|
14104
|
+
try {
|
|
14105
|
+
const reg = sessionOwnershipRegistry;
|
|
14106
|
+
const self = _meshSelfId;
|
|
14107
|
+
if (!reg || !self)
|
|
14108
|
+
return null;
|
|
14109
|
+
const machineId = reg.ownerOf(String(topicId));
|
|
14110
|
+
if (!machineId || machineId === self)
|
|
14111
|
+
return null;
|
|
14112
|
+
const displayName = machinePoolRegistry?.getCapacity(machineId)?.nickname ?? machineId;
|
|
14113
|
+
return { machineId, displayName };
|
|
14114
|
+
}
|
|
14115
|
+
catch {
|
|
14116
|
+
return null; /* @silent-fallback-ok — pool not wired yet → rule inert (withhold) */
|
|
14117
|
+
}
|
|
14118
|
+
};
|
|
14119
|
+
if (_closeoutLivenessGate) {
|
|
14120
|
+
const { CloseoutLivenessSnapshot } = await import('../monitoring/closeoutLivenessSnapshot.js');
|
|
14121
|
+
const _reaperTick = config.monitoring?.sessionReaper?.tickIntervalSec ?? 120;
|
|
14122
|
+
_closeoutSnapshot = new CloseoutLivenessSnapshot({
|
|
14123
|
+
resolvePeerUrls: () => _resolvePeerUrls?.() ?? [],
|
|
14124
|
+
// Reuse the proven per-peer GET /sessions fetch primitive (5s timeout,
|
|
14125
|
+
// same shape as the pool route's fan-out). Rejects on any failure so the
|
|
14126
|
+
// entry ages to stale → 'unknown' (fail-closed).
|
|
14127
|
+
fetchPeerSessions: async (peer) => {
|
|
14128
|
+
const r = await fetch(`${peer.url}/sessions`, {
|
|
14129
|
+
headers: { Authorization: `Bearer ${config.authToken}` },
|
|
14130
|
+
signal: AbortSignal.timeout(5000),
|
|
14131
|
+
});
|
|
14132
|
+
if (!r.ok)
|
|
14133
|
+
throw new Error(`HTTP ${r.status}`);
|
|
14134
|
+
return (await r.json());
|
|
14135
|
+
},
|
|
14136
|
+
// Owner set = distinct machineId of every owned-elsewhere topic that has
|
|
14137
|
+
// a live LOCAL leftover here (the exact set the closeout could act on).
|
|
14138
|
+
ownerSet: () => {
|
|
14139
|
+
const owners = new Set();
|
|
14140
|
+
try {
|
|
14141
|
+
for (const s of sessionManager.listRunningSessions()) {
|
|
14142
|
+
const t = _resolveTopic(s.tmuxSession);
|
|
14143
|
+
if (t == null)
|
|
14144
|
+
continue;
|
|
14145
|
+
const info = _topicOwnerElsewhereInfo(t);
|
|
14146
|
+
if (info)
|
|
14147
|
+
owners.add(info.machineId);
|
|
14148
|
+
}
|
|
14149
|
+
}
|
|
14150
|
+
catch { /* @silent-fallback-ok — degrade to whatever was already pending */ }
|
|
14151
|
+
return [...owners];
|
|
14152
|
+
},
|
|
14153
|
+
now: () => Date.now(),
|
|
14154
|
+
raiseAttention: (item) => {
|
|
14155
|
+
try {
|
|
14156
|
+
if (!telegram)
|
|
14157
|
+
return;
|
|
14158
|
+
void telegram.createAttentionItem({
|
|
14159
|
+
id: item.id, title: item.title, summary: item.summary, description: item.description,
|
|
14160
|
+
category: 'sessions', priority: 'NORMAL',
|
|
14161
|
+
sourceContext: 'session-reaper:closeout-snapshot-breaker',
|
|
14162
|
+
}).catch(() => { });
|
|
14163
|
+
}
|
|
14164
|
+
catch { /* @silent-fallback-ok — telegram not wired (TDZ) → audit-only */ }
|
|
14165
|
+
},
|
|
14166
|
+
audit: reaperAuditSink(config.stateDir),
|
|
14167
|
+
}, { tickIntervalSec: _reaperTick });
|
|
14168
|
+
// Level-triggered on the reaper cadence with ±10% jitter (anti-herd). Async
|
|
14169
|
+
// refresh; the closeout always reads the PREVIOUS snapshot, never a fetch it
|
|
14170
|
+
// triggers this tick. A thrown pass is swallowed (previous snapshot ages to
|
|
14171
|
+
// stale → 'unknown'); the loop is never wedged.
|
|
14172
|
+
const _jitter = 1 + (Math.random() * 0.2 - 0.1);
|
|
14173
|
+
const _snapshotTimer = setInterval(() => {
|
|
14174
|
+
void _closeoutSnapshot.refresh().catch(() => { });
|
|
14175
|
+
}, Math.round(_reaperTick * 1000 * _jitter));
|
|
14176
|
+
if (typeof _snapshotTimer.unref === 'function')
|
|
14177
|
+
_snapshotTimer.unref();
|
|
14178
|
+
console.log(pc.green(' SessionReaper closeoutLivenessGate ON (post-transfer closeout liveness-gated — live)'));
|
|
14179
|
+
}
|
|
14090
14180
|
const sessionReaper = new SessionReaper({
|
|
14091
14181
|
...reapGuardDeps,
|
|
14092
14182
|
dirtyCheck: _yieldSafetyDirtyCheck,
|
|
@@ -14133,6 +14223,8 @@ export async function startServer(options) {
|
|
|
14133
14223
|
},
|
|
14134
14224
|
terminate: (id, reason, opts) => sessionManager.terminateSession(id, reason, {
|
|
14135
14225
|
bypassActiveProcessKeep: opts?.bypassActiveProcessKeep,
|
|
14226
|
+
bypassRecentUserMessageForConfirmedMove: opts?.bypassRecentUserMessageForConfirmedMove,
|
|
14227
|
+
workEvidence: opts?.workEvidence,
|
|
14136
14228
|
}),
|
|
14137
14229
|
markReaping: (id) => sessionManager.markReaping(id),
|
|
14138
14230
|
clearReaping: (id) => sessionManager.clearReaping(id),
|
|
@@ -14161,6 +14253,28 @@ export async function startServer(options) {
|
|
|
14161
14253
|
return null; /* @silent-fallback-ok — pool not wired yet → rule inert */
|
|
14162
14254
|
}
|
|
14163
14255
|
},
|
|
14256
|
+
// Post-transfer closeout correctness (F1): the ATOMIC combined owner read
|
|
14257
|
+
// the gated closeout uses (stable machineId + display label from ONE
|
|
14258
|
+
// registry read). Always constructed (a pure read helper); the closeout
|
|
14259
|
+
// only consults it on the gated path. Returns null when the pool is dark.
|
|
14260
|
+
topicOwnerElsewhereInfo: _topicOwnerElsewhereInfo,
|
|
14261
|
+
// Post-transfer closeout correctness (F1): the liveness verdict, read from
|
|
14262
|
+
// the machine-local snapshot (NOT a live per-tick fetch). Injected ONLY
|
|
14263
|
+
// when the gate resolved on (the snapshot exists); absent ⇒ gate inert.
|
|
14264
|
+
remoteOwnerHasLiveSession: _closeoutSnapshot?.remoteOwnerHasLiveSession,
|
|
14265
|
+
// Post-transfer closeout correctness (F1, Part E): the LOCAL-receipt ts of
|
|
14266
|
+
// the bound topic's newest user message — same history source the
|
|
14267
|
+
// recent-user-message KEEP-guard reads. Backs the freshest-interaction veto.
|
|
14268
|
+
recentUserMessageAt: (topicId) => {
|
|
14269
|
+
try {
|
|
14270
|
+
if (!telegram)
|
|
14271
|
+
return null;
|
|
14272
|
+
return recentUserMessageAtFromHistory(telegram.getTopicHistory(topicId, 50));
|
|
14273
|
+
}
|
|
14274
|
+
catch {
|
|
14275
|
+
return null; /* @silent-fallback-ok — no history → withhold the bypass (safe) */
|
|
14276
|
+
}
|
|
14277
|
+
},
|
|
14164
14278
|
// WS1.3: pin-conflict do-not-act — a pin naming THIS machine while the
|
|
14165
14279
|
// owner is elsewhere means the reconciler is bringing the topic back;
|
|
14166
14280
|
// the closeout holds instead of attacking the session the pin wants here.
|
|
@@ -14210,6 +14324,11 @@ export async function startServer(options) {
|
|
|
14210
14324
|
// Observe-only busy-orphan detection rides the same dev-gate (dark fleet,
|
|
14211
14325
|
// live on dev agents). Zero risk — it never changes a keep/kill verdict.
|
|
14212
14326
|
busyOrphanDetection: resolveDevAgentGate(rcfg.busyOrphanDetection, config),
|
|
14327
|
+
// Post-transfer closeout correctness (F1): the liveness gate rides the
|
|
14328
|
+
// SAME dev-gate (dark fleet, live on dev agents). Resolved once here so
|
|
14329
|
+
// the reaper's gated/legacy branch matches the snapshot construction
|
|
14330
|
+
// above (both read resolveDevAgentGate(...closeoutLivenessGate)).
|
|
14331
|
+
closeoutLivenessGate: _closeoutLivenessGate,
|
|
14213
14332
|
};
|
|
14214
14333
|
})());
|
|
14215
14334
|
sessionReaper.start();
|