Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd6a07bb58 | ||
|
|
1921d76319 | ||
|
|
d302151a8d | ||
|
|
5b6f4381b0 | ||
|
|
cae49fcd09 | ||
|
|
ee292ffd10 | ||
|
|
dd4713fa81 | ||
|
|
a8727ddf0b | ||
|
|
2faeab665a | ||
|
|
62b3b92e69 | ||
|
|
ec6a707fe4 | ||
|
|
96553979fb | ||
|
|
ac5b377750 | ||
|
|
8f5a229cc6 | ||
|
|
ea514c8fd2 | ||
|
|
bc60fa33be | ||
|
|
e4ecc93f29 | ||
|
|
d055eb1e7f | ||
|
|
70346f3d57 | ||
|
|
1251cfbd40 | ||
|
|
e67bbd0de0 | ||
|
|
986081bf1d | ||
|
|
a9b3c495da | ||
|
|
c99eb8e11b | ||
|
|
cd20d6ddfd | ||
|
|
82dd0c7d09 | ||
|
|
99b9a6a17c | ||
|
|
39385636be | ||
|
|
d99c1c3c4f | ||
|
|
651924a4bc | ||
|
|
e86e60af39 | ||
|
|
01d9d3fbd5 | ||
|
|
570b5509d0 |
@@ -100,15 +100,18 @@ secret in every agent's context window on every machine that pulls this repo.
|
||||
|
||||
| box | role | GPU | notes |
|
||||
|-----|------|-----|-------|
|
||||
| Dev workstation | client box, never runs inference | laptop iGPU + dGPU (non-unified) | mainline llama.cpp at `~/GitPackages/llama.cpp/build/bin/`; this repo lives here at `~/.omp` |
|
||||
| Dev workstation (`blankpad`) | client box, never runs inference | Lenovo laptop, AMD Ryzen 5 PRO 5650U / Cezanne APU (**unified memory**, s2idle sleep only, no dGPU) | this repo lives here at `~/.omp`; the earlier "iGPU + dGPU / `~/GitPackages/llama.cpp`" description belonged to the sold `dankware` box |
|
||||
| Dankclaw | bench target, secondary models + service stack | Strix Halo APU (**unified memory**) + RTX 3090 (moved over from Dankserver 2026-09) | prod services `frank-dragoon` (halogen-flash-server, :7770, iGPU) and `frank-zealot` (llama.cpp PrismML fork, :7771, 3090); runbooks in the serverAppConfigs vault (`~/Projects/serverAppConfig/serverAppConfigs-docs/LLM/`); ssh: `ssh dankclaw` |
|
||||
| Dankserver | main-model box | 2× Radeon AI PRO R9700 — non-unified (was RTX 3090 until 2026-09) | runs `frank-archon` (radiance, TP=2, :7770) — **this repo's operator session runs on it**; ssh: `ssh dankserver` |
|
||||
|
||||
## Environment gotchas
|
||||
|
||||
- Gitea API needs a token: `GITEA_TOKEN` env (gitignored `.env`). No `tea` CLI
|
||||
installed anywhere. Remote URLs embed the token locally in `.git/config` — that
|
||||
file is never pushed; it is not a substitute for the secret gate.
|
||||
installed anywhere. Remote URLs carry NO embedded token (2026-10-09
|
||||
credential-store cutover) — git and the API both read
|
||||
`~/.config/secrets/gitea` (`store --file`, URL-line format; see
|
||||
`omp-docs/tools/gitea/client-access.md`). That file is never pushed; it is
|
||||
not a substitute for the secret gate.
|
||||
- Passwordless sudo (`sudo -n`) works on Dankclaw and Dankserver for systemctl
|
||||
verbs only; user units need no sudo at all.
|
||||
- SSH into both servers is BatchMode-capable from here:
|
||||
|
||||
@@ -158,6 +158,7 @@ task:
|
||||
security-reviewer: llamacpp (dankclaw)/frank-dragoon
|
||||
sonic: llamacpp (dankclaw-3090)/frank-zealot
|
||||
task: llamacpp (dankserver)/frank-archon
|
||||
seance: llamacpp (dankclaw-3090)/frank-zealot
|
||||
eager: default
|
||||
enableLsp: true
|
||||
maxRuntimeMs: 1800000
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: dankvoice-bats-serialization
|
||||
description: "Run dankvoice bats suites without hangs: serialize builds on shared dist/, DV_HOLD is seconds, stub needs sleep&wait trap before hold, timing tests assert CALLS/at not tail PLAYS."
|
||||
---
|
||||
|
||||
# Dankvoice bats: serialization and hang-proofing
|
||||
|
||||
## Serialize builds on the shared artifact
|
||||
`tests/behavior.bats` setup runs `bun run build` into the repo's shared `dist/index.js`
|
||||
before EVERY test (`DV_EXT="$REPO/dist/index.js"`). Any second concurrent bats run,
|
||||
`bun run build`, or `bun run typecheck` racing the same repo contends on that file and
|
||||
can stall single tests past 60 s. NEVER run two bats processes (or bats + build) against
|
||||
`~/Projects/dankvoice` at the same time — including harness background jobs. If a suite
|
||||
gets backgrounded, kill it before launching any other repo command; re-run serially.
|
||||
|
||||
## The stub player's units and traps
|
||||
- `DV_HOLD` is in **seconds** (`sleep "${DV_HOLD:-0.1}"`), not ms. `DV_HOLD=1500`
|
||||
means a 25-minute "hung" test. Use `DV_HOLD=2` for multi-second holds.
|
||||
- The stub must sleep as `sleep "${DV_HOLD:-0.1}" &` + `wait $!`, with
|
||||
`trap 'printf "KILLED\n" >> "$DV_STUB_LOG"; exit 143' TERM` installed **before** the
|
||||
sleep: a foreground `sleep` defers the trap until the sleep finishes, so SIGTERM-kill
|
||||
tests (shutdown/interrupt pins) stay red and every kill test eats the full hold.
|
||||
- Keep the `cp *.wav "$DV_COPY"` loop when editing the stub — the byte-equality test
|
||||
depends on it.
|
||||
|
||||
## Timing-sensitive assertions
|
||||
The driver prints `PLAYS` from the stub log at scenario end (~800 ms settle), so with a
|
||||
long `DV_HOLD` in-flight playback is UNDERCOUNTED — assert `CALLS`/arrival timestamps,
|
||||
not tail `PLAYS`. The fixture stamps every request with `at=` (ms since driver start,
|
||||
comparable between CALL lines); prefetch overlap = `t2 - t1 < 1500` with `DV_HOLD=2`
|
||||
(sequential chain cannot answer inside 2000 ms).
|
||||
|
||||
## Diagnosing a hung bats test (deterministic recipe)
|
||||
1. `timeout 45 bats -f "<name>" tests/behavior.bats; echo rc=$?` — rc=124 confirms hang.
|
||||
2. Launch the same test as a background job, then probe live:
|
||||
`pgrep -af "driver.ts|bats"` and `ps afx | grep -E "sleep|stub"` — a `sleep <N>` child
|
||||
with N seconds in the stub log names the culprit (usually DV_HOLD misuse).
|
||||
3. Detached `(cmd &)` inside a temp shell is KILLED when the shell exits — use the
|
||||
harness background jobs for anything you must probe.
|
||||
4. Direct driver repro: extract the heredoc with
|
||||
`sed -n '/cat > "$WORK\/driver.ts" <<.TS./,/^TS$/p' tests/behavior.bats | sed '1d;$d' > $W/driver.ts`,
|
||||
build a fresh ext, then run `bun $W/driver.ts <scenario>` with the env the setup block
|
||||
exports. Caveat: hand-made fixture env can yield different segment counts than bats —
|
||||
trust in-bats numbers for assertions.
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
name: docs-dedupe-verify-campaign
|
||||
description: "Run an exhaustive docs dedupe + fact-verification campaign in dank/command-center: scout cluster ledgers, override scouts with evidence, gate every commit, and sweep scaffolding before PR."
|
||||
---
|
||||
|
||||
# Exhaustive docs dedupe + verification campaign (dank/command-center)
|
||||
|
||||
## Frame
|
||||
- Read `omp-docs/references/okf-spec.md` + root `omp-docs/index.md` first; inventory with `find omp-docs -name '*.md' | wc -l`.
|
||||
- Run `scripts/kb-lint.sh omp-docs` baseline; index-coverage gate is `scripts/kb-coverage.py omp-docs` (each dir's `index.md` must link every sibling file/subdir).
|
||||
- Branch off fresh `origin/main` in a NEW worktree (`git -C ~/.omp worktree add ~/.omp/wt/<name> -b docs/<issue>-slug origin/main`) — workspace policy blocks `git checkout -b` in session worktrees.
|
||||
- Open the Gitea issue first (multi-moving-parts law); branch name `docs/<issue#>-<slug>`.
|
||||
|
||||
## Scout fleet (overlap detection)
|
||||
- One `task` call, `tasks[]` batch, agent `scout`, read-only; one cluster per task (skills trees, llama trees, pi vs packages, niri, sleep/power, core, gitea, gitea+cross-cutting sweep). Cap 2 concurrent; queue rest.
|
||||
- Ledger format per cluster → `local://dedupe/<cluster>.md`: inventory table (file | lines | verdict KEEP|MERGE|DELETE|VENDOR|UPDATE), overlaps, facts-to-keep, inbound links, staleness.
|
||||
- **Scouts lie.** Verified misses in the 2026-10-19 campaign: fabricated ledger entries ("peer-reviewed BrowseComp" claim that exists in no file), a DELETE verdict for a generated artifact that is checked in by design AND under test (`tools/niri/keybindings.md`, see `scripts/gen-keybinds.sh` + `tests/gen-keybinds.bats`), and a KEEP for a leftover the scout misread its own changelog about. NEVER apply a scout verdict without re-checking the file, the tests, and the changelog yourself.
|
||||
|
||||
## Fact verification
|
||||
- Fleet facts: read-only probes over `ssh -o BatchMode=yes dankclaw|dankserver` (podman ps/inspect/top, stat, /etc/os-release, curl localhost APIs, `podman exec <c> <tool> --version`). Live state beats docs even when docs claim recent verification — the 2026-10-18 "audit" still drifted (zealot 27B→9B, build 10754→10777, container census 14→32).
|
||||
- External claims: web_search/web read yourself (no subagents per Frank's rule). Kill fabrications outright (invented distro `FreeToken`, nonexistent `ornith-llama-cpp-setup` tree, unattributable "44.5% peer-reviewed CUA") — delete/drop with an explicit note, never keep "plausible" numbers.
|
||||
- Policy drift (live ≠ tuned docs): flag in the doc + PR body as an operator decision; NEVER silently re-apply policy.
|
||||
|
||||
## Log compaction (log.md)
|
||||
- Entry law: dated entry = what changed + durable lesson + concept-page pointer; narratives recoverable via `git log --follow`. Record the law at the top of the log. Tag historical-era entries.
|
||||
|
||||
## Gates + landing
|
||||
- Gate every commit: `bash scripts/kb-lint.sh omp-docs && python3 scripts/kb-coverage.py omp-docs && bats tests/`. Pre-commit hook prints `error: command not found: caddy` on Caddyfile-touching commits — warning only, commit still lands.
|
||||
- Before opening the PR: `git diff --stat origin/main..HEAD | grep -i 'tmp\|scratch\|\.bak'` — scaffolding merged under a `.tmp-` name in the 2026-10-19 campaign and needed a follow-up PR to promote.
|
||||
- PR via API (skill `gitea-api-pr-operations` for token-extraction + merge payload); `xdg-open` the PR the moment it opens; comment the campaign ledger on the issue.
|
||||
- After Frank's merge OK: propagate deployment `git -C ~/.omp fetch && git merge --ff-only origin/main`; reap campaign worktree (`git worktree remove --force`) + delete branch local/remote; close issue with landing comment.
|
||||
|
||||
## Line-edit op syntax trap (bit three times)
|
||||
- Valid ops: `PUT N.=M:` (body `+text` lines), `CUT N.=M` / `CUT N.=M @reg`, `PUT <N @reg`, `PUT >N:` / `PUT <N:`. There is NO `PUT N+=:` form — it lands in the file as a literal garbage line and shifts the insert to the wrong position. For gap-insert use a lone `PUT >N:` or `PUT <N:` per call; pre-compute line numbers against the file map (ops reference original lines within one call, but a failed op poisons positions).
|
||||
- Recovery recipe when a literal op line lands: read exact bounds, `CUT N.=N` (junk), `CUT A.=B @block` (misplaced section), then `PUT <M @block` at the true anchor, re-read tail, add spacing blank if a `---` now abuts a list line.
|
||||
@@ -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,85 @@
|
||||
---
|
||||
name: docs-refresh-scout-summaries
|
||||
description: "Refresh a stale documentation cluster without delegating the writing: scout subagents produce per-line verdict tables (holder verified by comma-insensitive grep), the parent makes every edit, and a port-before-cut census proves nothing was lost. Use for dedupe-our-docs, fix-the-stale-runbooks, pointers-instead-of-copied-numbers jobs."
|
||||
---
|
||||
|
||||
# Refresh stale docs with scout summaries, parent-side writes
|
||||
|
||||
Use when a cluster of documentation pages is stale and/or restates facts another page owns, and
|
||||
the fix touches many files. **Scouts read and classify; the parent writes.** Sibling skill
|
||||
`vault-one-fact-one-owner-dedupe` covers collapsing era pages into owner pages - its section 3
|
||||
(orphan census), section 7 (edit-tool hazard) and section 9 (verify/PR) apply unchanged.
|
||||
|
||||
## Why not writer subagents (measured cost)
|
||||
|
||||
Writer agents produce plausible output and cannot be trusted on the one claim that matters - the
|
||||
owner page already holds this fact. In one run they asserted every cut was grep-confirmed while
|
||||
FOUR cuts left pointers to pages that did not contain the fact (118->238 GiB, 16,095 tokens,
|
||||
0.739/0.554/0.427/0.340, PR #23897). Each became a broken promise the next reader trusts.
|
||||
Classification is the only part that parallelizes; writing is where taste (ownership, era
|
||||
naming, what counts as a law) lives. So fan out read-only scouts and keep the pen.
|
||||
|
||||
If writer agents were already spawned and are no longer wanted: `write agent://all` to stop
|
||||
them, then `git status` the target tree - `proc://` does not list agent jobs, and a finished
|
||||
worker may already have edited files.
|
||||
|
||||
## Pipeline
|
||||
|
||||
1. **Cluster** targets into groups of 3-4 pages sharing subject matter (one cluster per scout).
|
||||
Know the owner map first (endpoint/service/host pages, plus the repo documentation law).
|
||||
2. **Wave of 2 scouts** (harness cap is `task.maxConcurrency`, usually 2). Scout contract:
|
||||
|
||||
> READ-ONLY, no writes of any kind. Per file, one table row per candidate fact:
|
||||
> `| lines | verbatim figure + 6 words | holder elsewhere (file:line) or none | VERDICT |`
|
||||
> Verdicts: `CUT -> [[Owner]]` (holder verified), `KEEP(owned here)` (no holder, this page is
|
||||
> the record), `PORT(parent)` (rightful owner lacks it - name page and section), `STALE`
|
||||
> (contradicted by current state; quote the contradicting line), `INDEX` (locator page).
|
||||
> Verify every holder claim with a COMMA-INSENSITIVE grep: a holder writing 1,350,182
|
||||
> satisfies a page writing 1350182 and vice versa; 16,095 does NOT satisfy a check for 16095
|
||||
> unless commas are stripped. Never name a holder line you have not read.
|
||||
> End with a per-file tally: kept / cut / port / stale.
|
||||
|
||||
Put the law, the owner map and the verification rule in the batch-level `context`, never per
|
||||
task.
|
||||
3. **Write while the next wave runs**: edit cluster N from wave N, launch wave N+1 in the same
|
||||
turn. Never launch a wave you have nothing to write.
|
||||
4. **Verify each CUT yourself** before cutting - read the holder line. A scout row is a
|
||||
hypothesis, not evidence.
|
||||
5. **PORT items are your edits**: add the fact to the owner page section (Eras row / Laws / spec
|
||||
table), then cut it from the technique page in the same commit.
|
||||
6. **STALE items: check live state**, not another document - `ssh <host> systemctl is-active
|
||||
<svc>`, the endpoint `/health`, the env file. Then rewrite with a date, or drop transient
|
||||
live state an owner page already records.
|
||||
|
||||
## The ownership test that stops wasted ports
|
||||
|
||||
Two pages carrying one figure is the defect - a figure with exactly one holder is fine wherever
|
||||
it lives. A technique page that is the sole record of a campaign owns that campaign's arm
|
||||
tables; do not port such ledgers into an endpoint Eras table. Write the clause into the repo
|
||||
documentation law so the next pass stops porting single-owner facts. Corollary: a worked example
|
||||
may repeat a live number if it declares itself dated and names the owner (a snapshot, not fleet
|
||||
state - recompute from the live files).
|
||||
|
||||
## Census after each cluster (catches your own slips too)
|
||||
|
||||
Run the sibling skill's section 3 census over `git diff -U0` for the cluster (deleted lines x
|
||||
distinctive numeric keys vs the whole vault **plus AGENTS.md**), comma-insensitively; drive the
|
||||
count to zero or list each accepted loss in the commit message.
|
||||
|
||||
```python
|
||||
flat = corpus.replace(',', '')
|
||||
pres = lambda n: n in corpus or n.replace(',', '') in flat
|
||||
toks = lambda l: [n for n in re.findall(r'\d[\d,]*(?:\.\d+)?', l)
|
||||
if len(n.replace(',', '').split('.')[0]) >= 4
|
||||
or (len(n.split('.')[-1]) >= 2 and len(n.replace(',', '')) >= 5)]
|
||||
orphan = [l for l in deleted if toks(l) and not any(pres(n) for n in toks(l))]
|
||||
```
|
||||
|
||||
## Verify and land
|
||||
|
||||
- Vault link seam must print `0 unresolved links`; hard-wrapped `[[Two Word Page]]` links split
|
||||
across lines are the usual cause - unwrap them.
|
||||
- Full suite once at the end, not per cluster; a docs seam running while scouts are live may
|
||||
read half-written files, so re-run after the last edit.
|
||||
- Commit per cluster (docs-only means **no deploy**); push, open the PR through the API with a
|
||||
600-perm curl config, `xdg-open` the PR URL immediately.
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
name: fleet-service-runtime-census
|
||||
description: "Answer \"what is service running right now?\" for a dank-fleet service: live endpoint probe plus host units, image ids, live-vs-repo env, and drop-ins."
|
||||
---
|
||||
|
||||
# Fleet service runtime census
|
||||
|
||||
Answer the question "what is `<service>` running currently?" with evidence, not from docs. Docs say what *should* run; the host says what *does*. Run all five probes, then report one table.
|
||||
|
||||
## 1. Probe the published port (works from any LAN box, no ssh)
|
||||
|
||||
```bash
|
||||
curl -s -m 10 http://<host-ip>:<port>/health; echo
|
||||
curl -s -m 10 http://<host-ip>:<port>/v1/audio/voices # per-endpoint extras: /v1/models, /metrics
|
||||
```
|
||||
|
||||
The extra route matters more than `/health` for identity claims:
|
||||
- llama.cpp and radiance **echo the requested model name** — a 200 proves nothing; read `/v1/models`.
|
||||
- halogen 404s `/completion`, `/ping`, `/props`, `/tokenize`.
|
||||
- The frank-tts façade answers `/health` **without dialing the engine**, so "façade healthy, engine down" is a real state; the voice list in that same response is the honest census.
|
||||
|
||||
## 2. Units + containers on the host (ssh as the deploy user, no sudo)
|
||||
|
||||
```bash
|
||||
ssh <host> 'systemctl --user status <svc>.service <engine>.service --no-pager \
|
||||
| grep -E "^(●| Active| Loaded)"; \
|
||||
podman images --format "{{.Repository}}:{{.Tag}} {{.ID}} {{.Created}}"; \
|
||||
podman ps -a --format "{{.Names}}\t{{.Status}}\t{{.Image}}"'
|
||||
```
|
||||
|
||||
- `active (running) since …` + `Up N hours (healthy)` is the answer; `activating (auto-restart)` with a ~50 ms exit is a **preflight refusal**, not an engine fault.
|
||||
- **NEVER prefix these podman calls with `sudo`.** Containers live in the deploy user's rootless storage; `sudo podman inspect frank-tts-engine` returns `no such object` while the plain form succeeds. Treating that as "container missing" is a false finding.
|
||||
|
||||
## 3. Drop-ins — the override that no health gate sees
|
||||
|
||||
```bash
|
||||
ssh <host> 'systemctl --user show <svc>.service -p DropInPaths; \
|
||||
systemctl --user show <engine>.service -p DropInPaths'
|
||||
```
|
||||
|
||||
`DropInPaths=` must be empty. A leftover bench drop-in (`Environment=FRANK_<SVC>_ENV_FILE=/tmp/<arm>.env`) makes the next deploy boot a different model at a different shape while `/health` still answers 200 and the e2e gate passes.
|
||||
|
||||
## 4. Live env vs repo env — the only truth test
|
||||
|
||||
```bash
|
||||
# repo side (local checkout)
|
||||
grep -vE '^\s*#|^\s*$' scripts/<svc>.env
|
||||
# host side
|
||||
ssh <host> 'sudo cat /home/dank/serverAppConfigs/scripts/<svc>.env' | grep -vE '^\s*#|^\s*$'
|
||||
```
|
||||
|
||||
Diff them. Per repo law the env file beside the serve script **is** the authority; a doc page that disagrees with it is the bug, and host-side drift means an uncommitted edit. Also check `git log --oneline -3 -- scripts/<svc>.env` to confirm the host isn't ahead of git.
|
||||
|
||||
## 5. Report
|
||||
|
||||
Table of: unit state + since, image repo:tag@short-ID + age, backend/alias actually served (from step 1, not from the name), drop-ins, and whether live env == repo env. State explicitly when a fact came from docs rather than from a probe.
|
||||
|
||||
## Traps that produce false findings
|
||||
|
||||
- Digest-pinned images: the local image ID's *creation date* answers "is this stale" better than the tag; `latest` + `Pull=never` is a locally built image, not a registry pull.
|
||||
- `ssh` user context changes what podman sees (root vs rootless) — see step 2.
|
||||
- Two ports on one host are two providers in `models.yml`; a port mismatch is a rename or drift, not a config typo.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: gitea-api-pr-operations
|
||||
description: "Open, list, merge, and diagnose issues/PRs on the Dankclaw Gitea API (192.168.0.143:3000, repo dank/command-center) with the token stored in ~/.config/secrets/gitea — incl. the required merge payload and where review comments actually live on 1.27.3."
|
||||
description: "\"Open, list, merge, and diagnose issues/PRs on the Dankclaw Gitea API (192.168.0.143:3000, repo dank/command-center) with the token stored in ~/.config/secrets/gitea — incl. the required merge payload, where review comments actually live on 1.27.3, and how to recover the session id for the mandatory body footer.\""
|
||||
---
|
||||
|
||||
# Gitea API PR operations (Dankclaw `dank/command-center`)
|
||||
@@ -25,11 +25,13 @@ description: "Open, list, merge, and diagnose issues/PRs on the Dankclaw Gitea A
|
||||
fold footers into the --arg string instead.)
|
||||
- **List open PRs**: `GET /pulls?state=open` → `jq -r '.[] | "#\(.number) \(.head.ref) \(.title)"'`.
|
||||
- **Read PR**: `GET /pulls/<n>` (no token; public repo) → `jq -c '{state,merged,mergeable,head:.head.ref}'`.
|
||||
`mergeable:false` is often Gitea's *not-yet-checked* state, not a conflict — prove a real
|
||||
conflict locally with `git merge-tree --write-tree HEAD origin/main` before believing it.
|
||||
- **MERGE**: `POST /pulls/<n>/merge` with `-H 'Content-Type: application/json'`
|
||||
and body **`{"Do":"merge"}`** — this build REQUIRES the `Do` field:
|
||||
`{}` or `{"DoNotMerge":false,...}` → 422; `{"Do":"merge"}` → 200 +
|
||||
`{"state":"closed","merged":true,"merge_commit_sha":"..."}`. Verify with a
|
||||
plain GET /pulls/<n> afterwards (merge endpoint's own stdout may not parse).
|
||||
`{"state":"closed","merged":true,"merge_commit_sha":"..."}`. Verify with a plain
|
||||
GET /pulls/<n> afterwards (merge endpoint's own stdout may not parse).
|
||||
Merge is the `--no-ff` merge commit on main; then `git -C ~/.omp fetch && git
|
||||
merge --ff-only origin/main` propagates the live deployment.
|
||||
- **Issues**: same shape at `/issues` (`POST {title, body}`), `/issues/<n>/comments`
|
||||
@@ -51,6 +53,13 @@ description: "Open, list, merge, and diagnose issues/PRs on the Dankclaw Gitea A
|
||||
Every issue/PR body ends with `---` line then `cwd: <wd> · session: <id>`. Keep
|
||||
it inside the --arg string (not a `---` CLI arg).
|
||||
|
||||
`cwd` is THIS session's own working directory (note a build worktree separately if they
|
||||
differ). When `/status` is unreachable (headless/subagent context), recover the session id
|
||||
from the session store instead of inventing one:
|
||||
`ls -t ~/.omp/agent/sessions/<cwd-slug>/ | head -2` → `<timestamp>_<uuid>` (the same uuid as
|
||||
`<uuid>.jsonl`); the slug is the cwd with `/` replaced by `-`. Subagent files live under the
|
||||
**parent** session's directory, so the newest entry there is the parent id.
|
||||
|
||||
## Gotchas
|
||||
- Content-Type: POSTs with `-d @file.json` MUST carry
|
||||
`-H 'Content-Type: application/json'` on the command line. `-H` entries put in
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: gitea-merge-form-encoded
|
||||
description: "Use when a Gitea API merge on Dankclaw (192.168.0.143:3000) returns HTTP 422 \"[Do]: Required\" — the merge endpoint needs form-encoded fields, not the JSON body that PR creation accepts."
|
||||
---
|
||||
|
||||
Gitea on Dankclaw (192.168.0.143:3000, `dank/serverAppConfigs`) — merge quirk, measured 2026-10-19.
|
||||
|
||||
Creating a PR accepts a JSON body. **Merging does not**: `POST /api/v1/repos/{owner}/{repo}/pulls/{n}/merge` with a JSON body (`{"merge_style":"no-ff", "Do-Not-Reply-From":…, "Reply-To":…}`) or with those values as request headers returns `422 {"message":"[Do]: Required"}` — four variants of that all fail identically, so do not "fix" it by changing the style name or moving the headers around.
|
||||
|
||||
Working call (form-encoded):
|
||||
|
||||
```bash
|
||||
tok=$(sed -n 's|http://[^:]*:\([^@]*\)@.*|\1|p' ~/.config/secrets/gitea | head -1) # git credential.helper store file
|
||||
curl -sS -X POST -K <(printf 'header = "Authorization: token %s"\n' "$tok") \
|
||||
--data-urlencode 'do=merge' \
|
||||
--data-urlencode 'merge_style=no-ff' \
|
||||
--data-urlencode 'Do-Not-Reply-From=chief@franksdank.cloud' \
|
||||
--data-urlencode 'Reply-To=chief@franksdank.cloud' \
|
||||
http://192.168.0.143:3000/api/v1/repos/dank/serverAppConfigs/pulls/<N>/merge
|
||||
# 200 with an empty body == merged
|
||||
```
|
||||
|
||||
- `do=merge` is the field the 422 was demanding (the web-UI form field name, not an API doc field).
|
||||
- `merge_style` values are the dashed names: `no-ff`, `merge`, `rebase`, `squash`.
|
||||
- Keep the token out of argv: `-K <(printf …)` feeds the `Authorization` header through stdin (a `-H "Authorization: token …"` lands in `/proc/<pid>/cmdline`, world-readable — the 2026-09-16 HF-token leak class).
|
||||
- Verify by fast-forwarding a checkout (`git fetch && git merge --ff-only origin/main`) rather than re-reading the PR.
|
||||
- Fleet law still applies: never merge without an explicit current OK from Frank, and open the PR URL in his browser (`xdg-open`) the moment it exists.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: omp-bundle-implementation-port
|
||||
description: "Extract and port a working implementation from omp's minified dist/cli.js bundle (copy-not-invent requests); anchors, python slicing, regex-constant sweep, trace-driven test prediction."
|
||||
---
|
||||
|
||||
# Porting built-in omp behavior out of the minified bundle
|
||||
|
||||
Use when Frank says "copy the omp implementation / work off known-working code" — i.e. port a built-in feature (vocalizer segmentation, retry logic, formatting rules) into our own file instead of hand-rolling a heuristic. For merely *auditing behavior claims*, use `omp-bundle-claim-audit`; this skill is extraction-for-porting.
|
||||
|
||||
Bundle: `~/.bun/install/global/node_modules/@oh-my-pi/pi-coding-agent/dist/cli.js` (minified; single-letter names, private `#x` fields survive).
|
||||
|
||||
## Extraction recipe
|
||||
|
||||
1. **Find the setting/entry strings first.** `grep -o 'ce({id:"<area>[^"]*"[^}]\{0,200\}' cli.js` — setting descriptions state semantics verbatim (e.g. `speech.enhanced` = "Rewrite assistant output into natural spoken prose with the tiny/smol model"). Descriptions are quotable ground truth.
|
||||
2. **Anchor to code with a distinctive token**, not guesses: a method name (`pushDelta`), a state init, or a string. Then slice generously with python (bash heredoc), NOT grep -o which truncates:
|
||||
```python
|
||||
src = open('cli.js').read()
|
||||
i = src.index('pushDelta'); print(src[i-1500:i+3000])
|
||||
```
|
||||
3. **Follow the constructor**: pipeline classes instantiate collaborators there (`this.#t ??= new fHe` → `fHe` is the real worker; `#g()` returned `{speakable:new fHe, pending:[]…}`). Dump `class fHe{` +4000 chars.
|
||||
4. **Regex/helper sweep**: minified code declares shared constants in a trailing `var a,b,c,…` list and initializes them elsewhere (`Xyr=`, `Pwc=function`). Loop the names with `re.search(rf'{name}=', src)` and print ~400 chars each — the actual boundary/cleanup rules live in these one-liners.
|
||||
5. Write slices to `/tmp/*.txt` and `read` them; don't eyeball megabyte greps.
|
||||
|
||||
## Port rules
|
||||
|
||||
- Rename fields/methods to readable names but keep logic **1:1** — the value is behavioral fidelity (Frank's "known-working set of code").
|
||||
- Private `#x` fields port cleanly: TS classes in Bun extensions support `#`.
|
||||
- Global-regex `.lastIndex=0` before each scan loop — minified code relies on it; keep it.
|
||||
|
||||
## Verification shortcut
|
||||
|
||||
Before running tests, **hand-trace** each test input through the ported rules (boundary indices, state transitions) and predict exact segment counts/strings; then run — predicted-vs-actual mismatch localizes port errors faster than test output alone. Worked example (2026-10-19, dankvoice PR #26): traced `"First stop here. Second one goes!!! Really? Third ... done"` → predicted 3 segments incl. `"Third ... done"` merged via flush (10-char boundary < 24-char started-min) → bats green first run.
|
||||
|
||||
## Known anchors (2026-10-19 bundle)
|
||||
|
||||
- Speak-aloud vocalizer pipeline: class `I6o` (gating on `speech.enabled`, suspend counter, enhancer, `#g()` per-message state).
|
||||
- Utterance segmenter: class `fHe` + helpers `Pwc` (line-head classify), `Iwc`/`_wc`/`b6o`/`w6o` (boundary search), `Cwc`+`y6o` (cleanup: links→label, URL→host, path→basename). Regex consts: `Xyr` sentence-end runs, `pHe` weak breaks, `mwc` abbreviations, `hwc` undecided line-heads, `g6o` horizontal rules.
|
||||
- Port already living in `agent/extensions/dankvoice.ts` (`SpeechSegmenter`) — when the bundle updates, re-extract `fHe` and diff against it before assuming our copy still matches.
|
||||
@@ -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,47 @@
|
||||
---
|
||||
name: plugin-git-install-committed-artifact
|
||||
description: "Use when shipping an omp/pi plugin for omp plugin install git: — the installer clone fails validation (missing build artifact) or silently reuses a stale bun git-mirror cache; recipes for committing dist + drift pins + cache purge."
|
||||
---
|
||||
|
||||
# Plugin install from git: committed artifact + fresh mirror
|
||||
|
||||
`omp plugin install git:<url>` (and `pi install git:`) **clone the repo and validate the manifest's declared extension entry WITHOUT running a build step**. Two failure classes seen live (dank/dankvoice, 2026-10-19):
|
||||
|
||||
## 1. Declared entry missing from the clone
|
||||
|
||||
Symptom: `Plugin <name> extension validation failed: ./dist/index.js: declared extension entry not found on disk`.
|
||||
|
||||
Cause: build output (`dist/`) is gitignored; the manifest points at it; the clone has only `src/`.
|
||||
|
||||
Fix — ship the artifact:
|
||||
- Remove `dist/` from `.gitignore`, `bun run build`, commit `dist/`.
|
||||
- Prove build determinism first: build twice, `cmp` the outputs (bun esm builds are byte-reproducible without sourcemaps).
|
||||
- Pin the contract in a small bats suite so it can't rot:
|
||||
1. the manifest's declared entry is tracked in git (`git ls-files -- "${entry#./}"` non-empty — this is the installer's exact contract, not a config assertion);
|
||||
2. committed bytes equal a fresh build (`bun run build` then `git diff --name-only -- dist` is empty → red on drift).
|
||||
|
||||
## 2. Stale bun git-mirror cache
|
||||
|
||||
Symptom: fix pushed, retry **still** fails identically, and the retry is suspiciously fast (seconds).
|
||||
|
||||
Cause: bun keeps bare mirrors in `~/.bun/install/cache/<hash>.git` and may reuse them at an old commit — even after the fix is pushed and the default branch is correct.
|
||||
|
||||
Diagnose + fix:
|
||||
```bash
|
||||
find ~/.bun/install/cache -maxdepth 2 -iname "*<repo>*"
|
||||
git --git-dir ~/.bun/install/cache/<hash>.git log --oneline -3 --all # stale HEAD?
|
||||
rm -rf ~/.bun/install/cache/<hash>.git # it is a cache; safe
|
||||
```
|
||||
Prove the fetch path independently first (also validates credentials for private Gitea repos):
|
||||
```bash
|
||||
GIT_TERMINAL_PROMPT=0 git clone -q <url> /tmp/x && git -C /tmp/x log --oneline -1 && ls /tmp/x/dist
|
||||
```
|
||||
|
||||
## Order of investigation (don't skip)
|
||||
1. Gitea default branch correct? (`GET /api/v1/repos/<o>/<r>` with token — private repos 404/None unauthenticated.)
|
||||
2. Plain unattended clone contains the entry? If yes, the installer's view is cached → purge mirror.
|
||||
3. Only then suspect the installer itself (validation code lives in the minified bundle; `grep -oE '.{600}<error string>' "$bunfile"` on `readlink -f $(which omp)` shows the exact check).
|
||||
|
||||
## After install — proof without a TUI
|
||||
- `omp plugin doctor` → per-plugin ✔ line.
|
||||
- Audible/behavioral chain when TUI input is unusable (update-banner modal freezes pty submits): run `omp --mode=rpc --no-session` with the feature env armed (dankvoice: `DANKVOICE_AUTO=1`, gate is print/json-only) and watch for objective side effects, e.g. PipeWire: `pw-dump | grep -q "say-<ms>.wav"` proves synth+playback end-to-end.
|
||||
@@ -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.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
name: ryzenai-generic-failure-loader-order
|
||||
description: "Debug AMD Ryzen AI OGA \"Exception during initialization: Generic Failure\" on Linux XDNA2 — the LD_LIBRARY_PATH-vs-activate ordering trap, its proof instruments, and the OGA 0.14 run contract."
|
||||
---
|
||||
|
||||
Symptom (any `onnxruntime_genai` run on a Ryzen AI NPU, container or bare):
|
||||
|
||||
```
|
||||
[E:onnxruntime:, inference_session.cc:2811 operator()] Exception during initialization: Generic Failure
|
||||
```
|
||||
|
||||
Fails ~2 ms after `og.Model()`. No `openat` of `/dev/accel/accel0`, **nothing in the kernel log**, no XRT log (the INI logger is not built into AMD's shipped XRT), no core dump. It is NOT a platform, model-export, or driver-ABI failure.
|
||||
|
||||
## Root cause
|
||||
|
||||
`source <venv>/bin/activate` from `install_ryzen_ai.sh` **prepends** to `LD_LIBRARY_PATH`:
|
||||
|
||||
```
|
||||
site-packages/flexml/flexml_extras/lib : site-packages/onnxruntime/capi : site-packages/voe/lib
|
||||
```
|
||||
|
||||
`voe/lib` is the **compiler-side** bundle: it ships its own `libxrt_coreutil.so.2` and `libryzen_mm.so.1`. Set the path *before* activating and those copies win, XRT's XDNA shim binds against the wrong coreutil, `xrt_core::shim_loader::shim_loader()` → `get_userpf_device()` → `xrt::device(0)` throws, `ryzenai::Allocator::Alloc` throws next, and ORT flattens both into the bare string above.
|
||||
|
||||
**Rule: activate first, THEN set `LD_LIBRARY_PATH`, with `/opt/xilinx/xrt/lib` first.** Passing the var via `podman -e` and sourcing activate afterwards in the same `bash -lc` is the broken shape — that is exactly how a runner script differs from a hand-typed probe, and it is why diagnostics pass while the runner fails. Mounting XRT is not enough either: the tree must be **on** the path.
|
||||
|
||||
## Proof instruments, cheapest first
|
||||
|
||||
1. `ldd <deployment>/lib/libonnxruntime_providers_ryzenai.so | grep -E "libxrt_coreutil|libryzen_mm"` — the resolved path settles it alone: `/opt/xilinx/xrt/lib` = good, `.../voe/lib` = this bug.
|
||||
2. `XILINX_XRT=/opt/xilinx/xrt /opt/xilinx/xrt/bin/xrt-smi examine` → `RyzenAI-npu5 | aie2p | 6x8` + `NPU Firmware Version`. Needs `libboost_filesystem1.83.0`, `libboost_program_options1.83.0`, `libuuid1` (26.04 names; the 24.04 docs' 1.74.0 does not exist). A "No such file or directory" for a file that exists = missing interpreter/dep, not a missing binary.
|
||||
3. `strace -f -e trace=openat` — `/dev/accel/accel0` never opened ⇒ failure is pre-device ⇒ loader-level.
|
||||
4. `gdb -q -batch -x <(echo 'catch throw'; echo run; echo 'bt 10')` style catch-throw loop → names `shim_loader` / `Allocator::Alloc`.
|
||||
|
||||
Known dead ends (each costs one run to rule out, then stop): `--ulimit memlock`, XRT INI verbosity, `DD_LOG_LEVEL` / `RYZENAI_TRACE` / `RYZENAI_EP_TRACING` (print nothing before the throw), byte-scanning XRT `.so` for PCI IDs (ambiguous), libboost presence for the OGA path (only `xrt-smi` needs it), flag-by-flag container matrices (`--memory`, `--security-opt`, `--name`, extra mounts — all innocent).
|
||||
|
||||
## Verified facts on this stack
|
||||
|
||||
- Vendor XRT 2.25.37 userspace (`dpkg-deb -x`, never dpkg-installed) works against Ubuntu's **in-tree `amdxdna` 0.7.0`; no DKMS module needed. `1022:17f0` rev 11 = XDNA2, handled as `aie2p 6x8`.
|
||||
- AMD's `quicktest` passing does **not** prove NPU use (it can silently run on CPU); trust `xrt-smi` + logits, not "it didn't crash".
|
||||
- `/dev/accel/accel0` is `root:render 0660`; rootless podman cannot read it (userns drops the gid; `keep-groups`, `keep-id:gid=990`, `--group-add render` all fail) → rootful container, or a udev rule like the GPU nodes'.
|
||||
- OGA 0.14 (RAI 1.8) contract: `GeneratorParams` has only `set_search_options` (no `input_ids`, no `model.generate`); feed with `Generator.append_tokens(ids)`, loop `generate_next_token()`, read `get_sequence(0)`; `max_length` counts **prompt + generated**. Full Fusion (`*_npu_4K`) caps input+output at 4096.
|
||||
- Validate the *content*, not just the exit code: `np.argsort(logits[0])[-8:]`. `append_tokens` returning a real logits tensor proves the graph ran; if argmax is the sequence terminator (`
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: ryzenai-npu-oga-linux-run
|
||||
description: "Run an AMD vendor-compiled Ryzen AI (XDNA2) model — OGA/onnxruntime-genai — on a Linux Ryzen AI host with the in-tree amdxdna driver, without installing the vendor driver or touching the host driver; includes the triage for ORT \"Exception during initialization: Generic Failure\"."
|
||||
---
|
||||
|
||||
Run a vendor-compiled Ryzen AI (XDNA2) model on Linux with the **in-tree** amdxdna driver: no vendor kernel module, no `dpkg -i`, host driver untouched.
|
||||
|
||||
## Preconditions
|
||||
- Host: Strix Point / Strix Halo / Krackan (PCI `1022:17f0`), in-tree `amdxdna` bound to the NPU function (`readlink /sys/bus/pci/devices/<bdf>/driver` → `amdxdna`), `/dev/accel/accel0` present.
|
||||
- `ryzen_ai-<ver>.tgz` installed into a venv (`install_ryzen_ai.sh -a yes -p <venv>`; it hard-codes `python3.12` — put a uv-managed 3.12 **bin dir** on PATH, never a symlink: a symlinked shim breaks venv creation with `No module named 'encodings'`).
|
||||
- Model artifact MUST match the RAI version: `<name>_rai_<ver>_npu_<ctx>`. Other versions load and emit garbage.
|
||||
- Vendor XRT userspace: `dpkg-deb -x` the debs from `RAI_<ver>_Linux_NPU_XRT.zip` (base + npu + `xrt_plugin…amdxdna.deb` — the plugin is what ships `libxrt_driver_xdna.so.*`) into a host dir, bind-mount it at `/opt/xilinx/xrt`.
|
||||
|
||||
## Container run line (the part that is easy to get wrong)
|
||||
```
|
||||
--device /dev/accel/accel0 # root:render 0660 → rootful, or a world-writable udev rule
|
||||
-v <xrt-root>/opt/xilinx/xrt:/opt/xilinx/xrt:ro
|
||||
-e RYZEN_AI_INSTALLATION_PATH=<venv> -e XILINX_XRT=/opt/xilinx/xrt
|
||||
-e LD_LIBRARY_PATH=/opt/xilinx/xrt/lib:<venv>/onnxruntime/lib:<venv>/deployment/lib
|
||||
# cwd MUST be <venv>/deployment/lib — the RyzenAI EP is dlopen'd by bare name and the
|
||||
# only place ORT looks is the working directory.
|
||||
# Activate the venv explicitly; a login shell (`bash -lc`) re-sources the profile and
|
||||
# can put a numpy-less base python first on PATH.
|
||||
```
|
||||
|
||||
## LAW: mounting XRT is not enough — `/opt/xilinx/xrt/lib` must be ON `LD_LIBRARY_PATH`
|
||||
The RyzenAI EP reaches the XDNA shim through XRT's own loader. With the tree bind-mounted
|
||||
but off the loader path, `xrt::device(0)` throws in `xrt_core::shim_loader`, the RMM
|
||||
allocator fails next, and ORT flattens all of it into
|
||||
|
||||
```
|
||||
[E:onnxruntime:, inference_session.cc:2811] Exception during initialization: Generic Failure
|
||||
```
|
||||
|
||||
Signature that distinguishes this from a real device/driver fault: fails in ~2 ms, **never
|
||||
opens `/dev/accel/accel0`**, nothing in `dmesg`/`journalctl -k`, no XRT log (the INI logger
|
||||
is not built into the vendor build — `XRT_INI_PATH` + `[Common] verbosity` writes nothing).
|
||||
|
||||
## Triage recipe for "Generic Failure" (in this order — each step is one call)
|
||||
1. `strace -f -e trace=openat` → does it open `/dev/accel/accel0`? If **no**, the failure is pre-device: loader/shim, not the driver. Also note the last file it opens (`genai_config.json` = config parsed, then provider setup fails).
|
||||
2. `gdb -q -batch -x cmds --args python driver.py` with `catch throw` + `bt 10` + `continue`. Frames `xrt_core::shim_loader::shim_loader` / `get_userpf_device` / `xrt::device::device` then `ryzenai::Allocator::Alloc` ⇒ the shim never loaded ⇒ fix `LD_LIBRARY_PATH`.
|
||||
3. Prove it with a two-arm run in ONE container (toggle only the suspect) before writing the law down. Both arms passing ⇒ that variable was never the cause.
|
||||
4. Ground truth on device visibility: `xrt-smi examine` → `RyzenAI-npu5 | aie2p | 6x8` + `NPU Firmware Version`. If xrt-smi dies on `libboost_filesystem.so.1.83.0`, install `libboost_filesystem1.83.0`+`libboost_program_options1.83.0` — **boost is only needed by xrt-smi, not by the OGA/EP path** (verified by purging it and still loading the model).
|
||||
5. `voe` in site-packages is a *compiler* toolkit (passes/patterns), not a runtime — swapping `LD_LIBRARY_PATH` to `voe/lib` fixes nothing.
|
||||
6. Byte-scanning XRT `.so` files for supported PCI IDs is inconclusive (2-byte ID patterns collide constantly) — don't bother.
|
||||
|
||||
## Distrust "it ran" on this stack
|
||||
- Vendor `quicktest` can print success while computing on CPU (missing peano lib ⇒ silent CPU fallback). Prove NPU residency per run: sample `/sys/class/accel/accel0/device/mem_usage` (needs root) during generation, or read the EP's `Actually running on NPU` line.
|
||||
- Never report request #1 after a boot as a rate — first pass includes graph/init cost.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: ryzenai-npu-oga-linux-spike
|
||||
description: "Run a vendor-compiled AMD Ryzen AI (XDNA2) ONNX-GenAI model on a Linux Strix Halo host from public artifacts: staging, rootless NPU device-access wall, container recipe, and the NuTTS-air speech-token contract."
|
||||
---
|
||||
|
||||
Run an AMD-precompiled XDNA2 model (OGA / onnxruntime-genai) on a Linux Strix Halo host (Dankclaw-class) without installing the vendor stack on the host.
|
||||
|
||||
## Where the bits actually live (both public, no AMD account)
|
||||
|
||||
- Runtime tarball: `https://download.amd.com/opendownload/RyzenAI/1.8.0/ryzen_ai-1.8.0.tgz` (~7.28 GiB). Verify with a ranged GET — first bytes `1f 8b 08`.
|
||||
- NPU driver/XRT zip: `https://download.amd.com/opendownload/RyzenAI/Driver/RAI_1.8_Linux_NPU_XRT.zip` (90 MB).
|
||||
- Dead ends (404, do not re-probe): `download.amd.com/driver/linux/RAI_1.8_Linux_NPU_XRT.zip`, `.../opendownload/RyzenAI/ryzen_ai-1.8.0.tgz`, `www.xilinx.com/bin/public/openDownload?filename=...` (301 → 404). The login-walled EULA *form* is not the gate; the `opendownload` tree is the real file host.
|
||||
|
||||
Tarball has 30 top-level entries: cp312/linux_x86_64 wheels (`onnxruntime_genai_ryzenai-0.14.0`, `onnxruntime_vitisai-1.27.0`, `vitis_mllib`, `flexml*`, `device_essentials_strx`, `model_generate`, `voe-1.8.0`), plus `deployment.tar.gz` (contains `lib/libonnxruntime-genai.so`, `lib/libonnxruntime_providers_ryzenai.so`, AIE compiler libs), `onnxruntime.tar.gz`, `quicktest.tar.gz` (VitisAI-EP install validator), `LLM.tar.gz` (text-only OGA examples: `run_model.py`, `tokenizer_factory.py`), `install_ryzen_ai.sh`. `voe-4.0-linux_x86_64.tar.gz` is only `vaip_config.json` — no TTS xclbins. **AMD ships no TTS runner and no TTS example.**
|
||||
|
||||
## Host rules
|
||||
|
||||
- **Never `dpkg -i` the vendor XRT.** `dpkg-deb -x <deb> <dir>` and bind-mount `<dir>/opt/xilinx/xrt` at the same path in the container. The plugin deb would install a DKMS `amdxdna` that replaces the distro in-tree driver; the in-tree driver on Ubuntu 26.04 is `amdxdna 0.7.0` and already loads `amdnpu/17f0_11/npu_7.sbin` at boot (`dmesg | grep amdxdna`).
|
||||
- **Rootless containers cannot read `/dev/accel/accel0`** (`root:render 0660`): the host gid never enters the userns gid map, so `--device` yields `nobody:nogroup`. Verified failing 2026-10-19: `--group-add keep-groups`, `--userns=keep-id`, `--userns=keep-id:gid=990` (process gets gid 990, node still unreadable), `--group-add render`, `--group-add gid:990` (both error). Options: run rootful (`sudo podman`, separate storage → rebuild the image rootful, ~1 min), or add a world-writable udev rule for `accel0` (the fleet already does exactly this for `kfd`/`renderD*` in `99-comfyui-gpu-access.rules`, whose header explains why: systemd user-unit spawns carry no supplementary groups).
|
||||
- **Rootless image build trap:** the vendor installer's `tar -xf` preserves recorded uids (95777 etc.) and aborts under `set -e` with `Cannot change ownership ... Invalid argument`, silently skipping the `deployment`/`onnxruntime` extraction. Patch it in the Containerfile: `sed -i 's/tar -xf/tar --no-same-owner -xf/g' install_ryzen_ai.sh`.
|
||||
- Installer usage: `./install_ryzen_ai.sh -a yes -p /opt/rai -c /opt/rai` (python **3.12** required; base `python:3.12-slim`; needs `linux-libc-dev zip pciutils patch libgomp1`). It builds a venv from the local wheels, reinstalls `onnxruntime-vitisai` then `--no-deps onnxruntime-genai-ryzenai`, installs `requirements_extras.txt` (transformers 4.57.6), patches `bin/activate` (sets `RYZEN_AI_INSTALLATION_PATH=$VIRTUAL_ENV` + `LD_LIBRARY_PATH` into site-packages), and untars `LLM/deployment/onnxruntime/voe/quicktest` into the cpp path.
|
||||
|
||||
## HF artifact staging
|
||||
|
||||
- Gated (401 on API, 403 on git) for a plain account: `neuphonic/neucodec` (the **only** NeuCodec encoder), `neuphonic/neucodec-onnx-decoder`, `neuphonic/neucodec-onnx-decoder-int8`, `neuphonic/neutts-air`. `amd/neutts-air_rai_1.8.0_npu_4K` is public. Public mirrors of the codec exist (`eugenehp/neucodec` has the full 1.16 GB `pytorch_model.bin`) — treat a mirror of a gated release as a licensing decision for the operator, not a workaround to take silently.
|
||||
- `github.com/neuphonic/neutts` is public and ships `samples/{dave,emily,greta,jo}.{pt,txt,wav}` = **pre-encoded reference codes + transcripts** → a spike needs zero gated bytes.
|
||||
- Auth without leaking the token into `ps`: build a 600-perm credential file with a shell builtin and point git at it —
|
||||
`umask 077; printf 'https://oauth2:%s@huggingface.co\n' "$(cat ~/.cache/huggingface/token)" > ~/.git-credentials-hf`
|
||||
then `git -c credential.helper="store --file ~/.git-credentials-hf" clone ...`. Never `git clone https://oauth2:$TOKEN@...`.
|
||||
|
||||
## NuTTS-air on XDNA2 (the model-side contract)
|
||||
|
||||
- The package is an OGA model dir: `genai_config.json` (`type: qwen2`, 24 layers, hidden 896, 14 heads / 2 KV, ctx 32768, `provider_options: [{"RyzenAI": {"hybrid_opt_token_backend": "npu"}}]`), plus `dd_metastate_*` AIE artifacts and `model.onnx` + `model.onnx.data`.
|
||||
- **Speech tokens live in the text vocab**: `<|speech_0|>` = id 151671 (10 001 codes), with `<|TEXT_PROMPT_START|>` 151666, `<|TEXT_PROMPT_END|>` 151667, `<|TEXT_REPLACE|>` 151665, `<|SPEECH_REPLACE|>` 151668, `<|SPEECH_GENERATION_START|>` 151669, `<|SPEECH_GENERATION_END|>` 151670. Generation is a plain `og.Generator` loop; the graph's own `eos_token_id` is `[151645, 151643]`, so pass 151670 as an extra eos or stop on it manually.
|
||||
- **Real-time line = 50 speech tokens/s** (`sample_rate=24000`, `hop_length=480`). Judge any NPU/iGPU TTS number against 50.
|
||||
- Build the prompt by *importing* the vendor function, never by copying the template:
|
||||
`sys.path.insert(0, <neutts repo>); from neutts.neutts import NeuTTS`, then
|
||||
`NeuTTS._apply_chat_template(SimpleNamespace(tokenizer=hf_tok, input_format="text"), ref_codes, ref_text, text, None)` — works on a duck-typed `self`, so no backbone/codec load. Template: `user\n<|TEXT_REPLACE|>\nassistant\n<|SPEECH_REPLACE|>`; splice `TEXT_PROMPT_START + encode(f"{ref_text} {text}") + TEXT_PROMPT_END` at TEXT_REPLACE, then truncate at SPEECH_REPLACE and append `[SPEECH_GENERATION_START] + encode("".join(f"<|speech_{i}|>"))`.
|
||||
- Voice identity = reference codes + transcript (request-time conditioning). No trained artifact exists to preserve; packs holding only `reference.wav` require the gated encoder once, offline.
|
||||
|
||||
## Status caveat
|
||||
|
||||
Measured on 2026-10-19 up to and including: staged artifacts, image build, device-access matrix, prompt contract. The token-rate measurement (does the vendor userspace drive the in-tree 0.7.0 driver, and does it clear 50 tok/s) is **not** captured here — re-measure, never trust a remembered rate.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
name: ryzenai-venv-dependency-triangle
|
||||
description: "Debug the torchao/torchtune/transformers import triangle inside an AMD Ryzen AI (ryzen_ai-*.tgz) venv under torch 2.6, including the masked \"cannot import name\" failures and the port-the-one-symbol escape."
|
||||
---
|
||||
|
||||
# Ryzen AI venv dependency triangle (torch 2.6 era)
|
||||
|
||||
Symptom that starts it all — and it never names the culprit:
|
||||
|
||||
```
|
||||
ImportError: cannot import name 'HubertModel' from 'transformers'
|
||||
```
|
||||
|
||||
The named symbol is healthy. `import torchao` alone reproduces the failure; `import transformers` alone does not. transformers imports its **torchao integration** whenever the real modelling path loads, and the failure is re-raised two frames deep by the lazy loader as a missing name.
|
||||
|
||||
## Instruments
|
||||
|
||||
Never conclude from `grep -c Symbol transformers/__init__.py` — 4.5x generates its lazy `__init__`, so an absent literal proves nothing. Get the real exception:
|
||||
|
||||
```python
|
||||
import traceback, torch, transformers
|
||||
try:
|
||||
__import__("transformers.models.hubert.modeling_hubert")
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
```
|
||||
|
||||
That prints the truth, e.g. `AttributeError: module 'torchao.quantization' has no attribute 'Float8WeightOnlyConfig'` from `transformers/modeling_layers.py`.
|
||||
|
||||
Also probe the order matrix (`import X; from transformers import Y` for each suspect): only the poisoned order fails, which isolates the culprit without reading vendor code.
|
||||
|
||||
## The triangle (measured 2026-10-19, ryzen_ai 1.8.0, torch 2.6.0+cpu, transformers 4.57.6)
|
||||
|
||||
| Option | Result |
|
||||
|---|---|
|
||||
| torchao absent | `from transformers import HubertModel` -> OK |
|
||||
| torchao 0.7.0+cpu | `ImportError: Float8WeightOnlyConfig` (masked as missing symbol) |
|
||||
| torchao 0.8.0+cpu | imports (warns `No module named 'triton'`), still lacks `Float8WeightOnlyConfig` |
|
||||
| torchao >= 0.9 | has the symbol, requires torch >= 2.7 -> impossible in this venv |
|
||||
| torchtune, ANY version (0.6.1 … 0.1.1) | guard `torchao not installed`, or `pyarrow requires NumPy 2.0 or newer, found 1.26.4` |
|
||||
|
||||
Two independent dead ends: torchtune's package init pulls `datasets` -> **the pyarrow AMD ships in its own venv refuses that venv's own numpy 1.26.4**. So `import torchtune` is structurally dead, and torchao (the only thing that satisfies its guard) breaks transformers. **Never "just upgrade" torch/numpy: the vendor's ONNX runtime and torch build are what the NPU EP is loaded against.**
|
||||
|
||||
## Escape: port the one symbol, pin both absent
|
||||
|
||||
Ask what the third-party package is actually used for before fighting the resolver. In `neucodec` it was one symbol (`RotaryPositionalEmbeddings`, ~40 lines, copied verbatim from `torchtune/modules/position_embeddings.py`, BSD-3) used by two files. Apply it in the image with a transform that **asserts** each import line exists, so a vendor update fails the build instead of shipping a half-patched package:
|
||||
|
||||
```dockerfile
|
||||
COPY patches/rope_local.py /opt/patch/rope_local.py
|
||||
RUN python - <<'PY'
|
||||
import pathlib
|
||||
from importlib.util import find_spec
|
||||
pkg = pathlib.Path(find_spec("neucodec").origin).parent # find_spec: importing it is what is impossible yet
|
||||
(pkg / "rope_local.py").write_text(pathlib.Path("/opt/patch/rope_local.py").read_text())
|
||||
old, new = "from torchtune.modules import RotaryPositionalEmbeddings", "from .rope_local import RotaryPositionalEmbeddings"
|
||||
for name in ("bs_roformer5.py", "codec_decoder_vocos.py"):
|
||||
p = pkg / name; s = p.read_text()
|
||||
assert old in s, name + ": import line moved - re-read the vendor source"
|
||||
p.write_text(s.replace(old, new))
|
||||
PY
|
||||
```
|
||||
|
||||
Gate both absences at build time so nobody re-adds them and inherits a three-week-later mystery:
|
||||
|
||||
```dockerfile
|
||||
RUN ... import-check \
|
||||
&& python -c "import importlib.util as u; assert u.find_spec('torchao') is None; assert u.find_spec('torchtune') is None"
|
||||
```
|
||||
|
||||
Prove a ported numeric kernel with the vendor's own fixtures, not with faith: `neucodec` ships `samples/jo.wav` *and* its own encoding `samples/jo.pt`, so re-encoding the WAV and comparing integer codes is a pass/fail correctness test of the RoPE port.
|
||||
|
||||
## Rules of thumb
|
||||
|
||||
- `--no-deps` for anything adjacent to torch/onnxruntime/numpy; check the vendor pins by reading them out of the venv (`python -c "import torch; print(torch.__version__)"`), never from docs.
|
||||
- A `--dry-run` install that resolves without touching torch/numpy/onnxruntime is the licence to install *with* deps.
|
||||
- `uv pip install --target DIR` / a nested venv does **not** layer over a parent venv: a venv created from `/opt/rai/bin/python` resolves "system site-packages" to the base interpreter, and uv's resolver ignores `.pth` paths and will pull a second numpy that breaks the vendor C extensions.
|
||||
- Ephemeral `podman run --rm` probes discard everything you installed in them — build a throwaway tag (truncate the Containerfile before the failing step) instead of re-hypothesising.
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: sigterm-kill-test-stub
|
||||
description: "Pin \"code kills its child process\" behavior with a bash stub player: make the stub SIGTERM-reactive via sleep&wait, log KILLED via trap; diagnose deferred-trap failures."
|
||||
---
|
||||
|
||||
Use when a test must prove production code sends SIGTERM to a spawned child (player, worker, server stub) and the test asserts the kill happened — or when such a test mysteriously fails with `KILLED` missing and wall time equal to the stub's sleep duration.
|
||||
|
||||
## The trap-during-sleep gotcha
|
||||
|
||||
A bash stub that sleeps in the **foreground** does NOT run its TERM trap when signalled: bash defers traps until the current foreground command completes. The stub dies (or logs) only after the sleep finishes — long after the test read the evidence file.
|
||||
|
||||
Symptoms:
|
||||
- Assertion on a `KILLED` marker line fails although production code demonstrably calls `child.kill("SIGTERM")`.
|
||||
- Test wall time equals the stub's full sleep (the kill "had no effect").
|
||||
|
||||
## Fix: reactive stub skeleton
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
printf '%s\n' "$*" >> "$STUB_LOG" # call record
|
||||
trap 'printf "KILLED\n" >> "$STUB_LOG"; exit 143' TERM # BEFORE the sleep
|
||||
for arg in "$@"; do case "$arg" in *.wav) cp "$arg" "$COPY" ;; esac; done
|
||||
sleep "${STUB_HOLD:-0.1}" & # background sleep…
|
||||
wait $! # …wait is interruptible
|
||||
printf 'DONE\n' >> "$STUB_LOG"
|
||||
```
|
||||
|
||||
- `sleep N & wait $!` is the idiom: a signal makes builtin `wait` return immediately, the trap runs at once, `exit` inside the trap prevents fallthrough to `DONE`.
|
||||
- Tune duration per test via the env knob (`STUB_HOLD=5`) so the child is provably still alive when the kill is triggered.
|
||||
- Put the trap BEFORE any long command; a trap registered after the sleep never guards it.
|
||||
|
||||
## Harness wiring (black-box driver pattern)
|
||||
|
||||
- Scenario: start the long work → settle (>spawn latency, <hold) → trigger the killer (shutdown event, second invocation, `/stop`) → settle → read log.
|
||||
- Expose the stub log lines on the driver's stdout (`LOG <line>` per line) so tests grep output, not files: black-box seam stays output-only.
|
||||
- Assert `KILLED` present; for interrupt-semantics also count (`kills -eq 1`) and total call lines (`PLAYS 3` = call, KILLED, call).
|
||||
|
||||
## Orphan hygiene
|
||||
|
||||
Second child still sleeping when the driver exits: spawn with `stdio: "ignore"` so the orphan holds no capture pipe — it SIGPIPEs/quiets at teardown; do not lengthen tests waiting for it.
|
||||
|
||||
## Verify before trusting
|
||||
|
||||
Run the pair separately: kill-tests green while a byte-equality test (`cp` of the payload before sleep) stays green — the reactive rewrite must not drop the copy step (it sits between trap and sleep).
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: strix-halo-npu-readiness-census
|
||||
description: "Engine-agnostic census of whether an AMD Strix Halo / Ryzen AI host can run anything on its XDNA2 NPU: driver bind, firmware, device perms, IOMMU, distro XRT, missing AIE compiler, fabric clock, RAM headroom."
|
||||
---
|
||||
|
||||
Use when asked "can we run <engine/model> on the Strix Halo / Ryzen AI NPU?" for a runtime that is **not** halogen (halogen has its own gate + vendor catalog: use `halogen-npu-feasibility-census` for that). This answers only: is the *host* able, and what is missing.
|
||||
|
||||
## Why it is usually the wrong door first
|
||||
|
||||
XDNA2 executes **precompiled AIE partition programs** loaded through XRT → `amdxdna`. There is no generic tensor dispatch: an engine built on ggml/llama.cpp (or any GGUF loader) cannot "enable" the NPU — the port must be a re-export + vendor compile, not a flag. So pair this census with the accelerator the same engine *can* select by build flag (Vulkan/HIP on the gfx1151 iGPU) before proposing NPU work.
|
||||
|
||||
## Census (all read-only, over ssh from the operator box)
|
||||
|
||||
```bash
|
||||
ssh <host> '
|
||||
cat /proc/cmdline; ls /sys/kernel/iommu_groups | wc -l # iommu=pt required; groups==0 => IOMMU off => NPU dead
|
||||
lsmod | grep -i amdxdna # in-tree driver
|
||||
sudo dmesg | grep -iE "xdna|npu" | tail # "Initialized amdxdna_accel_driver <ver> for 0000:c6:00.1"
|
||||
lspci -nn | grep -iE "npu|processing" # Strix Halo = 1022:17f0
|
||||
ls /sys/bus/pci/drivers/amdxdna # must list the BDF
|
||||
ls -l /dev/accel # accel0, root:render 660
|
||||
id -nG <deploy-user> | tr " " "\n" | grep -E "render|video" # rootless podman needs render, else --device fails at create
|
||||
find /usr/lib/firmware -iname "*npu*" | head # firmware is /usr/lib/firmware/amdnpu/<devid>_<rev>/npu.sbin*.zst — match the PCI rev
|
||||
dpkg -l | grep -iE "xrt|xdna"; ls /opt/xilinx/xrt/lib 2>&1 # distro libxrt-npu2 = XDNA2 runtime; vendor /opt/xilinx/xrt usually absent
|
||||
apt-cache policy libxrt2 libxrt-npu2 | grep Candidate
|
||||
apt-cache search onnxruntime | head # distro ONNX RT exists; the Ryzen AI EP does not
|
||||
python3 -c "import onnxruntime" 2>&1 | tail -1 # absence of the EP + of ryzenai-compile is the real blocker
|
||||
for c in /sys/class/drm/card*/device; do echo "-- $c"; cat $c/power_dpm_force_performance_level 2>&1; cat $c/pp_dpm_fclk 2>&1 | tr "\n" " "; echo; done
|
||||
nproc; free -g | head -2 # RAM headroom + thread count the engine will pick
|
||||
'
|
||||
```
|
||||
|
||||
## Reading it
|
||||
|
||||
- Driver bound + `accel0` + firmware dir + `iommu=pt` ⇒ **kernel side is ready**; do not re-litigate "is the NPU disabled". A missing device node is *not* the modern failure mode.
|
||||
- `auto` on `pp_dpm_fclk` / `power_dpm_force_performance_level` ⇒ fabric clock **unheld**. GPU+NPU concurrently with a moving fclk hangs these hosts and corrupts NPU results; any NPU plan must pin the top fclk step (or run in a container holding it) first.
|
||||
- No `ryzenai-compile`/ONNX Ryzen AI EP ⇒ nothing on the host can produce a partition program. That is the enablement delta, and it is a toolchain install + a model-specific export/quantize/compile project, not a config change.
|
||||
- `free` headroom matters: NPU partitions want a few GB of host RAM each and can log benign `Failed to alloc dev bo memory, ret -28` under pressure.
|
||||
|
||||
## Laws / traps
|
||||
|
||||
- Read state only. Never probe or load the NPU beside a live inference service — stop + mask the service first (fleet benching policy); this host class has a precedent of a concurrent GPU/NPU experiment needing a power cycle.
|
||||
- `sudo podman ...` finds nothing (per-user rootless storage); run podman as the deploy user.
|
||||
- `/dev/accel/accel0` existing does not mean a context/PASID can be created; with IOMMU off the failure is at context creation, not at the node.
|
||||
@@ -0,0 +1,187 @@
|
||||
---
|
||||
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 (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
|
||||
|
||||
Use when a repo has accumulated one page per attempt/era (runbooks, bench logs, swap
|
||||
narratives) and the law is **one page owns one thing**. Applies to
|
||||
`serverAppConfigs-docs/` (Obsidian vault, `AGENTS.md` → *Documentation Policy*), but the
|
||||
mechanics are general.
|
||||
|
||||
## 1. Decide ownership before touching files
|
||||
|
||||
- Endpoint/service page owns: current shape, **Eras** table (window | payload | runtime |
|
||||
shape | replaced because | rollback), **Laws**, wire contract, files.
|
||||
- Technique page owns the mechanism and the arithmetic — **no per-endpoint throughput
|
||||
table or boot ledger**.
|
||||
- `log.md` owns incidents and laws only. A swap is an Eras row, never a log entry.
|
||||
- `AGENTS.md` carries operator-critical numbers + cross-border laws; everything else links.
|
||||
- A **retired** endpoint still gets one locator page: era windows quoted verbatim from each
|
||||
era page's own banner, no numbers restated, and any date conflict recorded as an open
|
||||
question instead of silently resolved. Never pick a winner between two primary sources.
|
||||
|
||||
## 2. Single-writer rule (the mistake that costs the most)
|
||||
|
||||
Facts get **ported into the owner page before they are cut** anywhere else. So while any
|
||||
subagent may port facts, only ONE writer may touch the owner pages. Spawn children with an
|
||||
explicit `DO NOT EDIT <owner pages>` and require a `needsPort` list in their report instead
|
||||
of letting them append. Send the narrowing message early — a child already editing them has
|
||||
to be reconciled by hand.
|
||||
|
||||
## 3. Port-before-cut census (proves nothing was lost)
|
||||
|
||||
For every deleted line, extract distinctive keys and check them against the vault minus the
|
||||
file being rewritten. Any line with **no** surviving key is an orphan → port, or accept
|
||||
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).
|
||||
|
||||
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.
|
||||
|
||||
## 4. When a page is the same page twice
|
||||
|
||||
Signature: a page whose `wc -l` is ~2× its `HEAD` size, with a **second frontmatter block in
|
||||
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 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
|
||||
it — that is the second copy, and a stray `type:` in a code block has no key run. Keep the copy
|
||||
whose body is a **superset** (compare after stripping the dropped copy's own frontmatter),
|
||||
un-glue the fence, and prove `0` census losses before writing. Refuse to guess: if the halves
|
||||
differ materially, stop.
|
||||
|
||||
## 5. `.AGENTTRASH` is not vault content
|
||||
|
||||
Every tool that walks the vault must exclude it — **both the scan set and the resolution
|
||||
index**. The link checker resolving links *into* the trash turns "live page points at a
|
||||
deleted page" into a false PASS, which is worse than a false alarm. The `docs_completeness`
|
||||
seam's `find` must carry `-not -path '*/.AGENTTRASH/*'` in both walks, or a trashed page
|
||||
demands an index row and a trashed page can satisfy the docs requirement for a live service.
|
||||
|
||||
Trash is gitignored; move with plain `mv` into the dated dir. `git mv` into an ignored path
|
||||
stages a rename the next agent cannot see (`git restore --staged <src> <dst>`). Never `rm`,
|
||||
never `git clean -f`.
|
||||
|
||||
## 6. Rewire + regenerate indexes mechanically
|
||||
|
||||
```bash
|
||||
grep -rnoE "\[\[(page-a|page-b|...)\]\]" --include="*.md" serverAppConfigs-docs | grep -v AGENTTRASH
|
||||
grep -rnoE "\((page-a|page-b|...)\.md\)" --include="*.md" serverAppConfigs-docs | grep -v AGENTTRASH
|
||||
```
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
`tests/docs_completeness.bats`: derive the live set instead of hardcoding it — an endpoint is
|
||||
live when `scripts/` holds **both** `<name>.env` and `<name>.service`; fail if any
|
||||
`<name>-*.md` page exists, and guard against a vacuous derivation (`derived -ge 3`). A
|
||||
re-created era page then cannot pass tests. For the length hint, prefer **derived** exemptions
|
||||
(live endpoint, or a `retired-endpoint` tag: a campaign ledger that exists nowhere else is
|
||||
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
|
||||
literal `+`** — do not use it. Safe rewrites inside an existing bullet: keep the `- ` opener
|
||||
line untouched and PUT only the indented continuation lines, or convert the note to a nested
|
||||
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:
|
||||
- A subagent killed by the runtime limit yielded a 495-line owner page, a verified era table
|
||||
and a byte census — **the file did not exist** and its table was self-referential.
|
||||
- Another wrote its output to disk and died without reporting, leaving a rewritten `log.md`;
|
||||
the census showed it had dropped laws held nowhere else.
|
||||
- Verdict tables claimed "0 sole records / no contradictions" while missing the contradiction
|
||||
sitting in their own evidence row, and invented bullet IDs — one renamed a bullet to the
|
||||
**opposite** claim.
|
||||
- A scout called accurate docs "WRONG" because the docs said `wip: "down"`.
|
||||
|
||||
Rules: after ANY delegated write run `wc`/`ls` + the orphan census yourself; re-grep every
|
||||
claimed holder before cutting a line; treat `cancelled`/timed-out yields as unverified no
|
||||
matter how concrete they read; and re-read the source bullet before trusting a table's ID.
|
||||
|
||||
## 10. Merge order (a long-lived branch under a moving main)
|
||||
|
||||
1. Commit your work in atomic groups **before** merging (a dirty tree cannot merge cleanly).
|
||||
2. Inspect the incoming commits: `git log --oneline --stat HEAD..origin/main`. If they modify
|
||||
a page you deleted, **port their additions into the owner page**, then merge and resolve
|
||||
the modify/delete as `git rm`.
|
||||
3. Resolve a content block with `write conflict://<id>` (`@ours` / `@theirs` / explicit text),
|
||||
then **`git add` the file** — resolving content does not stage it.
|
||||
4. **Re-probe live state after the merge, before you write any number.** A campaign that
|
||||
reported fleet shapes at the start was made stale by a mid-campaign reslice on main: probe
|
||||
`/slots` and `tr '\0' '\n' < /proc/$(pidof <engine>)/cmdline` again at the end, and let the
|
||||
live answer beat both your earlier probe and the docs.
|
||||
5. `git * --no-verify` is forbidden here. Sweep dead paths in `AGENTS.md`
|
||||
(`grep -oE "[A-Za-z0-9._-]+\.md" AGENTS.md | sort -u`, then `find` each; hard-wrapped names
|
||||
are false positives — confirm with `ls`).
|
||||
|
||||
## 11. Verify, open, land
|
||||
|
||||
- `./tests/run.sh` (full suite) + `python3 scripts/check-vault-links.py serverAppConfigs-docs`
|
||||
→ must print `0 unresolved links`, and the OKF linter `0 violations`.
|
||||
- Env trims: prove value-neutrality mechanically (`git show HEAD:scripts/<svc>.env | grep -E
|
||||
'^[A-Z_]+=' | sort` vs working copy, diff empty). **`scripts/<svc>.env` is a deploy-planner
|
||||
path**: a comment-only trim makes the next service-scoped deploy restart a healthy endpoint.
|
||||
- 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.
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792440454430
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792395788647,
|
||||
"lastConsolidatedAt": 1792439707623,
|
||||
"lastResult": {
|
||||
"at": 1791599865775,
|
||||
"sessions": 1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792386375195
|
||||
"lastConsolidatedAt": 1792401025778
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792396789735
|
||||
"lastConsolidatedAt": 1792439491829
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792396748497,
|
||||
"lastConsolidatedAt": 1792400853634,
|
||||
"lastResult": {
|
||||
"at": 1792393886960,
|
||||
"sessions": 1,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792396722373,
|
||||
"lastConsolidatedAt": 1792439324791,
|
||||
"lastResult": {
|
||||
"at": 1792396071933,
|
||||
"at": 1792398531282,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792396749853
|
||||
"lastConsolidatedAt": 1792439315327,
|
||||
"lastResult": {
|
||||
"at": 1792439315327,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792439612626,
|
||||
"lastResult": {
|
||||
"at": 1792439612626,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792398333838
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792440990901,
|
||||
"lastResult": {
|
||||
"at": 1792433353188,
|
||||
"sessions": 1,
|
||||
"deltas": 1,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792434572397,
|
||||
"lastResult": {
|
||||
"at": 1792432178813,
|
||||
"sessions": 1,
|
||||
"deltas": 2,
|
||||
"model": "frank-zealot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"v": 1,
|
||||
"lastConsolidatedAt": 1792441029706
|
||||
}
|
||||
+5
-5
@@ -158,13 +158,13 @@ providers:
|
||||
# contextWindow is the PER-SLOT window: llama.cpp divides --ctx-size
|
||||
# across slots and answers a longer prompt with a 400, never a
|
||||
# truncation, so this value must follow every reslice (live now:
|
||||
# 2 x 262,144 over exact f16 KV, 68afc6d).
|
||||
contextWindow: 262144
|
||||
# 3 x 200,704 over f16 K + q8_0 V with the MTP drafter armed, ba69ea5).
|
||||
contextWindow: 200704
|
||||
# Prompt + budget must fit inside the slot window; thinking counts
|
||||
# against the budget. Compaction fires at 85 % of the window =
|
||||
# 222,822 est; worst-case prompt + budget ≈ 222,822 × 1.03 +
|
||||
# 16,384 ≈ 245,891 ≤ 262,144. This endpoint is the fleet's
|
||||
# compaction hub: the widest window in the fleet.
|
||||
# 170,598 est; worst-case prompt + budget ≈ 170,598 × 1.03 +
|
||||
# 16,384 ≈ 192,100 ≤ 200,704. This endpoint stays the fleet's
|
||||
# compaction hub: still the widest window in this file.
|
||||
maxTokens: 16384
|
||||
reasoning: true
|
||||
input: [text, image]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
tt.*
|
||||
.tests
|
||||
doc/tags
|
||||
debug
|
||||
.repro
|
||||
foo.*
|
||||
*.log
|
||||
data
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"neodev": {
|
||||
"library": {
|
||||
"enabled": true,
|
||||
"plugins": true
|
||||
}
|
||||
},
|
||||
"neoconf": {
|
||||
"plugins": {
|
||||
"lua_ls": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,4 @@
|
||||
# 💤 LazyVim
|
||||
|
||||
A starter template for [LazyVim](https://github.com/LazyVim/LazyVim).
|
||||
Refer to the [documentation](https://lazyvim.github.io/installation) to get started.
|
||||
@@ -0,0 +1,2 @@
|
||||
-- bootstrap lazy.nvim, LazyVim and your plugins
|
||||
require("config.lazy")
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"LazyVim": { "branch": "main", "commit": "999700997f72227187d49d8b92667183dc7fc809" },
|
||||
"base16-nvim": { "branch": "master", "commit": "7183774e90841f4bd27a47cb6e75cf532fd1192d" },
|
||||
"blink.cmp": { "branch": "main", "commit": "78336bc89ee5365633bcf754d93df01678b5c08f" },
|
||||
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
|
||||
"catppuccin": { "branch": "main", "commit": "edefef779ab08ce1a4a404713e3012b0d202bd35" },
|
||||
"conform.nvim": { "branch": "master", "commit": "016802de402556da54c36bd7359b441266b01cdd" },
|
||||
"flash.nvim": { "branch": "main", "commit": "5f0f270fdc7c5b0c21d903ee85b9cb06f2ac636a" },
|
||||
"friendly-snippets": { "branch": "main", "commit": "b4d01b0fdf3c9a549961c2f9ffe8dc09be166219" },
|
||||
"gitsigns.nvim": { "branch": "main", "commit": "fd780920613e541cbdfac41bf711583ed49f9249" },
|
||||
"grug-far.nvim": { "branch": "main", "commit": "bbde8ef5ae46ceee2c3bd8b21fc048c5f8ffbfc0" },
|
||||
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
|
||||
"lazydev.nvim": { "branch": "main", "commit": "ff2cbcba459b637ec3fd165a2be59b7bbaeedf0d" },
|
||||
"lualine.nvim": { "branch": "master", "commit": "221ce6b2d999187044529f49da6554a92f740a96" },
|
||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "00b5473cca4db5b410ff4bae724e3b6e21f2687f" },
|
||||
"mason.nvim": { "branch": "main", "commit": "2a6940af80375532e5e9e7c1f2fc6319a1b7a69d" },
|
||||
"mini.ai": { "branch": "main", "commit": "d0c4987a1ead2bcf4eb22cc9815c662d76677c08" },
|
||||
"mini.icons": { "branch": "main", "commit": "f916635dc5ae2f479fbb9ab8184bb9444b62e86c" },
|
||||
"mini.pairs": { "branch": "main", "commit": "03eb1f0062a2cee5314d1ac3939246e4bb21352e" },
|
||||
"noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" },
|
||||
"nui.nvim": { "branch": "main", "commit": "10fc361835c856ba4233ef5ea135b919bf3dce97" },
|
||||
"nvim-lint": { "branch": "master", "commit": "f6230a5c06ba59e6059c14637f1dbe29a7978b9b" },
|
||||
"nvim-lspconfig": { "branch": "master", "commit": "45a3a444b710511c39abca3b60bb6e23a21e3de5" },
|
||||
"nvim-treesitter": { "branch": "main", "commit": "29212d826054bb2948fa9d3a99eca9bf6a050eb2" },
|
||||
"nvim-treesitter-textobjects": { "branch": "main", "commit": "5c7b0263797dfd1bd6202f2b219f3b53a80b2187" },
|
||||
"nvim-ts-autotag": { "branch": "main", "commit": "d7220b55e16ed3c04e88086256def5d282429493" },
|
||||
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
|
||||
"plenary.nvim": { "branch": "master", "commit": "74b06c6c75e4eeb3108ec01852001636d85a932b" },
|
||||
"snacks.nvim": { "branch": "main", "commit": "882c996cf28183f4d63640de0b4c02ec886d01f2" },
|
||||
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
|
||||
"tokyonight.nvim": { "branch": "main", "commit": "cdc07ac78467a233fd62c493de29a17e0cf2b2b6" },
|
||||
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
|
||||
"ts-comments.nvim": { "branch": "main", "commit": "a59d6092213447450191122c9346f309161504cb" },
|
||||
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extras": [
|
||||
|
||||
],
|
||||
"install_version": 8,
|
||||
"news": {
|
||||
"NEWS.md": "11866"
|
||||
},
|
||||
"version": 8
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
-- Autocmds are automatically loaded on the VeryLazy event
|
||||
-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
|
||||
--
|
||||
-- Add any additional autocmds here
|
||||
-- with `vim.api.nvim_create_autocmd`
|
||||
--
|
||||
-- Or remove existing autocmds by their group name (which is prefixed with `lazyvim_` for the defaults)
|
||||
-- e.g. vim.api.nvim_del_augroup_by_name("lazyvim_wrap_spell")
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Keymaps are automatically loaded on the VeryLazy event
|
||||
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
|
||||
-- Add any additional keymaps here
|
||||
@@ -0,0 +1,53 @@
|
||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||
if not (vim.uv or vim.loop).fs_stat(lazypath) then
|
||||
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
|
||||
local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
|
||||
if vim.v.shell_error ~= 0 then
|
||||
vim.api.nvim_echo({
|
||||
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
|
||||
{ out, "WarningMsg" },
|
||||
{ "\nPress any key to exit..." },
|
||||
}, true, {})
|
||||
vim.fn.getchar()
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
vim.opt.rtp:prepend(lazypath)
|
||||
|
||||
require("lazy").setup({
|
||||
spec = {
|
||||
-- add LazyVim and import its plugins
|
||||
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
|
||||
-- import/override with your plugins
|
||||
{ import = "plugins" },
|
||||
},
|
||||
defaults = {
|
||||
-- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
|
||||
-- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
|
||||
lazy = false,
|
||||
-- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
|
||||
-- have outdated releases, which may break your Neovim install.
|
||||
version = false, -- always use the latest git commit
|
||||
-- version = "*", -- try installing the latest stable version for plugins that support semver
|
||||
},
|
||||
install = { colorscheme = { "tokyonight", "habamax" } },
|
||||
checker = {
|
||||
enabled = true, -- check for plugin updates periodically
|
||||
notify = false, -- notify on update
|
||||
}, -- automatically check for plugin updates
|
||||
performance = {
|
||||
rtp = {
|
||||
-- disable some rtp plugins
|
||||
disabled_plugins = {
|
||||
"gzip",
|
||||
-- "matchit",
|
||||
-- "matchparen",
|
||||
-- "netrwPlugin",
|
||||
"tarPlugin",
|
||||
"tohtml",
|
||||
"tutor",
|
||||
"zipPlugin",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Options are automatically loaded before lazy.nvim startup
|
||||
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
|
||||
-- Add any additional options here
|
||||
@@ -0,0 +1,70 @@
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
require('base16-colorscheme').setup({
|
||||
base00 = '#181818',
|
||||
base01 = '#282828',
|
||||
base02 = '#323232',
|
||||
base03 = '#646464',
|
||||
base04 = '#95a99f',
|
||||
base05 = '#e4e4ef',
|
||||
base06 = '#e4e4ef',
|
||||
base07 = '#e4e4ef',
|
||||
base08 = '#f43841',
|
||||
base09 = '#9e95c7',
|
||||
base0A = '#96a6c8',
|
||||
base0B = '#f43841',
|
||||
base0C = '#a596e9',
|
||||
base0D = '#f8868c',
|
||||
base0E = '#96b0e9',
|
||||
base0F = '#becff4',
|
||||
})
|
||||
|
||||
local hi = function(group, opts)
|
||||
vim.api.nvim_set_hl(0, group, opts)
|
||||
end
|
||||
|
||||
-- telescope.nvim
|
||||
hi('TelescopeNormal', { fg = '#e4e4ef', bg = '#181818' })
|
||||
hi('TelescopeBorder', { fg = '#646464', bg = '#181818' })
|
||||
hi('TelescopePromptNormal', { fg = '#e4e4ef', bg = '#181818' })
|
||||
hi('TelescopePromptBorder', { fg = '#646464', bg = '#181818' })
|
||||
hi('TelescopePromptPrefix', { fg = '#f43841', bg = '#181818' })
|
||||
hi('TelescopePromptCounter', { fg = '#95a99f', bg = '#181818' })
|
||||
hi('TelescopePromptTitle', { fg = '#181818', bg = '#f43841' })
|
||||
hi('TelescopePreviewTitle', { fg = '#181818', bg = '#96a6c8' })
|
||||
hi('TelescopeResultsTitle', { fg = '#181818', bg = '#9e95c7' })
|
||||
hi('TelescopeSelection', { fg = '#e4e4ef', bg = '#323232' })
|
||||
hi('TelescopeSelectionCaret', { fg = '#f43841', bg = '#323232' })
|
||||
hi('TelescopeMatching', { fg = '#f43841', bold = true })
|
||||
|
||||
-- mini.pick
|
||||
hi('MiniPickNormal', { fg = '#e4e4ef', bg = '#181818' })
|
||||
hi('MiniPickBorder', { fg = '#646464', bg = '#181818' })
|
||||
hi('MiniPickPrompt', { fg = '#e4e4ef', bg = '#181818' })
|
||||
hi('MiniPickPromptPrefix', { fg = '#f43841', bg = '#181818' })
|
||||
hi('MiniPickBorderText', { fg = '#181818', bg = '#f43841' })
|
||||
hi('MiniPickMatchCurrent', { fg = '#e4e4ef', bg = '#323232' })
|
||||
hi('MiniPickPromptCaret', { fg = '#f43841', bg = '#323232' })
|
||||
hi('MiniPickMatchRanges', { fg = '#f43841', bold = true })
|
||||
end
|
||||
|
||||
-- Register a signal handler for SIGUSR1 (matugen updates).
|
||||
-- The handler re-requires this module, which re-runs the code below, so the
|
||||
-- previous handle is stopped first; otherwise handlers double on every signal.
|
||||
if _G.__matugen_signal then
|
||||
_G.__matugen_signal:stop()
|
||||
_G.__matugen_signal:close()
|
||||
end
|
||||
|
||||
local signal = vim.uv.new_signal()
|
||||
_G.__matugen_signal = signal
|
||||
signal:start(
|
||||
'sigusr1',
|
||||
vim.schedule_wrap(function()
|
||||
package.loaded['matugen'] = nil
|
||||
require('matugen').setup()
|
||||
end)
|
||||
)
|
||||
|
||||
return M
|
||||
@@ -0,0 +1,197 @@
|
||||
-- since this is just an example spec, don't actually load anything here and return an empty spec
|
||||
-- stylua: ignore
|
||||
if true then return {} end
|
||||
|
||||
-- every spec file under the "plugins" directory will be loaded automatically by lazy.nvim
|
||||
--
|
||||
-- In your plugin files, you can:
|
||||
-- * add extra plugins
|
||||
-- * disable/enabled LazyVim plugins
|
||||
-- * override the configuration of LazyVim plugins
|
||||
return {
|
||||
-- add gruvbox
|
||||
{ "ellisonleao/gruvbox.nvim" },
|
||||
|
||||
-- Configure LazyVim to load gruvbox
|
||||
{
|
||||
"LazyVim/LazyVim",
|
||||
opts = {
|
||||
colorscheme = "gruvbox",
|
||||
},
|
||||
},
|
||||
|
||||
-- change trouble config
|
||||
{
|
||||
"folke/trouble.nvim",
|
||||
-- opts will be merged with the parent spec
|
||||
opts = { use_diagnostic_signs = true },
|
||||
},
|
||||
|
||||
-- disable trouble
|
||||
{ "folke/trouble.nvim", enabled = false },
|
||||
|
||||
-- override nvim-cmp and add cmp-emoji
|
||||
{
|
||||
"hrsh7th/nvim-cmp",
|
||||
dependencies = { "hrsh7th/cmp-emoji" },
|
||||
---@param opts cmp.ConfigSchema
|
||||
opts = function(_, opts)
|
||||
table.insert(opts.sources, { name = "emoji" })
|
||||
end,
|
||||
},
|
||||
|
||||
-- change some telescope options and a keymap to browse plugin files
|
||||
{
|
||||
"nvim-telescope/telescope.nvim",
|
||||
keys = {
|
||||
-- add a keymap to browse plugin files
|
||||
-- stylua: ignore
|
||||
{
|
||||
"<leader>fp",
|
||||
function() require("telescope.builtin").find_files({ cwd = require("lazy.core.config").options.root }) end,
|
||||
desc = "Find Plugin File",
|
||||
},
|
||||
},
|
||||
-- change some options
|
||||
opts = {
|
||||
defaults = {
|
||||
layout_strategy = "horizontal",
|
||||
layout_config = { prompt_position = "top" },
|
||||
sorting_strategy = "ascending",
|
||||
winblend = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- add pyright to lspconfig
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
---@class PluginLspOpts
|
||||
opts = {
|
||||
---@type lspconfig.options
|
||||
servers = {
|
||||
-- pyright will be automatically installed with mason and loaded with lspconfig
|
||||
pyright = {},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- add tsserver and setup with typescript.nvim instead of lspconfig
|
||||
{
|
||||
"neovim/nvim-lspconfig",
|
||||
dependencies = {
|
||||
"jose-elias-alvarez/typescript.nvim",
|
||||
init = function()
|
||||
require("lazyvim.util").lsp.on_attach(function(_, buffer)
|
||||
-- stylua: ignore
|
||||
vim.keymap.set( "n", "<leader>co", "TypescriptOrganizeImports", { buffer = buffer, desc = "Organize Imports" })
|
||||
vim.keymap.set("n", "<leader>cR", "TypescriptRenameFile", { desc = "Rename File", buffer = buffer })
|
||||
end)
|
||||
end,
|
||||
},
|
||||
---@class PluginLspOpts
|
||||
opts = {
|
||||
---@type lspconfig.options
|
||||
servers = {
|
||||
-- tsserver will be automatically installed with mason and loaded with lspconfig
|
||||
tsserver = {},
|
||||
},
|
||||
-- you can do any additional lsp server setup here
|
||||
-- return true if you don't want this server to be setup with lspconfig
|
||||
---@type table<string, fun(server:string, opts:_.lspconfig.options):boolean?>
|
||||
setup = {
|
||||
-- example to setup with typescript.nvim
|
||||
tsserver = function(_, opts)
|
||||
require("typescript").setup({ server = opts })
|
||||
return true
|
||||
end,
|
||||
-- Specify * to use this function as a fallback for any server
|
||||
-- ["*"] = function(server, opts) end,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- for typescript, LazyVim also includes extra specs to properly setup lspconfig,
|
||||
-- treesitter, mason and typescript.nvim. So instead of the above, you can use:
|
||||
{ import = "lazyvim.plugins.extras.lang.typescript" },
|
||||
|
||||
-- add more treesitter parsers
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
opts = {
|
||||
ensure_installed = {
|
||||
"bash",
|
||||
"html",
|
||||
"javascript",
|
||||
"json",
|
||||
"lua",
|
||||
"markdown",
|
||||
"markdown_inline",
|
||||
"python",
|
||||
"query",
|
||||
"regex",
|
||||
"tsx",
|
||||
"typescript",
|
||||
"vim",
|
||||
"yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
-- since `vim.tbl_deep_extend`, can only merge tables and not lists, the code above
|
||||
-- would overwrite `ensure_installed` with the new value.
|
||||
-- If you'd rather extend the default config, use the code below instead:
|
||||
{
|
||||
"nvim-treesitter/nvim-treesitter",
|
||||
opts = function(_, opts)
|
||||
-- add tsx and treesitter
|
||||
vim.list_extend(opts.ensure_installed, {
|
||||
"tsx",
|
||||
"typescript",
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- the opts function can also be used to change the default opts:
|
||||
{
|
||||
"nvim-lualine/lualine.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = function(_, opts)
|
||||
table.insert(opts.sections.lualine_x, {
|
||||
function()
|
||||
return "😄"
|
||||
end,
|
||||
})
|
||||
end,
|
||||
},
|
||||
|
||||
-- or you can return new options to override all the defaults
|
||||
{
|
||||
"nvim-lualine/lualine.nvim",
|
||||
event = "VeryLazy",
|
||||
opts = function()
|
||||
return {
|
||||
--[[add your custom lualine config here]]
|
||||
}
|
||||
end,
|
||||
},
|
||||
|
||||
-- use mini.starter instead of alpha
|
||||
{ import = "lazyvim.plugins.extras.ui.mini-starter" },
|
||||
|
||||
-- add jsonls and schemastore packages, and setup treesitter for json, json5 and jsonc
|
||||
{ import = "lazyvim.plugins.extras.lang.json" },
|
||||
|
||||
-- add any tools you want to have installed below
|
||||
{
|
||||
"williamboman/mason.nvim",
|
||||
opts = {
|
||||
ensure_installed = {
|
||||
"stylua",
|
||||
"shellcheck",
|
||||
"shfmt",
|
||||
"flake8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
-- Applies the hand-kept wallpaper palette (lua/matugen.lua) on top of LazyVim's
|
||||
-- colorscheme instead of living with tokyonight defaults.
|
||||
--
|
||||
-- base16-colorscheme writes highlights directly and never touches v:colors_name,
|
||||
-- so LazyVim keeps thinking tokyonight is loaded and its plugin-specific tweaks
|
||||
-- still run; ours is the last word on the UI groups.
|
||||
return {
|
||||
"RRethy/base16-nvim",
|
||||
lazy = false,
|
||||
priority = 900,
|
||||
config = function()
|
||||
-- LazyVim loads its colorscheme after plugin configs, so re-apply on every
|
||||
-- ColorScheme event: that also makes `:colorscheme foo` land on our palette.
|
||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||
desc = "Re-apply the matugen base16 palette after any colorscheme",
|
||||
callback = function()
|
||||
require("matugen").setup()
|
||||
end,
|
||||
})
|
||||
require("matugen").setup()
|
||||
end,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
column_width = 120
|
||||
@@ -275,13 +275,13 @@ transition = [ "fade" ]
|
||||
interval_seconds = 1200
|
||||
|
||||
[wallpaper.default]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9w8r5.jpg"
|
||||
|
||||
[wallpaper.last]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9w8r5.jpg"
|
||||
|
||||
[wallpaper.monitors.DP-1]
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9w8r5.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_nzz3gy.jpg"
|
||||
path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9w8r5.jpg"
|
||||
|
||||
[weather]
|
||||
unit = "imperial"
|
||||
|
||||
@@ -4,3 +4,8 @@ source /usr/share/cachyos-zsh-config/cachyos-config.zsh
|
||||
[ -f ~/.config/secrets/hf_token ] && export HF_TOKEN="$(cat ~/.config/secrets/hf_token)"
|
||||
|
||||
[ -d "$HOME/.bun/bin" ] && export PATH="$HOME/.bun/bin:$PATH"
|
||||
|
||||
# LazyVim lives in its own NVIM_APPNAME profile (~/.config/lazyvim), so plain
|
||||
# `nvim` stays a vanilla quick-edit editor. NVIM_APPNAME swaps config, data,
|
||||
# state and cache dirs wholesale — no shared plugin tree between the two.
|
||||
lazyvim() { NVIM_APPNAME=lazyvim nvim "$@"; }
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
Agentic web research means that an AI drives the search loop. The agent formulates queries, reads results, decides what to read next, and writes a synthesis. It works best when search, extraction, and reasoning each run in the right place.
|
||||
|
||||
> **Your setup:** Pi Web Access calls SearXNG at `192.168.0.143:8081` (dankclaw) and serves models through llama.cpp at `192.168.0.235:7770`, `192.168.0.143:7770`, and `localhost:8080`. The pages below assume that topology.
|
||||
> **Fleet topology (2026-10):** SearXNG lives at `192.168.0.143:8081` (UI) /
|
||||
> `:8082` (JSON) on dankclaw; model endpoints are `frank-archon`
|
||||
> (dankserver :7770, radiance), `frank-dragoon` (dankclaw :7770,
|
||||
> halogen-flash-server), `frank-zealot` (dankclaw :7771, llama.cpp PrismML).
|
||||
> The pi-era `localhost:8080` llama.cpp endpoint is retired. See
|
||||
> [System hosts](/system/index.md).
|
||||
|
||||
This section connects four decisions:
|
||||
|
||||
|
||||
@@ -32,9 +32,15 @@ Qwen3 is the current state of the art for open function calling and tool use. It
|
||||
|
||||
The 8B and 14B models run on one consumer GPU. The 30B-A3B MoE runs on a single A100-class card or equivalent.
|
||||
|
||||
## Best Vision Model: Qwen2.5-VL-7B
|
||||
## Best Vision Model: Qwen3-VL (Apache 2.0)
|
||||
|
||||
Many web tasks need a model that can read a page image, not just text. Qwen2.5-VL-7B is the best open vision model for this. It reads text, charts, icons, and layout in screenshots. It supports computer-use and phone-use agents. Apache 2.0 license. The 7B model fits on a single GPU with 8 GB or more.
|
||||
Many web tasks need a model that can read a page image, not just text.
|
||||
**Qwen3-VL** supersedes Qwen2.5-VL as the strongest open-weights vision family
|
||||
(4B/8B dense through 30B-A3B/235B-A22B MoE): text, chart, icon, and layout
|
||||
reading in screenshots, plus computer-use agent support. Small dense sizes
|
||||
ship Apache 2.0; a quantized 4B/8B runs on a single consumer GPU. On this
|
||||
fleet, vision duty is carried by the mmproj vision towers on the endpoints
|
||||
(dragoon, zealot) — see [System hosts](/system/index.md).
|
||||
|
||||
Llama 4 Scout is the larger multimodal option. Verify the claims before you trust them:
|
||||
|
||||
@@ -47,7 +53,7 @@ Llama 4 Scout is the larger multimodal option. Verify the claims before you trus
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Consumer GPU 16-24GB] --> B[Qwen3-8B / 14B]
|
||||
A --> C[Qwen2.5-VL-7B]
|
||||
A --> C[Qwen3-VL-4B / 8B]
|
||||
D[Single server GPU 80GB] --> E[Qwen3-30B-A3B]
|
||||
D --> F[Llama 4 Scout INT4]
|
||||
G[Multi-GPU cluster] --> H[Qwen3-235B-A22B]
|
||||
@@ -71,7 +77,7 @@ llama-server -m qwen3-8b-q4_k_m.gguf -c 131072 --port 7770
|
||||
| Need | Pick |
|
||||
|------|------|
|
||||
| Best tool calling, one consumer GPU | Qwen3-8B or 14B |
|
||||
| Visually read a web page | Qwen2.5-VL-7B |
|
||||
| Visually read a web page | Qwen3-VL-4B / 8B |
|
||||
| Server-scale reliable agent | Qwen3-235B-A22B |
|
||||
| Cheapest acceptable agent | Qwen3-8B on a mid GPU |
|
||||
|
||||
@@ -79,7 +85,8 @@ llama-server -m qwen3-8b-q4_k_m.gguf -c 131072 --port 7770
|
||||
|
||||
- Qwen3 technical report: <https://qwenlm.github.io/blog/qwen3/>
|
||||
- Qwen3 repository: <https://github.com/QwenLM/Qwen3>
|
||||
- Qwen2.5-VL-7B model card: <https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct>
|
||||
- Qwen3-VL repository: <https://github.com/QwenLM/Qwen3-VL> (tech report: <https://arxiv.org/abs/2511.21631>)
|
||||
- Qwen2.5-VL-7B model card (predecessor): <https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct>
|
||||
- Meta AI Llama 4 announcement: <https://ai.meta.com/blog/llama-4-multimodal-intelligence/>
|
||||
- Ollama library: <https://ollama.com/library>
|
||||
- Browser Use supported models: <https://docs.browser-use.com/open-source/supported-models>
|
||||
|
||||
@@ -8,18 +8,41 @@ tags:
|
||||
- privacy
|
||||
- configuration
|
||||
- unverified
|
||||
verified: 2026-08-28
|
||||
verified: 2026-10-19
|
||||
timestamp: 2026-08-11
|
||||
resource: https://docs.searxng.org
|
||||
---
|
||||
|
||||
# SearXNG Tuning
|
||||
|
||||
SearXNG is a metasearch engine. It aggregates 274 or more upstream search services into one result set. Configuration lives in `settings.yml`. The recommended deployment is Docker Compose with a Valkey container.
|
||||
SearXNG is a metasearch engine. It aggregates hundreds of upstream search
|
||||
services into one result set (upstream `settings.yml` defines 388 engine
|
||||
entries at master, probed 2026-10-19; the live fleet instance loads 262).
|
||||
Configuration lives in `settings.yml`. The recommended deployment is Docker
|
||||
Compose (or Podman Quadlet) with a Valkey container.
|
||||
|
||||
This page lists the settings that matter for speed, privacy, and useful results.
|
||||
|
||||
> **Your setup:** Pi Web Access calls a remote SearXNG at [`192.168.0.143:8081`](../pi/packages/pi-web-access.md) (dankclaw). Apply these settings to that host, not to this machine.
|
||||
> **Fleet instance:** the harness `web/searxng` provider calls the instance at
|
||||
> `192.168.0.143:8081` (UI) / `:8082` (JSON API) on dankclaw. The pi-era
|
||||
> [Pi Web Access](../pi/packages/pi-web-access.md) called the same host.
|
||||
|
||||
## Live instance (probed 2026-10-19)
|
||||
|
||||
User Quadlet stack on dankclaw: `searxng.container`
|
||||
(`ghcr.io/searxng/searxng:latest`) + `searxng-valkey.container`
|
||||
(`docker.io/valkey/valkey:9-alpine`) + `gluetun.container` (VPN egress; the
|
||||
containers share its network namespace, which is why `podman ps` shows :8081/
|
||||
:8082 on several names) + `marreta`/`marreta_browser`. `limiter.toml`: enabled,
|
||||
`pass_searxng_org: true`.
|
||||
|
||||
**Policy drift flag:** this page's tuned engine policy (google and bing
|
||||
disabled; DuckDuckGo/Wikipedia/Google News enabled — verified via `/config` on
|
||||
2026-08-16) is NOT live: `/config` on 2026-10-19 reports all 262 engines
|
||||
enabled, google and bing included. Either the settings override was lost in
|
||||
the 2026-10 stack reinstatement or the policy was deliberately dropped.
|
||||
Confirm with Frank before re-applying.
|
||||
|
||||
|
||||
## Plan the Deployment
|
||||
|
||||
|
||||
@@ -29,10 +29,17 @@ Key ideas:
|
||||
- Ten watchdogs handle CAPTCHAs, crashes, popups, downloads, and security.
|
||||
- Real browser profiles carry saved logins.
|
||||
|
||||
**On the "87.4 percent" number:** that result refers to Browser Use's managed Cloud agent (the Hybrid type that blends structured browser tools with screenshots). Peer-reviewed results for vision-only (CUA) models are much lower, about 44.5 percent on the same task type. Treat any single accuracy number as one benchmark, not a universal score.
|
||||
**On the "87.4 percent" number:** that result refers to Browser Use's managed
|
||||
Cloud agent (the Hybrid type that blends structured browser tools with
|
||||
screenshots), not the open-source library you self-host. Academic
|
||||
computer-use results on comparable web tasks run far lower, and an earlier
|
||||
"44.5 percent peer-reviewed CUA" figure carried in this page could not be
|
||||
re-attributed to a specific published benchmark (checked 2026-10-19) and was
|
||||
dropped. Treat any single accuracy number as one benchmark, not a universal
|
||||
score.
|
||||
|
||||
```python
|
||||
# Local model via llama.cpp (OpenAI-compatible endpoint)
|
||||
# Local model via any OpenAI-compatible endpoint
|
||||
from browser_use import Agent
|
||||
from browser_use.llm.openai import ChatOpenAI
|
||||
|
||||
@@ -40,7 +47,7 @@ agent = Agent(
|
||||
task="Search for the latest AI news",
|
||||
llm=ChatOpenAI(
|
||||
base_url="http://192.168.0.235:7770/v1",
|
||||
model="frank-default-small",
|
||||
model="frank-archon",
|
||||
api_key="EMPTY",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -171,8 +171,14 @@ This pattern places the whole SearXNG process inside the tunnel namespace. The h
|
||||
4. Confirm that unrelated host traffic keeps the host IP.
|
||||
|
||||
```bash
|
||||
# From inside the tunnel with Gluetun
|
||||
docker exec gluetun curl -s ifconfig.me
|
||||
# Gluetun ships no curl; use its own endpoints or a throwaway container.
|
||||
podman exec gluetun sh -c 'test -e /sys/class/net/tun0 && echo tunnel-up'
|
||||
podman exec gluetun sh -c 'wget -qO- 127.0.0.1:9999/health' # "OK" when up
|
||||
# NOTE: :9999 is Gluetun's HTTP health server (200 "OK" / 500); :8000 is the
|
||||
# CONTROL server (/v1/* API), which 404s on everything else. Do not health-
|
||||
# probe :8000. Egress-IP check needs a real binary — run a companion
|
||||
# container on gluetun's network: docker run --rm --net container:gluetun
|
||||
# curlimages/curl -s ifconfig.me
|
||||
```
|
||||
|
||||
## Citations
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
|
||||
Caddy is the reverse proxy and TLS terminator for the homelab. A single caddy
|
||||
container on dankclaw (192.168.0.143) fronts every service on both hosts. It
|
||||
runs Caddy v2.11.4 from the custom `franksdank/caddy-porkbun` image
|
||||
(xcaddy-built with the Porkbun DNS-01 module, built locally on dankclaw).
|
||||
runs Caddy v2.11.7 (verified in-container 2026-10-19) from the custom
|
||||
`localhost/franksdank/caddy-porkbun:latest` image (xcaddy-built with the
|
||||
Porkbun DNS-01 module, built locally on dankclaw).
|
||||
Since 2026-08-26 it is managed as a Podman Quadlet unit (`caddy.container`)
|
||||
installed to `~/.config/containers/systemd/`, providing boot-persistent,
|
||||
auto-restart service management.
|
||||
|
||||
* [[caddyfile|caddyfile]] — directive and matcher syntax, named matchers,
|
||||
directive sorting, and the `handle`/`route` order rule.
|
||||
|
||||
The Caddyfile lives in the serverAppConfigs repo at
|
||||
`dankclaw/Caddyfile`. `deploy.sh` renders basicauth hashes from the host `.env`
|
||||
@@ -27,4 +26,4 @@ resolves `*.franksdank.cloud` names to dankclaw.
|
||||
|
||||
The porkbun DNS module source: [caddy-dns/porkbun](https://github.com/caddy-dns/porkbun).
|
||||
|
||||
* [Caddyfile Syntax](caddyfile.md) — Caddy Caddyfile reference — directive and matcher syntax, named matchers, directive sorting, and the handle/route order rule. Grounded in caddyserver.com (fetched 2026-08-28).
|
||||
* [Caddyfile Syntax](caddyfile.md) — Caddy Caddyfile reference — directive and matcher syntax, named matchers, directive sorting, and the `handle`/`route` order rule. Grounded in caddyserver.com (fetched 2026-08-28).
|
||||
|
||||
+71
-202
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: reference
|
||||
title: dankvoice
|
||||
description: omp extension that speaks assistant output with the fleet's cloned voices through frank-tts.
|
||||
description: Voice output ships as the dank/dankvoice package; this page keeps only the fleet integration facts and the cutover procedure.
|
||||
tags:
|
||||
- omp
|
||||
- extension
|
||||
@@ -15,226 +15,95 @@ timestamp: 2026-10-19
|
||||
|
||||
# dankvoice
|
||||
|
||||
`agent/extensions/dankvoice.ts` adds cloned-voice speech to the interactive
|
||||
harness: `/say` opens the options menu, `/say <text>` speaks through the
|
||||
speakers and `/say on` narrates the assistant's thinking and final answer
|
||||
after every turn. The words are first rewritten into natural spoken prose by
|
||||
the **@tiny** role model (exactly what the built-in vocalizer's
|
||||
`speech.enhanced` does), and everything is served by **frank-tts**
|
||||
(Dankclaw :7772, the `speech` model role in [agent/models.yml](/core/index.md)).
|
||||
Voice output lives in the **`dank/dankvoice` package**:
|
||||
`pi install git:http://192.168.0.143:3000/dank/dankvoice.git`. This page owns
|
||||
only fleet integration and the cutover. The package README
|
||||
(<http://192.168.0.143:3000/dank/dankvoice>) owns the `/say` command
|
||||
reference, the settings/env knob list, the segmentation state machine, the
|
||||
enhancer port, and mood control — never duplicate those facts here.
|
||||
|
||||
## Why it exists
|
||||
## Fleet wiring
|
||||
|
||||
Nothing built into the harness can pronounce Frank's cloned voices.
|
||||
* **TTS endpoint** — resolved from the provider block whose model row carries
|
||||
`api: openai-speech` in [agent/models.yml](/core/index.md):
|
||||
**frank-tts** on Dankclaw `:7772`. LAN-only — no Caddy vhost fronts it.
|
||||
* **Narration humanizer** — the harness `@tiny` role
|
||||
(`modelRoles.tiny` in `agent/config.yml`), on this fleet **frank-zealot**
|
||||
(Dankclaw `:7771`).
|
||||
* **Hybrid-endpoint trap (load-bearing)** — a raw `fetch` to a
|
||||
thinking-by-default model spends the token budget on `reasoning_content`
|
||||
and answers `content: ""`. The package pins
|
||||
`chat_template_kwargs: { enable_thinking: false }` on the rewrite call; do
|
||||
not remove it. On a hybrid endpoint, empty content beside non-empty
|
||||
`reasoning_content` means the flag was ignored — that is a failed rewrite
|
||||
(fall back to the mechanical text), never the legitimate "nothing to say".
|
||||
* **Voice contract** — omitting `voice` is legal: frank-tts fills its
|
||||
`DEFAULT_VOICE` (2026-10-18 voice-pack work). `GET {base}/v1/audio/voices`
|
||||
answers a bare JSON array; an unknown voice answers 400 with
|
||||
`available_voices`, which the package uses as roster fallback. On this shim
|
||||
`GET /v1/voices` and `GET /v1/models` are 404.
|
||||
|
||||
| Surface | Engine | Verdict |
|
||||
|---|---|---|
|
||||
| TUI speak-aloud (`speech.enabled`, `speech.voice`) | bundled Kokoro ONNX worker, `synthesizeStream(voice, speed, signal)` | Kokoro voice enum only; never consults `models.yml` or the speech role |
|
||||
| `omp say [TEXT]` | same local backend (`--model` = *local* model key) | `omp say --voice narrator1 "test"` → `error: Expected --voice to be one of: af_heart, af_bella, af_nicole, af_kore, af_sarah, am_michael, am_fenrir, am_puck, bf_emma, bm_george, bm_fable` (verified 2026-10-18) |
|
||||
| `tts` tool / `xd://tts` device (`modelRoles.speech`) | frank-tts over OpenAI `/v1/audio/speech` | cloned voices work, but only as a **file** — nothing plays them |
|
||||
## Cutover (Refs #34)
|
||||
|
||||
`dankvoice` is not a patch to that vocalizer (harness code, not ours); it is a
|
||||
second transport that happens to speak, so Kokoro stays available for quick
|
||||
local speech and the cloned voices carry the real narration.
|
||||
The `agent/extensions/dankvoice.ts` drop-in and its 26-test bats suite are
|
||||
retired here (the package suite is a strict superset; test names ported 1:1).
|
||||
Per box:
|
||||
|
||||
## Commands
|
||||
1. `pi install git:http://192.168.0.143:3000/dank/dankvoice.git`
|
||||
2. `/say status`, then "Speak a test phrase" from the `/say` menu — the
|
||||
audible proof a silent session needs.
|
||||
3. Pull `main` (the drop-in disappears with it) and restart the session.
|
||||
|
||||
| Command | Effect |
|
||||
|---|---|
|
||||
| `/say` \| `/say menu` | options menu (`ctx.ui.select`): auto-speak toggle, voice, output device, player, spoken cap, thinking-narration toggle, humanize toggle, test phrase |
|
||||
| `/say <text>` | synthesize once and play; interrupts whatever is playing |
|
||||
| `/say on` \| `/say off` | arm/disarm auto-speak of the thinking blocks and final text at `agent_end`; the footer shows `🔊 <voice>` while armed |
|
||||
| `/say voice <name>` | pick a voice; an empty name defers to the server's own default |
|
||||
| `/say voices` | list what frank-tts reports |
|
||||
| `/say stop` | cut the current utterance |
|
||||
| `/say status` \| `/say help` | endpoint, voice, player, device, cap, thinking, humanize |
|
||||
Menu choices survive the cutover: both transports persist to the same
|
||||
gitignored settings file, `~/.omp/cache/dankvoice.json`
|
||||
(`DANKVOICE_CONFIG` relocates it).
|
||||
|
||||
Menu choices persist to `~/.omp/cache/dankvoice.json` (runtime state, never
|
||||
tracked); the environment overrides the file, the file overrides defaults.
|
||||
"Speak a test phrase" synthesizes a short line through the current voice,
|
||||
player and device — the audible proof whenever a session "has say on" but
|
||||
stays silent.
|
||||
## Why not the built-in vocalizer
|
||||
|
||||
Auto-speak is skipped in `print`/`json` mode so benches and pipelines stay
|
||||
silent. Each spoken unit — thinking first when narrated, then the answer —
|
||||
is first rewritten into spoken prose by the @tiny model; when the enhancer
|
||||
(below) declines, the text goes to segmentation as-is, where fenced code and
|
||||
tables vanish, links collapse to their label and bullets and table pipes
|
||||
disappear. A long answer is never one monolithic synthesis request; see
|
||||
[Segmentation](#segmentation) for how utterances are cut and played.
|
||||
The harness speak-aloud path (`speech.enabled` / `speech.voice`, `omp say`)
|
||||
synthesizes with bundled Kokoro ONNX against a **compile-time voice enum** —
|
||||
cloned voices can never reach it, and no setting routes it to frank-tts.
|
||||
`dankvoice` is a second transport beside it, not a patch: Kokoro stays for
|
||||
quick local speech, the package carries cloned-voice narration. The `tts`
|
||||
tool / `xd://tts` device reach frank-tts too, but produce files, not audio
|
||||
playback.
|
||||
|
||||
## Segmentation
|
||||
## Arming auto-speak
|
||||
|
||||
Utterances are cut by a state machine ported from the harness's own
|
||||
speak-aloud vocalizer (the minified `fHe` class in the agent bundle's
|
||||
`dist/cli.js`), kept deliberately in lockstep with the stock path:
|
||||
Arming is **session-scoped by design**: `/say on` arms the running session and
|
||||
is deliberately never persisted. A session that starts silent is a config
|
||||
state, not a fault — set `"auto": true` in `~/.omp/cache/dankvoice.json` (this
|
||||
fleet does) or export `DANKVOICE_AUTO=1` to start armed. Editing the settings
|
||||
file mid-session does nothing; the plugin reads it at startup.
|
||||
|
||||
* A strong boundary is a run of `[.!?…]` followed by whitespace — so
|
||||
`!!!!!` and `...` are one boundary, never a pile of cuts.
|
||||
* Boundaries after `e.g.`, `etc.`, `Mr.` and friends, or inside inline
|
||||
code, don't count; decimals (`3.5`, `1,5`) survive because a boundary
|
||||
requires trailing whitespace.
|
||||
* Line starts are classified: table rows and fenced code are swallowed
|
||||
whole (their content is never read aloud), heading and bullet markers
|
||||
vanish, ordered-list markers speak their number ("1, …"), quote markers
|
||||
strip.
|
||||
* Per segment, markdown is cleaned: links collapse to their label, URLs
|
||||
to their host, deep paths to their last segment; emphasis markup dies.
|
||||
* Segments aim for one sentence; run-ons break at commas or word wraps
|
||||
before 280 characters.
|
||||
|
||||
Playback is strictly sequential: segment N+1 is synthesized only after
|
||||
segment N's player process exited, so audio never stacks. The chain runs
|
||||
detached from `agent_end` (fire-and-forget) and may legitimately outlive
|
||||
the harness's 30 s handler timeout — the old awaiting design produced a
|
||||
"handler timed out after 30000ms" toast on long answers. A new utterance,
|
||||
`/say stop`, or disarming auto-speak retires the live chain through a run
|
||||
token: the current player is killed and pending segments are skipped.
|
||||
`DANKVOICE_MAX` is a per-answer character budget: the leading whole
|
||||
segments that fit are spoken, the rest are dropped — the thinking unit
|
||||
draws on it before the answer does.
|
||||
|
||||
## Endpoint resolution
|
||||
|
||||
The base URL is **read from `agent/models.yml`**, from the provider block whose
|
||||
model row carries `api: openai-speech` — the same row the `speech` role
|
||||
resolves, so no host address and no credential appears in this file. From
|
||||
`baseUrl: http://192.168.0.143:7772/v1` it derives
|
||||
`POST …/v1/audio/speech`, `GET …/v1/audio/voices` and `GET …/health`.
|
||||
|
||||
| Environment | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `DANKVOICE_URL` | models.yml | speech base URL (`…/v1`), bypasses the YAML read |
|
||||
| `DANKVOICE_MODEL` | the id in that block (`frank-tts`) | model named in the request body |
|
||||
| `DANKVOICE_CONFIG` | `~/.omp/cache/dankvoice.json` | persisted menu choices (voice, player, sink, cap, auto) |
|
||||
| `DANKVOICE_VOICE` | empty (server default) | default voice name |
|
||||
| `DANKVOICE_AUTO=1` | off | start with auto-speak armed |
|
||||
| `DANKVOICE_MAX` | `700` | spoken-character budget per answer (whole leading segments, shared by the thinking and answer units) |
|
||||
| `DANKVOICE_PLAYER` | detect | player binary, skipping detection |
|
||||
| `DANKVOICE_MODELS` | `~/.omp/agent/models.yml` | YAML to read the endpoint from |
|
||||
| `DANKVOICE_REWRITE_URL` | the @tiny role | chat base URL (`…/v1`) for the enhancer, bypassing role resolution |
|
||||
| `DANKVOICE_REWRITE_MODEL` | the @tiny role's model | chat model named in the rewrite body |
|
||||
| `DANKVOICE_REWRITE=0` | enhancer on when a route resolves | speak mechanical text |
|
||||
| `DANKVOICE_THINKING` | settings file, default on | `0`/`1` force thinking narration off/on |
|
||||
| `DANKVOICE_OMPCONFIG` | `~/.omp/agent/config.yml` | YAML to read the `modelRoles.tiny` role from |
|
||||
|
||||
Player detection order is `pw-play` → `paplay` → `ffplay` (PipeWire first:
|
||||
the workstations run WirePlumber). A saved output device routes the player
|
||||
explicitly — `pw-play --target <sink>` or `paplay --device=<sink>`; ffplay
|
||||
has no device concept and ignores it — while an unset device leaves the
|
||||
player's own default. Sinks are enumerated with `wpctl list audio sinks`;
|
||||
if wireplumber is unreachable the menu offers only "system default". Each
|
||||
utterance is written to `$TMPDIR/dankvoice-*/say-<ms>.wav` and the file plus
|
||||
its directory are removed when the player process exits.
|
||||
|
||||
## Humanized narration (the @tiny role)
|
||||
|
||||
The built-in vocalizer never reads answers aloud verbatim when
|
||||
`speech.enhanced` is on: a small model rewrites each utterance into words a
|
||||
person would say. `dankvoice` ports that enhancer — same system prompt
|
||||
(verbatim from the bundle), same budgets (1536 max tokens, 6 s timeout,
|
||||
4000-char input window), same contract (a failed rewrite falls back to the
|
||||
mechanically cleaned text; an empty rewrite skips the unit as "nothing to
|
||||
say"). The target model is the harness's `@tiny` role, resolved the way the
|
||||
harness resolves it: `modelRoles.tiny` in `agent/config.yml` reads
|
||||
`provider (host)/model:effort`; the provider block in `agent/models.yml`
|
||||
supplies the `baseUrl`; the request is `POST {base}/chat/completions`. On
|
||||
this fleet that is **frank-zealot** (`llamacpp (dankclaw-3090)`,
|
||||
`:7771`) — the 6 s abort keeps a slow tiny model off the critical path.
|
||||
|
||||
Thinking blocks ride the same path: at `agent_end` the last assistant
|
||||
message's true `thinking` parts are narrated (rewritten first, as their own
|
||||
unit, before the answer), while blocks flagged `narration: true` — which
|
||||
providers use to address the user through the thinking channel — count as
|
||||
answer text. The menu, `/say status`, and `DANKVOICE_THINKING` toggle it;
|
||||
the choice persists in the settings file.
|
||||
|
||||
## Verified facts (2026-10-18, extended 2026-10-19)
|
||||
|
||||
* **Extension discovery** — any `.ts` file in `~/.omp/agent/extensions/` loads
|
||||
at startup: a probe file there printed `loaded 2026-10-19T02:36:55Z` from a
|
||||
fresh `omp -p` run. `omp --help` documents `--no-extensions` (discovery off,
|
||||
explicit `-e/--extension` and `--hook` still load) and `plugin install|link`.
|
||||
* **Endpoint** — resolving the live `agent/models.yml` yields
|
||||
`speechUrl http://192.168.0.143:7772/v1/audio/speech`,
|
||||
`voicesUrl …/v1/audio/voices`, `healthUrl …/health`, `model frank-tts`.
|
||||
* **Roster** — `GET /v1/audio/voices` answers the bare JSON array
|
||||
`["narrator1","narrator2","narrator3"]`; `/health` answers
|
||||
`{"status":"ok","backend":"omni-http","voices":[…]}`. `GET /v1/voices` and
|
||||
`GET /v1/models` are **404** on this shim, and an unknown voice answers
|
||||
`400 unknown voice 'zzz'; available voices: …` with `available_voices` in the
|
||||
body — which is the fallback the extension uses if the roster route ever
|
||||
disappears.
|
||||
* **Omitting `voice` is legal** — frank-tts fills its `DEFAULT_VOICE` since the
|
||||
2026-10-18 voice-pack work, so an unset voice synthesizes instead of failing.
|
||||
* **Speech** — `/say "dankvoice live smoke test"` produced a 99,884 B / 2.08 s
|
||||
WAV and `/say voice narrator2` + `/say "cloned voice check"` a 69,164 B /
|
||||
1.44 s WAV (durations from `ffprobe`), each handed to the player; temp
|
||||
directories were gone afterwards.
|
||||
* **Auto-speak** — verified in a real TUI session: `/say on` armed the footer
|
||||
(`🔊 narrator1`), the next finished turn synthesized and played the answer
|
||||
(1.20 s WAV), and an unknown voice name answers with the roster instead of
|
||||
speaking. An `agent_end` carrying `willContinue` (the harness scheduled an
|
||||
auto-retry) is never narrated — only the terminal settle speaks.
|
||||
* **Menu** — verified via driver scenarios 2026-10-18 (Refs #23): the menu
|
||||
lists auto-speak/voice/device/player/cap/test-phrase; a voice chosen in the
|
||||
menu is used by later utterances and survives a fresh load via the settings
|
||||
file; a device chosen in the menu appears in the player invocation as
|
||||
`--target <sink>`.
|
||||
* **Segmented playback** — driver scenarios 2026-10-19: "First stop here.
|
||||
Second one goes!!! Really? Third ... done" produced exactly 3 sequential
|
||||
requests and 3 plays; "Model 3.5 ships today. Version 1,5 too." produced
|
||||
exactly 2 (decimals never split); the markdown fixture's fenced code and
|
||||
URL never reached the fixture endpoint; with `DANKVOICE_MAX=60` only the
|
||||
leading segment was spoken.
|
||||
* **Humanize + thinking (2026-10-19, Refs #27)** — driver scenarios cover the
|
||||
rewrite round-trip (fixture chat route), the 404 → mechanical fallback,
|
||||
thinking narrated as its own unit before the answer, `DANKVOICE_THINKING=0`
|
||||
silencing it, and `narration: true` spoken once as the answer; the endpoint
|
||||
status line shows the resolved humanize model from the @tiny role. Live
|
||||
smoke against the real services: a markdown `/say` became 3 sequential
|
||||
prose segments (mechanical cleanup of that text yields at most 2), and a
|
||||
thinking+answer `agent_end` played thinking first. 22 green in
|
||||
`tests/dankvoice.bats`.
|
||||
Two checks prove the chain, in order: `/say status` must report
|
||||
`auto-speak on` with a real endpoint (not `NO ENDPOINT`), and `pgrep -a pw-play`
|
||||
during a turn must show one player per spoken segment, `--target` set to the
|
||||
saved sink. Thinking narration rides the same arming (`thinking: true`).
|
||||
|
||||
## Limits
|
||||
|
||||
* The TUI's own speak-aloud feature still narrates in Kokoro: its voice list is
|
||||
a compile-time enum in the harness bundle, and no setting routes it to
|
||||
frank-tts. Cloned voices live only on this file-producing/speaking path and
|
||||
on the `tts` tool. See [Handy](/tools/handy.md) for the STT half.
|
||||
* `agent_end` narrates thinking blocks and the final message only — mid-turn
|
||||
tool chatter is never spoken. Thinking covers the last assistant message;
|
||||
tool-loop gaps in earlier messages are skipped by design.
|
||||
* Humanized narration is serial: audio starts only after the @tiny rewrite
|
||||
returns (≤ 6 s per unit, then frank-tts synthesis). Say `/say off`-grade
|
||||
latency is the price of prose; `DANKVOICE_REWRITE=0` trades it back for
|
||||
instant mechanical speech.
|
||||
* frank-tts is LAN-only: no Caddy vhost fronts :7772, so this extension is
|
||||
usable on the home network.
|
||||
* Deployment, packs and the voice registry are owned by the
|
||||
`serverAppConfigs` repo (`serverAppConfigs-docs/Dankclaw/Frank TTS.md`), not
|
||||
by this one.
|
||||
* Auto-speak narrates **each turn** — the assistant's prose and thinking while
|
||||
the agent is still working — plus the settled final answer, spoken once. A
|
||||
turn that lands while audio is still playing is dropped, not queued or
|
||||
interrupting; tool-only turns stay silent; `print`/`json` modes never speak,
|
||||
so benches stay quiet. Narration goes through the humanizer, so it lags its
|
||||
turn by a rewrite round trip; `/say humanize off` removes the lag.
|
||||
* Arming is read at startup only — see **Arming auto-speak** above. A session
|
||||
that never speaks is unarmed, not broken; `/say on` before debugging.
|
||||
* frank-tts deployment, voice packs and the registry are owned by the
|
||||
`serverAppConfigs` repo (`serverAppConfigs-docs/Dankclaw/Frank TTS.md`).
|
||||
|
||||
## Citations
|
||||
|
||||
* Live probes on the workstation, 2026-10-18: `omp say --voice narrator1 …`,
|
||||
`curl http://192.168.0.143:7772/health`, `/v1/audio/voices`,
|
||||
`/v1/audio/…/speech` (invalid voice), `ffprobe` on the produced WAVs.
|
||||
* `omp --help` (extension discovery flags, `say`, `plugin`) and
|
||||
`@earendil-works/pi-coding-agent` `dist/core/extensions/types.d.ts`
|
||||
(`ExtensionAPI.on/registerCommand`, `ExtensionMode = "tui" | "rpc" | "json" | "print"`).
|
||||
* The stock speak-aloud implementation — vocalizer pipeline `I6o`, utterance
|
||||
segmenter `fHe` and speech enhancer `Qyr` with its prompt `T6o` — in
|
||||
`@oh-my-pi/pi-coding-agent`'s `dist/cli.js`, read off the minified bundle
|
||||
2026-10-19: dankvoice ports the mechanical and the enhanced halves, so an
|
||||
LLM rewrite does happen before frank-tts.
|
||||
* Gitea issue #21 on `dank/command-center` (the work item this page ships with).
|
||||
* Gitea issue #23 on `dank/command-center` (the options-menu work item).
|
||||
* Gitea issue #27 on `dank/command-center` (the enhanced-narration work item).
|
||||
* Package repo `dank/dankvoice` (README, `docs/decisions/`) — behaviour and
|
||||
knob truth. `docs/decisions/2026-10-19-turn-narration.md` records why
|
||||
narration rides `turn_end` and not only `agent_end`.
|
||||
* Gitea issues #21, #23, #27, #32 (drop-in history) and #34 (this cutover)
|
||||
on `dank/command-center`.
|
||||
* Live endpoint probes 2026-10-18/19 documented in those issues.
|
||||
|
||||
## See Also
|
||||
|
||||
* [Core Documentation](/core/index.md) — the live harness configuration.
|
||||
* [Handy](/tools/handy.md) — offline speech-to-text, the input half of voice.
|
||||
* `serverAppConfigs-docs/Dankclaw/Frank TTS.md` — the frank-tts service runbook.
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
type: reference
|
||||
title: AGENTS.md Index
|
||||
description: Overview of the cached tool documentation system — how it works, why the pre-flight check matters, and how to add new entries.
|
||||
tags:
|
||||
- documentation
|
||||
- index
|
||||
- pre-flight-check
|
||||
- meta
|
||||
timestamp: 2026-01-15
|
||||
---
|
||||
|
||||
# pi Documentation Index
|
||||
|
||||
This directory (`/home/dank/.pi/agent/docs/`) contains cached documentation for tools used during system configuration. It is the agent's primary reference before touching any configuration file.
|
||||
|
||||
---
|
||||
|
||||
## How to Use
|
||||
|
||||
Before configuring any tool, check whether documentation already exists here. If it does not, a subagent **must** be spawned to fetch documentation before proceeding.
|
||||
|
||||
This is not a suggestion. It is the difference between "I remember how to configure this" and "I will need to re-read the docs for the third time this week."
|
||||
|
||||
---
|
||||
|
||||
## Available Tool Documentation
|
||||
|
||||
### Core
|
||||
|
||||
* [AGENTS.md Format](agents-md-format.md) — Structure specification for the system-level instruction file: layer conventions, naming, summary table format, and add/remove procedures.
|
||||
|
||||
### Tools
|
||||
|
||||
* [Ghostty Terminal](../tools/ghostty/index.md) — GPU-accelerated terminal emulator. Complete configuration reference with 100+ options organized by category, CLI actions, keybindings, shaders, and default bindings.
|
||||
* [llama.cpp Server](../tools/llama-cpp/index.md) — LLM inference server. GGUF format, build guides (CPU/CUDA/Metal/Vulkan), server CLI options, API endpoints, Docker setup, and curl examples.
|
||||
* [Linux Power Management](../tools/linux-power-management.md) — Systemd sleep configuration, kernel sleep states, NVIDIA GPU suspend/resume, diagnostic tools, kernel parameters, and automated testing procedures.
|
||||
* [Niri](../tools/niri/index.md) — Scrollable-tiling Wayland compositor. Full keybind cheat sheet, configuration syntax, window management, workspace navigation, and action reference.
|
||||
|
||||
### Pi Packages
|
||||
|
||||
* [pi-browser-use](../packages/pi-browser-use.md) — Browser automation extension wrapping chrome-devtools-mcp with `browser_` prefix, full config reference, session modes, vision model setup, and tool augmentation docs.
|
||||
* [pi-permission-system](../packages/pi-permission-system.md) — 10 docs covering permission enforcement, config reference, session approvals, cross-extension API, subagent integration, troubleshooting, and migration guides.
|
||||
|
||||
### Skills
|
||||
|
||||
* [Npx Skills](../skills/npx-skills.md) — Distribution and installation patterns for agent skills via npm, package structure, SKILL.md frontmatter, discovery rules, and the Agent Skills specification.
|
||||
* [Vercel Labs `skills` CLI](../skills/vercel-skills.md) — CLI meta-installer for cross-agent skill distribution, supporting 68+ agents, with add/use/find/list/update/remove commands.
|
||||
|
||||
### References
|
||||
|
||||
* [OKF v0.1 Specification](../references/okf-spec.md) — Complete specification for OKF knowledge bundles: bundle structure, frontmatter fields, concept documents, index/log files, cross-linking, and conformance rules.
|
||||
* [OKF Bundle Maintenance](../references/okf-maintenance.md) — Bundle maintenance: log.md format, frontmatter discipline, one-concept-per-file, staleness detection, and automation strategies.
|
||||
|
||||
---
|
||||
|
||||
## Adding New Tool Documentation
|
||||
|
||||
When a subagent fetches documentation for a new tool:
|
||||
|
||||
1. Save it to `tools/<tool-name>/index.md` (multi-file) or `tools/<tool-name>.md` (small, single-concept).
|
||||
2. Add an entry to this index table.
|
||||
3. Include a brief description of what the document covers.
|
||||
4. Add YAML frontmatter with `type` and `description`.
|
||||
5. Update `log.md` with the change.
|
||||
|
||||
---
|
||||
|
||||
## Index Format
|
||||
|
||||
Give each row this content:
|
||||
|
||||
- **Tool** — the tool or technology name
|
||||
- **File / Path** — relative path within this directory
|
||||
- **Status** — for example, "Complete", "Partial", "Needs Update"
|
||||
@@ -11,9 +11,10 @@ These files define the structural conventions that govern the agent system itsel
|
||||
## Concept Files
|
||||
|
||||
* [AGENTS.md Format Specification](agents-md-format.md) — Canonical structure and conventions for the system-level instruction file that governs agent behavior.
|
||||
* [AGENTS.md Index](index-doc.md) — Overview of the cached tool documentation system and how to add new entries.
|
||||
* [Pi Settings System](settings.md) — pi-era `settings.json` record (archive): providers, models, packages, subagent overrides.
|
||||
* [dankvoice](dankvoice.md) — Cloned-voice vocalization extension: `/say` and auto-speak over frank-tts, endpoint read from `agent/models.yml`.
|
||||
* [dankvoice](dankvoice.md) — Voice output is the `dank/dankvoice` package (`pi install git:`); this page keeps fleet wiring and the cutover procedure.
|
||||
* [OMP Status Line Customization](statusline.md) — How presets, composer shapes, and segment arrays actually interact; the fleet's tuned bar. (moved from /pi/, 2026-10-19)
|
||||
* [OMP Subagent Limits & Fan-out Policy](subagent-limits.md) — Live caps: concurrency 2, no nested spawns (the `maxRecursionDepth: 0` trap), per-endpoint in-flight ceilings, isolation policy. (moved from /pi/, 2026-10-19)
|
||||
|
||||
## Change Tracking
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ Currently installed:
|
||||
| `@xynogen/pix-ls` | 0.2.1 | Directory listing |
|
||||
| `@xynogen/pix-edit` | 0.2.1 | File editing utilities |
|
||||
|
||||
See [packages](../packages/index.md) for full package documentation.
|
||||
See [Pi Packages](/pi/packages/index.md) for full package documentation.
|
||||
|
||||
---
|
||||
|
||||
@@ -236,5 +236,5 @@ When `lastChangelogVersion` is behind pi's internal version, pi prompts for migr
|
||||
|
||||
- [pi](../pi/index.md) — Pi configuration overview
|
||||
- [[models|models]] — Provider and model definitions
|
||||
- [packages](../packages/index.md) — Installed package documentation
|
||||
- [Pi Packages](/pi/packages/index.md) — Installed package documentation
|
||||
- [[skills|skills]] — Installed skill documentation
|
||||
|
||||
@@ -92,6 +92,6 @@ just the setting description.
|
||||
|
||||
# See Also
|
||||
|
||||
- [/pi/statusline.md](/pi/statusline.md) — the omp-era bundle-audit page pattern this page follows
|
||||
- [/core/statusline.md](/core/statusline.md) — the omp-era bundle-audit page pattern this page follows
|
||||
- [/pi/packages/pi-subagents.md](/pi/packages/pi-subagents.md) — retired pi-era subagent system (historical)
|
||||
- [/system/index.md](/system/index.md) — fleet endpoints these ceilings target
|
||||
@@ -97,4 +97,4 @@ Distribute skills through npm packages with a `pi` manifest, or through the `ski
|
||||
## See Also
|
||||
|
||||
* [SDLC and Tooling](sdlc.md)
|
||||
* [Skills Ecosystem](skills-ecosystem.md)
|
||||
* [Skills Ecosystem](/skills/ecosystem.md)
|
||||
|
||||
@@ -11,7 +11,7 @@ This area distills grounded research into an OKF knowledge bundle. Each page cov
|
||||
* [Language and Framework Stacks](languages/index.md) - Node/JavaScript, React, Python, Rust, Go.
|
||||
* [Infrastructure and Cloud](infra/index.md) - Terraform/OpenTofu, containers, Kubernetes, AWS, DigitalOcean, Hetzner.
|
||||
* [Pi Plugins](plugins.md) - The pi extension ecosystem and notable packages.
|
||||
* [Skills Ecosystem](skills-ecosystem.md) - skills.sh registry and the top skills.
|
||||
* [Skills Ecosystem](/skills/ecosystem.md) - skills.sh registry and the live install leaderboard.
|
||||
* [Signal Remote Control](signal-remote.md) - Drive a pi instance from Signal messages.
|
||||
|
||||
## Conventions
|
||||
|
||||
@@ -38,7 +38,7 @@ Some package names that appear in older documentation, such as `pi-browser-use`
|
||||
|
||||
## Related Ecosystem
|
||||
|
||||
Pi implements the open Agent Skills standard. This makes pi skills compatible with Claude Code, Codex CLI, Amp, Droid, Cursor, and many other agents. See the [Skills Ecosystem](skills-ecosystem.md) page.
|
||||
Pi implements the open Agent Skills standard. This makes pi skills compatible with Claude Code, Codex CLI, Amp, Droid, Cursor, and many other agents. See the [Skills Ecosystem](/skills/ecosystem.md) page.
|
||||
|
||||
## Citations
|
||||
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
---
|
||||
type: reference
|
||||
title: Skills Ecosystem and Top Skills
|
||||
description: The skills.sh registry, the Agent Skills ecosystem, and the verified top 50 skills by installs.
|
||||
tags:
|
||||
- skills
|
||||
- skills-sh
|
||||
- agent-skills
|
||||
- ecosystem
|
||||
- engineering
|
||||
- unverified
|
||||
---
|
||||
verified: 2026-08-28
|
||||
|
||||
# Skills Ecosystem and Top Skills
|
||||
|
||||
This page covers the open agent skills ecosystem. It describes the registries, the install tooling, and the top skills by category.
|
||||
|
||||
## The Ecosystem
|
||||
|
||||
`skills.sh` is the primary registry and leaderboard for agent skills. It runs on the open-source `skills` CLI from Vercel Labs. Use these commands:
|
||||
|
||||
```bash
|
||||
npx skills add <owner/repo> # Install skills
|
||||
npx skills find [query] # Search skills
|
||||
npx skills list # List installed skills
|
||||
```
|
||||
|
||||
The underlying standard is the Agent Skills specification at [agentskills.io](https://agentskills.io). Over 20 coding agents support it. A single `SKILL.md` works across these agents.
|
||||
|
||||
Related registries:
|
||||
|
||||
| Registry | Focus |
|
||||
|----------|-------|
|
||||
| skills.sh | Primary registry and leaderboard. |
|
||||
| agentskill.sh | Directory and marketplace with many indexed skills. |
|
||||
| officialskills.sh | Verified skills from major organizations. |
|
||||
| qaskills.sh | QA and testing skills. |
|
||||
|
||||
Use the local `npx skills` command to explore what is available. You can query the leaderboard data directly at `GET /api/skills/all-time/{page}` on skills.sh. The page index is zero-based and returns 200 skills per page.
|
||||
|
||||
## Top 50 Skills by All-Time Installs
|
||||
|
||||
The table lists the top 50 skills verified from the live skills.sh API on 2026-08-12. Install counts are exact at query time.
|
||||
|
||||
| # | Skill | Source | Installs |
|
||||
|----|-------|--------|----------|
|
||||
| 1 | `find-skills` | vercel-labs/skills | 2,918,155 |
|
||||
| 2 | `grill-me` | mattpocock/skills | 832,797 |
|
||||
| 3 | `frontend-design` | anthropics/skills | 767,871 |
|
||||
| 4 | `grill-with-docs` | mattpocock/skills | 708,703 |
|
||||
| 5 | `improve-codebase-architecture` | mattpocock/skills | 683,652 |
|
||||
| 6 | `tdd` | mattpocock/skills | 660,660 |
|
||||
| 7 | `agent-browser` | vercel-labs/agent-browser | 659,465 |
|
||||
| 8 | `vercel-react-best-practices` | vercel-labs/agent-skills | 625,739 |
|
||||
| 9 | `setup-matt-pocock-skills` | mattpocock/skills | 607,703 |
|
||||
| 10 | `handoff` | mattpocock/skills | 570,592 |
|
||||
| 11 | `triage` | mattpocock/skills | 568,784 |
|
||||
| 12 | `lark-doc` | open.feishu.cn | 561,794 |
|
||||
| 13 | `lark-approval` | open.feishu.cn | 561,758 |
|
||||
| 14 | `lark-base` | open.feishu.cn | 561,634 |
|
||||
| 15 | `lark-drive` | open.feishu.cn | 561,452 |
|
||||
| 16 | `lark-shared` | open.feishu.cn | 561,337 |
|
||||
| 17 | `lark-calendar` | open.feishu.cn | 561,273 |
|
||||
| 18 | `lark-im` | open.feishu.cn | 561,248 |
|
||||
| 19 | `lark-contact` | open.feishu.cn | 561,157 |
|
||||
| 20 | `lark-sheets` | open.feishu.cn | 561,006 |
|
||||
| 21 | `lark-wiki` | open.feishu.cn | 560,924 |
|
||||
| 22 | `lark-attendance` | open.feishu.cn | 560,891 |
|
||||
| 23 | `lark-event` | open.feishu.cn | 560,888 |
|
||||
| 24 | `lark-minutes` | open.feishu.cn | 560,818 |
|
||||
| 25 | `lark-openapi-explorer` | open.feishu.cn | 560,777 |
|
||||
| 26 | `lark-whiteboard` | open.feishu.cn | 560,768 |
|
||||
| 27 | `lark-mail` | open.feishu.cn | 560,720 |
|
||||
| 28 | `lark-task` | open.feishu.cn | 560,692 |
|
||||
| 29 | `lark-slides` | open.feishu.cn | 560,590 |
|
||||
| 30 | `lark-skill-maker` | open.feishu.cn | 560,554 |
|
||||
| 31 | `lark-vc` | open.feishu.cn | 560,466 |
|
||||
| 32 | `lark-workflow-meeting-summary` | open.feishu.cn | 560,368 |
|
||||
| 33 | `lark-workflow-standup-report` | open.feishu.cn | 560,358 |
|
||||
| 34 | `prototype` | mattpocock/skills | 556,403 |
|
||||
| 35 | `lark-okr` | open.feishu.cn | 541,430 |
|
||||
| 36 | `web-design-guidelines` | vercel-labs/agent-skills | 535,426 |
|
||||
| 37 | `lark-markdown` | open.feishu.cn | 526,555 |
|
||||
| 38 | `microsoft-foundry` | microsoft/azure-skills | 523,287 |
|
||||
| 39 | `azure-diagnostics` | microsoft/azure-skills | 518,052 |
|
||||
| 40 | `azure-ai` | microsoft/azure-skills | 517,867 |
|
||||
| 41 | `azure-deploy` | microsoft/azure-skills | 517,694 |
|
||||
| 42 | `azure-prepare` | microsoft/azure-skills | 517,512 |
|
||||
| 43 | `azure-validate` | microsoft/azure-skills | 517,228 |
|
||||
| 44 | `azure-storage` | microsoft/azure-skills | 516,821 |
|
||||
| 45 | `entra-app-registration` | microsoft/azure-skills | 516,567 |
|
||||
| 46 | `appinsights-instrumentation` | microsoft/azure-skills | 516,335 |
|
||||
| 47 | `azure-resource-lookup` | microsoft/azure-skills | 516,249 |
|
||||
| 48 | `azure-compliance` | microsoft/azure-skills | 516,198 |
|
||||
| 49 | `azure-aigateway` | microsoft/azure-skills | 516,058 |
|
||||
| 50 | `azure-kusto` | microsoft/azure-skills | 515,980 |
|
||||
|
||||
## Notable Categories
|
||||
|
||||
The top 50 breaks down into these groups:
|
||||
|
||||
* Development workflow: find-skills, grill-me, tdd, handoff, triage, prototype.
|
||||
* Design and frontend: frontend-design, vercel-react-best-practices, web-design-guidelines.
|
||||
* Lark office suite: 22 skills from open.feishu.cn, roughly ranks 12-35.
|
||||
* Azure infrastructure: 13 skills from microsoft/azure-skills, ranks 38-50.
|
||||
* Agent orchestration: agent-browser, setup-matt-pocock-skills.
|
||||
|
||||
`find-skills` leads by a wide margin with 2.9 million installs. The Lark suite and Azure suite dominate the middle of the list.
|
||||
|
||||
## SKILL.md Format
|
||||
|
||||
A skill is a directory that contains a `SKILL.md` file:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: my-skill
|
||||
description: What this skill does
|
||||
---
|
||||
```
|
||||
|
||||
The `name` field is required and lowercase. The `description` field is required. Skills load progressively: discovery loads only the metadata, activation loads the full file on match.
|
||||
|
||||
## 2025/2026 Trends
|
||||
|
||||
* The Agent Skills spec is the common standard across 20+ agents.
|
||||
* Skills are write once, use everywhere.
|
||||
* Registries add security audits for skill content.
|
||||
* Specialized registries, such as QA, are emerging.
|
||||
|
||||
## Citations
|
||||
|
||||
* [skills.sh](https://skills.sh)
|
||||
* [skills.sh API `/api/skills/all-time/0`](https://skills.sh/api/skills/all-time/0)
|
||||
* [vercel-labs/skills](https://github.com/vercel-labs/skills)
|
||||
* [vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills)
|
||||
* [agentskills.io](https://agentskills.io)
|
||||
* [openai/skills](https://github.com/openai/skills)
|
||||
|
||||
## See Also
|
||||
|
||||
* [Agent Instruction Files](agents-files.md)
|
||||
* [Pi Plugins](plugins.md)
|
||||
* [Skills Documentation](../skills/index.md)
|
||||
+15
-3
@@ -23,7 +23,7 @@ Porkbun DNS-01, hot reload).
|
||||
|
||||
## [Gitea and tooling](tools/index.md)
|
||||
|
||||
Installed software: Gitea, llama.cpp/ornith, niri, ghostty, tmux, ComfyUI,
|
||||
Installed software: Gitea, llama.cpp, niri, ghostty, tmux, ComfyUI,
|
||||
CachyOS, skills tooling — each with its verified operational facts.
|
||||
|
||||
## [Pi-era agent setup](pi/index.md)
|
||||
@@ -31,9 +31,11 @@ CachyOS, skills tooling — each with its verified operational facts.
|
||||
The legacy pi agent configuration (~/.pi era): settings, models, packages,
|
||||
skills. Kept for reference; the live harness is OMP under `~/.omp`.
|
||||
|
||||
## [OMP packages and skills](packages/index.md), [skills index](skills/index.md)
|
||||
## [Skills tooling](skills/index.md)
|
||||
|
||||
Extensions and skills installed for the current OMP harness.
|
||||
The Agent Skills standard, the `skills` CLI, this fleet's store wiring, and
|
||||
the registries — for the live OMP harness. Pi-era packages are archived under
|
||||
[Pi-era agent setup](pi/index.md).
|
||||
|
||||
## [Core config](core/index.md)
|
||||
|
||||
@@ -48,7 +50,17 @@ Practice notes: SDLC, languages, infra tooling (Terraform, K8s, containers).
|
||||
Decision-support research: agentic web tooling, chezmoi evaluation,
|
||||
secrets-for-agents. Research docs inform decisions; they are not facts yet.
|
||||
|
||||
## [Agentic web research](agentic-web-research/index.md)
|
||||
|
||||
Self-hosted web-agent stack research: SearXNG tuning, VPN routing, agentic
|
||||
search practices, open models, MCP.
|
||||
|
||||
## [Inventory](inventory/index.md)
|
||||
|
||||
Pre-pruning census of every userspace config on this box — the input for the
|
||||
pruning session.
|
||||
|
||||
## [Change history](log.md)
|
||||
|
||||
Chronological update history of this bundle — incident lessons land here first,
|
||||
then settle into concept pages.
|
||||
|
||||
+232
-308
@@ -6,401 +6,325 @@ tags:
|
||||
- okf
|
||||
- maintenance
|
||||
- changelog
|
||||
timestamp: 2026-08-28
|
||||
timestamp: 2026-10-19
|
||||
---
|
||||
|
||||
# Bundle Change Log
|
||||
|
||||
Entry law (since 2026-10-19): one dated entry = what changed + the durable
|
||||
lesson, a few lines. Full incident narratives are recoverable from git
|
||||
(`git log --follow omp-docs/log.md`); knowledge that outlives an entry lives
|
||||
on its concept page, linked here. Never re-expand an entry in place.
|
||||
|
||||
## 2026-10-19 — dankvoice auto-speak armed at startup
|
||||
|
||||
Sessions spoke only on explicit `/say`: the settings file carried no `auto`
|
||||
key, and arming is session-scoped by design (`/say on` never persists). Set
|
||||
`"auto": true` in `~/.omp/cache/dankvoice.json`. Same report, second half:
|
||||
auto-speak listened only to `agent_end` — a settle that fires once per prompt
|
||||
and is skipped outright when the harness schedules a continuation — so nothing
|
||||
was narrated while an agent worked; fixed in dank/dankvoice#3, which narrates
|
||||
`turn_end` as well. Law: silence at session start is a config state — read
|
||||
`/say status` for `auto-speak on`, then watch `pgrep -a pw-play` for one player
|
||||
per segment, before blaming the endpoint. Law: whether the harness delivers an
|
||||
event to extensions is settled in minutes by a throwaway probe extension that
|
||||
timestamps `turn_end`/`agent_end` — never inferred from audio timing, which the
|
||||
humanizer lags by seconds. Details: [dankvoice](core/dankvoice.md).
|
||||
|
||||
## 2026-10-19 — LazyVim installed as an NVIM_APPNAME profile
|
||||
|
||||
`lazyvim` had never been installed here — shell history shows the command typed
|
||||
twice and dropped; `~/.config/nvim` held only an orphaned `matugen.lua` palette
|
||||
that nothing loaded. Now: LazyVim starter in `dotfiles/lazyvim/` symlinked to
|
||||
`~/.config/lazyvim`, a `lazyvim` zsh function, and the palette applied through
|
||||
`RRethy/base16-nvim` on `ColorScheme`. Law: the distro stays out of
|
||||
`~/.config/nvim` so bare `nvim` keeps working as a vanilla quick-edit editor.
|
||||
Details: [neovim](tools/neovim.md).
|
||||
|
||||
## 2026-10-19 — dankvoice cut over to the `dank/dankvoice` package (Refs #34)
|
||||
|
||||
Drop-in `agent/extensions/dankvoice.ts` and its 26-test suite retired; the
|
||||
package carries the behaviour (41/41 black-box suite) and is installed with
|
||||
`pi install git:`. Law: install and prove `/say status` speaks on a box
|
||||
*before* pulling the cutover commit — the shared settings file keeps menu
|
||||
state across both transports, so the swap is stateless once installed.
|
||||
|
||||
## 2026-10-19 — dankvoice: silence and timeouts, root-caused (Refs #32)
|
||||
|
||||
The humanizer's raw `fetch` to frank-zealot omitted `chat_template_kwargs.
|
||||
enable_thinking: false`, so the Qwen35 hybrid *thought* instead of answering:
|
||||
6.9 s of `reasoning_content`, `content: ""` — timing out the rewrite twice
|
||||
(12 s dead air) and, when it did answer inside the window, speaking silence.
|
||||
Root-caused by replaying the exact wire body against the live endpoint.
|
||||
Fix: pin the kwarg in the request body; treat empty-content-with-reasoning as
|
||||
failure (mechanical voice), not "nothing worth saying"; the menu's test phrase
|
||||
fires without blocking its handler. Lesson: the harness injects thinking-off
|
||||
for managed roles, but raw HTTP callers must set it themselves — 26/26 green
|
||||
with three red-captured regressions.
|
||||
|
||||
## 2026-10-19 — dankvoice: humanized narration and thinking aloud (Refs #27)
|
||||
|
||||
dankvoice answered in verbatim markdown-cleaned text while the built-in
|
||||
vocalizer speaks humanized prose — the bundle's `Qyr` enhancer (`speech.enhanced`,
|
||||
system prompt `T6o`) now lives in the extension: every spoken unit is rewritten
|
||||
by the @tiny role (resolved from `modelRoles.tiny` in config.yml + the provider
|
||||
baseUrl in models.yml → frank-zealot :7771) under the same budgets (1536 tokens,
|
||||
6 s, 4000-char window), with mechanical cleanup as the fallback and an empty
|
||||
rewrite skipping the unit. Auto-speak also narrates the last assistant message's
|
||||
thinking blocks before the answer (`narration: true` blocks count as answer
|
||||
text); both are menu-toggleable and persisted (`thinking` in the settings file),
|
||||
env levers `DANKVOICE_REWRITE_URL/MODEL/REWRITE=0/THINKING/OMPCONFIG`. The
|
||||
fixture grows a chat route with echo/prose modes; 7 new scenarios, 22 green.
|
||||
Live smoke: a markdown answer became 3 sequential prose segments through real
|
||||
zealot + frank-tts, thinking played before its answer.
|
||||
Spoken units are rewritten by the `@tiny` role (frank-zealot) under the
|
||||
bundle's speech budgets before synthesis, with mechanical cleanup as fallback;
|
||||
auto-speak narrates the last message's thinking blocks first; all toggles
|
||||
persist. 7 new scenarios, 22 green; live smoke through real zealot + frank-tts.
|
||||
|
||||
## 2026-10-19 — dankvoice: segmented sequential speech, copied from the bundle's vocalizer
|
||||
## 2026-10-19 — dankvoice: segmented sequential speech
|
||||
|
||||
Silent-answer incident follow-up: `agent_end` awaiting one whole-answer
|
||||
synthesis hit the harness's 30 s extension-handler timeout
|
||||
(`handler timed out after 30000ms`) on long answers, and the single frank-tts
|
||||
request for the entire answer was the stall. Instead of inventing a heuristic,
|
||||
ported the utterance-splitting state machine out of the built-in speak-aloud
|
||||
vocalizer (minified class `fHe` in `dist/cli.js`): strong boundaries are
|
||||
`[.!?…]+` runs followed by whitespace — `!!!!!`/`...` stay one cut — with
|
||||
abbreviation and inline-code guards; `3.5`/`1,5` survive because a boundary
|
||||
needs trailing whitespace; fenced code and tables swallow whole; headings and
|
||||
bullets vanish, ordered markers speak their number ("1, "); links collapse to
|
||||
labels, URLs to hosts, paths to basenames; run-ons break at commas or word
|
||||
wraps before 280 chars. `speak()` now synthesizes segment N+1 only after
|
||||
segment N's player exited — strictly sequential, audio never stacks — and
|
||||
`agent_end`/`/say <text>` fire-and-forget a chain retired through a run token
|
||||
by `/say stop`, disarming, or a newer utterance. `DANKVOICE_MAX` became a
|
||||
per-answer budget of whole leading segments; the hand-rolled `stripForSpeech`
|
||||
truncator is gone. No LLM "humanization" rewrite happens (the bundle's
|
||||
`speech.enhanced` rewrites with the tiny/smol model; dankvoice speaks
|
||||
mechanically cleaned text through the cloned voices). Tests: two new driver
|
||||
scenarios plus two rewrites, 17/17 in `tests/dankvoice.bats`.
|
||||
`agent_end` awaiting one whole-answer synthesis hit the harness's 30 s
|
||||
extension-handler timeout — lesson: extensions must never await work that can
|
||||
exceed 30 s. Ported the built-in vocalizer's utterance-splitting state machine
|
||||
(boundary = `[.!?…]+` + whitespace, abbreviation/code guards, per-answer
|
||||
segment budget); segments synthesize strictly sequentially. `DANKVOICE_MAX` is
|
||||
now a segment budget. 17/17 in `tests/dankvoice.bats`.
|
||||
|
||||
## 2026-10-18 — dankvoice: `/say` options menu with output-device routing (Refs #23)
|
||||
|
||||
Added `/say menu` (bare `/say` now opens it; `help` keeps the text listing), the
|
||||
pi-peon-style settings surface: auto-speak toggle, voice picked from the frank-tts
|
||||
roster, **output device** (PipeWire sinks via `wpctl` → `pw-play --target` /
|
||||
`paplay --device=`), player binary, spoken-char cap, and a "speak a test phrase"
|
||||
utterance that proves the audio path audibly. Choices persist to
|
||||
`~/.omp/cache/dankvoice.json` (`DANKVOICE_CONFIG`); env now wins over that file,
|
||||
which wins over defaults — answering the silent-session incident where
|
||||
PipeWire's remembered Bluetooth route played synthesized answers into nowhere.
|
||||
`detectPlayer` becomes `availablePlayers` + `playerFor`. Tests gain a fixture
|
||||
`wpctl`, a scripted `select` in the driver, and three menu scenarios: 15 green
|
||||
in `tests/dankvoice.bats`, 51 green suite-wide.
|
||||
`/say menu` (pi-peon-style): auto-speak, voice, PipeWire output device
|
||||
(`wpctl` → `pw-play --target`), player, char cap, test phrase. Precedence
|
||||
env > `~/.omp/cache/dankvoice.json` > defaults — born from the incident where
|
||||
PipeWire's remembered Bluetooth route played answers into nowhere.
|
||||
|
||||
## 2026-10-18 — dankvoice: the cloned voices finally speak in the TUI (Refs #21)
|
||||
|
||||
Nothing in the harness could pronounce them: the TUI vocalizer and `omp say` gate `--voice` against the bundled Kokoro enum (`omp say --voice narrator1 "test"` → `error: Expected --voice to be one of: af_heart, …`), so frank-tts was reachable only as a file. Added `agent/extensions/dankvoice.ts` — `/say <text>`, `/say on|off` (narrate the final answer at `agent_end`), `/say voice|voices|stop|status` — synthesizing over the OpenAI speech route and playing through `pw-play`/`paplay`/`ffplay`, with the endpoint read from the `api: openai-speech` row of `agent/models.yml` (no host, no secret in the file). Verified live in a real TUI session on the workstation: roster `GET /v1/audio/voices` → `narrator1, narrator2, narrator3`; `/say` produced 99,884 B / 2.08 s and 69,164 B / 1.44 s WAVs handed to the player, temp dirs cleaned afterwards; `/say on` armed the footer (`🔊 narrator1`) and each following finished turn spoke its answer (1.20 s WAV), an unknown voice name answered with the roster instead of speaking, and an `agent_end` carrying `willContinue` (the harness scheduled an auto-retry) is deliberately never narrated. Extension discovery itself proved with a probe file in `~/.omp/agent/extensions/` loaded by a fresh `omp -p` run. Reference page [dankvoice](core/dankvoice.md), registered in the core index; black-box seam `tests/dankvoice.bats` (12 tests).
|
||||
The harness gates `--voice` against the bundled Kokoro enum, so frank-tts's
|
||||
cloned voices were unreachable in-TUI. Added `agent/extensions/dankvoice.ts`
|
||||
(`/say …`) synthesizing over the OpenAI speech route, endpoint read from the
|
||||
`api: openai-speech` row of `agent/models.yml` (no host or secret in code).
|
||||
|
||||
## 2026-10-18 — Noctalia bar layout clobbered by trunk-sync stash, recovered from dangling objects
|
||||
## 2026-10-18 — Noctalia bar layout clobbered by trunk-sync stash, recovered
|
||||
|
||||
Frank's months of GUI-built bar customizations (cat/clock/clock-utc/weather start, taskbar center, capsule groups g1–g4, control-cheat-sheet, thickness/font-scale/opacity styling) vanished from the live bar at 16:46. Root cause: the layout existed **only in the working tree** — the repo copy of `settings.toml` carried a stale plain layout because GUI edits hadn't been committed inside the hourly heartbeat window — and a trunk-sync session clearing the dirty tree for `origin/main` stashed it; the stash entry was subsequently destroyed (three `WIP on main` stashes within 60 s, all later dropped). Recovery: `git fsck --lost-found` surfaced the destroyed stash as dangling commit `7fe3ed8` (16:46:09); candidate validated in a sandboxed `XDG_*_HOME` before restore, clobbered file preserved to `.AGENTTRASH/`, layout restored through the symlink target and proven by screenshot, committed as `c87b378` — the durable copy the layout never had. Lessons codified into managed skills: trunk-sync must preservation-**commit** every dirty deployment path (never stash, never `stash clear`), and GUI layout edits get committed the same session they're made.
|
||||
GUI-built bar customizations existed only in the working tree; a trunk-sync
|
||||
stash-then-drop destroyed them. Recovery: `git fsck --lost-found` surfaced the
|
||||
dropped stash as a dangling commit; validated in a sandboxed `XDG_*_HOME`
|
||||
before restore. Lesson: GUI-written config is only durable once committed —
|
||||
the motivation for the live-sync heartbeat below.
|
||||
|
||||
## 2026-10-18 — Fleet law: issue/PR attribution footers
|
||||
|
||||
Every agent-opened issue and PR body now ends with a `cwd:` + `session:` footer (session id from `/status`), in AGENTS.md of both `dank/command-center` and `dank/serverAppConfigs` (mirrored PRs). Born from the live-sync review: once the machine starts filing and committing on its own, its artifacts must trace back to the box and session that produced them.
|
||||
Every agent-opened issue/PR body ends with `cwd:` + `session:` footer, in both
|
||||
`dank/command-center` and `dank/serverAppConfigs` AGENTS.md: machine-made
|
||||
artifacts must trace to the box and session that produced them.
|
||||
|
||||
## 2026-10-18 — live-sync heartbeat for machine-written paths (Refs #11)
|
||||
|
||||
Root-caused the month of silent divergence in the live checkout (~61 auto-learned skills on one disk only, a stranded `unexpectedStopDetection` fix, merge-refusals from dirty trees): the checkout IS the deployment, symlinks make machine writes dirty tracked files by design, and no commit law covered that churn. Added `scripts/live-sync.sh` + systemd user timer — allowlist tiers (memories, managed-skills, live config, dotfiles) auto-commit with hooks armed, merge `origin/main`, push, and reap stale `wt/*` worktrees; everything outside the allowlist is never staged, conflicts abort-and-alert. Black-box suite `tests/live-sync.bats` (9 tests). Tier law in AGENTS.md § Live-sync tiers; reference page `tools/live-sync.md` registered in the tools index.
|
||||
A month of silent divergence in the live checkout proved the checkout-is-
|
||||
deployment model needs a committer: `scripts/live-sync.sh` + systemd user
|
||||
timer auto-commits allowlisted tiers (memories, managed-skills, live config,
|
||||
dotfiles) with hooks armed, merges `origin/main`, pushes, reaps stale `wt/*`.
|
||||
Non-allowlist dirt never staged; conflicts abort-and-alert. See
|
||||
[tools/live-sync.md](tools/live-sync.md); tier law in AGENTS.md.
|
||||
|
||||
## 2026-10-18 — Fleet law: filed PRs open in Frank's browser immediately
|
||||
|
||||
Both repos' git rules now require it: the moment a PR is opened, `xdg-open <PR-URL>` drops a Firefox tab on the workstation (AGENTS.md § Trunk-based SDLC here; § Git Workflow step 6 in `dank/serverAppConfigs`, riding their PR #6 branch).
|
||||
`xdg-open <PR-URL>` the moment a PR opens — codified in both repos' git rules.
|
||||
|
||||
## 2026-10-18 — Trunk law: extension route closed unmerged; direct repo alignment instead
|
||||
## 2026-10-18 — Trunk law: extension route closed unmerged; direct repo alignment
|
||||
|
||||
Built and live-verified a cwd-scoped `before_agent_start` extension (quote probes: fires under `~/Projects`, silent elsewhere; kept as `.AGENTTRASH/trunk-law.js`). **Operator closed PR #9 unmerged** in favor of editing each repo's own AGENTS.md. Durable finding from the exploration: every context-file provider (AGENTS.md walk-up, `.omp/` dirs, CLAUDE.md) resolves at or below the repo root — a `~/Projects/AGENTS.md` for ancestor scope can never load; user-level `APPEND_SYSTEM.md` broadcasts to *all* sessions. Second finding: **serverAppConfigs never had git-flow** — its AGENTS.md mandated no branch regime at all (direct commit+push); a trunk + PR law is being added there by PR in that repo, not corrected.
|
||||
Operator closed PR #9 (cwd-scoped `before_agent_start` extension) in favor of
|
||||
editing each repo's AGENTS.md. Durable findings: every context-file provider
|
||||
(AGENTS.md walk-up, `.omp/` dirs, CLAUDE.md) resolves at or below the repo
|
||||
root — ancestor-scope files can never load; user-level `APPEND_SYSTEM.md`
|
||||
broadcasts to all sessions; serverAppConfigs never had git-flow.
|
||||
|
||||
## 2026-10-18 — SDLC switched to trunk-based development
|
||||
|
||||
`develop` retired by operator decision (single-dev repo; the branch bought nothing and cost a back-merge every release). New law in AGENTS.md § *Trunk-based SDLC*: branch off the freshest `origin/main` before every work item, PRs target `main` directly, `--no-ff` merges, tags `vX.Y.Z` straight on main. No back-merges, no release branches. The last back-merge (`527596a`) lands with this switch; the managed skill `gitflow-back-merge-plumbing` is now historical.
|
||||
`develop` retired (single-dev repo). Law in AGENTS.md § Trunk-based SDLC:
|
||||
branch off freshest `origin/main`, PRs target `main`, `--no-ff` merges, tags
|
||||
`vX.Y.Z` on main. Managed skill `gitflow-back-merge-plumbing` is historical.
|
||||
|
||||
## 2026-10-18 — Sibling-vault overlap census; system docs realigned to live ground truth
|
||||
|
||||
Census of `omp-docs/` against `~/Projects/serverAppConfig/serverAppConfigs-docs/` (subagent + live-ssh verification) found four contradicting pairs; all OURS-side stale pages corrected, THEIRS side flagged only (their repo, their PR flow). Ground truth from read-only probes on both boxes 2026-10-18.
|
||||
Census of `omp-docs/` vs `serverAppConfigs-docs` (subagents + live-ssh probes)
|
||||
found four contradicting pairs; ours fixed, theirs flagged for their PR flow.
|
||||
Recorded then: RTX 3090 moved Dankserver→Dankclaw 2026-09; dankserver = 2×
|
||||
Radeon AI PRO R9700 (the "board swap" story was false); served models per
|
||||
live units. Current state always: [/system/index.md](/system/index.md)
|
||||
(27B-era zealot figures here are historical; live census 2026-10-19 below).
|
||||
|
||||
* **Hardware drift corrected** (`system/dankserver.md`, `system/dankclaw.md` rewritten, `AGENTS.md` machine table): RTX 3090 moved Dankserver→Dankclaw 2026-09; dankserver now 2× Radeon AI PRO R9700 (7700X stays — the "board swap" story is false), 246 GiB RAM, no swap; dankclaw 121 GiB RAM + 64 GiB swap. Served models per live units: frank-archon (:7770 dankserver, radiance TP=2 iq4r), frank-dragoon (:7770 dankclaw, halogen NATIVE v2, iGPU), frank-zealot (:7771 dankclaw, llama.cpp PrismML, Ternary-Bonsai-2-27B PQ2_0, 3090). Both kernels 7.0.0-38-generic; dankclaw :7770 needs no auth.
|
||||
* **Gitea pages corrected** (`tools/gitea/` index + 3 subpages): `gitea-caddy` quadlet retired — fleet Caddy fronts the domain; data tree is `/home/dank/Containers/gitea/{data,postgres,env}` (2026-09-01 standard), `/opt/gitea/` is a do-not-use leftover; LAN IP, live domain, no WAN address.
|
||||
* **Pi-era pages demarcated as archive** (`pi/index.md`, `core/index.md` banners; `core/index.md` said settings.md was "Current"): `frank-default-small/large` endpoints, role tables, and 3090/4070 hardware rows now read as pi-era records. `tools/llama-cpp/index.md` fleet note modernized to the one remaining llama.cpp endpoint (zealot :7771).
|
||||
* **Their-side staleness flagged, NOT edited** (for operator clarification): `Agent/OMP Harness.md` still says thresholdPercent 70 — live config is **95** (`agent/config.yml:84`); `index.md:18` says Dankserver Ubuntu 24.04 vs their own specs page 26.04; `Dankclaw/Stack.md` "current mapping (2026-09-03)" predates the ACTIVE dragoon/zealot runbooks it links beside; `index.md:548` links the superseded pi-era KB at `~/.pi/agent/docs/`.
|
||||
* Consistent duplicates (no action): niri/noctalia desktop pages, Caddy reference. Divergence clarified: their "composer" = OpenWebUI chat box; ours = omp composer shape — unrelated subjects.
|
||||
## 2026-10-18 — Status line rebuilt on custom segments; full-source audit
|
||||
|
||||
## 2026-10-18 — Status line docs truth audit (full-source re-verification)
|
||||
New page [core/statusline.md](core/statusline.md) with an audit log — four
|
||||
first-pass claims were false and corrected against the minified bundle + a
|
||||
live screenshot matrix (context meter is `box`/`band` only; `composer.shape`
|
||||
routes segment arrays; `mode` states = Plan/Prewalk/Goal/Vibe/Loop). Bar
|
||||
rebuilt on `band` + custom segments; frank-archon display name slimmed in
|
||||
models.yml.
|
||||
|
||||
Exhaustive claim-by-claim re-audit of [OMP Status Line Customization](/pi/statusline.md) against the minified `dist/cli.js` bundle plus a live screenshot matrix (band × {off, percentage, embedded}, claude × off). Page carries an **Audit log** section; four first-pass claims were false and are corrected (see there): claude's rule is *not* the context meter (meter is `box`/`band` only; the "red rule" was the session-accent filler), the "Tern-only" composer-bar claim was bogus (the readout is `composer.tokenRate`, default off), `segmentOptions` are **not** gated to `preset: custom` (only the segment arrays are), and the `mode` segment's states are Plan/Prewalk/Goal/Vibe/Loop (no yolo). Page expanded with: the 7-preset defaults table, per-shape `statusAttachment`/`bottomBar` model (8 built-ins + plugin shape registry), `contextLine` per-value behavior, the 27-segment catalog with triggers/options, `segmentOptions` schema, and the full `statusLine.*`/`composer.*` knob registry. The bundle's own "(box composer only)" knob description for `contextLine` is upstream-wrong — band honors it.
|
||||
## 2026-10-09 — Blankpad DE redesign: desk profiles, keybinds, Handy wiring
|
||||
|
||||
ServerAppConfigs-docs overlap census: flagged separately for the operator (morning report); no doc merged/changed on either side.
|
||||
Per-desk niri profiles keyed by EDID long name (connector names reshuffle
|
||||
between docks; identity travels) + `scripts/desk.sh`; niri 26.04 has **no
|
||||
hotplug event** (`OutputConfigChanged` is only an ACK per niri-ipc) — the
|
||||
autoswitch daemon diffs output sets on `WorkspacesChanged`. Keybind cheat
|
||||
sheet now generated (`scripts/gen-keybinds.sh`); noctalia docs corrected to
|
||||
the v5 `noctalia msg` API. Handy: niri owns autostart; open breaker —
|
||||
frank-secondary answers in `reasoning_content` with empty `content`, and
|
||||
Handy cannot send `chat_template_kwargs.enable_thinking=false`. 27/27 green.
|
||||
|
||||
## 2026-10-18 — Status line rebuilt on custom segments; frank-archon display name slimmed
|
||||
|
||||
Interactive tune-up of the omp status bar (grilling session, live loop: config edit → watcher repaint → niri screenshot verify). New knowledge page: [OMP Status Line Customization](/pi/statusline.md).
|
||||
|
||||
* **Mechanics discovered:** `leftSegments`/`rightSegments` are inert unless `preset: custom` (fleet was on `nerd` with dead arrays; `segmentOptions` *do* merge under named presets); `composer.shape` routes them — `band` merges both arrays into one row above the editor (title rides the working row), `claude` splits them into top chip + bottom strip. The context meter exists **only in `box`/`band`** — `contextLine`: `off` plain rule, `embedded` hoists the context segment into the labeled inline meter (`60% ——— × 200K`), `percentage`/`annotated` paint an unlabeled proportional rule meter (all four live-verified); every other shape's rule is a constant session-accent filler. Working row (session title + tok/s readout gated by `composer.tokenRate`, default off) is composer chrome — model/thinking can never join it. Eight composer shapes ship in the bundle; plugins can register more.
|
||||
* **Final bar (`band`, after a `claude` sojourn):** left = `session_name · vim · mode · hostname · path · git(no branch text) · pr`; right cluster in array order = `model · cost · time_spent` (`context_pct` hoists out of the run to paint the labeled inline meter `60% ——— × 200K` as a flexible spacer between the groups). Cut: tok/s duplicate, clock, cache trio, `context_total`, `subagents`, `session` hash, and `token_in`/`token_out` (cumulative totals live in `/session`). `path`: logical `project/worktree` label (`stripWorkPrefix: true`, kept after a live `false` trial of the full cwd); branch text dropped (worktree branches are autogenerated), dirty badges kept.
|
||||
* **models.yml:** frank-archon display `name` slimmed to `"frank-archon"` (endpoint suffix dropped; `id` untouched).
|
||||
* **Out of scope noted:** worktree name generation (`wt-<date>-<hash>`) is omp-internal; possible upstream feature request.
|
||||
|
||||
## 2026-10-09 — Blankpad DE redesign: desk profiles, keybind rework, Handy fleet wiring
|
||||
|
||||
Branch `blankpad-de-redesign` (worktree `wt/de-redesign-20261009`). Full sweep + redesign of the niri/noctalia/Handy stack on blankpad.
|
||||
|
||||
* **Desk profiles.** `cfg/display.kdl` retired to a symlink; per-desk profiles `desk-1-home.kdl` / `desk-2-portable.kdl` declare monitors by **EDID long name** (`// requires:` lines) — connector names reshuffle between docks, identity travels. `scripts/desk.sh` = list/current/switch/cycle/match/capture; apply = relink → `niri validate` (rollback on failure) → `load-config-file` → noctalia notification. `scripts/desk-autoswitch.sh` + `blankpad-desk-autoswitch.service` watch `niri msg --json event-stream`: niri 26.04 has **no hotplug event** (`OutputConfigChanged` is only an ACK that an IPC/config output change was Applied, per niri-ipc); the daemon diffs the sorted output set carried by `WorkspacesChanged` and hot-applies the matching profile (debounced 1.5 s). Proven live with an eDP-1 off/on cycle: `[DP-2 eDP-1] → [DP-2] → [DP-2 eDP-1]`, apply + reload each time. PM1601 EDID still uncaptured (panel disconnected) — connector-keyed placeholder, `desk.sh capture` pending.
|
||||
* **Keybinds.** `swap-window-left/right` on Mod+CTRL+H/L; move-column demoted to Mod+CTRL+Alt+H/L; 7 column-width presets 12.5–87.5 %; Print trio (full / gui / screen) via noctalia screenshot IPC; launcher Mod+D; Alt+Tab → noctalia window-switcher; Mod+V → clipboard panel (id verified live); Mod+Shift+D → desk cycle; Mod+Shift+Space → `handy --toggle-post-process`; lid-close → `noctalia msg session lock-and-suspend` (pairs with logind `HandleLidSwitch=ignore`). Cheat sheet now GENERATED: `scripts/gen-keybinds.sh` → `omp-docs/tools/niri/keybindings.md` (119 bindings).
|
||||
* **Noctalia.** `config.toml` + `settings.toml` (lives in `~/.local/state/`, not `~/.config/`) tracked; `taskbar` widget added to bar center, applied live via `noctalia msg config-reload`. Docs corrected to the v5 `noctalia msg` API.
|
||||
* **Handy.** Self-autostart killed (`~/.config/autostart/Handy.desktop` → `.AGENTTRASH`; `autostart_enabled=false`); niri owns autostart (`spawn-at-startup "handy" "--start-hidden"`). Fleet post-processing wired into the live store: provider `custom` → `http://192.168.0.143:7771/v1`, model `frank-secondary`, prompt `default_improve_transcriptions`. **Open breaker:** frank-secondary answers in `reasoning_content` and leaves `content` empty; per-request cure `chat_template_kwargs.enable_thinking=false` verified, but Handy cannot send it and the server is shared with fleet compaction — dedicated no-think port proposed. 0.9.6→0.9.8 upgrade is operator-owned (`yay -Syu handy-bin`).
|
||||
* **Scripts + tests.** Two subagents died mid-run (one mid-test-write; one crashed **looping `sudo yay` without a TTY** — see next entry). Their scripts/tests were rebuilt from live-format ground truth: `tests/desk.bats` (16), `tests/gen-keybinds.bats` (6), `tests/niri-config.bats` (5, incl. real `niri validate` on the assembled base+zz tree with each desk profile active). Suite: 27/27 green.
|
||||
|
||||
## 2026-10-09 — Incident: agent sudo-loop tripped pam_faillock and locked out the operator's sudo
|
||||
|
||||
While attempting the Handy 0.9.8 install, a subagent ran `sudo yay -Syu handy-bin` in a retry loop for ~15 minutes. Harness sudo has no TTY, so every attempt logged 3 `pam_unix` auth failures; `pam_faillock` (deny=3) locked user `blank` out — the operator's own correct-password `sudo`/`pacman -Syu` began failing with "temporarily locked out", which looked exactly like a changed password.
|
||||
|
||||
* **No password change:** `/etc/shadow` mtime 2026-09-10 23:31, untouched; no `passwd`/`chpasswd`/`usermod` in the journal.
|
||||
* **Recovery:** loop process died with the agent; `faillock --user blank --reset` (unprivileged for own user, dir `/run/faillock/blank` is 0700) cleared the counter; verified empty.
|
||||
* **New law:** agents NEVER run `sudo`/`yay`/`pacman`/`pkexec` on Frank's workstations — root-requiring steps are handed to the operator as exact copy-paste commands. Codified as managed skill `faillock-sudo-lockout-recovery`.
|
||||
## 2026-10-09 — Incident: agent sudo-loop tripped pam_faillock, locked out the operator
|
||||
|
||||
A subagent retried `sudo yay` (no TTY) for ~15 min; `pam_faillock` deny=3
|
||||
locked user `blank` — correct-password sudo failed, mimicking a password
|
||||
change. Recovery: `faillock --user blank --reset`. Law: agents never run
|
||||
`sudo`/`yay`/`pacman`/`pkexec`; root steps go to the operator as exact
|
||||
commands. Skill `faillock-sudo-lockout-recovery`.
|
||||
|
||||
## 2026-10-09 — Full secret audit of the command-center repo: clean
|
||||
|
||||
Five-layer audit of `dank/command-center` at `79e780f`, driven by the four live values in `~/.config/secrets/` (gitea, hf_token, hf_token_write, kagi_api_key) plus 21 provider shapes (sk-, hf_, gh[pousr]_, glpat-, AKIA/ASIA, xox, npm_, pypi-, AIza, JWT, PEM/OpenSSH keys, `scheme://user:pass@host` basic-auth URLs, `password|secret|api_key = <literal>` assignments). Findings printed redacted (prefix + length + sha256 prefix).
|
||||
|
||||
* **Live-value scan — clean.** 77 revs (5 branches, 2 tags), 765 reachable blobs, 3.4 MiB of blob text: no known live value appears in any tracked blob at any ref.
|
||||
* **Whole object store, reachable *and* dangling — clean.** `git cat-file --batch-all-objects` finds 767 blobs; 2 are unreachable, never committed on any ref (`git log --all --find-object` empty). One is a 123 KB superseded memory page; the other is a 35-byte test fixture holding a synthetic `sk-` key whose body is the alphabet followed by `1234` — pattern-minted, not issued. No PEM key, no JWT, no basic-auth URL anywhere. (Quoting the literal here tripped the secret gate, which is the gate working as designed.)
|
||||
* **Shape hits, all triaged benign**: `api_key="sk-no-key-required"` (llama.cpp doc placeholder), `Set password:` / `authenticate(user, password)` prose in the Authentik memory skills, and a 40-hex string in the home-config census that is a git **packfile filename** (`pack-ff7cc541….pack`), not a token.
|
||||
* **Entropy layer — clean.** Zero tokens ≥ 32 chars with Shannon entropy ≥ 4.3 in HEAD blobs.
|
||||
* **Payloads, not just pointers**: all 23 git-lfs wallpaper objects (81 MiB) scanned as bytes — no secret shape in any payload.
|
||||
* **Quarantine list holds**: no tracked file matches `auth.json`/`trust.json`/`.env`/`*.pem`/`*.key`/`identity*`; the 42 ignored paths on disk carry no secret shape; no credential in any git config scope (local/global/system).
|
||||
* **Fixed on the spot**: `~/.config/secrets/hf_token_write` was mode 0644 (world-readable) → 0600. `~/.cache/huggingface/token` (the standard HF location, holds the same value) verified 0600.
|
||||
* **Known gap, not yet closed**: `.githooks/pre-commit` covers GitHub/GitLab/Slack/AWS/PEM/JWT/OpenAI-shaped `sk-`, but **not** `hf_…`, `npm_…`, `pypi-…`, `AIza…`, Stripe, Telegram, or a `scheme://user:token@host` basic-auth URL — which is exactly the shape that sat in `remote.origin.url` until today. Widening the gate is an open decision.
|
||||
Five layers (live-value scan across 77 revs/765 blobs, whole object store
|
||||
incl. dangling, shape triage, entropy ≥4.3, LFS payloads) — no secret in any
|
||||
reachable or dangling object; quarantine list holds. Fixed `hf_token_write`
|
||||
0644→0600. Open gap: the pre-commit gate lacks `hf_`/`npm_`/`pypi-`/`AIza`/
|
||||
Stripe/Telegram shapes and basic-auth URLs — widening it is an open decision.
|
||||
|
||||
## 2026-10-09 — Gitea token moved out of every remote URL
|
||||
|
||||
Both workstation clones (`~/.omp` → `dank/command-center`, `~/Projects/serverAppConfig` → `dank/serverAppConfigs`) carried the Gitea HTTP token inside `remote.origin.url`, so it sat in `.git/config`, was printed by `git remote -v`, and was echoed verbatim by the git-lfs lock warning on every push.
|
||||
Remotes bare; credential in `~/.config/secrets/gitea` (0600) behind a global
|
||||
`credential.helper store`. Trap (git 2.56.0, measured): `git
|
||||
credential-store` rejects the `protocol=`/`host=` block shape the man page
|
||||
shows — the store file must be one URL per line, port included. Verified with
|
||||
`GIT_TERMINAL_PROMPT=0`. Details: [tools/gitea/client-access.md](tools/gitea/client-access.md).
|
||||
|
||||
* **Cutover**: remotes are now bare (`http://192.168.0.143:3000/dank/<repo>.git`); the credential lives in `~/.config/secrets/gitea` (0600) behind a **global** helper — `git config --global credential.helper 'store --file ~/.config/secrets/gitea'` — so every repo on the host authenticates from one file. `lfs.…info/lfs.locksverify true` set on `~/.omp` to silence the warning that leaked the URL.
|
||||
* **The trap (git 2.56.0, measured)**: `git credential-store` will not parse the `protocol=`/`host=`/`password=` block shape that `git credential fill` accepts on stdin and that the man page shows for `~/.git-credentials`. It returns an empty `get`, and git falls through to askpass: `could not read Username for …`. The store file must be one URL per line, port included: `http://dank:<token>@192.168.0.143:3000`.
|
||||
* **Verified** with prompts disabled (`GIT_TERMINAL_PROMPT=0`): `git credential-store get` returns the credential, `ls-remote` reads, `push --dry-run` says `Everything up-to-date` on both repos, `git remote get-url origin` contains no `@`, and a grep for the token across `~/.gitconfig`, both `.git/config` files, and the shell rc files returns nothing.
|
||||
* **Doc**: new [[client-access|client-access]] (`tools/gitea/client-access.md`) — credential file layout, the store-format trap, the verification loop, LFS lock warning, rotation procedure. Cross-linked from the gitea index and management pages.
|
||||
## 2026-10-09 — Working tree reconciled: callsign renames, compaction move, gitignore quarantine
|
||||
|
||||
## 2026-10-09 — Working tree reconciled: callsign renames, Dankclaw compaction, gitignore quarantine
|
||||
|
||||
A 200-entry dirty tree (116 deleted, 73 untracked, 11 modified) sat uncommitted across several sessions. Committed as seven atomic units; nothing discarded.
|
||||
|
||||
* **Model ids renamed to the unit-name scheme** (`agent/models.yml`): `frank-medium → frank-archon` (dankserver :7770, 200,000 ctx / 16,384 max), `frank-large → frank-dragoon` (Dankclaw :7770, 217,088 / 45,056, `input: [text, image]`), `frank-small → frank-zealot` (Dankclaw-3090 :7771, 200,704 / 16,384). The **services keep the old names on the wire** — `/v1/models` still serves `frank-primary`, `frank-large`, `frank-secondary`; the engines accept an arbitrary request `model` id, so the rename is harness-side only. Probed live: all three chat completions return 200 with `reasoning_content`.
|
||||
* **Server-side compaction moved** off `192.168.0.235:7770` to `192.168.0.143:7771` (frank-zealot's 3090), threshold 70 % → 85 %, remote streaming v2 + async on; every model's `compactionModel` points at `frank-zealot` so the wire id stays valid at the compaction endpoint. Reference integrity checked programmatically: 22 model references across `modelRoles`, `task.agentModelOverrides`, `compactionModel` — zero unresolved.
|
||||
* **`.gitignore` quarantine** for runtime state that was tracked-adjacent noise: `autoresearch/`, `agent/predict/`, `local/`, `wt/`, and `agent/memories/--home-blank-.omp-wt-*` (a session inside a git worktree mints a memory bucket keyed on the ephemeral worktree path). All had zero tracked files, so the rules are purely additive — 73 untracked → 68, and the remaining 68 are real memory records that got committed.
|
||||
* **Skill libraries were renamed, not lost.** `agent/managed-skills` consolidated 94 → 25 (git renders directory renames as mass delete + mass add; pre-cutover content is intact at `12c5e88`). Workstation memory skills re-bucketed by topic: `dotfile-git-workflow` → `ghostty-text-aa` + `niri-display-rotation` + `noctalia-theme`, `handy-service-mgmt` → `handy-flm-inference`, `inference-runtime` → `llama-cpp-parallelism`.
|
||||
* **Display layout**: blankpad DP-2 back to landscape `3440x1440@239.999` (`transform "normal"`), HDMI-A-1 portrait bezel flipped `270 → 90`, eDP-1 re-pinned rightmost. Supersedes the 2026-09-15 portrait pin (`2baf0c0`).
|
||||
* **Secrets**: `.zshrc` now reads `KAGI_API_KEY` / `HF_TOKEN` from `~/.config/secrets/*` (600-perm files) instead of carrying literals into a repo published to Gitea. The pre-commit secret gate passed on all seven commits.
|
||||
200-entry dirty tree committed as seven atomic units. Harness model ids
|
||||
renamed `frank-{medium,large,small}` → `frank-{archon,dragoon,zealot}` —
|
||||
**services keep old names on the wire**; the engines accept any request model
|
||||
id, so renames are harness-side only. Server-side compaction moved to
|
||||
zealot's 3090 (threshold 70→85 %). `.gitignore` quarantine for worktree-keyed
|
||||
memory buckets and runtime dirs. Skill renames are not losses: git renders
|
||||
directory renames as mass delete+add; pre-cutover content intact at `12c5e88`.
|
||||
|
||||
## 2026-09-28 — Retired workstation purged from the knowledge base
|
||||
|
||||
Frank sold the client workstation. Every identifier for it is gone from this bundle: hostname, both of its LAN addresses, and its Wi-Fi SSID. The knowledge outlives the box; the machine does not.
|
||||
Sold box: hostname, both LAN addresses, Wi-Fi SSID gone bundle-wide; the
|
||||
knowledge distilled into [system/network.md](system/network.md) (multi-link
|
||||
resolver law: a static resolver must be pinned on each *connection*) and
|
||||
[tools/niri/displays.md](tools/niri/displays.md) (portrait transforms, the
|
||||
three ways a multi-monitor rig breaks). Hostname stays only where it is a
|
||||
lookup key (install.sh `--host`, `packages/<hostname>.pkgs`).
|
||||
|
||||
* **Distilled, not deleted.** The four per-host system pages carried two pieces of knowledge worth keeping and one that was not:
|
||||
* `/system/network.md` (new) — LAN topology, plus the multi-link resolver law: a client with two `+DefaultRoute` links flaps its DNS, and the fix is a static resolver pinned on each *connection* (a `resolved.conf` `DNS=` line is only a per-link fallback). Keeps the flush-caches verification loop, because one successful `dig` proves nothing on a flapping resolver.
|
||||
* `/tools/niri/displays.md` (new) — the multi-monitor rig: portrait transforms, absolute positions, the auto-placed third panel, the iGPU render-node pin, and the three ways it breaks (duplicate output blocks, positions that do not reflow, a mode the panel cannot drive).
|
||||
* Dropped: the machine's own spec sheet and quick-facts table. The OS and userspace facts they repeated already live in `tools/cachyos.md`.
|
||||
* **Mechanical scrub** across the rest of the bundle: indexes, tool and research pages, the inventory census, the changelog, one generated HTML report, and four managed skills. Facts kept, names dropped — `install.sh`'s `--host` case list and the `packages/<hostname>.pkgs` filename stay, because the hostname is the lookup key there.
|
||||
* `AGENTS.md` and `README.md` keep a nameless "workstation" row so the fleet tables still describe the class of box without advertising a machine that is no longer Frank's.
|
||||
* Out of scope by decision: `agent/memories/**` (past-session records the learn pipeline rewrites) and the retired pages' history — they are recoverable from `.AGENTTRASH/20260928-retired-workstation/` and from git.
|
||||
|
||||
## 2026-09-01 — Retry backoff and thinking default
|
||||
|
||||
* **Retry backoff**: configured Pi's automatic agent-level retries in `settings.json` with a 10-second base delay, producing 10s, 20s, and 40s delays across three retries.
|
||||
* **Thinking default**: set `settings.json` `defaultThinkingLevel` to `medium`. `models.json` has no supported per-model default-thinking field; Pi applies this global default to the configured models.
|
||||
## 2026-09-01 — Retry backoff and thinking default (pi era)
|
||||
|
||||
Pi `settings.json`: 10 s base retry backoff (10/20/40 s), `defaultThinkingLevel:
|
||||
medium` (no per-model thinking field exists in `models.json`).
|
||||
|
||||
## 2026-08-28 — KB rebuilt to OKF v0.1; live-verified fleet facts
|
||||
|
||||
* **Creation**: the whole `omp-docs/` bundle was copied from the legacy `~/.pi/agent/docs` tree and rebuilt as a git-tracked, OKF v0.1-conformant knowledge base inside the new `command-center` repo (repo root = live agent dir; the checkout *is* the deployment). Every checkable claim was re-verified against the live fleet (read-only probes); unverifiable claims are tagged `unverified` in frontmatter.
|
||||
* **Update — hardware facts corrected**: Dankserver is a **Ryzen 7 7700X + RTX 3090** (not Strix Halo); Strix Halo (gfx1151) is **Dankclaw**. RAM, storage, kernel, and network facts were probed live and corrected across `system/`.
|
||||
* **Update — conformance pass**: concept-in-disguise indexes promoted to `<dirname>.md` concept files (identity = path, per spec); index.md files stripped of frontmatter (indexes carry none); all wikilinks and relative links resolved or repointed; `scripts/kb-lint.sh` (OKF conformance + link-integrity linter) exits 0 on the bundle. Vendored `references/okf-spec.md` is exempt from link-lint — its example paths are illustrations, not links.
|
||||
* **Update — inventory**: home-config census (7 orphaned configs, 10 prune-candidates) recorded under `inventory/` for the pruning session; zero deletions performed. Legacy `~/.pi` tree left untouched and frozen.
|
||||
* **Deferred to operator** (decisions, not facts): chezmoi source layout (`research/chezmoi-evaluation.md` recommends a separate chezmoi repo) and the permanent secrets tool (`research/secrets-for-agents.md`; interim = pre-commit secret gate + quarantine list; top candidate sops+age). Gitea Projects unit is disabled instance-wide, so the kanban board is a one-time web-UI setup for the operator.
|
||||
`omp-docs/` copied from legacy `~/.pi/agent/docs`, rebuilt as git-tracked OKF
|
||||
v0.1 (checkout *is* the deployment); unverifiable claims tagged `unverified`.
|
||||
Conformance pass promoted concept-in-disguise indexes, stripped index
|
||||
frontmatter, resolved all links; `scripts/kb-lint.sh` exits 0. Hardware facts
|
||||
were corrected *then* (3090-on-dankserver since moved — see 2026-10-18).
|
||||
Inventory census recorded under `inventory/` for the pruning session.
|
||||
|
||||
## 2026-08-23 — Homepage deployed to production; Caddy KB doc
|
||||
|
||||
* **Homepage is live on Dankclaw.** `./scripts/deploy.sh dankclaw` deploys the static files to `/srv/homepage`, installs the status checker (systemd timer, every 3 min, writes `status.json`), writes `deployed.js` (the last master deployment datetime), renders the Caddyfile (both basicauth hashes from the host `.env`), reloads Caddy, and checks health. Verified end-to-end: `/admin/` (operator) + all shared files serve 200 under the operator credential; `/` and `/admin/` 401 without/wrong credentials; the LLM is healthy.
|
||||
* **Caddyfile auth design (the hard-won fix).** Caddy *sorts* top-level directives, so a `rewrite` runs before a `basicauth`; the rewrite changed `/admin/` to `/admin.html` and the path-based auth matchers then saw the rewritten path, applying the wrong (family) auth block — the operator password 401'd. Fix: serve each page from its own `handle` block (which preserves file order, so the auth is checked on the original path): `handle /admin*` (operator only), `handle @data` (shared data + assets, family OR operator, so the admin page's fetches reuse the operator credential), and a catch-all `handle` (family). Also: a `handle` inline matcher is a single token (multi-path needs a named matcher); a leading `@name <directive>` is parsed as a matcher *definition* (re-defines `@name`).
|
||||
* **Caddy mount fix.** The caddy container mounted the repo's `shared/homepage` (static source) to `/srv/homepage`; the generated files (`status.json`, `deployed.js`) are written to the host's `/srv/homepage`. Pointed the mount at the host's `/srv/homepage` so the generated files serve. A compose change needs a container *recreate* (not a reload) — `podman compose up -d caddy` (the deploy skips the compose restart, so this is manual).
|
||||
* **Caddy KB doc** (operator request: read the docs before guessing at syntax): new `caddy/` section in this bundle — [[caddyfile|caddyfile]] (`caddy/caddyfile.md`) + `caddy/index.md`, cross-linked from the root `index.md`. Grounded in caddyserver.com (fetched 2026-08-23) + a researcher subagent brief.
|
||||
* **Tests:** 116 green (was 112; +4 for the Caddyfile handle design + the `status.json` 0644 perms). The local `caddy validate` test is skipped (no local caddy binary); the rendered config is validated on the target via the porkbun image before each deploy.
|
||||
Homepage live on Dankclaw via `scripts/deploy.sh` (status checker timer,
|
||||
deployed.js, rendered basicauth hashes, health check). Hard-won Caddy lesson:
|
||||
top-level directives are *sorted*, so `rewrite` runs before `basicauth` and
|
||||
auth matchers saw rewritten paths — serve each page from its own `handle`
|
||||
block to preserve order; a `handle` inline matcher is a single token; a
|
||||
leading `@name <directive>` parses as a matcher definition. Now documented on
|
||||
[caddy/caddyfile.md](caddy/caddyfile.md). A compose mount change needs a
|
||||
container *recreate*, not a reload. 116 tests green.
|
||||
|
||||
## 2026-08-23 — Homepage design settled (grilling complete)
|
||||
|
||||
* **All 38 open questions (Q6–Q43) answered.** The homepage design is now fully settled. Full record: `serverAppConfigs/docs/Infrastructure/Homepage Design Grilling.md` (final decisions + the deltas) and `docs/Infrastructure/Homepage.md`.
|
||||
* **Key deltas from the initial recommendations:** the probe method is **per service** (`tcp` or `http`); the probe timeout is **5 s**; the layout is **TUI-style panels** (a grid), not a flat list; styling is **toggleable** (full theme default, a toggle to bare unstyled HTML); **do not alter the user's cursor**; **no client-side auto-refresh** (read `status.json` once on load); the footer shows the **last master deployment datetime** (not last-check); the deploy is **git-driven** (master = deployed state); the build is **full TDD**.
|
||||
* **Per-service docs workstream:** each service gets a `/docs/<svc>/` page (not `/usage/`), written as a **how-to for a regular user** (no maintenance details), password-protected by the same auth as its homepage section, built as each service goes active. The existing reference docs in `docs/` are NOT linked from the homepage (they may contain secrets).
|
||||
* **Build complete (all 6 slices, full TDD, 112 tests green):** 1 the checker core (tcp/wip/atomic write/generated_at), 2 the http probe, 3 the real `services.json` + schema, 4 the pages + theme + toggle, 5 the Caddyfile auth split (root vs `/admin/`), 6 the git-driven deploy. All committed + pushed. The render logic is verified with a Node DOM shim (9 user panels, correct summary, correct footer datetime).
|
||||
* **To go live:** the operator adds `CADDY_ADMIN_HASH` (the operator-only password, `caddy hash-password`) to the Dankclaw `.env`, then runs `./scripts/deploy.sh dankclaw`. Until then the admin hash stays a placeholder. The per-service `/docs/` pages, the *arr stack, and the optional `/how/` page remain separate threads.
|
||||
* **Correction (media stack):** the Dankserver media stack (RomM, Copyparty, Jellyfin, Plex, the *arr) is **UP** — it runs as **bare processes/services, not yet migrated to podman containers**. The 2026-08-22 "down / missing `.env`" finding was wrong: I was probing for the compose stack, which is not how it runs yet. Do not treat it as an outage and do not probe it as down. Its podman migration is a separate, future effort.
|
||||
All 38 open questions answered; full record lives in serverAppConfigs
|
||||
(`docs/Infrastructure/Homepage Design Grilling.md`). Key deltas: per-service
|
||||
tcp/http probes, 5 s timeout, TUI-style panel grid, no client auto-refresh,
|
||||
git-driven deploy, full TDD. Correction recorded: the Dankserver media stack
|
||||
runs as bare processes, not containers — never probe it as a compose stack.
|
||||
|
||||
## 2026-08-22 — vllmScripts merged into serverAppConfigs
|
||||
|
||||
* **Repo merge**: the `vllmScripts` repo (LLM inference fleet: serve scripts, systemd units, env tunables, deploy runbook, research docs) is merged into `serverAppConfigs` with its full git history (two-parent import commit, then reorganization: `docs/` → `docs/LLM/`, `scripts/` merged, `old/` for retired PP/NPU-era scripts). One repo, one checkout per host (`/home/dank/serverAppConfigs`), one `scripts/deploy.sh` covering both workloads per target (podman stack + LLM service relink/restart + both health checks).
|
||||
* **Units**: frank-default-{small,large,npu}.service now point at `/home/dank/serverAppConfigs/scripts/...`. The retired target checkouts (`/home/dank/vLLM` on Dankserver, `/home/dank/vllmScripts` on Dankclaw) are to be archived on the hosts during the production deploy.
|
||||
* **Secrets**: the live sudo password that the old vllmScripts AGENTS.md documented in plaintext is NOT carried into the merged repo (a bats leak-check guards it). It remains in the git history of both repos on the LAN Gitea — rotation recommended.
|
||||
* **KB links**: `system/index.md`, `system/dankserver.md`, `system/dankclaw.md`, and the root `index.md` updated — the "sibling knowledge bases" section is now a single sibling (serverAppConfigs, which contains the LLM fleet KB at `docs/LLM/index.md`).
|
||||
* **Port move**: `frank-default-large` (dankclaw) moved from `:52625` to `:7770` (operator request: the primary inference server sits on the standard llama.cpp port). Both LLM services now listen on `:7770`, distinguished by host. `models.json` (`llamacpp (dankclaw)`) and the OpenWebUI quadlet (`OPENAI_API_BASE_URL`) re-pointed to `:7770`. `pi/models.md` updated.
|
||||
* **Homepage design (grilling)**: the `serverAppConfigs` homepage (`docs/Infrastructure/Homepage.md`) is WIP — the Caddy site is live (basicauth 401, `:80` 302) but `/srv/homepage/` is not deployed. Settled design: a single site on Dankclaw (root = user services, `/admin/` = admin services behind a second operator-only password, optional `/how/` tourist page). Status is checked **server-side** — a systemd-timer checker (every 3 min) probes each backend `host:port` and writes a same-origin `status.json`; the page reads only that file (the client-side-ping design is blocked by cross-origin + mixed-content + auth). Full decision log + 38 open questions (Q6–Q43) in `docs/Infrastructure/Homepage Design Grilling.md`. A terminal-TUI-styled HTML progress report was generated for the operator to review and answer the open questions. Full-stack baseline verified: Dankclaw fully up; the Dankserver media stack is down (only Calibre-Web + the LLM are up; no `.env` on the target).
|
||||
Full-history two-parent import; one repo, one checkout per host, one
|
||||
`deploy.sh`. The plaintext sudo password from old docs was NOT carried over
|
||||
(a bats leak-check guards it); it remains in both repos' history on the LAN
|
||||
Gitea — rotation recommended.
|
||||
|
||||
## 2026-08-21 — Fleet ops: passwordless sudo, Hermes SSH keys, sibling KB links
|
||||
## 2026-08-21 — Fleet ops: passwordless sudo, Hermes SSH keys
|
||||
|
||||
* **Passwordless sudo**: added `/etc/sudoers.d/dank-nopasswd` (`dank ALL=(ALL) NOPASSWD: ALL`) on both Dankserver and Dankclaw. Verified `sudo -n true` on both. The pre-existing drop-ins (`frank-small` on Dankserver; `frank-large` + `frank-ling` on Dankclaw) grant per-command NOPASSWD for the frank restart scripts and remain in place.
|
||||
* **Hermes SSH keys**: the Hermes Agent (podman container `hermes`, project `dankclaw` in `serverAppConfigs`, gateway drops to container uid 10000 = host uid 109999, HOME `/opt/data` on a podman volume) now has a dedicated ed25519 key at `/opt/data/.ssh/id_ed25519` (`hermes-agent@dankclaw`) plus an SSH config for `dankclaw` (192.168.0.143), `dankserver` (192.168.0.235), and the workstation. The public key is in `dank`'s `authorized_keys` on all three machines. Verified from inside the container as the hermes user: all three `ssh <host> hostname` calls succeed.
|
||||
* **Sibling KB links**: `system/index.md`, `system/dankserver.md`, `system/dankclaw.md`, and the root `index.md` now link the two sibling knowledge bases on the workstation: `~/Projects/vllmScripts/` (inference fleet scripts + runbook, index `docs/index.md`) and `~/Projects/serverAppConfigs/` (Podman deploy configs for both servers, index `docs/index.md`).
|
||||
`/etc/sudoers.d/dank-nopasswd` on both servers (per-command drop-ins remain);
|
||||
dedicated ed25519 key for the Hermes container, verified into all three
|
||||
machines.
|
||||
|
||||
## 2026-08-19 — pi-web-access: SearXNG endpoint re-pointed to dankclaw
|
||||
## 2026-08-19 — pi-web-access: SearXNG endpoint re-pointed to dankclaw (pi era)
|
||||
|
||||
* **Config**: `~/.pi/web-search.json` — `searxngBaseUrl` moved from the dead `192.168.0.235:8081` (dankserver, connection refused) to `192.168.0.143:8081` (dankclaw; verified live: HTTP 200, 25 JSON results, 0.8 s). Deleted the redundant `provider: "all"` (the `searchProvider: "searxng"` pin already wins in v0.22). Added `maxInlineContentChars: 50000`. Kept `workflow: "none"` and `ssrf.allowRanges: ["192.168.0.0/24"]`.
|
||||
* **Docs**: `pi/packages/pi-web-access.md` bumped 0.14.0 → 0.22.0 (18-provider chain, config block, active-setup note, GitHub-clone section, yt-dlp present). `agentic-web-research/` SearXNG endpoint references repointed `.235` → `.143` (index, searxng-tuning, vpn-routing).
|
||||
* **Note**: pi-web-access caches `web-search.json` in memory per process — the new endpoint takes effect on the next Pi session, not the running one.
|
||||
* **Packages**: `yt-dlp` installed on the workstation (2026.07.04) — YouTube frame extraction now works; `ffmpeg` (n9.0.1) was already present.
|
||||
`searxngBaseUrl` moved off dead `.235:8081` to `.143:8081`; pi caches
|
||||
`web-search.json` per process — new endpoint needs a new session. `yt-dlp`
|
||||
installed (2026.07.04).
|
||||
|
||||
## 2026-08-19 — SearXNG + Gluetun bring-up on dankclaw
|
||||
|
||||
Field notes from standing up the search stack (gluetun + searxng + valkey) and confirming agentic JSON search. All four are operational; the SearXNG trio runs via podman-compose (not yet boot-persistent quadlet).
|
||||
Durable field notes (now on concept pages — see
|
||||
[agentic-web-research/vpn-routing.md](agentic-web-research/vpn-routing.md),
|
||||
[searxng-tuning.md](agentic-web-research/searxng-tuning.md),
|
||||
[engineering/infra/containers.md](engineering/infra/containers.md)):
|
||||
manual-WireGuard Proton needs `VPN_SERVICE_PROVIDER=custom` + the single-peer
|
||||
`WIREGUARD_*` env names (not `protonvpn`, not `WIREGUARD_PEERS_*`); gluetun
|
||||
ships no curl and `:8000` is the control server, not health; the limiter's
|
||||
JSON cap (`API_MAX=4`/hour) is hardcoded Python — `pass_ip` is the only
|
||||
bypass; rootless podman strips client IPs on published ports, so SearXNG must
|
||||
sit behind Caddy for XFF; quadlet generator rejects `CapAdd=`/`Device=` and
|
||||
generated units enable via `[Install] WantedBy=default.target`. ComfyUI on
|
||||
gfx1151: build on AMD's ROCm base and filter the torch family out of
|
||||
ComfyUI's requirements or you clobber the gfx1151 kernels.
|
||||
|
||||
* **Gluetun manual WireGuard**: a specific-server ProtonVPN config (private key + peer + endpoint) uses `VPN_SERVICE_PROVIDER=custom`, NOT `protonvpn`. The `protonvpn` provider is account/token-based and rejects a manually-set endpoint with `endpoint port is set`. Current Gluetun uses the single-peer model: `WIREGUARD_PUBLIC_KEY`, `WIREGUARD_ENDPOINT_IP`, `WIREGUARD_ENDPOINT_PORT`, `WIREGUARD_ADDRESSES` (not the old `WIREGUARD_PEERS_*` names). DNS is Gluetun's own `DNS_*` vars, not the WG `DNS` line.
|
||||
* **Gluetun healthcheck**: the image has no `curl`, and its `:8000` status server 404s on every path. Use `test: ["CMD","sh","-c","test -e /sys/class/net/tun0"]` — tun0 exists only while the tunnel is connected.
|
||||
* **SearXNG trusted group**: lives in `limiter.toml` (not `settings.yml`). A direct hit on the published port has no `X-Forwarded-For` header, so the bot-detection cannot resolve a client and returns 429 regardless of `pass_ip`. SearXNG must be reached through Caddy (which sets XFF); `trusted_proxies` then needs the podman bridge subnet (dynamic in rootless — pin the network CIDR) so Caddy's source is trusted for XFF extraction.
|
||||
* **Rootless podman gotchas**: short image names do not resolve (no unqualified-search registries) — qualify with `docker.io/`. Binding privileged ports (Caddy 80/443) needs the one-time sysctl `net.ipv4.ip_unprivileged_port_start=80`.
|
||||
* **Repo**: `serverAppConfigs` — added `shared/searxng/limiter.toml` + test seam, wired it into `deploy.sh`, fixed the Gluetun compose (peer env vars, qualified images, tun0 healthcheck), documented the rootless-port + Caddy/XFF gotchas, and skipped the ComfyUI GPU tests (migration pending).
|
||||
* **Boot-persistence (quadlet)**: converted the trio from podman-compose to quadlet so it survives reboot. searxng sets `Network=gluetun.container` (reuses gluetun's netns → exits the tunnel); gluetun + valkey join a pinned `searxng.network` (10.89.2.0/24). Deployed via `scripts/deploy-searxng-quadlet.sh`. Field gotchas (also in `engineering/infra/containers.md`): the generator rejects `CapAdd=`/`Device=` (use `AddCapability=`/`AddDevice=`) and silently skips the unit; generated units cannot be `systemctl enable`d — `[Install] WantedBy=default.target` is the enablement (`is-enabled` = "generated"), and linger makes them boot-start. Verified: all three `is-enabled` = generated, tunnel up (US-WA), agentic JSON search returns 27 on-topic results.
|
||||
* **open-webui moved to dankclaw (quadlet)**: the old open-webui was a bare container on Dankserver (:3000) pointing at a dead `:9090` backend. It now runs on Dankclaw as a boot-persistent quadlet (`scripts/deploy-open-webui-quadlet.sh`): CPU image `:main` (Dankclaw is CPU-only), isolated on `Network=slirp4netns`, published `:3005` (:3000 is Gitea's HTTP port), data at `/home/dank/Containers/open-webui/data`. Default LLM backend is the local vLLM (`host.containers.internal:52625`). The Dankserver `searxng` + `open-webui` bare containers were retired (data dirs preserved). `podman inspect <name>` can match an IMAGE, not just a container — a removed container still "exists" to inspect if its image remains; use `podman ps -a --filter name=` to check containers.
|
||||
* **Model/port mapping corrected (live, 2026-08-19)**: the fleet endpoints are the REVERSE of the 2026-08-17 note. Live truth (probed `/v1/models`): `frank-default-large` is on **Dankclaw :52625** (vLLM, completion) and `frank-default-small` is on **Dankserver :7770** (llama.cpp FastMTP, completion+multimodal). The `serverAppConfigs` docs (Stack, OpenWebUI) were corrected; the sibling `vllmScripts` KB still carries the old mapping and should be updated there.
|
||||
* **SearXNG 429 root cause (the "diva")**: the limiter's JSON cap is `API_MAX = 4` requests/IP/hour and that constant is **hardcoded in Python** (`searx/botdetection/ip_limit.py`), NOT settable in `limiter.toml`. The only bypass is `pass_ip` (SearXNG's `filter_request` returns before `ip_limit` runs when the IP is in `pass_ip`). Second gotcha: **rootless podman strips the client IP on published-port hits** — a request to the published port reaches the container with a slirp/bridge source (`10.88.x`/`10.89.x`), never the real client; only Caddy's `X-Forwarded-For` restores it. So even a LAN-IP curl 429'd. Fix: expand `pass_ip` to loopback (`127.0.0.1/32`, `::1`) + the host's private podman/slirp ranges (`10.88.0.0/16`, `10.89.0.0/16`) + the LAN. Verified: 20 concurrent JSON searches → all 200 (real results), while a spoofed public IP (8.8.8.8) still 429s (limiter still armed). The config file is root-owned (uid of the rootless podman namespace) — update with a one-off `sudo cp` + `systemctl --user restart searxng.service`.
|
||||
* **ComfyUI GPU (gfx1151) — DONE (Option 1/B)**: the deferred GPU ComfyUI is now built and running. It was previously a bare CPU venv (`/home/dank/ComfyUI`, py3.14, `torch 2.13.0+cu130` with no NVIDIA → CPU fallback). Now it's a **container** `comfyui-rocm:gfx1151` built from `dankclaw/Containerfile.comfyui` on AMD's `rocm/vllm:rocm7.12.0_gfx1151_..._py3.12_pytorch_2.9.1` base (the only torch build where `torch.cuda.is_available()=True` on the Strix Halo APU). Key gotchas: (1) the base image already ships the ROCm torch/torchvision/torchaudio, so the Containerfile must **skip the torch family** from ComfyUI's `requirements.txt` (an unpinned `torch` would clobber the gfx1151 kernels) — filter with `grep -viE '^(torch|torchvision|torchaudio)([^a-z]|$)'`. (2) **rootless podman cannot `--group-add render`** (gid 990 is outside the subgid range 100000+); GPU access comes from the `/dev/kfd`+`/dev/dri` passthrough checked host-side (the run user is already in `render`), so add only the `video` group. Verified: `/system_stats` → `cuda:0 Radeon 8060S`, logs show `AMD arch: gfx1151` + active HIP backend. Boot-persistent via a user systemd unit running `podman compose up -d comfyui` (old venv unit saved as `comfyui.service.venv.bak`). The 4 `comfyui_rocm.bats` tests are un-skipped (the group test now asserts video present + render ABSENT).
|
||||
## 2026-08-17 — Fleet redo + vLLM tool calling (pi era)
|
||||
|
||||
## 2026-08-17 — Fleet redo + vLLM tool calling
|
||||
Fleet moved off the pipeline-parallel + NPU topology; Quark W8A8 quant chosen
|
||||
over the Avesed INT8 for clean Qwen3 XML tool calls.
|
||||
|
||||
* **Update**: `pi/models.md` — providers rewritten for the fleet redo: `llamacpp (dankserver)` at :7770 and `vllm (dankclaw)` at :52625; model selection strategy and live defaults brought in line with the new topology and the Quark W8A8 model.
|
||||
* **Context**: the Frank fleet moved off the pipeline-parallel + NPU topology. `frank-default-large` (llama.cpp FastMTP, IQ4_XS) is on Dankserver; `frank-default-small` (vLLM ROCm, nameistoken Qwen3.6-35B-A3B Quark W8A8 INT8) is on Dankclaw with ngram spec and tool calling. The Avesed INT8 quant's tool-call XML fidelity was poor; the Quark quant follows the Qwen3 XML format cleanly.
|
||||
## 2026-08-16 — Gitea boot-persistence fix (dankclaw)
|
||||
|
||||
`unattended-upgrades` reboot exposed that the compose-era Gitea had no
|
||||
systemd units (~1 h down). Stack rewritten as quadlet (names, `systemd-gitea`
|
||||
network, linger + `WantedBy=default.target`, app.ini env-override gotcha, UID
|
||||
100999 ownership) across `tools/gitea/*`; `podman generate systemd` marked
|
||||
deprecated in [engineering/infra/containers.md](engineering/infra/containers.md).
|
||||
|
||||
## 2026-08-16
|
||||
## 2026-08-13 — Pi subagent limits recorded (pi era)
|
||||
|
||||
### Gitea Boot-Persistence Fix (dankclaw)
|
||||
Effective caps: globalConcurrencyLimit 2, parallel.maxTasks 8 / concurrency 4,
|
||||
maxSubagentDepth 2, turnBudget 30; no per-model limit. See
|
||||
[pi/packages/pi-subagents.md](pi/packages/pi-subagents.md).
|
||||
|
||||
* **Incident**: `unattended-upgrades` rebooted dankclaw at 15:01. The legacy podman-compose Gitea stack had no systemd units, so rootless podman did not auto-start the containers. Gitea was down ~1 hour.
|
||||
* **Update**: `tools/gitea/index.md`, `architecture.md`, `management.md`, `data-persistence.md` — rewritten for the quadlet-managed stack: container/unit names, the `systemd-gitea` network (DNS-enabled), boot persistence (linger + `WantedBy=default.target`), the app.ini env-override gotcha, UID 100999 ownership, incident log.
|
||||
* **Update**: `engineering/infra/containers.md` — marked `podman generate systemd` deprecated (podman 5.7), documented Quadlet with a field-tested gotcha list (default network DNS off, `[Service] EnvironmentFile=` for `${VAR}` expansion, unit naming, bind-mount UID mapping).
|
||||
## 2026-08-11 — Engineering research area; skills leaderboard verified
|
||||
|
||||
## 2026-08-13
|
||||
Created `engineering/` (SDLC, agent instruction files, stacks, infra,
|
||||
plugins, skills ecosystem, Signal remote) via parallel research fleet.
|
||||
Skills leaderboard replaced with the ranked list from the skills.sh API
|
||||
(zero-based pagination, 200-skill pages).
|
||||
|
||||
### Pi Subagents Limits
|
||||
## 2026-08-11 — Agentic web research section; exhaustive bundle audit
|
||||
|
||||
* Added a "Parallel Execution and Limits" section to `pi/packages/pi-subagents.md`.
|
||||
* Documented the effective values: `globalConcurrencyLimit` 2 (from `extensions/subagent/config.json`), `parallel.maxTasks` 8, `parallel.concurrency` 4, `maxSubagentSpawnsPerSession` unlimited, `maxSubagentDepth` 2, and `turnBudget.maxTurns` 30.
|
||||
* Noted that no per-model limit exists; all caps are global to a run or a session.
|
||||
Created `agentic-web-research/` (8 pages) and rewrote them on 2025/2026
|
||||
evidence (SearXNG valkey deployment, real engine defaults, limiter budgets,
|
||||
Gluetun pattern, open-model claim triage, MCP transports). Audit: 154+
|
||||
wikilinks resolved, dead external links fixed, `MemorySleepMode=deep`
|
||||
verified valid (systemd 256+), ASD-STE100 style pass. `AGENTS.md` created as
|
||||
the system behavior contract.
|
||||
|
||||
## 2026-08-11 (continued)
|
||||
## 2026-08-06 — Link fixes; ComfyUI docs; major documentation overhaul
|
||||
|
||||
### Engineering Research — New Area
|
||||
Fixed 15 broken wikilinks (missing frontmatter) + title mismatches → zero
|
||||
broken. Added ComfyUI pages, per-host system docs, pi config tree, tools
|
||||
entries; orphaned root duplicates moved to `.AGENTTRASH/`.
|
||||
|
||||
* Created the `engineering/` research area: SDLC and tooling, agent instruction files, language and framework stacks, infrastructure and cloud, pi plugins, skills ecosystem, and Signal remote control.
|
||||
* Ran a parallel research fleet (scout + 6 researchers) grounded in current 2025/2026 web sources.
|
||||
## 2026-07-18 — Maintenance tooling
|
||||
|
||||
### Skills Leaderboard — Live Verification
|
||||
Expanded `references/okf-maintenance.md` (cross-links, health metrics,
|
||||
troubleshooting); created `core/log.md` and `.okf/config.yaml`.
|
||||
|
||||
* Queried the skills.sh API (`GET /api/skills/all-time/{page}`) for the authoritative top 50 skills by all-time installs.
|
||||
* Replaced the inferred category table in `engineering/skills-ecosystem.md` with the verified ranked list.
|
||||
* Noted the API’s zero-based pagination and 200-skill page size for future queries.
|
||||
## 2026-01-15 — OKF conversion
|
||||
|
||||
## 2026-08-11 (continued)
|
||||
|
||||
### Agentic Web Research — Grounded Revision
|
||||
|
||||
* Ran a parallel research fleet (7 researchers + 2 scouts) for current 2025-2026 evidence on SearXNG tuning, VPN split-routing, agentic search, open models, research orchestration, and MCP.
|
||||
* Rewrote all 8 `agentic-web-research/` pages to match verified facts and the local topology: SearXNG at `192.168.0.235:8081`, llama.cpp inference on `7770` (dankserver/dankclaw) and `8080` (local-ornith), main model `openrouter/deepseek-v4-flash-0731`.
|
||||
* SearXNG: corrected to Valkey deployment, real engine defaults (DuckDuckGo/Wikipedia/Google News active, Google inactive, Bing disabled), limiter budgets, current `outgoing` defaults.
|
||||
* VPN: added Gluetun as the recommended pattern, corrected OpenVPN container joins, added `source_ips`/`network: ipv4`.
|
||||
* Open models: clarified Llama 4 claims (10M ctx = Scout only, single-H100 needs INT4, "beats GPT-4o" is Meta-only), added Qwen2.5-VL-7B as best self-hostable vision model.
|
||||
* Web agents: corrected the Browser Use "87.4%" claim (managed Cloud variant, not open-source; peer-reviewed 44.5% for CUA), added Skyvern.
|
||||
* MCP: updated transports (stdio + Streamable HTTP, legacy SSE), current reference servers, added SearXNG MCP, tightened security rules.
|
||||
|
||||
### Exhaustive Bundle Audit
|
||||
|
||||
* Link audit: resolved all 154+ wikilinks by frontmatter title — **0 broken wikilinks**. Fixed relative-link base errors in `core/index-doc.md`, `packages/index.md`, `pi-web-access.md`, `llama-cpp/setup.md`, `npx-skills/skill-commands.md`, `packages/pi-browser-use/index.md`.
|
||||
* External URL audit: fixed dead links (SearXNG limiter path, earendil-works/pi blob URLs, AYayOS/qs -> outfoxxed/quickshell, badlogic/pi-mono -> earendil-works/pi).
|
||||
* Factual fixes: `core/settings.md` stale JSON (defaultProvider/model/thinkingLevel/changelog-version), `pi/models.md` dankclaw auth, `Sleep-Fix-Guide.md` kernel 7.1.3 -> 7.1.4.
|
||||
* Verified (did not change) `MemorySleepMode=deep`: it is a valid systemd 256+ option.
|
||||
* ASD-STE100 style pass: removed contractions, banned `may`, and prose semicolons across research/tools/pi docs.
|
||||
* Added OKF index frontmatter to `core/index.md` and `skills/index.md`.
|
||||
* Added a "Pi-peon is installed" note to the npx skills ecosystem table and a port-7770 system note to llama.cpp docs.
|
||||
|
||||
### Agentic Web Research Section
|
||||
|
||||
* Created `agentic-web-research/` — seven new concept pages plus index covering self-hosted web agents, SearXNG tuning, VPN routing, agentic search practices, open models, research effectiveness, and model context protocol.
|
||||
* Expanded via parallel research: concrete BM25/Pruning/LLM content filters, credibility heuristics, failure-mode guardrails, MCP server and transport guidance.
|
||||
* Added the section to `index.md` under a new `## [Agentic Web Research]` heading.
|
||||
* Linked `pi/packages/pi-web-access.md` to the new section.
|
||||
|
||||
### System Instruction File
|
||||
|
||||
* Created `AGENTS.md` — system behavior contract with a dedicated layer on parallel subagent execution (one `subagent` call with `tasks` + `concurrency`).
|
||||
|
||||
### Bundle Audit
|
||||
|
||||
* Verified all 154 wikilinks resolve (zero broken).
|
||||
* Removed stale empty `Alienware M16a2 Sleep/Wake Issues.md` duplicate into `.AGENTTRASH`.
|
||||
* ran ASD-STE100 style pass: converted `should` to imperative or `must`, and `e.g.` to `for example` across 10 files.
|
||||
* Removed stale `frank-default-omni` model references and corrected dankclaw port `13305` to `8080` per commit `15d4af4`.
|
||||
* **Resolved**: the live config is authoritative. Updated both llama.cpp servers to port `7770` and set the default provider to `openrouter` (deepseek) per `settings.json`. Dankserver/dankclaw now 7770; main session default is openrouter.
|
||||
|
||||
## 2026-08-06 (continued)
|
||||
|
||||
### Link Fixes
|
||||
|
||||
* Fixed 15 broken wikilinks — added missing YAML frontmatter to `ghostty/index.md`, `tmux/index.md`, `linux-power-management/index.md`, `gitea/index.md`, `gitea/architecture.md`, `gitea/data-persistence.md`, `gitea/management.md`
|
||||
* Fixed title mismatches: `OKF v0.1 Specification` → `Open Knowledge Format (OKF) v0.1 Specification`, `Pi Settings` → `Pi Settings System (settings.json)`, `Alienware M16a2 Sleep/Wake Issues` → `Alienware M16a2 Linux Sleep/Wake Issues`, `Architecture Details` → `Gitea Architecture`, `Data Persistence` → `Gitea Data Persistence`, `Management Guide` → `Gitea Management`
|
||||
* Zero broken links remaining (47 links verified)
|
||||
|
||||
## 2026-08-06
|
||||
|
||||
### ComfyUI Documentation
|
||||
|
||||
* `tools/comfyui/index.md` — ComfyUI setup on dankclaw, architecture, service management
|
||||
* `tools/comfyui/troubleshooting.md` — Common errors, diagnostics, recovery steps
|
||||
* `tools/index.md` — Added ComfyUI entry
|
||||
* `system/dankclaw.md` — Added ComfyUI service, hardware specs, services section
|
||||
|
||||
### Major Documentation Overhaul
|
||||
|
||||
**Created — System Documentation**
|
||||
|
||||
* `system/index.md` — System documentation index with infrastructure diagram
|
||||
* Per-host system pages (overview, hardware specifications, display configuration, network interfaces) for the workstation — retired later; see `/system/network.md` and `/tools/niri/displays.md`
|
||||
* `system/dankserver.md` — Primary llama.cpp server documentation
|
||||
* `system/dankclaw.md` — Secondary llama.cpp server documentation
|
||||
|
||||
**Created — Pi Configuration**
|
||||
|
||||
* `pi/index.md` — Pi configuration overview with architecture diagram
|
||||
* `pi/settings.md` — Main settings.json reference (moved from core/)
|
||||
* `pi/models.md` — models.json provider and model definitions
|
||||
* `pi/packages/index.md` — Installed packages index
|
||||
* `pi/packages/pi-peon.md` — CESP/OpenPeon sound-pack player
|
||||
* `pi/packages/pi-web-access.md` — Web search, fetching, video understanding
|
||||
* `pi/packages/pi-subagents.md` — Core subagent delegation
|
||||
* `pi/skills/index.md` — Installed agent skills inventory
|
||||
|
||||
**Created — Tools**
|
||||
|
||||
* `tools/cachyos/index.md` — CachyOS documentation (kernel, repos, gaming stack)
|
||||
* `tools/noctalia-shell/index.md` — Noctalia Shell with Niri integration
|
||||
* `tools/applications/index.md` — Default applications reference
|
||||
|
||||
**Updated**
|
||||
|
||||
* `core/settings.md` — Updated with current config, subagent overrides, cross-links
|
||||
* `tools/niri/index.md` — Rewritten with actual system configuration
|
||||
* `tools/index.md` — Added CachyOS, Noctalia, Applications entries
|
||||
* `index.md` — Complete rewrite with new sections and cross-links
|
||||
|
||||
**Moved / Cleaned**
|
||||
|
||||
* `tmux.md` → `tools/tmux/index.md`
|
||||
* Orphaned root duplicates → `.AGENTTRASH/` (npx-skills.md, okf-maintenance.md, okf-spec.md, vercel-labs-skills.md, vercel-labs-skills-find-skills.md, ornith-llama-cpp-setup.md)
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-18
|
||||
|
||||
* **Enhancement**: Expanded `okf-maintenance.md` — added cross-link management, index management, health metrics, troubleshooting, and quick reference card
|
||||
* **Creation**: `core/log.md` — change log for the core documentation directory
|
||||
* **Creation**: `.okf/config.yaml` — bundle tooling configuration
|
||||
* **Update**: `core/index.md` — added log.md entry and cross-references
|
||||
|
||||
## 2026-01-15
|
||||
|
||||
* **Initialization**: Converted docs bundle to OKF v0.1 format
|
||||
* **Migration**: Migrated files to `core/`, `tools/`, `packages/`, `references/` directories
|
||||
* **Applied**: OKF frontmatter to all files
|
||||
Docs bundle converted to OKF v0.1; files migrated into `core/`, `tools/`,
|
||||
`packages/`, `references/` with frontmatter on all files.
|
||||
|
||||
## 2025-08-05 — Gitea documentation
|
||||
|
||||
Added ](tools/gitea/index.md) documentation to tools. Covers:
|
||||
|
||||
* [[architecture|architecture]] — Container topology, Caddy reverse proxy, network diagram.
|
||||
* [[management|management]] — Podman commands, upgrades, troubleshooting.
|
||||
* [[data-persistence|data-persistence]] — Volume mounts, backup strategy, restore procedures.
|
||||
|
||||
Updated tools index.
|
||||
Added [tools/gitea/index.md](tools/gitea/index.md) (topology, management,
|
||||
data persistence) to the tools index.
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Pi Packages
|
||||
|
||||
Self-contained extensions and tools bundled as npm packages, distributed via the `pi install` system. Each package contains extensions, skills, prompts, or themes.
|
||||
|
||||
---
|
||||
|
||||
## Concept Files
|
||||
|
||||
* [pi-browser-use](pi-browser-use.md) — Browser automation extension wrapping chrome-devtools-mcp with `browser_` prefix, full config reference, session modes, and vision model setup.
|
||||
* [pi-permission-system](pi-permission-system.md) — Permission enforcement and policy configuration system with 10 interconnected docs.
|
||||
|
||||
## Cross-References
|
||||
|
||||
- All packages are installed via `pi install npm:<name>` and loaded by pi's extension system.
|
||||
- See [Npx Skills](../skills/npx-skills.md) for the pi-package distribution mechanism and package.json manifest format.
|
||||
+18
-32
@@ -1,37 +1,28 @@
|
||||
# Pi Configuration
|
||||
# Pi Configuration (archive)
|
||||
|
||||
> **Archive note (2026-10-18).** Most pages in this directory document the retired
|
||||
> **pi** harness (settings.json / models.json, `frank-default-*` endpoints, verified
|
||||
> 2026-08-28). The live harness is **omp** — its config is `agent/config.yml` +
|
||||
> `agent/models.yml` in this repo, the current fleet endpoints are on
|
||||
> [System hosts](/system/index.md), and omp-specific knowledge lands in pages like
|
||||
> [OMP Status Line Customization](/pi/statusline.md) below. Read pi pages as
|
||||
> historical records, not current state.
|
||||
> **Archive (2026-10-18).** This directory documents the retired **pi** harness
|
||||
> (`settings.json` / `models.json`, `frank-default-*` endpoints). The live
|
||||
> harness is **omp**: config in `agent/config.yml` + `agent/models.yml` (this
|
||||
> repo), fleet endpoints on [System hosts](/system/index.md). Read these pages
|
||||
> as historical records, not current state. Knowledge that survived the harness
|
||||
> move lives under [Core](/core/index.md):
|
||||
> [OMP Status Line](/core/statusline.md) and
|
||||
> [OMP Subagent Limits](/core/subagent-limits.md).
|
||||
|
||||
## Configuration Files
|
||||
## Configuration Files (pi-era)
|
||||
|
||||
- [Pi Settings System (settings.json)](/core/settings.md) — Main `settings.json` reference. Providers, models, packages, subagent overrides.
|
||||
- [Pi Models Configuration](/pi/models.md) — `models.json` reference. Provider definitions, model specs, endpoints.
|
||||
- [OMP Status Line Customization](/pi/statusline.md) — How presets, composer shapes, and segment arrays actually interact; the fleet's tuned bar.
|
||||
- [Pi Settings System (settings.json)](/core/settings.md) — Main `settings.json` record. Providers, models, packages, subagent overrides.
|
||||
- [Pi Models Configuration](/pi/models.md) — `models.json` record. Provider definitions, model specs, endpoints.
|
||||
|
||||
## Extensions
|
||||
## Extensions (pi-era)
|
||||
|
||||
- [Pi Packages](/pi/packages/index.md) — Installed npm packages that extend pi functionality.
|
||||
- [Pi Peon](/pi/packages/pi-peon.md) — CESP/OpenPeon sound-pack player for lifecycle events.
|
||||
- [Pi Web Access](/pi/packages/pi-web-access.md) — Web search, URL fetching, GitHub cloning, PDF extraction, video understanding.
|
||||
- [Pi Browser Use](/packages/pi-browser-use.md) — Browser automation extension wrapping chrome-devtools-mcp with a `browser_` prefix.
|
||||
- [Pi Permission System](/packages/pi-permission-system.md) — Permission enforcement and policy configuration for subagent extensions.
|
||||
- [Pi Packages](/pi/packages/index.md) — installed npm packages: peon, web-access, subagents, browser-use, permission-system.
|
||||
|
||||
## Skills
|
||||
## Skills (pi-era)
|
||||
|
||||
- [Pi Skills](/pi/skills.md) — Installed agent skills. Symlinked from `~/.agents/skills/` and `~/.pi/agent/skills/`.
|
||||
- [Pi Skills](/pi/skills.md) — installed skills inventory. Current skill toolchain: [Skills](/skills/index.md).
|
||||
|
||||
## Subagent Architecture
|
||||
|
||||
- [OMP Subagent Limits & Fan-out Policy](/pi/subagent-limits.md) — Live caps: concurrency 2, no nested spawns (and the `maxRecursionDepth: 0` trap), per-endpoint in-flight ceilings, isolation policy.
|
||||
- [Pi Subagents](/pi/packages/pi-subagents.md) — (historical) pi-era delegation system. Chains, parallel execution, TUI clarification.
|
||||
|
||||
## Architecture
|
||||
## Architecture (pi-era)
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
@@ -51,7 +42,7 @@ graph TD
|
||||
M --> O[dankclaw 192.168.0.143:7770]
|
||||
```
|
||||
|
||||
## Note on the Live Default
|
||||
## Note on the Live Default (historical)
|
||||
|
||||
In the pi era, `models.json` defined the live provider set: the main session
|
||||
provider was `llamacpp` with default model `frank-default-large` (Dankclaw);
|
||||
@@ -60,8 +51,3 @@ to `frank-default-large`. Two scopes owned settings: the user
|
||||
`~/.pi/settings.json` (main → Dankclaw/large) and the project
|
||||
`/home/dank/.pi/agent/settings.json` (main → Dankserver/small); when they
|
||||
disagreed, the project-scope file won for the agent's own main session.
|
||||
|
||||
> **Note:** This documentation describes the pi-coding-agent harness (config
|
||||
> format, packages, skill system) as general reference material. The live
|
||||
> harness is OMP at `~/.omp/`; OMP-managed skills live in
|
||||
> `~/.omp/agent/managed-skills/`.
|
||||
|
||||
@@ -145,4 +145,3 @@ The subagent model IDs (`frank-default-small`, `frank-default-large`) resolve ag
|
||||
- [[settings|settings]] — Main configuration file
|
||||
- [[dankserver|dankserver]] — Primary llama.cpp server
|
||||
- [[dankclaw|dankclaw]] — Secondary llama.cpp server
|
||||
- [ornith-llama-cpp-setup](../tools/ornith-llama-cpp-setup/index.md) — Local Ornith model setup
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
# Pi Packages
|
||||
|
||||
Pi extends its functionality through npm packages installed via `pi install`. Each package provides extensions, skills, prompts, or themes.
|
||||
Pi extended itself through npm packages (`pi install npm:<name>`), each
|
||||
bundling extensions, skills, prompts, or themes. The harness is retired
|
||||
(2026-10-18); this page is the merged census of what was installed — one row
|
||||
per package, detail pages kept as historical records.
|
||||
|
||||
## Installed Packages
|
||||
## Installed packages
|
||||
|
||||
| Package | Version | Description |
|
||||
|---------|---------|-------------|
|
||||
| [[pi-peon|pi-peon]] | 0.1.1 | CESP/OpenPeon sound-pack player for pi lifecycle events |
|
||||
| [[pi-web-access|pi-web-access]] | 0.22.0 | Web search, URL fetching, GitHub cloning, PDF extraction, video understanding |
|
||||
| Package | Version | Detail | What it did |
|
||||
|---------|---------|--------|-------------|
|
||||
| `@wierdbytes/pi-peon` | 0.1.1 | [Pi Peon](pi-peon.md) | CESP/OpenPeon sound-pack player for pi lifecycle events. |
|
||||
| `pi-web-access` | 0.22.0 | [Pi Web Access](pi-web-access.md) | Web search, URL fetching, GitHub cloning, PDF extraction, video understanding. |
|
||||
| `pi-subagents` | 0.36.0 | [Pi Subagents](pi-subagents.md) | Core subagent delegation — chains, parallel execution, TUI clarification. |
|
||||
| `pi-browser-use` | — | [Pi Browser Use](pi-browser-use.md) | Browser automation wrapping chrome-devtools-mcp behind a `browser_` prefix. |
|
||||
| `pi-permission-system` | — | [Pi Permission System](pi-permission-system.md) | Permission enforcement and policy configuration; upstream docs are 10 interlinked pages. |
|
||||
|
||||
## Core Extension
|
||||
## Where the concepts live now
|
||||
|
||||
| Package | Version | Description |
|
||||
|---------|---------|-------------|
|
||||
| [[pi-subagents|pi-subagents]] | 0.36.0 | Core subagent delegation — chains, parallel execution, TUI clarification |
|
||||
|
||||
---
|
||||
* Subagent delegation → [OMP Subagent Limits & Fan-out Policy](/core/subagent-limits.md) (live caps).
|
||||
* Skill/package distribution → [Skills](/skills/index.md) (Agent Skills standard + `skills` CLI).
|
||||
* Web access → the `web/searxng` provider and MCP tooling; see [Agentic web research](/agentic-web-research/index.md).
|
||||
|
||||
## See Also
|
||||
|
||||
- [[settings|settings]] — Package configuration in settings.json
|
||||
- [pi](../index.md) — Pi configuration overview
|
||||
|
||||
* [Pi Peon](pi-peon.md) — CESP/OpenPeon sound-pack player for pi lifecycle events — peons, GLaDOS, battlecruisers, and 300+ community sound packs.
|
||||
|
||||
* [Pi Subagents](pi-subagents.md) — Core pi extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification.
|
||||
|
||||
* [Pi Web Access](pi-web-access.md) — Web search, URL fetching, GitHub cloning, PDF extraction, and video understanding for Pi. Zero-config with Exa MCP.
|
||||
- [Pi Settings System](/core/settings.md) — where these packages were registered (`settings.json` archive).
|
||||
- [Pi Configuration](/pi/index.md) — pi-era overview.
|
||||
|
||||
@@ -113,5 +113,5 @@ Resolves API key and base URL from the model registry automatically.
|
||||
|
||||
## Cross-References
|
||||
|
||||
- See [Npx Skills](../skills/npx-skills.md) for the pi-package distribution system.
|
||||
- See [OKF Specification](../references/okf-spec.md) for the knowledge bundle format.
|
||||
- See [Skills](/skills/index.md) for the skill toolchain that replaced pi-package distribution.
|
||||
- See [OKF Specification](/references/okf-spec.md) for the knowledge bundle format.
|
||||
@@ -81,5 +81,5 @@ The `/peon` command opens an interactive settings modal with:
|
||||
|
||||
## See Also
|
||||
|
||||
- [packages](../../packages/index.md) — Package overview
|
||||
- [Pi Packages](index.md) — Package overview
|
||||
- [pi](../index.md) — Pi configuration
|
||||
|
||||
+2
-2
@@ -33,5 +33,5 @@ timestamp: 2026-08-28
|
||||
|
||||
## Cross-References
|
||||
|
||||
- See [Npx Skills](../skills/npx-skills.md) for the pi-package distribution system.
|
||||
- See [AGENTS.md Format](../core/agents-md-format.md) for the system-level instruction format that governs how this system is referenced in agent contracts.
|
||||
- See [Skills](/skills/index.md) for the skill toolchain that replaced pi-package distribution.
|
||||
- See [AGENTS.md Format](/core/agents-md-format.md) for the system-level instruction format that governs how this system is referenced in agent contracts.
|
||||
@@ -44,4 +44,4 @@ Agent skills teach the agent new workflows. Skills are stored in `~/.pi/agent/sk
|
||||
## See Also
|
||||
|
||||
- [pi](index.md) — Pi configuration overview
|
||||
- [[npx-skills|npx-skills]] — Skill distribution via npm
|
||||
- [Skills documentation](../skills/index.md) — the standard, CLI, and store wiring (current harness)
|
||||
|
||||
@@ -8,7 +8,7 @@ tags:
|
||||
- documentation
|
||||
- best-practices
|
||||
- unverified
|
||||
timestamp: 2026-01-15
|
||||
timestamp: 2026-10-19
|
||||
---
|
||||
|
||||
# OKF Bundle Maintenance
|
||||
@@ -139,6 +139,27 @@ git status --short # What is uncommitted
|
||||
| `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
|
||||
|
||||
@@ -8,11 +8,20 @@ tags:
|
||||
- documentation
|
||||
- knowledge-bundle
|
||||
- specification
|
||||
verified: 2026-08-28
|
||||
verified: 2026-10-19
|
||||
timestamp: 2026-01-15
|
||||
---
|
||||
|
||||
> **Note:** Google Cloud published OKF v0.2 at [GoogleCloudPlatform/open-knowledge-format](https://github.com/GoogleCloudPlatform/open-knowledge-format) with additional frontmatter families for provenance, trust, and attestation. This document covers the v0.1 format used by this knowledge bundle.
|
||||
> **Note:** Google Cloud published OKF v0.2 at
|
||||
> [GoogleCloudPlatform/open-knowledge-format](https://github.com/GoogleCloudPlatform/open-knowledge-format)
|
||||
> (SPEC.md, verified 2026-10-19). v0.2 is a minor bump with two deliberate
|
||||
> breaking changes: `timestamp` is superseded by `generated: { by, at }`, and the
|
||||
> body `# Citations` list is superseded by a `sources` frontmatter family; it adds
|
||||
> optional trust/lifecycle fields (`verified: { by, at }`, `status`,
|
||||
> `stale_after`) and the `Attested Computation` type, and permits `okf_version:`
|
||||
> frontmatter in a bundle-root `index.md`. This bundle stays on v0.1 semantics
|
||||
> (kb-lint enforces them); the bundle-local `verified:` date stamp and `tags`
|
||||
> discipline are producer extensions compatible with both versions.
|
||||
|
||||
# Open Knowledge Format (OKF) v0.1
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: reference
|
||||
title: Alienware M16a2 Linux Sleep/Wake Issues
|
||||
description: Comprehensive research on NVIDIA GPU driver state corruption during suspend/resume on Alienware M16a2 with Linux.
|
||||
description: "Sleep/wake research on the Alienware m16 R2 (dankware, sold 2026-09-28): NVIDIA driver state corruption during suspend/resume on Dell hardware. Kept as class-level Dell/Alienware + NVIDIA knowledge."
|
||||
tags:
|
||||
- research
|
||||
- sleep-wake
|
||||
@@ -12,6 +12,13 @@ timestamp: 2026-01-15
|
||||
|
||||
# Alienware M16a2 Linux Sleep/Wake Issues — Comprehensive Research
|
||||
|
||||
> **Machine archive (2026-10-19).** "This system" throughout is **dankware**,
|
||||
> the Alienware m16 R2 client workstation sold 2026-09-28 (see `log.md`). The
|
||||
> current dev workstation (`blankpad` — AMD Ryzen 5 PRO 5650U / Cezanne APU,
|
||||
> s2idle only, no NVIDIA GPU) is not this machine. Hardware inventory and
|
||||
> driver versions are historical; the class-level Dell/Alienware + NVIDIA
|
||||
> suspend research is retained as durable knowledge.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The symptom — **screen stays black after waking from sleep (lid close)** — is a well-documented class of issues on Dell/Alienware laptops with NVIDIA GPUs running Linux. The root cause is almost always **NVIDIA GPU driver state corruption during suspend/resume**, compounded by ACPI/sleep state selection issues and BIOS/firmware settings.
|
||||
@@ -21,7 +28,7 @@ The symptom — **screen stays black after waking from sleep (lid close)** — i
|
||||
## 1. Known Issues with Alienware M16a2 + Linux Sleep States
|
||||
|
||||
### 1.1 Model Context
|
||||
The Alienware m16 R2 (this system) is equipped with:
|
||||
The Alienware m16 R2 (the retired **dankware** box) is equipped with:
|
||||
- **Intel Core Ultra 7 155H** (Meteor Lake, 6p+8e cores, 22 threads)
|
||||
- **Intel Arc Graphics** (Meteor Lake-P iGPU)
|
||||
- **NVIDIA GeForce RTX 4070 Laptop GPU** (AD106M, Max-Q/Mobile)
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
---
|
||||
type: guide
|
||||
title: Sleep Fix Guide
|
||||
description: Fix guide for Alienware M16a2 sleep/wake issues on CachyOS with NVIDIA RTX 40-series GPU.
|
||||
tags:
|
||||
- research
|
||||
- sleep-wake
|
||||
- fix
|
||||
- nvidia
|
||||
timestamp: 2026-01-15
|
||||
---
|
||||
z
|
||||
# Alienware M16a2 Sleep/Wake Fix Guide
|
||||
|
||||
Based on diagnostics from your system (CachyOS, Kernel 7.1.4, NVIDIA RTX 40-series)
|
||||
|
||||
---
|
||||
|
||||
## Problem Summary
|
||||
|
||||
Your system enters sleep when closing the lid, but the screen stays black on wake. Diagnostics show:
|
||||
- **Sleep state:** s2idle (Modern Standby) - problematic for NVIDIA hybrid GPUs
|
||||
- **NVIDIA services:** Disabled (nvidia-suspend.service, nvidia-resume.service)
|
||||
- **Kernel errors:** ACPI D-Notifier failures, spd5118 resume errors
|
||||
|
||||
---
|
||||
|
||||
## Fix #1: Enable NVIDIA Suspend Services (⚠️ MOST IMPORTANT)
|
||||
|
||||
This is the #1 cause of your issue. The NVIDIA GPU state is not being preserved during suspend.
|
||||
|
||||
```bash
|
||||
# Enable the NVIDIA suspend/resume services
|
||||
sudo systemctl enable nvidia-suspend.service
|
||||
sudo systemctl enable nvidia-resume.service
|
||||
|
||||
# Verify they're enabled
|
||||
systemctl status nvidia-suspend.service nvidia-resume.service
|
||||
```
|
||||
|
||||
**Deterministic verification:**
|
||||
```bash
|
||||
# This shows "enabled" for both services when the fixes work
|
||||
systemctl is-enabled nvidia-suspend.service nvidia-resume.service
|
||||
# Expected output: enabled\nenabled
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix #2: Force S3 Deep Sleep (If Available)
|
||||
|
||||
s2idle is fundamentally broken for NVIDIA hybrid GPUs. Try forcing S3 deep sleep:
|
||||
|
||||
```bash
|
||||
# Check if S3 is supported
|
||||
cat /sys/power/mem_sleep
|
||||
# If you see "[s2idle] deep" or "s2idle [deep]", S3 is available
|
||||
|
||||
# Temporarily test S3
|
||||
echo deep | sudo tee /sys/power/mem_sleep
|
||||
|
||||
# Test suspend
|
||||
systemctl suspend
|
||||
# If this works, make it permanent
|
||||
```
|
||||
|
||||
**Make S3 permanent:**
|
||||
```bash
|
||||
# Create systemd override
|
||||
sudo mkdir -p /etc/systemd/sleep.d
|
||||
sudo tee /etc/systemd/sleep.d/deep-sleep.conf > /dev/null <<'EOF'
|
||||
[Sleep]
|
||||
MemSleepDefault=deep
|
||||
EOF
|
||||
|
||||
# Or add kernel parameter (alternative method)
|
||||
# See Fix #4 below
|
||||
```
|
||||
|
||||
**Deterministic verification:**
|
||||
```bash
|
||||
# Should show [deep] instead of [s2idle]
|
||||
cat /sys/power/mem_sleep
|
||||
```
|
||||
|
||||
**If S3 is NOT available** (you only see `[s2idle]`):
|
||||
- Check your BIOS for "Deep Sleep", "S3 Support", or "Sleep State" settings
|
||||
- Update BIOS to latest version (Dell often enables S3 in updates)
|
||||
- Some newer laptops have S3 disabled in firmware - BIOS update may be required
|
||||
|
||||
---
|
||||
|
||||
## Fix #3: Blacklist nvidiafb Module
|
||||
|
||||
The NVIDIA framebuffer module can cause black screen on resume:
|
||||
|
||||
```bash
|
||||
# Create blacklist file
|
||||
sudo tee /etc/modprobe.d/blacklist-nvidiafb.conf > /dev/null <<'EOF'
|
||||
blacklist nvidiafb
|
||||
EOF
|
||||
|
||||
# Regenerate initramfs
|
||||
sudo mkinitcpio -P
|
||||
|
||||
# Verify nvidiafb is not loaded
|
||||
lsmod | grep nvidiafb
|
||||
# Expected: no output
|
||||
```
|
||||
|
||||
**Deterministic verification:**
|
||||
```bash
|
||||
# Should return non-zero (module not found)
|
||||
lsmod | grep -q nvidiafb && echo "FAIL: nvidiafb loaded" || echo "PASS: nvidiafb not loaded"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix #4: Add Kernel Parameters
|
||||
|
||||
Add these parameters to improve ACPI and sleep behavior:
|
||||
|
||||
```bash
|
||||
# For GRUB (edit /etc/default/grub):
|
||||
# GRUB_CMDLINE_LINUX_DEFAULT="... mem_sleep_default=deep acpi_backlight=vendor"
|
||||
|
||||
# For systemd-boot (edit /boot/loader/entries/*.conf):
|
||||
# Add to options line: mem_sleep_default=deep acpi_backlight=vendor
|
||||
|
||||
# For your current setup (check your bootloader):
|
||||
# Add these parameters:
|
||||
# mem_sleep_default=deep - forces S3 if available
|
||||
# acpi_backlight=vendor - fixes backlight control on resume
|
||||
# acpi_enforce_resources=lax - allows ACPI resource access
|
||||
```
|
||||
|
||||
After editing bootloader config:
|
||||
```bash
|
||||
# GRUB
|
||||
sudo update-grub
|
||||
|
||||
# systemd-boot - no action needed, changes take effect on next boot
|
||||
```
|
||||
|
||||
**Deterministic verification:**
|
||||
```bash
|
||||
# Check if parameters are active
|
||||
cat /proc/cmdline | grep -E "mem_sleep_default|acpi_backlight"
|
||||
# Should show the parameters you added
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix #5: Disable Problematic Wake Sources
|
||||
|
||||
Your diagnostics show XHCI (USB) and RP01/RP05 (PCIe) wake sources enabled. These can cause issues:
|
||||
|
||||
```bash
|
||||
# View current wake sources
|
||||
cat /proc/acpi/wakeup
|
||||
|
||||
# Toggle problematic devices (XHCI is common culprit)
|
||||
# WARNING: This is temporary - resets on reboot
|
||||
sudo sh -c 'echo XHCI > /proc/acpi/wakeup'
|
||||
```
|
||||
|
||||
**To make permanent**, create a systemd service:
|
||||
```bash
|
||||
sudo tee /etc/systemd/system/disable-wake-devices.service > /dev/null <<'EOF'
|
||||
[Unit]
|
||||
Description=Disable problematic wake devices
|
||||
Before=sleep.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh -c 'echo XHCI > /proc/acpi/wakeup'
|
||||
ExecStart=/bin/sh -c 'echo RP01 > /proc/acpi/wakeup'
|
||||
ExecStart=/bin/sh -c 'echo RP05 > /proc/acpi/wakeup'
|
||||
|
||||
[Install]
|
||||
WantedBy=sleep.target
|
||||
EOF
|
||||
|
||||
sudo systemctl enable disable-wake-devices.service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix #6: Update BIOS/Firmware
|
||||
|
||||
Dell frequently releases BIOS updates that fix ACPI/suspend bugs:
|
||||
|
||||
```bash
|
||||
# Check for firmware updates
|
||||
sudo fwupdmgr get-updates
|
||||
|
||||
# If updates available:
|
||||
sudo fwupdmgr update
|
||||
```
|
||||
|
||||
**Deterministic verification:**
|
||||
```bash
|
||||
# Check current BIOS version
|
||||
dmidecode -s bios-version
|
||||
dmidecode -s bios-release-date
|
||||
# Compare with Dell support site for your M16a2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fix #7: Configure TLP (If Installed)
|
||||
|
||||
If you use TLP for power management, add these settings:
|
||||
|
||||
```bash
|
||||
sudo tee -a /etc/tlp.conf > /dev/null <<'EOF'
|
||||
# NVIDIA power management
|
||||
RUNTIME_PM_ON_AUTO_SUSPEND=auto
|
||||
RUNTIME_PM_ON_IDLE_THRESHOLD=30
|
||||
|
||||
# PCI Express ASPM
|
||||
PCIE_ASPM_ON_AC=powersupersave
|
||||
PCIE_ASPM_ON_BAT=powersupersave
|
||||
EOF
|
||||
|
||||
# Restart TLP
|
||||
sudo tlp start
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Procedure
|
||||
|
||||
After applying fixes, test in this order:
|
||||
|
||||
### Test 1: Manual Suspend
|
||||
```bash
|
||||
# Simple suspend test
|
||||
systemctl suspend
|
||||
# Expected: System sleeps, wakes properly when you press a key/move mouse
|
||||
```
|
||||
|
||||
### Test 2: Lid Close Test
|
||||
```bash
|
||||
# Check lid trigger setting
|
||||
cat /etc/systemd/logind.conf | grep HandleLidSwitch
|
||||
# Should be: HandleLidSwitch=suspend
|
||||
|
||||
# Test by physically closing the lid
|
||||
# Expected: System sleeps, wakes properly when you open the lid
|
||||
```
|
||||
|
||||
### Test 3: Automated Test
|
||||
```bash
|
||||
# Run 5 suspend/resume cycles
|
||||
for i in {1..5}; do
|
||||
echo "Cycle $i"
|
||||
systemctl suspend
|
||||
# Wake up when system suspends
|
||||
done
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Emergency Recovery
|
||||
|
||||
If you get a black screen after wake:
|
||||
|
||||
1. **Try switching TTY:** `Ctrl+Alt+F3` - if this works, it is a display issue
|
||||
2. **SSH into the machine** from another device and check logs
|
||||
3. **Hard reset:** Hold power button for 10 seconds
|
||||
4. **Check logs after reboot:**
|
||||
```bash
|
||||
journalctl -b -1 -k | grep -iE "suspend|resume|nvidia|acpi"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If a fix breaks something:
|
||||
|
||||
1. **NVIDIA services:** `sudo systemctl disable nvidia-suspend.service`
|
||||
2. **S3 sleep:** Remove the sleep.d config or kernel parameter
|
||||
3. **nvidiafb blacklist:** Remove `/etc/modprobe.d/blacklist-nvidiafb.conf` and regenerate initramfs
|
||||
4. **Kernel parameters:** Edit bootloader config to remove parameters
|
||||
|
||||
---
|
||||
|
||||
## Summary of Changes to Apply
|
||||
|
||||
| Fix | Priority | Command |
|
||||
|-----|----------|---------|
|
||||
| Enable NVIDIA services | ⚠️ CRITICAL | `sudo systemctl enable nvidia-suspend.service nvidia-resume.service` |
|
||||
| Blacklist nvidiafb | HIGH | Create `/etc/modprobe.d/blacklist-nvidiafb.conf` + `sudo mkinitcpio -P` |
|
||||
| Force S3 sleep | HIGH | `echo deep \| sudo tee /sys/power/mem_sleep` (test first) |
|
||||
| Kernel parameters | MEDIUM | Add `mem_sleep_default=deep acpi_backlight=vendor` to bootloader |
|
||||
| Update BIOS | MEDIUM | `sudo fwupdmgr get-updates` |
|
||||
| Disable wake sources | LOW | Create wake device toggle service |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Start with Fix #1** (enable NVIDIA services) - this is most likely the issue
|
||||
2. **Test suspend** after each fix
|
||||
3. **Apply Fix #2** if s2idle continues to fail
|
||||
4. **Apply Fix #3** (blacklist nvidiafb) - low risk, high reward
|
||||
5. **Consider Fix #4** (kernel parameters) if issues persist
|
||||
6. **Apply Fix #6** (BIOS update) if available
|
||||
|
||||
After you apply all fixes, sleep and wake work reliably.
|
||||
@@ -170,7 +170,7 @@ This allows plugging in any custom secrets backend.
|
||||
|
||||
— [Keychain and Windows Credentials Manager][keyring]
|
||||
|
||||
**This is relevant for the workstation** — CachyOS uses GNOME Keyring (KDE uses kwallet, but the system has GNOME components). On the Strix Halo (Arch Linux) and RTX 3090 (FreeToken) boxes, GNOME Keyring or kwallet would be available depending on desktop environment.
|
||||
**This is relevant for the workstation** — CachyOS uses GNOME Keyring (KDE uses kwallet, but the system has GNOME components). On the Ubuntu 26.04 server boxes (dankclaw, dankserver), GNOME Keyring or kwallet would be available depending on desktop environment.
|
||||
|
||||
---
|
||||
|
||||
@@ -336,9 +336,9 @@ Use symlinks for configs that external programs modify and must write back to (V
|
||||
|
||||
### Setup
|
||||
|
||||
- **Machine fleet:** the workstation (Intel Ultra 7, CachyOS, niri), dankclaw (Strix Halo, llama.cpp frank-default-large on port 7770), dankserver (RTX 3090, FreeToken, frank-default-small)
|
||||
- **Machine fleet:** the dev workstation (AMD Ryzen 5 PRO 5650U laptop, CachyOS, niri) plus client boxes; dankclaw (Strix Halo + RTX 3090, Ubuntu 26.04, fleet services); dankserver (2x Radeon AI PRO R9700, Ubuntu 26.04) — fleet detail: [/system/index.md](/system/index.md)
|
||||
- **Central config repo:** `~/.omp` — already a git repo with agent config, model manifests, and the KB
|
||||
- **OS mix:** All Linux, but different distros (CachyOS, Arch, custom FreeToken)
|
||||
- **OS mix:** All Linux, but different distros (CachyOS on clients, Ubuntu 26.04 LTS on both servers)
|
||||
|
||||
### Verdict: **Recommended with moderate reservations**
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
# Research Documentation
|
||||
|
||||
Hardware-specific research and fix guides.
|
||||
Research documents inform decisions and preserve class-level knowledge; they
|
||||
are not live state. Hardware pages describe machines the fleet has retired.
|
||||
|
||||
## Sleep/Wake Issues
|
||||
## Sleep/Wake Research
|
||||
|
||||
| File | Type | Description |
|
||||
|------|------|-------------|
|
||||
| [[Alienware-M16a2-Linux-sleep-wake-issues|Alienware-M16a2-Linux-sleep-wake-issues]] | research | Comprehensive research on NVIDIA GPU driver state corruption during suspend/resume on Alienware m16 R2 |
|
||||
| [[Sleep-Fix-Guide|Sleep-Fix-Guide]] | guide | Step-by-step fix guide for this system (CachyOS, Kernel 7.1.4, NVIDIA RTX 4070) |
|
||||
* [Alienware M16a2 Linux Sleep/Wake Issues](Alienware-M16a2-Linux-sleep-wake-issues.md) — NVIDIA suspend/resume corruption research on **dankware**, the Alienware m16 R2 workstation sold 2026-09-28. Retained as Dell/Alienware + NVIDIA class knowledge. General Linux sleep configuration lives in [Linux Power Management](../tools/linux-power-management.md).
|
||||
|
||||
* [Alienware M16a2 Linux Sleep/Wake Issues](Alienware-M16a2-Linux-sleep-wake-issues.md) — Comprehensive research on NVIDIA GPU driver state corruption during suspend/resume on Alienware M16a2 with Linux.
|
||||
|
||||
* [Sleep Fix Guide](Sleep-Fix-Guide.md) — Fix guide for Alienware M16a2 sleep/wake issues on CachyOS with NVIDIA RTX 40-series GPU.
|
||||
## Evaluations
|
||||
|
||||
* [Chezmoi Evaluation for Dotfiles Management](chezmoi-evaluation.md) — Evaluation of chezmoi (v2.72.0) as a dotfiles management tool for the workstation fleet.
|
||||
|
||||
* [Secrets Management for AI Agents in the Loop](secrets-for-agents.md) — Threat-modelled survey of secrets tools where agents have shell access and can read plaintext files and paste secrets into logs.
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
type: concept
|
||||
title: The Agent Skills Standard
|
||||
description: "The open Agent Skills standard: SKILL.md format, frontmatter fields, directory structure, progressive-disclosure loading, authoring practice, and how skills differ from extensions."
|
||||
tags:
|
||||
- skills
|
||||
- agent-skills
|
||||
- specification
|
||||
- authoring
|
||||
timestamp: 2026-10-19
|
||||
verified: 2026-10-19
|
||||
---
|
||||
|
||||
# The Agent Skills Standard
|
||||
|
||||
A **skill** is a directory containing a `SKILL.md` file: YAML frontmatter
|
||||
(`name` + `description`) followed by markdown instructions, plus optional
|
||||
`scripts/`, `references/`, and `assets/`. The standard is maintained at
|
||||
[agentskills.io](https://agentskills.io) and adopted by 79 coding agents
|
||||
(upstream agent registry, checked 2026-10-19), so one skill works across
|
||||
harnesses. The `skills` CLI installs them; see
|
||||
[Skills CLI](/skills/skills-cli.md).
|
||||
|
||||
## SKILL.md format
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-skill
|
||||
description: What the skill does and when to use it.
|
||||
---
|
||||
|
||||
# My Skill
|
||||
Instructions the agent follows when the skill activates.
|
||||
```
|
||||
|
||||
### Frontmatter fields
|
||||
|
||||
| Field | Required | Notes |
|
||||
|-------|----------|-------|
|
||||
| `name` | yes | Max 64 chars; lowercase `a-z`, `0-9`, hyphens; no leading/trailing or consecutive hyphens (`pdf-processing` good, `PDF-Processing`, `-pdf`, `pdf--processing` bad). Pi does not require the name to match the parent directory; the standard does. |
|
||||
| `description` | yes | Max 1024 chars. The only text the agent sees when deciding whether to activate the skill. First sentence: what it does. Second: when to use it. |
|
||||
| `license` | no | License name or reference to a bundled file. |
|
||||
| `compatibility` | no | Max 500 chars; environment requirements. |
|
||||
| `metadata` | no | Arbitrary key/value mapping. `metadata.internal: true` hides the skill from discovery unless `INSTALL_INTERNAL_SKILLS=1` (skills CLI convention). |
|
||||
| `allowed-tools` | no | Space-delimited pre-approved tools (experimental; agent support varies — Zencoder and Kiro do not implement it). |
|
||||
| `disable-model-invocation` | no | When `true`, the skill is hidden from the system prompt; users invoke it explicitly (`/skill:name`). |
|
||||
|
||||
### Directory structure
|
||||
|
||||
```
|
||||
my-skill/
|
||||
├── SKILL.md # Required entry point
|
||||
├── scripts/ # Helper scripts (bash, js, python, ...)
|
||||
├── references/ # Detailed docs, loaded on demand
|
||||
├── assets/ # Templates, configs, binary data
|
||||
└── config.json # Optional skill settings
|
||||
```
|
||||
|
||||
Everything except `SKILL.md` is freeform. Scripts save tokens and improve
|
||||
reliability when the same code would otherwise be regenerated per run.
|
||||
|
||||
## Loading: progressive disclosure
|
||||
|
||||
Harnesses (pi, omp, Claude Code, ...) load skills the same way:
|
||||
|
||||
1. At startup, scan configured skill locations; extract `name` + `description` only.
|
||||
2. Inject the metadata list into the system prompt.
|
||||
3. On a matching task, the agent reads the full `SKILL.md` and follows it,
|
||||
referencing bundled scripts by relative path.
|
||||
|
||||
Only descriptions live in context permanently; full instructions load on demand.
|
||||
On omp the load order is priority-ranked: authored `agent/skills/` (100) beats
|
||||
the `~/.agents` store provider, which beats auto-learned
|
||||
`agent/managed-skills/` (5). See [Skill Store Wiring](/skills/store-wiring.md).
|
||||
|
||||
## Skills vs extensions
|
||||
|
||||
| | Skills | Extensions |
|
||||
|---|--------|------------|
|
||||
| Format | Markdown (`SKILL.md`) + scripts | TypeScript (`.ts`) |
|
||||
| Purpose | Instructions for the model | Code intercepting events, registering tools |
|
||||
| Execution | The agent reads and follows | Runs in the harness runtime |
|
||||
| Loading | On demand | Always loaded at startup |
|
||||
| Trust model | Review the text (it instructs the model) | Review the code (it executes) |
|
||||
|
||||
A harness package may bundle both (pi did; omp extensions live in
|
||||
`agent/extensions/`).
|
||||
|
||||
## Authoring practice
|
||||
|
||||
- Descriptions beat clever bodies: activation depends entirely on the description matching the user's words. "Extracts text and tables from PDF files, fills forms, merges documents" beats "Helps with PDFs."
|
||||
- Keep `SKILL.md` focused; push long detail into `references/` (files load whole; split past roughly 500 lines).
|
||||
- Skills instruct the model to run arbitrary commands, and scripts run with full user permissions. Review content before installing from untrusted sources.
|
||||
- Document dependencies (tools, API keys, setup steps) inside the skill.
|
||||
|
||||
## Citations
|
||||
|
||||
- [Agent Skills specification](https://agentskills.io) — re-fetched 2026-10-19.
|
||||
- [vercel-labs/skills README](https://github.com/vercel-labs/skills) — compatibility matrix, re-fetched 2026-10-19.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Skills CLI](/skills/skills-cli.md) — install/use/update tooling.
|
||||
- [Skill Store Wiring](/skills/store-wiring.md) — how the fleet provisions skills.
|
||||
- [Skills Ecosystem](/skills/ecosystem.md) — registries and leaderboards.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
type: reference
|
||||
title: Skills Ecosystem
|
||||
description: "Registries and the leaderboard API for the open agent-skills ecosystem, with a live-verified install snapshot."
|
||||
tags:
|
||||
- skills
|
||||
- skills-sh
|
||||
- ecosystem
|
||||
- registry
|
||||
timestamp: 2026-10-19
|
||||
verified: 2026-10-19
|
||||
---
|
||||
|
||||
# Skills Ecosystem
|
||||
|
||||
The open agent-skills ecosystem is a set of registries over the shared
|
||||
[Agent Skills standard](/skills/agent-skills.md), installed with the
|
||||
[Skills CLI](/skills/skills-cli.md).
|
||||
|
||||
## Registries
|
||||
|
||||
| Registry | Focus |
|
||||
|----------|-------|
|
||||
| [skills.sh](https://skills.sh) | Primary registry and all-time install leaderboard. |
|
||||
| [agentskill.sh](https://agentskill.sh) | Broad directory/marketplace. |
|
||||
| [officialskills.sh](https://officialskills.sh) | Skills from major organizations. |
|
||||
| [qaskills.sh](https://qaskills.sh) | QA and testing skills. |
|
||||
|
||||
## skills.sh leaderboard API
|
||||
|
||||
Fetch the all-time ranking programmatically:
|
||||
|
||||
```bash
|
||||
curl 'https://skills.sh/api/skills/all-time/0'
|
||||
```
|
||||
|
||||
Response is `{ skills, total, hasMore, page }`. Pagination is **zero-based**,
|
||||
**200 skills per page** (`GET /api/skills/all-time/{page}`). Each entry carries
|
||||
`source`, `skillId`, `name`, `installs`, `weeklyInstalls` (last ~8 weeks), and
|
||||
`isOfficial`. Verified live 2026-10-19: page 0 returned 200 entries,
|
||||
`total` 9909, `hasMore` true.
|
||||
|
||||
## Install snapshot (2026-10-19, live)
|
||||
|
||||
Top 10 by all-time installs, queried from the API above:
|
||||
|
||||
| # | Skill | Source | Installs |
|
||||
|---|-------|--------|----------|
|
||||
| 1 | `find-skills` | vercel-labs/skills | 3,927,274 |
|
||||
| 2 | `grill-me` | mattpocock/skills | 1,387,557 |
|
||||
| 3 | `grill-with-docs` | mattpocock/skills | 1,188,473 |
|
||||
| 4 | `agent-browser` | vercel-labs/agent-browser | 1,170,738 |
|
||||
| 5 | `improve-codebase-architecture` | mattpocock/skills | 1,133,991 |
|
||||
| 6 | `tdd` | mattpocock/skills | 1,110,148 |
|
||||
| 7 | `hyperframes-cli` | heygen-com/hyperframes | 1,109,284 |
|
||||
| 8 | `hyperframes` | heygen-com/hyperframes | 1,063,942 |
|
||||
| 9 | `setup-matt-pocock-skills` | mattpocock/skills | 1,024,734 |
|
||||
| 10 | `handoff` | mattpocock/skills | 1,008,869 |
|
||||
|
||||
`mattpocock/skills` dominates the workflow/design middle of the board; a single
|
||||
`find-skills` out-installs the next several combined. Vendor suites (Lark, Azure)
|
||||
that filled ranks 12-50 in the 2026-08-12 snapshot have since dropped out of the
|
||||
head, so this page keeps only a live top-10 rather than a full 50-row table that
|
||||
rots between queries. Re-query the API above for a current census.
|
||||
|
||||
## Repositories
|
||||
|
||||
- [vercel-labs/skills](https://github.com/vercel-labs/skills) — the CLI.
|
||||
- [vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills) — reference skills.
|
||||
- [anthropics/skills](https://github.com/anthropics/skills) — Anthropic's skill set.
|
||||
- [openai/skills](https://github.com/openai/skills) — OpenAI's skill set.
|
||||
|
||||
## See Also
|
||||
|
||||
- [The Agent Skills Standard](/skills/agent-skills.md)
|
||||
- [Skills CLI](/skills/skills-cli.md)
|
||||
- [Skill Store Wiring](/skills/store-wiring.md)
|
||||
@@ -1,11 +1,14 @@
|
||||
# Skills Documentation
|
||||
|
||||
Distribution and installation patterns for agent skills via npm packages, including SKILL.md structure, discovery rules, and the pi-package system.
|
||||
The open agent-skills ecosystem as the fleet uses it: the standard, the
|
||||
installer CLI, this fleet's provisioning tiers, and the registries.
|
||||
|
||||
## Concept Files
|
||||
|
||||
| File | Type | Description |
|
||||
|------|------|-------------|
|
||||
| [npx-skills.md](npx-skills.md) | reference | Distribution and installation patterns for agent skills via npm packages, including SKILL.md structure and the pi-package system |
|
||||
| [vercel-skills.md](vercel-skills.md) | reference | The meta-installer CLI for cross-agent skill distribution, supporting 68+ agents |
|
||||
* [The Agent Skills Standard](agent-skills.md) — SKILL.md format, frontmatter fields, loading model, authoring practice, skills vs extensions.
|
||||
* [Skills CLI](skills-cli.md) — `npx skills`: commands, sources, scopes, discovery, lock file, agent registry.
|
||||
* [Skill Store Wiring](store-wiring.md) — the three skill tiers on Dank workstations and how omp loads them.
|
||||
* [Skills Ecosystem](ecosystem.md) — registries, the skills.sh leaderboard API, live install snapshot.
|
||||
|
||||
Pi-era skill packaging (`pi install npm:...`, the `pi` package manifest) is
|
||||
archived under [pi](/pi/index.md).
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
---
|
||||
type: reference
|
||||
title: Npx Skills — Distribution and Installation Patterns
|
||||
description: Distribution and installation patterns for agent skills via npm packages, including SKILL.md structure, discovery rules, and the pi-package system.
|
||||
tags:
|
||||
- skills
|
||||
- npm
|
||||
- agent-skills
|
||||
- distribution
|
||||
- pi-package
|
||||
- unverified
|
||||
timestamp: 2026-08-28
|
||||
---
|
||||
|
||||
# Npx Skills — Distribution and Installation
|
||||
|
||||
In the pi coding agent ecosystem, **"npx skills"** refers to the distribution and installation pattern for agent skills through npm packages. Skills are the content (SKILL.md + scripts); pi packages are the delivery mechanism (npm tarball with a `pi` manifest).
|
||||
|
||||
---
|
||||
|
||||
## The Two-Layer Model
|
||||
|
||||
```
|
||||
npm package (tagged pi-package)
|
||||
├── pi.skills manifest → points to ./skills/
|
||||
└── skills/
|
||||
├── brave-search/SKILL.md
|
||||
├── browser-tools/SKILL.md
|
||||
└── tdd-workflow/SKILL.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## The Agent Skills Specification
|
||||
|
||||
Pi implements the [Agent Skills standard](https://agentskills.io), which defines:
|
||||
|
||||
- A **frontmatter block** (YAML) at the top of `SKILL.md` with required `name` and `description` fields
|
||||
- A **Markdown body** with the skill's instructions
|
||||
- Optional subdirectories: `scripts/`, `references/`, `assets/`
|
||||
|
||||
The specification is **cross-agent-compatible**: skills written for pi work with Claude Code, Codex CLI, Amp, Droid, and others.
|
||||
|
||||
---
|
||||
|
||||
## How Skills Work in Pi
|
||||
|
||||
1. **At startup**, pi scans all configured skill locations and extracts skill names and descriptions
|
||||
2. **The system prompt** includes available skills in XML format
|
||||
3. **When a task matches**, the agent uses `read` to load the full SKILL.md
|
||||
4. **The agent follows the instructions**, using relative paths to reference scripts and assets
|
||||
|
||||
This is **progressive disclosure**: only descriptions are always in context, full instructions load on-demand.
|
||||
|
||||
---
|
||||
|
||||
## Installing Skills via NPM / Npx
|
||||
|
||||
### Method 1: Direct `pi install` (recommended)
|
||||
|
||||
```bash
|
||||
pi install npm:pi-web-access
|
||||
pi install npm:@anton-kochev/pi-skills
|
||||
pi install npm:bigpowers
|
||||
pi install npm:@monopi/skills
|
||||
```
|
||||
|
||||
### Method 2: Npx-based setup tools
|
||||
|
||||
```bash
|
||||
npx @monopi/monopi # One-command setup
|
||||
npx @monopi/monopi --version 0.2.13 # Pin a version
|
||||
npx @monopi/monopi --local # Project-local install
|
||||
```
|
||||
|
||||
### Method 3: Manual clone (git repos)
|
||||
|
||||
```bash
|
||||
git clone https://github.com/badlogic/pi-skills ~/.pi/agent/skills/pi-skills
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pi Packages
|
||||
|
||||
### Package Structure
|
||||
|
||||
```
|
||||
my-pi-package/
|
||||
├── package.json # npm metadata + pi manifest
|
||||
├── skills/ # Conventional directory (auto-discovered)
|
||||
│ ├── my-skill/
|
||||
│ │ └── SKILL.md
|
||||
├── extensions/ # TypeScript extensions
|
||||
├── prompts/ # Prompt templates
|
||||
└── themes/ # TUI themes
|
||||
```
|
||||
|
||||
### package.json with pi Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-pi-package",
|
||||
"keywords": ["pi-package"],
|
||||
"pi": {
|
||||
"extensions": ["./extensions"],
|
||||
"skills": ["./skills"],
|
||||
"prompts": ["./prompts"],
|
||||
"themes": ["./themes"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Package Sources
|
||||
|
||||
| Source Type | Example | Notes |
|
||||
|-------------|---------|-------|
|
||||
| **npm** | `npm:@foo/bar@1.0.0` | Pinned versions, installed to `~/.pi/agent/npm/` |
|
||||
| **git** | `git:github.com/user/repo@v1` | Pinned to tags/commits, cloned to `~/.pi/agent/git/` |
|
||||
| **local** | `./relative/path` | Points to local directory, added without copying |
|
||||
|
||||
---
|
||||
|
||||
## SKILL.md Frontmatter
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `name` | **Yes** | Max 64 chars. Lowercase a-z, 0-9, hyphens only. |
|
||||
| `description` | **Yes** | Max 1024 chars. What the skill does and when to use it. |
|
||||
| `license` | No | License name or reference to bundled file. |
|
||||
| `compatibility` | No | Max 500 chars. Environment requirements. |
|
||||
| `metadata` | No | Arbitrary key-value mapping. |
|
||||
| `allowed-tools` | No | Space-delimited list of pre-approved tools (experimental). |
|
||||
| `disable-model-invocation` | No | When `true`, skill is hidden from system prompt. |
|
||||
|
||||
**The description determines when the agent loads the skill. Be specific.**
|
||||
|
||||
---
|
||||
|
||||
## Discovery Rules
|
||||
|
||||
| Location | Scope | Rule |
|
||||
|----------|-------|------|
|
||||
| `~/.pi/agent/skills/` | All projects | Direct root `.md` files + directories with `SKILL.md` |
|
||||
| `.pi/skills/` | Current project | Direct root `.md` files + directories with `SKILL.md` |
|
||||
| `~/.agents/skills/` | All projects | Only directories with `SKILL.md` (root `.md` ignored) |
|
||||
|
||||
---
|
||||
|
||||
## Skills vs Extensions
|
||||
|
||||
| Feature | Skills | Extensions |
|
||||
|---------|--------|------------|
|
||||
| **Format** | Markdown (`SKILL.md`) | TypeScript (`.ts`) |
|
||||
| **Purpose** | Instructions for the LLM | Code that intercepts events |
|
||||
| **Execution** | Agent reads and follows | Runs in pi's Node.js runtime |
|
||||
| **Loading** | On-demand | Always loaded at startup |
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
- See [Vercel `skills` CLI](vercel-skills.md) for the meta-installer tool.
|
||||
- The [Agent Skills specification](https://agentskills.io/specification) is the canonical format.
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
type: reference
|
||||
title: Skills CLI
|
||||
description: "The Vercel Labs `skills` CLI: commands, sources, install scopes, discovery rules, lock file, environment variables, and the agent registry."
|
||||
tags:
|
||||
- skills
|
||||
- cli
|
||||
- vercel
|
||||
- meta-installer
|
||||
resource: https://github.com/vercel-labs/skills
|
||||
timestamp: 2026-10-19
|
||||
verified: 2026-10-19
|
||||
---
|
||||
|
||||
# Skills CLI
|
||||
|
||||
`npx skills` is the CLI for the open agent-skills ecosystem
|
||||
([vercel-labs/skills](https://github.com/vercel-labs/skills)). It is a
|
||||
meta-installer: it pulls `SKILL.md` bundles from a source and links or copies
|
||||
them into each supported agent's skill directory. No global install; run via
|
||||
`npx`. Version 1.7.2 (`package.json`, 2026-10-19).
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Aliases | Purpose |
|
||||
|---------|---------|---------|
|
||||
| `skills add <source>` | `a` | Install skills from a source. |
|
||||
| `skills use <source>[@skill]` | | Emit a prompt for one skill (pipe to an agent) or launch an agent with `--agent`, without installing. |
|
||||
| `skills list` | `ls` | List installed skills (`-g` global only, `-a <agent>` filter). |
|
||||
| `skills find [query]` | | Interactive (fzf-style) or keyword search; `--owner <org>` scans an org. |
|
||||
| `skills update [skills...]` | | Update installed skills to latest; `-g`/`-p` scope, `-y` auto-scope. |
|
||||
| `skills remove [skills]` | `rm`, `r` | Remove installed skills from agents. |
|
||||
| `skills init [name]` | | Create a `SKILL.md` template. |
|
||||
| `skills experimental_install` | `i`, `install` | Restore installs recorded in the lock file. |
|
||||
| `skills experimental_sync` | | Sync installed skills against sources. |
|
||||
| `skills check` | | Report drift: GitHub tree SHA vs locked `skillFolderHash`. |
|
||||
|
||||
`skills check` and `skills update` share a dispatch path in `src/cli.ts`
|
||||
(2026-10-19). For `check`/`update`, only GitHub-backed skills carrying both
|
||||
`skillFolderHash` and `skillPath` are compared.
|
||||
|
||||
### `add` options
|
||||
|
||||
| Option | Effect |
|
||||
|--------|--------|
|
||||
| `-g, --global` | User directory instead of project. |
|
||||
| `-a, --agent <agents...>` | Target specific agents (`'*'` for all). |
|
||||
| `-s, --skill <skills...>` | Specific skills by name (`'*'` for all). |
|
||||
| `-l, --list` | List the source's skills without installing. |
|
||||
| `--copy` | Copy instead of symlink. |
|
||||
| `-y, --yes` | Skip prompts (CI-friendly). |
|
||||
| `--all` | All skills to all agents, no prompts. |
|
||||
| `--full-depth` | Discover `SKILL.md` outside standard container dirs too. |
|
||||
|
||||
## Sources
|
||||
|
||||
GitHub shorthand (`owner/repo`), full GitHub URL, a tree path to one skill
|
||||
(`.../tree/main/skills/<name>`), GitLab URL, Azure DevOps URL, any git URL, a
|
||||
local path, or a direct download URL (single `SKILL.md`, or `.zip`/`.tar`/
|
||||
`.tar.gz`/`.tgz`). Private repos reuse the credentials git already has;
|
||||
`GITHUB_TOKEN`/`GH_TOKEN` override for API access. Direct downloads cap at
|
||||
10 MiB compressed, 25 MiB extracted, 1000 files (override with
|
||||
`SKILLS_DOWNLOAD_MAX_BYTES`, `SKILLS_EXTRACT_MAX_BYTES`,
|
||||
`SKILLS_EXTRACT_MAX_FILES`).
|
||||
|
||||
## Install scope and method
|
||||
|
||||
| Scope | Flag | Location |
|
||||
|-------|------|----------|
|
||||
| Project | default | `./<agent>/skills/` |
|
||||
| Global | `-g` | `~/<agent>/skills/` |
|
||||
|
||||
Symlink (recommended: one canonical copy, easy update) or `--copy` (independent
|
||||
copies, for hosts where symlinks are unsupported).
|
||||
|
||||
## Skill discovery in a source repo
|
||||
|
||||
The CLI walks each container directory up to three levels: flat
|
||||
(`skills/<name>/SKILL.md`) and one- or two-level catalog layouts. Containers:
|
||||
repo root, `skills/` (and `.curated`/`.experimental`/`.system`), plus
|
||||
per-agent dirs (`.claude/skills/`, `.agents/skills/`, `.pi/skills/`, and
|
||||
dozens more). A `SKILL.md` at a shallower level shadows deeper ones.
|
||||
`--full-depth` also scans outside containers (`examples/`, `tests/`). If a
|
||||
`.claude-plugin/marketplace.json` or `plugin.json` exists, its declared skill
|
||||
paths load too (Claude Code marketplace compatibility). Nothing found in
|
||||
containers triggers a recursive search.
|
||||
|
||||
## Lock file
|
||||
|
||||
| Type | Path |
|
||||
|------|------|
|
||||
| Global | `$XDG_STATE_HOME/skills/.skill-lock.json`, else `~/.agents/.skill-lock.json` |
|
||||
| Project | `skills-lock.json` (commit it) |
|
||||
|
||||
Schema **v3**; key field `skillFolderHash` (GitHub tree SHA per skill folder).
|
||||
A lock file older than v3 is wiped, not migrated — reinstall to repopulate
|
||||
(`src/skill-lock.ts`, 2026-10-19).
|
||||
|
||||
## Environment variables
|
||||
|
||||
| Variable | Effect |
|
||||
|----------|--------|
|
||||
| `INSTALL_INTERNAL_SKILLS` | `1`/`true` reveals `metadata.internal: true` skills. |
|
||||
| `DISABLE_TELEMETRY` | Disable anonymous usage telemetry. |
|
||||
| `DO_NOT_TRACK` | Alternative telemetry opt-out. |
|
||||
| `GITHUB_TOKEN`, `GH_TOKEN` | Explicit GitHub API token. |
|
||||
|
||||
## Agent registry
|
||||
|
||||
79 agents supported (upstream README + `--agent` registry, checked 2026-10-19);
|
||||
the CLI auto-detects installed agents, prompting when it finds none. Each agent
|
||||
maps to a project and global path (e.g. `claude-code` → `.claude/skills/` /
|
||||
`~/.claude/skills/`; `pi` → `.pi/skills/` / `~/.pi/agent/skills/`). The
|
||||
authoritative table lives in the upstream README; this bundle does not mirror
|
||||
it because the list churns. omp is not a registered agent — see
|
||||
[Skill Store Wiring](/skills/store-wiring.md).
|
||||
|
||||
## Citations
|
||||
|
||||
- [vercel-labs/skills README](https://github.com/vercel-labs/skills) — 2026-10-19.
|
||||
- `src/cli.ts`, `src/skill-lock.ts`, `package.json` at `vercel-labs/skills@main` — 2026-10-19.
|
||||
|
||||
## See Also
|
||||
|
||||
- [The Agent Skills Standard](/skills/agent-skills.md)
|
||||
- [Skill Store Wiring](/skills/store-wiring.md)
|
||||
- [Skills Ecosystem](/skills/ecosystem.md)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user