Install
$ agentstack add skill-yongwoon-ywc-agent-toolkit-ywc-spec-writer ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
ywc-spec-writer
Announce at start: "I'm using the ywc-spec-writer skill to create or update the project specification in docs/specification/."
Writes and maintains the docs/specification/ directory. Produces human-readable markdown describing the project's goals, features, data model, user flows, and non-functional requirements — with no program code. Intended audience: developers and non-developers alike. Supports Korean, Japanese, English, Chinese, and Spanish output.
Rationalization Defense
When tempted to bypass a rule, check this table first:
| Excuse | Reality | |---|---| | "This is a minor change — I'll update inline without reading existing spec files" | Always read existing spec files before writing. Editing without reading overwrites valid content silently. | | "A code snippet would make this feature clearer" | Zero program code in any spec output. Non-developer audience cannot parse code. Use user stories and flow descriptions instead. | | "User seems to want a full spec — I'll generate it without --full to save time" | Full generation requires the explicit --full flag AND user confirmation. Never auto-generate the full spec from an incremental run. | | "The commit changed several files — I'll update the entire spec to be safe" | Update only sections mapped to the changed domain. Use scripts/detect-affected-sections.sh to determine scope precisely. | | "Language not specified — I'll default to English" | Default is Korean (ko) unless the project's CLAUDE.md or --lang flag says otherwise. | | "--setup-hook is optional — I'll just describe the hook approach" | --setup-hook must produce a working script at tools/scripts/spec-update-hook.sh and install it. Documentation alone does not fulfill the step. | | "Multiple PRs share files — I'll skip deduplication" | Always dedupe the union file list before invoking section detection. Without dedup, the same diff is fed to the LLM multiple times and bloats context. | | "Open PR diff will change soon — recording the HEAD SHA in README index is unnecessary" | Always record headRefOid (and PR numbers) in the README index entry. Without it, a future reader cannot reproduce or audit which PR snapshot drove the update. | | "The task range or PR set touched >4 sections — I'll patch them all anyway" | Stop and propose --update (Full Refresh) explicitly. Spec changes at that scope are coherent only when written holistically; patching pieces creates internal drift. | | "Range spans phase boundary — I'll silently combine them" | Phase boundaries are hard gates in ywc-task-generator. When a range crosses phases, the README index entry must list every resolved task ID so the audit trail survives. | | "Spec is for business stakeholders, so keeping NFR numbers vague is fine" | Spec must be dual-audience: readable by business stakeholders AND decomposable by ywc-task-generator. NFR with placeholder values like "数秒以内" / "X seconds" fail downstream ywc-spec-validate and force a Re-plan iteration. Always extract concrete numbers from *.constants.ts, *config*.ts, migrations, or record them under Open Questions with rationale. | | "Project has many models — I'll lump them into category groups" | Every model in prisma/schema.prisma (or equivalent ORM/DB schema) MUST appear by name in 03-data.md. Lumping ≥3 sibling entities is permitted only as a ### heading with an explicit inline list of all member names. Silent omission produces Code Compatibility Critical findings downstream. | | "Token-efficiency rule says 'no open-ended exploration' — constants files are off-limits" | The "no open-ended exploration" rule has explicit exceptions documented in [references/full-gen-workflow.md](references/full-gen-workflow.md) §Exceptions: constants files, primary schema, feature directory listings, and auth guard / middleware definitions. These supply the concrete numbers and enumeration boundaries that ywc-spec-validate checks for. Skipping them produces vague NFRs and lumped entities. | | "UL is for code-level naming, spec uses business language so it's OK" | docs/ubiquitous-language.md is the canonical vocabulary for the entire project, not just code. Synonyms-to-Avoid violations (e.g., using "Tenant Admin" when UL canonical is "Admin" with "Tenant Admin" listed as a synonym to avoid) propagate through every downstream artifact: tasks generated by ywc-task-generator, code authored by ywc-backend-coder / ywc-frontend-coder, and PR titles created by ywc-create-pr. Skipping the UL cross-check at spec-write time turns a 5-minute grep into a multi-PR rename refactor downstream. Always run the avoid-list extraction grep before drafting 01-overview.md. | | "Inline backticks are not code blocks, so a Prisma snippet in them is OK" | Inline backticks containing executable syntax (@default(...), dbgenerated(...), WHERE x = $1, decorators) are exactly the case ywc-spec-validate flags as a Code Compatibility Warning — the spec then drifts when the underlying ORM / SQL changes. Field-reference identifiers (tenantId, BeaconSite.samplingState) are fine; expressions are not. The mechanical test: "if I copy this backtick content into a .prisma / .sql file, would it parse?" If yes, paraphrase into plain prose. | | "Intent is clear enough — start writing without an up-front scope check" | Estimating the affected-section count and surfacing any irreversible-choice ambiguity before writing prevents a mid-write switch to --update and prevents silently deciding an ambiguous design point. Run the Step 1.5 pre-check; record undecided points under ## Open Questions, never resolve them yourself — a spec writer transcribes decided intent, it does not decide it. |
Violating the letter of these rules is violating the spirit. A spec containing code, written in the wrong language, or auto-generated without explicit intent does not serve its readers. A spec that cannot pass ywc-spec-validate at the REVIEW band (Gate ≥ 70) does not serve its pipeline — fix the gaps at write time, not at validate time.
Arguments
| Parameter | Format | Example | Description | |-----------|--------|---------|-------------| | --full | flag | --full | Generate complete spec from scratch. Requires user confirmation. Uses best available model. | | --update | flag | --update | Regenerate all existing spec sections. | | --from-task | --from-task | --from-task tasks/000002-010-api-user/ | Update spec from a single ywc-task-generator task directory. | | --from-tasks | --from-tasks [ ...] | --from-tasks 000002-010..000003-020 | Update spec from a range, glob, or multi-id set of task directories. Patterns: single ID prefix, START..END range, shell glob, or multi-value list. Active and completed tasks both resolve. | | --from-commit | --from-commit | --from-commit HEAD | Update spec based on diff of a specific commit. | | --from-pr | --from-pr | --from-pr 42 | Update spec from a single pull request's diff. Requires gh CLI auth. | | --from-prs | --from-prs [ ...] | --from-prs 42 43 51 | Update spec from the union diff of multiple PRs. Each PR fetched via gh pr diff; duplicate files are coalesced. | | --setup-hook | flag | --setup-hook | Install git hook for automatic spec-update tracking. | | --lang | --lang ko\|ja\|en\|zh\|es | --lang ja | Output language. Default: ko. |
Workflow
Step 1: Determine Mode
| Mode | Trigger | Notes | |------|---------|-------| | Full Generation | --full | Requires user confirmation. Uses best model. | | Full Refresh | --update | Regenerates all existing sections. | | Task-based Update | --from-task | Maps a single task's category to affected sections. | | Task Range Update | --from-tasks ... | Resolves IDs / ranges / globs via scripts/resolve-task-paths.sh; unions each task's category mapping. | | Commit-based Update | --from-commit | Analyzes git diff to determine affected sections. | | PR-based Update | --from-pr / --from-prs ... | Fetches changed files via scripts/collect-files-from-prs.sh (gh CLI); unions across PRs; uses PR title + body as narrative context. | | Auto | No flags | Reads last commit diff; runs commit-based update. |
Step 1.5: Scope & Intent Pre-Check
Before collecting context and writing, right-size the run and confirm intent. This is the "Right Job, Right Tool" gate for spec writing — it surfaces the routing decision up front instead of discovering it mid-write.
- Estimate scope early. For incremental modes, roughly estimate the affected-section count from the task/PR/commit before doing the precise detection in Step 5. If it is likely to exceed the Step 5 safety threshold (>4 sections), propose
--update(Full Refresh) now rather than after partial writing. For--full/--update, note the project's entity and feature scale so the per-section size cap (see Step 6) is applied from the start. - Confirm intent on irreversible choices. If the source (task / PR / commit / design note) admits two readings that change the spec's meaning — especially on an irreversible choice (data ownership, sync vs. async boundary, API versioning) — surface it as one clarifying question OR record both readings under
## Open Questions. Never silently pick one; the spec writer transcribes decided intent, it does not decide it.
Step 2: Collect Context
Always read before writing:
docs/specification/README.md— current spec state (if exists)CLAUDE.md— language policy, domain conventionsdocs/ubiquitous-language.md(if exists) — canonical terms; use these verbatim in spec text
For --full and --update only, also read:
- Project directory structure (top 2 levels of
src/,app/, or equivalent) docs/ywc-plans/— existing feature plans- Key structural files: schema, API route index, main domain directories
Step 3: Language Setup
If --lang is not specified, resolve the output language via the shared resolution reference.
> Action required: Read [../references/language-resolution.md] — it defines the precedence chain (--lang flag → project CLAUDE.md ## Language Policy → user ~/.claude/CLAUDE.md ## Language Policy → this skill's existing fallback), so the user-global CLAUDE.md is checked and project-over-user precedence is honored.
This skill's terminal fallback is unchanged (AC10): when no canonical ## Language Policy is configured, honor a project CLAUDE.md's declared primary documentation language if present, otherwise default to Korean (ko). Ask the user only when they explicitly ask to choose a language or the project guidance conflicts.
> "사양서를 어떤 언어로 작성할까요? / Which language should the spec be written in? / 仕様書をどの言語で作成しますか?" > 1. 한국어 (ko) — 기본값 > 2. English (en) > 3. 日本語 (ja) > 4. 中文 (zh) > 5. Español (es)
When asking, wait for the user's answer before proceeding.
For locale-specific writing rules (formality level, term policy), see [references/language-policy.md](references/language-policy.md).
Step 4: Prepare Spec Directory
If docs/specification/ does not exist, run:
bash claude-code/skills/ywc-spec-writer/scripts/init-spec-structure.sh ""
Pass the language code resolved in Step 3 as the `` first positional argument so the scaffolded skeleton is created in the resolved language, not just the document bodies (Amendment A4). This creates the 7-section skeleton without any LLM calls. For the full section layout and writing templates, see [references/spec-structure.md](references/spec-structure.md).
Step 5: Determine Affected Sections
For incremental modes, identify which spec sections need updating before writing. Run the appropriate branch then union every detected section across sources.
Commit-based
git diff ^.. --name-only \
| bash claude-code/skills/ywc-spec-writer/scripts/detect-affected-sections.sh
Task-based (single task) — read the task README.md for its category field and apply the mapping in [references/section-mapping.md](references/section-mapping.md).
Task Range / Multi-task — resolve task IDs, then read each task's README.md for its category field:
# Resolve range / glob / multi-id to absolute task directory paths
bash claude-code/skills/ywc-spec-writer/scripts/resolve-task-paths.sh \
000002-010..000003-020
# For each resolved path: read README.md → category → look up in section-mapping.md
# Then UNION every resulting section list.
PR-based (single or multiple PRs) — fetch the changed-file union, then feed it into detect-affected-sections.sh:
bash claude-code/skills/ywc-spec-writer/scripts/collect-files-from-prs.sh 42 43 51 \
| bash claude-code/skills/ywc-spec-writer/scripts/detect-affected-sections.sh
Additionally, for --from-pr / --from-prs, fetch each PR's title + body as narrative context:
gh pr view --json number,title,body,headRefOid
Use the PR's title + body to inform spec wording (the "why") and record headRefOid in the README change log entry for reproducibility.
Safety threshold — if the unioned section count exceeds 4, stop and propose --update (Full Refresh) to the user. Patching that many sections piecemeal produces internal drift; see [references/section-mapping.md](references/section-mapping.md) §"When Many Sections Are Affected".
Step 6: Write or Update Spec Content
Non-negotiable writing rules for all modes:
- Zero program code in any spec output
- When the source (task / PR / commit / design note) admits two readings that change the spec's meaning, record both under
## Open Questionsrather than silently picking one. A spec writer transcribes decided intent; it does not decide it. The silent pick is invisible until implementation contradicts the spec. - Write for a dual audience: business stakeholder (must be readable without engineering knowledge) AND
ywc-task-generator(must be decomposable into concrete tasks). Vague prose serves neither — concrete numbers serve both. - Features use the user story format: "As a [user], I want [action] so that [benefit]"
- Data and flows use plain-language descriptions
- Section file size cap, scaled to project size:
- Default: ≤ 400 lines per section file
- When project has >50 entities (Prisma models / equivalent ORM models) OR >20 features (top-level feature directories): cap raises to ≤ 800 lines per section file
03-data.mdmay exceed the section cap by up to 30 lines per entity beyond 50 entities (e.g., 82 entities → cap = 400 + 30×32 = 1,360 lines), so enumeration is not artificially blocked by the cap
Additional non-negotiable rules for --full and --update modes (these modes claim to produce a complete spec, so they bear the full burden):
- Every NFR in
06-requirements.mdMUST include ≥1 quantitative target (latency, throughput, retention period, concurrency, etc.). If the project does not yet have a target, list it under an## Open Questionssection with the reason, do NOT leave it as a placeholder like "X seconds" or vague prose like "数秒以内". - Every model in the project's primary schema (
prisma/schema.prisma,*/migrations/*.sql,*/models/, or*/entities/) MUST appear by name in03-data.md. Sibling entities sharing a prefix MAY be grouped under one###heading, but each member name MUST appear in the inline list under that heading. - When the project has ≥3 distinct actor roles (Operator/Admin/Owner/etc.),
02-features.mdor06-requirements.mdMUST include a Role × Action matrix. - When the project has long-lived high-volume data (audit logs, time-series analytics, event streams),
06-requirements.mdMUST include a Data Lifecycle subsection covering retention period per entity, sampling strategy, and aggregation timing. - Constants and config files (
*.constants.ts,*config*.ts, `*.confi
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: yongwoon
- Source: yongwoon/ywc-agent-toolkit
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.