Group G — markdown tech-debt cleanup (post-audit 2026-05-02).
- 36 SKILL.md files: added "## When to use" section. Was missing across the
catalog; orchestrator routing by keyword could not auto-dispatch.
- 20 code-implementer agent .md files: added Output Footer block prescribing
RULE 0.16 STATUS-TRUTH MARKER schema in agent's final report. Previously only
code-implementer-rust.md had it; other 27 language/role variants were silent
about the marker, breaking RULE 0.16 §3 status-truth aggregation for non-Rust
batches.
- skills/site-create/: added phase-5-preview.md and phase-6-deploy.md skeleton
files. SKILL.md table-of-contents referenced 7 phases; only 5 existed on disk.
- skills/{ai-animation,rag-pipeline}/skill.md: added migration banner comment
noting they should be SKILL.md (canonical filename). Case-rename via git is a
separate orchestrator task (macOS APFS is case-insensitive; Linux deploy needs
explicit rename).
- 3 deprecated skills (site-builder, competitor-analysis, design-inspiration):
added concrete removed-after dates (was vague "before v2").
- docs/CONVERGENCE-PLAN.md:129: TBD on _blocks/evidence-grading.md duplicate
resolved (file exists, not duplicated).
- docs/DNA-INDEX.md: count edits made then overwritten by auto-encyclopedia-refresh
hook during agent run. The .kei-registry-ignore files in test fixtures (Group F)
are the structural fix; kei-registry walker implementation is the follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.2 KiB
6.2 KiB
| name | description | argument-hint |
|---|---|---|
| vm-provision | End-to-end VPS provisioning — select provider → plan → provision → harden → verify (ssh-check + firewall-diff hard-gate) → handoff. 6 phases, ≥6 AskUserQuestion calls, defensive-only. Stops if either verification primitive fails. | <optional one-line intent, e.g. "staging api hetzner eu"> |
/vm-provision — 6-Phase VPS Pipeline (index)
When to use
- Provisioning a new VPS from scratch: select provider → plan → provision → harden → verify → handoff.
- Setting up a hardened production or staging server with firewall verification as a hard gate.
- Any new VM where the security posture (fail2ban, UFW, non-root SSH) must be verified before handoff.
You turn a short intent ("staging API in EU") into a hardened, verified
VPS ready to host an app. Six phases. Every provider choice, plan detail,
and fix is surfaced as an AskUserQuestion click — no silent defaults.
This SKILL.md is the INDEX. Each phase lives in its own file, executed in
order. Never skip a phase. Never re-order phases.
Pipeline overview
| Phase | File | Purpose | AskUserQuestion |
|---|---|---|---|
| 1 | phase-1-select-provider.md | Provider + region + plan + ARM/x86 | 2× |
| 2 | phase-2-plan.md | Plan Mode doc: ports, TLS, admin user | 1× |
| 3 | phase-3-provision.md | Provision + SSH first contact | 1× |
| 4 | phase-4-harden.md | Run harden-base.sh over SSH |
1× |
| 5 | phase-5-verify.md | ssh-check + firewall-diff HARD GATE |
1× |
| 6 | phase-6-handoff.md | Artifact list + optional /web-deploy |
— (final report) |
Minimum AskUserQuestion count across a complete pipeline: 6+ — pure- click contract. Only the intent argument and per-port customisations are typed.
Hard-Gate Invariant (LOAD-BEARING)
No application is deployed onto a VM that has not passed BOTH
ssh-check(exit 0) andfirewall-diff(exit 0) in Phase 5.
Enforced by Phase 5:
ssh-check --config /etc/ssh/sshd_config --drop-in /etc/ssh/sshd_config.d→ exit 0.ufw status numbered | firewall-diff --intent firewall-intent.yaml --stdin→ exit 0.- Any non-zero exit → STOP the pipeline; loop back to Phase 4 after the user approves a remediation path.
The verify step is DEFENSIVE ONLY (read + parse). It never scans the host for open CVEs or probes third-party endpoints.
Variables the pipeline produces
| Name | Set in | Meaning |
|---|---|---|
INTENT |
arg | 1-line user description of the target VM |
PROVIDER |
Phase 1 | hetzner / vultr / digitalocean / upcloud / linode |
REGION |
Phase 1 | provider-specific region code |
PLAN |
Phase 1 | cx22 / cax11 / vc2-1c-1gb / … |
ARCH |
Phase 1 | x86_64 / arm64 |
ADMIN_USER |
Phase 2 | default keiadmin |
SSH_PORT |
Phase 2 | default 22; custom permitted |
APP_PORTS |
Phase 2 | e.g. [443/tcp, 80/tcp] |
TLS_HOST |
Phase 2 | optional FQDN for Caddy |
VM_IP |
Phase 3 | IPv4 of the created VM |
VM_NAME |
Phase 3 | provider resource label |
HARDENED |
Phase 4 | true when harden-base.sh exited 0 |
SSH_CHECK_OK |
Phase 5 | exit 0 of ssh-check |
FW_DIFF_OK |
Phase 5 | exit 0 of firewall-diff |
HANDOFF_TO |
Phase 6 | next skill (e.g. /web-deploy) or none |
Final report (emit after Phase 6)
=== /VM-PROVISION REPORT ===
Intent: <first 80 chars of INTENT>
Provider: <PROVIDER> / region=<REGION> / plan=<PLAN> / arch=<ARCH>
VM: <VM_NAME> @ <VM_IP>
Admin: <ADMIN_USER> (ssh port <SSH_PORT>)
Ports: <APP_PORTS>
TLS: <TLS_HOST or "none">
Hardened: <HARDENED>
Verification: ssh-check=<PASS/FAIL> firewall-diff=<PASS/FAIL>
Handoff: <HANDOFF_TO>
Artifacts: <terraform state path | cloud-init.yaml path>
Rules (enforced at every phase)
- Pure-click contract. Only
INTENT(argument) and custom port values (Phase 2.c) are typed. Every other decision is anAskUserQuestion. - Hard gate (Phase 5).
ssh-checkANDfirewall-diffmust exit 0 before Phase 6. Neither can be skipped. - RULE -1 NO DOWNGRADE. Any phase that fails returns 2-3 constructive paths, never "can't be done".
- RULE 0.8 Secrets Single Source. All provider tokens come from
~/.claude/secrets/.env(or per-projectsecrets/*.env). NEVER read a token from the conversation, NEVER write one to a file. - RULE 0.4 NO HALLUCINATION. Provider specifics (prices, region codes, plan IDs) must be fetched at time of use, not recalled. Cite source.
- RULE 0.5 Plan Mode First. Phase 2 writes the plan; no provisioning happens before the user clicks "approve".
- Defensive-only. No scanning tools, no CVE probes, no third-party attack surface analysis. Pure config linting.
- Surgical changes. Harden only the VM being provisioned. Never touch the caller's workstation config.
- Constructor Pattern (RULE ZERO). Each phase file ≤ 200 LOC; generated cloud-init / Caddyfile artefacts never exceed 200 LOC — split into role-specific files if they would.
References
- phase-1-select-provider.md · phase-2-plan.md · phase-3-provision.md · phase-4-harden.md · phase-5-verify.md · phase-6-handoff.md
_blocks/deploy-hetzner-cloud.md— Hetzner Cloud specifics (Phase 1)_blocks/deploy-vps-generic.md— provider-agnostic cloud-init + TF skeleton (Phase 1/3)_blocks/security-ssh-hardening.md— sshd drop-in baseline (Phase 4/5)_blocks/security-firewall-ufw.md— ufw intent schema (Phase 2/5)_blocks/security-tls-caddy.md— TLS (Phase 6 handoff)_blocks/security-audit-logging.md— auditd baseline (Phase 4)_blocks/security-patching.md— unattended-upgrades (Phase 4)_primitives/provision-hetzner.sh·_primitives/provision-vultr.sh— provisioners (Phase 3)_primitives/harden-base.sh— hardening script (Phase 4)_primitives/_rust/ssh-check/·_primitives/_rust/firewall-diff/— verify gate (Phase 5)skills/web-deploy/SKILL.md— optional Phase 6 handoff