@afokapu/atdd-flow 0.3.52 → 0.3.54
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 +1 -1
- package/src/handover.ts +24 -3
package/package.json
CHANGED
package/src/handover.ts
CHANGED
|
@@ -286,7 +286,26 @@ function assertSinglePiWriter(raw: string) {
|
|
|
286
286
|
if (pi.length !== 1) throw new Error("Legacy source bootstrap requires exactly one live Pi writer on the authorized source pane.");
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
|
|
289
|
+
type PiSource = Pick<HandoverReplacementRequest["source"], "pi_session" | "pi_session_path">;
|
|
290
|
+
|
|
291
|
+
function assertCanonicalSourceNotLive(raw: string, canonical: PiSource) {
|
|
292
|
+
const value = JSON.parse(raw), agents = result(value)?.agents;
|
|
293
|
+
if (!Array.isArray(agents)) throw new Error("Consumed Path-A replacement requires complete global Herdr agent-list evidence.");
|
|
294
|
+
for (const entry of agents) {
|
|
295
|
+
const agent = object(entry);
|
|
296
|
+
if (!agent) throw new Error("Consumed Path-A replacement requires complete global Herdr agent-list evidence.");
|
|
297
|
+
if (text(agent.agent) !== "pi") continue;
|
|
298
|
+
const session = object(agent.agent_session);
|
|
299
|
+
const sessionPath = session?.kind === "path" ? text(session.value) : undefined;
|
|
300
|
+
if (!sessionPath) throw new Error("Consumed Path-A replacement requires complete global Herdr agent-list evidence.");
|
|
301
|
+
const sessionId = basename(sessionPath).match(/_([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i)?.[1];
|
|
302
|
+
if (resolve(sessionPath) === resolve(canonical.pi_session_path) || sessionId === canonical.pi_session) {
|
|
303
|
+
throw new Error("Consumed Path-A replacement prior canonical source is still a live Pi agent.");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function verifyLegacySource(source: HandoverReplacementRequest["source"], target: HandoverReplacementRequest["target"], authorizationHash: string, dependencies: HandoverReplacementDependencies, canonical?: PiSource) {
|
|
290
309
|
const command = dependencies.command ?? runOutput;
|
|
291
310
|
const pane = legacyPaneObservation(await command(herdr(source.herdr_session, "pane", "get", source.pane)));
|
|
292
311
|
assertLegacyPane(pane, source, target.cwd);
|
|
@@ -296,6 +315,9 @@ async function verifyLegacySource(source: HandoverReplacementRequest["source"],
|
|
|
296
315
|
]);
|
|
297
316
|
const agent = legacyAgentName(agentRaw, source, target.cwd);
|
|
298
317
|
assertSinglePiWriter(processRaw);
|
|
318
|
+
if (canonical && (canonical.pi_session !== source.pi_session || resolve(canonical.pi_session_path) !== resolve(source.pi_session_path))) {
|
|
319
|
+
assertCanonicalSourceNotLive(await command(herdr(source.herdr_session, "agent", "list")), canonical);
|
|
320
|
+
}
|
|
299
321
|
return { authorization_hash: authorizationHash, ...source, cwd: target.cwd, agent, verified_at: dependencies.at?.() ?? now() };
|
|
300
322
|
}
|
|
301
323
|
|
|
@@ -421,7 +443,6 @@ function assertCanonicalPlacement(intent: Awaited<ReturnType<typeof prepareRepla
|
|
|
421
443
|
|| resolve(request.target.cwd) !== resolve(intent.record.worktree)) {
|
|
422
444
|
throw new Error("Consumed Path-A replacement does not match the unchanged canonical main runtime and placement.");
|
|
423
445
|
}
|
|
424
|
-
if (intent.handover.supersedes !== request.handover.id) throw new Error("Consumed Path-A replacement does not match the current handover lineage.");
|
|
425
446
|
}
|
|
426
447
|
|
|
427
448
|
function canonicalRuntimeForSupersession(intent: Awaited<ReturnType<typeof prepareReplacement>>, request: HandoverReplacementRequest) {
|
|
@@ -666,7 +687,7 @@ async function supersedeConsumedReplacement(root: string, resolved: string, file
|
|
|
666
687
|
seat: resolved, pi_session: intent.source.pi_session, pi_session_path: intent.source.pi_session_path,
|
|
667
688
|
source: { herdr_session: intent.source.herdr_session, pane: intent.source.pane }, target: intent.target,
|
|
668
689
|
});
|
|
669
|
-
const liveSource = await verifyLegacySource(intent.source, intent.target, authorization.hash, dependencies);
|
|
690
|
+
const liveSource = await verifyLegacySource(intent.source, intent.target, authorization.hash, dependencies, consumed.canonical);
|
|
670
691
|
const request = supersedingRequest(resolved, file, intent, authorization, consumed, liveSource, dependencies);
|
|
671
692
|
const manifest = supersessionManifest(resolved, file, consumed);
|
|
672
693
|
const staging = await stageSupersession(file, request, consumed, manifest, dependencies);
|