easysdd-feature-design
The output of this phase is a design document
, plus an action checklist
extracted from it. These two files will be used in the next two phases — implement phase follows the checklist, acceptance phase verifies against it. So any mistakes or omissions here will lead to errors downstream.
See
easysdd/reference/shared-conventions.md
for shared paths and naming conventions. Generally, the feature directory has already been created by brainstorm; if not, create it in this step.
The design document is for skimming, not for reading word-for-word
The entire writing style of the design revolves around this principle. Readers open
to grasp the key points within 5 minutes, and know where to find details when needed — not to read every word carefully. This principle leads to several specific practices:
- Trim or split any section longer than one screen. If a section can't fit on one screen, readers will lose their sense of orientation.
- Lock down terms first. Run a grep for all new terms before writing, covering code, architecture directory, and design documents of all features. The cost of term conflicts is that others will look in the wrong place when checking code — the cost of prevention is far lower than sorting it out afterwards.
- Examples take precedence over definitions. Describe interface behavior with specific examples first (input→output for APIs, Props→rendering/Events examples for components), then supplement with formal types if complex. Readers build a mental model faster from specific input-output than abstract descriptions.
- Progress by "feature visibility" instead of code file order. Start with the minimal closed loop (an end-to-end working path), then add details. This way, each step can be verified independently, and only one step is lost if a deviation is found along the way.
- New logic goes into new files by default. Create independent files for new cohesive logic units by default, instead of appending to existing files. Mark each item in the change plan as "New file" or "Append to existing file (reason)". The reason is that larger files make it harder to distinguish responsibilities, and adding to old files forces future maintainers to read irrelevant changes when checking git blame.
- Each piece of information appears only once in its most natural position. Repetition makes readers repeatedly confirm "Are these two the same thing?", which is more annoying than missing one.
- Separate process from template. Complete the process below first, then fill in the template content — don't switch between writing and process.
Two judgment rules during drafting
Beyond writing style, there are two more fundamental rules that determine whether this design can truly support implement/acceptance — not just look like a design but full of vague commitments.
1. Don't make decisions for the user; explicitly state uncertainties
When encountering "ambiguous areas not clarified by the user" while writing the design, the default action is to stop and ask, not to pick one and fill it in yourself. Specifically, this applies to several things:
- State assumptions: Every judgment not explicitly stated by the user (input boundaries, error handling, edge cases) should be written as "Assumption: ...", allowing the user to refute precisely.
- Present options instead of choosing: If there are 2-3 reasonable approaches for a point, list all candidates first, then explain your preference, so the user can switch during review.
- Mention simpler alternatives: If the user's direction can achieve the same goal with a lighter approach, explicitly say "There's a simpler approach: ..., should we rule it out first?" Don't stay silent just because the user has given a direction.
- Stop if you don't understand: If you're not sure you've understood the requirement correctly, directly say "I'm not sure about this section" instead of guessing and writing.
The cost is concrete: Decisions made secretly will become "special logic introduced by AI on its own" during implementation, and won't match acceptance criteria in the acceptance phase. Design is the final checkpoint to bring all "things we assume everyone understands" to the surface.
2. Write both goals and constraints in verifiable terms
The output of the design will be followed during implementation and verified during acceptance — so every goal and constraint in the design must be independently verifiable:
- Don't use weak standards like "Make it work". Phrases like "Complete feature X" / "Handle errors properly" / "Smooth user experience" essentially shift the verification responsibility downstream. Rewrite them as "Return B when input is A", "Show prompt Y when error X occurs".
- Every step in the progress sequence has an exit signal. Just writing "Implement XX" is not enough; write "After completion, pass {specific test / operation steps}".
- "Explicitly not doing" must also be verifiable. "Not doing XX" should be specific enough to be checked reversely via grep or tests, not empty phrases like "Avoid over-design".
The check items "Each step is independently verifiable" and "Test design is organized by feature points" in the exit conditions are the implementation of this rule — if these sections are written vaguely, this rule hasn't been implemented.
Process: What to do when
1. Startup check
Go through these items before starting this phase; don't start writing if any are not met:
-
Is this a continuation of previous work — First glob
easysdd/features/{feature}/{slug}-design.md
to see if there's a design document with the same name:
- No → Jump to item 2
- Yes, but it's an empty template or only has frontmatter → Treat as new creation, jump to item 2
- Yes, and all sections are basically complete → Last time you finished writing but didn't get reviewed, directly jump to step "5. Overall review" in this process
- Yes, some sections are missing → Report "The previous design was written up to section X, I'll complete the rest and send it to you for review uniformly", only fill in the missing sections, don't rewrite completed ones
- Yes, → Don't overwrite silently; ask the user whether to continue modifying or create a new slug
-
Is the requirement input clear — Confirm at least four items: user goals, core behavior, success criteria, and explicitly excluded scope. Fill in any missing items; if the user can't clarify, go back to brainstorm.
-
Read prerequisite materials — Before writing, you must read
, the project architecture entry point, architecture index, existing code related to the requirement, and subsystem architecture docs. This step ensures your design connects with existing code; writing without reading will likely result in a design that's disconnected from reality.
-
Archive search — Whether it's worth searching and which directories to prioritize are specified in section 5 of
easysdd/reference/shared-conventions.md
. At least consider these two directories in this phase:
- Precipitation directory (search once uniformly, filter by as needed):
- Full search:
python easysdd/tools/search-yaml.py --dir easysdd/compound --query "{关键词}"
- Only view decisions: Append
--filter doc_type=decision --filter status=active
- Only view tricks: Append
--filter doc_type=trick --filter status=active
- Only view learnings: Append
--filter doc_type=learning
- Only view explorations: Append
--filter doc_type=explore
- Existing feature designs:
python easysdd/tools/search-yaml.py --dir easysdd/features --filter doc_type=feature-design --query "{关键词}"
Prioritize reuse when hits are found, and record the reference source in the design document — this way, future maintainers can trace back through the references.
2. Figure out where this feature should fit
Before writing the change plan, first think about a more fundamental question: Where does the thing we're adding fit in the overall project structure?
Specifically, ask these questions:
- Is this something an existing module should be responsible for? If yes, extend that module instead of creating a new one outside.
- Does this span multiple modules — should we extract a common layer in the middle, or let one party lead and others depend on it?
- Does this not fit any existing module? Then we may need to create a new independent module/subsystem — we must clarify in advance where to place the new module, what it exposes externally, and how it interacts with others.
- Is there already a module doing similar things but with a different name that you didn't notice? Grep the project to avoid reinventing the wheel due to different naming.
The cost of wrong placement is concrete: Putting it in a module that shouldn't be responsible for it will make that module gradually become a "catch-all basket" with increasingly blurred responsibilities; creating parallel implementations every time will result in multiple versions of the same thing coexisting in the project, forcing future maintainers to guess which one to use.
Write the conclusion in section 1 "Decisions and Constraints" of the design document — at least explicitly state "This feature is placed in {module/layer} because {brief reason}". When involving new modules or cross-module interfaces, simultaneously write it in section 4 "Relationship with project-level architecture documents", and prompt to add a link in the architecture entry point
.
The default mistake AI makes in this step is adding to the most convenient file in front without thinking — skipping this step and going directly to step 3 will lead to this mistake.
3. Check the current state of the files to be modified
After figuring out which module to place it in step 2, dive deeper to check the current state of the file (or class) before writing the change plan — can it cleanly accept the new code?
Check several dimensions:
- How long is this file now? How many responsibilities does it take on? Is the new content an extension of existing responsibilities, or the N+1th thing?
- How many methods does this class have? Is the new method a natural extension of the same responsibility, or does it push the class towards "can do everything"?
- For frontend-related work, also check if the component tree hierarchy is too deep and if state ownership is clear (local state / props passing / global store).
Handle based on severity:
| Situation | Handling |
|---|
| Healthy state, can add directly | Proceed normally, no additional actions |
| Needs cleanup first (split an overly long file into several, extract an overly heavy function) | Include as step 1 in the progress sequence subsection of section 3 "Implementation Tips", lock the scope to "Move only, no behavior changes", exit signal is "Existing functions remain unchanged after moving" |
| Structural issues (responsibility needs to be redefined, modules need to be split/merged, interfaces need to be redesigned) | Record as prerequisite dependency in section 1, suggest splitting into an independent feature to solve first; suspend the current feature or mark "Proceed after prerequisite is completed" |
Why do this step? Forcing features into an already messy file results in an even messier file, making the next change harder. Bring "Should we clean up first" to the surface in advance and let the user decide, instead of AI secretly including it in a PR.
Write the conclusion at the beginning of the change plan subsection in section 3 "Implementation Tips" (specific format see
in the same directory). No need to write for "Healthy, add directly" — only record when there are actions.
4. Complete the remaining sections, submit the full draft for review at once
Step 2 and 3 have already written the key conclusions for section 1 "Decisions and Constraints" and section 3 "Implementation Tips" into the file. In this step, complete the remaining sections (sections 0/2/4, and parts of sections 1/3 not covered in steps 2/3) according to the template below,
submit the complete draft to the user for review only after it's fully formed, don't let the user review semi-finished products in batches. Set
to
in the YAML frontmatter of the first draft.
Note that "at once" refers to the number of review requests sent to the user, not the number of times you write the file — the file itself can be written in several rounds, but only sent out after it's fully complete.
Why not review in batches? The problem with batches is that the user only sees parts each time and can't spot cross-section issues like "The scope in section 1 doesn't match the progress steps in section 3". Only when the complete first draft is presented can the user check global consistency.
5. Overall review
Send one overall review prompt to the user. If the user raises modification suggestions for any part, revise according to the suggestions and confirm again, repeating until the user explicitly says "The design is okay". After the user approves, change
from
to
in the frontmatter.
6. Generate {slug}-checklist.yaml
After the design is confirmed, extract the action checklist from
and save it as
in the same directory. See
easysdd/reference/shared-conventions.md
for the lifecycle of this checklist: This phase is responsible for generating it, implement phase only advances
, acceptance phase only verifies
. Each of the three phases manages its own part without crossing boundaries — this way, each phase can see its work progress from the yaml.
The complete templates, frontmatter examples, section anchors, and extraction format for
and
are in
in the same directory. This skill only retains the extraction principles:
- : Extract step by step from the progress sequence subsection of section 3 "Implementation Tips", one step per entry
- : Extract comprehensively from these places —
- Each item in section 1 "Explicitly excluded scope" → Scope guard check items
- Key interface contracts in section 2 → Interface consistency check items
- Each test constraint in the test design subsection of section 3 "Implementation Tips" → Test verification check items
After saving, validate the syntax with
validate-yaml.py --file {slug-checklist.yaml path} --yaml-only
.
7. Exit
After checking all items in the exit condition list below, guide the user to enter phase 2 implementation.
Templates and Format
The complete reference for
/
is split into
in the same directory:
- YAML frontmatter example
- Top-level section anchor requirements
- Complete format and status semantics of
- What to write in each section 0-4
This skill only retains process-level constraints: Draft the complete first draft at once according to that reference, don't output semi-finished products in batches.
The prompt for overall review is also in
. The rule remains:
Send only one overall review, don't confirm section by section.
Exit Conditions
The user has approved the overall review, and all the following are met:
File path: The design document is under
easysdd/features/{feature}/
; create the feature directory in this step if it doesn't exist. See section 0 of
easysdd/reference/shared-conventions.md
for naming conventions.
Common Pitfalls
These are recurring anti-patterns from the past; stop and ask yourself if you're falling into them:
- Writing without reading and relevant architecture docs — the design will likely not align with existing code
- Not checking for term conflicts — resolving conflicts later will take ten times longer via git blame
- Describing interface behavior in prose without giving specific examples — readers can't build a mental model and can't judge during review
- Writing the contract layer as a full-field encyclopedia — don't copy existing and unchanged interfaces repeatedly
- Forcing diagrams — if there are ≤2 modules and linear calls, diagrams will blur the focus instead
- Splitting progress steps too finely (>8 steps) — so fine that each step has no independent value
- Only giving half the document for user review first — the user can't see global consistency
- Secretly expanding scope in the requirement summary or change plan — won't match acceptance criteria later
",