From b7416036db787713839845bb1cd187881d80e84f Mon Sep 17 00:00:00 2001 From: Eve Date: Fri, 24 Apr 2026 10:52:44 +0800 Subject: [PATCH] feat: write subagent completion receipt state --- scripts/subagent_delivery_watchdog.mjs | 78 ++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/scripts/subagent_delivery_watchdog.mjs b/scripts/subagent_delivery_watchdog.mjs index 03f79ba..b6075f7 100755 --- a/scripts/subagent_delivery_watchdog.mjs +++ b/scripts/subagent_delivery_watchdog.mjs @@ -122,6 +122,66 @@ function writeDispatchReceiptState(payload) { }; } +function writeCompletionReceiptState(payload) { + if (!payload || typeof payload !== 'object') { + return null; + } + + const { runId } = payload; + const completionReceivedAt = payload.completionReceivedAt ?? payload.completionReceiptAt ?? null; + const forwardedToMain = payload.forwardedToMain; + const resultSource = payload.resultSource; + + if (typeof runId !== 'string' || runId.length === 0) { + return null; + } + + const completionUpdates = {}; + + if (typeof completionReceivedAt === 'string' && completionReceivedAt.length > 0) { + completionUpdates.completionReceivedAt = completionReceivedAt; + } + + if (typeof forwardedToMain === 'boolean') { + completionUpdates.forwardedToMain = forwardedToMain; + } + + if (typeof resultSource === 'string' && resultSource.length > 0) { + completionUpdates.resultSource = resultSource; + } + + if (Object.keys(completionUpdates).length === 0) { + return null; + } + + fs.mkdirSync(STATE_DIR, { recursive: true }); + + const statePath = path.join(STATE_DIR, `${runId}.json`); + let currentRecord = {}; + + if (fs.existsSync(statePath)) { + try { + currentRecord = JSON.parse(fs.readFileSync(statePath, 'utf8')); + } catch { + currentRecord = {}; + } + } + + const nextRecord = { + ...currentRecord, + runId, + ...completionUpdates, + }; + + fs.writeFileSync(statePath, `${JSON.stringify(nextRecord, null, 2)}\n`, 'utf8'); + + return { + statePath, + record: nextRecord, + updatedFields: Object.keys(completionUpdates), + }; +} + function main() { const args = parseArgs(process.argv.slice(2)); @@ -133,16 +193,25 @@ function main() { const input = tryReadInput(args.input); const inputPayload = input.exists ? tryParseJson(input.content) : null; const dispatchWrite = writeDispatchReceiptState(inputPayload); + const completionWrite = writeCompletionReceiptState(inputPayload); if ('content' in input) { delete input.content; } + const records = []; + if (dispatchWrite) { + records.push(dispatchWrite.record); + } + if (completionWrite) { + records.push(completionWrite.record); + } + const response = { ok: true, tool: 'subagent_delivery_watchdog', - version: 'skeleton-v2', - mode: 'dispatch-receipt-write', + version: 'skeleton-v3', + mode: 'receipt-write', args: { compact: args.compact, input: args.input, @@ -150,9 +219,10 @@ function main() { input, result: { status: 'not_implemented', - message: 'Dispatch receipt write is implemented; status recompute remains pending.', - records: dispatchWrite ? [dispatchWrite.record] : [], + message: 'Dispatch and completion receipt writes are implemented; status recompute remains pending.', + records, dispatchReceiptWrite: dispatchWrite, + completionReceiptWrite: completionWrite, }, };