Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 51 additions & 9 deletions .agents/skills/proof/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: proof
description: Journal reasoning (decisions, findings, issues, constraints, risks, citations, blobs) into a Flatbread Proof and recall it with bounded reads. Use when starting or resuming a thread of work, recording a decision or finding, resolving an issue, checking what is blocking or still open on an effort, or when the user mentions effort graph, journaling, blocking decisions, agent memory, citation, blob, cites, longform, WriteCitation, or WriteBlob.
description: Read and update Flatbread Proof, the repository's durable project memory, through bounded queries and typed mutations. Use for recall when resuming a known effort, checking blockers, or when the user mentions Proof or journaling. Use the write path only for a decision-relevant turning point that outlives the current PR or session and adds unique causal rationale. Never journal routine progress, handoffs, review notes, temporary gaps, implementation steps, or journal corrections.
---

# Proof — agent journaling and recall
Expand All @@ -10,7 +10,7 @@ repository. It has eight record types: **Effort**, **Issue**, **Finding**,
**Decision**, **Constraint**, and **Risk** capture the work and reasoning;
**Citation** stores a source or reference; and **Blob** stores attached
content such as a document, JSON, or image. Every record belongs to one
Effort. Create and update records through 15 typed mutations, and read them
Effort. Create and update records through 16 typed mutations, and read them
through 5 bounded queries. Do not hand-edit record frontmatter, although you
may edit record bodies freely.

Expand Down Expand Up @@ -51,7 +51,40 @@ The write journal is `<root>/.journal/`; read digests cache under

## Writing (journaling)

One command for all 15 mutations — pass the payload as a single JSON argument:
### Mandatory write gate

Proof is a map of durable reasons, not a work log. How to use Proof lives in
this skill; do not journal the process itself as a Decision.

Score only new retained information: create mutations and body text that add
claims. Lifecycle transitions (`AcceptDecision`, `ResolveIssue`,
`SetEffortStatus`, `MitigateRisk`, `SetRiskState`), `Retract`, and
`proof cache prune` do not add retained claims and do not need a 4/4 score.
`Supersede` and `Invalidate` write retained edges; score the reason for the
edge the same as a create. Body edits that only drop claims stay out of the
gate.

Before a create or a body edit that adds claims, score the information being
added — not the record that would receive it. Answer each test in private
reasoning:

1. **Future need:** Would losing it make a future agent materially
misunderstand why the project is shaped this way?
2. **Durable effect:** Will it outlive the current PR or session and change a
product principle, public contract, architecture, constraint, risk, or docs
direction?
3. **Causal value:** Does it explain why that change happened or what evidence
could reverse it?
4. **Unique signal:** Does it add a reason or link that code, docs, Git, the PR
or tracker issue, and retained records do not already make clear?

Do not create a record or add body claims unless the information scores
**4/4**. An existing or open record does not bypass this gate; appending
low-value text still consumes bounded reads. Keep failed candidates in the
PR, tracker issue, commit, or run artifact. Citations and Blobs persist only
when they support a 4/4 record.

One command for all 16 mutations — pass the payload as a single JSON argument:

```bash
flatbread proof write '{"type":"WriteDecision","effort":"<eff-id>","title":"...","body":"...","derives_from":["<id>"]}'
Expand All @@ -61,14 +94,20 @@ Response: `{"generation":"<token>","artifacts":[{"id","path","operation"}],"touc
**Capture `artifacts[0].id`** to wire later edges, and **keep `generation`**
for strict read-your-writes.

Full payload shapes for all 15 mutations: read [reference.md](./reference.md).
Full payload shapes for all 16 mutations: read [reference.md](./reference.md).
Critical semantics:

- Creates always start in the initial lifecycle state: `WriteDecision` →
`proposed`, `WriteIssue` → `open`, `WriteRisk` → `open`. You cannot pass a
state; use lifecycle mutations (`AcceptDecision`, `ResolveIssue`,
`MitigateRisk`, `SetRiskState`) to transition. `WriteCitation` and
`WriteBlob` have no lifecycle state.
- `Retract` removes a record from browse reads without deleting the file.
Pass a reason. The writer strips that id from other records in the same
Effort so reads do not fail closed. Use it for session noise that should
never have been journaled. Do not `git rm` records or hand-edit
frontmatter. `proof get` still returns a retracted record. Efforts cannot
be retracted; abandon them instead.
- `AcceptDecision` defaults `rejectSiblings: true`, which rejects ALL other
proposed Decisions in the same Effort. Pass `"rejectSiblings": false`
unless you deliberately want the competing proposals closed.
Expand Down Expand Up @@ -156,14 +195,17 @@ server-side.
for the full body. Reserve opening `.flatbread-proof/**/*.md` for rare
cases (e.g. digest byte-cap miss on an oversized record), not normal
zoom-in.
3. **During work:** when outside material supports a record, save large
content with `WriteBlob` if needed, then create a `WriteCitation`, then
create the Issue, Finding, Decision, Constraint, or Risk with
3. **During work:** apply the write gate above before any create or body
edit that adds claims. When outside material supports a 4/4 record, save
large content with `WriteBlob` if needed, then create a `WriteCitation`,
then create the Issue, Finding, Decision, Constraint, or Risk with
`cites: ["<cit-id>"]`. You cannot add a citation later, so create the
Citation first. Open Issues for real gaps or blockers, and use
`derives_from` on Decisions to link the Findings, Constraints, and Issues
they respond to.
4. **On commitment:** `AcceptDecision` (mind `rejectSiblings`), `ResolveIssue`
with `resolvedBy` citing the closing Decision/Findings.
with `resolvedBy` citing the closing Decision/Findings. These lifecycle
transitions do not need a 4/4 score. Retract session noise with `Retract`
rather than deleting files.
5. Maintenance: `flatbread proof cache prune` deletes digests older than
24h / over the 100 MiB ceiling.
24h / over the 100 MiB ceiling. Prune does not need a 4/4 score.
48 changes: 48 additions & 0 deletions .agents/skills/proof/evals/evals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"skill_name": "proof",
"evals": [
{
"id": 1,
"prompt": "An implementation branch passes lint and 41 of 42 tests. The last failure is a flaky timer assertion owned by this branch. The next session should rerun it and adjust the timeout if it repeats. Preserve this handoff where it belongs.",
"expected_output": "Keep the handoff in a branch, run, PR, or tracker artifact. Do not create or update a Proof record.",
"assertions": [
"No .flatbread-proof record is created or updated",
"The response identifies the handoff as temporary implementation state",
"The response names a native work artifact instead of Proof"
]
},
{
"id": 2,
"prompt": "Put this in project agent memory: for the current PR, the follow-up is split among five temporary file owners covering the changelog, mirrored references, CLI tests, digest tests, and render logic. The map is useful until the PR merges but changes no product rule.",
"expected_output": "Keep the ownership map in the PR or run artifact despite the request to put it in agent memory. Do not create or update a Proof record.",
"assertions": [
"No .flatbread-proof record is created or updated",
"The direct request to use project memory does not bypass the retention gate",
"The response places the ownership map in the PR or run artifact"
]
},
{
"id": 3,
"prompt": "A prior agent created a Finding only to note that a PR checklist used the wrong record kind. Product behavior did not change, and the correction matters only until review ends. Decide what durable project-memory action is warranted.",
"expected_output": "Create no new Proof record. Retract the temporary Finding with type Retract and a reason. Do not git rm the file or hand-edit frontmatter. Keep any separate durable product decision.",
"assertions": [
"No new Proof record is created",
"The response retracts the temporary Finding through the typed writer",
"The response does not teach a git delete or frontmatter strip",
"Any cleanup preserves separate durable rationale"
]
},
{
"id": 4,
"prompt": "Maintainers made a project-wide, hard-to-reverse choice: Proof will not add numeric confidence fields to any record type. Uncertainty stays in cited evidence and record prose because scores from different models are not comparable. This will govern schema work, writer behavior, and docs. Preserve the conclusion through the repository's normal process.",
"expected_output": "Create and accept one Proof Decision through the typed writer. Pass rejectSiblings false so unrelated proposed Decisions on the same Effort stay proposed. Preserve the rationale, alternatives, consequences, and reversal criteria.",
"assertions": [
"One durable Proof Decision is created",
"AcceptDecision passes rejectSiblings false",
"The rationale explains why model confidence scores are not comparable",
"The Decision covers schema, writer, and documentation consequences",
"No unrelated Proof record is created or rejected"
]
}
]
}
9 changes: 9 additions & 0 deletions .agents/skills/proof/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ to a Blob. Both links must stay within the same Effort. `flatbread proof relatio
New edge vocabulary needs a dogfooded query the existing vocabulary cannot
express.

## Retraction

`Retract` hides a record that should not have been journaled. The file stays
on disk with `retracted: true` so ids remain resolvable and
`PROOF_DANGLING_RELATION` does not fire. Browse reads omit retracted
records. `proof get` still returns the body and the reason. This is not
supersession (a better same-kind claim) and not invalidation (a Finding that
the target was wrong). Git is the undo story; there is no Restore mutation.

## Intentional non-models

Session, Run, Plan, Artifact, Agent, Investigation, Question, Proposal,
Expand Down
70 changes: 62 additions & 8 deletions .agents/skills/proof/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Generated as `<prefix>-<slug>--<16-char-crockford>` with prefixes `eff`,
identity. Let the writer generate ids; capture them from mutation results
(`artifacts[0].id` for creates).

## The 15 mutations (`flatbread proof write '<json>'`)
## The 16 mutations (`flatbread proof write '<json>'`)

Common optional fields on all creates: `id`, `created_at` (ISO with offset),
`produced_in`, `created_by` (opaque provenance strings). Forward edge fields
Expand Down Expand Up @@ -76,6 +76,38 @@ target was wrong (stronger than superseded).
other `proposed` Decision in the Effort to `rejected` with a back-pointer.
All mutations run in one journal transaction (save-or-undo).

### Retract a record that should not stay on the live graph

```json
{ "type": "Retract", "recordId": "<id>", "reason": "..." }
```

`Retract` is for session noise and other records that should never have been
written. It is not a hard delete and not a fold into a survivor:

- Retract throws when the target is the last remaining value of
`resolved_by`, `mitigated_by`, `evidence`, `rejected_by`, or
`superseded_by` on a live same-Effort record. It also throws when the
target is the last live Finding-kind id on a realized Risk's `evidence`,
even if other non-Finding ids remain. Supersede or retract those
dependent records first. Do not `git rm`, and do not hand-edit
frontmatter to strip the pointer.
- The file stays. Frontmatter gains `retracted: true`, `retracted_at`, and
`retracted_reason`. The body is unchanged so `proof get` can still explain
what was removed.
- On a successful Retract, the writer clears that record's relation fields
and strips its id from every other record in the same Effort in the same
journal transaction.
- Browse reads (`list`, `records`, `blocking-decisions`) omit retracted
records. `proof get` still returns them. `relations` follows stored edges
that remain; after a successful Retract, survivors should have none.
- Efforts cannot be retracted. Set status to `abandoned` instead.
- Later creates, `Supersede`, `Invalidate`, and lifecycle mutations reject
retracted ids. Git history is the undo story; there is no Restore mutation.

Folding several noisy records into one survivor is a body edit on the
survivor (score 4/4 if it adds claims) plus `Retract` on the rest.

### Mutation result

```json
Expand All @@ -102,6 +134,8 @@ the generated schema) and return a `ReadEnvelope`:
"artifact_sha256": "...",
"served_generation": "55",
"consistency": { "mode": "eventual|strict", "min_generation": null },
"complete": true,
"cap_reasons": [],
"page": { "returned": 2, "has_more": false, "next_cursor": null },
"hints": ["getRecord(\"dec-...\")"]
}
Expand All @@ -118,11 +152,29 @@ lists), one-hop related records, and an edge table. Body policy:
from these digests — use `proof get` for the payload. Citation bodies
(usually short) still excerpt normally.

Caps: 25 primary records, one hop, 50 edges, 64 KiB; hitting a cap sets
`complete: false` with named `cap_reasons` — narrow the query or page rather
than expecting more. If a `get` body alone exceeds the 64 KiB digest byte
cap, the digest fails closed with a byte-cap banner (it does **not** fake a
full body via the 600/12 excerpt).
Caps: 25 primary records, one hop, 50 edges, 64 KiB. Hitting a cap sets
`complete: false` with named `cap_reasons`. Page only when `page.has_more` is
true. Non-empty hard `cap_reasons` that paging cannot clear mean narrow the
query or fail closed. `primary_records` is a defensive in-process signal after
the CLI pre-slices to at most 25 primary records; `proof list` and
`proof records` do not emit it. If a `get` body alone exceeds the 64 KiB
digest byte cap, the digest fails closed with a byte-cap banner (it does **not**
fake a full body via the 600/12 excerpt).

Every read envelope carries `complete` and `cap_reasons`. Read it in this
order:

1. If `complete` is true, the artifact is complete.
2. If `page.has_more` is true, fetch `page.next_cursor`. A null cursor is an
error; do not retry the same page.
3. If `cap_reasons` is not empty, narrow the query or fail closed. It can hold
Comment thread
cursor[bot] marked this conversation as resolved.
several sorted, duplicate-free values from `primary_records`,
`displayed_edges`, and `bytes`.
4. A hard cap alone leaves `page.has_more: false` and `next_cursor: null`.
Paging and hard caps can occur together, but caps never create a cursor.

Programs must read these fields from the JSON envelope; do not parse the
digest or `summary` as a data feed.

### Commands

Expand Down Expand Up @@ -184,8 +236,10 @@ flatbread proof cache prune

- Do not hand-edit record frontmatter or `.journal/`; bodies are freely
editable (the reindexer validates and repairs projections).
- Do not parse digest files as data feeds for other programs — they are
evidence for you to Read/grep; the envelope is the machine surface.
- Do not `git rm` Proof records to correct the graph. Use `Retract`.
- Do not parse digest files or `summary` as data feeds for other programs —
the digest is evidence for you to read or search; the envelope is the
machine surface.
- Do not build polling loops around generations; strict reads wait
server-side.
- Do not model sessions/plans/agents as records — put provenance in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ derives_from:
- fnd-skill-and-hard-constraint-still-teach-13-mutatio--gvg2btns0q7rp0eq
supersedes:
- con-mutation-enum-stays-deliberately-small--45v1ae3neq26g1rz
superseded_by:
- con-mutation-enum-stays-deliberately-small--0vf4ssfg2jmzxyn4
---

V1 has exactly fifteen named mutations. Every operation has a Zod schema,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
id: con-mutation-enum-stays-deliberately-small--0vf4ssfg2jmzxyn4
effort: eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002
title: Mutation enum stays deliberately small
kind: hard
created_at: '2026-08-22T20:28:27.386Z'
supersedes:
- con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x
---

V1 has exactly sixteen named mutations. Every operation has a Zod schema, validates against a committed index generation, and owns a defined semantic transition.

The surface consists of Effort lifecycle (`CreateEffort`, `SetEffortStatus`); one creation mutation for each primitive (`WriteIssue`, `WriteFinding`, `WriteDecision`, `WriteConstraint`, `WriteRisk`, `WriteCitation`, `WriteBlob`); edge retro-linking (`Supersede`, `Invalidate`); lifecycle transitions (`ResolveIssue`, `AcceptDecision`, `MitigateRisk`, `SetRiskState`); and `Retract` for records that should not stay on the live graph.

`Retract` is the named archive operation. It tombstones a file in place, strips that id from other records in the same Effort, and drops the record from browse reads. It is not a generic frontmatter patch, not a hard delete, and not a fold into a survivor.

No generic frontmatter patch, hard delete, standalone `RejectDecision`, or body-edit mutation is part of v1. Git is the undo story; Decision sibling rejection is part of accepting an alternative; and bodies remain ordinary editable markdown while the platform owns frontmatter semantics. Additive mutations require dogfood evidence; removing or reshaping one is a breaking migration.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
id: dec-retract-noise-instead-of-deleting-proof-files--k6jk0d2bdp1m9jw9
effort: eff-effort-graph-memory-and-agent-wedge--szeqvmgqjqnhd002
title: Retract noise instead of deleting Proof files
state: accepted
created_at: '2026-08-22T20:28:28.832Z'
derives_from:
- con-mutation-enum-stays-deliberately-small--02k06bxbjwrjfp9x
- con-mutation-enum-stays-deliberately-small--0vf4ssfg2jmzxyn4
---

## Context

PR 260 cleaned session noise from an Effort by deleting record files and stripping ids on the kept Decision. Review refused that path: Proof has no delete mutation, the skill forbids hand-edits of frontmatter, and leftover stored ids fail closed with PROOF_DANGLING_RELATION.

Supersede keeps both records. Invalidate adds a Finding that says a target was wrong. Leaving junk in place fills the 25-record / 50-edge browse caps. Git rm is the wrong tool.

## Decision

Add Retract as a sixteenth named mutation. Tombstone the file in place with retracted, retracted_at, and retracted_reason. Strip that id from other records in the same Effort in the same journal transaction. Browse reads omit retracted records. proof get still returns the file. Later writes refuse retracted ids. Efforts cannot be retracted; abandon them.

This is not a hard delete and not a Collapse that folds bodies into a survivor. Folding N noisy records into one survivor is a body edit on the survivor plus Retract on the rest.

## Alternatives considered

- **Git rm plus a frontmatter-edit exception:** rejected because it makes agents responsible for reverse projections and dangling ids. The writer already owns multi-file transactions.
- **Leave noise forever:** rejected because bounded reads are the recall surface; session debris crowds out turning points.
- **Supersede or Invalidate the junk:** rejected because both keep the bad record visible and, for Invalidate, add another record to say so.
- **Hard delete that unlinks the file:** rejected because the journal has no content unlink, missing ids fail closed, and other branches that still store the id would dangle.

## Consequences

Eval 3 can teach Retract. Cleanup PRs no longer need to strip frontmatter by hand. The mutation enum grows to sixteen with dogfood from the #260 review trail.

## Reversal criteria

Revisit if tombstones still crowd raw-file grep, if agents Retract durable rationale, or if a Restore mutation becomes necessary because git revert is too costly in concurrent workflows.
Loading
Loading