Skip to content

Checks and findings

Every check is deterministic, offline and read-only. Nothing here writes a file, calls a model, or touches the network.

The checks

They run in this order, and each prints one line in human output:

CheckCategoryVerifies
manifestmanifestThe manifest exists, parses, and declares a supported schema.
context structurestructure.context/ exists, belongs to Syngraphe, and has the expected files.
internal referencesreferencesLocal paths referenced from context documents resolve.
AGENTS.mdagentsThe AGENTS.md managed block is present, unique and unmodified.
Claude integrationagentsCLAUDE.md points at AGENTS.md, when Claude is used here.
context statestatestate/current.md says something, and has not silently fallen behind.

Checks do not cascade. When .context/ is absent, the structure check reports it once and the others stay quiet rather than adding six symptoms of the same cause.

Integrations that write nothing — Cursor, Codex — contribute no check: there is nothing about them that can be wrong.

Finding codes

Codes are stable. They are never renumbered, never reused for a different meaning, and never named after internal implementation details.

Structure — CTX

CodeSeverityMessageMeaning
CTX001errorRepository context is not initialized.No .context/. Run syngraphe init.
CTX002errorExpected context file is missing.One of the seven schema files is absent. init restores it.
CTX003error.context/ is not a Syngraphe repository context.The directory exists but belongs to something else.

Manifest — MANIFEST

CodeSeverityMeaning
MANIFEST001error.context/manifest.json is missing while the rest of the context exists.
MANIFEST002errorThe manifest is not valid JSON, is not an object, or has no numeric schemaVersion. The parser's message is included as details.
MANIFEST003errorThe manifest declares a schema version this build does not support. Forces exit code 3.
MANIFEST004warningThe manifest declares a layout this build does not know.

AGENTS.mdAGENT

CodeSeverityMeaning
AGENT001errorAGENTS.md has no Syngraphe block. Run syngraphe init.
AGENT002errorThe block was modified manually. Syngraphe will not overwrite it.
AGENT003errorThe file contains more than one Syngraphe block.
AGENT004errorThe markers are unbalanced. The finding carries the line number.
AGENT005errorAGENTS.md cannot be managed safely — it is a directory, a symlink, or declares an unknown block version.

These are errors rather than warnings because .context/ without a bootstrap is context nothing will read.

Claude — CLAUDE

CodeSeverityMeaning
CLAUDE001warningClaude is used in this repository (a CLAUDE.md or .claude/ exists) but nothing imports AGENTS.md.
CLAUDE002errorThe CLAUDE.md managed block was modified manually.
CLAUDE003errorCLAUDE.md contains duplicate Syngraphe blocks.
CLAUDE004errorThe markers in CLAUDE.md are unbalanced.
CLAUDE005warningA setup Syngraphe deliberately leaves alone, such as a symlink pointing elsewhere.

A missing integration is a warning, not an error: an agent nobody uses here needs no file. Nothing at all is reported for a repository that shows no sign of using Claude.

CodeSeverityMeaning
LINK001errorA context document references a local path that does not exist. The finding carries the file and the line.

Markdown links resolve relative to the document. Inline-code references — `truth/architecture.md` — are also accepted if they resolve from the repository root, because prose commonly quotes a repository-relative path. Fenced code blocks, anchors and external URLs are ignored.

State — STATE

CodeSeverityMeaning
STATE001warningstate/current.md has not changed in N days while the repository has.
STATE002warningstate/current.md contains only headings.

How freshness is judged

STATE001 is raised only when both conditions hold:

  1. the last commit touching .context/state/current.md is at least 45 days old, and
  2. the repository has commits newer than that one.

If Git cannot answer — no history, an untracked file, a shallow clone, no git on the PATH — the check stays silent. An unanswerable question produces no finding.

The message states the age and asks for a review:

text
WARN STATE001  .context/state/current.md
.context/state/current.md has not changed in 47 days.
This may be intentional. Review whether it still reflects the current repository state.

What it deliberately does not say is ERROR: context is stale. Age is a signal, not a verdict: a document can be old and perfectly accurate, and a tool that cries wolf about it teaches people to ignore the one time it matters.

Severity and exit codes

SeverityDefault run--strict
errorfails (exit 1)fails (exit 1)
warningreported only (exit 0)fails (exit 1)
inforeported onlyreported only

MANIFEST003 is the one special case: it forces exit code 3 regardless, because an unsupported schema makes every other answer unreliable.

Adding a check

The registry is a list, and each check is a small object:

ts
interface Check {
  id: string;
  label: string;         // the line printed in human output
  category: CheckCategory;
  run(context: CheckContext): Promise<Finding[]>;
}

CheckContext is a snapshot gathered once per run — the repository, the context inspection, the AGENTS.md state, every agent's state, and the reference instant used by age-based checks. Checks read from it; they never print, never write, and never decide the exit code.

Adding one means: a module in src/checks/, a line in the registry, a new stable code, tests, and a row in this table.

Syngraphe v0.1.0 · context schema v1 · GitHub