diff --git a/README.md b/README.md index e6b62cd..bab614b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,53 @@ -# crucible-agent-maintain-only-latest +# FastAPI current-status step -> Maintain only the latest check result for each monitored target in concurrency-safe memory and expose it through the specified FastAPI current-status endpoint. +Python/FastAPI implementation for step 3. It keeps one in-memory completed result per target behind a single `asyncio.Lock` and emits `current_status_implementation` while preserving all prior contract outputs. -A tool, not a standing agent service — see `input.schema.json`/`output.schema.json` for its contract. Generated by crucible-agent-decomposer for a plan gap step; language and structure are whatever the capability actually needs, not a fixed layout. +## Integrate with the prior service/checker + +Create one coordinator for the FastAPI process and include its router: + +```python +coordinator = CurrentStatusCoordinator() +app.include_router(build_current_status_router(coordinator)) +``` + +The prior target-create path must call `await coordinator.register_target(target_id)`. The prior target-delete path must call `await coordinator.delete_target(target_id)`. The scheduler/check path calls: + +```python +published = await coordinator.run_check(target_id, target, prior_checker) +``` + +`prior_checker` is an async callable returning a JSON-compatible mapping. `published=False` means the result became stale. These lifecycle hooks are deliberately explicit so target deletion and status cleanup share the coordinator's critical section. + +## REST contract + +`GET /targets/{target_id}/status` returns: + +* `404` with `{"detail":{"code":"target_not_found","target_id":"..."}}` when the target does not exist. +* `200` with `state="not_checked"` and `result=null` when it exists but has no completed check. +* `200` with `state="checked"` and the latest result otherwise. + +Only one `_statuses[target_id]` value can exist. A UUID incarnation prevents an in-flight check from publishing after delete/recreate. A per-incarnation sequence prevents an older overlapping check from replacing a newer-started check. Deletion removes status while holding the same lock. + +## Contract transformer + +```bash +python -m current_status < input.json > output.json +``` + +The three input objects are deep-copied unchanged and `current_status_implementation` is appended. + +## Tests and exact verification command + +Files: `tests/test_api.py`, `tests/test_concurrency.py`, and `tests/test_transform.py`. + +```bash +python -m pip install -e '.[test]' +python -m pytest -q +``` + +The tests audit latest-only retention, REST not-found/no-check/latest responses, deletion cleanup, overlapping-check ordering, delete/recreate resurrection prevention, and output preservation/emission. + +## Execution evidence + +No shell/test runner is available to the generation call, so this commit does **not** claim that pytest was executed there. The exact reproducible command is above; committed tests are the auditable evidence supplied by this generation step.