live: heartbeat sync 2026-10-19T11:18:41-07:00 (Refs #11)
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: docs-point-of-use-destruction
|
||||
description: "Documentation exists for point of use, not archival. Use before any dedupe/compact/verify-docs job, and whenever a census or \"only copy\" argument is being used to KEEP documentation: apply the purpose test and destroy obsolete measurements. Supersedes the preservation conclusions of vault-one-fact-one-owner-dedupe §3/§12."
|
||||
---
|
||||
|
||||
# Documentation exists for point of use
|
||||
|
||||
**Supersedes** `vault-one-fact-one-owner-dedupe` §3 ("port before cut") and §12
|
||||
("expect docs flat") wherever those conclude a page must be *kept*. Sole custody of a
|
||||
useless fact is still useless.
|
||||
|
||||
## The test, before you write and again before you keep
|
||||
|
||||
- Would the reader, doing a real task tomorrow, **act differently** because of this
|
||||
line? No → delete it.
|
||||
- Is it a measured rate (t/s, tok/s, ms, MiB-of-pool, acceptance %, a bench ladder) for
|
||||
a model / runtime / layout that is **not running now and not being compared now**?
|
||||
Destroy it. Not "file it in an Eras row", not "preserve it for history". AI moves
|
||||
faster than the vault: the number is wrong before anyone reads it, and a wrong number
|
||||
in a runbook gets believed.
|
||||
- Keep the **law** the measurement taught; drop the measurement. Qualitative causal
|
||||
stories survive; numbers do not.
|
||||
- What survives: live config and its exact numbers, procedures, failure signatures,
|
||||
security posture, interface contracts, rollback pointers.
|
||||
- **Losing information is an acceptable, usually correct outcome.** Frank said so
|
||||
explicitly on 2026-10-19 after rejecting a PR that had preserved 53 ledgers.
|
||||
|
||||
## Traps that lead agents to preserve junk
|
||||
|
||||
- **A census cannot decide what to keep.** `port-census.py`-style tools answer "where
|
||||
does this fact live", never "does anyone need it". "14–63 sole-record lines per page"
|
||||
was read as *irreplaceable* when the fact was *obsolete*. Ask usefulness, not custody.
|
||||
- **A census that includes the file under test proves the page is held by itself.**
|
||||
Exclude it, print the corpus size, assert absence; treat `0 unheld` on a long page as
|
||||
a tool bug until proven otherwise.
|
||||
- **"One fact, one owner" is a placement rule, not a preservation rule.** It says where
|
||||
a surviving fact lives; it never says the fact must survive.
|
||||
- **A change diary (`log.md`) is the largest archive in most vaults** (this one: 2,380
|
||||
lines, ~8 % of the vault). Git holds the chronology; a causal law belongs on the page
|
||||
that owns the thing it governs. Retire the diary.
|
||||
|
||||
## Execution that worked (2026-10-19, −13.7k lines)
|
||||
|
||||
1. Write the kill list as a reviewed artifact, one path per line, grouped by *why it is
|
||||
dead* — that list becomes the PR's argument and the trash manifest.
|
||||
2. Destroy whole pages first (`scripts/destroy-vault.py <list>`): move to
|
||||
`.AGENTTRASH/<date>-destruction/`, then delete every reference from survivors, whole
|
||||
line included when the dead link was its only content. Do not compare link targets
|
||||
with `pathlib.Path.stem` — it strips real suffixes (`sd.cpp`).
|
||||
3. Then strip numbers from what remains (`scripts/axe-measurements.py`): delete ledger
|
||||
sections (noun-LEDS the heading, nothing instructional after it), blank any table cell
|
||||
reporting a rate, fold Eras older than the current one into a single row pointing at
|
||||
git. Never touch a shape number or a Laws/Wire/Rollback section.
|
||||
4. Sweep indices (generator must exclude the trash dir, drop rows whose page cell became
|
||||
empty), re-lint, re-check links.
|
||||
5. Rewrite the governing policy in the same PR, or the next agent re-grows the vault:
|
||||
project `AGENTS.md` *Documentation Policy* + the global agent settings.
|
||||
|
||||
## Report honestly, per area
|
||||
|
||||
docs / scripts / operator-doc separately, measured against the merge-base. The tools are
|
||||
a cost that must be named, not hidden inside a headline "net" number — that is what got
|
||||
the previous pass rejected.
|
||||
|
||||
## Verify the repair tools themselves
|
||||
|
||||
One repair pass matched "line ends with a comma" and deleted the trailing comma from 660
|
||||
wrapped prose lines. Restore by matching lines that are byte-identical to `HEAD` except
|
||||
for trailing punctuation (`restore-punctuation.py`), keep the destructive rule out of the
|
||||
tool, and record the incident in its docstring.
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: omp-extension-stale-module-audit
|
||||
description: "Diagnose recurring omp extension handler timeouts/silence when the on-disk fix is already deployed: harness has no extension hot-reload, so running sessions freeze the module at session start (zombie modules)."
|
||||
---
|
||||
|
||||
Use when a fix for an omp extension is merged/deployed yet the SAME errors persist ("handler timed out after 30000ms", silence, wrong behavior) in running sessions.
|
||||
|
||||
**Core fact:** the harness loads extension `.ts` modules at session start and never reloads them (no `/reload` for extensions; bundle `reload` hits are LSP/MCP/browser only). A session older than the fix keeps executing stale code regardless of the file on disk.
|
||||
|
||||
**Procedure:**
|
||||
1. Census the errors from logs, not guesses — timeout lines carry the culprit pids:
|
||||
`grep -h "handler timed out" ~/.omp/logs/omp.<today>*.log | python3 -c 'import sys,json; rows=[json.loads(l) for l in sys.stdin]; rows.sort(key=lambda r:r["timestamp"]); [print(r["timestamp"], r["event"], r["pid"]) for r in rows]'`
|
||||
(`~/.omp/logs/omp.<date>.<pid>.log` — the pid in the filename is the session.)
|
||||
2. Session start times vs deployed file versions:
|
||||
`ps -eo pid,lstart,args | grep '[o]mp'`
|
||||
`git log --format='%h %ad %s' --date=format:'%m-%d %H:%M' -- <extension path>`
|
||||
`git reflog --format='%gd %ad %gs' --date=format:'%m-%d %H:%M' | grep merge` (live-sync pull times = when the file content changed).
|
||||
Any session whose start time precedes the fix's arrival has the stale module.
|
||||
3. Confirm the stale revision actually contains the bad pattern — read what that session loaded, not HEAD:
|
||||
`git show <old-rev>:<path> | grep -n 'await speak\|async (event'`
|
||||
(e.g. an `async agent_end` awaiting a >30 s chain is exactly what the harness's per-handler `Kzc` 30 s race logs; fire-and-forget `void` is fine — detached promises are NOT tracked by the dispatch window.)
|
||||
4. Optional empirical proof when static analysis says "impossible": probe extensions through the real harness:
|
||||
`omp -p --no-extensions -e /tmp/probe.ts "Reply OK"` with a probe that logs handler start/return and `void`s a 40 s detached promise + spawns a long child. Fast exit + no timeout log ⇒ detachment is untracked ⇒ blame stale modules, not the harness.
|
||||
5. Remediation: restart the affected sessions (kill the listed pids or their terminals — the operator session itself may be one of the zombies; say so explicitly). There is no other fix.
|
||||
|
||||
**Gotchas:**
|
||||
- Per-handler attribution in the log is accurate per dispatch; don't blame other extensions before checking the pid's start time.
|
||||
- Endpoints healthy + silence persisting usually means TWO stacked bugs (e.g. stale awaiting module in old sessions AND a mute bug in current code) — diagnose each pid cohort separately.
|
||||
- Extension chain code must use self-owned `AbortSignal.timeout(...)`, never a ctx-scoped signal: harness dispatch signals die when the dispatch window closes.
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: red-verify-without-stash
|
||||
description: "Prove a regression test is red-capable against pre-fix code in a shared worktree where git stash/checkout are policy-blocked, via git-show blob swap with md5-verified restore."
|
||||
---
|
||||
|
||||
# Red-verifying tests without `git stash`
|
||||
|
||||
## When
|
||||
You fixed a file and added tests that should have failed before the fix, but workspace policy blocks `git stash` (and `git checkout -- file`) in shared worktrees (e.g. `~/.omp` shared-workspace policy). Needed to prove red-capture instead of asserting it.
|
||||
|
||||
## Recipe
|
||||
One `bash` call — swap the fixed file for the HEAD (pre-fix) blob, run only the fix-relevant tests, restore, verify byte-identity:
|
||||
|
||||
```bash
|
||||
cd "$WT"
|
||||
md5sum path/to/fixed.file > /tmp/file-hash
|
||||
cp path/to/fixed.file /tmp/fixed.file.bak
|
||||
git show HEAD:path/to/fixed.file > path/to/fixed.file # pre-fix content; new tests now exercise old code
|
||||
bats -f "test name A|test name B" tests/suite.bats # expect: not ok for every fix-relevant test
|
||||
cp /tmp/fixed.file.bak path/to/fixed.file
|
||||
md5sum -c /tmp/file-hash && echo RESTORED
|
||||
```
|
||||
|
||||
## Notes
|
||||
- `git show HEAD:path > path` truncates-and-refills the file in place; safe because you hold the md5 and a backup copy, and the restore check proves the fixed bytes are back.
|
||||
- Run only the fix-relevant tests via the runner's name filter (`bats -f` regex); a full suite wastes time and old tests pass on both versions.
|
||||
- Expect exactly the tests that pin the fix's behavior to fail pre-fix; tests unrelated to the change (pure coverage of old behavior) pass on both versions — don't count them as red evidence.
|
||||
- `bats` pipelines mask exit codes without `pipefail`; judge by the `ok`/`not ok` lines, not the shell status.
|
||||
- For non-test proof of endpoint behavior (live A/B of an HTTP request body), replay the exact body with `curl` against the live endpoint instead of speculating; keep both timings.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: vault-one-fact-one-owner-dedupe
|
||||
description: "\"Collapse per-payload/per-attempt vault pages into one owner page per endpoint without losing a fact: port-before-cut orphan census, doubled-page repair, trash-aware tools, delegated-write verification, index regeneration, and the merge-resolution order.\""
|
||||
description: "\"Collapse per-payload/per-attempt vault pages into one owner page per endpoint without losing a fact: port-before-cut orphan census (corpus must exclude the file under test), doubled-page repair, trash-aware tools, delegated-write verification, honest per-area line accounting, index regeneration, and the merge-resolution order.\""
|
||||
---
|
||||
|
||||
# One fact, one owner: dedupe the vault without losing a fact
|
||||
@@ -37,12 +37,19 @@ file being rewritten. Any line with **no** surviving key is an orphan → port,
|
||||
deliberately and say so. Use `scripts/port-census.py <new-dir> <git-HEAD:path|file>` (numbers
|
||||
with ≥ 4 int digits, decimals, flags, paths, backticked spans, `--`, ALL-CAPS, or ≥ 2 hyphens).
|
||||
|
||||
Two calibration traps:
|
||||
Three calibration traps:
|
||||
- **Prose words are not facts.** A hyphen or trailing period inside a word (`long-standing`,
|
||||
`deployed:`) was counted as a tracked token while real identifiers hid behind it; that noise
|
||||
buried 300 real lines under 979 fake ones. Strip punctuation, require fact shape.
|
||||
- **The corpus decides the question.** Corpus = the new file only → "what did this rewrite
|
||||
drop?" Corpus = whole vault → "is the dropped fact orphaned repo-wide?" Ask one at a time.
|
||||
- **The corpus MUST exclude the file under test, and you must assert it.** A census pointed at
|
||||
the directory that *contains* the page proves the page is held by itself: ten era pages
|
||||
reported `0 sole-record lines`, which reads as "pure duplication, trash it". With the file
|
||||
excluded, the same pages held **14–63 sole-record lines each** — campaign ledgers that exist
|
||||
nowhere else. A tool's own docstring promise ("excluding it") is not a check: print the
|
||||
corpus size, assert the target is absent, and treat `0 unheld` on a long page as a tool bug
|
||||
until proven otherwise. A mechanical census is a scout: its verdict is a lead, not a finding.
|
||||
|
||||
Also grep `AGENTS.md` separately — a fact it carries is not an orphan.
|
||||
|
||||
@@ -52,7 +59,7 @@ Signature: a page whose `wc -l` is ~2× its `HEAD` size, with a **second frontma
|
||||
the body** whose closing `---` is glued onto the end of a body/timestamp line. Cause chain: a
|
||||
frontmatter rewrite that re-reads the file it just wrote (so its own output becomes the body),
|
||||
then a fence-repair pass keyed on `line == "---"` that cannot see a glued fence and inserts a
|
||||
fence mid-page, so the next pass treats the tail as a new document.
|
||||
fence mid-page, so the next page-tail becomes a new document.
|
||||
|
||||
Un-double rule that worked: find the first frontmatter's close (accepting a glued fence), then
|
||||
the first `type:` line after it that has more keys (`title|description|tags|timestamp`) behind
|
||||
@@ -82,9 +89,10 @@ grep -rnoE "\((page-a|page-b|...)\.md\)" --include="*.md" serverAppConfigs-docs
|
||||
|
||||
Both wikilinks and markdown path refs must be repointed (Research `See Also` lists and bench
|
||||
pages are where path refs hide). Then **regenerate** index rows with a script, never by hand.
|
||||
The generator bug to check for: presence tested as a **bare stem substring** — a page whose
|
||||
name prefixes another's (`frank-medium` inside `frank-medium-rocmfpx`) then silently never
|
||||
gets a row. Test the wikilink form `[[<stem>]]`.
|
||||
Generator bugs to check for: presence tested as a **bare stem substring** — a page whose name
|
||||
prefixes another's (`frank-medium` inside `frank-medium-rocmfpx`) then silently never gets a
|
||||
row (test the wikilink form `[[<stem>]]`); and **no dead-row sweep**, so deleting a page leaves
|
||||
an index row that fails the link check — the generator must drop rows for absent pages too.
|
||||
|
||||
## 7. Enforce the law with a seam
|
||||
|
||||
@@ -96,6 +104,12 @@ re-created era page then cannot pass tests. For the length hint, prefer **derive
|
||||
owned by the page that measured it) plus one documented per-page opt-out; never let a size
|
||||
ceiling force a ledger to be split across two owners.
|
||||
|
||||
Splitting an over-long page to satisfy a ceiling is usually line-NEGATIVE: one measured split
|
||||
turned a 700-line page into 488 + 306 across five files (+23 for the folder net of stub
|
||||
deletions), because frontmatter blocks, pointer sections and connective prose are charged per
|
||||
file while the facts move for free. Roll the split back, carry `okf-exempt: length` with the
|
||||
reason, and keep the stub pages deleted.
|
||||
|
||||
## 8. Edit-tool hazard (costs the most time)
|
||||
|
||||
Body rows beginning with `-` or `+` are op markers. The documented `+-` escape **writes a
|
||||
@@ -104,6 +118,10 @@ line untouched and PUT only the indented continuation lines, or convert the note
|
||||
bullet whose body lines start with two/four spaces. If a wrapped `[[Two Word Page]]` shows up
|
||||
as an unresolved link, the target was hard-wrapped across lines — unwrap it.
|
||||
|
||||
A `PUT` that spans a multi-line statement can silently drop neighbouring assignments
|
||||
(auto-repaired boundary echo); after editing a constants block, `grep -n "^[A-Z_]* = "` and
|
||||
run a syntax probe before executing.
|
||||
|
||||
## 9. Delegated writes: verify bytes, never narrative
|
||||
|
||||
Measured in one campaign, all four failure modes live:
|
||||
@@ -146,7 +164,24 @@ matter how concrete they read; and re-read the source bullet before trusting a t
|
||||
- Open the PR through the API with a 600-perm curl config (managed skill
|
||||
`gitea-api-pr-operations`), end the body with the `cwd:` / `session:` footer, then
|
||||
`xdg-open <PR-URL>` the instant it exists. Never merge without Frank's current explicit OK.
|
||||
Push with an explicit refspec (`HEAD:refs/heads/<pr-branch>`) — a worktree's own branch name
|
||||
is not the PR branch, and `git push origin HEAD` opens a stray branch.
|
||||
- Docs-only change ⇒ **no deploy**. Fast-forward the deploy checkout only
|
||||
(`git -C ~/Projects/serverAppConfig merge --ff-only origin/main`).
|
||||
- Say what was NOT done, in the PR body: soft lint tallies left (missing `## Citations`),
|
||||
conflicts left standing, repo config that was never installed on a host.
|
||||
|
||||
## 12. Report line counts per area, never one net
|
||||
|
||||
"Compaction" measured against the merge-base **per area**: docs / `scripts/` / `AGENTS.md`.
|
||||
A single headline number hides that tooling and prose move in opposite directions — one
|
||||
campaign reported "−1,849 vault lines" while the vault was flat and the growth was the two
|
||||
enforcement scripts that made the law mechanical. Expect a mature one-owner vault to land
|
||||
**docs flat**: the reductions available are deletions of *restatement* (duplicated pages,
|
||||
transient deploy chatter in `log.md`, `AGENTS.md` bullets whose numbers an endpoint page owns)
|
||||
and they are roughly cancelled by the cost of the citations the verification pass adds. When
|
||||
asked to shrink further, show the menu — drop the tools, drop the citations, or accept content
|
||||
loss — instead of inventing cuts. `log.md` compaction rule that survived census: drop a line
|
||||
only when it matches a transient shape (`/health`, `deployed`, `restart`, `systemctl start`)
|
||||
**and** every fact token in it is held by an owner page; a token-held line can still be the
|
||||
only record of *when* an incident happened.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792398289746
|
||||
"lastConsolidatedAt": 1792432172049
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792430072641,
|
||||
"lastConsolidatedAt": 1792433858713,
|
||||
"lastResult": {
|
||||
"at": 1792429115686,
|
||||
"at": 1792433135862,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792430229908,
|
||||
"lastConsolidatedAt": 1792433709913,
|
||||
"lastResult": {
|
||||
"at": 1792402864677,
|
||||
"at": 1792433353188,
|
||||
"sessions": 1,
|
||||
"deltas": 8,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792430069015,
|
||||
"lastConsolidatedAt": 1792433789051,
|
||||
"lastResult": {
|
||||
"at": 1792428814873,
|
||||
"at": 1792432178813,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"deltas": 2,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,13 +275,13 @@ transition = [ "fade" ]
|
||||
interval_seconds = 1200
|
||||
|
||||
[wallpaper.default]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_g7r3vd.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
|
||||
[wallpaper.last]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_g7r3vd.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
|
||||
[wallpaper.monitors.DP-1]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_g7r3vd.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
|
||||
[wallpaper.monitors.DP-2]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_oxex69.jpg"
|
||||
@@ -290,7 +290,7 @@ transition = [ "fade" ]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9e2w3.jpg"
|
||||
|
||||
[wallpaper.monitors.eDP-1]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_g7r3vd.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
|
||||
[weather]
|
||||
unit = "imperial"
|
||||
|
||||
Reference in New Issue
Block a user