Installs into .claude/skills of the current project.
Are you the author of System Spec Kit?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/michelkerkmeester-system-spec-kit-bff01ca9)
---
name: system-spec-kit
description: "Unified spec-folder workflow + context preservation: Levels 1-3+, validation, trigger-index and ripgrep retrieval. Required for file modifications."
allowed-tools: [Bash, Edit, Glob, Grep, Read, Task, Write]
version: 4.6.0.0
---
<!-- Keywords: spec-kit, speckit, documentation-workflow, spec-folder, template-enforcement, context-preservation, progressive-documentation, validation, trigger-index, retrieval-conventions, ripgrep-retrieval, continuity-writer, handover, opencode-goal, goal-plugin, active_goal, session-goal, importance-tiers -->
# Spec Kit - Mandatory Conversation Documentation
Orchestrates mandatory spec folder creation for all conversations involving file modifications. Ensures proper documentation level selection (1-3+), template usage, and context preservation through AGENTS.md-enforced workflows.
## 1. WHEN TO USE
### What is a Spec Folder?
A **spec folder** is a numbered directory (e.g., `007-auth-feature/`) that contains documentation for a single feature/task or a coordinated packet of related phase work:
Spec folders may also be nested as coordination-root packets with direct-child phase folders (e.g., `specs/02--track/022-feature/011-phase/002-child/`).
- **Purpose**: Track specifications, plans, tasks, and decisions for one unit of work
- **Location**: Under `specs/` using either `###-short-name/` at the root or nested packet paths for phased coordination
- **Contents**: Markdown files (spec.md, plan.md, tasks.md, and implementation-summary.md when work is complete) plus optional support folders such as `scratch/`, `research/`, or `review/`
Think of it as a "project folder" for AI-assisted development - it keeps context organized and enables session continuity.
### Activation Triggers
**MANDATORY for ALL file modifications:**
- Code files: JS, TS, Python, CSS, HTML
- Documentation: Markdown, README, guides
- Configuration: JSON, YAML, TOML, env templates
- Templates, knowledge base, build/tooling files
**Request patterns that trigger activation:**
- "Add/implement/create [feature]"
- "Fix/update/refactor [code]"
- "Modify/change [configuration]"
- Positive keywords include add, implement, fix, update, create, modify, rename, delete and configure. The authoritative Gate 3 classifier intentionally omits `analyze`, `decompose` and `phase` from positive triggers; `analyze` is a read-only disqualifier unless a real write, memory-save or resume trigger is also present.
**Example triggers:**
- "Add email validation to the signup form" → Level 1-2
- "Refactor the authentication module" → Level 2-3
- "Fix the button alignment bug" → Level 1
- "Implement user dashboard with analytics" → Level 3
### When NOT to Use
- Pure exploration/reading (no file modifications)
- Single typo fixes (<5 characters in one file)
- Whitespace-only changes
- Auto-generated file updates (package-lock.json)
- User explicitly selects Option D (skip documentation)
**Rule of thumb:** If modifying ANY file content → Activate this skill.
Status: ✅ This requirement applies immediately once file edits are requested.
### Distributed Governance Rule
Any agent writing authored spec folder docs (`spec.md`, `plan.md`, `tasks.md`, `acceptance-criteria.md`, `implementation-summary.md`, `decision-record.md`, `handover.md`, `review-report.md`, `debug-delegation.md`, `resource-map.md`, `goal.md`, `before-after.md`, `timeline.md`, `roadmap.md` (the last six optional)) MUST use contract-backed templates through `create.sh` or the inline renderer. `goal.md` may also come from `/create:goal`, whose per-kind templates are parity-checked copies of `goal.md.tmpl`. This is a workflow-required gate, not a runtime hook: run `bash .skilled/skills/system-spec-kit/runtime/cli/spec/validate.sh <spec-folder> --strict` after authored spec-doc writes and before completion claims, then route continuity updates through /speckit:save. Deep-research workflow-owned packet markdown (`research/iterations/*.md`, `research/deep-research-*.md`, and progressive `research/research.md` loop updates) is exempt from that generic per-write rule; `/deep:research` must instead run targeted strict validation after every `spec.md` mutation it performs. @deep-research retains exclusive write access for `research/research.md`; @debug retains exclusive write access for `debug-delegation.md`.
- `handover.md` stays in the canonical recovery ladder and is maintained through `/speckit:save` handover_state routing using the handover template for initial creation.
- `review-report.md` remains owned by `@deep-review` when deep review workflows synthesize findings.
- `resource-map.md` is a lazy add-on in every level contract; render it with the inline gate renderer when a packet wants a lean file ledger alongside `implementation-summary.md`. The deep loops write their own evidence ledger of the same name into their artifact directory, not the packet root.
### Utility Template Triggers
| Template | Trigger Keywords | Action |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `handover.md` | "handover", "next session", "continue later", "pass context", "ending session", "save state", "multi-session", "for next AI" | Suggest `/speckit:save` handover maintenance |
| `debug-delegation.md` | "stuck", "can't fix", "tried everything", "same error", "fresh eyes", "hours on this", "still failing", "need help debugging" | Suggest Task-tool debug delegation |
**Rule:** When detected, proactively suggest the appropriate action.
---
## 2. SMART ROUTING
### Resource Domains
This skill uses simple intent/domain routing, not keyed runtime resource routing. It does not select whole `references/<key>/` or `assets/<key>/` subtrees from project, mode, stack, or model signals. Instead, the router discovers markdown resources recursively from `references/` and `assets/`, then applies intent scoring from `RESOURCE_MAP` to load real, guarded resources from the current inventory. Keep this section domain-focused rather than static file inventories.
- `references/retrieval/` for the trigger-index lookup and the ripgrep recipes.
- `references/memory/` for continuity save workflows, trigger-phrase behavior, and the shared embedding stack.
- `references/templates/` for level selection, template selection, and structure guides.
- `references/validation/` for checklist policy, verification rules, decision formats, and template compliance contracts.
- `references/structure/` for folder organization and sub-folder versioning.
- `references/workflows/` for command workflows, shared intake, rename procedures, and worked examples.
- `references/debugging/` for troubleshooting and root-cause methodology.
- `references/cli/` for daemon CLI behavior, shared smart-router behavior, and continuity handback contracts.
- `references/config/` for runtime environment configuration and launcher/lease contracts.
- `assets/*.md` for shared decision matrices, template mapping, and parallel dispatch support.
**Typed leaf projection (fleet routing standard).** system-spec-kit is a normal, registry-less single-mode skill whose sole workflow mode is `system-spec-kit` (there is no `mode-registry.json`). Its router routes ONLY into the `references/` and `assets/` doc corpora, so those are the only routable leaves: every one is enumerated in `leaf-manifest.json`, generated from `leaf-manifest.config.json` (`generate-leaf-manifest.cjs --write .skilled/skills/system-spec-kit`; byte-stable under `--check`). `leaf-aliases.json` binds each router-emitted root-relative path (e.g. `references/memory/memory-system.md`) to its typed `(system-spec-kit, leafResourceId)` identity so a deterministic router replay recovers real typed pairs against the manifest. The `RESOURCE_MAP` below names every leaf in that manifest under at least one intent, so each reference and asset is reachable through the router as well as by browsing; the manifest stays the inventory, and a leaf added to the corpus without an intent is a routing gap to close, not a browse-only tier. The rest of the package is deliberately NOT routable: `runtime/cli/`, `runtime/`, `shared/`, `templates/`, `changelog/` and other engine dirs are the spec-kit runtime, and `feature-catalog/` + `manual-testing-playbook/` are runtime-engine capability docs and behavior-test fixtures — no `RESOURCE_MAP` intent selects them, so they are excluded from `leafRoots` and never appear in the manifest. This is an intentionally thin router: it maps spec-folder workflow intents (plan, implement, complete, memory, phase, hooks, …) to a small set of reference docs, while the large playbook chiefly exercises validation and generator behavior rather than doc routing (most scenarios carry empty typed gold). Regenerate `leaf-manifest.json` and keep `leaf-aliases.json` in sync whenever the `references/` or `assets/` corpus changes.
### Template and Script Sources of Truth
- Level definitions and template size guidance: level specifications reference
- Template usage and composition rules: [template-guide.md](./references/templates/template-guide.md)
- Use the Level contract for operational templates; `create.sh` and the Level contract resolver share the same template index.
- Use `templates/changelog/` for packet-local nested changelog generation at completion time.
- Script architecture, build outputs, and runtime entrypoints: [runtime/cli/README.md](./runtime/cli/README.md)
- Memory save JSON schema and workflow contracts: [save-workflow.md](./references/memory/save-workflow.md)
- Nested packet changelog workflow: [nested-changelog.md](./references/workflows/nested-changelog.md)
Primary operational scripts:
- `spec/validate.sh`
- `spec/create.sh`
- `spec/archive.sh`
- `spec/refresh-track-roots.mjs`
- `spec/sweep-track-roots.mjs`
- `spec/check-completion.sh`
- `spec/recommend-level.sh`
- `runtime/lib/templates/level-contract-resolver.ts`
Spec-script exit codes (`spec/*.sh`; distinct from the daemon-backed memory CLI taxonomy in §3):
- `0`: success.
- `1`: user error such as bad flags or invalid input.
- `2`: validation error.
- `3`: system error such as missing folders, missing manifests, or file I/O failures.
### Resource Loading Levels
| Level | When to Load | Resources |
| ----------- | -------------------------- | ---------------------------- |
| ALWAYS | Every skill invocation | Shared patterns + SKILL.md |
| CONDITIONAL | If intent signals match | Intent-mapped references |
| ON_DEMAND | Only on explicit request | Deep-dive quality standards |
`references/workflows/quick-reference.md` is the primary first-touch command surface. Keep the compact `spec_kit` and `memory` command map there, including `/speckit:plan --intake-only` as the standalone intake entry, `/speckit:plan` and `/speckit:complete` smart delegation notes, and the pointer from `/deep:research` to `../system-deep-loop/deep-research/references/protocol/spec-check-protocol.md`, and use this file only to point readers to it rather than duplicating the full matrix.
### Smart Router Pseudocode
The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling. Because this skill is an intent/domain router, Pattern 3 is adapted to extensible intent labels over discovered resources rather than keyed resource subdirectories.
- Pattern 1: Runtime Discovery - `discover_markdown_resources()` recursively inventories `references/` and `assets/`.
- Pattern 2: Existence-Check Before Load - `load_if_available()` guards, de-duplicates with `seen`, and checks `inventory`.
- Pattern 3: Extensible Routing Key - command and intent signals select domain labels and resource maps without forcing `references/<key>/` or `assets/<key>/` subtrees.
- Pattern 4: Multi-Tier Graceful Fallback - `UNKNOWN_FALLBACK` asks for disambiguation and missing-resource cases return a "no knowledge base" notice.
```python
from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/workflows/quick-reference.md"
INTENT_SIGNALS = {
"PLAN": {"weight": 3, "keywords": ["plan", "design", "new spec", "level selection", "option b"]},
"RESEARCH": {"weight": 3, "keywords": ["investigate", "explore", "analyze", "prior work", "evidence"]},
"IMPLEMENT": {"weight": 3, "keywords": ["implement", "build", "execute", "workflow"]},
"DEBUG": {"weight": 4, "keywords": ["stuck", "error", "not working", "failed", "debug"]},
"COMPLETE": {"weight": 4, "keywords": ["done", "complete", "finish", "verify", "checklist"]},
"MEMORY": {"weight": 4, "keywords": ["memory", "save context", "resume", "checkpoint", "context"]},
"HANDOVER": {"weight": 4, "keywords": ["handover", "continue later", "next session", "pause"]},
"PHASE": {"weight": 4, "keywords": ["phase", "decompose", "split", "workstream", "multi-phase", "phased approach", "phased", "multi-session"]},
"RETRIEVAL_TUNING": {"weight": 3, "keywords": ["retrieval", "search tuning", "fusion", "scoring", "pipeline"]},
"INTAKE": {"weight": 4, "keywords": ["intake", "folder_state", "start_state", "repair-mode", "intake-only"]},
"HOOKS": {"weight": 4, "keywords": ["hook", "skill advisor hook", "advisor hook", "prompt-time advisor", "advisor_validate", "goal plugin", "opencode-goal", "/goal", "active_goal", "session goal", "set goal", "bind goal", "update the goal", "resend goal", "durable slice"]},
"LAUNCHER": {"weight": 4, "keywords": ["launcher", "lease", "pid file", "single-writer", "lease_held_by"]},
"RENAME": {"weight": 3, "keywords": ["rename", "mechanical refactor", "rename pattern", "git mv", "case variants"]},
"EVALUATION": {"weight": 3, "keywords": ["evaluate", "ablation", "benchmark", "baseline", "metrics"]},
"SCORING_CALIBRATION": {"weight": 3, "keywords": ["calibration", "scoring", "normalization", "decay", "interference"]},
"ROLLOUT_FLAGS": {"weight": 3, "keywords": ["feature flag", "rollout", "toggle", "enable", "disable"]},
"GOVERNANCE": {"weight": 3, "keywords": ["governance", "tenant", "retention", "audit"]},
"DISPATCH": {"weight": 3, "keywords": ["dispatch", "parallel agents", "agent header", "result envelope", "sub-agent", "fan-out"]},
"AUTO_MODE": {"weight": 3, "keywords": [":auto", "auto mode", "autopilot", "unattended", "setup resolution"]},
"CLI_TRANSPORT": {"weight": 3, "keywords": ["daemon cli", "cli shim", "memory handback", "smart router", "cli-*", "warm-only"]},
"TEMPLATE_AUTHORING": {"weight": 3, "keywords": ["template style", "author a template", "template convention", "tmpl", "template anchors"]},
}
RESOURCE_MAP = {
"PLAN": [
"references/templates/template-guide.md",
"references/workflows/intake-contract.md",
"references/validation/template-compliance-contract.md",
"assets/level-decision-matrix.md",
"assets/complexity-decision-matrix.md",
"references/templates/level-selection-guide.md",
"references/templates/level-specifications.md",
"references/structure/folder-structure.md",
],
"RESEARCH": [
"references/workflows/quick-reference.md",
"references/workflows/worked-examples.md",
"references/memory/epistemic-vectors.md",
"references/retrieval/retrieval-conventions.md",
"references/structure/grep-convention.md",
],
"IMPLEMENT": [
"references/validation/validation-rules.md",
"references/validation/template-compliance-contract.md",
"references/templates/template-guide.md",
"assets/template-mapping.md",
"references/workflows/execution-methods.md",
"references/validation/path-scoped-rules.md",
],
"DEBUG": [
"references/debugging/troubleshooting.md",
"references/debugging/universal-debugging-methodology.md",
"references/workflows/quick-reference.md",
],
"COMPLETE": [
"references/validation/validation-rules.md",
"references/workflows/nested-changelog.md",
"references/workflows/intake-contract.md",
"references/workflows/spec-folder-write-recipe.md",
"references/workflows/spec-folder-authoring-checklist.md",
"references/validation/decision-format.md",
"references/validation/five-checks.md",
],
"MEMORY": [
"references/memory/memory-system.md",
"references/memory/save-workflow.md",
"references/memory/trigger-config.md",
"references/structure/folder-routing.md",
],
"HANDOVER": [
"references/workflows/quick-reference.md",
],
"PHASE": [
"references/structure/phase-definitions.md",
"references/structure/sub-folder-versioning.md",
"references/validation/phase-checklists.md",
"references/structure/phase-system.md",
],
"RETRIEVAL_TUNING": [
"references/memory/embedder-pluggability.md",
"references/memory/trigger-config.md",
],
"INTAKE": [
"references/workflows/intake-contract.md",
"references/templates/template-guide.md",
"references/validation/template-compliance-contract.md",
],
"HOOKS": [
"references/config/hook-system.md",
"references/workflows/goal-set-string-playbook.md",
],
"LAUNCHER": [
"references/config/launcher-lease.md",
"references/memory/memory-system.md",
],
"RENAME": [
"references/workflows/rename-pattern.md",
],
"EVALUATION": [
"references/memory/epistemic-vectors.md",
"references/config/environment-variables.md",
],
"SCORING_CALIBRATION": [
"references/config/environment-variables.md",
],
"ROLLOUT_FLAGS": [
"references/config/environment-variables.md",
],
"DISPATCH": [
"references/workflows/agent-io-contract.md",
"assets/parallel-dispatch-config.md",
],
"AUTO_MODE": [
"references/workflows/auto-mode-contract.md",
],
"CLI_TRANSPORT": [
"references/cli/daemon-cli-reference.md",
"references/cli/memory-handback.md",
"references/cli/shared-smart-router.md",
],
"TEMPLATE_AUTHORING": [
"references/templates/template-style-guide.md",
"references/templates/template-guide.md",
],
"GOVERNANCE": [
"references/config/environment-variables.md",
],
}
COMMAND_BOOSTS = {
"/speckit:plan": "PLAN",
"/speckit:implement": "IMPLEMENT",
"/speckit:complete": "COMPLETE",
"/speckit:plan --intake-only": "INTAKE",
"/speckit:plan :with-phases": "PHASE",
"/speckit:search": "MEMORY",
"/speckit:save": "MEMORY",
"/speckit:resume": "MEMORY",
}
LOADING_LEVELS = {
"ALWAYS": [DEFAULT_RESOURCE],
"ON_DEMAND_KEYWORDS": ["deep dive", "full validation", "full checklist", "full template", "save context", "/speckit:save", "/speckit:resume", "implementation-summary", "tasks.md", "spec folder", "phase folder", "description metadata"],
"ON_DEMAND": [
"references/validation/phase-checklists.md",
"references/templates/template-guide.md",
"references/workflows/intake-contract.md",
],
}
UNKNOWN_FALLBACK_CHECKLIST = [
"Confirm whether this is planning, memory, validation, phase, debug, or completion work",
"Confirm the target spec folder or command surface",
"Provide one concrete file, error, or expected output",
"Confirm which verification gate must pass",
]
def _task_text(task) -> str:
parts = [
str(getattr(task, "query", "")),
str(getattr(task, "text", "")),
" ".join(getattr(task, "keywords", []) or []),
str(getattr(task, "command", "")),
]
return " ".join(parts).lower()
def _guard_in_skill(relative_path: str) -> str:
"""Allow markdown loads only within this skill folder."""
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() != ".md":
raise ValueError(f"Only markdown resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def _guard_resource_map(resource_map: dict[str, list[str]]) -> None:
"""Reject compatibility stubs as router targets while allowing them to preserve old links."""
for intent, resources in resource_map.items():
for relative_path in resources:
guarded = _guard_in_skill(relative_path)
if guarded.startswith("references/"):
tail = guarded.removeprefix("references/")
if "/" not in tail and "-" in Path(tail).stem:
raise ValueError(f"RESOURCE_MAP must target canonical references, not compatibility stubs: {intent} -> {guarded}")
def discover_markdown_resources() -> set[str]:
"""Recursively discover routable markdown docs for this skill only."""
docs = []
for base in RESOURCE_BASES:
if base.exists():
docs.extend(p for p in base.rglob("*.md") if p.is_file())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def score_intents(task) -> dict[str, float]:
"""Weighted scoring from request text, keywords, and explicit command boosts."""
text = _task_text(task)
scores = {intent: 0.0 for intent in INTENT_SIGNALS}
for intent, cfg in INTENT_SIGNALS.items():
for keyword in cfg["keywords"]:
if keyword in text:
scores[intent] += cfg["weight"]
command = str(getattr(task, "command", "")).lower()
for prefix, intent in COMMAND_BOOSTS.items():
if command.startswith(prefix):
scores[intent] += 6
return scores
def select_intents(scores: dict[str, float], ambiguity_delta: float = 1.0, max_intents: int = 2) -> list[str]:
"""Return primary intent and secondary intent when scores are close."""
ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
if not ranked or ranked[0][1] <= 0:
return []
selected = [ranked[0][0]]
if len(ranked) > 1:
primary_score = ranked[0][1]
secondary_intent, secondary_score = ranked[1]
if secondary_score > 0 and (primary_score - secondary_score) <= ambiguity_delta:
selected.append(secondary_intent)
return selected[:max_intents]
def route_speckit_resources(task):
"""Scoped, recursive, weighted, ambiguity-aware routing."""
_guard_resource_map(RESOURCE_MAP)
_guard_resource_map({
"ALWAYS": LOADING_LEVELS["ALWAYS"],
"ON_DEMAND": LOADING_LEVELS["ON_DEMAND"],
})
inventory = discover_markdown_resources()
scores = score_intents(task)
intents = select_intents(scores, ambiguity_delta=1.0)
loaded = []
seen = set()
def load_if_available(relative_path: str) -> None:
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
# ALWAYS: base references for every invocation
for relative_path in LOADING_LEVELS["ALWAYS"]:
load_if_available(relative_path)
if max(scores.values() or [0]) < 0.5:
return {
"intents": intents or ["UNKNOWN"],
"intent_scores": scores,
"load_level": "UNKNOWN_FALLBACK",
"needs_disambiguation": True,
"disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
"resources": loaded,
}
# CONDITIONAL: intent-scored resources
matched_intents = []
for intent in intents:
before_count = len(loaded)
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
if len(loaded) > before_count:
matched_intents.append(intent)
# ON_DEMAND: explicit deep-dive requests
text = _task_text(task)
if any(keyword in text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
for relative_path in LOADING_LEVELS["ON_DEMAND"]:
load_if_available(relative_path)
if not loaded:
load_if_available(DEFAULT_RESOURCE)
result = {"intents": intents, "intent_scores": scores, "resources": loaded}
if not matched_intents:
result["notice"] = f"No knowledge base found for intent(s): {', '.join(intents)}"
return result
```
---
## 3. HOW IT WORKS
### Core Workflow
1. Gate 3 selects an existing, new, related, skipped, or phase spec folder before file changes.
2. For new folders, estimate level from LOC, risk, affected systems, and verification needs; create from contract-backed templates.
3. Keep phase parents lean: parent folders hold `spec.md`, `description.json`, and `graph-metadata.json`; child phases hold working docs.
4. Clear both completion gates before claiming done: the priority-ordered checklist in the `tasks.md` verification section, and the closure verdict in `acceptance-criteria.md`. See Two Completion Gates below.
5. Preserve continuity in `implementation-summary.md` or through canonical `/speckit:save` with `generate-context.js`.
### Two Completion Gates
Level 2+ packets close through two different documents. They are often conflated, so keep the question each one answers distinct.
| | `tasks.md` verification section | `acceptance-criteria.md` |
|---|---|---|
| Answers | Is the work done? | May the packet close? |
| Unit | A checklist item | A criterion, written Given / When / Then |
| Vocabulary | `[ ]` / `[x]`, tagged P0, P1 or P2 | `Met`, `Unmet`, `Waived`, `Superseded` |
| Enforced by | `check-completion.sh` | `AC_CLOSURE` and `AC_COVERAGE` in `validate.sh` |
| Blocks when | A P0 or P1 item is incomplete, an item carries no priority tag, or a completed P0/P1 item cites no evidence. P2 blocks only under `--strict` | Any criterion is still `Unmet`, or a `Waived` or `Superseded` row names a decision record that does not exist |
The two are linked rather than parallel. `AC_COVERAGE` requires every criterion's evidence to trace back into the merged tasks document, so `tasks.md` is where the proof lives and `acceptance-criteria.md` is where the verdict lives. A criterion marked `Met` with no traceable item behind it is the failure that rule exists to catch.
`acceptance-criteria.md` is an optional add-on: `validate.sh` warns when a Level 2+ packet has none. Once the file exists, `AC_CLOSURE` is an error-severity gate on that packet.
### Retrieval and Continuity
Retrieval is file-based and needs no running service. Gate 1 resolves a prompt against the committed trigger index with `node .skilled/skills/system-spec-kit/runtime/cli/retrieval/lookup-trigger-index.mjs --json -- "<prompt>"`, which exits `0` on candidates, `1` on a clean no-hit and `2` on a bad invocation or unreadable index. Free-text retrieval uses the literal ripgrep recipes in [`references/retrieval/retrieval-conventions.md`](references/retrieval/retrieval-conventions.md), scoped by track and packet through the trailing positional path. Those recipes are precise only because the corpus is regular: [`references/structure/grep-convention.md`](references/structure/grep-convention.md) holds the frontmatter, anchor, naming and body-preservation rules that `validate.sh` enforces on every spec document.
Recovery walks the continuity ladder rather than inferring a session: `handover.md`, then the `_memory.continuity` frontmatter block, then packet-first spec docs, then the bounded context recipe. `/speckit:resume` owns that ladder. Saves go through `node .skilled/skills/system-spec-kit/runtime/cli/dist/continuity/generate-context.js`, invoked by `/speckit:save`; the writer updates the packet's continuity surfaces in place and there is no indexing hand-off afterwards.
Regenerate the index with `node .skilled/skills/system-spec-kit/runtime/cli/retrieval/generate-trigger-index.mjs` after spec-doc frontmatter changes. The artifact at `runtime/data/trigger-index.json` is committed, so a fresh clone answers Gate 1 before anything is built.
`score-track-narrowing.mjs` in the same folder measures offline whether a classifier that names a packet's spec track would beat ripgrep and the lookup: its default run makes no model call and writes no file, `--deem` and `--jev` each add a model column behind that backend's own check, and it changes no lookup, index or recipe.
**Declared loss.** Semantic paraphrase matching, vector and BM25 fusion, decay scoring, access tracking, session dedup and causal traversal are gone and have no file-based successor. A lookup that matches nothing returns nothing; callers must say so plainly rather than degrading to a guess. What `trigger_phrases` never declared, the index cannot find — see `references/retrieval/retrieval-conventions.md` §8 for what belongs in that field.
### Reranking
Model-based cross-encoder/local-GGUF reranking was removed in the 014 deprecation: the local model path was removed in phase 003 and the local rerank sidecar skill was deleted in phase 004 (cloud rerankers were removed earlier in 022/013). Nothing reranks retrieval today. Ripgrep produces matches, paths and lines and never orders them by relevance; ordering is the caller's job, using the deterministic tuple in `references/retrieval/retrieval-conventions.md` §5. That tuple is a stable sort, not a relevance model. The `SPECKIT_CROSS_ENCODER`/`RERANKER_LOCAL` flags are no longer wired.
### Security
- `VOYAGE_API_KEY` is read from the process environment only. It must never be logged, written into spec docs, or persisted to disk by Spec Kit. Operators should set it in shell init files owned by the operator with mode `600`.
- Tests may mutate env vars, but must restore them in `afterEach`. Production code paths should not treat mutable process env as request-time configuration.
### Validation and Recovery
Run `.skilled/skills/system-spec-kit/runtime/cli/spec/validate.sh <spec-folder> --strict` before completion claims. Validation errors block completion; warnings must be addressed or documented. Startup, resume, hook, goal plugin, code graph, and Code Graph readiness details live in `references/config/hook-system.md`, `.skilled/skills/system-skill-advisor/hooks/skill-advisor-hook.md`, `.skilled/hooks/goal/goal-plugin.md`, `runtime/hooks/README.md` (Claude and OpenCode hook folders; OpenCode uses plugin-backed delivery), and the code graph references.
### OpenCode Goal Plugin
The packet `goal.md` is the source of goal state. A session binds to it (`opencode_goal({ action: "bind", packetPath })` on OpenCode, `bin/goal.cjs bind <packet>` on Pi), the runtime injects the objective slice built from the file on every turn, and the per-session record under `.skilled/skills/.state/goal/` keeps only the pointer, liveness and telemetry. When an operator says "set the goal", "bind the goal", "update the goal" or "resend the goal" in conversation, that is this surface: render the parent's chat slice from the file and hand it over to be set, keep reminding while it stays unset and never stop work for it. `node .skilled/hooks/goal/bin/goal.cjs packet <packet> --workspace <repo root>` prints it as `chat_slice`. What that slice contains and when it may be sent are section 4 of `sk-create-goal`'s [budget-and-handoff.md](../sk-doc/sk-create-goal/references/budget-and-handoff.md), and authoring or amending a `goal.md` is `/create:goal`'s. The OpenCode surface is `.skilled/plugins/opencode-goal.js` plus `.skilled/commands/goal-opencode.md`; it injects with `experimental.chat.system.transform`, observes lifecycle events through the plugin `event` hook, and exposes `opencode_goal` / `opencode_goal_status` plugin tools. Use [`.skilled/hooks/goal/goal-plugin.md`](../../hooks/goal/goal-plugin.md) for the operator contract, restart requirement, environment variables, validation commands, and boundary between raw `objective` and generated `goalPrompt`.
### Code Graph and Search Routing
---
## 4. RULES
### ✅ ALWAYS
1. **Determine level (1/2/3/3+) before ANY file changes** - Count LOC, assess complexity/risk
2. **Scaffold from contract-backed templates** - Use `create.sh` or `inline-gate-renderer`, NEVER create from scratch
3. **Fill ALL placeholders** - Remove placeholder markers and sample content
4. **Ask A/B/C/D when file modification detected** - Present options, wait for selection
5. **Prefer coordinated related packets before new top-level folders** - Check active and related specs, their scope, status, and Phase Documentation Map. When related work qualifies for phase decomposition, recommend one phased packet rather than separate single-spec folders.
6. **Get explicit user approval before changes** - Show level, path, templates, approach
7. **Use consistent folder naming** - `specs/###-short-name/` format
8. **Clear both completion gates (Level 2+)** - The `tasks.md` verification checklist AND the `acceptance-criteria.md` closure verdict. Load both before claiming done; see §3 Two Completion Gates
9. **Mark items `[x]` with evidence** - Include links, test outputs, screenshots
10. **Complete P0/P1 before claiming done** - No exceptions
11. **Suggest handover.md on session-end keywords** - "continue later", "next session"
12. **Run validate.sh before completion** - Completion Verification requirement
13. **Create implementation-summary.md at end of implementation phase (Level 1+)** - Document what was built
14. **Suggest /speckit:save when session-end keywords detected OR after extended work (15+ tool calls)** - Proactive context preservation
15. **Suggest Task-tool debug delegation after 3+ failed fix attempts on same error** - Do not continue without offering a fresh debugging pass
16. **Apply the phased-packet preference without bypassing qualification** - Suggest `/speckit:plan :with-phases` only when phase complexity score >= 25 AND documentation level >= 3. If either condition fails, use a standard packet; if the work is new or unrelated, create a separate packet and evaluate that packet independently.
17. **Route all code creation/updates through `sk-code`** - Full surface alignment is mandatory before claiming completion
- **Authoring-time vs review-time load**: `sk-code` is loaded at TWO distinct points in `/speckit:complete`. (a) Authoring-time (Step 10 development): when the implementation target is under `.skilled/skills/`, `.skilled/agents/`, `.skilled/commands/`, or `.opencode/specs/`, load the matching sk-code authoring checklist (`../sk-code/sk-code-opencode/assets/checklists/{surface}-authoring.md`) and, for `.opencode/specs/` targets, the system-spec-kit spec-folder docs (`references/workflows/spec-folder-authoring-checklist.md` + `references/workflows/spec-folder-write-recipe.md`) BEFORE the first write. (b) Review-time (Step 11 review): the existing `sk-code` code-review mode (findings-first baseline + router-selected surface evidence) overlay runs after writes complete. Authoring-time load surfaces invariants the writer needs to honor; review-time load catches drift the writer didn't honor. See the `cross_skill_authoring_load` block in `speckit-complete.yaml` for the YAML contract.
18. **Route all documentation creation/updates through `sk-doc`** - Full alignment is mandatory before claiming completion
19. **Enforce ToC policy from validation rules** - Only `research/research.md` may include a Table of Contents section; remove ToC headings from standard spec artifacts
20. **Literal naming for AI-derived spec folders and phases** - When the AI (not the user) picks a spec-folder or phase slug, the name MUST describe the concrete work being built or fixed. Names must include a specific subject token (the component, behavior, or bug being addressed). Forbidden as standalone slugs: `remediation`, `cleanup`, `fix`, `phase-N`, `review-remediation`, `round-N`. Good remediation-packet examples: `fix-deep-review-p1-p2-findings-for-sk-doc-skill`, `harden-mcp-server-startup-races`, `fix-singleton-leak-in-launcher`. Good phase-decomposition examples: `data-model-design`, `api-implementation`, `ui-integration`. **Remediation-packet source/target rule** - remediation slugs MUST follow `NNN-fix-<source>-for-<target>` where: **Source** = the event or evidence that triggered the packet (e.g. `deep-review-p0-p1-findings`, `verdict-fail`, `audit-finding-NN`); **Target** = the specific component being remediated (e.g. `skill-local-benchmarks-format`, `trigger-index-generator`, `launcher-cache`). The source names WHERE the work comes from; the target names WHAT is being fixed. Do not conflate them: the thing being remediated is the target, not the source. Worked example: `007-fix-deep-review-p0-p1-findings-for-skill-local-benchmarks-format` (source=`deep-review-p0-p1-findings`, target=`skill-local-benchmarks-format`). This rule is documentation-layer guidance; `validate.sh` does not lint slugs today (operator decision; may be lifted in a follow-on packet).
### ⛔ NEVER
1. **Create documentation from scratch** - Use templates only
2. **Skip spec folder creation** - Unless user explicitly selects D
3. **Make changes before spec + approval** - Spec folder is prerequisite
4. **Leave placeholders in final docs** - All must be replaced
5. **Decide autonomously update vs create** - Always ask user
6. **Claim done without clearing both completion gates** - Level 2+ requires the `tasks.md` verification checklist verified with evidence AND every `acceptance-criteria.md` criterion `Met`, `Waived` or `Superseded`
7. **Proceed without spec folder confirmation** - Wait for A/B/C/D
8. **Skip validation before completion** - Completion Verification hard block
9. **Add ToC sections to standard spec artifacts** - `spec.md`, `plan.md`, `tasks.md`, `acceptance-criteria.md`, `decision-record.md`, `implementation-summary.md`, `handover.md`, `debug-delegation.md`, and `resource-map.md` must not contain ToC headings
### ⚠️ ESCALATE IF
1. **Scope grows during implementation** - Run `upgrade-level.sh` to add higher-level templates (recommended), then auto-populate all placeholder content:
- Read all existing spec files (spec.md, plan.md, tasks.md, implementation-summary.md) for context
- Replace every placeholder marker pattern in newly injected sections with content derived from that context
- For sections without sufficient source context, write "N/A - insufficient source context" instead of fabricating content
- Run `check-placeholders.sh <spec-folder>` to verify zero placeholders remain (see level specifications reference for the full procedure)
- Document the level change in changelog
2. **Uncertainty about level <80%** - Present level options to user, default to higher
3. **Template doesn't fit requirements** - Adapt closest template, document modifications
4. **User requests skip (Option D)** - Warn about tech debt, explain debugging challenges, confirm consent
5. **Validation fails with errors** - Report specific failures, provide fix guidance, re-run after fixes
---
## 5. SUCCESS CRITERIA
Success means the selected spec folder uses the right template set, placeholders and sample content are removed, links between packet docs work, continuity is saved or updated, Level 2+ `tasks.md` P0/P1 checklist items are verified with evidence, every `acceptance-criteria.md` criterion is `Met`, `Waived` or `Superseded`, and `validate.sh --strict` has no blocking errors.
---
## 6. INTEGRATION POINTS
P0 blocks, P1 requires completion or approved deferral, and P2 is optional. Code updates route through `sk-code`; documentation updates route through `sk-doc`; git handoff routes through `sk-git`.
### Quick Reference Commands
| Command | Usage |
| --- | --- |
| Canonical intake | `/speckit:plan --intake-only "Description"` |
| Create spec folder | `./runtime/cli/spec/create.sh "Description" --short-name name --level 2` |
| Create in a track | Add `--track <track>` to the create command. The new packet is also listed in `specs/<track>/graph-metadata.json` |
| Track-root lists | `node .skilled/skills/system-spec-kit/runtime/cli/spec/refresh-track-roots.mjs --apply` after moving, renaming or deleting a packet in a track by hand; `archive.sh` refreshes it itself. The pre-push hook blocks a commit whose track lists other packets than it holds |
| Validate | `.skilled/skills/system-spec-kit/runtime/cli/spec/validate.sh specs/007-feature/` |
| Verify code alignment drift | `python3 .skilled/skills/sk-code/sk-code-opencode/assets/scripts/verify_alignment_drift.py --root .skilled/skills/system-spec-kit` |
| Save context | `node .skilled/skills/system-spec-kit/runtime/cli/dist/continuity/generate-context.js /tmp/save-context-data-<session-id>.json specs/007-feature/` |
| Gate 1 trigger lookup | `node .skilled/skills/system-spec-kit/runtime/cli/retrieval/lookup-trigger-index.mjs --json -- "<prompt>"` (exit `0` hit, `1` no-hit, `2` broken) |
| Regenerate trigger index | `node .skilled/skills/system-spec-kit/runtime/cli/retrieval/generate-trigger-index.mjs` |
| Free-text retrieval | The ripgrep recipes in `references/retrieval/retrieval-conventions.md` §2, scoped by the trailing positional path |
| Compaction recall census | `node .skilled/skills/system-spec-kit/runtime/scripts/compaction-recall/score-compaction-recall.mjs --transcripts <dir> --newest-compacted 15 --out <file outside the repo>` makes no model call, prints counts and one `stop:` line and changes no transcript |
| Alignment suggestion measurement | `cd .skilled/skills/system-spec-kit/runtime/cli && npx tsx evals/score-alignment-suggestion.ts` makes no model call and prints below-50 alignment counts per save path; `--score <rows>` prints `stop: fewer than 30 labeled rows` until the operator labels 30, and `--jev` or `--deem` with `--out <dir outside the repo>` add a verdict column behind that backend's own check |
| Completion claim audit | `node .skilled/skills/system-spec-kit/runtime/scripts/completion-claim-audit/score-completion-claims.mjs --rows <file>` runs the offline completion-claim audit and makes no model call by default, and `--deem` and `--jev` with `--out <dir outside the repo>` each run that backend's arm behind that backend's own check (`--accept-payload` is required for `--jev`) |
| Debug next-check measurement | `node .skilled/skills/system-spec-kit/runtime/scripts/debug-next-check/score-debug-next-check.mjs --fixture <file outside the repo>` makes no model call by default and changes no debug step, and `--jev` or `--deem` with `--out <dir>` each run that backend's arm behind that backend's own check |
| Next spec number | `ls -d specs/[0-9]*/ \| sed 's/.*\/\([0-9]*\)-.*/\1/' \| sort -n \| tail -1` |
| Upgrade level | `bash .skilled/skills/system-spec-kit/runtime/cli/spec/upgrade-level.sh specs/007-feature/ --to 2` |
| Completeness | `.skilled/skills/system-spec-kit/runtime/cli/spec/calculate-completeness.sh specs/007-feature/` |
| Worktree isolation | `.skilled/bin/worktree-session.sh` creates a per-session git worktree with isolated `SPEC_KIT_DB_DIR` / `SPECKIT_IPC_SOCKET_DIR`. Pair with `worktree-reaper.sh` for teardown and `worktree-guard.sh` for lock enforcement |
| Session cleanup | `.skilled/scripts/session-cleanup.sh` resolves PIDs across claude/opencode/opencode runtimes |
Canonical command lifecycle: `/speckit:plan --intake-only` establishes or repairs the packet when standalone intake is needed, `/deep:research` follows `../system-deep-loop/deep-research/references/protocol/spec-check-protocol.md` when research needs bounded `spec.md` anchoring, and `/speckit:plan` or `/speckit:complete` continue from the same folder while reusing the shared intake contract (`.skilled/skills/system-spec-kit/references/workflows/intake-contract.md`) only when the local `folder_state` still needs repair. When intake runs, the returned `start_state` is the canonical downstream field.
**Remember**: This skill is the foundational documentation orchestrator. It enforces structure, template usage, context preservation, and workflow-required validation for all file modifications. Every conversation that modifies files MUST have a spec folder.
---
## 7. REFERENCES AND RELATED RESOURCES
The router discovers reference, asset, and script docs dynamically. Start with `references/workflows/quick-reference.md`, `references/templates/template-guide.md`, `references/validation/validation-rules.md`, `references/retrieval/retrieval-conventions.md`, `references/structure/grep-convention.md`, `references/memory/save-workflow.md`, then load task-specific resources from `references/`, templates from `assets/`, and automation from `runtime/cli/` when present.
Scripts: `runtime/cli/spec/validate.sh`, `runtime/cli/spec/create.sh`, `runtime/cli/dist/continuity/generate-context.js`, `runtime/cli/spec/check-completion.sh`.
Related skills: `sk-doc` for authored documentation quality, `sk-code` for code changes, `sk-git` for git handoff, and `system-deep-loop` for iterative research and audit (its `research` and `review` modes).