Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/agents/flaky-test-qa.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ with free-form input.
"review_targets": [
"optional paths"
],
"round_limit": false,
"changed_files": ["optional/path.rs"],
"carry_forward_findings": ["optional finding id"],
"triage_records": ["optional/.triage/path.ttl"],
"notes": "optional context"
}
```
Expand Down
4 changes: 3 additions & 1 deletion .claude/agents/quality-mgr.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ TODO-specific rule:
6. Render structured JSON assignments:
- `req-qa` from `.claude/skills/codex-orchestration/req-qa-assignment.json.j2`
- `arch-qa` from `.claude/skills/codex-orchestration/arch-qa-assignment.json.j2`
- `rust-best-practices-agent` from `.claude/skills/codex-orchestration/rust-best-practices-agent-assignment.json.j2`
- `ruthless-boundary-qa` from `.claude/skills/codex-orchestration/ruthless-boundary-qa-assignment.json.j2`
- `rust-best-practices-agent` from `.claude/assets/sc-rust/quality-mgr/templates/rust-best-practices-assignment.json.j2`
on every sprint QA round for the near term, plus docs-only plan review
and phase-ending review
- `flaky-test-qa` from `.claude/skills/codex-orchestration/flaky-test-qa-assignment.json.j2` only when tests changed or instability is suspected
Expand Down Expand Up @@ -211,6 +212,7 @@ creates and wires the resulting fix beads.
For implementation QA-1 in this Rust repo:
- always run `req-qa`
- always run `arch-qa`
- always run `ruthless-boundary-qa`
- always run `rust-best-practices-agent`
- always run `rust-qa-agent`
- always run `rust-best-practices-agent`
Expand Down
5 changes: 5 additions & 0 deletions .claude/agents/rust-best-practices-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ with free-form input.
],
"practice_mode": "all | selected",
"practice_ids": ["RBP-001", "RBP-004"],
"round_limit": false,
"changed_files": ["optional files changed in the assigned round"],
"triage_records": ["optional triage-record paths relevant to this review"],
"carry_forward_findings": ["optional/pre-existing finding ids assigned for verification this round"],
"findings_scope_locked": false,
"notes": "optional context"
Expand All @@ -57,6 +60,8 @@ Rules:
- `practice_mode` is required.
- `review_targets` is optional. Omit to review default changed-file scope plus directly impacted boundaries.
- `practice_ids` must be non-empty when `practice_mode` is `selected`.
- `round_limit`, `changed_files`, and `triage_records` are optional lifecycle
context supplied by the orchestration caller.
- Unknown practice ids are input errors. Do not guess.
- When `practice_mode` is `all`, review the full canonical inventory from `practice-inventory.md`.

Expand Down
6 changes: 6 additions & 0 deletions .claude/agents/rust-qa-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ with free-form input.
"baseline_ref": "optional git ref for artifact or regression comparison",
"artifact_regeneration_required": false,
"artifact_commands": "",
"round_limit": false,
"changed_files": ["optional files changed in the assigned round"],
"triage_records": ["optional triage-record paths relevant to this review"],
"carry_forward_findings": ["optional/pre-existing finding ids assigned for verification this round"],
"notes": "optional context"
}
```
Expand All @@ -47,6 +51,8 @@ Rules:
- `review_targets` is optional. Omit to review the default changed-file scope plus impacted files when needed.
- `run_checks` is optional. If omitted, default to `fmt=true`, `clippy=true`, `tests=true`, `coverage=false`.
- `artifact_commands` is optional. If `artifact_regeneration_required` is true and commands are supplied, run them and treat failure as a finding. Phase-end assignments use this existing execution channel for `just lint && just test`; report its result under `executed_checks.artifacts`.
- `round_limit`, `changed_files`, `triage_records`, and `carry_forward_findings`
are optional lifecycle context supplied by the orchestration caller.
- This agent does not own `rust-best-practices` or `rust-service-hardening` policy. Do not infer those reviews from this input.

## Review Process
Expand Down
8 changes: 8 additions & 0 deletions .claude/agents/rust-service-hardening-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ with free-form input.
"actix-web",
"reqwest"
],
"service_indicators_extra": ["optional additional service indicators"],
"round_limit": false,
"changed_files": ["optional files changed in the assigned round"],
"triage_records": ["optional triage-record paths relevant to this review"],
"carry_forward_findings": ["optional/pre-existing finding ids assigned for verification this round"],
"notes": "optional context"
}
```
Expand All @@ -54,6 +59,9 @@ Rules:
- `topics` is optional. Omit to use the default topic set for the selected review mode.
- `service_indicator_dependencies` is optional. Omit to use the default service-indicator dependency list shown above.
- `review_targets` is optional. Omit to review default changed-file scope plus directly impacted runtime boundaries.
- `service_indicators_extra`, `round_limit`, `changed_files`, `triage_records`,
and `carry_forward_findings` are optional lifecycle context supplied by the
orchestration caller.

## Review Process

Expand Down
2 changes: 2 additions & 0 deletions .claude/agents/ruthless-boundary-qa.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ Input must be JSON, either raw JSON or fenced JSON.
"worktree_path": "/absolute/path/to/worktree",
"review_targets": ["optional/path.rs"],
"reference_docs": ["optional/docs/path.md"],
"round_limit": false,
"changed_files": ["optional/path.rs"],
"duplicate_sweep_symbols": ["optional symbol"],
"triage_records": ["optional/.triage/path.ttl"],
"carry_forward_findings": ["optional/pre-existing finding ids assigned for verification this round"],
"findings_scope_locked": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ defaults:
notes: ""
---
{
"review_mode": "{{ review_mode }}",
"worktree_path": "{{ worktree_path }}",
"review_targets": [{% for target in review_targets %}"{{ target }}"{% if not loop.last %}, {% endif %}{% endfor %}],
"review_mode": {{ review_mode }},
"worktree_path": {{ worktree_path }},
"review_targets": {{ review_targets }},
"topics": {% if topics %}
[{% for topic in topics %}"{{ topic }}"{% if not loop.last %}, {% endif %}{% endfor %}]
[{% for topic in topics %}{{ topic }}{% if not loop.last %}, {% endif %}{% endfor %}]
{% elif review_mode == "doc_review" %}
["config_validation", "timeouts", "graceful_shutdown", "retry_scope", "backpressure", "health_readiness"]
{% elif review_mode == "sprint_review" %}
Expand All @@ -38,10 +38,10 @@ defaults:
["config_validation", "timeouts", "graceful_shutdown", "structured_logging", "request_ids", "retries", "backpressure", "spawn_blocking", "input_limits", "dependency_hygiene", "health_readiness", "ci_release_gates"]
{% endif %},
"service_indicator_dependencies": ["tokio", "axum", "hyper", "tonic", "warp", "actix-web", "reqwest"],
"service_indicators_extra": [{% for indicator in service_indicators_extra %}"{{ indicator }}"{% if not loop.last %}, {% endif %}{% endfor %}],
"service_indicators_extra": {{ service_indicators_extra }},
"round_limit": {% if round_limit %}true{% else %}false{% endif %},
"changed_files": [{% for file in changed_files %}"{{ file }}"{% if not loop.last %}, {% endif %}{% endfor %}],
"triage_records": [{% for record in triage_records %}"{{ record }}"{% if not loop.last %}, {% endif %}{% endfor %}],
"changed_files": {{ changed_files }},
"triage_records": {{ triage_records }},
"carry_forward_findings": {{ carry_forward_findings_json }},
"notes": "{{ notes }}"
"notes": {{ notes }}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"review_mode":"sprint_review","worktree_path":"/tmp/worktree","review_targets":["crates/sc-lint-boundary/src/lib.rs"],"practice_mode":"selected","practice_ids":["RBP-001"],"round_limit":false,"changed_files":[],"carry_forward_findings_json":"[]","triage_records":[],"notes":"sample"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"review_mode":"sprint_review","worktree_path":"/tmp/worktree","review_targets":["crates/sc-lint-boundary/src/lib.rs"],"fmt":true,"clippy":true,"tests":true,"coverage":false,"baseline_ref":"develop","artifact_regeneration_required":false,"artifact_commands":"","round_limit":false,"changed_files":[],"carry_forward_findings_json":"[]","triage_records":[],"notes":"sample"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"review_mode":"sprint_review","worktree_path":"/tmp/worktree","review_targets":["crates/sc-lint-boundary/src/lib.rs"],"topics":["timeouts"],"round_limit":false,"changed_files":[],"carry_forward_findings_json":"[]","triage_records":[],"service_indicators_extra":[],"notes":"sample"}
1 change: 0 additions & 1 deletion .claude/lib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
"""Shared implementation helpers for repository-local Claude skills."""

12 changes: 12 additions & 0 deletions .claude/lib/orchestration_test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"""External-CLI policy shared by orchestration tests."""
from __future__ import annotations
import os
import shutil
import pytest

def require_dev_cli(name: str, minimum: str, install: str) -> None:
if shutil.which(name):
return
if os.getenv("CI"):
return pytest.skip(f"dev-host-only check: {name} not installed in CI")
pytest.fail(f"{name} CLI is required ({minimum}); install it with: {install}")
1 change: 0 additions & 1 deletion .claude/lib/sc_compose_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,3 @@ def parse_version(text: str | None) -> tuple[int, int, int] | None:
return None
match = _VERSION_RE.search(text)
return tuple(int(part) for part in match.groups()) if match else None

Original file line number Diff line number Diff line change
Expand Up @@ -441,4 +441,3 @@ def main(argv: list[str] | None = None) -> int:

if __name__ == "__main__":
sys.exit(main())

170 changes: 170 additions & 0 deletions .claude/skills/closing-triage/scripts/test_query_open_findings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
"""Unit tests for the closing-triage query's sprint and worktree selection.

Requires: rdflib (not a bootstrap dependency, so this file is run directly like
the graph-orchestration script tests: ``python3 <this file>``).
"""

from __future__ import annotations

import importlib.util
import tempfile
import unittest
from pathlib import Path

from rdflib import Graph, Namespace, URIRef

SCRIPT = Path(__file__).with_name("query_open_findings.py")
SPEC = importlib.util.spec_from_file_location("query_open_findings", SCRIPT)
assert SPEC is not None and SPEC.loader is not None
qof = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(qof)

TRIAGE = Namespace("urn:atm:triage:")

BB_STRUCTURE = """\
@prefix triage: <urn:atm:triage:> .
triage:PhaseBB a triage:Phase .
triage:BB3 a triage:Sprint ; triage:inPhase triage:PhaseBB ; triage:order 3 ; triage:branch "fix/bb3-qa2-r2" ; triage:criteria "docs/plans/phase-bb/sprint-BB.3.md" .
triage:BB6 a triage:Sprint ; triage:inPhase triage:PhaseBB ; triage:order 6 ; triage:branch "feature/bb6-prompt-handoffs" ; triage:criteria "docs/plans/phase-bb/sprint-BB.6.md" .
"""

AJ_STRUCTURE = """\
@prefix triage: <urn:atm:triage:> .
triage:PhaseAJ a triage:Phase .
triage:BB6 a triage:Sprint ; triage:inPhase triage:PhaseAJ ; triage:order 1 ; triage:branch "feature/aj-dup" ; triage:criteria "docs/plans/phase-aj/sprint-AJ1.md" .
"""


def _write_structures(root: Path, phases: dict[str, str]) -> None:
for phase, text in phases.items():
phase_dir = root / ".sprints" / phase
phase_dir.mkdir(parents=True)
(phase_dir / "structure.ttl").write_text(text)


class SprintSelectionTests(unittest.TestCase):
def test_declared_branch_still_maps_without_sprint_id(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write_structures(root, {"BB": BB_STRUCTURE})
phase, _, sprint = qof._sprint_for_branch(root, "feature/bb6-prompt-handoffs", None)
self.assertEqual(phase, "BB")
self.assertEqual(sprint, TRIAGE["BB6"])

def test_undeclared_stacked_layer_fails_closed_and_names_sprint_flag(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write_structures(root, {"BB": BB_STRUCTURE})
with self.assertRaises(qof.QueryError) as caught:
qof._sprint_for_branch(root, "fix/bb6-cli-qa2", None)
self.assertIn("--sprint <ID>", str(caught.exception))

def test_sprint_id_selects_sprint_for_undeclared_branch(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write_structures(root, {"BB": BB_STRUCTURE})
phase, _, sprint = qof._sprint_for_branch(root, "fix/bb6-cli-qa2", None, "BB6")
self.assertEqual((phase, sprint), ("BB", TRIAGE["BB6"]))

def test_sprint_id_ambiguous_across_phases_needs_phase(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write_structures(root, {"BB": BB_STRUCTURE, "AJ": AJ_STRUCTURE})
with self.assertRaises(qof.QueryError) as caught:
qof._sprint_for_branch(root, "fix/bb6-cli-qa2", None, "BB6")
self.assertIn("found 2", str(caught.exception))
phase, _, sprint = qof._sprint_for_branch(root, "fix/bb6-cli-qa2", "BB", "BB6")
self.assertEqual((phase, sprint), ("BB", TRIAGE["BB6"]))

def test_unknown_sprint_id_fails_closed(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write_structures(root, {"BB": BB_STRUCTURE})
with self.assertRaises(qof.QueryError) as caught:
qof._sprint_for_branch(root, "fix/bb9-x", "BB", "BB9")
self.assertIn("sprint 'BB9'", str(caught.exception))


class IntegrationCandidateTests(unittest.TestCase):
CANDIDATES = [
(Path("/wt/integrate/phase-aq"), "integrate/phase-aq"),
(Path("/wt/integrate/phase-az"), "integrate/phase-az"),
(Path("/wt/integrate/phase-bb"), "integrate/phase-bb"),
]

def test_single_candidate_wins_without_phase(self) -> None:
self.assertEqual(
qof.choose_integration_candidate(self.CANDIDATES[:1], None), self.CANDIDATES[0][0]
)

def test_multiple_candidates_without_phase_is_ambiguous(self) -> None:
self.assertIsNone(qof.choose_integration_candidate(self.CANDIDATES, None))

def test_phase_selects_matching_worktree_case_insensitively(self) -> None:
for phase in ("BB", "bb", "phase-bb"):
with self.subTest(phase=phase):
self.assertEqual(
qof.choose_integration_candidate(self.CANDIDATES, phase),
Path("/wt/integrate/phase-bb"),
)

def test_phase_without_matching_worktree_stays_ambiguous(self) -> None:
self.assertIsNone(qof.choose_integration_candidate(self.CANDIDATES, "AX"))

def test_no_candidates_is_ambiguous(self) -> None:
self.assertIsNone(qof.choose_integration_candidate([], "BB"))


class ClosedFindingTests(unittest.TestCase):
def _graph(self, body: str) -> tuple[Graph, URIRef]:
graph = Graph()
graph.parse(
data="@prefix triage: <urn:atm:triage:> .\n<urn:atm:triage:finding/X> a triage:Finding ;\n" + body,
format="turtle",
)
return graph, URIRef("urn:atm:triage:finding/X")

def test_open_finding_is_not_closed(self) -> None:
graph, finding = self._graph(' triage:status "open" .\n')
self.assertFalse(qof.is_closed_finding(graph, finding))

def test_terminal_status_appended_beside_open_is_closed(self) -> None:
graph, finding = self._graph(' triage:status "open" ;\n triage:status "fixed" .\n')
self.assertTrue(qof.is_closed_finding(graph, finding))

def test_closed_flag_is_closed(self) -> None:
graph, finding = self._graph(' triage:status "open" ;\n triage:closed true .\n')
self.assertTrue(qof.is_closed_finding(graph, finding))

def test_resolution_record_is_closed(self) -> None:
graph, finding = self._graph(
' triage:status "open" .\n'
"<urn:atm:triage:resolution/X/1> a triage:Resolution ; triage:resolves <urn:atm:triage:finding/X> .\n"
)
self.assertTrue(qof.is_closed_finding(graph, finding))

def test_non_terminal_status_values_stay_open(self) -> None:
graph, finding = self._graph(' triage:status "open" ;\n triage:status "in_progress" ;\n triage:closed false .\n')
self.assertFalse(qof.is_closed_finding(graph, finding))


class OccurrenceFilesTests(unittest.TestCase):
def test_occurrence_files_are_collected_sorted_and_deduped(self) -> None:
graph = Graph()
graph.parse(
data=(
"@prefix triage: <urn:atm:triage:> .\n"
"<urn:atm:triage:finding/X> a triage:Finding ; triage:hasOccurrence <urn:o/1>, <urn:o/2> .\n"
'<urn:o/1> triage:file "crates/atm/src/b.rs" .\n'
'<urn:o/2> triage:file "crates/atm/src/a.rs" ; triage:file "crates/atm/src/b.rs" .\n'
),
format="turtle",
)
self.assertEqual(
qof.occurrence_files(graph, URIRef("urn:atm:triage:finding/X")),
["crates/atm/src/a.rs", "crates/atm/src/b.rs"],
)


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion .claude/skills/codex-orchestration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Before starting a sprint:
vars). The template path goes through the daemon-owned admission path
and the dispatch is queryable from outside.
9. `.claude/agents/rust-best-practices-agent.md` and
`.claude/skills/codex-orchestration/rust-best-practices-agent-assignment.json.j2`
`.claude/assets/sc-rust/quality-mgr/templates/rust-best-practices-assignment.json.j2`
exist for first-pass boundary optimization review.
10. Every agent pane exports `BEADS_ACTOR` equal to its `ATM_IDENTITY` (the
pane name, not an alias), and bead assignee values use those same names.
Expand Down

This file was deleted.

Loading
Loading