Files
hyperguild/docs/raw-inbox.md
mathiasandClaude Sonnet 5.5 80f3fd3c5e
CI / Lint / Test / Vet (pull_request) Successful in 1m3s
CI / Mirror to GitHub (pull_request) Skipped
fix(wing,server): client names are matched as whole Unicode words; unsafe lists are a startup error (review of #214)
- WrapNames bounds the bare name list with Unicode-aware edges instead of \b
  (Go's \b is ASCII-only, so a name with a non-ASCII edge letter such as Åke,
  Société, Ørsted would never have matched), and validates the list on its own:
  it must compile, must not match the empty string, and cannot break out of its
  group ('x)|.*(' compiles alone only if balanced)
- NewRouter refuses any pattern that matches text naming no client
- docs state the whole-word semantics and what is not matched
Mutation-checked. Open decision for Mathias: whole-word versus substring recall
for a confidentiality filter (plurals, CamelCase and digits glued on do not match).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 21:44:23 +02:00

4.4 KiB

The raw/ inbox

raw/ is an inbox: only unprocessed material sits there. Syncthing shares it with the machines you drop files from. (hyperguild#205, #208, #209)

What happens to a file you drop

You drop Result
raw/clip.md (no folder, no wing:) extracted and filed as a source in wiki/web-clip/sources/; its concepts and entities update the shared wiki/concepts/ and wiki/entities/ pages; the original moves to raw/processed/<date>/, so raw/ is empty again
raw/<wing>/clip.md or wing: <wing> in the frontmatter the same, with the source in wiki/<wing>/sources/. The wing must already exist; a typo is parked, never created. This is your deliberate choice and is not second-guessed
a note whose text matches the client-content pattern, with no folder parked in raw/needs-review/, not extracted
a folder or wing: naming an unknown, reserved or non-ASCII wing, or two disagreeing signals parked in raw/needs-review/
a note over the size cap, or one that cannot be archived stays in raw/, reported once, not retried until it changes
a note the model returned nothing usable for (no source page could be written) fails: the note is kept in raw/failed/ and the reason is in log.md; it is never archived as processed

Concepts and entities are shared across wings because their slug is the graph's identity. A source whose slug is taken gets a wing-qualified one (notes-homelab).

Parked notes

brain_pending lists them with queue: needs-review, a proposed wing and the reason. To act on one: brain_promote / brain_reject (pass queue when the same name also sits in the inbox), or move the file into raw/<wing>/ to have it extracted. Parked pdf/txt files are listed but can only be moved or rejected.

Switching it on

Routing is off by default (the retired layout is used). Set on the ingestion deployment:

Variable Meaning
INGEST_WING_ROUTING 1/true enables the rules above; unset or 0/false is off; any other value stops the server at startup
INGEST_DEFAULT_WING wing for unsignalled notes (default web-clip; must be a plain name, not sources/concepts/entities/wiki)
INGEST_CLIENT_BLOCK case-insensitive regexp over note text; a match parks an unsignalled note. Falls back to CLAUDE_INGEST_CLIENT_BLOCK, which the deployment injects as a bare list of client names (`acme

A bad default or pattern stops the server at startup. A wing created while the server runs is usable without a restart.

Known limits

  • The client filter works on 1 MiB chunks that overlap by 4 KiB. A match that can span more than 4 KiB (crafted padding between two words of a multi-word pattern, exactly at a chunk edge) is not guaranteed to be found; this affects notes over 1 MiB only. On a 64 MiB note the check takes about ten seconds.

  • A pattern that matches the empty string (.*, x*) parks every unsignalled note. That fails closed and only the operator's own configuration can do it.

  • A deliberate folder into a sensitive wing places the note there, and the shared concept/entity pages then cite that source by title. Client material does not belong in the brain at all; the pattern only guards the unsignalled lane.

  • A merge into a shared page refreshes last_updated and origin to the latest ingest; the first wing's attribution is not kept.

  • A marker file (<note>.processed) is only written when a processed original cannot be removed. One at least as new as its note holds the note (and says so once); an older or future-dated one is ignored and removed.