chore: bootstrap skills library — 19 skills + installer + CI auto-tag
Some checks failed
release / tag (push) Has been cancelled
Some checks failed
release / tag (push) Has been cancelled
Phase 1 of mathias/skills extraction (infra#62 Track D — homelab next-step plan addendum). Imports ~/dev/.skills/ verbatim (19 skill dirs + SKILLS_INDEX.md) and adds the installation surface: - Taskfile.yml — install / update / list / release / check targets - install.sh — bootstrap installer for hosts without Task. Idempotent symlink wirer; default checkout at ~/.local/share/skills/ on every host; SKILLS_REF env var pins a tag (default: main). - .gitea/workflows/release.yml — auto-tag every push to main by Bump-Type footer (major/minor/patch, default patch). Skipped when commit contains [skip-release]. - README — usage, versioning, contribution flow, secret-hygiene rule. Phase 1 wires Claude Code only (~/.claude/skills/<name> global + <repo>/.claude/skills/<name> per-repo). Phase 2 adds Crush, opencode, antigravity, and gitea-resident agents (cobalt-dingo, agentsquad) once their skill conventions are researched. Public repo, markdown-only — no secrets, no client names. Verified via pre-push grep before initial push. [skip-release]
This commit is contained in:
252
trainer/SKILL.md
Normal file
252
trainer/SKILL.md
Normal file
@@ -0,0 +1,252 @@
|
||||
---
|
||||
name: trainer
|
||||
description: Two-phase brain curation — scan session logs to score candidate learnings (READ), then write the ones that pass the quality gate as generalized knowledge entries (WRITE). Use periodically to keep the brain useful, not noisy.
|
||||
---
|
||||
|
||||
# Trainer
|
||||
|
||||
## Overview
|
||||
|
||||
The trainer is the brain's quality gate. It runs in two phases:
|
||||
|
||||
- **READ phase:** scan session logs, score candidate learnings 1-5, output the candidate list.
|
||||
- **WRITE phase:** take candidates that score ≥3, apply a quality gate (must generalize, no project-specific identifiers, must be clear cold), emit knowledge entries.
|
||||
|
||||
`session-retrospective` surfaces candidates loosely. The trainer is stricter — it produces only generalized, reusable knowledge, the kind that earns its place in long-term memory.
|
||||
|
||||
**Core principle:** If a knowledge entry only makes sense to someone who was in the session, it does not belong in the brain.
|
||||
|
||||
## Iron Laws
|
||||
|
||||
1. **Do not call `brain_write` from this skill.** Emit entries; the operator decides which to commit.
|
||||
2. **Apply the quality gate before emitting any entry.** A skipped gate produces brain pollution.
|
||||
3. **No project-specific paths, identifiers, or function names in entries.** If you cannot generalize the lesson, drop the entry.
|
||||
|
||||
## When to Use
|
||||
|
||||
- Periodically (weekly, or after a stretch of intense work) — not after every session
|
||||
- When `session-retrospective` has produced too many candidates to keep — trainer filters them
|
||||
- When the brain is becoming noisy and needs curation pruning before adding more
|
||||
|
||||
**Do not use for:**
|
||||
- Single sessions with one or two clear learnings (use `session-retrospective` directly)
|
||||
- Project-specific decisions (those belong in CLAUDE.md, not the brain)
|
||||
|
||||
## Phase READ — Scan and Score
|
||||
|
||||
### What to Look For
|
||||
|
||||
- **Patterns that worked** — the approach was clean, correct, and worth reinforcing for future sessions
|
||||
- **Corrections** — something was first done wrong, then corrected. Both sides are valuable: the rationalization that led to the wrong path, and the correction that fixed it.
|
||||
|
||||
### Scoring (1-5)
|
||||
|
||||
| Score | Criteria |
|
||||
|---|---|
|
||||
| 5 | Novel pattern, clearly correct, generalizes across projects and domains |
|
||||
| 4 | Good pattern, correct, somewhat project-specific but still broadly useful |
|
||||
| 3 | Correct but obvious — include only if especially clean or pedagogically useful |
|
||||
| 2 | Trivial or already widely known — skip |
|
||||
| 1 | Project-specific noise, mechanical fix, or single-use detail — skip |
|
||||
|
||||
Anything below 3 is dropped. Anything at 3 is borderline — include only if the operator might benefit from the framing.
|
||||
|
||||
### READ Output Format
|
||||
|
||||
Respond in markdown:
|
||||
|
||||
```
|
||||
**Candidate N (score: X/5, type: pattern|correction)**
|
||||
- **What happened:** Brief description of the learning moment
|
||||
- **Why it's valuable:** What makes this worth preserving
|
||||
- **Key insight:** The distilled lesson in one sentence
|
||||
```
|
||||
|
||||
End with: `N candidates found (M scoring ≥ 3)` — the WRITE phase will use the ≥3 candidates.
|
||||
|
||||
## Phase WRITE — Emit Knowledge Entries
|
||||
|
||||
### Quality Gate
|
||||
|
||||
Apply BEFORE writing each entry. Drop the entry if any check fails:
|
||||
|
||||
- **Lesson** is phrased so it could apply to any project, not just this one — no project-specific paths, variable names, function names, or repo identifiers
|
||||
- **When it applies** may name a stack or tool family (e.g. "Go projects with golangci-lint") to scope the relevance, but must not name specific files or functions
|
||||
- **Example** may use concrete tool names, language syntax, or commands to make the point land — concrete examples are pedagogically necessary; only the Lesson and When-it-applies sections need to generalize
|
||||
- The insight is clearly stated enough that someone reading it cold (no session context) understands it
|
||||
- The lesson is not already in `CLAUDE.md` or an existing memory file
|
||||
|
||||
### WRITE Output Format
|
||||
|
||||
For each candidate that passes the quality gate:
|
||||
|
||||
```
|
||||
# [Topic]
|
||||
|
||||
## Lesson
|
||||
|
||||
[The key insight in 1-3 sentences. Generalized — no project-specific names.]
|
||||
|
||||
## When it applies
|
||||
|
||||
[Conditions under which this pattern is relevant.]
|
||||
|
||||
## Example
|
||||
|
||||
[A brief, generic example illustrating the lesson. Pseudocode or
|
||||
language-agnostic prose preferred over a copy of the original code.]
|
||||
```
|
||||
|
||||
After all entries, end with: `N entries ready for brain_write` or `0 entries passed quality gate — <reason>`.
|
||||
|
||||
The operator (or a calling agent) decides whether to actually run `brain_write` on each entry. This skill does not write directly.
|
||||
|
||||
## Worked Example
|
||||
|
||||
### READ phase output
|
||||
|
||||
```
|
||||
**Candidate 1 (score: 4/5, type: correction)**
|
||||
- **What happened:** Implementer subagent reported "tests pass" after running `go test ./...`, but CI failed on a `defer resp.Body.Close()` errcheck violation 30 minutes later.
|
||||
- **Why it's valuable:** Captures a specific gap between local verification and CI verification that is easy to repeat across Go projects.
|
||||
- **Key insight:** Per-task verification must include the linter, not just the test runner.
|
||||
|
||||
**Candidate 2 (score: 5/5, type: pattern)**
|
||||
- **What happened:** Repaired malformed JSON from LLM output by stripping invalid escape sequences before parsing. Generalizes well — most LLM-as-JSON pipelines need this.
|
||||
- **Why it's valuable:** Pattern works across any LLM-as-JSON ingestion pipeline.
|
||||
- **Key insight:** Treat LLM JSON output as untrusted input that may need normalization before parsing.
|
||||
|
||||
**Candidate 3 (score: 3/5, type: pattern)**
|
||||
- **What happened:** Implementer subagent saved its commit SHA in the structured report so the spec reviewer could verify against a stable revision.
|
||||
- **Why it's valuable:** Obvious in hindsight, but cleanly framed — passing identifiers between subagents avoids race conditions when the file changes mid-review.
|
||||
- **Key insight:** Subagent reports should include verifiable identifiers (commit SHAs, file hashes) the reviewer can pin against.
|
||||
|
||||
**Candidate 4 (score: 2/5, type: pattern)**
|
||||
- **What happened:** Renamed a local variable from `data` to `invoiceLineItems` for clarity.
|
||||
- **Why it's valuable:** It's good practice but trivial.
|
||||
- **Key insight:** Use names that describe what the data is.
|
||||
|
||||
4 candidates found (3 scoring ≥ 3)
|
||||
```
|
||||
|
||||
### WRITE phase output
|
||||
|
||||
```
|
||||
# Per-task verification must include lint
|
||||
|
||||
## Lesson
|
||||
|
||||
When dispatching tasks that include "tests pass" as a success criterion,
|
||||
the verification command must include the project's linter, not just the
|
||||
test runner. Tests verify behavior; linters catch policy violations
|
||||
(error handling, unused variables, formatting) that the test suite is
|
||||
blind to.
|
||||
|
||||
## When it applies
|
||||
|
||||
Any project with a CI lint gate, particularly Go projects with
|
||||
golangci-lint configured for errcheck or similar policies.
|
||||
|
||||
## Example
|
||||
|
||||
In a project with a Taskfile that chains lint + test, the per-task
|
||||
verification should be `task check`, not `go test ./...`. The latter
|
||||
will pass locally and fail in CI.
|
||||
|
||||
---
|
||||
|
||||
# LLM JSON output is untrusted input
|
||||
|
||||
## Lesson
|
||||
|
||||
Output from an LLM that is supposed to be JSON should be treated as
|
||||
untrusted input. It may contain invalid escape sequences (often from
|
||||
markdown-formatted content the LLM included), structurally valid but
|
||||
semantically wrong fields, or trailing prose. Normalize before parsing.
|
||||
|
||||
## When it applies
|
||||
|
||||
Any pipeline that calls an LLM with a JSON output contract and parses
|
||||
the response with a strict JSON parser.
|
||||
|
||||
## Example
|
||||
|
||||
Wrap the parser in a normalization step: strip invalid escape sequences,
|
||||
trim trailing prose after the closing brace, validate against the
|
||||
expected schema. Treat the LLM as a network boundary, not a function call.
|
||||
|
||||
---
|
||||
|
||||
# Subagent reports should carry verifiable identifiers
|
||||
|
||||
## Lesson
|
||||
|
||||
When a subagent reports completion of work that another agent will verify,
|
||||
the report must carry an identifier that pins the verifiable state — a
|
||||
commit SHA, file hash, or revision number. Without one, the verifier may
|
||||
read a different state than the subagent produced if the workspace
|
||||
changes between report and review.
|
||||
|
||||
## When it applies
|
||||
|
||||
Any multi-agent workflow with a verify-after-implement step, particularly
|
||||
when the workspace is shared (a worktree or branch held by multiple
|
||||
processes).
|
||||
|
||||
## Example
|
||||
|
||||
After committing changes, a subagent reports `Status: DONE, SHA: abc1234`.
|
||||
The verifier runs `git show abc1234` to read exactly the state the
|
||||
subagent produced, even if newer commits arrived in the interim.
|
||||
|
||||
3 entries ready for brain_write
|
||||
```
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
| Anti-Pattern | Why It Fails |
|
||||
|---|---|
|
||||
| Score everything 4 or 5 | The gate exists for a reason. If everything is high-value, nothing is. |
|
||||
| Knowledge entries with project-specific paths | They will not match queries from other projects, defeating the brain's value. |
|
||||
| Writing entries directly without the quality gate | Polluted brain → useless brain. The gate is the whole point. |
|
||||
| Skipping READ and going straight to WRITE | The score is what determines whether to write. Without it, you are just transcribing. |
|
||||
|
||||
## Brain MCP Integration
|
||||
|
||||
The brain holds prior curated knowledge entries. Querying it before READ prevents duplicate entries from cluttering the gate.
|
||||
|
||||
**Before READ:**
|
||||
- Run `brain_query` for the topics that appear in the session log. This prevents scoring candidates that are already in the brain (skip them — same content twice does not help).
|
||||
|
||||
**After WRITE:**
|
||||
- This skill does NOT call `brain_write`. The operator decides which entries to commit, then runs `brain_write` per accepted entry.
|
||||
|
||||
### Logging
|
||||
|
||||
Call `session_log` once at the end of every phase to record the outcome.
|
||||
Pass-rate is computed downstream by the `/pass-rate` HTTP endpoint, which
|
||||
treats `pass` as success, `fail` as failure, `skip` as neither.
|
||||
|
||||
**At end of `read` phase:**
|
||||
- `session_log` with `{skill: "trainer", phase: "read", final_status: "pass" | "fail" | "skip", message: "<one-line summary>", duration_ms: <wall-clock>, project_root: "<absolute path>"}`
|
||||
|
||||
**At end of `write` phase:**
|
||||
- `session_log` with `{skill: "trainer", phase: "write", final_status: "pass" | "fail" | "skip", message: "<one-line summary>", duration_ms: <wall-clock>, project_root: "<absolute path>"}`
|
||||
|
||||
**Phases for this skill:** read, write
|
||||
|
||||
**Status semantics:**
|
||||
- `pass` — the phase's intended outcome was reached (read: candidates scored; write: gate-passed entries emitted).
|
||||
- `fail` — the phase's intended outcome was NOT reached.
|
||||
- `skip` — phase was skipped intentionally (e.g. no candidates passed the gate, write skipped).
|
||||
|
||||
**Why this matters:** the routing pod (Plan 6) reads pass-rate to decide whether to route a future call to a local model. If your skill never logs, the routing pod sees no data.
|
||||
|
||||
## Mode 2 Routing Note
|
||||
|
||||
Trainer is the same shape as `session-retrospective` — long-context reading, mechanical filtering — and is a Mode 2 routing candidate. Until Plan 6, treat as Mode 1 only.
|
||||
|
||||
## Cross-References
|
||||
|
||||
- Load `session-retrospective` first if you want a looser, faster surfacing pass before the strict gate.
|
||||
- The brain's `brain_query` and `brain_write` tools are the read/write side of the brain that this skill curates.
|
||||
Reference in New Issue
Block a user