Help us improve
Share bugs, ideas, or general feedback.
From harness-claude
Critiques spec quality (proposals + ADRs) against a curated rubric catalog. Use during PR review, after authoring a proposal, or periodically to catch spec drift.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeHow this skill is triggered — by the user, by Claude, or both
Slash command
/harness-claude:spec-craftThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> LLM-judgment critique of spec quality (proposals + ADRs) against a curated rubric catalog from the spec-quality canon. Per-section critique with rubric-to-section mapping. Second member of the craft-pipeline initiative; highest-leverage craft skill because spec quality compounds across the entire planning → implementation → review lifecycle below it. Emits 3-axis findings (tier × impact × con...
Reviews spec.md files for completeness, clarity, implementability, testability, and structure. Identifies ambiguities, gaps, and missing sections before implementation.
Reviews PRDs and specs for completeness, ambiguities, edge cases, acceptance criteria quality. Structures findings by severity and offers direct fixes.
Reviews specs, PRDs, requirements, and design docs for unrelated features, oversized scope, contradictions, feasibility issues, scope imbalance, omissions, ambiguity, security concerns, and git repo conflicts.
Share bugs, ideas, or general feedback.
LLM-judgment critique of spec quality (proposals + ADRs) against a curated rubric catalog from the spec-quality canon. Per-section critique with rubric-to-section mapping. Second member of the craft-pipeline initiative; highest-leverage craft skill because spec quality compounds across the entire planning → implementation → review lifecycle below it. Emits 3-axis findings (tier × impact × confidence per ADR 0019).
harness-soundness-review — that's the rule-based floor)docs-craft #2)align-spec sibling)code-craft #4 or docs-craft #2)Read project configuration. Check harness.config.json for:
craft.spec.enabled — gate (default true)craft.spec.maxFiles — doc count cap (default 50)craft.spec.maxSectionsPerFile — per-doc section cap (default 10)Discover spec files:
docs/changes/*/proposal.md and docs/changes/*/<sub>/proposal.md (one level of nesting, for initiatives with sub-projects)docs/knowledge/decisions/*.md (excluding README)--kinds proposal or --kinds adr for single-kind runs.For each spec file:
--- ... --- block at top, if present).## ...) into named sections. Each section captures:
heading — original H2 text (e.g., "Decisions", "Out-of-scope (v1)")canonical — normalized form for rubric matching ("decisions", "out-of-scope-v1")body — content between this H2 and the nextline / endLine — line range7 seed rubrics:
| Rubric | Title | Applies to |
|---|---|---|
SPEC-R001 | Sharpness vs vagueness | * (all sections) |
SPEC-R002 | Cuts at the joints | decisions, scope, technical-design |
SPEC-R003 | Two readers, same understanding | decisions, success-criteria |
SPEC-R004 | Load-bearing decision vs ambient context | decisions, overview |
SPEC-R005 | Honest rationalizations | rationalizations* (regex) |
SPEC-R006 | Non-goals are non-goals | out-of-scope*, non-goals* (regex) |
SPEC-R007 | Stranger in 6 months | * (all sections) |
For each eligible (section, rubric) pair:
null (rubric doesn't apply / section is fine) OR { tier, impact, confidence, message }.SpecFinding with cite.rubricId populated for ADR 0020 traceability.Emit SpecCraftOutput:
{
findings: SpecFinding[];
summary: {
phaseRun: ['critique'];
durationMs: number;
llmCalls: { provider, model, count, costUsd };
catalog: { rubricsApplied: string[] };
docsScanned: number;
sectionsScanned: number;
runId: string;
}
}
harness spec-craft — CLI entry. --files <glob> / --kinds proposal,adr / --sections decisions,scope / --max-files <n> / --max-sections-per-file <n> / --json / --verbose.mcp__harness__spec_craft — MCP tool. Same input/output. Consumed by agents.critiqueSpecFile(file, opts) exported from packages/cli/src/spec-craft/index.ts. Future craft skills (or harness-brainstorming) can call this when they have a doc in hand without re-walking the project.LlmProvider, MockLlmProvider, derivePriority, 3-axis types all live in packages/cli/src/shared/craft/. design-craft + naming-craft + spec-craft import from there; design-craft + naming-craft keep their old import paths via re-export shims.See docs/changes/craft-pipeline/spec-craft/proposal.md for the full 34 success criteria. Highlights:
catalog/rubrics/<id>.ts (file-per-rubric, matches naming-craft)cite.rubricId populated on every finding (ADR 0020)critiqueSpecFile cross-cutting API works on a single file without project walkInput: A proposal's ## Decisions section reads:
| Decision | Why |
|----------|-----|
| Use modern stack | scalable and clean |
| Defer auth | not in scope |
Output (mock LLM):
SPEC-R001 [polish/medium/medium] ## Decisions:34
"Modern stack" and "scalable and clean" are vague — no concrete framework
named, no metric for "scalable", no operational definition of "clean".
Sharpen: name the framework, state the scale target (req/sec, team size),
define what "clean" means in observable terms.
SPEC-R004 [polish/medium/medium] ## Decisions:34
The Decisions section pads load-bearing choices with vague qualifiers
rather than naming the trade-off chosen and the rejected alternative.
Input: A ## Rationalizations to reject section reads:
| "Use a different framework" | Other frameworks are worse |
Output:
SPEC-R005 [foundational/large/high] ## Rationalizations to reject:88
"Other frameworks are worse" is a strawman — not stated charitably, not
paired with a specific reason. Steelman the rejected position: name the
competing framework, name its strongest feature, then explain the specific
trade-off that made it unsuitable here.
Input: Project has no docs/changes/ or docs/knowledge/decisions/ directory.
Output:
No spec findings.
Summary: 0 findings across 0 docs (0 sections, 7 rubrics, 0 LLM calls, $0.0000, 3ms)
align-spec deferred until signal warrants safe-to-apply rewrites.maxSectionsPerFile to 5 or maxFiles to 25. Per-doc cost = sections × rubrics × per-call. Rubric-to-section mapping already prunes most calls; further: use --sections decisions to target the highest-value section.craft.spec.disabledRubrics: ['SPEC-R007']. Until then: filter findings by cite.rubricId in your consumer.<!-- spec-craft:skip --> HTML comment.--mode doc opt-in for whole-doc critique.--files <rfc.md> at a single file — the section parser works on any markdown.v1 — in implementation. See:
docs/changes/craft-pipeline/spec-craft/proposal.mdcraft-pipeline sub-project #6 (the highest-leverage craft skill)harness-design-craft (design-pipeline #6), naming-craft (craft-pipeline #1)packages/cli/src/shared/craft/ (extracted on this PR)align-spec (FIX side), docs-craft (#2), test-craft (#3), code-craft (#4) — each can call critiqueSpecFile if they want spec-level critique for a doc they're already processing.