Evidence Graph
@ttsc/evidence makes every specification you configure demand an explicit acknowledgement from the code, test, or document that claims to satisfy it. A specification nothing acknowledges fails the build, by name.
It is a rule contributor to @ttsc/lint, not a top-level ttsc plugin, so it needs the lint engine and the compiler that hosts it. Wire Lint & Format first if your build does not run ttsc yet.
Install
npm
npm install -D ttsc @ttsc/lint @ttsc/evidence typescriptThe first build after installing links the contributor’s Go rules into the lint binary and can take several minutes. Later builds reuse the linked binary. Pin TTSC_GO_BINARY and TTSC_CACHE_DIR in CI so that step stays deterministic across matrix runs.
The config file
Register the plugin in the lint.config.ts you already have, and pass the graph as the option of evidence/graph:
// lint.config.ts
import { evidence, type ITtscEvidenceGraphConfig } from "@ttsc/evidence";
import type { ITtscLintConfig } from "@ttsc/lint";
const graph: ITtscEvidenceGraphConfig = {
claims: [
{
type: "typescript",
files: ["src/components/**/*.tsx"],
symbol: "function",
reference: {
type: "markdown",
files: ["docs/requirements/**/*.md"],
symbol: ["h2", "h3"],
},
},
],
};
export default {
plugins: {
evidence,
},
rules: {
"evidence/graph": ["error", graph],
},
} satisfies ITtscLintConfig;That claim reads as one sentence. The components under src claim to implement the requirements, so every H2 and H3 under docs/requirements must be cited by a component.
Read every claim in that direction: files and symbol pick who owes the answers, reference picks the questions they owe.
See it fail
Write a requirement nobody has implemented:
<!-- docs/requirements/discount.md -->
# Discount Policy
## Coupon Stacking {#coupon-stacking}
At most one seller coupon and one platform coupon may combine on a single order.$ npx ttsc --noEmit
error TS16411: [evidence/graph] Missing acknowledgement for 'docs/requirements/discount.md#coupon-stacking' (Markdown H2 'Coupon Stacking' at docs/requirements/discount.md:3) in Claim 1 reference 1 (markdown, symbols: h2, h3). Cite the artifact that answers for this unit with @evidence on a selected typescript host, building that artifact first when none does, or write @evidenceExclude on an eligible carrier when nothing here owes it. Never leave an untrue tag standing just to pass this check; it removes the error, not the problem.
Found 1 error.The diagnostic names the section, the obligation that owes it, and both repairs. Implement it and cite the section:
// src/components/CouponStackingNotice.tsx
/**
* @evidence docs/requirements/discount.md#coupon-stacking Renders the combination limit defined by this rule.
*/
export function CouponStackingNotice() {
return <p>One seller coupon and one platform coupon may be combined.</p>;
}Or record that this population deliberately does not serve it, with a reason a reviewer can veto:
// src/components/SCREEN_EVIDENCE_EXCLUDE.tsx
/**
* @evidenceExclude docs/requirements/discount.md#coupon-stacking Settlement owns coupon combination; reject this exclusion once a screen displays a stacked total.
*/
export const SCREEN_EVIDENCE_EXCLUDE = true;An exclusion has to sit on a public export in a file the claim already selects, so this one lives under src/components/ like any other selected file. Gathering them in one named ledger is what evidenceExcludeCarriers is for, and it is worth declaring before the first exclusion is written.
Findings arrive in every ttsc build, every --noEmit check, every ttsx run, and in the editor. The CI step that already runs ttsc --noEmit gates the graph without a second job.
Match on the bracketed rule id rather than on the number. TS16411 is assigned deterministically from the complete set of loaded contributors, so changing that set can renumber a contributor rule while [evidence/graph] stays stable.
What a green build means
Every H2 and H3 under docs/requirements is either implemented by a component that says which one and why, or excluded by a decision someone wrote down.
That guarantee holds only over what the claim selects. A section in a file the globs miss is not covered, and a passing build says nothing about it. Widening a population is how coverage grows; it is never inferred.
Turn on the file rules
evidence/graph is the graph. Four file rules protect the conditions it depends on:
rules: {
"evidence/graph": ["error", graph],
"evidence/documented": "error",
"evidence/singular": "error",
"evidence/todo": "error",
"evidence/review": "error",
}evidence/documentedrequires a JSDoc block on every selected export, because a block is the only place a citation can live.evidence/singularkeeps one public identity per file, named after the file.evidence/todofails the build on every remaining JSDoc@todo, so a stub cannot be mistaken for finished work.evidence/reviewrequires an@evidenceReviewbeside every acknowledgement. A false tag removes the error, not the problem, and the review is what resolves it.
Start with evidence/graph alone and add the others once the graph is green.
Stage the rollout
To keep findings visible without failing the build, set severity: "warning" on one claim or reference. Omit it or set it to undefined to inherit the enclosing level. severity: "off" disables that claim or reference. See severity precedence.
A claim you are not ready to enforce carries disabled: true. Its shape is still validated, but it contributes no populations, no obligations, no completion hints, and no watched inputs:
{
name: "screens",
type: "typescript",
files: ["src/components/**/*.tsx"],
symbol: "function",
reference: {
type: "markdown",
files: ["docs/requirements/**/*.md"],
symbol: ["h2", "h3"],
},
// Remove once every required screen and its evidence mapping is complete.
disabled: true,
}Declaring the whole graph up front and enabling one claim at a time is the intended adoption path, not a workaround.
Next
-
Evidence Graph: what the graph is for and what it catches.
-
Spec-Driven Development: the backend, frontend, principles, and novel graphs, and the order to adopt them in.
-
Evidence Tags: the grammar your agent will be writing.
-
Configuration: every claim option and all five rules.