Agent Builder
shareAI-lab/learn-claude-code
Design and build AI agents for any domain. An agent skill from shareAI-lab/learn-claude-code.
Updates the docs website after a change to the SDK or CLI. An agent skill from tetherto/qvac.
$ npx skills add tetherto/qvac --skill qv-docs-update -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install tetherto/qvac qv-docs-update --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/qv-docs-update .claude/skills/qv-docs-update && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .claude/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-updateType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add tetherto/qvac --skill qv-docs-update -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install tetherto/qvac qv-docs-update --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/qv-docs-update .agents/skills/qv-docs-update && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .agents/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add tetherto/qvac --skill qv-docs-update -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install tetherto/qvac qv-docs-update --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/qv-docs-update .cursor/skills/qv-docs-update && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .cursor/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/tetherto/qvac.git --path .agents/skills/qv-docs-update--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add tetherto/qvac --skill qv-docs-update -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install tetherto/qvac qv-docs-update --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/qv-docs-update .gemini/skills/qv-docs-update && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .gemini/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install tetherto/qvac qv-docs-updateInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add tetherto/qvac --skill qv-docs-update -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/qv-docs-update .github/skills/qv-docs-update && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .github/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add tetherto/qvac --skill qv-docs-update -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install tetherto/qvac qv-docs-update --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/tetherto/qvac.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/qv-docs-update .opencode/skills/qv-docs-update && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "qv-docs-update" agent skill from https://github.com/tetherto/qvac/tree/main/.agents/skills/qv-docs-update into .opencode/skills/qv-docs-update/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "qv-docs-update", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
qv-docs-updateUpdates the docs website after a change to the SDK or CLI. An agent skill from tetherto/qvac.
Qv Docs Update is an agent skill from tetherto/qvac. Updates the docs website after a change to the SDK or CLI. Finds the pages your change made out of date and proposes the smallest edit that fixes them. Use when invoking /qv-docs-update.
Its SKILL.md is about 11k tokens, which your agent loads only when the skill is triggered. The skill folder holds 12 other files, including scripts and reference files (for example `agents/openai.yaml`, `references/docs-impact-policy.md` and `references/docs-scope.md`).
It sits in AI & LLM Engineering. The repository describes itself as: Open-source local AI SDK - run AI on-device with no cloud, no API keys. Supports GGUF, RAG, image, music, and video generation, speech-to-text, P2P inference, and more… The licence is Apache-2.0.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit c3a6030. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 3 files in scripts/ (TypeScript and Shell), which the agent can run.
Shell commands in SKILL.md call:
gitbunbashghFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git and gh, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Qv Docs Update loads about 11k tokens when it runs, and up to ~20k if it reads all its reference files. Until then it costs about 50 tokens; SKILL.md has 4,983 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from tetherto/qvac at commit c3a6030, republished under its Apache-2.0 licence (© tetherto). 4,983 words, ~10,640 tokens.
.claude/skills/qv-docs-update/SKILL.md (or your agent's skills folder). This skill also uses 9 other files; get the full folder from GitHub.Whenever a developer finishes implementing a feature in the SDK or the CLI, they invoke this skill to update the docs website, adding or updating the content. That way, every new feature PR opens with its documentation already in place.
Route a source change to the documentation pages it invalidated. Propose the smallest patch that makes them correct again.
Everything you write is read by a developer building a local AI application on QVAC, an open-source ecosystem. docs/website is their developer portal: it teaches how to use the SDK and the CLI, never how the codebase works internally. Write for that reader in Phase 3 and Phase 5.
Run this skill only when the developer asks for it. The source API must be stable. Do not run it mid-implementation: developers iterate on an API several times before it settles, and prose written against a moving surface is the waste this skill exists to avoid.
There are three observed source packages: packages/sdk, packages/sdk-python, packages/cli. They are read-only.
Never edit anything under packages/**. If a source file is wrong, report it and stop. Fixing source is the developer's job.
The writable surface is defined in references/docs-scope.md. Read that file before writing anything. A write outside the allowlist aborts the run and reverts every patch already applied.
One constraint from that file shapes every phase, so it is repeated here. The SDK and the CLI are each cut into one documentation line per published version, and this skill writes to the current line only — the folder written in parentheses, sdk/(v0.20) and cli/(v0.14). It documents the working tree, which is the release not yet cut; a line already cut documents a release already shipped. Resolve the folder each run, never from memory:
ls docs/website/content/docs/sdk | grep '^(v'
ls docs/website/content/docs/cli | grep '^(v'The two scripts that read the docs — the Phase 4 router and the Phase 6 parity gate — resolve it the same way and exit 2 if a collection has anything other than exactly one current line. Page paths below are written sdk/<line>/…, and the routing map uses the same placeholder.
The skill builds four objects, in order. Each one appears as a block in the final report.
| Object | Question it answers | Built in |
|---|---|---|
SOURCE_CHANGE_SET | What changed in the code? | Phase 2 |
DOCS_IMPACT | What does that mean for a user? | Phase 3 |
DOCS_TARGETS | Which pages and sections became wrong, and why? | Phase 4 |
DOCS_PATCH | What is the smallest change that fixes them? | Phase 5 |
Cardinality:
1 SOURCE_CHANGE_SET -> 1 DOCS_IMPACT (always one, never split)
1 DOCS_IMPACT -> N pages (routing is a union of hits)
1 page -> N targets (distinct sections of that page)
1 target -> 1 reason + 1 patchDOCS_IMPACT is always a single report. Never split it. Never estimate how many pages it will touch. The router produces the page grouping, deterministically.
You have exactly two jobs in this pipeline, and both are verifiable: describe the change (Phase 3), and judge a concrete page you have in front of you (Phase 4). Nothing here asks you how many independent impacts a change contains. That question has no ground truth, and nothing downstream needs the answer.
A state classifies the documentary impact of a change, and decides what the skill does next: proceed to routing, stop and report, or ask the developer a question.
There are eight. Six classify one source file. Two describe the whole run.
| State | Scope | Meaning |
|---|---|---|
NO_SOURCE_CHANGE | run | Nothing changed in the three packages against the merge base. |
NO_DOCS_IMPACT | file | Code changed. Nothing user-facing went stale. |
GENERATED_DOCS_ONLY | file | User-facing impact, fully covered by a generated surface. |
DOCS_UPDATE_REQUIRED | file | Editable prose must change. Proceed to routing. |
NEW_CAPABILITY_PAGE | file | New AI capability with no page. The skill creates it. |
NEW_MODELS_PAGE | file | New model-lifecycle topic with no page. The skill creates it. |
HUMAN_INPUT_REQUIRED | file | An ambiguity the repo does not resolve. Ask the developer. |
DONE | run | Every patch applied and validated. |
The two page-creation states are the same operation on different subtrees, and they are mutually exclusive. Separate them by what the symbol is about, not by where its source file sits. A symbol that performs inference — it takes a prompt, audio, or an image and returns a generated result — is an AI capability. A symbol that acquires, inspects, or prepares a model without performing inference is a model-lifecycle topic. completion and transcribe are the first. downloadAsset and assessModelFit are the second.
Assign the file-scoped states one source file at a time. If one file is unresolved, keep the patches already proposed for the files that routed cleanly.
Both scripts report a single run-level state field, and it is advisory. You own the state machine, not the scripts.
The collector decides only the two states it can prove alone, NO_SOURCE_CHANGE and NO_DOCS_IMPACT, and reports CONTINUE for everything else. CONTINUE is not one of the seven states: it means the script reached no verdict and Phase 3 must judge. The router reports its best guess from the routing signals it can see. Treat either field as a starting point, then refine per file as you work.
The final report carries one state in its header. Choose it this way. If any file is HUMAN_INPUT_REQUIRED, then report HUMAN_INPUT_REQUIRED, and list the resolved patches alongside the pending question. Else if every patch was applied and validated, then report DONE. Else report the state that every file shares.
This is every path through the skill, and every point where it stops. The phases below implement this flow.
Developer finishes the feature
│
▼
/qv-docs-update
│
▼
Phase 1 — resolve the merge base; collect committed, staged,
unstaged and untracked changes
│
├── nothing changed ──────────────► NO_SOURCE_CHANGE STOP
├── every changed file `internal` ─► NO_DOCS_IMPACT STOP
▼
Phase 1 — export diff, TSDoc diff, auxiliary context
│
▼
Phase 2 — build SOURCE_CHANGE_SET
│
▼
Phase 3 — classify against the impact policy
│
├── nothing user-facing ──────────► NO_DOCS_IMPACT STOP
├── a generated surface covers it ─► GENERATED_DOCS_ONLY STOP
├── is the behaviour supported? ──► HUMAN_INPUT_REQUIRED STOP
│ the repo does not say
▼
DOCS_UPDATE_REQUIRED
│
▼
Phase 4 — run the router
│
├── new_capability_symbols ───────► NEW_CAPABILITY_PAGE
│ symbol performs inference four append-only edits,
│ then Phase 6
│
├── new_capability_symbols ───────► NEW_MODELS_PAGE
│ symbol is model lifecycle three append-only edits,
│ then Phase 6
│
├── unrouted and user-facing ─────► HUMAN_INPUT_REQUIRED
│ for that source only;
│ routed pages continue
▼
Phase 4 — filter each candidate; write one reason for each
│
▼
Phase 5 — write the patch; present the diff
│
├── developer rejects ────────────► revise, present again
▼
Apply to disk
│
▼
Phase 6 — five gates
│
├── any gate fails ───────────────► report the error, leave
│ the patches on disk,
│ do not declare DONE STOP
▼
DONE/tmp/qv-docs-scs.json (written by the script), plus three records you gather by hand: export diff, TSDoc diff, auxiliary context.Start with the script. It resolves the merge base, collects changes across all four git states (committed on the branch, staged, unstaged, untracked), and classifies every path into a bucket.
bash .agents/skills/qv-docs-update/scripts/collect-source-changes.sh > /tmp/qv-docs-scs.jsonThe output has this shape:
{
"state": "CONTINUE",
"base": { "ref": "tether/main", "sha": "3f2a91c…", "short": "3f2a91c", "via": "url" },
"strong_evidence": true,
"buckets": ["api", "examples"],
"file_count": 2,
"files": [{ "path": "packages/sdk/src/client/api/completion-stream.ts", "bucket": "api", "status": "M" }]
}Each file carries a bucket. The bucket decides which router runs in Phase 4.
| Bucket | Paths |
|---|---|
examples | packages/{sdk,sdk-python}/examples/** |
api | packages/sdk/src/client/api/** |
client-other | packages/sdk/src/client/** outside api/ |
surface | barrels, src/types/**, src/schemas/** |
cli-command | packages/cli/src/{bundle-sdk,serve,configure,openai,doctor,verify}/** |
cli-infra | packages/cli/src/cli/**, src/{config,errors,logger,index}.ts |
python-surface | packages/sdk-python/** outside examples/ |
area | packages/sdk/src/{logging,models,server,worker}/** |
internal | everything else |
The script decides two states on its own. It reports NO_SOURCE_CHANGE when nothing changed, and NO_DOCS_IMPACT when every changed file is internal. Every other run reports CONTINUE: changes exist, and their documentary impact is Phase 3's to judge.
state is NO_SOURCE_CHANGE or NO_DOCS_IMPACT, then stop and emit the no-update report. Else continue.strong_evidence is true when any of examples, api, or cli-command was touched. Treat it as weight in Phase 3, not as a verdict. Do not put it in the report.
base.via records how the base was chosen: url when a remote points at tetherto/qvac, explicit when the developer passed --base, single-remote when neither applied and the clone has exactly one remote. Report the base with its via. A single-remote base plus an implausible file_count means the base is wrong, so stop and say so rather than routing hundreds of files.
The script cannot read the public export surface. Get it from the barrel, comparing the base against the working tree.
api or surface bucket, then skip to step 5. Else read the barrel at the base and in the working tree, and record added, removed, and renamed exports.git show <base-sha>:packages/sdk/src/client/api/index.tsCompare it against the current packages/sdk/src/client/api/index.ts. The barrel is the authority on what is public.
api and surface buckets, then record each changed function signature and each changed TSDoc block.git diff <base-sha> -- <file-path>For an untracked file, read the file directly. There is no diff to read.
Collect three things: the branch commit messages (git log <base-sha>..HEAD --format=%s), the PR title and body (gh pr view --json title,body, only when a PR exists), and any changed test that exercises an affected symbol. A new test often states new behaviour more plainly than the diff does.
SOURCE_CHANGE_SETSOURCE_CHANGE_SET text block.This object is what you read from here on. Do not go back to the raw diff after this phase.
SOURCE_CHANGE_SET block in this exact shape.SOURCE_CHANGE_SET
Base: tether/main @ 3f2a91c (via url)
Packages: packages/sdk
Buckets:
- api: packages/sdk/src/client/api/completion-stream.ts
- examples: packages/sdk/examples/completion-events.ts
- surface: packages/sdk/src/types/generation.ts
Exports:
- changed: completion() — new optional parameter `maxTokens?: number`
- unchanged: all others
TSDoc:
- completion(): @param maxTokens added
Tests:
- packages/sdk/test/completion-max-tokens.test.ts (new)DOCS_IMPACTSOURCE_CHANGE_SET block, and references/docs-impact-policy.md.DOCS_IMPACT text block, and a state.The question here is not "did the code change?". Phase 1 already answered that. Ask two questions instead, and answer both.
First: did a claim the docs make stop being true, or become incomplete?
Second: with the docs exactly as they stand today, can a user use the feature that changed?
The two catch different failures. The first catches a page that went stale. The second catches a page that is still entirely correct and yet leaves the user unable to reach the new capability. A new optional parameter usually makes no existing sentence false, and still leaves the user with no way to learn that the parameter exists. If the answer to either question is bad, the change has documentary impact.
Write the DOCS_IMPACT block in this exact shape.
DOCS_IMPACT
User-facing change:
completion() accepts an optional maxTokens parameter.
Public surface affected:
- completion()
- GenerateTextOptions.maxTokens
Behaviour:
- maxTokens caps the total tokens generated in the response.
- Omitted, current behaviour is unchanged.
Generated coverage:
- The API summary will list completion() with the new signature.
- The API summary will NOT describe what maxTokens means. It omits parameter descriptions by design.
Documentary implication:
maxTokens is essential to controlling output, so it belongs on the capability page, per the policy on essential parameters.HUMAN_INPUT_REQUIRED, put that exact question to the developer, and stop.This is the impact ambiguity, not the routing one. It appears when an observable behaviour changed and no barrel export, no TSDoc, no test and no page says whether that behaviour is part of the contract or an accident of the implementation. Documenting an accident is worse than documenting nothing, because the next change silently breaks a promise the docs made. Ask instead of inferring. Phase 4 raises the same state for a different reason: there the behaviour is known and the page is not.
NO_DOCS_IMPACT or GENERATED_DOCS_ONLY, then stop and emit the no-update report. Else continue.When you claim GENERATED_DOCS_ONLY, name the covering surface in the report. An unnamed claim is not checkable.
DOCS_TARGETS/tmp/qv-docs-scs.json, and the DOCS_IMPACT block.DOCS_TARGETS block, grouped by page, with a written reason per candidate.The router reads the JSON from Phase 1, not the SOURCE_CHANGE_SET.
bun run .agents/skills/qv-docs-update/scripts/route-docs-targets.ts --input /tmp/qv-docs-scs.jsonThe output has this shape:
{
"state": "DOCS_UPDATE_REQUIRED",
"base": { "ref": "tether/main", "sha": "3f2a91c…", "short": "3f2a91c", "via": "url" },
"r3_used": false,
"high_page_count": false,
"new_capability_symbols": [],
"pages": [
{
"page": "sdk/(v0.20)/ai-capabilities/text-generation.mdx",
"targets": [
{
"page": "sdk/(v0.20)/ai-capabilities/text-generation.mdx",
"section": "Examples › Usage",
"sectionLevel": 3,
"via": "R1",
"source": "packages/sdk/examples/completion-events.ts",
"evidence": "file=<rootDir>/packages/sdk/examples/completion-events.ts",
"line": 185
}
]
}
],
"unrouted": [{ "source": "…", "bucket": "…", "status": "M", "reason": "…" }],
"discarded": [{ "page": "…", "source": "…", "via": "R4", "reason": "…" }]
}Read the fields as follows:
pages[].targets[] are the candidates. Each one is a page section to judge in step 3.evidence is the authored binding the router matched. It is a fact about the repo, not a guess.line is where that binding sits in the page. Use it to find the section fast.section is null on a page-level hit: every R3 hit, and the cli/<line>/http-server/** subtree of R4. The router bound the page, not a section, because the map and the subtree rule name pages only.unrouted[] are source files no router could place. Handle them in step 5.discarded[] are hits that fell outside the allowlist or hit a path declared undocumented. Copy them into the report. Never re-add them.new_capability_symbols[] are new exported symbols in client/api/ with no page. Each one means NEW_CAPABILITY_PAGE.r3_used is true only when every hit came from the area map. It is run-level, so a run with one R1 hit and one R3 hit reports false. To weigh a single candidate, read its via field instead: R3 is the declared fallback, so treat an R3 candidate with more suspicion than an R1, R2 or R4 hit.high_page_count is true when the router produced more than four pages. It is counted before your filtering, so recount after step 3.There are four routers, and their hits are unioned. R1, R2 and R4 are exact: each resolves a binding that already exists in the content. R3 is the declared fallback and labels itself as such.
| Router | Binding it resolves | Buckets it covers |
|---|---|---|
| R1 | the literal file=<rootDir>/… directive in a fence | examples |
| R2 | the /sdk/reference/api#<symbol> anchor | api, export diff |
| R4 | the ### `qvac <command>` heading | cli-command |
| R3 | references/routing-map.yaml | everything else |
Four router behaviours affect how you read the output:
dist/**.js counterpart.completion-stream.ts exports completion, so the anchor is #completion and never #completionstream. rag.ts exports nine functions and transcribe.ts exports two. Use the same rule when you write a link in a patch.text-generation.mdx links the text `batchCompletion()` to the batch-processing page instead of to its API anchor, and carries a paragraph on how that function shares parallel slots. That page is a real target even though the anchor is absent. A symbol mentioned in prose with no link at all is routed by nothing.## Reference, and for serve/ it adds the whole cli/<line>/http-server/** subtree. That subtree is in the CLI's line, not the SDK's: the HTTP server ships in the SDK and is documented under qvac serve, and the two collections are versioned independently.A pages: [] entry in the routing map is a positive declaration that a path is intentionally not documented. It is why a file can be unrouted without becoming a question.
Judge the page itself, not the diff. Read the section with DOCS_IMPACT in hand.
If section is null, then read the whole page and choose the section yourself, then state that choice and its justification in the candidate's Reason. This is the one place where you pick a target the router did not name, so make the choice auditable rather than silent. If no section on the page fits, dismiss the candidate — do not invent a section for it.
DOCS_IMPACT?Keep the candidate if the answer is yes. Dismiss it if the answer is no. Either way, write the reason. A page that routed by accident has no answer to "which claim here went stale?", and that is what removes it.
The Reason field is the contract for the patch. Phase 5 is bound to it, so write it precisely.
DOCS_TARGETS block, grouped by page, in this exact shape.DOCS_TARGETS — 2 pages, 3 targets
sdk/(v0.20)/ai-capabilities/text-generation.mdx
1. Section: "Features"
Via: R2 (completion -> /sdk/reference/api#completion)
Reason: the list of generation controls is complete today and would
become incomplete by omitting maxTokens.
Action: list maxTokens among the controls.
2. Section: "Examples › Usage"
Via: R1 (packages/sdk/examples/completion-events.ts)
Reason: the introductory sentence describes what the script does, and the
script now demonstrates the new parameter.
Action: update the introductory sentence.
sdk/(v0.20)/configuration/index.mdx
3. Section: "Reference"
Via: R3 (packages/sdk/src/client/config-loader/**)
Reason: R3 bound the page and named no section; "Reference" is the only
section that enumerates config keys, and its key table lacks the
new one.
Action: add the key, its accepted values, and its default.
Dismissed:
- sdk/(v0.20)/ai-capabilities/batch-processing.mdx
Reason: links completion() only by comparison; no claim went stale.There is no page limit, and multi-page is a normal result.
The team rule "1 change == 1 scope" describes the scope of the change in the source. It says nothing about how many pages document that change, and the two are different quantities. A new CLI command that reads a new config key is perfectly scoped, and it needs both cli/<line>/index.mdx and the configuration page. Do not drop a target to keep the page count down. The gate against wide routing is the written reason, not a count.
Routing produced 6 pages after filtering. That is allowed but uncommon. Worth
checking whether routing went wide (candidates that should have been dismissed)
or the source change mixes scopes. The patches stand.new_capability_symbols[], classify the symbol by the rule in States, then run the matching subprocedure, below. If the symbol performs inference, run NEW_CAPABILITY_PAGE. Else run NEW_MODELS_PAGE.Both subprocedures also apply to a symbol the router could not place because no page links its anchor yet. R2 binds a page by the /sdk/reference/api#<symbol> link it already contains, so a public symbol that no prose page mentions routes to nothing and reaches unrouted[] whether or not it is new in this run. A symbol in that position, exported from the barrel and listed in the API summary, needs the page the routers found missing rather than a question to the developer. Confirm the absence before creating the page: search the current line, docs/website/content/docs/sdk/<line>/, for the symbol name and for its anchor, and treat a hit under reference/ as no coverage, since the API summary and the release notes are both generated there. Search that line alone — a hit in a line already cut says the symbol was documented for a shipped release, not that the current one covers it.
unrouted[] that is user-facing and carries no newSymbol, emit HUMAN_INPUT_REQUIRED for that source and ask which page covers the topic.new_capability_symbols[] is derived from unrouted[], so a new symbol appears in both lists. Step 6 already handled it. Asking about it here would create the page and then ask which page covers the topic.
The answer becomes a new routing-map.yaml entry. That is how the map grows. A source file that is not user-facing needs no question: ignore it.
DOCS_PATCHDOCS_TARGETS block, and references/editorial-guidelines.md.Reason, and changes nothing else.Work page by page. Close every target on one page before opening the next, so the developer reviews one file at a time.
Read the whole target page, then locate the target section by its heading.
Write the smallest change that settles that target's Reason, and nothing beyond it.
If the new text asserts something the Reason does not support, it is scope creep or hallucination. Delete it and write it again.
Match the patch to the change type:
| Change in the source | Patch to write |
|---|---|
| Existing example modified | Update the script's introductory sentence. Take it from the example's own top-of-file comment. |
| New example using existing functions | Add a ### subsection under Examples: one introductory sentence, then a complete <Tabs> block for the language files that exist. |
| New essential parameter on an existing function | Document it on the capability page, as a Features bullet or as prose in the relevant section. Follow text-generation.mdx. |
| Observable behaviour changed | Correct the stale statement in place. Do not rewrite the section. |
| New function in an existing capability | Add it to the Functions list with a /sdk/reference/api#<symbol> link. |
| New flag on an existing CLI command | Document it inside that command's own ### block in cli/<line>/index.mdx, following how the neighbouring flags are shown. |
| New CLI command | Add a ### `qvac <command>` heading under ## Reference in cli/<line>/index.mdx, matching the shape of the commands already there. Never a new page. |
| New function that institutes a new capability | Run the NEW_CAPABILITY_PAGE subprocedure, below. |
| New function that institutes a new model-lifecycle topic | Run the NEW_MODELS_PAGE subprocedure, below. |
Present the diff to the developer before writing to disk.
If the developer approves, then apply the patch and preserve the rest of the page byte for byte. Else revise the patch and present it again.
Validation: block.DONE.There are five gates. Run them in order. If any gate fails, report the error, leave the patches on disk for the developer to fix, and do not declare DONE.
NEW_CAPABILITY_PAGE, three for NEW_MODELS_PAGE) — and check each one against the allowlist in references/docs-scope.md.Check the files this run wrote, never the dirty working tree. The tree legitimately holds the developer's own changes under packages/**, which Phase 1 collected on purpose. Treating those as scope violations would abort every run. To confirm nothing else in the website was touched, run git status --short -- docs/website/ and verify that every path it lists is one you wrote.
A file outside the allowlist aborts the run. Revert everything already applied. The three restricted files pass only when the diff is an append inside the one block their row names — the AI-capabilities grid in ecosystem/index.mdx and the pages array of ai-capabilities/meta.json under NEW_CAPABILITY_PAGE, the pages array of models/meta.json under NEW_MODELS_PAGE. src/lib/custom-tree.ts is not among them: it declares the sidebars of the two unversioned collections, and this skill adds a page to neither.
git diff and review the full diff.Check three things: which files and sections were touched, whether the patch is proportional to the source change, and whether any editorial edit unrelated to the source change slipped in. Remove anything unrelated.
This review is the only gate that catches a well-formed but false sentence. Every other gate catches a broken patch: invalid MDX, a file= pointing at nothing, a dead route. A sentence claiming a default is 512 when it is 1024 compiles, renders, and passes all of them. Do not skip this gate.
The skill relies on the developer here, and that works because the reviewer is the person who just wrote the feature. If this skill is ever run where the reviewer is not the feature's author — a CI companion, a sweep over someone else's branch, a batch over old commits — that premise no longer holds. Say so in the report instead of declaring DONE.
Check that every symbol cited in a patch exists in packages/sdk/src/client/api/index.ts, and that every file= directive introduced resolves to a real file on disk.
If the run created a capability page, then run the parity script.
bun run .agents/skills/qv-docs-update/scripts/check-capability-parity.tsIt cross-checks all four registration points, verifies the card's icon is imported and matches the sidebar's, and catches registrations pointing at pages that do not exist. Three of the four points fail silently without it: omit the card, the bullet, or the sidebar entry and the build still succeeds, the tests still pass, and the capability is missing everywhere a user would look.
If the run created a models page instead, then check its three registration points by hand: the page file exists and declares an icon:, sdk/<line>/index.mdx carries a bullet linking its URL under ### Utilities, and sdk/<line>/models/meta.json lists its slug. The script does not cover models/. The silent failure is the same one — omit the bullet or the slug and every other gate still passes — so do not skip this because no command reports it.
docs/website/.bun run test:examples # file refs, example type-check, transpilation, inline blocks, Python
bun run test # website suite (link integrity, open graph, …)
bun run build # static build; catches broken MDX and broken routesNEW_CAPABILITY_PAGEThis is not a phase. It is a conditional subprocedure, and it runs only when a change institutes a new AI capability. Two places call it: Phase 4, for each entry in new_capability_symbols[], and Phase 5, for the last row of the patch-shape table. When it finishes, go to Phase 6. Gate 4 exists to validate it.
A new capability is not "create an MDX". It is one operation with four points, every time. All four are appends. Nothing else is touched.
| # | File | Operation |
|---|---|---|
| 1 | content/docs/sdk/<line>/ai-capabilities/<slug>.mdx | create, from references/capability-page-template.mdx |
| 2 | content/docs/sdk/<line>/ai-capabilities/meta.json | append 1 slug at the end of the pages array |
| 3 | content/docs/ecosystem/index.mdx | append 1 <Card> at the end of the ## AI capabilities grid, and 1 identifier to the lucide-react import |
| 4 | content/docs/sdk/<line>/index.mdx | append 1 bullet at the end of the ### AI tasks list |
The capability belongs to the release being documented, so all of this happens in the current line and in no other. A line already cut shipped without the capability.
If the change requires touching any file outside those four, then stop and emit HUMAN_INPUT_REQUIRED. The case is not a new capability.
Create the page from the template, and declare its icon in the frontmatter.
A versioned collection composes its navigation from the content, so a page carries its own icon rather than a hand-written tree carrying it. The icon is not derivable from the source: propose a Lucide name, use the same one in the card at step 3, and flag it in the report as needing editorial confirmation.
content/docs/sdk/<line>/ai-capabilities/meta.json.The pages array is explicit and ordered, with no catch-all, so it is the whole of the sidebar for that folder. Without this entry the page is reachable by URL and invisible in navigation.
{
"title": "AI capabilities",
"pages": ["text-generation", "…", "image-classification"]
}content/docs/ecosystem/index.mdx.The grid lives on the Ecosystem overview — the page the old site index became — and its cards point at the version-less capability URLs, which the current line answers. Both edits are required. Without the import, the build breaks.
import { MessagesSquare, /* … */, Shapes, Eye, Brain, /* … */ } from 'lucide-react' <Card href="/sdk/ai-capabilities/image-classification" title={<span className="inline-flex items-center gap-2"><Shapes className="size-4 text-[var(--color-fd-primary)]" />Image classification</span>}>
Classify images into labels with confidence scores via a customized GGML backend.
</Card>If the icon name collides in MDX scope, then alias it. Image is imported as Image as ImageIcon for that reason. The page's frontmatter declares the Lucide export itself, so it reads icon: Image where the card reads <ImageIcon>, and the parity gate resolves the alias before comparing them.
content/docs/sdk/<line>/index.mdx, under ### AI tasks.That page is the SDK collection overview, the one the old introduction.mdx became.
* [**Image classification:**](/sdk/ai-capabilities/image-classification) assigning class labels with confidence scores to images, via [a customized GGML backend](https://github.com/tetherto/qvac/tree/main/packages/classification-ggml).Use the same icon in the page's frontmatter (step 2) and the card (step 4).
Write the card and bullet descriptions from this formula, which is already present as an MDX comment in both files.
{/* <Task name>: <what computation is performed> for <what the developer achieves> via <engine> */}Base all three strings — frontmatter description, card, bullet — on the same sentence. They describe the same thing at different lengths and must agree.
NEW_MODELS_PAGEThis is not a phase. It is a conditional subprocedure, and it runs only when a change institutes a new model-lifecycle topic — acquiring, inspecting, or preparing a model, with no inference performed. Two places call it: Phase 4 step 6, and the patch-shape table in Phase 5. When it finishes, go to Phase 6.
models/meta.json, and the bullet all exist and agree.It is the NEW_CAPABILITY_PAGE operation on the models/ subtree, with one point fewer. There is no card, because the Ecosystem overview's only grid is ## AI capabilities and this topic is not one.
| # | File | Operation |
|---|---|---|
| 1 | content/docs/sdk/<line>/models/<slug>.mdx | create, following models/download-lifecycle.mdx and models/sharded-models.mdx |
| 2 | content/docs/sdk/<line>/models/meta.json | append 1 slug at the end of the pages array |
| 3 | content/docs/sdk/<line>/index.mdx | append 1 bullet at the end of the ### Utilities list |
Like a capability, the topic belongs to the release being documented, so every edit lands in the current line.
If the change requires touching any file outside those three, then stop and emit HUMAN_INPUT_REQUIRED. The case is not a model-lifecycle topic.
Create the page, following the shape both existing models/ pages share.
frontmatter: title, icon, description, schemaType: HowTo
## Overview
## Functions
<topic sections>
## Example
<Callout type="success"> footer tipIt is close to the capability skeleton and differs in two ways. There is no ## Models section: the topic is about handling models, not about which ones a task supports. And the topic sections carry the page, so they are the bulk of it rather than an optional extra — download-lifecycle.mdx has five, sharded-models.mdx two.
Open ## Overview by naming the function and the question it answers for the user, then link the function to its API anchor. Do not open by naming an inference engine: that opening belongs to capability pages, which have one, and this topic does not.
content/docs/sdk/<line>/models/meta.json.{
"title": "Models",
"pages": ["download-lifecycle", "sharded-models", "assess-model-fit"]
}content/docs/sdk/<line>/index.mdx, under ### Utilities.Model-lifecycle topics go in ### Utilities, not ### AI tasks. All three existing pages are already there.
* [**Sharded models:**](/sdk/models/sharded-models) download a model that is sharded into multiple parts.The icon is not derivable from the source. Unlike a capability, this page has only one icon to choose, since there is no card to keep in agreement.
description and the bullet on the same sentence. Both describe the topic, at different lengths, and must agree. Keep the description to one line, as both existing pages do.Emit one of these three at the end of the run.
Run with updates:
qv-docs-update — DONE
Source impact:
completion() accepts an optional maxTokens parameter.
Routing:
- sdk/(v0.20)/ai-capabilities/text-generation.mdx via R2 (symbol) -> section "Features"
- sdk/(v0.20)/ai-capabilities/text-generation.mdx via R1 (example) -> section "Examples › Usage"
Generated coverage:
- The API summary covers the signature. It does not cover the parameter's meaning.
Documentation updated:
- sdk/(v0.20)/ai-capabilities/text-generation.mdx (2 sections, +7 −2)
Validation:
- scope ok
- diff reviewed
- grounding ok
- test:examples ok
- test ok
- build okRun with no update:
qv-docs-update — NO_DOCS_IMPACT
Changes detected in packages/sdk (buckets: internal, client-other).
No public surface changed; no documentary claim became incorrect or incomplete.Run partially blocked. The resolved patch survives:
qv-docs-update — HUMAN_INPUT_REQUIRED
Source impact:
completion() accepts an optional maxTokens parameter.
Resolved:
- sdk/(v0.20)/ai-capabilities/text-generation.mdx "Features" via R2 +4 −0
(patch proposed, awaiting approval)
Pending:
- The change in src/types/streaming.ts is user-facing and no router hit. Which
page covers this topic? The answer becomes a new routing-map.yaml entry.
The proposed patch stands — answering the pending question does not invalidate it.Do not do any of the following:
covers frontmatter, no embeddings, no semantic search.file= resolution. Broad factual validation is v2. The developer reviewing the diff wrote the feature, so they catch a false claim.cli/<line>/index.mdx. A new Python example is a tab on an existing page, or a section of sdk/<line>/python-sdk.mdx.scripts/collect-source-changes.sh — Phase 1.scripts/route-docs-targets.ts — Phase 4.scripts/check-capability-parity.ts — Phase 6, gate 4.© tetherto, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 9 other files (scripts, references) in .agents/skills/qv-docs-update of tetherto/qvac.
Open the folder on GitHubat commit c3a6030
Qv Docs Update next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Qv Docs Update this skilltetherto/qvac | 681 | — | ~11k | Automated safety check: Pass | Apache-2.0 | |
| Agent BuildershareAI-lab/learn-claude-code | 78k | 6 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Add Uint Supportpytorch/pytorch | 104k | 2 repos | ~2.3k | Automated safety check: Pass | Custom licence | |
| Peft Fine TuningOrchestra-Research/AI-Research-SKILLs | 13k | 9 repos | ~3.1k | Automated safety check: Pass | MIT | |
| Segment Anything Model GuideOrchestra-Research/AI-Research-SKILLs | 13k | 9 repos | ~3.3k | Automated safety check: Pass | MIT | |
| 1passwordtrpc-group/trpc-agent-go | 1.8k | 15 repos | ~656 | Automated safety check: Pass | Apache-2.0 |
shareAI-lab/learn-claude-code
Design and build AI agents for any domain. An agent skill from shareAI-lab/learn-claude-code.
pytorch/pytorch
Add unsigned integer (uint) type support to PyTorch operators by updating ATDISPATCH macros.
Orchestra-Research/AI-Research-SKILLs
Parameter-efficient fine-tuning for LLMs using LoRA, QLoRA, and 25+ methods.
Orchestra-Research/AI-Research-SKILLs
Guide to using Meta's Segment Anything Model for zero-shot image segmentation with point, box or mask prompts, or automatic mask generation.
trpc-group/trpc-agent-go
Set up and use 1Password CLI (op). An agent skill from trpc-group/trpc-agent-go.
Orchestra-Research/AI-Research-SKILLs
Shows how to store documents and embeddings in Chroma, query them by similarity with metadata filters, and persist them to disk for RAG and semantic search projects.
tetherto/qvac
Creates a Solutions page in the QVAC documentation website from a real use case, generalizing the case into reusable guidance and registering the page in the site navigation.
tetherto/qvac
Plan and prepare the QVAC agent-stack release cascade across @qvac/inference, @qvac/sdk, @qvac/cli, @qvac/ai-sdk-provider, @qvac/opencode-plugin, and @qvac/openclaw-plugin.
tetherto/qvac
Run the deterministic code-quality audit, turn related findings into contextual remediation groups, prepare approval-gated Asana proposals, reconcile recurring runs, or configure twice-monthly…
tetherto/qvac
Review C++ changes for string parameter and call-site efficiency conventions (std::stringview, std::string&&, const std::string&, const char, and TransparentStringMap lookup).
tetherto/qvac
Generate changelog entries for a target add-on package. An agent skill from tetherto/qvac.
tetherto/qvac
Generate release notes for addon packages (non-SDK inference addons, decoder, OCR).
Categories
Updates the docs website after a change to the SDK or CLI. An agent skill from tetherto/qvac. Qv Docs Update is an agent skill from tetherto/qvac. Updates the docs website after a change to the SDK or CLI.
Qv Docs Update fits situations like: invoking /qv-docs-update.
Run `npx skills add tetherto/qvac --skill qv-docs-update -a claude-code`. Or copy the skill folder (.agents/skills/qv-docs-update in tetherto/qvac) into .claude/skills/qv-docs-update in your project. Claude Code loads it when a task matches its description.
Run `npx skills add tetherto/qvac --skill qv-docs-update -a codex`. Or copy the skill folder (.agents/skills/qv-docs-update in tetherto/qvac) into .agents/skills/qv-docs-update in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add tetherto/qvac --skill qv-docs-update -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/qv-docs-update, .gemini/skills/qv-docs-update, .github/skills/qv-docs-update and .opencode/skills/qv-docs-update in your project.
Going by SKILL.md and its folder, Qv Docs Update needs TypeScript and a shell for the scripts in its folder and the command-line tools its instructions call (git, bun, bash and gh). Our summary lists: Node.js; A Bash shell.
SKILL.md contains no URLs. Its commands use git and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Qv Docs Update is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 11k tokens (SKILL.md is roughly 43k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 9.4k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Qv Docs Update: Agent Builder (shareAI-lab/learn-claude-code, 78k stars), Add Uint Support (pytorch/pytorch, 104k stars), Peft Fine Tuning (Orchestra-Research/AI-Research-SKILLs, 13k stars) and Segment Anything Model Guide (Orchestra-Research/AI-Research-SKILLs, 13k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
tetherto (a GitHub organization) maintains it in tetherto/qvac, which has 681 GitHub stars. The repository holds 50 skills in this directory. The repository was last updated on October 7, 2026.
Source: tetherto/qvac on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.