I0809 — Record only edges that a file states, each with where it was observed
Implement the resolve and graph stages: edges derived from the explicit relationships the canonical files already declare — claim to source, implementation and test; issue to milestone and to its dependencies; evidence to issue; doctrine to validator, claim and test; record to task — each carrying the file and field it was observed in, and none carrying a relationship inferred from prose.
DONE wave 3 · p1 · deep-work profile · runs alone
Part of M003 — A session is a durable envelope, and knowledge is compiled from what is already canonical.
Objective
Implement the resolve and graph stages: edges derived from the explicit relationships the canonical files already declare — claim to source, implementation and test; issue to milestone and to its dependencies; evidence to issue; doctrine to validator, claim and test; record to task — each carrying the file and field it was observed in, and none carrying a relationship inferred from prose.
Why
The repository already contains a dense, hand-maintained, machine-readable graph that no command can traverse. Extracting it costs nothing in accuracy because every edge is stated. Heuristic extraction from prose would add edges nobody wrote, and an edge nobody wrote cannot be checked by the person who would notice it is wrong.
Current state
docs/CLAIMS.yaml states three relationships per claim; the issue files state a milestone and a dependency list; share/doctrines.yaml states a validator, a claim list, a test and the commands that enforce it; every continuity record states its task. Nothing reads any of them as a graph.
Desired state
An edge is a from, a to, a type and a provenance, and the graph stage rejects an edge missing any of the four. Edge types are a closed declared set. A dangling edge — one whose target is not a node — is retained and reported rather than dropped, because a broken reference is the finding.
Scope
- lib/knowledge.sh
- lib/knowledge.awk
- test/cases/74_knowledge_edges.sh
- test/cases/75_knowledge_mutation.sh
Out of scope
- Inferring a relationship from prose
- Any similarity, clustering or taxonomy generation
- Session edges, which arrive with the session integration
Dependencies
What waits on this
Acceptance criteria
- Every edge carries the source file it was observed in, and an edge without provenance is a validation failure rather than a silent drop
- The edge types are a declared closed set and an undeclared type is an error
- Changing a dependency in an issue file changes the graph on the next sync with no generated file edited by hand
- A dangling edge is reported and names both ends
- No edge is produced from a Markdown link whose target is outside the repository
Validation
- bash test/run.sh 74_knowledge_edges
- bash test/run.sh 75_knowledge_mutation
Evidence required
- provenance_required
- mutation_propagates
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| provenance_required | test | test/run.sh 74_knowledge_edges | one case passed. Every edge carries the file and the field or line it was observed in; the case asserts the provenance string of each of the six declared relationship kinds and then checks that no emitted row has fewer than four columns. Two guards are mutation-tested against a copy of the extractor: blanking a provenance argument makes the edge refused with a FAIL rather than emitted with an empty source, and renaming an edge type to one the closed set does not declare is an error rather than a new vocabulary word | 4a7c934 |
| mutation_propagates | test | test/run.sh 75_knowledge_mutation | one case passed. Each mutation edits exactly one canonical file and the case asserts both what moved and what did not: redirecting a dependency moves that edge and leaves every other edge byte-identical; moving an issue to another milestone moves its part_of edge; repointing a claim's implementation repoints that edge; adding a claim adds its node and exactly its three declared edges and disturbs nothing else; deleting an issue removes its node and makes what pointed at it a reported dangling edge. Nothing generated is edited to make any of it happen, and the working tree is byte-identical afterwards | 4a7c934 |
Risk
Markdown links are the one edge source that is not curated. Treating a broken external link as the same severity as a broken claim-to-test reference would make a permanent red gate out of an intentional outbound link; ownership and severity have to be distinguished.
Timeline
- started
- 2026-09-04T18:14:13Z
- verified
- —
- completed
- 2026-09-04T18:31:05Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I0809.yaml. Read it back with majordomus plan show I0809.