Engine documentation

FIMO-RUN: 404-in-a-box, build- en testverslag

Engine protocol and working reference.

Gebouwd: 2026-07-09. Alleen python3-stdlib (sqlite3 met FTS5, getest op Python 3.12.3 / SQLite 3.45.1) en bash. Geen pip, geen server. Het pakket wordt LEEG geleverd; alle tests hieronder draaiden met zelfgemaakte dummy-data (fictieve gebruiker Alex, companion Nova, bedrijf Brightbeam; zie examples/sample-input/).

De lagen en de keuzes

  1. Ingest + zoek (ingest.py, ask.py, fimo_core.py) Een SQLite-bestand (data/brain.db) met een documents-tabel plus FTS5-index (external content, triggers houden 'm in sync). Idempotent via sha256 per bestand: ongewijzigd = overslaan, gewijzigd = update in place, nieuw = insert. JSON-chatexports worden platgeslagen naar leesbare tekst (tekstvelden van elke vendor-vorm), datum/titel/bron best-effort gedetecteerd. ask.py zoekt eerst in de memory-files (gedestilleerd), dan FTS over de bronnen, elke hit met snippet en bronpad.
  2. Canon (generate_canon.py -> CANON/KERN.md + CANON/LLM-PROMPT.md) Twee routes: (a) offline extract zonder LLM (corpus-stats, top-topics, key statements met altijd/nooit/regel/besloten-signaalwoorden, recente docs) en (b) model-agnostische prompt + corpus-digest die de gebruiker aan een eigen LLM voert en importeert met --from-file. Handwerk tussen <!-- HAND --> ... <!-- /HAND --> overleeft elke re-run byte voor byte (regex-extractie, blokken worden na de generated-sectie teruggeplaatst); alleen het blok tussen de GENERATED-markers wordt herschreven.
  3. Memory (remember.py, memory/MEMORY.md) Eén file per onderwerp, indexregel in MEMORY.md, geen duplicaten: zelfde onderwerp opnieuw = append in de bestaande file.
  4. Archivers (archivers/) run_ingest.sh als enige entry point; systemd-user-timer (hourly, Persistent) en cron-template, beide met __FIMO_DIR__-placeholder; install.sh vult het echte pad in en valt terug op cron-instructies zonder systemd. Canon-regeneratie zit bewust NIET in de timer (canon is iets dat je reviewt).
  5. Session-start + gedrag (session-start/) build_context.py print KERN.md + MEMORY.md + gebruiksinstructies; CLAUDE.md-template en hook-voorbeeld voor Claude Code, generiek system-prompt-blok voor andere runners. behavior_catcher.py + behavior-rules.txt (regex :: uitleg) als gedrag-catcher, met Stop-hook-modus die een blocking decision teruggeeft.

Self-verify gate: letterlijke uitslagen (alles echt gedraaid)

1. Dummy-chats erin, ask.py vindt de gezegde zin (PASS)

=== INGEST RUN 1 ===
Scanned: 4 | new: 4 | updated: 0 | unchanged: 0
Total in brain: 4

=== ASK: purple heron ===
--- SOURCES (raw documents) ---
* [2026-05-14] First long chat about the garden project  (input)
   ... the >>purple<< >>heron<< lands at midnight on the old jetty. ...

JSON-export ook gevonden, met datum uit create_time:
=== ASK: hardcovers ===
* [2026-06-10] chat-export  (input)
   ... paperbacks only, I never buy >>hardcovers<<.

2. Canon geregenereerd, HAND-blok overleeft (PASS, bewijs: diff)

Twee handmatige HAND-blokken in KERN.md gezet, daarna geregenereerd:

=== FULL-FILE DIFF (regen vs regen) ===
4c4
< *Offline structured extract, generated 2026-07-09 17:08 UTC. ...*
> *Offline structured extract, generated 2026-07-09 17:09 UTC. ...*
=== HAND-ONLY DIFF ===
HAND-only diff exit: 0 (identical, byte for byte)

Alleen de timestamp in de generated-sectie verschilt; beide HAND-blokken byte-identiek terug. Ook getest met --from-file (LLM-antwoord als generated body): "hand blocks preserved: 2".

3. Memory-file blijft staan over een verse sessie (PASS)

remember.py gedraaid, daarna in een NIEUW proces session-start/build_context.py:

- [liner order rule](liner-order-rule.md): Pond liners must be ordered two weeks ahead, decided after the June delay
- [book format](book-format.md): Paperbacks only, never hardcovers

Zelfde onderwerp nogmaals remember-en: append in de file, geen dubbele indexregel (grep-count op de indexregel bleef 1).

4. Archiver pakt nieuwe input (PASS)

Nieuwe dummy-file in input/ gezet, bash archivers/run_ingest.sh 1x handmatig gedraaid:

Scanned: 5 | new: 1 | updated: 0 | unchanged: 4
=== ASK: silver fox towpath ===
* [2026-07-01] Night walk chat 2026-07-01  (input)
   ... The >>silver<< >>fox<< crossed the >>towpath<< at dawn today.

5. Idempotent (PASS, bewijs: counts)

Scanned: 5 | new: 0 | updated: 0 | unchanged: 5   (run 1)
Scanned: 5 | new: 0 | updated: 0 | unchanged: 5   (run 2)
documents: 5
distinct paths: 5

Extra: gedrag-catcher (PASS)

echo "As an AI language model I cannot help with that. Is there anything else?" | behavior_catcher.py -
-> 3 violations, exit 2
hook-modus met fake transcript.jsonl:
-> {"decision": "block", "reason": "Behavior rules violated: ..."} , exit 0
schone reply -> exit 0

Extra: installer-templates

bash -n op beide shellscripts OK; sed-substitutie van __FIMO_DIR__ gecontroleerd (ExecStart en cron-regel kloppen); hook-settings-voorbeeld is valide JSON. De timer is bewust NIET op deze machine geinstalleerd (zou hier een nutteloze user-timer achterlaten); de unit-files volgen hetzelfde patroon als de draaiende timers van dit systeem.

Privacy-check

Case-insensitive grep over het hele pakket op de zes gevoelige namen/termen uit de bouwopdracht: 0 hits buiten de productnaam "404-in-a-box". Het pakket bevat uitsluitend lege structuur en verzonnen dummy-data (Alex, Nova, Brightbeam); niets uit de bron-architectuur is inhoudelijk overgenomen.

Wat de gebruiker zelf doet

  1. Eigen data in input/, python3 ingest.py.
  2. python3 generate_canon.py; voor echte destillatie LLM-PROMPT.md aan een eigen LLM voeren en met --from-file importeren.
  3. bash archivers/install.sh voor de timer (of cron-regel plakken).
  4. Session-start koppelen (CLAUDE.md of system-prompt) en behavior-rules.txt vullen met eigen regels.

Bekende grenzen / open punten

  • SQLite over SMB/CIFS is traag en lock-gevoelig: het pakket hoort op een lokale schijf te draaien. Echt gemeten bij de oplevering: ingest met de db op de NAS-share gaf sqlite3.OperationalError: database is locked; dezelfde geleverde kopie draaide daarna vlekkeloos end-to-end met FIMO_DB naar een lokale schijf (ingest 4 docs, ask vond de dummy-zin, canon gegenereerd). Staat ook zo in de README-verwachting: lokaal draaien is de norm, FIMO_DB is de escape hatch.
  • De offline canon-extract is bewust simpel (frequenties + signaalwoorden); de echte destillatie-kwaliteit komt uit de LLM-route. Dat is een keuze, geen gat: model-agnostisch blijven was de eis.
  • Windows: scripts zijn OS-neutraal (python3 + paden via os.path), maar de archiver-templates zijn systemd/cron; een Task Scheduler-template is niet meegeleverd. RECON NEEDED als er een Windows-koper komt: welke scheduler, dan is dat een template van 10 regels.
  • .json-extractie is heuristisch (tekstvelden op key-naam). Exotische exportvormen kunnen ruis geven; de fallback (pretty-printed JSON) blijft wel doorzoekbaar.