Round 2 of the PR #147 review forged origin: static for yaml.v3 with an
alias key plus a "..." document-end line: per-line judgement cannot see
context-dependent YAML. It also found REST ingest writing pages with no
provenance (stampPages lived only in the MCP server).
- New package internal/provenance. Apply keeps only top-level groups
`key: value` with a bare-identifier key whose group decodes on its own
to exactly that key, drops reserved and duplicate keys and everything
else (aliases, anchors as keys, document markers, complex/merge keys,
flow maps, tags, quoted keys), appends the stamp, then decodes the
whole result with yaml.v3 and refuses the write unless it reads back
exactly the stamp. api.StampProvenance wraps it and now returns an
error, which every caller propagates.
- The ingest pipeline stamps every page it writes or merges, from
provenance.FromContext(ctx); MCP attaches the caller's stamp, REST and
the watcher stamp unknown. RunRaw takes a ctx.
- brain_edit snapshots the note and rolls the edit back if the stamp
cannot be verified.
Tests: R1/R2 payloads join the write/update variant table, plus
brain_edit with the alias payload; REST /ingest-raw (title newline
checked with the line-oriented reader) and REST /ingest (stub LLM) stamp
unknown. Two existing byte-exact tests updated for the stamp line.
Refs #145#144
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The PR #147 review forged origin: static as a JWT principal through
three tools the first version never touched (brain_edit, brain_ingest_raw,
ingest_raw + brain_promote), and through YAML spellings a key-name match
missed (quoted, escaped, tagged, flow-mapped, merge keys, lone CR).
- api.StampProvenance removes every spelling of origin/written_by from
the frontmatter and appends the real values. A line is dropped if
EITHER yaml.v3 (decoding quotes, escapes, tags, flow maps) or the
brain's line-oriented readers would read it as provenance; complex
keys, orphan values and merge keys are dropped outright. Lone CRs in
frontmatter become LF. Principal values that are not bare words are
quoted.
- Applied as the last step of writeHallNote, UpdateNote, PromoteNote
(re-attributed to the promoter), brain_edit (re-attributed to the
editor) and both ingests (every page written or merged). REST
/write and /promote carry no principal and stamp unknown.
- Ingest: newlines in scalar fields fold to spaces; a page type must be
a plain lower-case name (../raw wrote outside wiki/, pre-existing).
- Audit: outcome is ok|error, never the error text, which echoed
argument values.
Tests: every escape from the review is a table case asserting the
invariant on the file (parses as YAML, yaml.v3 and brain_get agree,
exactly the stamped lines). Plus REST /write, REST capture AuthPath,
body-line provenance in search, and quoted principals; two of the
review's surviving flips now go red. Three tests renamed so names claim
only what they assert.
Refs #145#144
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds brain_reject (RejectNote + MCP tool) and fixes the watcher to skip raw/rejected/, preventing declined notes from being silently re-ingested and republished.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Mathias <mthbqv@gmail.com>
Closes the human curation loop: list brain/raw/ notes awaiting review
(oldest-first, with excerpt) and promote one into brain/wiki/<wing>/<hall>/.
PromoteNote rewrites frontmatter (sets wing/hall/promoted_at, preserves
created_at + custom fields via the existing frontmatter editor), rebuilds
the wing _index, and runs auto-tunnel. Atomic from the caller's view:
hall/wing/slug/collision validation happens before any fs change, and the
source is deleted only after the destination write succeeds (write-then-
delete, never move) — a collision or write failure leaves raw/ intact.
Default slug = filename minus the YYYY-MM-DD- prefix.
Also exposes GET /pending + POST /promote for shell scripts (bad
hall/collision/missing-source → 400, not 500).
Scope note: operates on raw/ (the retrospective-skill review queue) per
this issue's spec. The knowledge/ legacy pile is #22's bulk-migration
concern, not this ongoing queue.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>