feat: add canonical per-solution controls-covered.json export#221
Conversation
Addresses framework finding U-050 (P2). Each of the 36 solutions now emits a `controls-covered.json` with its framework control IDs and coverage level (full/partial), generated deterministically from `manifest.yaml` by `build-manifest.py`. New artifacts: - `scripts/controls-covered.schema.json` — JSON Schema for the export - `<slug>/controls-covered.json` × 36 — per-solution control maps - `build-manifest.py` emitter + `--check` drift detection The framework `solutions-lock.json` can now consume these files as the canonical per-solution contract instead of manual maintenance. Closes #163 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06a3882ec5
ℹ️ 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".
| {"id": ctrl, "coverage": "full"} | ||
| for ctrl in m.get("controls", []) |
There was a problem hiding this comment.
Honor partial coverage when emitting controls-covered.json
Do not hardcode coverage to "full" for every control here, because this makes the new export inaccurate as soon as a solution only partially implements a control. The schema and docs explicitly model full|partial, but this emitter currently cannot produce partial, so downstream consumers will overstate implementation strength for those solutions.
Useful? React with 👍 / 👎.
Summary
Addresses framework finding U-050 (P2) — adds canonical per-solution control-coverage export so customers and the framework can answer "which controls does Solution X implement?" without manual maintenance.
Changes
scripts/controls-covered.schema.json— JSON Schema (v1.0.0) defining the per-solution export format withfull/partialcoverage levelsscripts/build-manifest.py— newemit_controls_covered_json()emitter; wired into the build pipeline with--checkdrift detection<slug>/controls-covered.json× 36 — generated per-solution control mapsExample output (
action-confirmation-auditor/controls-covered.json){ "schemaVersion": "1.0.0", "generatedBy": "scripts/build-manifest.py", "solutionId": "action-confirmation-auditor", "solutionName": "Action Confirmation Auditor", "solutionVersion": "1.2.1", "status": "live", "controls": [ { "id": "2.12", "coverage": "full" }, { "id": "1.10", "coverage": "full" } ], "controlCount": 2 }Acceptance criteria from #163
controls-covered.jsonsolutions-lock.jsonconsumes from solution exports (framework-side — separate PR)Validation
python scripts/build-manifest.py --checkpasses (zero drift)python -m pytest scripts/tests/— 30/30 tests pass