feat: export continuity hard-gate and watchdog workstream

This commit is contained in:
2026-04-24 12:36:31 +08:00
commit 111cf27634
24 changed files with 3648 additions and 0 deletions

View File

View File

@@ -0,0 +1,62 @@
# Approved Plan Continuity Receipt Storage
This directory stores file-backed continuity receipts for approved-plan flows.
## Scope
This storage definition is intentionally minimal.
It defines only the receipt location, minimum receipt shape, and filename convention for continuity receipts.
It does **not** implement receipt writing, hook integration, dispatch orchestration, or gate evaluation logic.
## Receipt file format
- Format: JSON
- Encoding: UTF-8
- One receipt per file
## Minimum receipt shape
Each continuity receipt file must contain a JSON object with at least these fields:
- `planId`
- `currentTask`
- `nextDerivedAction`
- `dispatchedAt`
- `dispatchRunId`
- `childSessionKey`
- `replyClosureState`
### Minimal example
```json
{
"planId": "plan_2026_04_24_example",
"currentTask": "Task 15",
"nextDerivedAction": "dispatch next approved-plan task",
"dispatchedAt": "2026-04-24T12:00:00.000+08:00",
"dispatchRunId": "dispatch_2026_04_24_example",
"childSessionKey": "agent:engineering:subtask-example",
"replyClosureState": "open"
}
```
## Filename convention
Continuity receipt filenames must follow this pattern:
```text
receipt-<planId>-<dispatchRunId>.json
```
## Naming rules
- `<planId>` should match the receipt `planId`
- `<dispatchRunId>` should match the receipt `dispatchRunId`
- Use lowercase kebab-case or other filesystem-safe identifiers
- Do not reuse one file for multiple dispatch runs
## State interpretation
- A receipt in this directory represents a persisted continuity dispatch record for one approved-plan dispatch run.
- `replyClosureState` is stored alongside the dispatch linkage so later tasks can distinguish an active dispatch record from an allowed non-dispatch closure state.
- Legal non-dispatch closure values are defined by the plan/runbook logic outside this storage README.

View File

@@ -0,0 +1,12 @@
{
"planId": "plan_2026_04_24_example",
"currentTask": "task-16",
"nextDerivedAction": {
"type": "message_subagent",
"task": "continue with task-17"
},
"dispatchedAt": "2026-04-24T12:24:00.000+08:00",
"dispatchRunId": "dispatch_2026_04_24_example",
"childSessionKey": "agent:engineering:subtask-example",
"replyClosureState": "open"
}

View File

@@ -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/<runId>.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.

View File

@@ -0,0 +1,6 @@
{
"runId": "fixture-run-active-before-sla",
"childSessionKey": "session:active-before-sla",
"dispatchAt": "2026-04-24T10:00:00.000Z",
"expectedBy": "2026-04-24T10:10:00.000Z"
}

View File

@@ -0,0 +1,7 @@
{
"runId": "fixture-run-completed",
"childSessionKey": "session:completed",
"dispatchAt": "2026-04-24T10:00:00.000Z",
"expectedBy": "2026-04-24T10:10:00.000Z",
"completionReceivedAt": "2026-04-24T10:04:00.000Z"
}

View File

@@ -0,0 +1,6 @@
{
"runId": "fixture-run-done-not-forwarded",
"childSessionKey": "session:done-not-forwarded",
"dispatchAt": "2026-04-24T10:00:00.000Z",
"expectedBy": "2026-04-24T10:10:00.000Z"
}

View File

@@ -0,0 +1,6 @@
{
"runId": "fixture-run-suspect-delivery-failure",
"childSessionKey": "session:suspect-delivery-failure",
"dispatchAt": "2026-04-24T10:00:00.000Z",
"expectedBy": "2026-04-24T10:10:00.000Z"
}

View File

@@ -0,0 +1,9 @@
{
"runId": "preview-completion-write",
"childSessionKey": "session:preview",
"dispatchAt": "2026-04-24T10:00:00.000Z",
"expectedBy": "2026-04-24T10:10:00.000Z",
"completionReceivedAt": "2026-04-24T10:04:00.000Z",
"forwardedToMain": false,
"resultSource": "child_history"
}