fix(brain): close round-3 review findings on provenance
- B1: search.extractProvenance locates the frontmatter with
frontmatter.Split (fence at column 0), so an indented "---" inside a
block scalar no longer hides provenance from brain_query.
- B2: brain_edit refuses to edit without a snapshot, and if the stamp
cannot be verified restores the note and reports failure; a failed
restore is reported as exactly that, never as "rolled back".
- B3: internal/provenance gets direct tests for the whole-document
backstop (a stamp that cannot read back is refused), standalone group
decoding, duplicates, lone CR, tab continuations and unclosable
fences. Removing verify or the restore now fails the suite.
- Principals YAML would read as non-strings (true, 123, null, ~) are
quoted instead of refused. An unclosable fence ("---x") is refused
rather than demoted into the body. writeHallNote creates the hall
directory only after the note passes, so a refused write leaves
nothing behind (brain#21).
- MCP brain_ingest (stub LLM) asserted to stamp the caller.
Refs #145 #144
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,3 +19,11 @@ func TestExtractProvenanceIgnoresBodyLines(t *testing.T) {
|
||||
assert.Equal(t, "jwt", o)
|
||||
assert.Equal(t, "attacker", w)
|
||||
}
|
||||
|
||||
// Round 3 (B1): an indented "---" inside a block scalar is content, not the
|
||||
// closing fence — the same rule as frontmatter.Split.
|
||||
func TestExtractProvenanceUsesTheSharedFenceRule(t *testing.T) {
|
||||
o, w := extractProvenance("---\nk: |\n ---\norigin: jwt\nwritten_by: attacker\n---\nbody\n")
|
||||
assert.Equal(t, "jwt", o)
|
||||
assert.Equal(t, "attacker", w)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
sharedfm "github.com/mathiasbq/hyperguild/ingestion/internal/frontmatter"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -296,33 +297,32 @@ func hydrate(brainDir, relPath string) (Result, error) {
|
||||
}
|
||||
|
||||
// extractProvenance reads origin/written_by from the leading frontmatter
|
||||
// block only — a body line that happens to start with "origin:" is not
|
||||
// provenance.
|
||||
// block only, located with the shared fence rule (frontmatter.Split: a "---"
|
||||
// at column 0) so an indented "---" inside a block scalar is content, not a
|
||||
// closing fence (PR #147 review round 3). A body line is never provenance.
|
||||
func extractProvenance(content string) (origin, writtenBy string) {
|
||||
scanner := bufio.NewScanner(strings.NewReader(content))
|
||||
inFrontmatter := false
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.TrimSpace(line) == "---" {
|
||||
if !inFrontmatter {
|
||||
inFrontmatter = true
|
||||
continue
|
||||
}
|
||||
break
|
||||
block, _, ok := sharedfm.Split([]byte(content))
|
||||
if !ok {
|
||||
return "", ""
|
||||
}
|
||||
for _, line := range strings.Split(string(block), "\n") {
|
||||
if line == "" || line[0] == ' ' || line[0] == '\t' {
|
||||
continue
|
||||
}
|
||||
if !inFrontmatter {
|
||||
return "", ""
|
||||
}
|
||||
key, val, ok := strings.Cut(line, ":")
|
||||
if !ok || strings.HasPrefix(line, " ") || strings.HasPrefix(line, "\t") {
|
||||
key, val, found := strings.Cut(line, ":")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
v := strings.Trim(strings.TrimSpace(val), `"'`)
|
||||
switch strings.TrimSpace(key) {
|
||||
case "origin":
|
||||
origin = v
|
||||
if origin == "" {
|
||||
origin = v
|
||||
}
|
||||
case "written_by":
|
||||
writtenBy = v
|
||||
if writtenBy == "" {
|
||||
writtenBy = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return origin, writtenBy
|
||||
|
||||
Reference in New Issue
Block a user