Governance & Compliance Traceability¶
Reference for compliance claims on ways and the ways-audit binary: the claim fields, every command, and what the output does and does not show. To add a claim to a way, follow provenance.md. The model and its rationale are in ADR-200, and the finding record in ADR-201.
A way can carry a claim that its guidance is designed to steer work toward a control (NIST 800-53, OWASP, ISO 27001, SOC 2, CIS, IEEE). A claim is a design assertion, the SOC 2 Type I posture: suitably designed at a point in time. It is not evidence that the control operates. Evidence is a finding, built from real sessions (SOC 2 Type II).
ways-audit assemblebuilds finding records; deciding whether a control is satisfied is left to a separate assessor and is out of scope. Read any coverage number as claims made, not conformance achieved.
The chain¶
Control framework (NIST 800-53, OWASP, ISO 27001, SOC 2, CIS, IEEE…)
↓ cited by
Policy document (governance/policies/*.md, human prose)
↓ claimed by
Way + claim ({way}.md + provenance.yaml sidecar)
↓ injected at runtime (the sidecar is never read: zero tokens)
Agent context (the guidance fires when its triggers match)
↓ recorded
Finding (firing events + transcript, judged against satisfied_when)
Each layer above the way compresses the one above it. Every layer down to the claim is authored; the finding is the only one that comes from a session.
Claim fields¶
A claim is a provenance.yaml file in the way's directory (ADR-110). The runtime never reads it.
| Field | Purpose |
|---|---|
policy[].uri |
Source policy document: a relative path, or github://org/repo/path / an http URL for another repo |
policy[].type |
adr, governance-doc, regulatory-framework or control-spec |
controls[].id |
The control the way claims to be designed for |
controls[].justifications[] |
How the guidance is meant to address the control. Assertions, not evidence. |
controls[].satisfied_when |
The determination criterion: the session behavior that would let an assessor mark the control satisfied or other than satisfied (ADR-200 §1, ADR-201). Optional; a control without one can only ever have a process finding (the way fired), never an outcome finding. |
verified |
Date the claim's authoring was last reviewed, YYYY-MM-DD. Not an assessment date. |
rationale |
How the way's guidance turns the cited controls into practice |
ways-audit¶
ways-audit is a sibling of the ways binary (ADR-151). It reads the sidecars on each run and builds its view in memory; nothing is persisted except by assemble --write. It is run by an operator on purpose; no hook or CI job runs it.
It reads one ways root: the current project's .claude/ways/ when there is one, otherwise the shipped ways at ~/.claude/hooks/ways/. --global skips the project. It does not read the personal root, $XDG_CONFIG_HOME/agent-ways/ways/.
| Command | Output |
|---|---|
ways-audit report |
Claim coverage: which ways carry a claim and which do not (the default) |
ways-audit trace <way> |
The chain for one way: policy sources, controls with justifications, verified date, rationale, firing history. Example: ways-audit --global trace softwaredev/delivery/commits |
ways-audit control <text> |
Ways that claim a control matching the text, such as OWASP |
ways-audit policy <text> |
Ways whose policy URI matches the text, such as code-lifecycle |
ways-audit gaps |
Ways without a claim |
ways-audit stale <days> |
Claims whose verified date is older than the given days |
ways-audit active |
Claims beside firing counts from the event log |
ways-audit matrix |
One row per way, control and justification |
ways-audit lint |
Claim integrity: controls and justifications present, policy URIs resolve, verified well formed |
ways-audit assemble [--write] |
The finding dataset; --write appends it to the findings ledger |
ways-audit findings |
The findings ledger |
Every command takes --json.
lint resolves a relative policy URI against the app directory ($XDG_DATA_HOME/agent-ways, where the shipped governance/policies/ lives), then the ~/.claude projection, then the root of the project whose ways it is linting. The working directory is not a base, so the result does not depend on where lint runs. github:// and http URIs are not checked.
Findings: assembled, not determined¶
ways-audit assemble builds one record per claimed way and control: the claim, its satisfied_when criterion, and the firing evidence (counts, sessions as transcript pointers, first and last seen), beside an empty determination. ways-audit never writes a determination; that would manufacture the evidence the claim/finding split exists to keep honest. The label is filled later by an assessor (a person, a deterministic check, or a model), which is a separate system outside agent-ways. With --write, records go to $XDG_STATE_HOME/agent-ways/findings.jsonl, an append-only ledger where each write adds a timestamped snapshot.
flowchart LR
classDef tool fill:#2196F3,stroke:#1565C0,color:#fff
classDef data fill:#FF9800,stroke:#E65100,color:#fff
classDef output fill:#4CAF50,stroke:#2E7D32,color:#fff
W["way + provenance.yaml<br/>(claims)"]:::data
F["event log<br/>(observed firing)"]:::data
P["governance/policies/<br/>(policy source docs)"]:::data
CLI["ways-audit"]:::tool
R["Reports<br/>(coverage, traces,<br/>matrix, lint)"]:::output
D["Finding dataset<br/>(empty determination,<br/>for an assessor)"]:::output
W --> CLI
P --> CLI
F --> CLI
CLI --> R
CLI --> D
Scope¶
- A claim is a design assertion (SOC 2 Type I; an OSCAL Component Definition), not a finding.
- Reports show claim coverage, not conformance. A claim is never "complete"; it waits for a finding.
- This is a first-line aid. In the IIA's Three Lines Model the first line owns risk in the doing of the work; this helps the work take a control-aligned shape at that point. It is not an assessment, attestation or certification. That is the third line, which agent-ways feeds and does not replace.
Policy documents¶
governance/policies/ holds the human-readable interpretation layer that claims point at: why a way exists, what principle it implements, where the boundaries are. If a policy file moves, the claims that point at it break; ways-audit lint catches that.
Adoption¶
Claims are optional and additive; a way without one runs identically.
- Ways: encode how you work.
- Policies: write down why, in
governance/policies/. - Claims: link a way to the controls it is designed to address.
- Reporting:
ways-audit report,gaps,matrix. - Criteria: give each control a
satisfied_whenso it can be assessed. - Findings:
ways-audit assemblebuilds the records an assessor labels.
Across repositories¶
Policy documents and ways often live in separate repositories:
compliance-repo/ your ways/
├── docs/architecture/ └── softwaredev/delivery/commits/
│ ├── ADR-150.md ├── commits.md
│ └── ADR-200.md └── provenance.yaml (policy uri → ADR-150)
└── controls-catalog.md
A claim names its policy by URI, and ways-audit resolves it at query time. Nothing is stored between the repositories, so the two sides stay decoupled.