diff --git a/state/subagent-delivery-watchdog/.gitkeep b/state/subagent-delivery-watchdog/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/state/subagent-delivery-watchdog/README.md b/state/subagent-delivery-watchdog/README.md new file mode 100644 index 0000000..936df21 --- /dev/null +++ b/state/subagent-delivery-watchdog/README.md @@ -0,0 +1,81 @@ +# Subagent Delivery Watchdog State Shape + +This directory is reserved for file-backed state used by the subagent delivery watchdog. + +## Purpose + +The watchdog tracks whether a subagent dispatch has a matching completion receipt and whether the main thread has enough evidence to classify the run state without guessing. + +This task defines the **state JSON shape only**. It does **not** implement receipt write logic, status recomputation, recovery behavior, or live integration. + +## Suggested file model + +One JSON document per dispatched subagent run. + +Example path pattern: + +- `state/subagent-delivery-watchdog/.json` + +## State JSON shape + +```json +{ + "runId": "run_2026_04_24_abc123", + "childSessionKey": "agent:engineering:subagent:cd236af1-7d4a-4f4e-bccd-04e4f9a96c02", + "dispatchAt": "2026-04-24T10:40:00+08:00", + "expectedBy": "2026-04-24T10:50:00+08:00", + "completionReceivedAt": null, + "forwardedToMain": false, + "resultSource": null, + "status": "active", + "statusUpdatedAt": "2026-04-24T10:40:00+08:00", + "statusReason": "Dispatch receipt exists and SLA has not been crossed.", + "recoveryAction": null, + "recoveryAttemptCount": 0, + "lastRecoveryAt": null, + "notes": [] +} +``` + +## Receipt fields + +### Dispatch receipt fields + +- `runId`: unique identifier for the dispatched subagent run. +- `childSessionKey`: session key or stable child-session identifier used to correlate the run. +- `dispatchAt`: ISO-8601 timestamp for when the subagent was dispatched. +- `expectedBy`: ISO-8601 timestamp for the watchdog SLA / expected completion deadline. + +### Completion receipt fields + +- `completionReceivedAt`: ISO-8601 timestamp for when a completion receipt was observed by the owner thread; `null` if not yet observed. +- `forwardedToMain`: boolean indicating whether the completion/result was confirmed forwarded back to the main thread. +- `resultSource`: source label for the result evidence, for example `completion_event`, `history_fetch`, or `manual_recovery`; `null` if no completion evidence exists yet. + +## Status fields + +- `status`: current watchdog classification. Expected values include: + - `active` + - `suspect_delivery_failure` + - `done_but_not_forwarded` + - `completed` + - `recovered` + - `blocked` +- `statusUpdatedAt`: ISO-8601 timestamp of the latest status evaluation/update. +- `statusReason`: short human-readable explanation for why the current status was assigned. + +## Optional supporting fields + +These fields are not a substitute for the required receipt/status fields, but they can support later tasks safely. + +- `recoveryAction`: pending or last recovery decision, if any. +- `recoveryAttemptCount`: number of recovery attempts already made. +- `lastRecoveryAt`: ISO-8601 timestamp of the last recovery attempt. +- `notes`: append-only diagnostic notes. + +## Constraints + +- Receipt fields and status fields must remain explicit in stored state. +- `completionReceivedAt`, `resultSource`, and recovery-related fields may be `null` before any completion signal exists. +- `forwardedToMain` should remain `false` until the return path to the main thread is actually confirmed. +- Status must be derived from evidence; later implementation should not infer success without a receipt or equivalent recovery proof.