@agfpd/iapeer 0.2.47 → 0.2.48
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/package.json
CHANGED
package/src/lifecycle/index.ts
CHANGED
|
@@ -1251,20 +1251,29 @@ export function superviseTick(cfg: LifecycleConfig, deps: SuperviseDeps = {}): S
|
|
|
1251
1251
|
* consumed BEFORE the relaunch so a relaunch failure does not loop on the same eager mark
|
|
1252
1252
|
* (it then fresh-wakes lazily on its next message — branch 3a — never lost). NB: a /new'd
|
|
1253
1253
|
* peer is expected to carry an initial_prompt; without one the first turn delivers nothing.
|
|
1254
|
+
*
|
|
1255
|
+
* Runtime is DELIBERATELY NOT pinned to the dead session's runtime: the relaunch passes
|
|
1256
|
+
* no runtime so resolveWakeRuntime falls through to the registry default (H5 — registry
|
|
1257
|
+
* is the only source of wake-runtime truth). Pinning broke the fleet-switch procedure
|
|
1258
|
+
* (`default-runtime <rt>` + `self-fresh`): the peer silently resurrected on the OLD
|
|
1259
|
+
* runtime, ignoring the just-flipped default (live incident 12.06, claude-iapeer). A
|
|
1260
|
+
* session deliberately living on a non-default runtime has explicit paths back (wake
|
|
1261
|
+
* with an explicit runtime); an owner /new returns the peer to its declared default.
|
|
1254
1262
|
*/
|
|
1255
1263
|
export async function processEagerRelaunches(
|
|
1256
1264
|
cfg: LifecycleConfig,
|
|
1257
1265
|
outcomes: SuperviseOutcome[],
|
|
1258
|
-
deps: WakeDeps = {},
|
|
1266
|
+
deps: WakeDeps & { wakeFn?: (args: WakeArgs, deps: WakeDeps) => Promise<WakeResult> } = {},
|
|
1259
1267
|
): Promise<WakeResult[]> {
|
|
1268
|
+
const wake = deps.wakeFn ?? wakeOrSpawn
|
|
1260
1269
|
const results: WakeResult[] = []
|
|
1261
1270
|
for (const o of outcomes) {
|
|
1262
|
-
if (o.action !== 'needs-eager-fresh' || !o.personality
|
|
1271
|
+
if (o.action !== 'needs-eager-fresh' || !o.personality) continue
|
|
1263
1272
|
clearNewEager(cfg, o.identity) // consume the eager mark — the relaunch is fresh by construction
|
|
1264
1273
|
try {
|
|
1265
1274
|
results.push(
|
|
1266
|
-
await
|
|
1267
|
-
{ personality: o.personality,
|
|
1275
|
+
await wake(
|
|
1276
|
+
{ personality: o.personality, task: '', resume: false },
|
|
1268
1277
|
{ cfg, env: deps.env },
|
|
1269
1278
|
),
|
|
1270
1279
|
)
|
|
@@ -621,6 +621,38 @@ describe('superviseTick death-cause accounting (TARGET)', () => {
|
|
|
621
621
|
}
|
|
622
622
|
})
|
|
623
623
|
|
|
624
|
+
test('eager relaunch does NOT pin the dead session runtime — re-resolves from the registry (H5 fleet-switch)', async () => {
|
|
625
|
+
// Live incident 12.06: `default-runtime codex` + `self-fresh` resurrected the peer
|
|
626
|
+
// on the OLD runtime — the relaunch passed the dead session's runtime EXPLICITLY,
|
|
627
|
+
// so resolveWakeRuntime never consulted the just-flipped registry default.
|
|
628
|
+
const { env, cfg, root, laDir } = deadSessionEnv('rt')
|
|
629
|
+
try {
|
|
630
|
+
setNewEager(cfg, 'claude-rt')
|
|
631
|
+
const outcomes = superviseTick(cfg, { env })
|
|
632
|
+
const o = outcomes.find(x => x.identity === 'claude-rt')
|
|
633
|
+
expect(o?.action).toBe('needs-eager-fresh')
|
|
634
|
+
const seen: Array<{ personality: string; runtime?: string; resume?: boolean; task: string }> = []
|
|
635
|
+
const { processEagerRelaunches } = await import('./index.ts')
|
|
636
|
+
await processEagerRelaunches(cfg, outcomes, {
|
|
637
|
+
env,
|
|
638
|
+
wakeFn: async args => {
|
|
639
|
+
seen.push({ personality: args.personality, runtime: args.runtime, resume: args.resume, task: args.task })
|
|
640
|
+
return { status: 'READY', woke: true }
|
|
641
|
+
},
|
|
642
|
+
})
|
|
643
|
+
expect(seen.length).toBe(1)
|
|
644
|
+
expect(seen[0].personality).toBe('rt')
|
|
645
|
+
expect(seen[0].runtime).toBeUndefined() // ← the fix: wakeOrSpawn re-resolves from the registry
|
|
646
|
+
expect(seen[0].resume).toBe(false)
|
|
647
|
+
expect(seen[0].task).toBe('')
|
|
648
|
+
// the mark was consumed by the relaunch
|
|
649
|
+
expect(hasNewEager(cfg, 'claude-rt')).toBe(false)
|
|
650
|
+
} finally {
|
|
651
|
+
rmSync(root, { recursive: true, force: true })
|
|
652
|
+
rmSync(laDir, { recursive: true, force: true })
|
|
653
|
+
}
|
|
654
|
+
})
|
|
655
|
+
|
|
624
656
|
test('a DEAD session with NO .new-eager → reaped-gone, NO .idle-reaped written (crash leaves no marker)', () => {
|
|
625
657
|
const { env, cfg, root, laDir } = deadSessionEnv('w')
|
|
626
658
|
try {
|