feat(cc-230): state-store writer + codex-dispatch runs_append wiring#159
Merged
Conversation
M1 state store writer (designated-writer boundary per core/state/layout.yaml): - scripts/lib/state-writer.sh: _sw_store_root (XDG path resolution), _sw_project_key (sha1 of git toplevel), state_store_init (mkdir + VERSION), runs_append, events_append, task_upsert — all best-effort, never fatal - scripts/codex-dispatch.sh: source state-writer.sh; after EXIT=$? add guarded block that builds Run JSON and calls runs_append (task_id extracted from brief file/inline, fallback UNKN-0) - hook-routing-log.sh unchanged (dual-write: routing_log.md stays in M1) - scripts/test-state-store.sh: 10 test cases (path resolution, append, lock, non-fatal failure, dispatch self-containment) - run-all-tests.sh + test-run-all-tests.sh + lint.yml: register new suite 30 suites pass (0 failed). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… dispatch tests
- _sw_project_key: check _SW_REPO_ROOT env var first so runs_append resolves
the target repo partition from WORK_DIR, not the caller's cwd
- codex-dispatch.sh: set _SW_REPO_ROOT=WORK_DIR before runs_append; build Run
JSON via jq -cn to safely escape quotes/backslashes in path/model fields
- task_upsert: validate task_id against ^[A-Z]{1,4}-[0-9]+[a-z]?$ before using
it in a filesystem path (prevents path traversal)
- test-state-store.sh: add 3 integration tests (cases 11–13): fake-codex dispatch
creates runs.jsonl, correct project partition for --cd target, valid JSON with
special chars in model field — suite now 13 cases, all passing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…vents fixture, regressions - _sw_project_key: use git -C "$_SW_REPO_ROOT" rev-parse --show-toplevel to normalize subdirectory paths to the repo root before hashing the partition key - codex-dispatch.sh: anchor both task_id: grep patterns with ^ so parent_task_id and similar prefixed keys are not mistaken for the real task attribution - test-state-store.sh: remove invalid "type" field from events_append fixture (event.schema.json has additionalProperties: false) - test-state-store.sh: add case_dispatch_subdir_partition_key (case 14) and case_dispatch_task_id_anchor (case 15) — suite now 15 cases, all passing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… jq failure log - test-state-store.sh: add Verifies/Steps docstrings to cases 1–10 per QA rules - test-state-store.sh: add case 16 (inline -- <brief> task_id extraction) and case 17 (failed dispatch records state:failed + exit code) — suite now 17 cases - codex-dispatch.sh: log _sw_log_error when jq Run JSON construction produces empty output so missing run rows have forensic evidence Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…end JSON validity - Add case_task_upsert_invalid_id: calls task_upsert with "../evil", asserts exit 0 and no file is created — covers the path-traversal guard added in round 1 - case_events_append: add jq parse assertion to verify written JSONL is valid JSON, matching the existing case_runs_append_valid_jsonl pattern (medium sweep) Suite: 18 passed, 0 failed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dium advisory) Raised by critic/architecture-reviewer/risk-reviewer in CC-230 gate 5: sha1sum (GNU only) used directly in _sw_project_key without fallback to shasum -a 1 (macOS) — platforms without either silently route to global partition, violating core/state/layout.yaml per-project partitioning. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
screenleon
added a commit
that referenced
this pull request
May 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/lib/state-writer.sh: XDG-compliant state store at~/.local/share/pm-dispatch/state/; per-project partitioning viasha1(git rev-parse --show-toplevel);serialize_with_lock-backedruns_append/events_append/task_upsert; all functions best-effort (never propagate errors to callers)scripts/codex-dispatch.sh: sourcesstate-writer.sh; after each dispatch appends a Run row toruns.jsonlusingjq -cnfor safe JSON encoding; routes to target project partition via_SW_REPO_ROOT=WORK_DIR; entire block is{ … } 2>/dev/null || true— EXIT code unaffectedscripts/test-state-store.sh: 18-case regression suite (store root resolution, dir init, append/upsert JSONL, dispatch integration with fake codex, partition key correctness, invalid ID rejection, failed dispatch recording)scripts/run-all-tests.sh+.github/workflows/lint.yml: suite registration and CI jobDual-write strategy:
routing_log.mdstays unchanged in M1;runs.jsonlis added in parallel. M2 will cuthook-routing-log.sh.Gate
Full tier —
Final: GO(gate-20260525-155943.md)Remaining advisories (non-blocking, follow-up tracked in BACKLOG):
sha1sumportability — consider portable hash helper inportable.sh(CC-263)Test plan
.gate-results/gate-20260525-155943.mdbash scripts/test-state-store.sh— 18 passedbash scripts/run-all-tests.sh— 30 passedscripts/lib/state-writer.shbest-effort invariant: any function failure leaves caller exit code = 0codex-dispatch.shEXIT code preservation (existingtest-codex-dispatch.shcovers this)🤖 Generated with Claude Code