diff --git a/src/diag.ts b/src/diag.ts index 70c02d3..03f844b 100644 --- a/src/diag.ts +++ b/src/diag.ts @@ -1,16 +1,28 @@ import type { ExtensionContext, Skill } from "@earendil-works/pi-coding-agent"; import type { SkillReinjectSettings } from "./settings.js"; -import type { ExtensionState } from "./state.js"; +import type { CompactionSource, ExtensionState } from "./state.js"; -export type ReinjectDiagPhase = "session_compact" | "before_agent_start"; +export type ReinjectDiagPhase = "session_compact" | "before_agent_start" | "mid_turn_deliver"; -/** Filter snapshot for debug logging (Phase 14 / B-002). */ +/** Optional compaction/delivery context for debug snapshots (Phase 15 / B-003). */ +export interface ReinjectDiagContext { + compactionSource?: CompactionSource | null; + sourceInferred?: boolean; + deliveryBranch?: "before_agent_start" | "steer" | "none"; + isIdle?: boolean; +} + +/** Filter snapshot for debug logging (Phase 14 / B-002, Phase 15 / B-003). */ export interface ReinjectDiagSnapshot { tracked: string[]; kept: string[]; registered: string[]; planned: string[]; pending: string[]; + compactionSource?: CompactionSource | null; + sourceInferred?: boolean; + deliveryBranch?: "before_agent_start" | "steer" | "none"; + isIdle?: boolean; } export function buildReinjectDiagSnapshot( @@ -18,6 +30,7 @@ export function buildReinjectDiagSnapshot( registeredSkills: readonly Pick[], keptPresent: ReadonlySet, planned: readonly string[], + context?: ReinjectDiagContext, ): ReinjectDiagSnapshot { return { tracked: state.skills.map((skill) => skill.name), @@ -25,6 +38,7 @@ export function buildReinjectDiagSnapshot( registered: registeredSkills.map((skill) => skill.name), planned: [...planned], pending: [...state.pendingReinject], + ...context, }; } diff --git a/src/index.ts b/src/index.ts index bde8cea..1a58901 100644 --- a/src/index.ts +++ b/src/index.ts @@ -107,7 +107,9 @@ export default function skillReinject(pi: ExtensionAPI): void { const trackedNames = state.skills.map((skill) => skill.name); const keptEntries = getKeptEntries(branch, event.compactionEntry.firstKeptEntryId); const keptPresent = skillsPresentInKeptWindow(keptEntries, trackedNames); + const sourceBeforeMark = compactionRuntime.pendingCompactionSource; ensureCompactionSourceMarked(compactionRuntime); + const sourceInferred = sourceBeforeMark === null; const shouldReinject = consumeCompactionOnSessionCompact( compactionRuntime, state, @@ -121,16 +123,30 @@ export default function skillReinject(pi: ExtensionAPI): void { : planReinject(state, settings, ctx, event, skills); applyPendingReinjectAfterCompact(state, compactionRuntime, shouldReinject, planned); + const isIdle = ctx.isIdle(); + const deliveryBranch: "before_agent_start" | "steer" | "none" = + !shouldReinject || planned.length === 0 + ? "none" + : deliveryMode === "defer" && !isIdle + ? "steer" + : deliveryMode === "defer" + ? "before_agent_start" + : "none"; notifyReinjectDiag( ctx, settings, "session_compact", - buildReinjectDiagSnapshot(state, skills, keptPresent, planned), + buildReinjectDiagSnapshot(state, skills, keptPresent, planned, { + compactionSource: state.lastCompactionSource, + sourceInferred, + deliveryBranch, + isIdle, + }), ); if (deliveryMode === "defer") { - if (shouldReinject && planned.length > 0 && !ctx.isIdle()) { - deliverDeferredReinjectSteer( + if (shouldReinject && planned.length > 0 && !isIdle) { + const steered = deliverDeferredReinjectSteer( pi, state, settings, @@ -139,6 +155,19 @@ export default function skillReinject(pi: ExtensionAPI): void { event.compactionEntry.id, ctx, ); + if (steered) { + notifyReinjectDiag( + ctx, + settings, + "mid_turn_deliver", + buildReinjectDiagSnapshot(state, skills, keptPresent, planned, { + compactionSource: state.lastCompactionSource, + sourceInferred, + deliveryBranch: "steer", + isIdle, + }), + ); + } } persistState(); return; @@ -201,7 +230,11 @@ export default function skillReinject(pi: ExtensionAPI): void { ctx, settings, "before_agent_start", - buildReinjectDiagSnapshot(state, skills, keptPresent, []), + buildReinjectDiagSnapshot(state, skills, keptPresent, [], { + deliveryBranch: + state.pendingReinject.length > 0 ? "before_agent_start" : "none", + isIdle: ctx.isIdle(), + }), ); const pendingBefore = state.pendingReinject.length; const deferred = tryConsumeDeferredReinject( diff --git a/test/diag.test.ts b/test/diag.test.ts index bab1914..09717d4 100644 --- a/test/diag.test.ts +++ b/test/diag.test.ts @@ -22,6 +22,12 @@ describe("buildReinjectDiagSnapshot", () => { [{ name: "beta" }], new Set(["gamma"]), ["alpha"], + { + compactionSource: "auto", + sourceInferred: true, + deliveryBranch: "steer", + isIdle: false, + }, ), ).toEqual({ tracked: ["alpha"], @@ -29,6 +35,10 @@ describe("buildReinjectDiagSnapshot", () => { registered: ["beta"], planned: ["alpha"], pending: ["alpha"], + compactionSource: "auto", + sourceInferred: true, + deliveryBranch: "steer", + isIdle: false, }); }); });