remediate: governed runtime path + honest runtime disclosure (Tranches A+B) - #260
Conversation
…s A+B)
Make the clean governed operator path real and provable end-to-end through
supported CLI. Record durable canonical event history across capability,
approval and Work Graph domains. Deterministic per-domain rebuild from JSONL.
Semantic before/after digest equivalence.
Storage / replay (A2)
- shiroe/storage/projections.py: single reducer/projection dispatcher; live
and replay call the same handler per domain.
- shiroe/storage/events.py: whitelist approval.requested/decided/staled,
capability.stale/compromised. Rewrite EventLog.replay_into: FK-safe wipe
across all rebuildable domains, dispatch each event through projections,
return {"replayed": N, "domains": {name: "rebuilt"}, "legacy_incomplete"}.
- shiroe/cli/state.py: consume new dict shape; state rebuild --json emits
per-domain map.
Capability (A3)
- shiroe/capabilities/store.py: event-first mutations for upsert/set_lifecycle/
refresh_digest/register_discovery. Project-relative source_location so
REDACT.md internal_paths scrubbing cannot corrupt operational state. Fix
_LIFECYCLE_EVENT_TYPE stale/compromised fallback bug.
- shiroe/capabilities/onboarding.py + shiroe/cli/capability.py: capability
onboard <path> --json composite command. Discover -> quarantine -> inspect
-> pending human approval bound to {capability_id, digest}.
- shiroe/capabilities/gate.py: resolve project-relative source paths against
store root at read time.
- shiroe/adapters/capabilities/cli.py: resolve manifest command relative
paths against project root at invocation time.
Approvals (A4)
- shiroe/policy/approvals.py: extend ApprovalType with 'capability'.
- shiroe/policy/approval_service.py: event-source request/decide_human/
assert_current. Human-only guard fails closed before event emission.
Capability-scope approval decisions chain CapabilityStore.set_lifecycle
(ponytail comment names single-process ceiling).
Work Graph + supervisor (A5)
- shiroe/work/store.py: docstring corrected (topology is projection). Event-
first refactor emits run.created (full compiled graph), step.started/
completed/failed on node status transitions. state_version CAS held at
emit pre-check; reducer path deterministic under replay.
- shiroe/execution/supervisor.py: runtime-generated approval requests via
_ensure_approval_request. Dedups by (graph_id, node_id). RunSummary
surfaces pending approval ids.
Runtime disclosure (B1)
- shiroe/runtime/report.py + shiroe/cli/status.py --runtime --json: emit
shiroe.runtime-update/v1 with evidence-backed fields only; skills, agents,
model, transport all return 'unknown' when unverifiable. Non-absolute
project root.
Tests
- tests/e2e/test_governed_operator_path.py: subprocess-only R2 gate.
- tests/integration/storage/test_runtime_domain_replay.py: domain replay +
event emission proofs.
- tests/unit/test_runtime_report.py: schema, no absolute-path leakage,
degradation to 'unknown'.
- Existing tests updated to unwrap new replay_into dict shape and to drive
onboard through the CLI instead of direct CapabilityStore seeding.
Invariants
- Privacy: no scrub bypass; all persisted paths project-relative.
- Human-only approval: decide_human still fails closed on non-human actors.
- Event-first: single append + single reducer + single commit per mutation.
- Hash chain, head marker, MemoryLock, atomic append untouched.
- ADR-0006: WorkStore is projection, not canonical.
Verification
- 1072 passed, 4 skipped, 0 failed on fresh output.
- scripts/release_ready.py: PASS.
- R2 gate (test_governed_operator_path.py): GREEN.
- Semantic before/after digest equal across memory/capabilities/approvals/
work_projection domains.
Out of scope (per plan)
- Native harness portability tranche (C).
- Runtime Smoke Test R2 initialization.
- Node0/Node1 or infrastructure work.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52053f82f9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if env.get("event_type") != "capability.discovered": | ||
| return False |
There was a problem hiding this comment.
Apply lifecycle events during capability replay
When state rebuild replays a capability that transitioned after discovery, this branch ignores every inspected/approved/active/revoked/digest-drift event and restores only the lifecycle and digest captured by capability.discovered. An approved capability therefore commonly returns to quarantine, while a capability initially registered as executable can even be restored after a later revocation, so replay does not reproduce the governed state.
AGENTS.md reference: AGENTS.md:L42-L42
Useful? React with 👍 / 👎.
| for table in ( | ||
| "memory_events", "memory_sources", "memory_records", | ||
| "approval_advice", "approval_requests", | ||
| "work_attempts", "work_edges", "work_nodes", "work_graphs", |
There was a problem hiding this comment.
Preserve attempt history during replay
Whenever an operator runs state rebuild after execution attempts, this deletion permanently clears work_attempts, but the supervisor still writes attempts directly without emitting any replayable event. Because _attempt_count() derives the retry budget from this table, a rebuilt or recovered run forgets spent attempts and can invoke a capability again beyond its configured max_attempts.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
| row = self.conn.execute( | ||
| "SELECT state_version FROM work_nodes WHERE id=?", (node_id,) | ||
| ).fetchone() |
There was a problem hiding this comment.
Keep the CAS check atomic with the node update
When two WorkStore instances read the same state_version concurrently, both can pass this standalone SELECT before either reducer updates the row; both then append conflicting events and succeed instead of one raising ConcurrentWorkUpdate. This regresses the previous compare-and-swap UPDATE ... WHERE state_version=? behavior and allows stale workers to overwrite terminal status or output; the commit also skips the pressure test that demonstrates this case.
AGENTS.md reference: AGENTS.md:L53-L53
Useful? React with 👍 / 👎.
| # cleared before those work tables, not after. | ||
| for table in ( | ||
| "memory_events", "memory_sources", "memory_records", | ||
| "approval_advice", "approval_requests", |
There was a problem hiding this comment.
Preserve approval advice during rebuild
Running state rebuild after approval_advisor has produced recommendations deletes every approval_advice row, yet that service still persists advice directly and emits no event that any reducer can reconstruct. The command consequently reports the approvals domain as rebuilt while silently losing all persisted recommendations.
AGENTS.md reference: AGENTS.md:L42-L42
Useful? React with 👍 / 👎.
Summary
init→capability onboard→ fail-closedgate→ real humanapprove decide→plan→run→ filesystem output →verify→ wipe projections →state rebuild→ per-domain map → semantic digest equal).shiroe/storage/projections.py) shared by live-write and replay paths.shiroe status --runtime --json(shiroe.runtime-update/v1) — evidence-backed only;skills,agents,model,transportreturn"unknown"when unverifiable.internal_pathsscrubbing cannot corrupt operational state.Test plan
python3 -m pytest -q --tb=no→ 1072 passed, 4 skipped, 0 failedpython3 scripts/release_ready.py→ PASSpython3 -m pytest tests/e2e/test_governed_operator_path.py -q→ GREENpython3 -m pytest tests/integration/storage/test_runtime_domain_replay.py -q→ GREENR2 gate
Ready to OPEN.
tests/e2e/test_governed_operator_path.pyis subprocess-only, zero internal store seeding.Out of scope (per plan)
🤖 Generated with Claude Code