google / google/capsem

Harden typed gate composition identity and graph guard coverage

Open
#186 0 comments 0 reactions 0 assignees View on GitHub
type:bug
Dominant language
Rust
Stars
72
Forks
13
Avg merge
1d 2h
Merged PRs (30d)
5

Description

## Why

A review of the new typed gate found a few localized composition seams. These are not known v0.6 release blockers and do not call the architecture into question, but they should be closed so composition order and rendered text cannot influence plan semantics.

## Findings

1. **`Plan.shared` drops the first edge kind.** In `src/capsem/gate/plan.py`, the first-registration branch calls `self.add(step, after=after)` without forwarding `requires=requires`. Later registrations do forward it through `edge()`. No current production caller appears to pass `requires=` to `shared`, so this looks dormant today.

2. **Shared-step identity is incomplete.** Collision detection compares rendered actions, carry checks, and resume policy, but not `contends`, `produces`, `kind`, `needs`, `arch`, `speed`, or `concurrency`. Two fragments can therefore request semantically different steps with the same label and actions, with the winner determined by composition order.

3. **Candidate prerequisite deduplication uses rendered command text.** `_already_issuing` in `src/capsem/gate/candidateplan.py` treats equal `Run`/`Script` renderings as equal work. This is narrower than the old shell matching, but it still makes presentation a semantic identity and can omit action or step properties that rendering does not encode. Prefer an explicit shared identity or the actual shared step handle.

4. **Work-graph guard scope needs reconciliation.** `tests/citadel/test_work_graph_invariants.py` says its command inventory covers the whole candidate and the release lanes, while `COMMANDS` currently contains `candidate`, `test-fast`, and `test-static`. Decide which invariants apply to release dispatch plans, encode any deliberate exceptions, and make the comment and executable inventory agree.

## Maintainability note

The 300-line boundary has produced many small gate modules. Do not mechanically merge them: the separation is mostly valuable. Once release stabilization is complete, check whether any boundaries exist only to satisfy the line ceiling and obscure one lifecycle or transaction. Any consolidation should preserve single ownership and the Citadel guards.

## Done when

- `Plan.shared(..., requires=...)` preserves the edge kind on both first and subsequent registration.
- Tests reject shared steps whose operational claims or outputs differ, not only whose rendered actions differ.
- Candidate prerequisite reuse is based on explicit semantic identity rather than rendered text.
- Work-graph guard coverage and its documented scope agree, with deliberate release-plan exceptions tested.
- The changes remain localized and do not alter release behavior or delay v0.6 publication.

Contributor guide

Open the contributing guide

Research direction

Start with Plan.shared in src/capsem/gate/plan.py and _already_issuing in src/capsem/gate/candidateplan.py, then run tests/citadel/test_work_graph_invariants.py. Trace shared-step identity and prerequisite reuse through the existing tests, and reconcile COMMANDS with the documented release-plan scope. Done means semantic mismatches are rejected, requires= is preserved, and guard coverage matches its stated scope without changing release behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
tooling
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.