Measured fixes, one line each, from the review of everything that landed on 2026-10-20 (issue #60). Each page keeps its own facts; nothing was moved. - inventory/index, index: the census blurb says what the page actually covers (tracked-vs-box-only per file), not "all userspace configuration" - dotfiles-deploy: the wallpaper re-fetch recipe resolves the CDN URL through the wallhaven API — /w/<id> answers text/html, so curl -L never yields a JPEG; description widened to the whole page, tools/index blurb matched - okf-maintenance: the link example and the mistake bullet now agree with okf-spec, which RECOMMENDS absolute bundle paths (they said the opposite) - decisions/index: the unlisted-page gate is kb-coverage.py, not kb-lint - AGENTS.md: the three skill-config subsections are pointers again; the pages own issue tracker, labels and domain docs - swayidle-lock.service: Description names what the unit does (arms the idle lock over noctalia-shell IPC); suspend belongs to noctalia's inhibitor - common.pkgs: git-lfs re-justified by the tracked .gitattributes filter contract; the swayidle comment drops its lid-policy claim
192 lines
7.3 KiB
Markdown
192 lines
7.3 KiB
Markdown
---
|
|
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`
|
|
|
|
Every OKF bundle has a `log.md`, and it is the bundle's **only** work log: one file,
|
|
at the bundle root. A subdirectory never gets its own — not `core/log.md`, not
|
|
`notes.md`, not a per-project, per-branch or per-run diary. Sprawl is not caution:
|
|
with fifty logs the entry is never where the next agent looks, and each copy re-dates
|
|
the same event on its own authority. `scripts/kb-lint.sh` reports any `log.md` that is
|
|
not the root's.
|
|
|
|
**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.
|