I0808 — Extract nodes with identities that survive a rebuild
Implement the extract and normalise stages in lib/knowledge.awk: one node per canonical object, with an identity derived from its canonical id or its repository path, a kind that is only asserted when a structural fact establishes it, and a title taken from the record or from the document's first heading.
DONE wave 2 · 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 extract and normalise stages in lib/knowledge.awk: one node per canonical object, with an identity derived from its canonical id or its repository path, a kind that is only asserted when a structural fact establishes it, and a title taken from the record or from the document's first heading.
Why
Identity is what makes the index a pointer rather than a copy. An id derived from enumeration order or from a title changes when something unrelated changes, and every reference to it silently becomes wrong. Classification that guesses from prose is the same failure in another dimension: a confident wrong kind is worse than an honest unknown.
Current state
The canonical objects already have identities — claims, milestones, issues, profiles, prompts and doctrines are all keyed — and lib/project.awk is the precedent for deriving a model in awk from flattened records.
Desired state
Nodes are emitted in a stable order with ids of the form kind and canonical key, where the key is the object's own id for structured records and its repository path for documents. A kind is asserted from the source class or from an explicit field, never from a keyword found in prose, and an unrecognised source yields the unknown kind rather than a guess.
Scope
- lib/knowledge.sh
- lib/knowledge.awk
- test/cases/73_knowledge_nodes.sh
Out of scope
- Edges
- The manifest
- Any full Markdown parser
Dependencies
What waits on this
Acceptance criteria
- Two syncs of an unchanged repository produce byte-identical node output
- Renaming a document changes that document's node id and no other
- A node's kind comes from its source class or an explicit field, and a case proves prose containing a kind word does not change it
- An unrecognisable source produces a node of kind unknown rather than being dropped or guessed at
- Extraction from a generic Markdown document takes only the path, the first heading and explicit links
Validation
- bash test/run.sh 73_knowledge_nodes
Evidence required
- node_identity_stable
- unknown_stays_unknown
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| node_identity_stable | test | test/run.sh 73_knowledge_nodes | 1 passed. Two runs produce identical bytes; editing a document keeps its node id and moves only its own hash; renaming one is a delete and an add that disturbs no other id; answering a question leaves its identity unchanged. The last of those was a real defect: keying a question on its whole line changed the identity the moment somebody answered it, and the mutation that restores that behaviour fails the case | 2e96215 |
| unknown_stays_unknown | test | test/run.sh 73_knowledge_nodes | 1 passed. A document whose body discusses roadmaps, milestones and policies is a document; a source class declaring a kind the extractor has no rule for yields a node of kind unknown plus one WARN naming the class, rather than being dropped or guessed at; a document with no heading gets an empty title rather than its filename. Two further defects surfaced while proving it: the extractor keyed sources by path, so two classes discovering one file overwrote each other's kind, and the reader handed a Markdown file to the YAML flattener and complained that it was not YAML | 2e96215 |
Risk
Deriving a document id from its path means a rename is a delete and an add, which is correct and will look like churn. The alternative, a content hash identity, makes an edit a delete and an add, which is worse.
Timeline
- started
- 2026-09-04T17:46:56Z
- verified
- —
- completed
- 2026-09-04T17:59:30Z
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/I0808.yaml. Read it back with majordomus plan show I0808.