Merge pull request 'Configure the engineering skills against this repo and this KB' (#39) from feat/agent-skills-config into main
This commit was merged in pull request #39.
This commit is contained in:
@@ -86,6 +86,28 @@ never committed, only surfaced. Conflicts abort and alert (ntfy); it never
|
||||
force-pushes, auto-resolves, or uses `--no-verify`. Details:
|
||||
[omp-docs/tools/live-sync.md](omp-docs/tools/live-sync.md).
|
||||
|
||||
## Agent skills
|
||||
|
||||
The engineering skills (`triage`, `to-tickets`, `to-spec`, `research`,
|
||||
`implement`, …) read their per-repo configuration from three pages in the
|
||||
knowledge base. Those pages own their facts; this is only the pointer.
|
||||
|
||||
### Issue tracker
|
||||
|
||||
Work items are Gitea issues on `dank/command-center` (Dankclaw,
|
||||
`192.168.0.143:3000`) — no `gh`, no `tea`. See
|
||||
[`omp-docs/skills/issue-tracker.md`](omp-docs/skills/issue-tracker.md).
|
||||
|
||||
### Triage labels
|
||||
|
||||
The five canonical roles, each label string equal to its name. See
|
||||
[`omp-docs/skills/triage-labels.md`](omp-docs/skills/triage-labels.md).
|
||||
|
||||
### Domain docs
|
||||
|
||||
Single-context, inside the existing knowledge base: `omp-docs/glossary.md` and
|
||||
`omp-docs/decisions/`. See [`omp-docs/skills/domain-docs.md`](omp-docs/skills/domain-docs.md).
|
||||
|
||||
## Secret gate (HARD rule)
|
||||
|
||||
The pre-commit hook (`.githooks/pre-commit`, enabled via
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Architecture decision records
|
||||
|
||||
Decisions this repo has made and will not silently revisit. One file per
|
||||
decision, named `NNN-<slug>.md`, listed here — an unlisted page fails `kb-lint`
|
||||
and does not exist as far as any agent is concerned.
|
||||
|
||||
**No ADRs yet.** The first one lands the moment a decision stops being
|
||||
reversible.
|
||||
|
||||
## Format
|
||||
|
||||
Same shape as the `dank/dankvoice` decision records, which read well under time
|
||||
pressure:
|
||||
|
||||
- `# <Decision as a claim> (YYYY-MM-DD)` — a title you can disagree with.
|
||||
- **Root** — the situation and the evidence that forced the question, with measured
|
||||
output rather than recollection where measurement exists.
|
||||
- **Decision** — what was chosen, and the rule an agent must follow because of it.
|
||||
- **Rejected** — the alternatives and the specific reason each was turned down, so
|
||||
nobody spends an afternoon rediscovering them.
|
||||
- **Verification** — what was run to prove the decision holds, and where that
|
||||
proof lives.
|
||||
|
||||
Frontmatter is required like any other page in this bundle (`type: decision`), and
|
||||
an ADR that a code change has superseded gets an amendment section appended rather
|
||||
than a rewrite: the point of the record is that the reasoning is still readable.
|
||||
@@ -60,6 +60,11 @@ search practices, open models, MCP.
|
||||
Pre-pruning census of every userspace config on this box — the input for the
|
||||
pruning session.
|
||||
|
||||
## [Decisions](decisions/index.md)
|
||||
|
||||
Architecture decision records — the choices that are no longer up for debate,
|
||||
with what was rejected and why. Currently empty; the format rule is in its index.
|
||||
|
||||
## [Change history](log.md)
|
||||
|
||||
Chronological update history of this bundle — incident lessons land here first,
|
||||
|
||||
@@ -16,6 +16,22 @@ 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-20 — engineering skills configured against this KB
|
||||
|
||||
`setup-matt-pocock-skills` ran, and its output moved out of the skill's default
|
||||
`docs/agents/` into the knowledge base: [issue tracker](skills/issue-tracker.md)
|
||||
(Gitea on Dankclaw is the tracker — no `gh`, no `tea`, token via a `600` curl
|
||||
config), [triage labels](skills/triage-labels.md) (the five canonical roles,
|
||||
created on the repo, which carried zero labels before), [domain
|
||||
docs](skills/domain-docs.md) (single-context; glossary withheld until a term has
|
||||
no other owner), plus an empty [decisions](decisions/index.md) with its format
|
||||
rule. `AGENTS.md` gained an `## Agent skills` pointer block. Law: this repo has
|
||||
one knowledge base, so per-tool configuration is a concept page in `omp-docs/` —
|
||||
a second `docs/` tree means a second set of index rules, which is where
|
||||
documentation starts disagreeing with itself. Known cost: re-running that setup
|
||||
skill will not recognise `omp-docs/skills/*` and will offer to recreate
|
||||
`docs/agents/`; the `AGENTS.md` pointer is the thing that stops it.
|
||||
|
||||
## 2026-10-19 — dankvoice auto-speak armed at startup
|
||||
|
||||
Sessions spoke only on explicit `/say`: the settings file carried no `auto`
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
type: reference
|
||||
title: Domain docs layout and consumer rules
|
||||
description: Single-context domain documentation for dank/command-center — glossary and ADRs live inside the omp-docs knowledge base, not at the repo root.
|
||||
tags:
|
||||
- skills
|
||||
- documentation
|
||||
- okf
|
||||
- agents
|
||||
timestamp: 2026-10-20
|
||||
---
|
||||
|
||||
# Domain docs: single-context, inside the KB
|
||||
|
||||
One domain, one glossary, one ADR folder — and all of it inside the existing
|
||||
knowledge base, because this repo caps its root at "config, docs, scripts,
|
||||
harness dirs" and `omp-docs/` is the one knowledge base. A `docs/` tree at the
|
||||
repo root would be a second KB with a second set of index rules, which is exactly
|
||||
how documentation starts disagreeing with itself.
|
||||
|
||||
| Kind | Path | Status |
|
||||
|---|---|---|
|
||||
| Glossary | `omp-docs/glossary.md` | deliberately not created yet |
|
||||
| ADRs | `omp-docs/decisions/NNN-<slug>.md`, listed by its `index.md` | directory exists, empty |
|
||||
| Facts | the rest of `omp-docs/` | existing concept pages own them |
|
||||
|
||||
## Consumer rules
|
||||
|
||||
1. Read [the KB index](/index.md), then the relevant directory's `index.md`, then
|
||||
the concept page. That is AGENTS.md's existing discipline; the engineering
|
||||
skills follow it instead of inventing a second entry point.
|
||||
2. Read the ADRs that govern an area before changing that area, and write one the
|
||||
moment a decision stops being reversible. An ADR records the choice, the
|
||||
reasons, and what was rejected — the part that stops a later agent from
|
||||
re-litigating it.
|
||||
3. Do not confuse the neighbours. [Research](/research/index.md) is decision
|
||||
*support* and explicitly not fact. [log.md](/log.md) is chronology, where
|
||||
incident lessons land before settling into concept pages. An ADR is neither: it
|
||||
is the decision itself, dated, and it stays true after the code moves on.
|
||||
4. One fact, one owner. If a glossary term or an ADR sentence restates a concept
|
||||
page, the concept page wins and the duplicate is deleted.
|
||||
|
||||
## Why the glossary is withheld
|
||||
|
||||
A glossary earns its bytes when it holds terms no other page owns. The obvious
|
||||
candidates already have owners: host roles in [system](/system/index.md), agent
|
||||
configuration in [core](/core/index.md), skill tiers in
|
||||
[skills](/skills/index.md). A term list that paraphrases those is a second owner
|
||||
of facts already written down, and the first thing to go stale. Create
|
||||
`omp-docs/glossary.md` when a real term has nowhere else to live, and list it in
|
||||
the KB index the same commit you create it.
|
||||
@@ -9,6 +9,9 @@ installer CLI, this fleet's provisioning tiers, and the registries.
|
||||
* [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.
|
||||
* [Issue Tracker](issue-tracker.md) — Gitea on Dankclaw as the tracker for the engineering skills: auth via a `600` curl config, the endpoint table, the 404-on-empty-token and form-encoded-merge traps.
|
||||
* [Triage Labels](triage-labels.md) — the five canonical role labels as they exist on the tracker, and what renaming one costs.
|
||||
* [Domain Docs](domain-docs.md) — single-context layout inside this KB: glossary and ADR paths, the read-before-acting rules, and why the glossary is still empty.
|
||||
|
||||
Pi-era skill packaging (`pi install npm:...`, the `pi` package manifest) is
|
||||
archived under [pi](/pi/index.md).
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
type: reference
|
||||
title: Issue tracker for engineering skills
|
||||
description: Where work items live for dank/command-center — Gitea on Dankclaw — with the exact API mechanics, traps, and laws the engineering skills must follow.
|
||||
tags:
|
||||
- skills
|
||||
- gitea
|
||||
- sdlc
|
||||
- agents
|
||||
timestamp: 2026-10-20
|
||||
verified: 2026-10-20
|
||||
---
|
||||
|
||||
# Issue tracker: Gitea on Dankclaw
|
||||
|
||||
Issues and PRs for this repo live in Gitea: `dank/command-center` at
|
||||
`http://192.168.0.143:3000`. There is no `gh` and no `tea` on any box — talk to
|
||||
the REST API with `curl`.
|
||||
|
||||
## Authentication
|
||||
|
||||
The token lives in `~/.config/secrets/gitea` (never embedded in a remote URL,
|
||||
never committed). Hand it to curl as a `600`-permission config file: `-H` puts it
|
||||
in world-readable `/proc/<pid>/cmdline`.
|
||||
|
||||
```bash
|
||||
tok=$(sed -nE 's#^https?://[^:/@]+:([^@]+)@192\.168\.0\.143.*#\1#p' ~/.config/secrets/gitea | head -1)
|
||||
[ "${#tok}" -ge 40 ] || { echo "token extraction failed"; exit 1; }
|
||||
cfg=$(mktemp); chmod 600 "$cfg"; printf 'header = "Authorization: token %s"\n' "$tok" > "$cfg"
|
||||
curl -sS -K "$cfg" … ; shred -u "$cfg"
|
||||
```
|
||||
|
||||
Assert the length before posting anything. **An empty token answers `404 not
|
||||
found`, not `401`** — Gitea hides the private repo, so a 404 on a path that worked
|
||||
yesterday is an auth failure rather than a typo. The awk-style alternative that
|
||||
splits the store line on `/` silently yields an empty variable, because the host
|
||||
sits in field three. Deeper detail: [Gitea client access](/tools/gitea/client-access.md).
|
||||
|
||||
Multi-line bodies: build the JSON with `python3 -c 'json.dumps(...)'` reading the
|
||||
body from a file. Never pass `---` as a bare `jq` argument (it parses as a flag),
|
||||
and never escape quotes inside a single-quoted `python3 -c`.
|
||||
|
||||
## Endpoints the skills use
|
||||
|
||||
| Action | Call |
|
||||
|---|---|
|
||||
| Open a work item | `POST /api/v1/repos/dank/command-center/issues` `{title, body}` |
|
||||
| Correct a body afterwards | `PATCH …/issues/N` (works on PRs too — a PR is an issue) |
|
||||
| Open a PR | `POST …/pulls` `{title, body, base: "main", head: <branch>}` — JSON accepted here |
|
||||
| Merge | `POST …/pulls/N/merge` **form-encoded**: `do=merge`, `merge_style=no-ff` |
|
||||
| Labels | `GET` / `POST …/labels` |
|
||||
|
||||
Three traps that cost time before:
|
||||
|
||||
- `POST /pulls` answers `409 … already exists for these targets` when the branch
|
||||
already has a PR (Frank clicks Create from the push message). `GET
|
||||
/pulls?state=all`, find it, `PATCH` it — do not re-post.
|
||||
- A JSON merge body (`{"Do":"merge"}`) returns `422 {"message":"[Do]: Required"}`.
|
||||
The field name is lowercase `do` and the body must be form-encoded.
|
||||
- A successful merge returns `200` with an **empty body**. Verify by landing a
|
||||
checkout (`git merge --ff-only origin/main`), never by re-reading the PR.
|
||||
|
||||
## Laws inherited from AGENTS.md
|
||||
|
||||
A skill working in this repo does not get to renegotiate these:
|
||||
|
||||
- A work item is a Gitea issue. Anything with more than one moving part gets the
|
||||
issue before the branch. Branch naming `<type>/<issue#>-<slug>`, PRs target
|
||||
`main` directly, merge with `--no-ff`.
|
||||
- **Never merge without Frank's explicit per-PR OK**, and `xdg-open` the PR URL
|
||||
into his browser the moment it exists — he should not have to hunt for it.
|
||||
- Every issue and PR body ends with `---`, then `cwd: <session cwd> · session:
|
||||
<session id>`. The session id is the UUID of the transcript file being appended
|
||||
to right now (`ls -l --time-style=+%H:%M:%S ~/.omp/agent/sessions/<cwd-dir>/*.jsonl`),
|
||||
not the session directory name — one cwd can hold several sessions.
|
||||
- `git * --no-verify` is forbidden; the pre-commit hook is the secret gate.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
type: reference
|
||||
title: Triage label vocabulary
|
||||
description: The five canonical triage roles and the exact Gitea label strings applied to dank/command-center issues.
|
||||
tags:
|
||||
- skills
|
||||
- gitea
|
||||
- triage
|
||||
- agents
|
||||
timestamp: 2026-10-20
|
||||
verified: 2026-10-20
|
||||
---
|
||||
|
||||
# Triage labels
|
||||
|
||||
Canonical vocabulary, unchanged: the label string equals the role name. Created
|
||||
on `dank/command-center` on 2026-10-20 — the repo carried zero labels before that,
|
||||
so nothing collides and nothing needs renaming.
|
||||
|
||||
| Label | Means |
|
||||
|---|---|
|
||||
| `needs-triage` | filed, not yet read by a human or agent |
|
||||
| `needs-info` | blocked on a question back to the reporter |
|
||||
| `ready-for-agent` | specified enough to implement without further decisions |
|
||||
| `ready-for-human` | needs a human decision, credential, or judgement first |
|
||||
| `wontfix` | decided against; keep the record, close it |
|
||||
|
||||
The `triage` skill applies and removes these strings directly, so a label must
|
||||
exist on the tracker before it can be applied:
|
||||
|
||||
```bash
|
||||
curl -sS -K "$cfg" -X POST -H 'content-type: application/json' \
|
||||
-d '{"name":"ready-for-agent","color":"0e8a16"}' \
|
||||
http://192.168.0.143:3000/api/v1/repos/dank/command-center/labels
|
||||
```
|
||||
|
||||
Renaming is a two-sided edit — change the strings here *and* on the tracker, or
|
||||
`triage` starts failing to apply them. Adding near-duplicates (`needs-reinfo`,
|
||||
`ready-for-ai`) is worse than either option: two labels for one role means no
|
||||
issue reliably carries either.
|
||||
@@ -90,3 +90,18 @@ EOF
|
||||
run bash "$LINT" "$KB/no-such-dir"
|
||||
[ "$status" -eq 2 ]
|
||||
}
|
||||
|
||||
@test "the shipped knowledge base itself is conformant" {
|
||||
# The tests above exercise the linter against fixtures; nothing else in the
|
||||
# suite ever points it at the real bundle, so a page added without frontmatter
|
||||
# or an index that stops listing a file passes CI silently. This is the gate.
|
||||
run bash "$BATS_TEST_DIRNAME/../scripts/kb-lint.sh" "$BATS_TEST_DIRNAME/../omp-docs"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"0 violation(s)"* ]]
|
||||
}
|
||||
|
||||
@test "every page in the shipped knowledge base is listed by an index" {
|
||||
run python3 "$BATS_TEST_DIRNAME/../scripts/kb-coverage.py" "$BATS_TEST_DIRNAME/../omp-docs"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"0 issue(s)"* ]]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user