--- type: guide title: OKF Bundle Maintenance description: Keep your OKF knowledge bundle from rotting — change tracking, frontmatter discipline, staleness detection, and automation. tags: - okf - maintenance - documentation - best-practices - unverified timestamp: 2026-10-19 --- # OKF Bundle Maintenance Knowledge bundles rot. It is the nature of knowledge to attract cobwebs, much like an unvisited pantry attracts spiders that are frankly doing you a favor by reminding you it has been a while. An OKF bundle maintained by agents is no exception — files drift out of sync, frontmatter becomes decorative, and `index.md` turns into a ghost town where links go to die. **The core principle:** if you do not track changes, you do not know when they happened. If you do not have a changelog, you are the person who finds the broken thermostat and wonders why it is set to "volcano." --- ## Change Tracking with `log.md` Exactly one `log.md` per bundle, at the bundle root — [okf-spec.md](okf-spec.md) owns that rule and `scripts/kb-lint.sh` enforces it, reporting any `log.md` that is not the root's. The maintenance action is collapse, never coexistence: when a second log turns up (`core/log.md`, `notes.md`, a per-run diary), move its entries into the root log under their own dates, delete the file, and re-run the linter. **Format:** one dated section per day, newest first; a few lines per change — what happened, and the durable lesson. It is not a file manifest. ```markdown # Bundle Change Log ## 2026-01-15 — the gate was reading the wrong files A gate that gets an empty file list reports success. Law: a check MUST fail closed; a silently-passing gate is worse than none, because it buys the belief of safety. Details: [secret gate](/tools/index.md). ``` **Rules:** - **Newest entries first.** Old entries at the top invert the timeline. - **What changed + the durable lesson, a few lines.** Full narratives are recoverable from git (`git log --follow log.md`); never re-expand one in place. - **Laws and incidents, never bookkeeping.** No per-file inventories, no run-by-run numbers, no transcripts. Measured numbers still have to pass the purpose test. - **Link, do not duplicate.** Knowledge that outlives the entry belongs on its concept page; the entry points there. - **One dated section per day** (`## YYYY-MM-DD`), and mention `index.md` whenever a file is added or removed. ### Common Mistakes - ❌ `Updated ghostty.md` — updated it with what, and what did it teach? - ❌ Forgetting the entry — the change lands undocumented and the next agent rediscovers the failure the hard way. - ❌ Starting a second log in a subdirectory — the sprawl that makes logging useless. - ❌ Invented paths in links — the RECOMMENDED form is an absolute bundle path (`/tools/index.md`), resolved against the bundle root; the mistake is a path that names no file there, and that is what the linter reports. - ❌ Re-expanding an old entry in place — the entry is a pointer; git is the transcript. --- ## Frontmatter Discipline Frontmatter is the metadata layer. It is not decoration. ### Required field: - `type` — The concept type. The only strictly required frontmatter field. ### Strongly recommended: - `description` — The preview text. Without it, the file is invisible and confusing. - `tags` — Use for cross-cutting concerns. Tags hold things together across categories. - `timestamp` — Include for staleness detection. A file with a timestamp from 2023 is more likely stale than one from 2026. - `title` — Optional but helpful. ### Rules: - ✅ Every concept file must have a `description`. - ✅ Use `tags` liberally but consistently. - ✅ Include `timestamp` on every file. - ✅ Pick descriptive `type` values: `reference`, `guide`, `configuration`, `tutorial`. - ❌ Don't use `type: file` or `type: document` — be specific. - ❌ Never leave `description` blank or copy the title. --- ## One Thing Per File OKF is built on the principle that a file is one concept. **Splitting criteria:** - ✅ One topic, one file. If the content can be summarized in one sentence without using "and," it belongs in one file. - ✅ Give each file its own `type`. - ✅ Keep each file between 1 and 500 lines. Under 1 = over-split. Over 500 = under-split. - ❌ Don't create a file called `misc.md` — `misc` is a graveyard, not a category. - ❌ Don't use `# Other` or `# Additional Notes` sections — these are taping things to the wall. ## Quarantine, Not Deletion A page is never deleted outright: it moves to `.AGENTTRASH/` beside where it lived and waits for a pruning session with Frank present. The quarantine is not part of the bundle — `scripts/kb-lint.sh` and `scripts/kb-coverage.py` skip any path containing `.AGENTTRASH`. That exemption is deliberate: a gate that goes green only once the quarantined copy is gone is a gate that deletes history. --- ## Auto-Generation Strategies ### Index files as living documents: ```bash find docs/bundle-name/ -name '*.md' ! -name 'log.md' -type f | \ sort | \ awk '{print "- " $0}' > docs/bundle-name/index.md ``` ### Staleness detection: ```bash # Find files older than 90 days find docs/ -name '*.md' ! -name 'index.md' ! -name 'log.md' \ -mtime +90 -type f -print # Find files missing timestamp find docs/ -name '*.md' ! -name 'index.md' ! -name 'log.md' \ -type f -exec grep -L '^timestamp:' {} \; # Find files missing description find docs/ -name '*.md' ! -name 'index.md' ! -name 'log.md' \ -type f -exec grep -L '^description:' {} \; ``` --- ## Version Control Best Practices - ✅ One logical change per commit - ✅ Write meaningful commit messages ("Updated file" is not a commit message. It is a shrug in text form.) - ❌ Don't commit entire bundle dumps — a commit touching 50 files is a data dump, not a change ### Useful git commands: ```bash git blame -L 1,30 docs/ghostty.md # Who changed what and when git log --oneline -n 10 -- docs/pi-permission-system/ # Last commits in a directory git status --short # What is uncommitted ``` --- ## Knowing When Something Is Stale | Signal | Threshold | Action | |--------|-----------|--------| | `timestamp` field older than 6 months | Auto-flag | Review and update or archive | | File not modified in 12 months | Auto-flag | Assess whether still relevant | | `index.md` count differs from file count | Always | Fix immediately | | `log.md` has no entries for 30+ days | Context-dependent | Normal if no changes made | --- ## Automated Gates (this bundle) Two mechanical checkers live in `scripts/`; both exit non-zero on violations. Run both before committing any `omp-docs/` change; `tests/kb-lint.bats` pins their behavior. ```bash bash scripts/kb-lint.sh omp-docs # OKF conformance python3 scripts/kb-coverage.py omp-docs # index coverage doctrine ``` - **kb-lint** — OKF v0.1 rules: non-empty `type` frontmatter on every non-index file, no frontmatter on `index.md`, resolvable wikilinks and relative links, reserved names (`index.md`/`log.md`), `YYYY-MM-DD` log headings. - **kb-coverage** — the AGENTS.md anti-rot mechanism: every directory has an `index.md`, and that index links every sibling file and subdirectory. --- ## See Also - [OKF v0.1 Specification](okf-spec.md) — The complete format specification. - [Root Index](/index.md) — This bundle's structure and navigation.