You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The substrate records problem observations (events) but has no way to thread a problem to what was done about it. When recall surfaces a recurring bug event, the reader's first question — "was this ever addressed, and how?" — has no answer in the record; the link to the response is a dead end. The only relation available today is supersedes/superseded-by, which is the wrong semantics: superseding deprecates the old record, but a problem that has been addressed is not deprecated. It remains a true observation, and its recurrence is signal worth keeping.
Context
supersedes/superseded-by is a 1:1 chain (recall walks it hop by hop in kb-retrieve's normalize.ts). The problem→response link is many-to-many: one response can address many problems, and one problem can accrue many responses.
The responder is frequently not a KB note — a commit, a PR, or a URL — so the relation often can only live on the problem record, not on the responder.
Recall is event-centric (recurrence-recency surfaces events), so the field recall reads must live on the event.
This emerged from Remove the unused immutable flag from the record-type schema #748 (removing the immutable flag). Annotating events with response pointers is the use case that motivated reconsidering event mutability; the conclusion was that a metadata relation, not a frozen or append-only model, is the right home.
Not strictly event-only: any record noting a problem could carry addressed-by, though events are the motivating case.
Why addressed-by, not resolved-by
The field is populated when a response is made, not when its success is confirmed. "Resolved" asserts an outcome the writer usually cannot vouch for at write time: some bugs are verifiably fixed (the steps to reproduce no longer reproduce the error), but refinements to agent guidance only reduce recurrence and are rarely verifiable. addressed-by stays true across that whole spectrum — a full fix and a mitigation both address the problem. Verifiable resolution is a status of the problem, orthogonal to what was done, so it does not belong in the relation name; if it is ever tracked, it belongs on the problem (for example, a tag), not as a second relation. A single neutral relation also matches the project's single-pair supersedes precedent and avoids the redundant double-pointer that a resolved-as-subset-of-addressed pair would force.
Proposed solution
Add an addressed-by/addresses inverse-pair relation, both multi-valued (list fields):
addressed-by on the problem record is the canonical, recall-facing field: a list of references to whatever was done about the problem. It is the workhorse and the only viable store when the responder is external (commit/PR/URL).
addresses on a KB-note responder is an optional inverse for the rare "what does this address?" query, documented as non-authoritative — not a required bidirectional invariant, since keeping it in sync would be an N-file write.
References are a heterogeneous free-form list: a KB wikilink or relative path, a commit SHA, a PR/issue ref, or a URL. The accepted forms are documented. The field's shape is validated as a list (like tags), while entries are not individually validated — they are free-form, like the existing sources field.
Placement: addressed-by is available on event (the motivating problem-bearer, and the field recall reads) and on assertion; addresses is available on assertion (the KB-note responder). Events do not carry addresses.
Recall surfaces an event's addressed-by alongside its recurrence signals, so a recurring-but-addressed problem reads as addressed rather than unaddressed. The list is surfaced flat — no chain-walking, unlike supersedes.
kb-curate deliberately gains no asymmetry or dangling checks for this relation; policing symmetry would contradict the non-authoritative inverse and the heterogeneous, often-external references the list is designed to hold.
Acceptance criteria
Must have
A problem record can declare addressed-by as a list of references to whatever was done about it.
addressed-by is an optional field on the event and assertion record types.
The accepted reference forms are defined and documented; list shape is validated (like tags), while entries are free-form (like sources).
Recall surfaces an event's addressed-by so an addressed recurring problem is distinguishable from an unaddressed one.
New behavior is covered by tests.
Documentation (README and affected skills) describes the relation, its many-to-many cardinality, and why it is distinct from supersedes/superseded-by.
Should have
addresses is available as the optional inverse on the assertion record type, documented as non-authoritative (the problem-side addressed-by is canonical).
Problem
The substrate records problem observations (events) but has no way to thread a problem to what was done about it. When recall surfaces a recurring bug event, the reader's first question — "was this ever addressed, and how?" — has no answer in the record; the link to the response is a dead end. The only relation available today is
supersedes/superseded-by, which is the wrong semantics: superseding deprecates the old record, but a problem that has been addressed is not deprecated. It remains a true observation, and its recurrence is signal worth keeping.Context
supersedes/superseded-byis a 1:1 chain (recall walks it hop by hop in kb-retrieve'snormalize.ts). The problem→response link is many-to-many: one response can address many problems, and one problem can accrue many responses.immutableflag). Annotating events with response pointers is the use case that motivated reconsidering event mutability; the conclusion was that a metadata relation, not a frozen or append-only model, is the right home.addressed-by, though events are the motivating case.Why
addressed-by, notresolved-byThe field is populated when a response is made, not when its success is confirmed. "Resolved" asserts an outcome the writer usually cannot vouch for at write time: some bugs are verifiably fixed (the steps to reproduce no longer reproduce the error), but refinements to agent guidance only reduce recurrence and are rarely verifiable.
addressed-bystays true across that whole spectrum — a full fix and a mitigation both address the problem. Verifiable resolution is a status of the problem, orthogonal to what was done, so it does not belong in the relation name; if it is ever tracked, it belongs on the problem (for example, a tag), not as a second relation. A single neutral relation also matches the project's single-pairsupersedesprecedent and avoids the redundant double-pointer that aresolved-as-subset-of-addressedpair would force.Proposed solution
Add an
addressed-by/addressesinverse-pair relation, both multi-valued (list fields):addressed-byon the problem record is the canonical, recall-facing field: a list of references to whatever was done about the problem. It is the workhorse and the only viable store when the responder is external (commit/PR/URL).addresseson a KB-note responder is an optional inverse for the rare "what does this address?" query, documented as non-authoritative — not a required bidirectional invariant, since keeping it in sync would be an N-file write.tags), while entries are not individually validated — they are free-form, like the existingsourcesfield.addressed-byis available onevent(the motivating problem-bearer, and the field recall reads) and onassertion;addressesis available onassertion(the KB-note responder). Events do not carryaddresses.addressed-byalongside its recurrence signals, so a recurring-but-addressed problem reads as addressed rather than unaddressed. The list is surfaced flat — no chain-walking, unlikesupersedes.kb-curatedeliberately gains no asymmetry or dangling checks for this relation; policing symmetry would contradict the non-authoritative inverse and the heterogeneous, often-external references the list is designed to hold.Acceptance criteria
Must have
addressed-byas a list of references to whatever was done about it.addressed-byis an optional field on theeventandassertionrecord types.tags), while entries are free-form (likesources).addressed-byso an addressed recurring problem is distinguishable from an unaddressed one.supersedes/superseded-by.Should have
addressesis available as the optional inverse on theassertionrecord type, documented as non-authoritative (the problem-sideaddressed-byis canonical).Dependencies
addressed-by/addressesare declared optional fields subject to allowlist enforcement).