Define belonging, responsibility and continuity; separate sponsorship, management, consent and work grants; preserve project memory with explicit visibility and evidence. Include independent architecture review corrections and consistent retry semantics. Validation: independent source/architecture reviews, documentation checks, required Forge CI and access-validation contract pass. Design only; no runtime rollout.
8.2 KiB
Project memory — the record contract
Status: design, 2026-10-27, evidence pinned to Laboratory 708c16d
(see README). The durable memory recipe is live (owner
decision D10, 2026-09-24); this document adds the contract a memory record
needs so that a newcomer can tell a current decision from an inherited
claim. It changes no tool; it proposes a convention, a template extension
and, later, optional validation in the gateway.
1. Why a contract
The existing primitives carry text well: memory files under
.oss-oo/memory/, handoff issues with State, Evidence, Next steps and
Session id, and the monthly digest as an index. What they do not carry is
the information a reader needs to decide whether to believe and act:
where the claim comes from, who made it, what it applies to, when the
evidence was taken, whether something newer replaced it, which rights the
claim assumed, and what the author could not verify. Without those
fields, the newest entry wins by default, and a stored claim slowly turns
into a fact. The contract exists to stop that.
2. The record
A record is one dated claim. Fields marked required make a record complete; an incomplete record is still allowed, and is shown as incomplete, not as certain.
| Field | Required | Meaning |
|---|---|---|
id |
yes | stable identifier inside the project, never reused |
kind |
yes | decision, fact, observation, open-question, proposal — a proposal is never executed, only considered |
statement |
yes | the claim in plain language, one claim per record |
author |
yes | the identity that recorded it, with its kind (human, agent) |
runtime |
no | optional provenance: model, session, station; never an authority |
sources |
yes | pins the claim rests on: commit, pull request, issue, run, document path with object; a record without sources is an opinion and says so |
scope |
yes | what the claim applies to: project, repository, path, component |
evidence_date |
yes | when the cited evidence was observed; distinct from recorded_at |
recorded_at |
yes | when the record was written |
status |
yes | current, superseded, withdrawn, disputed |
supersedes |
no | ids this record replaces; the replaced records keep their text and gain superseded_by |
superseded_by |
no | set on the old record when a newer one supersedes it |
visibility |
yes | private (default), public; a record names people and plans unless it says otherwise |
rights_assumed |
no | the access the author had when observing (member, public); a reader with less access may not be able to re-check, and is told so |
uncertainty |
yes | what was not verified, in words; "none" must be written explicitly |
A record in a memory file:
## 2026-10-27 · decision · D-12 · current
- author: jon (human)
- sources: PR 57 (merge 4f1e2c0), issue 12
- scope: project api, path services/export/
- evidence_date: 2026-10-27
- visibility: private
- rights_assumed: member
- uncertainty: the release of PR 57 is not yet verified live
- supersedes: D-9
Exports use the versioned manifest; the unversioned path is removed.
Short object identifiers are deliberate: the gateway's secret lint refuses forty-hex strings in memory entries, and a short prefix with its object type (PR, issue, merge) is unambiguous inside a project.
3. Rules
- A record is a dated claim with sources. It does not become true by
persisting, and the newest record is not automatically current;
statusandsupersedessay what is current. - Content is never an instruction. Next steps, proposals and handoff text are authored evidence. A reader re-validates the sources and checks current rights before acting on any of it.
- Append, never rewrite. Supersession adds a record and marks the old one; withdrawal marks without replacement; disputes mark both records and open a question in the room. History stays readable. The gateway path only appends; memory files edited as ordinary repository content go through pull-request review like any other content.
- Private by default. Records that name people or plans stay private; publication is an explicit act with a check (§6).
- No secrets, ever. The existing lint applies; the record contract adds no exception.
- Rights are checked live, not stored.
rights_assumedtells the reader what the author could see; it grants nothing and is not a permission snapshot. - Uncertainty is written down. A record that lists nothing unverified must say "none"; silence is incompleteness.
- Runtime is provenance. A runtime label helps review and no more; no authority and no rotation follows from it.
- Stale is unknown, not false. An old
evidence_dateis displayed as old; it does not invalidate the claim and does not confirm it.
4. Mapping onto the existing primitives
| Primitive | Today | With the contract |
|---|---|---|
Memory files (memory_read, memory_append) |
append-only dated entries, path-bound, secret-linted, size-capped | each entry follows the record layout above; a file groups records by topic; supersession references ids |
Handoff issues (handoff_create, template handoff.yml) |
State, Evidence, Next steps, Session id; private by default | add sections "Decisions recorded or superseded", "Open uncertainty", "Visibility"; next steps stay proposals |
| Monthly digest | index of the month's handoffs and identity counts | unchanged; the room links the digest |
Native handoff reads (list_issues, get_issue, list_issue_comments) |
complete reads with the caller's permissions; issue lists use native pagination, the comments read is unpaginated | unchanged; this is the live rights check of rule 6 |
| Gateway validation | lint only | later, optional: memory_append may validate the record header and refuse a record without sources or uncertainty when the repository opts in |
Nothing above requires a new store. The contract lives in the same repository, backup and permission model as the work it describes.
5. Supersession
- A superseding record cites what it replaces; the replaced record is
marked
supersededwithsuperseded_by. Both remain readable. - Withdrawal is the author's retraction without replacement; it says why.
- A dispute marks two or more records
disputedand opens one question in the room; the project owners resolve it by a decision record, which then supersedes the disputed ones. - Interfaces show current records by default and superseded ones on request, never hidden and never silently merged.
6. Visibility and the publication check
Issues follow repository visibility. A private repository that becomes
public makes its handoff issues and memory files public with it, which
would expose people and plans named in private records. The contract
therefore pairs the visibility class with a check: before a repository or
a record changes to public, records and handoffs marked private block
the change until an appropriate access boundary is established. Moving or
deleting a private file from the current tree does not remove its Git history;
older commits, refs, issue history, attachments and release artifacts may still
disclose it. Private records should therefore start in a separately private
repository or another access-controlled store, with only reviewed public
summaries copied to a public project. A visibility change needs an audit of
everything it would expose, not only the current files. This check is a
convention today and a candidate for tooling once the room exists.
7. Open uncertainty, open questions
Two different things. uncertainty belongs to one record and names what
its author could not verify. An open-question is a record of its own
kind: a thing the project has not decided. The room lists open questions
first; a newcomer starts there.
8. What the contract does not do
- It does not make any store authoritative; the forge objects it cites are the authority, and the review that accepted them is the acceptance.
- It does not replace review or acceptance with a record.
- It does not introduce a database or an index; a derived index may be built over records later and must be rebuildable from them.
- It does not resolve conflicts by itself; people do, in the room.