Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Trevin Chow <tmchow@users.noreply.github.com>
6.6 KiB
Grounding Validation (Phase 2.45)
Read this when Phase 2.45 runs. The doc just written becomes permanent, trusted knowledge. Future agents will act on its claims without re-verifying them. This phase checks the claims against reality before they compound: a deterministic mechanical pass (bundled script) plus a semantic pass (one read-only validator subagent). Neither pass is a hard stop. You judge every flag, because solution docs legitimately cite deleted paths and pre-fix states.
Which tree is the ground truth
Two claim categories verify against different trees:
- Code-behavior claims (enum values, status semantics, limits, defaults) verify against the local working tree. They describe what this session's work produced and verified here.
- Merge-state claims ("fixed in #1608", "landed", "shipped") verify against remote truth. The checkout may predate a merge, so
gh pr view(or the tracker equivalent) is primary and local git reachability is only the fallback. The script'sINFO: worktree is N commits behind …line tells you how much to distrust the local tree for this category.
Before running the script, optionally run git fetch --quiet (best-effort; skip silently on failure or offline, because the network is never a correctness dependency). When remote state cannot be checked at all, keep the claim, add an as-of qualifier ("as of this writing"), and record degraded verification in the run report.
Step 1: Adjudicate the mechanical flags
The script reports in two tiers and you decide each item. A FLAG is a claim it can defend; a NOTE is an item it reported without being able to classify, and notes do not affect its exit code. There are three resolutions, fix, annotate, or confirm intentional, and never an automatic rewrite or an automatic pass:
| Flag | Likely meaning | Resolution |
|---|---|---|
| path not found anywhere | Typo, or drafted from memory | Fix the citation or remove the claim |
| path missing here, exists at upstream | Stale checkout | Verify the claim against upstream; annotate if the doc implies the file is present locally |
| path deliberately gone (doc says removed/renamed) | Historical citation | Confirm the surrounding prose marks it as historical ("removed by this fix", "pre-fix state"); add that marker if absent |
| SHA does not resolve, cited as a commit | Fabricated or from another repo | Replace with the PR number, or drop |
| NOTE: unresolved hex, no commit context | The script cannot tell a session id or content hash from a commit; it is reporting, not accusing | Read the line: if it was never a commit citation, nothing to do; if it was, verify it |
| SHA reachable from HEAD only | Local-only commit; SHA will change on rebase/squash merge | Replace with the PR number |
| SHA reachable from upstream only | Checkout predates the merge | Keep, with a temporal qualifier; verify the landed claim via gh |
| SHA exists but unreachable | Rebased-away commit | Replace with the PR number |
scaffold ("Learning 3", {{…}}) |
Drafting-context leak | Always fix; rewrite as a real path or link |
| relative link unresolved | Wrong target | Fix the path |
If the script cannot be resolved on this platform, apply its checks manually at the same scope: scan the body for cited paths that do not exist, hex words presented as commits anywhere in the body (in commands and code blocks as much as in prose), Learning(s) N / {{…}} scaffold, and broken relative links. Note in the run output that the check was manual. Do not silently skip.
After any body edit from this step or Step 2, re-run the script until it reports clean or every remaining flag is confirmed intentional.
Step 2: Semantic validator subagent (Full and non-interactive; skipped in lightweight)
Dispatch one generic read-only subagent covering the written solution doc plus any CONCEPTS.md entries added or edited this run. Phase 2.4's entries are claims too; a glossary entry written from a session-level summary is exactly how wrong semantics enter the vocabulary. Use the same mid-tier model class as other reviewer subagents when the platform exposes one. Build its prompt from this template:
You are a grounding validator for documentation about to enter a permanent
knowledge store. You are read-only: never edit files. Inspect with Read,
Grep, Glob, git (non-mutating), and gh when available.
Inputs: the doc content below, the CONCEPTS.md entries below (if any), and
this staleness context: <INFO line from the mechanical script, or "none">.
Check every factual claim in three categories:
1. CODE-BEHAVIOR CLAIMS — assertions about how code behaves: enum values,
status semantics, limits, defaults, ordering, state transitions. For
each, locate the defining source in the current tree and quote the
defining line(s) with file:line. Verdict: verified (with quote),
contradicted (with the quote showing otherwise), or unverifiable
(defining source not found).
2. MERGE-STATE CLAIMS — assertions that a change landed ("fixed in",
"merged", "shipped in", "resolved by #N"). Primary check: gh pr view
<n> --json state,mergedAt,baseRefName (remote truth). Fallback: git
reachability from the upstream default branch. Verdict: verified,
contradicted (e.g. PR open, not merged), or unverifiable (offline / no
gh) — mark unverifiable as "degraded", do not guess.
3. INTERNAL COMPLETENESS — countable assertions ("six PRs", "three root
causes", "all N consumers"). Count the substantiating items in the doc
itself. Verdict: complete, or short (found M of N).
Ignore session narrative ("we first tried X") — that describes the
conversation, not the tree. Ignore style.
Return a structured list, one entry per claim checked:
claim (verbatim) | category | verdict | evidence (quote + file:line, or
command output) | suggested edit (only for non-verified claims)
Orchestrator handling of verdicts:
- contradicted → fix the doc using the quoted evidence (the quote, not the conversation, is authoritative)
- unverifiable (behavior) → soften or attribute ("per this session's conclusion…"), or drop the claim
- unverifiable/degraded (merge-state) → keep with an as-of qualifier; record degraded verification in the report
- short (completeness) → complete the enumeration or restate the count to match what the doc substantiates
- verified → no change
Reporting
Summarize the phase in one line of the run output (non-interactive report's Grounding: line; interactive success output): flags adjudicated (fixed / annotated / confirmed), claims checked, claims softened or corrected, and degraded — merge-state claims unverified offline when applicable.