Commit Graph
11 Commits
Author SHA1 Message Date
mathiasandClaude Sonnet 5.5 27b1579b80 fix(pipeline,api,wing): never archive a note as processed when nothing was ingested; titles do not merge sources; ties prefer the page on disk (review of #211, pass 3)
CI / Lint / Test / Vet (pull_request) Successful in 1m6s
CI / Mirror to GitHub (pull_request) Skipped
- in a wing, an ingest that writes no source page is an error: the note goes to
  raw/failed with the warnings in log.md instead of leaving the inbox as
  'processed' (model returned [], only invalid types, only clashing entities)
- the wing's source path is deterministic, so Resolve no longer redirects a
  source onto another note's page because the model gave both the same title
  ('Home'); that overwrote the hash and the text
- a batch tie between concept and entity prefers the page already on disk, so
  its update is not lost; the wing's own source page keeps its slug even when a
  foreign page shares it
- brain_pending lists an unreadable (over-cap) note with the reason instead of
  dropping it; the client filter's 4 KiB match-span limit is documented
Each has a test that fails without it (mutation-checked).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:56:03 +02:00
mathiasandClaude Sonnet 5.5 49286ba8b8 fix(api,watcher,server): reject moves non-markdown untouched; read caps; BOM; strict routing flag (review of #211, pass 2)
CI / Lint / Test / Vet (pull_request) Successful in 1m2s
CI / Mirror to GitHub (pull_request) Skipped
- brain_reject on a parked pdf/txt moves the bytes; it no longer prepends YAML
- raw/ notes are read through a cap (readCapped); an endless reader test fails
  instead of exhausting memory
- a byte-order mark no longer hides a note's wing: key
- INGEST_WING_ROUTING is parsed strictly; a typo stops the server rather than
  leaving routing silently off
- tests for the reserved-wing check in every disguise (Sources, sources., ...)
Mutation-checked.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:49:10 +02:00
mathiasandClaude Sonnet 5.5 87c40fe364 fix(api,watcher): name the queue, list parked non-markdown, reserved wings, top-level-only frontmatter key; document the inbox (review of #211)
CI / Lint / Test / Vet (pull_request) Successful in 1m2s
CI / Mirror to GitHub (pull_request) Skipped
- brain_promote/brain_reject take an optional queue (inbox | needs-review); a
  name present in both is refused instead of silently acting on the top-level
  note; brain_pending labels every entry with its queue
- parked pdf/txt files are listed (they were invisible); only markdown can be
  promoted, the others are moved or rejected
- promote refuses sources/concepts/entities/wiki as a wing
- frontmatterWing reads only a top-level key inside a properly fenced block
- docs/raw-inbox.md: the contract, the three env vars, the known limits
Each behaviour has a test that fails without it (mutation-checked).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:34:52 +02:00
mathiasandClaude Sonnet 5.5 8988c291ca feat(server): INGEST_WING_ROUTING wires the Router; remove the classifier path (#208)
Removes the LLM classifier, the substring 'BM25' scorer, the agreement gate,
the backtest and the old migrate/wingmigrate tooling: measured at 2 of 55
pages placed (#208), and the migration was built for the per-wing facts layout
this branch replaces. wing now holds the decision types, the Router and
KnownWings. INGEST_WING_ROUTING=1 builds the Router (default wing
INGEST_DEFAULT_WING=web-clip, client pattern from INGEST_CLIENT_BLOCK or
CLAUDE_INGEST_CLIENT_BLOCK); a bad default or pattern is fatal at startup.
Watcher tests rewritten for the Router, including a deliberate subfolder into
any existing wing, typo'd folders parked, forged-key and edit-while-placing
cases.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:18:39 +02:00
mathiasandClaude Sonnet 5.5 750dc93bdb feat(watcher): Placer interface; acceptance tests for the sprint goal (#209)
A clip dropped in raw/ with no other action lands in web-clip, its entity and
concept are the shared pages, raw/ is empty and nothing waits for a human;
client-marked text and a typo'd wing name park; a deliberate subfolder places.
Real pipeline and file layout, model stubbed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 20:09:19 +02:00
mathiasandClaude Sonnet 5.5 bd33a0a4e8 fix(watcher): park through the brain root, keep a note edited mid-resolve, honour only real fences (#205)
CI / Lint / Test / Vet (pull_request) Successful in 1m7s
CI / Mirror to GitHub (pull_request) Skipped
From the second independent review of #207:
- parkForReview now skips the delete when the note changed since it was read
  (an LLM call sits in that window; Syncthing can deliver a newer version)
- parked copies are created via brainfs (real dirs only, O_EXCL, no symlink
  following), so a planted raw/needs-review symlink cannot redirect or hide a
  note; this also removes the need for the guard allowlist entry added in
  1e14c56, which is reverted
- a '----' line no longer closes the proposal block
Each has a test that failed first and a mutant that fails it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:21:25 +02:00
mathiasandClaude Sonnet 5.5 006a891423 fix(watcher): never overwrite a parked note; a proposal cannot be forged or pre-empted; CRLF notes; wing dirs must be plain (#205)
CI / Lint / Test / Vet (pull_request) Failing after 1m2s
CI / Mirror to GitHub (pull_request) Skipped
From the independent review of #207:
- parked notes are created O_EXCL with -2,-3 suffixes (same-named notes from
  different subfolders were overwritten and their originals deleted)
- proposed_wing is emitted only if a plain wing name; a note's own proposal_*
  keys are dropped so they cannot outrank the resolver's (first-wins reads)
- CRLF notes: wing: key honoured, one valid frontmatter block on parking
- KnownWings skips wiki dirs that are not canonical lower-case names
- adds the wingmigrate dry-run/apply command
Each fix has a test that failed first and a mutant that fails it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:16:48 +02:00
mathiasandClaude Sonnet 5.5 b4b36c9bfd test(watcher): a re-synced unchanged note is not extracted twice; a changed one is (#205 S6)
CI / Lint / Test / Vet (pull_request) Successful in 1m4s
CI / Mirror to GitHub (pull_request) Skipped
Mutation-checked against the source-hash drift check.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:11:26 +02:00
mathiasandClaude Sonnet 5.5 96c63906c2 test(watcher): make the frontmatter-forgery test reach the code it names (#205 S4)
The first version fed the text through a path that never carried it into the
file, so it passed under the mutant. A classifier error does carry it; the
test now fails with %q replaced by %s.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:10:54 +02:00
mathiasandClaude Sonnet 5.5 b9657973ff feat(api): brain_pending lists notes parked in raw/needs-review/ with the wing proposal (#205 S4)
Approval is moving the note into raw/<wing>/ (the watcher ingests it there);
a dedicated approve tool is tracked separately. Proposal reason is written
Go-quoted so LLM text cannot start a frontmatter key; pinned by a
mutation-checked test.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:10:39 +02:00
mathiasandClaude Sonnet 5.5 2c6220782d feat(watcher): resolve each note's wing; park the unplaceable in raw/needs-review/ (#205 S3)
With Config.Resolver set, an explicit subfolder/frontmatter wing or an agreeing
classifier+scorer routes the note into that wing; anything else is parked with
its proposal in frontmatter and never extracted. needs-review/ is skipped by
the walk like rejected/. Nil Resolver keeps the retired layout.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:08:15 +02:00