From st4ck
Author a Product Requirements Document from an existing codebase, code export, or unpacked low-code project — by reading source rather than asking the user. Use when the user wants a PRD generated from imported elements, exported builders (Bubble, Webflow, Retool), screen recordings, or any "code-first" reverse-engineering of intent. Self-contained — bundles its foundational PRD-authoring rules so it works with or without a server connection.
How this skill is triggered — by the user, by Claude, or both
Slash command
/st4ck:prd-from-sourceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Announce at start:** "I'm using the prd-from-source skill — authoring a PRD by reading the codebase rather than asking the user."
Announce at start: "I'm using the prd-from-source skill — authoring a PRD by reading the codebase rather than asking the user."
A PRD authoring skill grounded in the spec-driven development consensus (GitHub Spec Kit, AWS Kiro, Reversa, OpenSpec, AGENTS.md). PRDs authored here are: read-by-source, not asked-of-humans; three-audience (non-technical stakeholders, QA, devs); file-based Markdown + YAML frontmatter, one node per file; machine-parseable with stable IDs and confidence markers; verifiable (every claim cites its source).
DO NOT use when designing a new feature from scratch — use a requirements/discovery skill instead.
Every PRD node MUST pass this: could a developer who has never seen this application implement exactly this feature from your description alone — no source code, no PO, no designer? Anything they'd need to guess = a question they cannot answer; a vague description = a feature they will build wrong.
Hierarchy, target depth 4–5 levels:
root → module → screen / entity / user_flow / backend_flow / business_rule / integration
→ component / field / logic / validation / endpoint / error_state / element / button
| Parent type | Required children |
|---|---|
| Screen | One component per distinct UI section (header, form, table, sidebar, modal). One element per non-obvious interactive element. |
| Entity | One field per non-trivial field — type, constraints, defaults, validation. Skip boilerplate (id, created_at, updated_at, deleted_at). |
| User flow | One logic per major step. One error_state per distinct failure path. |
| Backend flow | One logic per processing stage. One validation per input guard. One endpoint if it exposes an API. |
| Business rule | One validation per distinct condition. One error_state per exception. |
| Integration | One endpoint per call direction (inbound / outbound). |
root, overview, module, subsystem.screen, section, user_flow, backend_flow, entity, business_rule, integration, process.component, element, field, button, logic, validation, error_state, endpoint.calls_endpoint, uses_entity, enforces_rule, triggers_flow, depends_on, related_to, validates_with, redirects_to. Cross-link screens ↔ entities, flows ↔ rules, endpoints ↔ flows.
Product document. What the software DOES, not how it's built:
useAdvisor() hook checks isAdvisor === true and renders AdvisorBanner"Rules: NO function/variable/component/class names or file paths in the body. Name UI fields as the user sees them (the label, not the DB column). Plain-language validation. Quote error messages exactly as the user reads them. Be specific — vague statements fail the Rebuild Test.
(Self-review checklist for declaring a module complete: see § Self-review checklist below.)
The Rebuild Test fails silently when the PRD grounds on the SCHEMA (field exists) instead of the CODE (field is wired). Ori dc31e7ae is the canonical burn: the schema had both Customer.Allowed Produce (positive whitelist) and User.Products Blacklist (negative blacklist); the PRD picked the whitelist because its NAME matched the described feature — but only the blacklist is wired into any code path. The whitelist is dead schema. A test was then authored against the dead carve-out.
A schema field appearing in an export is NOT evidence the feature is built. Before a node describes a feature backed by entity fields:
product_library_list_custom_product_library, NOT the display name "Products Blacklist" — display names lie, keys are stable) across Reusable Elements/, Pages/, Backend Workflows/. Count writers (ChangeThing / Save / Auto-bind) and readers (Data Source filters, Conditional States, dynamic expressions, Display text).KNOWN GAPS / dead schema bullet; never describe it as a feature.<field> but no active code references it — intent, not shipped behavior." Never describe dead schema as if it were shipped.This is GREP-THEN-WALK at field granularity: grep finds candidates; the walk tells you which one is real. (Same discipline the prd-review reviewer must attest — see that skill.)
verification_status frontmatter (every business_rule / backend_flow / user_flow node)shipped — cited workflow(s) have actions, are not Disabled, AND have ≥1 caller (Button Clicked / TriggerCustomEvent / ScheduleAPIEvent / DatabaseTriggerEvent).aspirational — workflow/field exists but has 0 callers OR is Disabled OR has 0 active field refs. Documented intent, no active path.partial — some cited paths alive, others dead-stub.Derive it from the same caller-walk. Test authors gate on this: NEVER author a test against an aspirational rule without first building the missing product code.
PRDs document features in isolation; test authors need "if I mutate X, what reads it / what cascade fires?":
Trigger | Fire condition | Cascade output | Downstream impact. DB triggers are the #1 most-missed surface (invisible from the UI).DisplayGroupData / ToggleElement) WITH each caller's Conditional State (the gate is on the opening BUTTON, not the popup). Test authors then pick the entry point matching their preconditions instead of hitting an unknown gate.test_knowledge hits for the file.(Server-side precompute of the writer/reader/caller graph during export parsing is a deferred optimization; until it lands, do the greps yourself with the code-search MCP tools — you already have them.)
A PRD without an anchor produces garbled assumptions from raw code reading. Four checks before opening the first source file. 5 minutes total; saves hours of misinterpretation.
If connected to st4ck (orchestrator has mcp__st4ck-pm__* or mcp__st4ck-dev__*):
get_project_users() # lists project_users / user types with roles, permissions, descriptions
get_project_briefing() # one-liner about the app + recent versions
Non-empty taxonomy → use as the role anchor for the whole PRD. Every user_role_ids:, every state-machine role binding, every privacy rule cites these by name. Don't reinvent IDs from option-sets; reconcile both. Empty / no st4ck → 0.2.
Higher frame before role taxonomy: what kind of app is this, who's it for, how does it differ from generic SaaS? These decide rigor for the whole PRD.
Business-specific + single tenant + single language → PRD can skip i18n testing, translation completeness, public-sign-up SLA, multi-tenant security as "attacker defense" (still test isolation, but accepted-as-design rather than threat-modeled). Edge cases that "wouldn't happen with these users" can be marked accepted operational behavior. SaaS + multi-tenant + multi-language → all of the above MATTER. Cross-tenant isolation is defense-against-strangers. Translation completeness gates release. Edge cases are paying customers — same finding is a real bug.
Existing artifacts usually richer than code: old PRDs, design docs, wireframes, diagrams; Slack/meeting decisions; customer-facing help pages (often most accurate); existing spec/ADR docs. Ask explicitly: "Do you have any other documentation you'd like to use as input for this PRD pass?" — users forget they have these. Treat extras as hints, not source of truth (code still wins per Iron Rule #1).
DO NOT ping nine times. Send all of 0.2 + 0.3 + 0.4 in a single message — 60-second answer for the user, and the orchestrator's rigor framing comes from these. Biggest Phase 0 anti-pattern: making the user feel a long discussion is starting. It isn't.
Short anchor block in PRD root _index.md BEFORE authoring modules: app in one sentence + type + audience + deployment + language posture; role taxonomy; primary lifecycle; key-entity list; source shape; additional input docs; "PRD rigor frame" — what gets tested rigorously, what gets accepted as operational/informal, what's out of scope (derived from 0.2).
Pass 1 (mechanical scaffold) and Pass 2 (curated intent) follow.
A product question the running code answers is not a question — it is a fact waiting to be read. Default move for an apparent clarification:
.meta.json, AST dump, raw export blob) for operators or attributes the human-readable summary stripped (list operators like add/remove, condition values referencing internal codes).*_get_schema, *_describe_table, *_query).[NEEDS CLARIFICATION] — for genuinely-unanswerable-from-code things only (untranslated copy, design intent for an empty state, business decisions on un-built features).When code shows something is never called, never set, never reached: state it plainly. DO NOT soften "dead code" to "might be unused" or "needs verification". The grep result IS the verification. Confident findings can be reviewed and corrected; hedged findings cannot be acted on.
See EXAMPLES.md § "Dead-code phrasing table" for the canonical phrasings.
Three confidence markers (Reversa-inspired):
[CONFIRMED: <src>] — directly observable in cited source. Default.[INFERRED: <src>] — reasonable read involving judgment (e.g., interpreting an option-set's intended meaning from workflow usage when the option set itself is opaque).[GAP] — source silent/ambiguous. Used sparingly with a concrete question for the next pass.Source paths go in frontmatter source: list. Inline [src: <path>] for specific disputed claims.
Persistent memory (prior conversation notes, auto-memory, briefings): treat as hint about where to look, not ground truth. Verify every claim against current code. Memory may be from failed prior attempts. Memory naming an identifier (function, table, status) — confirm it still exists.
Dispatching a subagent (Explore, Plan, research) to read code: require citation of specific file paths (and line numbers) for every non-trivial claim. Subagent returning "the page has 11 tabs" without citing the files = un-auditable; treat as hint. Spot-check at least one claim per subagent return. If it holds, the rest is probably OK; if not, demand attestation for everything.
Good dispatch prompt always includes: "For each claim, cite the specific file path under the source root where you read it. If you cannot cite a file, mark [INFERRED] or [GAP]. Do NOT blend confirmed and inferred claims as the same."
This is the single biggest mitigation against subagent hallucinations.
Pass 1 — mechanical scaffold. One PRD node per first-class artifact with 2–3 sentence overview: one entity per data type / table; one screen per page / route; one backend flow per server-side workflow / function / handler; one option-set / enum captured as a referenced concept. Fast, complete, flat re-encoding. Low test signal on its own — but it's the skeleton.
Pass 2 — curated intent. Walk same artifacts; add what source does NOT encode: user flows traversing multiple screens/handlers; business rules from condition expressions, status state machines, privacy/auth gates; cross-links screens ↔ entities, flows ↔ rules, rules ↔ entities; role bindings (user_role_ids) where role matters. Pass 2 is where PRD becomes useful for test authoring.
Author as Markdown under <project>/<path>/docs/prd/. One MD file per node. A future importer walks the tree and calls DB writes. Folder layout, frontmatter schema, content rules, stable-ID conventions, cross-module reuse pattern: see EXAMPLES.md § "File-based authoring shape".
Every node readable by all three: Non-technical stakeholder (plain English / native UI language; body prose; UI labels with translation glosses; observable behavior). QA engineer (test preconditions, success states, error paths; "Test implications" section on every leaf; state machines with explicit transitions + side effects). Developer (source provenance for ground-truth verification; decomposition deep enough to anchor tests on specific UI surfaces; source: frontmatter; tree depth 3–5 levels; cross-links).
Per leaf: could a stranger (no source code, no PO, no designer) implement exactly this piece from this node alone? Anything they'd need to guess = incomplete. Industry equivalent: "Rebuild Test", "completeness check", "self-sufficiency test".
Many low-code exports = .md body for humans + .meta.json (or similar) sidecar for raw builder data. Always check both. Some critical facts live ONLY in the sidecar (list operators add/remove/set; conditional bindings to roles/option-sets; obfuscated db_value/IDs). When a sidecar exists, treat MD as "the index" and JSON as "the truth". Disagreement → JSON wins.
Common export quirks + the internal-code anti-pattern: see EXAMPLES.md § "Export quirks" + § "Internal-code anti-pattern".
Per the AGENTS.md convention, a project with a PRD should also have project-root AGENTS.md. AGENTS.md and the PRD have non-overlapping purposes:
| Belongs in AGENTS.md | Belongs in the PRD |
|---|---|
| Where files live | What the product does |
| Build / test / run commands | Entities, flows, business rules |
| Code conventions, naming, style | State machines |
| Always / Ask first / Never operational tiers | Security findings, dead code |
| Which MCP tools / skills are wired up | Stakeholder questions |
| A pointer to the PRD root | Cross-tenant isolation rules |
Rule: product running = PRD. How to work in this repo as an agent = AGENTS.md.
Why this matters: AGENTS.md has no update mechanism tied to product changes. Workflow behavior changes → PRD update is part of the change; AGENTS.md sits next to repo root and tends to rot. Never let AGENTS.md own product knowledge in the first place. A good AGENTS.md after a PRD pass is ~50–100 lines. Longer = bleeding PRD content into a file with no update mechanism.
*_get_schema, *_list_records, *_describe_table, *_query — preferred over re-deriving schema from an export. Use them to resolve any export ambiguity (obfuscated values, "is this field still used", row counts). Export → PRD is a translation; translations drop information. Live data is the closest thing to source of truth.
[NEEDS CLARIFICATION] for things code answers.source: path points at files that exist.7a03ce10). Multi-candidate features code-walked the internal field key, not name-matched.verification_status (shipped / aspirational / partial).____________".dc31e7ae dead-schema trap, st4ck 7a03ce10). The field existing in the export is not the feature being built.aspirational.get_project_users if connected; else ask user for role taxonomy + app anchor. Ask about other documentation. Write anchor block to PRD root.00_shared/.prd-review skill for the four-phase review pipeline.AGENTS.md — operational steering only.PRD (this skill) = intent + behavior (what / for whom / why). Spec = precise contract for how it's built (derived from a PRD requirement). ADR = why we chose this approach (standalone, cross-cutting). Plan / Tasks = sequenced steps to implement (derived from a spec). A PRD-from-source pass on a long-running system may also produce ADRs for decisions visible in code — surface as a candidate, don't bury inside a node.
Spec-driven-development consensus (2026): GitHub Spec Kit, AGENTS.md, Addy Osmani's "How to write a good spec for AI agents", AWS Kiro, Reversa, SpecFact code2spec, OpenSpec spec-gen, EARS notation, Karpathy's vibe-to-agentic, Aakash Gupta's PRDs Modern Guide, David Haberlah's PRDs for AI Coding Agents.
npx claudepluginhub edo-ceder/st4ck-plugin --plugin st4ckCreates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.