Skip to content

Latest commit

 

History

History
232 lines (193 loc) · 12.8 KB

File metadata and controls

232 lines (193 loc) · 12.8 KB

libmisbklv agent instructions

C++ library to read and write MISB KLV data — ST 0601 (UAS Datalink Local Set) + ST 0903 (VMTI) — from/to MPEG-TS containers via gstreamer (file or stream; real-time insertion via appsrc). Video passthrough can generate ST 0604 Precision Time Stamp SEI on request (ADR 0024 — off by default, so passthrough video is byte-identical); the rest of ST 0604 (ES-layer timestamp reading, H.265 Nano, Commercial time code) and an ffmpeg backend are deferred — see ADRs 0008/0009.

This file is the canonical, vendor-neutral copy — edit it here. CLAUDE.md is a one-line @AGENTS.md import, since Claude Code auto-loads that filename. Adding support for another agent means adding another thin pointer, never a second copy of these rules.

Agent knowledge base

The project's working knowledge lives in context/ as an OKF v0.2 bundle.

Before every commit checklist

When you implement a significant change (new feature, milestone, decision):

  1. ✅ Code changes staged
  2. context/log.md updated (append dated entry)
  3. planning/PROGRESS.md updated (Now/In-progress/Next reflect current state)
  4. ✅ If decision made: ADR written, context/decisions/index.md updated

Never commit code without updating the docs that describe it. If you're about to commit and haven't touched log.md or PROGRESS.md, stop and update them first.

What goes in each doc — and the rules behind this checklist — is Planning hygiene below.

Planning hygiene

Each doc has one job — keep them from re-narrating each other. The why behind each rule is in context/workflow-rationale.md — read it before relaxing a rule. A rule without its reason gets deleted the first time it's inconvenient.

  • context/log.md — the durable chronological record: what landed when, milestone/decision detail, routine ingests/lint. History lives here, newest-first.
  • context/decisions/index.md — the decided register: fork # ↔ ADR ↔ status. The single source of truth for what's decided.
  • planning/PROGRESS.mdpresent state only (Now / In-progress / Next). Volatile; rewrite each session. No "Done" history (that's log.md); "Next" is the 1–3 immediate actions and points to ROADMAP for the candidate backlog — it doesn't re-list it. "Now" is where the work is, not a feature inventory: if a sentence would still be true after a month of no work, it's durable knowledge — it belongs in a context/ concept or an ADR, with only a pointer here.
  • planning/ROADMAP.md — scope, phases, and the single backlog of open + candidate forks (a fork = a decision point that needs a choice — a fork in the road, not a git fork; see CONVENTIONS § Decisions). Defers the decided register (and the fork count) to decisions/index.md; never enumerates a fork range.

So:

  • On a significant decision (a fork resolved or changed): write/update the ADR in context/decisions/ per the lifecycle in context/CONVENTIONS.md (decision_status: proposed → accepted / superseded / deferred), add/update its row in the decided register (decisions/index.md), append one thin log.md line (chronology + link — the ADR owns the rationale; see CONVENTIONS § Decisions), and refresh PROGRESS's present state. Touch ROADMAP only if it opens/closes an open fork or shifts a phase.
  • On implementing a significant change: append a log.md entry (the detail) and refresh planning/PROGRESS.md's present state (Now / In-progress / Next) — a thin pointer, not a history. Do this in the same commit as the implementation: a doc updated "later" is wrong in between.
  • Closing scrubs the future: when you resolve a fork or complete a candidate / deferred / "Next" item, delete its forward-looking mentions (ROADMAP candidates, PROGRESS "Next") — not just the present-state bullet you're editing. Open work has one home; a resolved item leaves it. (Forward-looking claims drift the same way history does — this is the future-tense half of "one job per doc".)
  • No live tallies in durable prose: never bake a running count (test cases, item totals, "N of M done", fork ranges like "1–N") into present-tense docs (PROGRESS, ROADMAP) or ADR bodies — it drifts. Say "all CTest cases green", not "19"; "none open, see the register", not "forks 1–17". A specific number belongs only in a dated log.md snapshot (history, frozen at write time). Same for any state that moves — describe the state, don't tally it.

Build / test / run

Preferred: cmake --preset release && cmake --build --preset release && ctest --test-dir build/release (also debug, sanitize — see README.md's preset matrix; these are the same presets CI uses). Fallback without presets: cmake -S . -B build && cmake --build build && ctest --test-dir build. Normal builds consume committed generated fixtures and need no Python. Python 3.11+ is needed only for the optional registry/fixture regeneration targets.

klv_bench is a timing harness, built by default and deliberately not a CTest case — a timing threshold in CI measures the runner, not the library. Run it by hand when a number is needed, and read it as ranges rather than point values (codec rows move ~15% run to run on a normal desktop): ./build/release/klv_bench test/fixtures/synthetic-basic.klv test/fixtures/synthetic-timed-0x06.ts [MiB]

Format changed C/C++ lines with git clang-format origin/main (preview with git clang-format --diff origin/main); the checked-in .clang-format owns the style. Handwritten C++ has a formatter-clean baseline; generated registry headers opt out in their directory because the generator owns their bytes. Do not turn an unrelated change into a whole-tree formatting sweep.

The formatting-only baseline commit is listed in .git-blame-ignore-revs. GitHub honors it automatically; for the same local blame view, run git config blame.ignoreRevsFile .git-blame-ignore-revs.

Two options: MISBKLV_GSTREAMER (default ON) builds the gstreamer media backend — the KLV core builds and tests without it, and that separation is load-bearing (see context/backend-scope.md). MISBKLV_SANITIZE (default OFF) builds with -fsanitize=address,undefined; the core is kept clean under it.

What the suites guard, so a change lands in the right one:

  • st0601_examples — the standard's own per-item worked examples. The authority on scales and encoding for the 0601 registry; a scale change that passes everything else must pass this.
  • hardening — multi-byte BER-OID tags (≥128), Report-on-Change trimmed packets, and malformed/adversarial input (overflow guards in length arithmetic, length validation in codec::decode).
  • message, roundtrip, imapb, nested_vmti, vtarget_series, standalone_vmti — core encode/decode and the ST 1201 IMAPB path.
  • gst_* and stream_* — the backend: extraction and insertion, file and live, against project-owned synthetic fixtures under test/fixtures/. The developer-provided media in data/ is not required by the suite.
  • api_stream, stream_stop — the high-level API and prompt cancellation (ADR 0019).
  • jmisb_crosscheck — our output read back by an independent implementation.

CI runs build+test, a consumer smoke test (find_package(misbklv COMPONENTS gst) against a real out-of-tree build), a sanitizer job (core only), and generated-output drift checks for the registry tables and synthetic fixtures (ADR 0012, ADR 0028).

Prose style

American English, everywhere prose appears — code comments, doc strings, CLI help and error text, test messages, Markdown, commit messages. behavior not behaviour, center not centre, -ize/-ization not -ise/-isation, meters not metres, license (noun and verb), judgment, analyze. This is consistency, not correctness: the standards this library implements (MISB ST 0601, "Frame Center") are American-spelled, so matching them keeps our prose and the item names we quote from disagreeing on the same page.

references/ is exempt, and no snapshot already there is ever restyled — it is append-only source-of-truth input: an ingest may add a new PDF/.txt snapshot, but nothing already deposited is edited, reformatted, or restyled to match. So is any vendored third-party code: read it, never restyle it.

Commit messages

No Co-Authored-By trailer — keep history clean. When committing on the user's behalf, write the message without the Claude co-authorship line.

Agent authorship on PRs, issues, and comments

When an agent posts a PR body, an issue, or a review comment, it identifies itself — the generating model — as the author, e.g. Author: Claude Code (model: claude/opus-5). This is separate from the git commit author, which stays the human or machine that invoked git, and the commit message's author field is not the place for it (see Commit messages above). It goes in the PR/issue/comment prose so a reader can tell which model produced what, and a comment's author line names the model that wrote that comment — not the model that opened the PR. More than one agent works this repo, so an unattributed comment is genuinely ambiguous.

Spell the model as <producer>/<model> — the vendor or harness that generated the text, then the model: claude/opus-5, openai/gpt-5, opencode-go/muse-spark-1.2-contributor. One pair, no exceptions. That is the same pair the knowledge bundle's generated.by actor form uses (context/CONVENTIONS.md § Actors), written for a narrower case, so an agent spells itself identically in frontmatter and in prose. Don't exempt an agent whose harness and model are distinct: two spellings for one agent is the failure this rule exists to prevent, and a <producer> slot that accepts a harness already fits it.

The rule applies going forward; comments predating it are left as they are.

Security — location and identity data

data/ holds developer-provided media that may carry real location and identity data, and is gitignored. Never commit a file from data/, and never copy what one contains — coordinates, platform or sensor identity, tail numbers, absolute times — into code, tests, fixtures, commit messages, documentation, or agent memory. test/fixtures/ is project-authored and synthesized by generate_synthetic_fixtures.py, never derived from supplied media.

Scope: media this project holds, and anything derived from it. The rule protects recordings; it is not a rule about citing external material. Published facts about third-party media the project does not hold — where a sample came from, who holds the rights, why its terms were judged unclear — are bibliography. context/data-samples.md is exactly that: the record of why the historical corpus was removed (ADR 0028), describing files this repository never contained and no longer references. It is subject to this rule for accuracy, not for redaction — and it is the evidence that the removal was deliberate, so it is retained.

The sibling repository parrot-to-klv carries this same rule, scoped the same way, where data/ holds real flight recordings. The same class of data crosses both repositories, so the two are kept aligned deliberately — change one and change the other.

Repo layout

  • references/ — MISB standards (PDF + .txt extract). Source of truth, append-only: read; add a snapshot on a directed ingest; never edit what's there.
  • context/ — agent knowledge bundle (maintain this).
  • docs/ — human-facing guides (terse).
  • data/ — ignored developer-provided media; see data/README.md.
  • test/fixtures/ — project-owned deterministic KLV/MPEG-TS fixtures and the generator used to create them.
  • planning/ — live plan + progress (ROADMAP.md, PROGRESS.md). Read first for "what now".