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
16 changes: 13 additions & 3 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,17 @@ crates/evidence-core/tests/fixtures/compliance/** binary
Cargo.lock text eol=lf
rust-toolchain.toml text eol=lf

# Golden wire-shape fixture for `cargo evidence rules --json`. Keep
# literal bytes so cross-OS checkouts don't mangle line endings and
# trip the byte-diff test.
# Golden wire-shape fixtures byte-diffed against the CLI output —
# keep literal bytes so cross-OS checkouts don't mangle line endings
# and trip the byte-diff tests.
crates/cargo-evidence/tests/fixtures/golden_rules.json binary
crates/cargo-evidence/tests/fixtures/golden_context.json binary

# Certification config (boundary, profiles, floors, trace/*.toml) is
# read by `cargo evidence context --json` and its multi-line
# `description = """ ... """` blocks flow through into the JSON
# response. On Windows with `core.autocrlf=true`, git checks these
# out with CRLF and the CLI embeds `\r\n` in the JSON string values,
# breaking the byte-diff against the LF golden fixture. Force LF on
# checkout so cross-OS contributors see identical bytes.
cert/**/*.toml text eol=lf
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ Mechanical enforcement: `walker_usage_locked` asserts (a) no unallowlisted `fs::
Default: every PR seeds its SYS/HLR/LLR/TEST entries in the first commit on the branch, before any implementation. The trace chain is the contract; the code implements it.

**Exception — bidirectional contracts spanning two PRs.** When a single SYS-level claim covers both directions of a contract (e.g., forward-enrichment in one PR + reverse-verification in a follow-up), the *second* PR seeds the chain for both halves. The first PR ships functionality under an implicit trace obligation; the second PR's chain-seed discharges it for both. This is rare — only legitimate when the two halves form one logical deliverable and splitting the chain would force referencing UUIDs that don't yet exist. Do not generalize: if a later PR's scope is independent (new surface, different concern), seed its own chain from commit 1 as normal.

## Module-level context for agents

This repo follows the *lean root + layered subdirectory* `CLAUDE.md` pattern from [Anthropic's large-codebases guide](https://claude.com/blog/how-claude-code-works-in-large-codebases-best-practices-and-where-to-start). Root `CLAUDE.md` (this file) carries project-wide rules; each crate's `crates/<x>/CLAUDE.md` carries local conventions and the scoped test command for that crate.

For per-module trace + boundary + floors context on any source file, call `evidence_context` (MCP) or `cargo evidence context <path>`. Don't grep `cert/trace/*.toml` manually — the query is cheap and returns the requirements governing the file, their parent HLR / SYS roots, the tests that verify them, the diagnostic codes the module owns, and the floors it must respect. Design spec: `docs/superpowers/specs/2026-05-19-agent-context-from-evidence-design.md`.
23 changes: 12 additions & 11 deletions cert/floors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,29 @@ schema_version = 1

# evidence_core::RULES length — every diagnostic code the tool can emit,
# hand-curated. Lives in a single crate, so workspace-wide.
diagnostic_codes = 154
diagnostic_codes = 162

# evidence_core::TERMINAL_CODES length — hand-emitted terminals
# (VERIFY_OK / VERIFY_FAIL / VERIFY_ERROR / CLI_SUBCOMMAND_ERROR /
# DOCTOR_OK / DOCTOR_FAIL / KEYGEN_OK / KEYGEN_FAIL).
terminal_codes = 15
# DOCTOR_OK / DOCTOR_FAIL / KEYGEN_OK / KEYGEN_FAIL /
# CONTEXT_OK / CONTEXT_FAIL / CONTEXT_ERROR).
terminal_codes = 18

# cert/trace/sys.toml — System Requirements.
trace_sys = 30
trace_sys = 31
# cert/trace/hlr.toml — High-Level Requirements.
trace_hlr = 71
trace_hlr = 75
# cert/trace/llr.toml — Low-Level Requirements.
trace_llr = 78
trace_llr = 87
# cert/trace/tests.toml — Test Cases.
trace_test = 83
trace_test = 93

# evidence_core::trace::surfaces::KNOWN_SURFACES length — hand-curated
# catalog of CLI verbs + named observable contracts. Matching HLR
# coverage is enforced by `require_hlr_surface_bijection`; this floor
# guards against silently shrinking the catalog itself (which would
# relax the bijection without firing the check).
known_surfaces = 23
known_surfaces = 26

# --------------------------------------------------------------------
# Per-crate-true dimensions: one table per in-scope crate.
Expand All @@ -78,13 +79,13 @@ known_surfaces = 23

[per_crate.evidence-core]
# `#[test]` attribute count inside crates/evidence-core/**/*.rs.
test_count = 367
test_count = 384

[per_crate.cargo-evidence]
test_count = 154
test_count = 166

[per_crate.evidence-mcp]
test_count = 45
test_count = 55

# Per-crate ceilings. library_panics is a ceiling, not a floor:
# more panics is always worse. Placing a ceiling dimension under
Expand Down
102 changes: 102 additions & 0 deletions cert/trace/hlr.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1800,3 +1800,105 @@ keypair), the check is a no-op.
verification_methods = ["test"]
traces_to = ["d469f0fa-0816-47a8-9452-b73e65f4cfd7"]
surfaces = ["generate"]

[[requirements]]
uid = "d33a1a39-c57a-48cc-9138-c4f8ff61f77d"
id = "HLR-072"
title = "Repo demonstrates lean-layered CLAUDE.md doctrine"
owner = "tool"
scope = "component"
description = """
Each workspace crate under `crates/` ships a `CLAUDE.md` file that
(a) carries local conventions only — not a re-statement of root
rules; (b) documents its own scoped test command
(`cargo test -p <crate-name>`) so agents and humans avoid running
the full workspace suite for a single-crate change; (c) stays under
an 80-line cap so the file remains skimmable. The root `CLAUDE.md`
holds project-wide rules + a pointer to the per-module agent-context
surface; it must not absorb per-crate detail. The doctrine is
enforced mechanically by an integration test so adding a new
workspace crate without a `CLAUDE.md` fails CI.
"""
verification_methods = ["test"]
traces_to = ["d8d1f204-3909-418d-b62a-1e28edd088ed"]
surfaces = ["layered CLAUDE.md (root + crates/*/CLAUDE.md)"]

[[requirements]]
uid = "5ccff935-87c2-4b57-a78b-459d1eb81ad2"
id = "HLR-073"
title = "cargo evidence context CLI verb returns per-module trace slice"
owner = "tool"
scope = "component"
description = """
`cargo evidence context [<selector>]` returns a structured per-module
context blob: the LLR-level requirements governing the selector
(file path under `crates/<crate>/...`, workspace crate name, or
Rust module path), their parent HLR / SYS rollup, the tests that
verify them, the diagnostic codes those LLRs own, the per-crate
floors / ceilings, the boundary slice, and the nearest layered
`CLAUDE.md`. Selector resolution prioritises file > crate > module
on ambiguity. The graceful-degradation path (no `cert/trace/`) maps
to `CONTEXT_NO_TRACE_CONFIGURED` (info) + `CONTEXT_OK` (exit 0);
invalid selectors emit `CONTEXT_SELECTOR_OUT_OF_SCOPE` + the
`CONTEXT_FAIL` terminal (exit 2); runtime / I/O failures emit
`CONTEXT_ERROR` (exit 1). Output is text (default), `--json` (single
blob), or `--format=jsonl` (report line + per-warning diag +
terminal). The wire shape is byte-locked against a golden fixture.
"""
verification_methods = ["test"]
traces_to = ["d8d1f204-3909-418d-b62a-1e28edd088ed"]
surfaces = ["context"]

[[requirements]]
uid = "f88508e9-eb70-4ee6-bb3e-13f07e4f181b"
id = "HLR-074"
title = "evidence_context MCP tool returns per-module trace slice"
owner = "tool"
scope = "component"
description = """
`evidence_context` is the seventh `#[tool]` on the MCP `Server`. It
takes a `ContextRequest` with an optional `workspace_path` and at
most one of `selector` (file/crate/module string), `crate_name`
(crate disambiguator), or `module` (module-path disambiguator), and
returns a `ContextToolResponse` carrying the single JSON blob
emitted by `cargo evidence context [--crate <c> | --module <m> |
<selector>] --json`. The handler spawns the CLI verb through the
existing `subprocess::run_evidence` plumbing (no new transport
machinery), prepends workspace-fallback + version-skew warnings via
the shared response helpers, and surfaces tool-layer failures
(subprocess could not spawn / timed out / produced malformed JSON)
as a well-formed response with `context = None`, `exit_code != 0`,
and a structured `MCP_*` diagnostic in `error`. Mutual-exclusivity
of the three selector fields is validated at the handler layer and
returned as `Err(String)`. No new diagnostic codes — the underlying
content vocabulary (`CONTEXT_*`) is owned by the CLI verb (HLR-073).
"""
verification_methods = ["test"]
traces_to = ["d8d1f204-3909-418d-b62a-1e28edd088ed"]
surfaces = ["context"]

[[requirements]]
uid = "e93c01e2-b5e8-48f4-94ee-e08c139245ae"
id = "HLR-075"
title = "cargo evidence init --with-agent-context scaffolds downstream CLAUDE.md"
owner = "tool"
scope = "component"
description = """
`cargo evidence init` accepts `--with-agent-context` (default on)
and `--no-agent-context` (mutually exclusive). When on, the
command emits a starter root `CLAUDE.md` (≤30 lines, lean: title
+ project-description placeholder + pointer to `evidence_context`
/ `cargo evidence context` + per-crate-CLAUDE.md guidance — no
project rules) and a `.claude/settings.json` snippet registering
`evidence-mcp` as an MCP server with a `permissions.deny` entry
for the default `evidence/**` output dir. Existing files are
preserved unconditionally (matches `init`'s pre-existing
no-overwrite behavior); when `.claude/settings.json` already
exists, the command prints one stderr info line explaining what
the user would merge in by hand and continues. New emissions log
via the same JSONL `INIT_TEMPLATE_WRITTEN` channel as the
`cert/` tree so machine consumers see one stream.
"""
verification_methods = ["test"]
traces_to = ["d8d1f204-3909-418d-b62a-1e28edd088ed"]
surfaces = ["init"]
Loading
Loading