REQ-C-034: Long-Running Commands Report Progress
Tier: Command Contract | Priority: P1
Source: §79 Work Outlives the Caller's Budget · §11 Timeouts & Hanging Processes
Addresses: Severity: Critical / Token Spend: High / Time: Critical / Context: Medium
Description
A command that declares interruption (REQ-C-033) MUST report its progress through the framework's ctx.progress(done, total?, unit?) API as the work advances, at least once every 10 seconds of work. done is a count of completed work units (bytes, rows, items, steps) and MUST never decrease within one run or across its continuations; total is the expected count when known; unit names the units.
Progress is what tells working from hung. A timer that ticks while a worker thread is deadlocked proves only that the process is alive; a growing done proves that the work advances. The framework uses each report three ways:
data.progressof theINCOMPLETEresponse (REQ-F-082), which the agent compares between continuations- the idle watchdog of a background job (REQ-F-081): a job whose
donestops changing ends as stalled - the status text of the heartbeat when one is enabled (REQ-O-012)
A report is cheap: the framework records the latest values and throttles writes to the job's status; a handler may call it on every chunk.
Acceptance Criteria
- A command declaring
interruptioncallsctx.progress()at least once every 10 s of work in its test suite's longest fixture data.progress.donein successiveINCOMPLETEresponses of one job never decreases, including after a resume from a checkpoint- A handler that stops calling
ctx.progress()while its process stays alive is ended by the idle watchdog of REQ-F-081 - Calling
ctx.progress()with adonelower than the previous report raises a framework error in test mode
Schema
Types: response-envelope.md
The values reach the wire only as data.progress of the INCOMPLETE response: {done, total?, unit?}.
Wire Format
{ "done": 120000000, "total": 980000000, "unit": "bytes" }
Example
execute(args, ctx):
total = file_size(args.file)
for chunk in read_chunks(args.file):
stats.add(chunk)
ctx.progress(done=chunk.end, total=total, unit="bytes")
return stats.summary()
Related
| Requirement | Tier | Relationship |
|---|---|---|
| REQ-C-033 | C | Consumes: every command declaring interruption reports progress |
| REQ-F-082 | F | Provides: data.progress of the incomplete-work response |
| REQ-F-081 | F | Provides: the signal the idle watchdog watches |
| REQ-C-035 | C | Composes: a checkpoint carries the done a resumed run continues from |
| REQ-O-012 | O | Provides: the status text of a heartbeat line |