laboratory/docs/design/shared-home/04-project-memory.md
claude b42bcb9bfe
All checks were successful
access-validation-contract / contract (push) Successful in 3m21s
ci / ci (push) Successful in 5m28s
Document the shared home for people, agents and project memory
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.
2026-10-28 19:02:06 +00:00

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

  1. A record is a dated claim with sources. It does not become true by persisting, and the newest record is not automatically current; status and supersedes say what is current.
  2. 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.
  3. 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.
  4. Private by default. Records that name people or plans stay private; publication is an explicit act with a check (§6).
  5. No secrets, ever. The existing lint applies; the record contract adds no exception.
  6. Rights are checked live, not stored. rights_assumed tells the reader what the author could see; it grants nothing and is not a permission snapshot.
  7. Uncertainty is written down. A record that lists nothing unverified must say "none"; silence is incompleteness.
  8. Runtime is provenance. A runtime label helps review and no more; no authority and no rotation follows from it.
  9. Stale is unknown, not false. An old evidence_date is 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 superseded with superseded_by. Both remain readable.
  • Withdrawal is the author's retraction without replacement; it says why.
  • A dispute marks two or more records disputed and 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.