Codebook authoring

The complete reference for building a pack. A codebook is seven files in a folder, all yours: four data files the engine enforces, and three prompt files the model reads in your words. Start by copying the shipped example (vision/example_codebook) and validate as you go with neuraframe codebook check <dir>.

The pack at a glance

FileRequiredRole
manifest.jsonyesYour domain's tables: context, grading columns, band sets, legality, readings.
registry.jsonyesYour codes, one entry each: family, record mode, grading.
rules.mdnoDomain knowledge that rides on EVERY model call: discriminators, confusion pairs, grading discipline.
detect.mdnoTask framing for wide-net detection calls, verbatim.
confirm.mdnoTask framing for dossier confirmation calls, verbatim.
notes.mdnoStanding operator notes (site or standard guidance), appended to confirmation calls.
excluded.jsonnoRegistry codes out of scope for this deployment.

manifest.json, key by key

KeyWhat it declares
name, version, descriptionIdentity. Version your pack like software: the run output records which pack coded it.
context_fieldsThe facts a run can be told ([{"key", "values"?, "note"?, "assumed_note"?}]). Anything not supplied falls back to defaults and is listed on every record in assumed_defaults, with your assumed_note explaining the risk. Defaulting silently is the failure this prevents.
defaults{field: value}. The safe assumption per field, used only when the run does not supply one.
grading_field, grading_columnsWhich context field selects the grading column, and the legal column names. A registry entry's grading object is keyed by these columns.
band_setsNamed percentage-band ladders, e.g. {"A": ["<=10","10-20","20-30",">30"]}. A code references one by name; different codes can use different ladders, and the model is only ever offered the bands, never asked for a number.
legality{field: {value_substring: [families]}}: a context value under which whole families cannot occur. Unknown context means the gate does not run (confidence reduced, never blocked).
conditional_legality[{"codes"|"families", "allow_when": {field: [values]}, "message"}]: codes only legal under certain context. Outside it they are INVALID records and the engine blocks them regardless of the model's confidence.
presence_gated_families{family: context_field}: a family legal only when a feature is recorded present (a lining, an attachment).
remap_families{prefix: family}: where a loose model code routes when it is not in the book, so the finding is kept with candidates instead of dropped.
surfaces, surface_rulesYour surface vocabulary and the contradictions to catch: [{"prefix"|"family", "require"|"forbid": [surfaces], "message"}].
readingsNumeric scene values some codes carry, read against a datum your standard defines: {field: {"codes"|"families", "ask", "min"?, "max"?, "unit"?}}. The ask text is put to the model in your words and must name the datum. Values outside the range are ignored and flagged, never accepted. Readings drive STATE-mode change detection (state_min_reading_delta).
regionsNamed places around the frame mapped to clock hours: {"<region>": {"clocks": [..]} | {"exclude_clocks": [..]}}. A registry entry's expected_region is checked against the OBSERVED clock (which comes from tracking, not the model): a low-lying code observed overhead is flagged for recoding, never dropped.
state_at_startSTATE codes that are properties of the whole survey (a level, a size) and exist from the very start. The first record is anchored to the segment start however late the camera first read it, later records are changes only, and a declared code that never appears at all is surfaced for review rather than silently absent.
hostsWhat satisfies each host name a registry entry can require (requires_host). Forms: {"codes"|"families": [..]} (a coded record of these near in time and clock), {"context": "field"} (a survey fact), {"external": true} (only an external record can satisfy it; the engine routes such claims to review), {"visual": true} (the confirmation call itself judges it). A code asserting a host that is not independently present goes to review: a hallucinated feature rarely brings a hallucinated host along with it.

registry.json, entry by entry

{"code": "WG", "title": "Growth, general", "family": "growth",
 "record_mode": "PROMOTABLE",         one of SINGULAR | STATE | REPEATED | EXTENSIVE | PROMOTABLE
 "graded": true, "axis": "upkeep",    axis splits the ratings (e.g. condition vs upkeep)
 "band_set": "A",                     which band ladder this code resolves on
 "grading": {"ornamental": {"type": "threshold", "rules": [
     {"band": "<=10", "grade": 2}, ...]},
             "vegetable": {"type": "fixed", "grade": 4}},
 "expected_region": "ground",         optional: checked against the observed clock via manifest regions
 "evidence_primary": "L",             optional: L/luma (structure, default) | C/chroma | T/temporal.
                                      T codes grade as a range until rate metrics resolve them; L codes
                                      with chroma-only support are flagged suspect (unless their
                                      declared evidence_secondary is chroma)
 "requires_host": ["stake"],          optional: hosts this code asserts, checked against the manifest's
                                      hosts map before a record is written
 "min_extent": {                      optional: an EXTENT FLOOR for codes describing things with
   "min_sightings": 6,                physical extent (an installed repair covers a section). Both
   "min_clock_span_hours": 3},        terms must hold or the finding routes to review - appearance
                                      alone can never carry an extent-gated code. Units the engine
                                      has: sightings and wrap-aware clock span. Policy, tunable.
 "anchored": true,                    optional: SURVEY STRUCTURE, emitted from the job header at the
                                      boundaries (manifest anchored_records says which context field
                                      names the type and what the honest unknown default is). Never
                                      the output of a confirmation call: a tracked claim of an
                                      anchored code routes to review.
 "position_constraint":               optional: "survey_boundary" - the code may only exist at the
   "survey_boundary",                 start or end of the survey; mid-reach is a contradiction and
                                      routes to review (stands down when the length is unknown).
 "clock_applicable": false,           optional: the code occupies the FULL view (you pass through
                                      it), so a candidate localised to one clock position is a wall
                                      feature by construction; genuine full-view records have their
                                      meaningless clock stripped.
 "residual_code": true,               optional: marks a LAST-RESORT bucket (an "Other", a vague
                                      catch-all). Residuals are structurally last: the model must
                                      reject the specific alternatives explicitly to answer one,
                                      downgrades from specific proposals are logged, and broad-support
                                      overrides route to review. Under-call leaves no artifact, so it
                                      is gated, not advised against.
 "state_trigger": "survey_start",     STATE codes only: survey_start (the record exists from frame one,
                                      anchored at t=0, emitted even if never sighted, value unknown when
                                      illegible) | on_change (exists ONLY at a transition; absence is
                                      the normal output - a change with an unknown value is a claim
                                      that something changed with no idea what). Authoritative over the
                                      manifest's state_at_start list when declared.
 "fields": {"cont": "optional"}}      cont: "-" forbids a run for this code

Grading types: fixed (one grade for the column) and threshold (a grade per band, in ladder order; the rule count must match the band set, and check verifies it). A graded code with no column supplied resolves to a range across columns; a threshold code with no band resolves to a range across its ladder. The engine never invents the missing information.

The three prompt files

Model calls are assembled in three layers, and you own the first two:

LayerWhere it livesNotes
Task framingdetect.md / confirm.mdWide-net coverage wording for detection; decisive single-code wording for confirmation. When present, used verbatim in place of the built-in framing. Keep them separate on purpose: mixing "include everything" with "be decisive" degrades both passes.
Domain knowledgerules.md (+ notes.md)Rides on every call: your decision spine, the confusions your footage produces, your grading discipline. notes.md is standing site guidance appended to confirmations; a per-job notes_file in the run config appends after it.
Answer contractthe engine, alwaysThe JSON shape the model must return is appended by NeuraFrame™ and cannot be overridden, so no amount of prompt tuning can break parsing.

The authoring loop

# 1. copy the example and replace its content with your standard
cp -r /opt/neuraframe-studio/current/vision/example_codebook my-pack

# 2. validate after every change: every problem is listed, nothing silently ignored
neuraframe codebook check my-pack

# 3. prove the whole spine free, then live on a SHORT clip
neuraframe codebook use my-pack
neuraframe codebook run --input clip.mp4 --out coded --stub
neuraframe codebook run --input clip.mp4 --out coded --end-ms 30000

# 4. read coded/report.md against the dossiers, then tune

Tuning lives in three places, in order of power: the pack's prompt files (what the model is told), the run configuration, and the registry itself (what exists and how it grades). The configuration has four blocks: run (sampling and tracking; also CLI flags, listed by codebook run --help. sample_fps is the sampling rate and 0 means every frame), coder (endpoint, dossier, location; views_per_dossier sets how many frames of one finding ride in a single confirmation call), records (projection and verification thresholds), and context. The run output records the pack version and every knob in force, so two runs are always comparable.

What the engine will do with your pack, regardless

Prove the mechanisms on your own install any time: python3 vision/nf_codebook_board.py.