If you track requirements as .req.md files (see
Requirements), an AI coding tool can work
with that corpus directly through ten MCP tools instead of parsing the files
itself: three read-only query verbs — req_context, req_search, and
req_justify — req_affected and req_verify, which turn a diff and the
pin-evaluation engine into agent-usable answers, req_acknowledge, the one
governed edge-acknowledgment mutation, req_coverage, which reports
bidirectional traceability coverage over the whole corpus, and three
authoring verbs — req_draft, req_bind, and req_request_acceptance —
that let an agent scaffold a new requirement, bind criteria and anchors to
code, and flag work for a human's review. None of the ten can accept a
requirement. That stays a human act on the command line via
codecharter req; an agent can ground a change in the
requirements behind it, ask whether the criteria the human already accepted
still hold, measure how much of the codebase is justified, propose a
skeleton or a binding for a human to review, or record a governed sign-off
on one specific analysis gap — but it cannot decide a requirement is
satisfied.
Why acceptance never routes through MCP
An accepted requirement is a claim that the code actually does what the
requirement says — a judgment call the corpus format deliberately routes
through a human, not an inference an agent gets to make on the corpus's
behalf. The three query tools below therefore only ever report what the
corpus and the code graph already say, and the three authoring tools below
only ever propose text for a human to review — one narrow governed mutation
in req_acknowledge aside, the actual acceptance
decision, and every pin field it produces, has no MCP tool at all, by
design.
req_context
Everything relevant to a code symbol or file, in one call: its directly
anchored requirements, plus what transitively justifies it (via the
[Satisfies] call-graph reachable from an anchor), what it refines, and what
overlaps with it (other requirements that share a justifying-method
footprint, useful for co-retrieval).
target resolves the same way the graph tools resolve theirs: an exact or
case-insensitive full type/method name, a name suffix, or a source file path.
An ambiguous or unresolved target returns a candidate list instead of
guessing. include selects which of the four relation sections to compute
(anchored, justified, refines, overlaps — all four by default), and
prose controls how much of each requirement's prose body comes back
(none, summary, or full).
A requirement reached by more than one relation keeps only its strongest one — a direct anchor beats a transitive justification, which beats a refines edge, which beats an overlap — so the same id never appears labeled with weaker evidence than what was actually found.
req_search
Find requirements by id, status, kind, priority, the contractual
flag, section, or a free-text query over id, title, and prose. Results
are ranked by match strength (an id match first, then title, then prose) and
sorted by id within a tier, so the same corpus in any input order always
returns the same result order.
req_justify
The reverse of req_context: starting from a code symbol or file, walk back
to the requirement roots that justify it existing at all. The result's
outcome is one of three states:
justified— at least one requirement's[Satisfies]anchor reaches the target through the call graph.not_justified— the target resolved to real, analyzable code, and the search genuinely found nothing.unknown— anything short of that: no code model available, or a target that didn't resolve to an analyzable declaration.
Absence of evidence is never rendered as not_justified. That distinction
matters: a tool that can't tell "nothing justifies this" apart from "I
couldn't check" would train you to stop trusting its not_justified
verdicts.
witness controls how much justifying evidence comes back alongside the
outcome: none, roots (the justifying requirement's [Satisfies] anchor
sites, labeled as set membership — the default), or paths (opt-in, a
token-bounded breadth-first search for an actual call path from an anchor to
the target, deterministic and capped at a fixed hop limit — a null path
means none was found within the bound, not that none exists).
Rule criteria are never evaluated by the query verbs
A requirement's rule: criteria — the ones checked against your solution's
graph — are deliberately never evaluated by the query verbs. Of the three,
only req_context reports criterion state at all, and it evaluates just the
pin-derived criteria (test, manual, integration, external); req_search and
req_justify report no criterion state to evaluate. A requirement carrying a
rule: criterion still comes back from req_context, with that criterion
marked as not evaluated here rather than silently omitted or guessed at. Run
codecharter req check, the analyze/analyze_diff MCP
tools, req_verify (below) or req_coverage for the real verdict — see
Rule Criteria.
req_affected
The req-level counterpart to analyze_diff: which requirements a diff
touches, and which criteria's pins that diff may have invalidated. Matching
is file-level — a requirement's own .req.md changed, or a file+selector
anchor's file changed — and every matched criterion reports a pin_impact
signal (rule-input-changed, fingerprint-suspect, test-hash-suspect,
none, or unknown-analysis-unavailable when no code model was available).
pin_impact is never a verdict, and it is never none without a model — it
says "this diff changed an input the pin depends on", not "the pin is now
stale". That verdict belongs to req_verify. Omitting diff/git_ref/
files defaults to the working tree against HEAD, same as req_verify's
default scope.
req_verify
The verdict per acceptance criterion — holds, violated, unknown,
stale, or open — with reasons, DSL violations, and unacknowledged edges.
req_verify computes nothing of its own: it is a thin projection of the same
merged evaluator codecharter req check --with-code composes, so a verdict
never differs between the CLI and this tool by construction. No verb reached
through req_verify can mark a criterion fulfilled; the only way a criterion
turns green is for the evaluator to actually confirm it.
scope defaults to diff — the requirements req_affected would report for
the same diff/git_ref inputs — or all for the whole corpus. req_id
(one id or a comma-separated list) takes precedence over scope when
supplied.
req_acknowledge
The one governed exception to "no MCP tool mutates the corpus": recording
that a specific unknown edge in a rule: criterion's evaluation — not a
requirement, not a criterion, one named edge — is understood and accepted
rather than a gap that should keep blocking the verdict. An edge is
something RuleCriterionEvaluator could
not resolve one way or the other (an unrecognized reflection call, a
dispatch/declared-call divergence, and so on); req_verify reports every
live one as unacknowledged_edges on the criterion it blocks.
This is deliberately not requirement acceptance. Acknowledging an edge can
only ever remove one specific, named analysis gap from blocking a verdict the
evaluator still computes fresh on every call — it can never turn a violated
verdict into holds, and it can never touch the pin fields
codecharter req accept owns. Two tiers of edge exist,
and only one is acknowledgeable:
- Tier B (
pattern-matches-no-type,dispatch-divergence,opaque-site) — a genuine analysis gap in an otherwise-successful evaluation. A human can knowingly accept these, andreq_acknowledgewill. - Tier A (analysis-unavailable, criterion-not-compilable, a schema
mismatch, an unbound parameter, an evaluation error, an undecided path
search) — a defect in the criterion or the run itself, not something about
the code to accept.
req_acknowledgerefuses these unconditionally, regardless of what the caller names.
req_acknowledge also refuses an edge that does not currently occur on the
criterion, a non-rule: criterion (only rule criteria carry acknowledgeable
edges), and a call with no reason — an acknowledgment without one is
reported as absent, exactly as if it had not been written at all. A stale
acknowledgment (the edge id it names no longer occurs, because the code
changed) is report-only, surfaced by req_verify, never re-written here.
dry_run defaults to true: the tool returns the unified diff of the exact
edit it would make — appending one entry to the criterion's acknowledge:
sequence, byte-preserving every other line of the file — without writing
anything. Pass dry_run=false once the diff looks right.
req_draft
Scaffolds a new .req.md file: frontmatter, criteria proposed as rule,
test, manual, integration, or external, and anchor proposals. The
composed draft is self-validated through the same parser
codecharter req check uses before it is ever written,
and any diagnostic comes back on the tool's result rather than only surfacing
later on disk.
write defaults to false: the tool always returns the composed skeleton
for a human to review before anything touches disk. Pass write=true once it
looks right. req_draft never creates a requirement silently and never
overwrites one — if req_id already resolves to an existing file, it
refuses; picking a different id, or deciding to edit the existing file, is a
human's call, not a parameter this tool exposes.
req_bind
Adds a criterion or an anchor to an existing requirement, or updates an
existing criterion's carrier value, status, or confidence override.
Every new criterion or anchor is proposed at unverified confidence by
default — req_bind never assumes a carrier is correct just because it was
named. Passing verify_target=true resolves a test carrier's target
against the code model before writing it (other carrier kinds and anchor
targets always come back unverified, since the tool has no way to confirm
they mean what they say). req_bind refuses to switch an existing
criterion's carrier kind outright — that is a re-authoring decision, not an
edit — and it can never write a pin field: the same fields
codecharter req accept owns stay mechanically off
limits, the same way req_acknowledge can't touch them. dry_run returns a
diff preview of the exact edit without writing it.
req_request_acceptance
Marks a criterion as ready for a human's sign-off: writes a requested_by,
requested_on, and optional note marker — never a pin field — and returns
a ready-to-read question plus the exact
codecharter req accept command a human runs to actually
accept it. The marker only ever records that someone asked; it carries no
authority of its own and does not change any criterion's verdict.
dry_run=true previews the same marker without writing it.
req_coverage
Requirement-corpus coverage in both directions — see
Requirements coverage for the full model,
and codecharter req coverage for the CLI
surface over the exact same aggregator (the two never diverge: one shared
IReqCoverageAggregator, two renderers). Per-requirement rollups
(requirement → code), plus every code method classified as justified,
infrastructure-declared, dead-candidate, or
undocumented-requirement-candidate (code → requirement), the last of which
carries a nearest_anchored_neighbour hint that feeds req_draft.
Unlike every other tool on this page, req_coverage has no with_code-style
opt-out: code is its subject matter, so it always analyzes the solution, and
a model that could not be acquired comes back as is_inconclusive: true
with a notice rather than a fabricated percentage. git_ref/diff narrow
the classified/rollup lists only — every total and percentage
(justified_percent, accounted_percent) stays corpus-wide, the same
scope pattern graph_hubs uses. req_coverage is report-only over MCP: it
never writes the tolerated-legacy baseline (--write-baseline is a CLI-only,
disk-writing operation, deliberately absent from this read-only tool) and
never enforces the ratchet gate — that stays a CI-side decision behind
req.coverage.gate.enabled in .codecharter/config.yml.
Token budgets
The seven query, verification, and coverage tools — req_context,
req_search, req_justify, req_affected, req_verify, req_acknowledge,
and req_coverage — accept max_tokens and report estimatedTokens,
matching the graph tools' truncation contract: a result that would exceed the
budget is trimmed (with a notice naming what was cut and why) rather than
silently returned oversized. max_reqs/max_results cap the count
independently of the token budget. req_acknowledge has no max_tokens
parameter — a single edge's diff is always small enough to return whole. The
three authoring tools — req_draft, req_bind, and req_request_acceptance
— likewise take no max_tokens: a composed skeleton, a bind's diff preview,
or an acceptance-request marker is always small enough to return whole.