diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 49a5889..564d7ac 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -12,7 +12,7 @@ "name": "dev-workflows", "source": "./dev-workflows", "strict": true, - "version": "0.20.4", + "version": "0.20.5", "description": "Skills + Subagents for backend development - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", "author": { "name": "Shinsuke Kagawa", @@ -81,7 +81,7 @@ "name": "dev-workflows-frontend", "source": "./dev-workflows-frontend", "strict": true, - "version": "0.20.4", + "version": "0.20.5", "description": "Skills + Subagents for React/TypeScript - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", "author": { "name": "Shinsuke Kagawa", @@ -152,7 +152,7 @@ "name": "dev-workflows-fullstack", "source": "./dev-workflows-fullstack", "strict": true, - "version": "0.20.4", + "version": "0.20.5", "description": "Skills + Subagents for fullstack development (backend + React/TypeScript) - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", "author": { "name": "Shinsuke Kagawa", @@ -240,7 +240,7 @@ "name": "dev-skills", "source": "./dev-skills", "strict": true, - "version": "0.20.4", + "version": "0.20.5", "description": "Lightweight skills for users with existing workflows - coding best practices, testing principles, and design guidelines without recipe workflows or agents", "author": { "name": "Shinsuke Kagawa", diff --git a/agents/code-reviewer.md b/agents/code-reviewer.md index 3a875db..d04ca98 100644 --- a/agents/code-reviewer.md +++ b/agents/code-reviewer.md @@ -60,6 +60,7 @@ For each acceptance criterion extracted in Step 1: - For behavior-changing ACs, confirm the evidence covers the boundary paths, not only the main path: where a distinct branch, state, input class, lifecycle step, or fallback governs the behavior, verify it is exercised. Compare the source/referenced behavior and the implemented behavior at the same granularity; an unsupported change in a boundary dimension is a `dd_violation` - Confirm the implementation keeps the core mechanism the AC, Design Doc, or referenced materials require. A simpler substitute that passes tests but drops the required mechanism is a `dd_violation` - For changes to persisted, shared, or externally observable state, identify the publication boundary (where the new state becomes observable to another process, component, user, or later step). State that is observable as complete while still partial, uninitialized, stale, or rollback-only is a `reliability` finding, because a downstream consumer can treat the incomplete state as complete and fail +- When the reviewed change is classified as `bug-fix`, `regression`, `state-change`, or `boundary-change` (the task's `Change Category` field, when present, names the kind), check the cases sharing its path, contract, persisted state, or external boundary. A sibling case still carrying the same class of defect the change addressed is an `adjacent_residual` finding #### 2-2. Identifier Verification @@ -112,6 +113,7 @@ Classify each quality finding into one of: | **maintainability** | Code structure impedes future changes or comprehension | Long functions, deep nesting, multiple responsibilities, unclear naming | | **reliability** | Missing safeguards that could cause runtime failures | Unhandled error paths, missing validation at boundaries, silent failures | | **coverage_gap** | Acceptance criteria lack corresponding test verification | AC fulfilled in code but no test exercises it | +| **adjacent_residual** | A case sharing the change's path, contract, persisted state, or external boundary still carries the class of defect the change addressed | Fallback path left unfixed, sibling state transition still stale, another consumer of a changed contract not updated | Each finding must include a `rationale` field: @@ -121,6 +123,7 @@ Each finding must include a `rationale` field: | **maintainability** | What specific maintenance or comprehension risk this creates | | **reliability** | What failure scenario is unguarded and under what conditions it could occur | | **coverage_gap** | Which AC is untested and why test coverage matters for this specific case | +| **adjacent_residual** | Which adjacent case shares the path/contract/state/boundary and how it still exhibits the defect class | ### 4. Check Architecture Compliance @@ -173,14 +176,14 @@ identifierVerification[].codeValue: string (or "not found") identifierVerification[].location: string (file:line; null if not found) identifierVerification[].match: boolean -qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap") +qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap" | "adjacent_residual") qualityFindings[].location: string (file:line or file:function) qualityFindings[].description: string qualityFindings[].rationale: string (category-specific) qualityFindings[].suggestion: string summary.{acsTotal, acsFulfilled, acsPartial, acsUnfulfilled, identifiersTotal, identifiersMatched, lowConfidenceItems}: number (integer >= 0) -summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap}: number (integer >= 0) +summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap, adjacent_residual}: number (integer >= 0) ``` ### Minimal Shape Example @@ -191,22 +194,14 @@ summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage "identifierMatchRate": 95, "verdict": "needs-improvement", "acceptanceCriteria": [ - { - "item": "User can log in with valid credentials", - "status": "fulfilled", - "confidence": "high", - "location": "src/auth/login.ts:42", - "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], - "gap": null, - "suggestion": null - } + {"item": "User can log in with valid credentials", "status": "fulfilled", "confidence": "high", "location": "src/auth/login.ts:42", "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], "gap": null, "suggestion": null} ], "identifierVerification": [{"identifier": "AUTH_TOKEN_TTL", "designDocValue": "3600", "codeValue": "1800", "location": "src/auth/config.ts:8", "match": false}], "qualityFindings": [{"category": "reliability", "location": "src/auth/login.ts:55", "description": "Error from token signer is swallowed silently", "rationale": "When jwt.sign throws, the catch block returns null without logging", "suggestion": "Re-throw with context or log then propagate"}], "summary": { "acsTotal": 12, "acsFulfilled": 10, "acsPartial": 1, "acsUnfulfilled": 1, "identifiersTotal": 20, "identifiersMatched": 19, "lowConfidenceItems": 2, - "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0 } + "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0, "adjacent_residual": 0 } } } ``` diff --git a/agents/quality-fixer-frontend.md b/agents/quality-fixer-frontend.md index 35a5d14..367ed07 100644 --- a/agents/quality-fixer-frontend.md +++ b/agents/quality-fixer-frontend.md @@ -102,7 +102,7 @@ Return one of the following as the final response (see Output Format for schemas Prefer repository-local component patterns over generic React advice; when patterns coexist for the same concern, follow the dominant one in the changed feature area — the surrounding feature folder, or the nearest parent directory containing siblings using the same concern. Route any new library/pattern decision through the `blocked` output (`reason: "Cannot determine due to unclear specification"`). ### Testing Quality -- **Test Coverage**: 60% baseline; foundational/leaf components (Atomic Design atoms, or reused-across-features components) target 70%, molecules 65%, organisms 60% +- **Test Coverage**: concentrate rigor on foundational/high-reuse units (shared components, hooks, utils); treat coverage as a signal for gaps, not a target. Enforce the project's configured threshold when one exists - **Mock layering**: Use the repository's existing network/API mocking layer for network behavior; browser-primitive doubles (e.g., ResizeObserver, IntersectionObserver, time, router/provider) are acceptable when the test environment requires them; the component under test is exercised through real renders and user interactions - **Query selection**: Prefer role/name queries for user-visible elements; use async queries (`findBy*`, `waitFor`) for async appearance and `queryBy*`/`queryAllBy*` only when asserting intentional absence diff --git a/agents/solver.md b/agents/solver.md index 26d7bae..f947488 100644 --- a/agents/solver.md +++ b/agents/solver.md @@ -71,6 +71,10 @@ Generate at least 3 solutions from the following perspectives: | mitigation | Measures to reduce impact | Temporary measure while waiting for root fix | | fundamental | Comprehensive fix including recurrence prevention | When similar problems have occurred repeatedly | +**Adjacent Case Coverage**: +- When the confirmed failure point concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the failure point itself), evaluate whether cases sharing the same path, contract, persisted state, or external boundary need the same fix +- Include those adjacent cases in the solution scope when they share the same class of defect; record in residualRisks why any are excluded + **Generated Solution Verification**: - Check if project rules have applicable guidelines - For areas without guidelines, research current best practices via WebSearch to verify solutions align with standard approaches @@ -116,24 +120,12 @@ Recommendation strategy based on coverage assessment: }, "solutions": [ { - "id": "S1", - "name": "Solution name", - "type": "direct|workaround|mitigation|fundamental", - "description": "Detailed solution description", - "implementation": { - "approach": "Implementation approach description", - "affectedFiles": ["Files requiring changes"], - "dependencies": ["Affected dependencies"] - }, + "id": "S1", "name": "Solution name", "type": "direct|workaround|mitigation|fundamental", "description": "Detailed solution description", + "implementation": {"approach": "Implementation approach description", "affectedFiles": ["Files requiring changes"], "dependencies": ["Affected dependencies"]}, "tradeoffs": { - "cost": {"level": "low|medium|high", "details": "Details"}, - "risk": {"level": "low|medium|high", "details": "Details"}, - "scope": {"level": "low|medium|high", "details": "Details"}, - "maintainability": {"level": "low|medium|high", "details": "Details"}, - "certainty": {"level": "low|medium|high", "details": "Details"} + "cost": {"level": "low|medium|high", "details": "Details"}, "risk": {"level": "low|medium|high", "details": "Details"}, "scope": {"level": "low|medium|high", "details": "Details"}, "maintainability": {"level": "low|medium|high", "details": "Details"}, "certainty": {"level": "low|medium|high", "details": "Details"} }, - "pros": ["Advantages"], - "cons": ["Disadvantages"] + "pros": ["Advantages"], "cons": ["Disadvantages"] } ], "recommendation": { @@ -144,12 +136,7 @@ Recommendation strategy based on coverage assessment: }, "implementationPlan": { "steps": [ - { - "order": 1, - "action": "Specific action", - "verification": "How to verify this step", - "rollback": "Rollback procedure if problems occur" - } + {"order": 1, "action": "Specific action", "verification": "How to verify this step", "rollback": "Rollback procedure if problems occur"} ], "criticalPoints": ["Points requiring special attention"] }, diff --git a/agents/task-decomposer.md b/agents/task-decomposer.md index 728867e..98a6d24 100644 --- a/agents/task-decomposer.md +++ b/agents/task-decomposer.md @@ -92,6 +92,7 @@ Decompose tasks based on implementation strategy patterns determined in implemen - Task overview - Target files - **Investigation Targets** (what the executor must read and understand before implementing) + - **Change Category** (when the task is a bug fix / regression / state-change / boundary-change — see Change Category Classification below) - Concrete implementation steps - **Quality Assurance Mechanisms** (derived from work plan header — see Quality Assurance Mechanism Propagation below) - **Operation Verification Methods** (derived from Verification Strategy in work plan) @@ -213,6 +214,21 @@ When the work plan contains a Design-to-Plan Traceability table, propagate the m 2. Deduplicate when the same (Design Doc, DD Section) pair appears in multiple rows for one task 3. Apply only when the work plan contains a Design-to-Plan Traceability table +## Change Category Classification + +When a task corrects observed behavior or alters how state or a boundary behaves, classify it so the executor and downstream reviewers run a scoped adjacent-case sweep from the field value, rather than re-inferring the task's intent: + +1. **Classify from the work plan and Design Doc**. A task can match more than one category (e.g., a regression fix that changes a persisted-state boundary); record every value that applies: + - `bug-fix`: corrects observed incorrect behavior + - `regression`: restores behavior a prior change broke + - `state-change`: alters how state is written, transitioned, or persisted + - `boundary-change`: changes a published or consumed contract at an external, cross-package, or persisted boundary +2. **Populate the task's `Change Category` field** with all matched values, comma-separated (see task template). +3. **Extend Investigation Targets with the adjacent cases**. For every matched category, add the files sharing the same path, contract, persisted state, or external boundary as the change — including the owner module on both sides of an affected boundary — so the executor can sweep them for the same class of defect. Union the targets across all matched categories. +4. **Apply only on a match**. Purely additive, config, or scaffolding tasks default to no `Change Category` field and skip this propagation. + +This is distinct from per-AC boundary-path proof (which proves a boundary path *within* an AC): Change Category drives a sweep of cases that sit *outside* the task's ACs but share its path, contract, state, or boundary. + ## Task File Template See task template in documentation-criteria skill for details. @@ -312,6 +328,7 @@ Please execute decomposed tasks according to the order. - [ ] Appropriate granularity (1-5 files/task) - [ ] Investigation Targets specified for every task (specific file paths, not vague categories) - [ ] Proof Obligations recorded for each claim-implementing task (primary failure mode + boundary to exercise) +- [ ] Change Category set for bug-fix / regression / state-change / boundary-change tasks, with adjacent path/boundary owners added to Investigation Targets - [ ] Quality Assurance Mechanisms from work plan header propagated to relevant tasks - [ ] UI Spec Component → Task Mapping rows propagated to matching tasks (when work plan has the table) - [ ] Connection Map boundary rows propagated to matching tasks (when work plan has the table) diff --git a/agents/task-executor-frontend.md b/agents/task-executor-frontend.md index 1af1cef..59ab7cf 100644 --- a/agents/task-executor-frontend.md +++ b/agents/task-executor-frontend.md @@ -139,6 +139,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Duplication Check — Pattern 5 from frontend-ai-guide) Read relevant Design Doc sections accurately; investigate existing implementations (similar components/hooks in same domain/responsibility); determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback rendering, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -209,18 +217,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["src/components/Button/Button.test.tsx"], "requiresTestReview": false, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", - "executed": true, - "command": "test -- Button.test.tsx", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", "executed": true, "command": "test -- Button.test.tsx", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -235,19 +233,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -260,27 +249,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar component/hook discovered", "taskName": "[Task name being executed]", "similar_components": [ - { - "file_path": "src/components/ExistingButton/ExistingButton.tsx", - "component_name": "ExistingButton", - "similarity_reason": "Same UI pattern, same Props structure", - "code_snippet": "[Excerpt of relevant component code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "src/components/ExistingButton/ExistingButton.tsx", "component_name": "ExistingButton", "similarity_reason": "Same UI pattern, same Props structure", "code_snippet": "[Excerpt of relevant component code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["component keywords", "feature keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["component keywords", "feature keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_component_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing component", - "Refactor existing component then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing component", "Refactor existing component then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing component analysis]" } ``` @@ -294,18 +268,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -319,18 +285,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[library or pattern concern, e.g., routing, server-state, forms]", - "candidatesFound": ["list of coexisting choices found in repository"], - "filesChecked": ["file paths where each choice was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]" - }, + "dependency": {"name": "[library or pattern concern, e.g., routing, server-state, forms]", "candidatesFound": ["list of coexisting choices found in repository"], "filesChecked": ["file paths where each choice was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]"}, "user_decision_required": true, - "suggested_options": [ - "Follow choice X (dominant in adjacent feature area)", - "Follow choice Y (matches a specific repository convention or constraint)", - "Defer the choice and split the task" - ] + "suggested_options": ["Follow choice X (dominant in adjacent feature area)", "Follow choice Y (matches a specific repository convention or constraint)", "Defer the choice and split the task"] } ``` @@ -342,17 +299,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -369,21 +318,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/agents/task-executor.md b/agents/task-executor.md index b2fa617..fe47c66 100644 --- a/agents/task-executor.md +++ b/agents/task-executor.md @@ -134,6 +134,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Pattern 5 Compliant) Read relevant Design Doc sections (interface contracts, data structures, dependency constraints); investigate existing implementations in the same domain/responsibility; determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback behavior, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -206,18 +214,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["created/test/file/path"], "requiresTestReview": true, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test / L2: Integration test / L3: E2E test", - "executed": true, - "command": "Executed test command", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test / L2: Integration test / L3: E2E test", "executed": true, "command": "Executed test command", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -232,19 +230,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -257,27 +246,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar function discovered", "taskName": "[Task name being executed]", "similar_functions": [ - { - "file_path": "[path to existing implementation]", - "function_name": "existingFunction", - "similarity_reason": "Same domain, same responsibility", - "code_snippet": "[Excerpt of relevant code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "[path to existing implementation]", "function_name": "existingFunction", "similarity_reason": "Same domain, same responsibility", "code_snippet": "[Excerpt of relevant code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["domain keywords", "responsibility keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["domain keywords", "responsibility keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_function_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing function", - "Refactor existing function then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing function", "Refactor existing function then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing code analysis]" } ``` @@ -291,18 +265,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -314,18 +280,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[dependency name]", - "versionsFound": ["list of versions found in repository"], - "filesChecked": ["file paths where dependency was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]" - }, + "dependency": {"name": "[dependency name]", "versionsFound": ["list of versions found in repository"], "filesChecked": ["file paths where dependency was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]"}, "user_decision_required": true, - "suggested_options": [ - "Use version X (majority in repository)", - "Use version Y (specific reason)", - "Research latest stable version and advise" - ] + "suggested_options": ["Use version X (majority in repository)", "Use version Y (specific reason)", "Research latest stable version and advise"] } ``` @@ -337,17 +294,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -364,21 +313,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/agents/verifier.md b/agents/verifier.md index 21986ff..475e056 100644 --- a/agents/verifier.md +++ b/agents/verifier.md @@ -61,7 +61,8 @@ Check the upstream investigation's pathMap for completeness: 1. **Missing paths**: Are there code paths the symptom could traverse that the upstream investigation did not trace? (e.g., error handling branches, async forks, fallback paths) 2. **Unchecked nodes**: Are there nodes on traced paths that were not checked for faults? -3. **Additional failure points**: If missing paths or unchecked nodes reveal new faults, record them +3. **Adjacent cases**: When the investigation concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the investigation itself), are there cases sharing the same path, contract, persisted state, or external boundary that could carry the same fault? Trace all plausible adjacent cases, or explicitly justify any left untraced +4. **Additional failure points**: If missing paths, unchecked nodes, or adjacent cases reveal new faults, record them The goal is to verify that the upstream investigation's path coverage is sufficient. @@ -117,78 +118,33 @@ Evaluate each failure point independently (do NOT select a single "winner"): "identifiedGaps": ["Missing paths or unchecked nodes"] }, "triangulationSupplements": [ - { - "source": "Additional information source investigated", - "findings": "Content discovered", - "impactOnFailurePoints": "Impact on existing failure points" - } + {"source": "Additional information source investigated", "findings": "Content discovered", "impactOnFailurePoints": "Impact on existing failure points"} ], "externalResearch": [ - { - "query": "Search query used", - "source": "Information source", - "findings": "Related information discovered", - "impactOnFailurePoints": "Impact on failure points" - } + {"query": "Search query used", "source": "Information source", "findings": "Related information discovered", "impactOnFailurePoints": "Impact on failure points"} ], "coverageCheck": { "missingPaths": ["Paths not traced by upstream investigation"], "uncheckedNodes": ["Nodes on traced paths that were not checked"], "additionalFailurePoints": [ - { - "id": "AFP1", - "nodeId": "Node reference", - "symptomId": "Symptom reference", - "description": "Newly discovered fault", - "checkStatus": "supported|weakened|blocked|not_reached", - "evidence": [ - {"type": "supporting", "detail": "Evidence detail", "source": "file:line"} - ] - } + {"id": "AFP1", "nodeId": "Node reference", "symptomId": "Symptom reference", "description": "Newly discovered fault", "checkStatus": "supported|weakened|blocked|not_reached", "evidence": [{"type": "supporting", "detail": "Evidence detail", "source": "file:line"}]} ] }, "devilsAdvocateFindings": [ - { - "targetFailurePoint": "FP1", - "alternativeExplanation": "Could this be correct behavior?", - "hiddenAssumptions": ["Implicit assumptions"], - "potentialCounterEvidence": ["Potentially overlooked counter-evidence"] - } + {"targetFailurePoint": "FP1", "alternativeExplanation": "Could this be correct behavior?", "hiddenAssumptions": ["Implicit assumptions"], "potentialCounterEvidence": ["Potentially overlooked counter-evidence"]} ], "failurePointEvaluation": [ - { - "failurePointId": "FP1 or AFP1", - "description": "Failure point description", - "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", - "finalStatus": "supported|weakened|blocked|not_reached", - "statusChangeReason": "Why status changed (if changed)", - "remainingUncertainty": ["Remaining uncertainty"] - } + {"failurePointId": "FP1 or AFP1", "description": "Failure point description", "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", "finalStatus": "supported|weakened|blocked|not_reached", "statusChangeReason": "Why status changed (if changed)", "remainingUncertainty": ["Remaining uncertainty"]} ], "conclusion": { "confirmedFailurePoints": [ - { - "failurePointId": "FP1", - "description": "What the fault is", - "location": "file:line", - "symptomId": "S1", - "symptomExplained": "How this fault leads to the observed symptom", - "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", - "finalStatus": "supported|weakened", - "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], - "impactScope": ["Affected file paths"], - "recurrenceRisk": "low|medium|high" - } + {"failurePointId": "FP1", "description": "What the fault is", "location": "file:line", "symptomId": "S1", "symptomExplained": "How this fault leads to the observed symptom", "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", "finalStatus": "supported|weakened", "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], "impactScope": ["Affected file paths"], "recurrenceRisk": "low|medium|high"} ], "refutedFailurePoints": [ {"failurePointId": "FP2", "reason": "Reason for refutation"} ], "failurePointRelationships": [ - { - "points": ["FP1", "FP3"], - "relationship": "independent|dependent|same_chain", - "detail": "Description of how the failure points relate" - } + {"points": ["FP1", "FP3"], "relationship": "independent|dependent|same_chain", "detail": "Description of how the failure points relate"} ], "coverageAssessment": "sufficient|partial|insufficient", "unresolvedSymptoms": ["Symptoms not fully explained by confirmed failure points"], diff --git a/dev-skills/.claude-plugin/plugin.json b/dev-skills/.claude-plugin/plugin.json index c380050..a6d4663 100644 --- a/dev-skills/.claude-plugin/plugin.json +++ b/dev-skills/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-skills", "description": "Lightweight skills for users with existing workflows - coding best practices, testing principles, and design guidelines without recipe workflows or agents", - "version": "0.20.4", + "version": "0.20.5", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-skills/skills/documentation-criteria/references/task-template.md b/dev-skills/skills/documentation-criteria/references/task-template.md index 28c65c3..6dd3c81 100644 --- a/dev-skills/skills/documentation-criteria/references/task-template.md +++ b/dev-skills/skills/documentation-criteria/references/task-template.md @@ -17,6 +17,13 @@ Metadata: Files to read before starting implementation (file path, with optional search hint): - [e.g., src/orders/checkout (processOrder function) — determined during task decomposition based on task nature] +## Change Category +(Include this field only when the task is a bug fix, regression, state-change, or boundary-change — populated during task decomposition. Omit otherwise.) + +`Change Category: ` + +When present, the implementation sweeps the cases sharing the same path, contract, persisted state, or external boundary for the same class of defect (see Implementation Steps Red Phase). + ## Binding Decisions (Include this section when the work plan's ADR Bindings table covers this task. Omit otherwise.) @@ -32,6 +39,7 @@ Each row is an ADR decision the implementation in this task must comply with. ## Implementation Steps (TDD: Red-Green-Refactor) ### 1. Red Phase - [ ] Read all Investigation Targets and record key observations +- [ ] (When Change Category is set) Sweep the adjacent cases sharing the same path/contract/state/boundary for the same class of defect; fold any found within scope into the failing tests - [ ] Review dependency deliverables (if any) - [ ] Verify/create contract definitions - [ ] Write failing tests diff --git a/dev-skills/skills/frontend-ai-guide/SKILL.md b/dev-skills/skills/frontend-ai-guide/SKILL.md index 8a05065..a20b940 100644 --- a/dev-skills/skills/frontend-ai-guide/SKILL.md +++ b/dev-skills/skills/frontend-ai-guide/SKILL.md @@ -141,7 +141,8 @@ To isolate problems, attempt reproduction with minimal code: - Create minimal configuration that reproduces problem - Use React DevTools to inspect component tree -### 4. Debug Log Output +### 4. Debug Log Output (temporary) +Add structured debug logs to isolate the issue, then remove them before commit (per "Delete debug `console.log()`" in typescript-rules): ```typescript console.log('DEBUG:', { context: 'user-form-submission', @@ -153,38 +154,19 @@ console.log('DEBUG:', { ## Quality Check Workflow -Use the appropriate run command based on the `packageManager` field in package.json. +Read `package.json` scripts and run them with the project's package manager (`packageManager` field). Map the project's actual script names to the phases below — do not assume fixed names. -### Build Commands -- `dev` - Development server -- `build` - Production build -- `preview` - Preview production build -- `type-check` - Type check (no emit) - -### Quality Check Phases - -**Phase 1-3: Basic Checks** -- `check` - Biome (lint + format) -- `build` - TypeScript build - -**Phase 4-5: Tests and Final Confirmation** -- `test` - Test execution -- `test:coverage:fresh` - Coverage measurement (fresh cache) -- `check:all` - Overall integrated check - -### Auxiliary Commands -- `test:coverage` - Run tests with coverage -- `test:safe` - Safe test execution (with auto cleanup) -- `cleanup:processes` - Cleanup Vitest processes -- `format` - Format fixes -- `lint:fix` - Lint fixes -- `open coverage/index.html` - Check coverage report +### Phases (run in order) +1. **Lint/format** — the project's formatter + linter (e.g., Biome, or ESLint + Prettier) +2. **Type check** — type check without emit +3. **Build** — production build +4. **Test** — unit/integration tests +5. **Coverage** — coverage run when the task added or changed behavior ### Troubleshooting -- **Port in use error**: Run `cleanup:processes` script -- **Cache issues**: Run `test:coverage:fresh` script -- **Dependency errors**: Clean reinstall dependencies -- **Vite preview not starting**: Check port 4173 availability +- **Port already in use** — stop the stale dev/preview/test process holding the port +- **Stale cache** — re-run with the project's fresh/clean-cache option +- **Dependency errors** — clean reinstall dependencies ## Situations Requiring Technical Decisions @@ -196,6 +178,7 @@ Use the appropriate run command based on the `packageManager` field in package.j ### Performance vs Readability - Prioritize readability unless React DevTools Profiler identifies a measurable bottleneck (e.g., render time exceeding 16ms, unnecessary re-renders) - Measure before optimizing with React DevTools Profiler +- When React Compiler is enabled, routine memoization is automatic; manual memoization is a profiler- or identity-justified exception (measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - Document reason with comments when optimizing ### Granularity of Component/Type Definitions diff --git a/dev-skills/skills/test-implement/references/frontend.md b/dev-skills/skills/test-implement/references/frontend.md index ff3098f..8f7acff 100644 --- a/dev-skills/skills/test-implement/references/frontend.md +++ b/dev-skills/skills/test-implement/references/frontend.md @@ -12,26 +12,13 @@ ## Basic Testing Policy ### Quality Requirements -- **Coverage**: Unit test coverage must be 60% or higher (Frontend standard 2025) +- **Coverage**: prioritize meaningful assertions on critical paths and high-reuse components; treat coverage as a signal for gaps, not a target. Any threshold is the project's CI config - **Independence**: Each test can run independently without depending on other tests - **Reproducibility**: Tests are environment-independent and always return the same results - **Readability**: Test code maintains the same quality as production code -### Coverage Requirements (ADR-0002 Compliant) -**Component-specific targets**: - -When the project adopts Atomic Design (atoms / molecules / organisms layering): -- Atoms (Button, Text, etc.): 70% or higher -- Molecules (FormField, etc.): 65% or higher -- Organisms (Header, Footer, etc.): 60% or higher - -When the project uses a different component architecture (Feature-based, Container-Presenter, etc.): apply 60% as the baseline and raise the target for foundational/leaf components (those reused across many features) to 70%. - -Component-architecture-independent targets: -- Custom Hooks: 65% or higher -- Utils: 70% or higher - -**Metrics**: Statements, Branches, Functions, Lines +### Where to concentrate test rigor +Test foundational, high-reuse units the hardest — shared components, custom hooks, and utils reused across many features carry the widest blast radius. Higher-composition surfaces (organisms, pages) lean on integration/E2E coverage instead. Any numeric threshold is the project's CI config. ### Test Types and Scope 1. **Unit Tests (React Testing Library)** diff --git a/dev-skills/skills/testing-principles/SKILL.md b/dev-skills/skills/testing-principles/SKILL.md index dd5831f..b6aac8b 100644 --- a/dev-skills/skills/testing-principles/SKILL.md +++ b/dev-skills/skills/testing-principles/SKILL.md @@ -33,12 +33,11 @@ description: Language-agnostic testing principles including TDD, test quality, c ## Quality Requirements -### Coverage Standards +### Coverage -- **Minimum 80% code coverage** for production code -- Prioritize critical paths and business logic -- Prioritize meaningful assertions over coverage percentage -- Use coverage as a guide, not a goal +- Treat coverage as a diagnostic signal for finding untested areas, not a target — a target gets gamed into trivial tests (Goodhart's Law) +- Concentrate tests on critical paths, business logic, and behavior whose regression would matter +- Prioritize meaningful assertions over the coverage number; any CI threshold is the project's config, not a quality goal in itself ### Test Characteristics diff --git a/dev-skills/skills/typescript-rules/SKILL.md b/dev-skills/skills/typescript-rules/SKILL.md index 947ab7b..a47574e 100644 --- a/dev-skills/skills/typescript-rules/SKILL.md +++ b/dev-skills/skills/typescript-rules/SKILL.md @@ -65,6 +65,11 @@ function isUser(value: unknown): value is User { - **Component Hierarchy**: Use the project's adopted component architecture. When the project uses Atomic Design: Atoms → Molecules → Organisms → Templates → Pages. When the project uses Feature-based, Container-Presenter, or another structure: follow that structure consistently and document the chosen layering in the project README or design doc - **Co-location**: Place tests, styles, and related files alongside components +**Server/Client Boundary (RSC frameworks only — e.g., Next.js App Router)** +- Default to server components for data fetching and rendering; isolate interactivity behind a `"use client"` boundary at the smallest scope that needs it +- Keep browser-only APIs (`window`, `localStorage`, event handlers) inside client components; calling them in a server component breaks the render +- N/A for client-only SPAs (e.g., Vite) — skip when the project has no server-component runtime + **State Management Patterns** - **Local State**: `useState` for component-specific state - **Context API**: For sharing state across component tree (theme, auth, etc.) @@ -93,15 +98,17 @@ setUsers(prev => [...prev, newUser]) - Type-safe: Always define Props type explicitly **Environment Variables** -- **Use build tool's environment variable system**: `process.env` does not work in browsers -- Centrally manage environment variables through configuration layer -- Define a typed config object with defaults for every environment variable +- **Use the build tool's env accessor**: read client-side env through the bundler's exposed accessor — Vite via `import.meta.env`, Next.js/CRA via prefixed `process.env`. Raw, unprefixed access is `undefined` in the browser bundle +- **Only prefixed vars reach the client**: build tools expose only vars carrying their public prefix; an unprefixed var is `undefined` in the browser. The prefix differs per tool — match the project's bundler (Vite `VITE_`, Next.js public `NEXT_PUBLIC_`, CRA `REACT_APP_`) +- Centrally manage env through a typed config object with a default for every variable ```typescript -// Use import.meta.env (not process.env — unavailable in browser bundles) +// Client-exposed env must carry the bundler's public prefix, or it is undefined in the browser. +// Vite: import.meta.env.VITE_API_URL +// Next.js: process.env.NEXT_PUBLIC_API_URL const config = { - apiUrl: import.meta.env.API_URL || 'http://localhost:3000', - appName: import.meta.env.APP_NAME || 'My App' + apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000', // adjust accessor + prefix to the project's bundler + appName: import.meta.env.VITE_APP_NAME || 'My App' } ``` @@ -123,6 +130,7 @@ const response = await fetch('/api/data') // Backend handles API key authenticat - Promise Handling: Always use `async/await` - Error Handling: Always handle with `try-catch` or Error Boundary - Type Definition: Explicitly define return value types (e.g., `Promise`) +- Effect race/cleanup: guard `useEffect` data fetches against out-of-order responses and post-unmount state updates — abort or ignore stale results (`AbortController` or a mounted flag), or use a server-state library (React Query/SWR) that cancels and dedupes. `try-catch` alone does not cover this **Format Rules** - Semicolon omission (follow Biome settings) @@ -195,10 +203,10 @@ Redact sensitive fields (password, token, apiKey, secret, creditCard) before log ## Performance Optimization -- Component Memoization: Use React.memo for expensive components +- Automatic memoization: when React Compiler is enabled, rely on it; reach for manual `React.memo`/`useMemo`/`useCallback` only as a profiler- or identity-justified escape hatch (a measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - State Optimization: Minimize re-renders with proper state structure -- Lazy Loading: Use React.lazy and Suspense for code splitting -- Bundle Size: Monitor with the `build` script and keep under 500KB +- Lazy Loading: Use `React.lazy` and `Suspense` for code splitting +- Bundle Size: Monitor via the build script against the project's budget ## Non-functional Requirements diff --git a/dev-workflows-frontend/.claude-plugin/plugin.json b/dev-workflows-frontend/.claude-plugin/plugin.json index 366cc1f..137a819 100644 --- a/dev-workflows-frontend/.claude-plugin/plugin.json +++ b/dev-workflows-frontend/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-workflows-frontend", "description": "Skills + Subagents for React/TypeScript - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", - "version": "0.20.4", + "version": "0.20.5", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows-frontend/agents/code-reviewer.md b/dev-workflows-frontend/agents/code-reviewer.md index 3a875db..d04ca98 100644 --- a/dev-workflows-frontend/agents/code-reviewer.md +++ b/dev-workflows-frontend/agents/code-reviewer.md @@ -60,6 +60,7 @@ For each acceptance criterion extracted in Step 1: - For behavior-changing ACs, confirm the evidence covers the boundary paths, not only the main path: where a distinct branch, state, input class, lifecycle step, or fallback governs the behavior, verify it is exercised. Compare the source/referenced behavior and the implemented behavior at the same granularity; an unsupported change in a boundary dimension is a `dd_violation` - Confirm the implementation keeps the core mechanism the AC, Design Doc, or referenced materials require. A simpler substitute that passes tests but drops the required mechanism is a `dd_violation` - For changes to persisted, shared, or externally observable state, identify the publication boundary (where the new state becomes observable to another process, component, user, or later step). State that is observable as complete while still partial, uninitialized, stale, or rollback-only is a `reliability` finding, because a downstream consumer can treat the incomplete state as complete and fail +- When the reviewed change is classified as `bug-fix`, `regression`, `state-change`, or `boundary-change` (the task's `Change Category` field, when present, names the kind), check the cases sharing its path, contract, persisted state, or external boundary. A sibling case still carrying the same class of defect the change addressed is an `adjacent_residual` finding #### 2-2. Identifier Verification @@ -112,6 +113,7 @@ Classify each quality finding into one of: | **maintainability** | Code structure impedes future changes or comprehension | Long functions, deep nesting, multiple responsibilities, unclear naming | | **reliability** | Missing safeguards that could cause runtime failures | Unhandled error paths, missing validation at boundaries, silent failures | | **coverage_gap** | Acceptance criteria lack corresponding test verification | AC fulfilled in code but no test exercises it | +| **adjacent_residual** | A case sharing the change's path, contract, persisted state, or external boundary still carries the class of defect the change addressed | Fallback path left unfixed, sibling state transition still stale, another consumer of a changed contract not updated | Each finding must include a `rationale` field: @@ -121,6 +123,7 @@ Each finding must include a `rationale` field: | **maintainability** | What specific maintenance or comprehension risk this creates | | **reliability** | What failure scenario is unguarded and under what conditions it could occur | | **coverage_gap** | Which AC is untested and why test coverage matters for this specific case | +| **adjacent_residual** | Which adjacent case shares the path/contract/state/boundary and how it still exhibits the defect class | ### 4. Check Architecture Compliance @@ -173,14 +176,14 @@ identifierVerification[].codeValue: string (or "not found") identifierVerification[].location: string (file:line; null if not found) identifierVerification[].match: boolean -qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap") +qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap" | "adjacent_residual") qualityFindings[].location: string (file:line or file:function) qualityFindings[].description: string qualityFindings[].rationale: string (category-specific) qualityFindings[].suggestion: string summary.{acsTotal, acsFulfilled, acsPartial, acsUnfulfilled, identifiersTotal, identifiersMatched, lowConfidenceItems}: number (integer >= 0) -summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap}: number (integer >= 0) +summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap, adjacent_residual}: number (integer >= 0) ``` ### Minimal Shape Example @@ -191,22 +194,14 @@ summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage "identifierMatchRate": 95, "verdict": "needs-improvement", "acceptanceCriteria": [ - { - "item": "User can log in with valid credentials", - "status": "fulfilled", - "confidence": "high", - "location": "src/auth/login.ts:42", - "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], - "gap": null, - "suggestion": null - } + {"item": "User can log in with valid credentials", "status": "fulfilled", "confidence": "high", "location": "src/auth/login.ts:42", "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], "gap": null, "suggestion": null} ], "identifierVerification": [{"identifier": "AUTH_TOKEN_TTL", "designDocValue": "3600", "codeValue": "1800", "location": "src/auth/config.ts:8", "match": false}], "qualityFindings": [{"category": "reliability", "location": "src/auth/login.ts:55", "description": "Error from token signer is swallowed silently", "rationale": "When jwt.sign throws, the catch block returns null without logging", "suggestion": "Re-throw with context or log then propagate"}], "summary": { "acsTotal": 12, "acsFulfilled": 10, "acsPartial": 1, "acsUnfulfilled": 1, "identifiersTotal": 20, "identifiersMatched": 19, "lowConfidenceItems": 2, - "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0 } + "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0, "adjacent_residual": 0 } } } ``` diff --git a/dev-workflows-frontend/agents/quality-fixer-frontend.md b/dev-workflows-frontend/agents/quality-fixer-frontend.md index 35a5d14..367ed07 100644 --- a/dev-workflows-frontend/agents/quality-fixer-frontend.md +++ b/dev-workflows-frontend/agents/quality-fixer-frontend.md @@ -102,7 +102,7 @@ Return one of the following as the final response (see Output Format for schemas Prefer repository-local component patterns over generic React advice; when patterns coexist for the same concern, follow the dominant one in the changed feature area — the surrounding feature folder, or the nearest parent directory containing siblings using the same concern. Route any new library/pattern decision through the `blocked` output (`reason: "Cannot determine due to unclear specification"`). ### Testing Quality -- **Test Coverage**: 60% baseline; foundational/leaf components (Atomic Design atoms, or reused-across-features components) target 70%, molecules 65%, organisms 60% +- **Test Coverage**: concentrate rigor on foundational/high-reuse units (shared components, hooks, utils); treat coverage as a signal for gaps, not a target. Enforce the project's configured threshold when one exists - **Mock layering**: Use the repository's existing network/API mocking layer for network behavior; browser-primitive doubles (e.g., ResizeObserver, IntersectionObserver, time, router/provider) are acceptable when the test environment requires them; the component under test is exercised through real renders and user interactions - **Query selection**: Prefer role/name queries for user-visible elements; use async queries (`findBy*`, `waitFor`) for async appearance and `queryBy*`/`queryAllBy*` only when asserting intentional absence diff --git a/dev-workflows-frontend/agents/solver.md b/dev-workflows-frontend/agents/solver.md index 26d7bae..f947488 100644 --- a/dev-workflows-frontend/agents/solver.md +++ b/dev-workflows-frontend/agents/solver.md @@ -71,6 +71,10 @@ Generate at least 3 solutions from the following perspectives: | mitigation | Measures to reduce impact | Temporary measure while waiting for root fix | | fundamental | Comprehensive fix including recurrence prevention | When similar problems have occurred repeatedly | +**Adjacent Case Coverage**: +- When the confirmed failure point concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the failure point itself), evaluate whether cases sharing the same path, contract, persisted state, or external boundary need the same fix +- Include those adjacent cases in the solution scope when they share the same class of defect; record in residualRisks why any are excluded + **Generated Solution Verification**: - Check if project rules have applicable guidelines - For areas without guidelines, research current best practices via WebSearch to verify solutions align with standard approaches @@ -116,24 +120,12 @@ Recommendation strategy based on coverage assessment: }, "solutions": [ { - "id": "S1", - "name": "Solution name", - "type": "direct|workaround|mitigation|fundamental", - "description": "Detailed solution description", - "implementation": { - "approach": "Implementation approach description", - "affectedFiles": ["Files requiring changes"], - "dependencies": ["Affected dependencies"] - }, + "id": "S1", "name": "Solution name", "type": "direct|workaround|mitigation|fundamental", "description": "Detailed solution description", + "implementation": {"approach": "Implementation approach description", "affectedFiles": ["Files requiring changes"], "dependencies": ["Affected dependencies"]}, "tradeoffs": { - "cost": {"level": "low|medium|high", "details": "Details"}, - "risk": {"level": "low|medium|high", "details": "Details"}, - "scope": {"level": "low|medium|high", "details": "Details"}, - "maintainability": {"level": "low|medium|high", "details": "Details"}, - "certainty": {"level": "low|medium|high", "details": "Details"} + "cost": {"level": "low|medium|high", "details": "Details"}, "risk": {"level": "low|medium|high", "details": "Details"}, "scope": {"level": "low|medium|high", "details": "Details"}, "maintainability": {"level": "low|medium|high", "details": "Details"}, "certainty": {"level": "low|medium|high", "details": "Details"} }, - "pros": ["Advantages"], - "cons": ["Disadvantages"] + "pros": ["Advantages"], "cons": ["Disadvantages"] } ], "recommendation": { @@ -144,12 +136,7 @@ Recommendation strategy based on coverage assessment: }, "implementationPlan": { "steps": [ - { - "order": 1, - "action": "Specific action", - "verification": "How to verify this step", - "rollback": "Rollback procedure if problems occur" - } + {"order": 1, "action": "Specific action", "verification": "How to verify this step", "rollback": "Rollback procedure if problems occur"} ], "criticalPoints": ["Points requiring special attention"] }, diff --git a/dev-workflows-frontend/agents/task-decomposer.md b/dev-workflows-frontend/agents/task-decomposer.md index 728867e..98a6d24 100644 --- a/dev-workflows-frontend/agents/task-decomposer.md +++ b/dev-workflows-frontend/agents/task-decomposer.md @@ -92,6 +92,7 @@ Decompose tasks based on implementation strategy patterns determined in implemen - Task overview - Target files - **Investigation Targets** (what the executor must read and understand before implementing) + - **Change Category** (when the task is a bug fix / regression / state-change / boundary-change — see Change Category Classification below) - Concrete implementation steps - **Quality Assurance Mechanisms** (derived from work plan header — see Quality Assurance Mechanism Propagation below) - **Operation Verification Methods** (derived from Verification Strategy in work plan) @@ -213,6 +214,21 @@ When the work plan contains a Design-to-Plan Traceability table, propagate the m 2. Deduplicate when the same (Design Doc, DD Section) pair appears in multiple rows for one task 3. Apply only when the work plan contains a Design-to-Plan Traceability table +## Change Category Classification + +When a task corrects observed behavior or alters how state or a boundary behaves, classify it so the executor and downstream reviewers run a scoped adjacent-case sweep from the field value, rather than re-inferring the task's intent: + +1. **Classify from the work plan and Design Doc**. A task can match more than one category (e.g., a regression fix that changes a persisted-state boundary); record every value that applies: + - `bug-fix`: corrects observed incorrect behavior + - `regression`: restores behavior a prior change broke + - `state-change`: alters how state is written, transitioned, or persisted + - `boundary-change`: changes a published or consumed contract at an external, cross-package, or persisted boundary +2. **Populate the task's `Change Category` field** with all matched values, comma-separated (see task template). +3. **Extend Investigation Targets with the adjacent cases**. For every matched category, add the files sharing the same path, contract, persisted state, or external boundary as the change — including the owner module on both sides of an affected boundary — so the executor can sweep them for the same class of defect. Union the targets across all matched categories. +4. **Apply only on a match**. Purely additive, config, or scaffolding tasks default to no `Change Category` field and skip this propagation. + +This is distinct from per-AC boundary-path proof (which proves a boundary path *within* an AC): Change Category drives a sweep of cases that sit *outside* the task's ACs but share its path, contract, state, or boundary. + ## Task File Template See task template in documentation-criteria skill for details. @@ -312,6 +328,7 @@ Please execute decomposed tasks according to the order. - [ ] Appropriate granularity (1-5 files/task) - [ ] Investigation Targets specified for every task (specific file paths, not vague categories) - [ ] Proof Obligations recorded for each claim-implementing task (primary failure mode + boundary to exercise) +- [ ] Change Category set for bug-fix / regression / state-change / boundary-change tasks, with adjacent path/boundary owners added to Investigation Targets - [ ] Quality Assurance Mechanisms from work plan header propagated to relevant tasks - [ ] UI Spec Component → Task Mapping rows propagated to matching tasks (when work plan has the table) - [ ] Connection Map boundary rows propagated to matching tasks (when work plan has the table) diff --git a/dev-workflows-frontend/agents/task-executor-frontend.md b/dev-workflows-frontend/agents/task-executor-frontend.md index 1af1cef..59ab7cf 100644 --- a/dev-workflows-frontend/agents/task-executor-frontend.md +++ b/dev-workflows-frontend/agents/task-executor-frontend.md @@ -139,6 +139,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Duplication Check — Pattern 5 from frontend-ai-guide) Read relevant Design Doc sections accurately; investigate existing implementations (similar components/hooks in same domain/responsibility); determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback rendering, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -209,18 +217,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["src/components/Button/Button.test.tsx"], "requiresTestReview": false, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", - "executed": true, - "command": "test -- Button.test.tsx", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", "executed": true, "command": "test -- Button.test.tsx", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -235,19 +233,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -260,27 +249,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar component/hook discovered", "taskName": "[Task name being executed]", "similar_components": [ - { - "file_path": "src/components/ExistingButton/ExistingButton.tsx", - "component_name": "ExistingButton", - "similarity_reason": "Same UI pattern, same Props structure", - "code_snippet": "[Excerpt of relevant component code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "src/components/ExistingButton/ExistingButton.tsx", "component_name": "ExistingButton", "similarity_reason": "Same UI pattern, same Props structure", "code_snippet": "[Excerpt of relevant component code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["component keywords", "feature keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["component keywords", "feature keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_component_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing component", - "Refactor existing component then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing component", "Refactor existing component then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing component analysis]" } ``` @@ -294,18 +268,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -319,18 +285,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[library or pattern concern, e.g., routing, server-state, forms]", - "candidatesFound": ["list of coexisting choices found in repository"], - "filesChecked": ["file paths where each choice was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]" - }, + "dependency": {"name": "[library or pattern concern, e.g., routing, server-state, forms]", "candidatesFound": ["list of coexisting choices found in repository"], "filesChecked": ["file paths where each choice was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]"}, "user_decision_required": true, - "suggested_options": [ - "Follow choice X (dominant in adjacent feature area)", - "Follow choice Y (matches a specific repository convention or constraint)", - "Defer the choice and split the task" - ] + "suggested_options": ["Follow choice X (dominant in adjacent feature area)", "Follow choice Y (matches a specific repository convention or constraint)", "Defer the choice and split the task"] } ``` @@ -342,17 +299,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -369,21 +318,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/dev-workflows-frontend/agents/verifier.md b/dev-workflows-frontend/agents/verifier.md index 21986ff..475e056 100644 --- a/dev-workflows-frontend/agents/verifier.md +++ b/dev-workflows-frontend/agents/verifier.md @@ -61,7 +61,8 @@ Check the upstream investigation's pathMap for completeness: 1. **Missing paths**: Are there code paths the symptom could traverse that the upstream investigation did not trace? (e.g., error handling branches, async forks, fallback paths) 2. **Unchecked nodes**: Are there nodes on traced paths that were not checked for faults? -3. **Additional failure points**: If missing paths or unchecked nodes reveal new faults, record them +3. **Adjacent cases**: When the investigation concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the investigation itself), are there cases sharing the same path, contract, persisted state, or external boundary that could carry the same fault? Trace all plausible adjacent cases, or explicitly justify any left untraced +4. **Additional failure points**: If missing paths, unchecked nodes, or adjacent cases reveal new faults, record them The goal is to verify that the upstream investigation's path coverage is sufficient. @@ -117,78 +118,33 @@ Evaluate each failure point independently (do NOT select a single "winner"): "identifiedGaps": ["Missing paths or unchecked nodes"] }, "triangulationSupplements": [ - { - "source": "Additional information source investigated", - "findings": "Content discovered", - "impactOnFailurePoints": "Impact on existing failure points" - } + {"source": "Additional information source investigated", "findings": "Content discovered", "impactOnFailurePoints": "Impact on existing failure points"} ], "externalResearch": [ - { - "query": "Search query used", - "source": "Information source", - "findings": "Related information discovered", - "impactOnFailurePoints": "Impact on failure points" - } + {"query": "Search query used", "source": "Information source", "findings": "Related information discovered", "impactOnFailurePoints": "Impact on failure points"} ], "coverageCheck": { "missingPaths": ["Paths not traced by upstream investigation"], "uncheckedNodes": ["Nodes on traced paths that were not checked"], "additionalFailurePoints": [ - { - "id": "AFP1", - "nodeId": "Node reference", - "symptomId": "Symptom reference", - "description": "Newly discovered fault", - "checkStatus": "supported|weakened|blocked|not_reached", - "evidence": [ - {"type": "supporting", "detail": "Evidence detail", "source": "file:line"} - ] - } + {"id": "AFP1", "nodeId": "Node reference", "symptomId": "Symptom reference", "description": "Newly discovered fault", "checkStatus": "supported|weakened|blocked|not_reached", "evidence": [{"type": "supporting", "detail": "Evidence detail", "source": "file:line"}]} ] }, "devilsAdvocateFindings": [ - { - "targetFailurePoint": "FP1", - "alternativeExplanation": "Could this be correct behavior?", - "hiddenAssumptions": ["Implicit assumptions"], - "potentialCounterEvidence": ["Potentially overlooked counter-evidence"] - } + {"targetFailurePoint": "FP1", "alternativeExplanation": "Could this be correct behavior?", "hiddenAssumptions": ["Implicit assumptions"], "potentialCounterEvidence": ["Potentially overlooked counter-evidence"]} ], "failurePointEvaluation": [ - { - "failurePointId": "FP1 or AFP1", - "description": "Failure point description", - "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", - "finalStatus": "supported|weakened|blocked|not_reached", - "statusChangeReason": "Why status changed (if changed)", - "remainingUncertainty": ["Remaining uncertainty"] - } + {"failurePointId": "FP1 or AFP1", "description": "Failure point description", "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", "finalStatus": "supported|weakened|blocked|not_reached", "statusChangeReason": "Why status changed (if changed)", "remainingUncertainty": ["Remaining uncertainty"]} ], "conclusion": { "confirmedFailurePoints": [ - { - "failurePointId": "FP1", - "description": "What the fault is", - "location": "file:line", - "symptomId": "S1", - "symptomExplained": "How this fault leads to the observed symptom", - "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", - "finalStatus": "supported|weakened", - "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], - "impactScope": ["Affected file paths"], - "recurrenceRisk": "low|medium|high" - } + {"failurePointId": "FP1", "description": "What the fault is", "location": "file:line", "symptomId": "S1", "symptomExplained": "How this fault leads to the observed symptom", "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", "finalStatus": "supported|weakened", "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], "impactScope": ["Affected file paths"], "recurrenceRisk": "low|medium|high"} ], "refutedFailurePoints": [ {"failurePointId": "FP2", "reason": "Reason for refutation"} ], "failurePointRelationships": [ - { - "points": ["FP1", "FP3"], - "relationship": "independent|dependent|same_chain", - "detail": "Description of how the failure points relate" - } + {"points": ["FP1", "FP3"], "relationship": "independent|dependent|same_chain", "detail": "Description of how the failure points relate"} ], "coverageAssessment": "sufficient|partial|insufficient", "unresolvedSymptoms": ["Symptoms not fully explained by confirmed failure points"], diff --git a/dev-workflows-frontend/skills/documentation-criteria/references/task-template.md b/dev-workflows-frontend/skills/documentation-criteria/references/task-template.md index 28c65c3..6dd3c81 100644 --- a/dev-workflows-frontend/skills/documentation-criteria/references/task-template.md +++ b/dev-workflows-frontend/skills/documentation-criteria/references/task-template.md @@ -17,6 +17,13 @@ Metadata: Files to read before starting implementation (file path, with optional search hint): - [e.g., src/orders/checkout (processOrder function) — determined during task decomposition based on task nature] +## Change Category +(Include this field only when the task is a bug fix, regression, state-change, or boundary-change — populated during task decomposition. Omit otherwise.) + +`Change Category: ` + +When present, the implementation sweeps the cases sharing the same path, contract, persisted state, or external boundary for the same class of defect (see Implementation Steps Red Phase). + ## Binding Decisions (Include this section when the work plan's ADR Bindings table covers this task. Omit otherwise.) @@ -32,6 +39,7 @@ Each row is an ADR decision the implementation in this task must comply with. ## Implementation Steps (TDD: Red-Green-Refactor) ### 1. Red Phase - [ ] Read all Investigation Targets and record key observations +- [ ] (When Change Category is set) Sweep the adjacent cases sharing the same path/contract/state/boundary for the same class of defect; fold any found within scope into the failing tests - [ ] Review dependency deliverables (if any) - [ ] Verify/create contract definitions - [ ] Write failing tests diff --git a/dev-workflows-frontend/skills/frontend-ai-guide/SKILL.md b/dev-workflows-frontend/skills/frontend-ai-guide/SKILL.md index 8a05065..a20b940 100644 --- a/dev-workflows-frontend/skills/frontend-ai-guide/SKILL.md +++ b/dev-workflows-frontend/skills/frontend-ai-guide/SKILL.md @@ -141,7 +141,8 @@ To isolate problems, attempt reproduction with minimal code: - Create minimal configuration that reproduces problem - Use React DevTools to inspect component tree -### 4. Debug Log Output +### 4. Debug Log Output (temporary) +Add structured debug logs to isolate the issue, then remove them before commit (per "Delete debug `console.log()`" in typescript-rules): ```typescript console.log('DEBUG:', { context: 'user-form-submission', @@ -153,38 +154,19 @@ console.log('DEBUG:', { ## Quality Check Workflow -Use the appropriate run command based on the `packageManager` field in package.json. +Read `package.json` scripts and run them with the project's package manager (`packageManager` field). Map the project's actual script names to the phases below — do not assume fixed names. -### Build Commands -- `dev` - Development server -- `build` - Production build -- `preview` - Preview production build -- `type-check` - Type check (no emit) - -### Quality Check Phases - -**Phase 1-3: Basic Checks** -- `check` - Biome (lint + format) -- `build` - TypeScript build - -**Phase 4-5: Tests and Final Confirmation** -- `test` - Test execution -- `test:coverage:fresh` - Coverage measurement (fresh cache) -- `check:all` - Overall integrated check - -### Auxiliary Commands -- `test:coverage` - Run tests with coverage -- `test:safe` - Safe test execution (with auto cleanup) -- `cleanup:processes` - Cleanup Vitest processes -- `format` - Format fixes -- `lint:fix` - Lint fixes -- `open coverage/index.html` - Check coverage report +### Phases (run in order) +1. **Lint/format** — the project's formatter + linter (e.g., Biome, or ESLint + Prettier) +2. **Type check** — type check without emit +3. **Build** — production build +4. **Test** — unit/integration tests +5. **Coverage** — coverage run when the task added or changed behavior ### Troubleshooting -- **Port in use error**: Run `cleanup:processes` script -- **Cache issues**: Run `test:coverage:fresh` script -- **Dependency errors**: Clean reinstall dependencies -- **Vite preview not starting**: Check port 4173 availability +- **Port already in use** — stop the stale dev/preview/test process holding the port +- **Stale cache** — re-run with the project's fresh/clean-cache option +- **Dependency errors** — clean reinstall dependencies ## Situations Requiring Technical Decisions @@ -196,6 +178,7 @@ Use the appropriate run command based on the `packageManager` field in package.j ### Performance vs Readability - Prioritize readability unless React DevTools Profiler identifies a measurable bottleneck (e.g., render time exceeding 16ms, unnecessary re-renders) - Measure before optimizing with React DevTools Profiler +- When React Compiler is enabled, routine memoization is automatic; manual memoization is a profiler- or identity-justified exception (measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - Document reason with comments when optimizing ### Granularity of Component/Type Definitions diff --git a/dev-workflows-frontend/skills/test-implement/references/frontend.md b/dev-workflows-frontend/skills/test-implement/references/frontend.md index ff3098f..8f7acff 100644 --- a/dev-workflows-frontend/skills/test-implement/references/frontend.md +++ b/dev-workflows-frontend/skills/test-implement/references/frontend.md @@ -12,26 +12,13 @@ ## Basic Testing Policy ### Quality Requirements -- **Coverage**: Unit test coverage must be 60% or higher (Frontend standard 2025) +- **Coverage**: prioritize meaningful assertions on critical paths and high-reuse components; treat coverage as a signal for gaps, not a target. Any threshold is the project's CI config - **Independence**: Each test can run independently without depending on other tests - **Reproducibility**: Tests are environment-independent and always return the same results - **Readability**: Test code maintains the same quality as production code -### Coverage Requirements (ADR-0002 Compliant) -**Component-specific targets**: - -When the project adopts Atomic Design (atoms / molecules / organisms layering): -- Atoms (Button, Text, etc.): 70% or higher -- Molecules (FormField, etc.): 65% or higher -- Organisms (Header, Footer, etc.): 60% or higher - -When the project uses a different component architecture (Feature-based, Container-Presenter, etc.): apply 60% as the baseline and raise the target for foundational/leaf components (those reused across many features) to 70%. - -Component-architecture-independent targets: -- Custom Hooks: 65% or higher -- Utils: 70% or higher - -**Metrics**: Statements, Branches, Functions, Lines +### Where to concentrate test rigor +Test foundational, high-reuse units the hardest — shared components, custom hooks, and utils reused across many features carry the widest blast radius. Higher-composition surfaces (organisms, pages) lean on integration/E2E coverage instead. Any numeric threshold is the project's CI config. ### Test Types and Scope 1. **Unit Tests (React Testing Library)** diff --git a/dev-workflows-frontend/skills/testing-principles/SKILL.md b/dev-workflows-frontend/skills/testing-principles/SKILL.md index dd5831f..b6aac8b 100644 --- a/dev-workflows-frontend/skills/testing-principles/SKILL.md +++ b/dev-workflows-frontend/skills/testing-principles/SKILL.md @@ -33,12 +33,11 @@ description: Language-agnostic testing principles including TDD, test quality, c ## Quality Requirements -### Coverage Standards +### Coverage -- **Minimum 80% code coverage** for production code -- Prioritize critical paths and business logic -- Prioritize meaningful assertions over coverage percentage -- Use coverage as a guide, not a goal +- Treat coverage as a diagnostic signal for finding untested areas, not a target — a target gets gamed into trivial tests (Goodhart's Law) +- Concentrate tests on critical paths, business logic, and behavior whose regression would matter +- Prioritize meaningful assertions over the coverage number; any CI threshold is the project's config, not a quality goal in itself ### Test Characteristics diff --git a/dev-workflows-frontend/skills/typescript-rules/SKILL.md b/dev-workflows-frontend/skills/typescript-rules/SKILL.md index 947ab7b..a47574e 100644 --- a/dev-workflows-frontend/skills/typescript-rules/SKILL.md +++ b/dev-workflows-frontend/skills/typescript-rules/SKILL.md @@ -65,6 +65,11 @@ function isUser(value: unknown): value is User { - **Component Hierarchy**: Use the project's adopted component architecture. When the project uses Atomic Design: Atoms → Molecules → Organisms → Templates → Pages. When the project uses Feature-based, Container-Presenter, or another structure: follow that structure consistently and document the chosen layering in the project README or design doc - **Co-location**: Place tests, styles, and related files alongside components +**Server/Client Boundary (RSC frameworks only — e.g., Next.js App Router)** +- Default to server components for data fetching and rendering; isolate interactivity behind a `"use client"` boundary at the smallest scope that needs it +- Keep browser-only APIs (`window`, `localStorage`, event handlers) inside client components; calling them in a server component breaks the render +- N/A for client-only SPAs (e.g., Vite) — skip when the project has no server-component runtime + **State Management Patterns** - **Local State**: `useState` for component-specific state - **Context API**: For sharing state across component tree (theme, auth, etc.) @@ -93,15 +98,17 @@ setUsers(prev => [...prev, newUser]) - Type-safe: Always define Props type explicitly **Environment Variables** -- **Use build tool's environment variable system**: `process.env` does not work in browsers -- Centrally manage environment variables through configuration layer -- Define a typed config object with defaults for every environment variable +- **Use the build tool's env accessor**: read client-side env through the bundler's exposed accessor — Vite via `import.meta.env`, Next.js/CRA via prefixed `process.env`. Raw, unprefixed access is `undefined` in the browser bundle +- **Only prefixed vars reach the client**: build tools expose only vars carrying their public prefix; an unprefixed var is `undefined` in the browser. The prefix differs per tool — match the project's bundler (Vite `VITE_`, Next.js public `NEXT_PUBLIC_`, CRA `REACT_APP_`) +- Centrally manage env through a typed config object with a default for every variable ```typescript -// Use import.meta.env (not process.env — unavailable in browser bundles) +// Client-exposed env must carry the bundler's public prefix, or it is undefined in the browser. +// Vite: import.meta.env.VITE_API_URL +// Next.js: process.env.NEXT_PUBLIC_API_URL const config = { - apiUrl: import.meta.env.API_URL || 'http://localhost:3000', - appName: import.meta.env.APP_NAME || 'My App' + apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000', // adjust accessor + prefix to the project's bundler + appName: import.meta.env.VITE_APP_NAME || 'My App' } ``` @@ -123,6 +130,7 @@ const response = await fetch('/api/data') // Backend handles API key authenticat - Promise Handling: Always use `async/await` - Error Handling: Always handle with `try-catch` or Error Boundary - Type Definition: Explicitly define return value types (e.g., `Promise`) +- Effect race/cleanup: guard `useEffect` data fetches against out-of-order responses and post-unmount state updates — abort or ignore stale results (`AbortController` or a mounted flag), or use a server-state library (React Query/SWR) that cancels and dedupes. `try-catch` alone does not cover this **Format Rules** - Semicolon omission (follow Biome settings) @@ -195,10 +203,10 @@ Redact sensitive fields (password, token, apiKey, secret, creditCard) before log ## Performance Optimization -- Component Memoization: Use React.memo for expensive components +- Automatic memoization: when React Compiler is enabled, rely on it; reach for manual `React.memo`/`useMemo`/`useCallback` only as a profiler- or identity-justified escape hatch (a measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - State Optimization: Minimize re-renders with proper state structure -- Lazy Loading: Use React.lazy and Suspense for code splitting -- Bundle Size: Monitor with the `build` script and keep under 500KB +- Lazy Loading: Use `React.lazy` and `Suspense` for code splitting +- Bundle Size: Monitor via the build script against the project's budget ## Non-functional Requirements diff --git a/dev-workflows-fullstack/.claude-plugin/plugin.json b/dev-workflows-fullstack/.claude-plugin/plugin.json index 1e08c00..d9f8517 100644 --- a/dev-workflows-fullstack/.claude-plugin/plugin.json +++ b/dev-workflows-fullstack/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-workflows-fullstack", "description": "Skills + Subagents for fullstack development (backend + React/TypeScript) - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", - "version": "0.20.4", + "version": "0.20.5", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows-fullstack/agents/code-reviewer.md b/dev-workflows-fullstack/agents/code-reviewer.md index 3a875db..d04ca98 100644 --- a/dev-workflows-fullstack/agents/code-reviewer.md +++ b/dev-workflows-fullstack/agents/code-reviewer.md @@ -60,6 +60,7 @@ For each acceptance criterion extracted in Step 1: - For behavior-changing ACs, confirm the evidence covers the boundary paths, not only the main path: where a distinct branch, state, input class, lifecycle step, or fallback governs the behavior, verify it is exercised. Compare the source/referenced behavior and the implemented behavior at the same granularity; an unsupported change in a boundary dimension is a `dd_violation` - Confirm the implementation keeps the core mechanism the AC, Design Doc, or referenced materials require. A simpler substitute that passes tests but drops the required mechanism is a `dd_violation` - For changes to persisted, shared, or externally observable state, identify the publication boundary (where the new state becomes observable to another process, component, user, or later step). State that is observable as complete while still partial, uninitialized, stale, or rollback-only is a `reliability` finding, because a downstream consumer can treat the incomplete state as complete and fail +- When the reviewed change is classified as `bug-fix`, `regression`, `state-change`, or `boundary-change` (the task's `Change Category` field, when present, names the kind), check the cases sharing its path, contract, persisted state, or external boundary. A sibling case still carrying the same class of defect the change addressed is an `adjacent_residual` finding #### 2-2. Identifier Verification @@ -112,6 +113,7 @@ Classify each quality finding into one of: | **maintainability** | Code structure impedes future changes or comprehension | Long functions, deep nesting, multiple responsibilities, unclear naming | | **reliability** | Missing safeguards that could cause runtime failures | Unhandled error paths, missing validation at boundaries, silent failures | | **coverage_gap** | Acceptance criteria lack corresponding test verification | AC fulfilled in code but no test exercises it | +| **adjacent_residual** | A case sharing the change's path, contract, persisted state, or external boundary still carries the class of defect the change addressed | Fallback path left unfixed, sibling state transition still stale, another consumer of a changed contract not updated | Each finding must include a `rationale` field: @@ -121,6 +123,7 @@ Each finding must include a `rationale` field: | **maintainability** | What specific maintenance or comprehension risk this creates | | **reliability** | What failure scenario is unguarded and under what conditions it could occur | | **coverage_gap** | Which AC is untested and why test coverage matters for this specific case | +| **adjacent_residual** | Which adjacent case shares the path/contract/state/boundary and how it still exhibits the defect class | ### 4. Check Architecture Compliance @@ -173,14 +176,14 @@ identifierVerification[].codeValue: string (or "not found") identifierVerification[].location: string (file:line; null if not found) identifierVerification[].match: boolean -qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap") +qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap" | "adjacent_residual") qualityFindings[].location: string (file:line or file:function) qualityFindings[].description: string qualityFindings[].rationale: string (category-specific) qualityFindings[].suggestion: string summary.{acsTotal, acsFulfilled, acsPartial, acsUnfulfilled, identifiersTotal, identifiersMatched, lowConfidenceItems}: number (integer >= 0) -summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap}: number (integer >= 0) +summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap, adjacent_residual}: number (integer >= 0) ``` ### Minimal Shape Example @@ -191,22 +194,14 @@ summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage "identifierMatchRate": 95, "verdict": "needs-improvement", "acceptanceCriteria": [ - { - "item": "User can log in with valid credentials", - "status": "fulfilled", - "confidence": "high", - "location": "src/auth/login.ts:42", - "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], - "gap": null, - "suggestion": null - } + {"item": "User can log in with valid credentials", "status": "fulfilled", "confidence": "high", "location": "src/auth/login.ts:42", "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], "gap": null, "suggestion": null} ], "identifierVerification": [{"identifier": "AUTH_TOKEN_TTL", "designDocValue": "3600", "codeValue": "1800", "location": "src/auth/config.ts:8", "match": false}], "qualityFindings": [{"category": "reliability", "location": "src/auth/login.ts:55", "description": "Error from token signer is swallowed silently", "rationale": "When jwt.sign throws, the catch block returns null without logging", "suggestion": "Re-throw with context or log then propagate"}], "summary": { "acsTotal": 12, "acsFulfilled": 10, "acsPartial": 1, "acsUnfulfilled": 1, "identifiersTotal": 20, "identifiersMatched": 19, "lowConfidenceItems": 2, - "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0 } + "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0, "adjacent_residual": 0 } } } ``` diff --git a/dev-workflows-fullstack/agents/quality-fixer-frontend.md b/dev-workflows-fullstack/agents/quality-fixer-frontend.md index 35a5d14..367ed07 100644 --- a/dev-workflows-fullstack/agents/quality-fixer-frontend.md +++ b/dev-workflows-fullstack/agents/quality-fixer-frontend.md @@ -102,7 +102,7 @@ Return one of the following as the final response (see Output Format for schemas Prefer repository-local component patterns over generic React advice; when patterns coexist for the same concern, follow the dominant one in the changed feature area — the surrounding feature folder, or the nearest parent directory containing siblings using the same concern. Route any new library/pattern decision through the `blocked` output (`reason: "Cannot determine due to unclear specification"`). ### Testing Quality -- **Test Coverage**: 60% baseline; foundational/leaf components (Atomic Design atoms, or reused-across-features components) target 70%, molecules 65%, organisms 60% +- **Test Coverage**: concentrate rigor on foundational/high-reuse units (shared components, hooks, utils); treat coverage as a signal for gaps, not a target. Enforce the project's configured threshold when one exists - **Mock layering**: Use the repository's existing network/API mocking layer for network behavior; browser-primitive doubles (e.g., ResizeObserver, IntersectionObserver, time, router/provider) are acceptable when the test environment requires them; the component under test is exercised through real renders and user interactions - **Query selection**: Prefer role/name queries for user-visible elements; use async queries (`findBy*`, `waitFor`) for async appearance and `queryBy*`/`queryAllBy*` only when asserting intentional absence diff --git a/dev-workflows-fullstack/agents/solver.md b/dev-workflows-fullstack/agents/solver.md index 26d7bae..f947488 100644 --- a/dev-workflows-fullstack/agents/solver.md +++ b/dev-workflows-fullstack/agents/solver.md @@ -71,6 +71,10 @@ Generate at least 3 solutions from the following perspectives: | mitigation | Measures to reduce impact | Temporary measure while waiting for root fix | | fundamental | Comprehensive fix including recurrence prevention | When similar problems have occurred repeatedly | +**Adjacent Case Coverage**: +- When the confirmed failure point concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the failure point itself), evaluate whether cases sharing the same path, contract, persisted state, or external boundary need the same fix +- Include those adjacent cases in the solution scope when they share the same class of defect; record in residualRisks why any are excluded + **Generated Solution Verification**: - Check if project rules have applicable guidelines - For areas without guidelines, research current best practices via WebSearch to verify solutions align with standard approaches @@ -116,24 +120,12 @@ Recommendation strategy based on coverage assessment: }, "solutions": [ { - "id": "S1", - "name": "Solution name", - "type": "direct|workaround|mitigation|fundamental", - "description": "Detailed solution description", - "implementation": { - "approach": "Implementation approach description", - "affectedFiles": ["Files requiring changes"], - "dependencies": ["Affected dependencies"] - }, + "id": "S1", "name": "Solution name", "type": "direct|workaround|mitigation|fundamental", "description": "Detailed solution description", + "implementation": {"approach": "Implementation approach description", "affectedFiles": ["Files requiring changes"], "dependencies": ["Affected dependencies"]}, "tradeoffs": { - "cost": {"level": "low|medium|high", "details": "Details"}, - "risk": {"level": "low|medium|high", "details": "Details"}, - "scope": {"level": "low|medium|high", "details": "Details"}, - "maintainability": {"level": "low|medium|high", "details": "Details"}, - "certainty": {"level": "low|medium|high", "details": "Details"} + "cost": {"level": "low|medium|high", "details": "Details"}, "risk": {"level": "low|medium|high", "details": "Details"}, "scope": {"level": "low|medium|high", "details": "Details"}, "maintainability": {"level": "low|medium|high", "details": "Details"}, "certainty": {"level": "low|medium|high", "details": "Details"} }, - "pros": ["Advantages"], - "cons": ["Disadvantages"] + "pros": ["Advantages"], "cons": ["Disadvantages"] } ], "recommendation": { @@ -144,12 +136,7 @@ Recommendation strategy based on coverage assessment: }, "implementationPlan": { "steps": [ - { - "order": 1, - "action": "Specific action", - "verification": "How to verify this step", - "rollback": "Rollback procedure if problems occur" - } + {"order": 1, "action": "Specific action", "verification": "How to verify this step", "rollback": "Rollback procedure if problems occur"} ], "criticalPoints": ["Points requiring special attention"] }, diff --git a/dev-workflows-fullstack/agents/task-decomposer.md b/dev-workflows-fullstack/agents/task-decomposer.md index 728867e..98a6d24 100644 --- a/dev-workflows-fullstack/agents/task-decomposer.md +++ b/dev-workflows-fullstack/agents/task-decomposer.md @@ -92,6 +92,7 @@ Decompose tasks based on implementation strategy patterns determined in implemen - Task overview - Target files - **Investigation Targets** (what the executor must read and understand before implementing) + - **Change Category** (when the task is a bug fix / regression / state-change / boundary-change — see Change Category Classification below) - Concrete implementation steps - **Quality Assurance Mechanisms** (derived from work plan header — see Quality Assurance Mechanism Propagation below) - **Operation Verification Methods** (derived from Verification Strategy in work plan) @@ -213,6 +214,21 @@ When the work plan contains a Design-to-Plan Traceability table, propagate the m 2. Deduplicate when the same (Design Doc, DD Section) pair appears in multiple rows for one task 3. Apply only when the work plan contains a Design-to-Plan Traceability table +## Change Category Classification + +When a task corrects observed behavior or alters how state or a boundary behaves, classify it so the executor and downstream reviewers run a scoped adjacent-case sweep from the field value, rather than re-inferring the task's intent: + +1. **Classify from the work plan and Design Doc**. A task can match more than one category (e.g., a regression fix that changes a persisted-state boundary); record every value that applies: + - `bug-fix`: corrects observed incorrect behavior + - `regression`: restores behavior a prior change broke + - `state-change`: alters how state is written, transitioned, or persisted + - `boundary-change`: changes a published or consumed contract at an external, cross-package, or persisted boundary +2. **Populate the task's `Change Category` field** with all matched values, comma-separated (see task template). +3. **Extend Investigation Targets with the adjacent cases**. For every matched category, add the files sharing the same path, contract, persisted state, or external boundary as the change — including the owner module on both sides of an affected boundary — so the executor can sweep them for the same class of defect. Union the targets across all matched categories. +4. **Apply only on a match**. Purely additive, config, or scaffolding tasks default to no `Change Category` field and skip this propagation. + +This is distinct from per-AC boundary-path proof (which proves a boundary path *within* an AC): Change Category drives a sweep of cases that sit *outside* the task's ACs but share its path, contract, state, or boundary. + ## Task File Template See task template in documentation-criteria skill for details. @@ -312,6 +328,7 @@ Please execute decomposed tasks according to the order. - [ ] Appropriate granularity (1-5 files/task) - [ ] Investigation Targets specified for every task (specific file paths, not vague categories) - [ ] Proof Obligations recorded for each claim-implementing task (primary failure mode + boundary to exercise) +- [ ] Change Category set for bug-fix / regression / state-change / boundary-change tasks, with adjacent path/boundary owners added to Investigation Targets - [ ] Quality Assurance Mechanisms from work plan header propagated to relevant tasks - [ ] UI Spec Component → Task Mapping rows propagated to matching tasks (when work plan has the table) - [ ] Connection Map boundary rows propagated to matching tasks (when work plan has the table) diff --git a/dev-workflows-fullstack/agents/task-executor-frontend.md b/dev-workflows-fullstack/agents/task-executor-frontend.md index 1af1cef..59ab7cf 100644 --- a/dev-workflows-fullstack/agents/task-executor-frontend.md +++ b/dev-workflows-fullstack/agents/task-executor-frontend.md @@ -139,6 +139,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Duplication Check — Pattern 5 from frontend-ai-guide) Read relevant Design Doc sections accurately; investigate existing implementations (similar components/hooks in same domain/responsibility); determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback rendering, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -209,18 +217,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["src/components/Button/Button.test.tsx"], "requiresTestReview": false, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", - "executed": true, - "command": "test -- Button.test.tsx", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test (React Testing Library) / L2: Integration test / L3: E2E test", "executed": true, "command": "test -- Button.test.tsx", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -235,19 +233,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -260,27 +249,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar component/hook discovered", "taskName": "[Task name being executed]", "similar_components": [ - { - "file_path": "src/components/ExistingButton/ExistingButton.tsx", - "component_name": "ExistingButton", - "similarity_reason": "Same UI pattern, same Props structure", - "code_snippet": "[Excerpt of relevant component code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "src/components/ExistingButton/ExistingButton.tsx", "component_name": "ExistingButton", "similarity_reason": "Same UI pattern, same Props structure", "code_snippet": "[Excerpt of relevant component code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["component keywords", "feature keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["component keywords", "feature keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_component_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing component", - "Refactor existing component then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing component", "Refactor existing component then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing component analysis]" } ``` @@ -294,18 +268,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -319,18 +285,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[library or pattern concern, e.g., routing, server-state, forms]", - "candidatesFound": ["list of coexisting choices found in repository"], - "filesChecked": ["file paths where each choice was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]" - }, + "dependency": {"name": "[library or pattern concern, e.g., routing, server-state, forms]", "candidatesFound": ["list of coexisting choices found in repository"], "filesChecked": ["file paths where each choice was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple choices coexist with no clear majority for the changed feature area]"}, "user_decision_required": true, - "suggested_options": [ - "Follow choice X (dominant in adjacent feature area)", - "Follow choice Y (matches a specific repository convention or constraint)", - "Defer the choice and split the task" - ] + "suggested_options": ["Follow choice X (dominant in adjacent feature area)", "Follow choice Y (matches a specific repository convention or constraint)", "Defer the choice and split the task"] } ``` @@ -342,17 +299,9 @@ Triggered when Reference Representativeness cannot determine the dominant librar "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -369,21 +318,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/dev-workflows-fullstack/agents/task-executor.md b/dev-workflows-fullstack/agents/task-executor.md index b2fa617..fe47c66 100644 --- a/dev-workflows-fullstack/agents/task-executor.md +++ b/dev-workflows-fullstack/agents/task-executor.md @@ -134,6 +134,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Pattern 5 Compliant) Read relevant Design Doc sections (interface contracts, data structures, dependency constraints); investigate existing implementations in the same domain/responsibility; determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback behavior, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -206,18 +214,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["created/test/file/path"], "requiresTestReview": true, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test / L2: Integration test / L3: E2E test", - "executed": true, - "command": "Executed test command", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test / L2: Integration test / L3: E2E test", "executed": true, "command": "Executed test command", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -232,19 +230,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -257,27 +246,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar function discovered", "taskName": "[Task name being executed]", "similar_functions": [ - { - "file_path": "[path to existing implementation]", - "function_name": "existingFunction", - "similarity_reason": "Same domain, same responsibility", - "code_snippet": "[Excerpt of relevant code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "[path to existing implementation]", "function_name": "existingFunction", "similarity_reason": "Same domain, same responsibility", "code_snippet": "[Excerpt of relevant code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["domain keywords", "responsibility keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["domain keywords", "responsibility keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_function_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing function", - "Refactor existing function then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing function", "Refactor existing function then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing code analysis]" } ``` @@ -291,18 +265,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -314,18 +280,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[dependency name]", - "versionsFound": ["list of versions found in repository"], - "filesChecked": ["file paths where dependency was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]" - }, + "dependency": {"name": "[dependency name]", "versionsFound": ["list of versions found in repository"], "filesChecked": ["file paths where dependency was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]"}, "user_decision_required": true, - "suggested_options": [ - "Use version X (majority in repository)", - "Use version Y (specific reason)", - "Research latest stable version and advise" - ] + "suggested_options": ["Use version X (majority in repository)", "Use version Y (specific reason)", "Research latest stable version and advise"] } ``` @@ -337,17 +294,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -364,21 +313,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/dev-workflows-fullstack/agents/verifier.md b/dev-workflows-fullstack/agents/verifier.md index 21986ff..475e056 100644 --- a/dev-workflows-fullstack/agents/verifier.md +++ b/dev-workflows-fullstack/agents/verifier.md @@ -61,7 +61,8 @@ Check the upstream investigation's pathMap for completeness: 1. **Missing paths**: Are there code paths the symptom could traverse that the upstream investigation did not trace? (e.g., error handling branches, async forks, fallback paths) 2. **Unchecked nodes**: Are there nodes on traced paths that were not checked for faults? -3. **Additional failure points**: If missing paths or unchecked nodes reveal new faults, record them +3. **Adjacent cases**: When the investigation concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the investigation itself), are there cases sharing the same path, contract, persisted state, or external boundary that could carry the same fault? Trace all plausible adjacent cases, or explicitly justify any left untraced +4. **Additional failure points**: If missing paths, unchecked nodes, or adjacent cases reveal new faults, record them The goal is to verify that the upstream investigation's path coverage is sufficient. @@ -117,78 +118,33 @@ Evaluate each failure point independently (do NOT select a single "winner"): "identifiedGaps": ["Missing paths or unchecked nodes"] }, "triangulationSupplements": [ - { - "source": "Additional information source investigated", - "findings": "Content discovered", - "impactOnFailurePoints": "Impact on existing failure points" - } + {"source": "Additional information source investigated", "findings": "Content discovered", "impactOnFailurePoints": "Impact on existing failure points"} ], "externalResearch": [ - { - "query": "Search query used", - "source": "Information source", - "findings": "Related information discovered", - "impactOnFailurePoints": "Impact on failure points" - } + {"query": "Search query used", "source": "Information source", "findings": "Related information discovered", "impactOnFailurePoints": "Impact on failure points"} ], "coverageCheck": { "missingPaths": ["Paths not traced by upstream investigation"], "uncheckedNodes": ["Nodes on traced paths that were not checked"], "additionalFailurePoints": [ - { - "id": "AFP1", - "nodeId": "Node reference", - "symptomId": "Symptom reference", - "description": "Newly discovered fault", - "checkStatus": "supported|weakened|blocked|not_reached", - "evidence": [ - {"type": "supporting", "detail": "Evidence detail", "source": "file:line"} - ] - } + {"id": "AFP1", "nodeId": "Node reference", "symptomId": "Symptom reference", "description": "Newly discovered fault", "checkStatus": "supported|weakened|blocked|not_reached", "evidence": [{"type": "supporting", "detail": "Evidence detail", "source": "file:line"}]} ] }, "devilsAdvocateFindings": [ - { - "targetFailurePoint": "FP1", - "alternativeExplanation": "Could this be correct behavior?", - "hiddenAssumptions": ["Implicit assumptions"], - "potentialCounterEvidence": ["Potentially overlooked counter-evidence"] - } + {"targetFailurePoint": "FP1", "alternativeExplanation": "Could this be correct behavior?", "hiddenAssumptions": ["Implicit assumptions"], "potentialCounterEvidence": ["Potentially overlooked counter-evidence"]} ], "failurePointEvaluation": [ - { - "failurePointId": "FP1 or AFP1", - "description": "Failure point description", - "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", - "finalStatus": "supported|weakened|blocked|not_reached", - "statusChangeReason": "Why status changed (if changed)", - "remainingUncertainty": ["Remaining uncertainty"] - } + {"failurePointId": "FP1 or AFP1", "description": "Failure point description", "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", "finalStatus": "supported|weakened|blocked|not_reached", "statusChangeReason": "Why status changed (if changed)", "remainingUncertainty": ["Remaining uncertainty"]} ], "conclusion": { "confirmedFailurePoints": [ - { - "failurePointId": "FP1", - "description": "What the fault is", - "location": "file:line", - "symptomId": "S1", - "symptomExplained": "How this fault leads to the observed symptom", - "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", - "finalStatus": "supported|weakened", - "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], - "impactScope": ["Affected file paths"], - "recurrenceRisk": "low|medium|high" - } + {"failurePointId": "FP1", "description": "What the fault is", "location": "file:line", "symptomId": "S1", "symptomExplained": "How this fault leads to the observed symptom", "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", "finalStatus": "supported|weakened", "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], "impactScope": ["Affected file paths"], "recurrenceRisk": "low|medium|high"} ], "refutedFailurePoints": [ {"failurePointId": "FP2", "reason": "Reason for refutation"} ], "failurePointRelationships": [ - { - "points": ["FP1", "FP3"], - "relationship": "independent|dependent|same_chain", - "detail": "Description of how the failure points relate" - } + {"points": ["FP1", "FP3"], "relationship": "independent|dependent|same_chain", "detail": "Description of how the failure points relate"} ], "coverageAssessment": "sufficient|partial|insufficient", "unresolvedSymptoms": ["Symptoms not fully explained by confirmed failure points"], diff --git a/dev-workflows-fullstack/skills/documentation-criteria/references/task-template.md b/dev-workflows-fullstack/skills/documentation-criteria/references/task-template.md index 28c65c3..6dd3c81 100644 --- a/dev-workflows-fullstack/skills/documentation-criteria/references/task-template.md +++ b/dev-workflows-fullstack/skills/documentation-criteria/references/task-template.md @@ -17,6 +17,13 @@ Metadata: Files to read before starting implementation (file path, with optional search hint): - [e.g., src/orders/checkout (processOrder function) — determined during task decomposition based on task nature] +## Change Category +(Include this field only when the task is a bug fix, regression, state-change, or boundary-change — populated during task decomposition. Omit otherwise.) + +`Change Category: ` + +When present, the implementation sweeps the cases sharing the same path, contract, persisted state, or external boundary for the same class of defect (see Implementation Steps Red Phase). + ## Binding Decisions (Include this section when the work plan's ADR Bindings table covers this task. Omit otherwise.) @@ -32,6 +39,7 @@ Each row is an ADR decision the implementation in this task must comply with. ## Implementation Steps (TDD: Red-Green-Refactor) ### 1. Red Phase - [ ] Read all Investigation Targets and record key observations +- [ ] (When Change Category is set) Sweep the adjacent cases sharing the same path/contract/state/boundary for the same class of defect; fold any found within scope into the failing tests - [ ] Review dependency deliverables (if any) - [ ] Verify/create contract definitions - [ ] Write failing tests diff --git a/dev-workflows-fullstack/skills/frontend-ai-guide/SKILL.md b/dev-workflows-fullstack/skills/frontend-ai-guide/SKILL.md index 8a05065..a20b940 100644 --- a/dev-workflows-fullstack/skills/frontend-ai-guide/SKILL.md +++ b/dev-workflows-fullstack/skills/frontend-ai-guide/SKILL.md @@ -141,7 +141,8 @@ To isolate problems, attempt reproduction with minimal code: - Create minimal configuration that reproduces problem - Use React DevTools to inspect component tree -### 4. Debug Log Output +### 4. Debug Log Output (temporary) +Add structured debug logs to isolate the issue, then remove them before commit (per "Delete debug `console.log()`" in typescript-rules): ```typescript console.log('DEBUG:', { context: 'user-form-submission', @@ -153,38 +154,19 @@ console.log('DEBUG:', { ## Quality Check Workflow -Use the appropriate run command based on the `packageManager` field in package.json. +Read `package.json` scripts and run them with the project's package manager (`packageManager` field). Map the project's actual script names to the phases below — do not assume fixed names. -### Build Commands -- `dev` - Development server -- `build` - Production build -- `preview` - Preview production build -- `type-check` - Type check (no emit) - -### Quality Check Phases - -**Phase 1-3: Basic Checks** -- `check` - Biome (lint + format) -- `build` - TypeScript build - -**Phase 4-5: Tests and Final Confirmation** -- `test` - Test execution -- `test:coverage:fresh` - Coverage measurement (fresh cache) -- `check:all` - Overall integrated check - -### Auxiliary Commands -- `test:coverage` - Run tests with coverage -- `test:safe` - Safe test execution (with auto cleanup) -- `cleanup:processes` - Cleanup Vitest processes -- `format` - Format fixes -- `lint:fix` - Lint fixes -- `open coverage/index.html` - Check coverage report +### Phases (run in order) +1. **Lint/format** — the project's formatter + linter (e.g., Biome, or ESLint + Prettier) +2. **Type check** — type check without emit +3. **Build** — production build +4. **Test** — unit/integration tests +5. **Coverage** — coverage run when the task added or changed behavior ### Troubleshooting -- **Port in use error**: Run `cleanup:processes` script -- **Cache issues**: Run `test:coverage:fresh` script -- **Dependency errors**: Clean reinstall dependencies -- **Vite preview not starting**: Check port 4173 availability +- **Port already in use** — stop the stale dev/preview/test process holding the port +- **Stale cache** — re-run with the project's fresh/clean-cache option +- **Dependency errors** — clean reinstall dependencies ## Situations Requiring Technical Decisions @@ -196,6 +178,7 @@ Use the appropriate run command based on the `packageManager` field in package.j ### Performance vs Readability - Prioritize readability unless React DevTools Profiler identifies a measurable bottleneck (e.g., render time exceeding 16ms, unnecessary re-renders) - Measure before optimizing with React DevTools Profiler +- When React Compiler is enabled, routine memoization is automatic; manual memoization is a profiler- or identity-justified exception (measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - Document reason with comments when optimizing ### Granularity of Component/Type Definitions diff --git a/dev-workflows-fullstack/skills/test-implement/references/frontend.md b/dev-workflows-fullstack/skills/test-implement/references/frontend.md index ff3098f..8f7acff 100644 --- a/dev-workflows-fullstack/skills/test-implement/references/frontend.md +++ b/dev-workflows-fullstack/skills/test-implement/references/frontend.md @@ -12,26 +12,13 @@ ## Basic Testing Policy ### Quality Requirements -- **Coverage**: Unit test coverage must be 60% or higher (Frontend standard 2025) +- **Coverage**: prioritize meaningful assertions on critical paths and high-reuse components; treat coverage as a signal for gaps, not a target. Any threshold is the project's CI config - **Independence**: Each test can run independently without depending on other tests - **Reproducibility**: Tests are environment-independent and always return the same results - **Readability**: Test code maintains the same quality as production code -### Coverage Requirements (ADR-0002 Compliant) -**Component-specific targets**: - -When the project adopts Atomic Design (atoms / molecules / organisms layering): -- Atoms (Button, Text, etc.): 70% or higher -- Molecules (FormField, etc.): 65% or higher -- Organisms (Header, Footer, etc.): 60% or higher - -When the project uses a different component architecture (Feature-based, Container-Presenter, etc.): apply 60% as the baseline and raise the target for foundational/leaf components (those reused across many features) to 70%. - -Component-architecture-independent targets: -- Custom Hooks: 65% or higher -- Utils: 70% or higher - -**Metrics**: Statements, Branches, Functions, Lines +### Where to concentrate test rigor +Test foundational, high-reuse units the hardest — shared components, custom hooks, and utils reused across many features carry the widest blast radius. Higher-composition surfaces (organisms, pages) lean on integration/E2E coverage instead. Any numeric threshold is the project's CI config. ### Test Types and Scope 1. **Unit Tests (React Testing Library)** diff --git a/dev-workflows-fullstack/skills/testing-principles/SKILL.md b/dev-workflows-fullstack/skills/testing-principles/SKILL.md index dd5831f..b6aac8b 100644 --- a/dev-workflows-fullstack/skills/testing-principles/SKILL.md +++ b/dev-workflows-fullstack/skills/testing-principles/SKILL.md @@ -33,12 +33,11 @@ description: Language-agnostic testing principles including TDD, test quality, c ## Quality Requirements -### Coverage Standards +### Coverage -- **Minimum 80% code coverage** for production code -- Prioritize critical paths and business logic -- Prioritize meaningful assertions over coverage percentage -- Use coverage as a guide, not a goal +- Treat coverage as a diagnostic signal for finding untested areas, not a target — a target gets gamed into trivial tests (Goodhart's Law) +- Concentrate tests on critical paths, business logic, and behavior whose regression would matter +- Prioritize meaningful assertions over the coverage number; any CI threshold is the project's config, not a quality goal in itself ### Test Characteristics diff --git a/dev-workflows-fullstack/skills/typescript-rules/SKILL.md b/dev-workflows-fullstack/skills/typescript-rules/SKILL.md index 947ab7b..a47574e 100644 --- a/dev-workflows-fullstack/skills/typescript-rules/SKILL.md +++ b/dev-workflows-fullstack/skills/typescript-rules/SKILL.md @@ -65,6 +65,11 @@ function isUser(value: unknown): value is User { - **Component Hierarchy**: Use the project's adopted component architecture. When the project uses Atomic Design: Atoms → Molecules → Organisms → Templates → Pages. When the project uses Feature-based, Container-Presenter, or another structure: follow that structure consistently and document the chosen layering in the project README or design doc - **Co-location**: Place tests, styles, and related files alongside components +**Server/Client Boundary (RSC frameworks only — e.g., Next.js App Router)** +- Default to server components for data fetching and rendering; isolate interactivity behind a `"use client"` boundary at the smallest scope that needs it +- Keep browser-only APIs (`window`, `localStorage`, event handlers) inside client components; calling them in a server component breaks the render +- N/A for client-only SPAs (e.g., Vite) — skip when the project has no server-component runtime + **State Management Patterns** - **Local State**: `useState` for component-specific state - **Context API**: For sharing state across component tree (theme, auth, etc.) @@ -93,15 +98,17 @@ setUsers(prev => [...prev, newUser]) - Type-safe: Always define Props type explicitly **Environment Variables** -- **Use build tool's environment variable system**: `process.env` does not work in browsers -- Centrally manage environment variables through configuration layer -- Define a typed config object with defaults for every environment variable +- **Use the build tool's env accessor**: read client-side env through the bundler's exposed accessor — Vite via `import.meta.env`, Next.js/CRA via prefixed `process.env`. Raw, unprefixed access is `undefined` in the browser bundle +- **Only prefixed vars reach the client**: build tools expose only vars carrying their public prefix; an unprefixed var is `undefined` in the browser. The prefix differs per tool — match the project's bundler (Vite `VITE_`, Next.js public `NEXT_PUBLIC_`, CRA `REACT_APP_`) +- Centrally manage env through a typed config object with a default for every variable ```typescript -// Use import.meta.env (not process.env — unavailable in browser bundles) +// Client-exposed env must carry the bundler's public prefix, or it is undefined in the browser. +// Vite: import.meta.env.VITE_API_URL +// Next.js: process.env.NEXT_PUBLIC_API_URL const config = { - apiUrl: import.meta.env.API_URL || 'http://localhost:3000', - appName: import.meta.env.APP_NAME || 'My App' + apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000', // adjust accessor + prefix to the project's bundler + appName: import.meta.env.VITE_APP_NAME || 'My App' } ``` @@ -123,6 +130,7 @@ const response = await fetch('/api/data') // Backend handles API key authenticat - Promise Handling: Always use `async/await` - Error Handling: Always handle with `try-catch` or Error Boundary - Type Definition: Explicitly define return value types (e.g., `Promise`) +- Effect race/cleanup: guard `useEffect` data fetches against out-of-order responses and post-unmount state updates — abort or ignore stale results (`AbortController` or a mounted flag), or use a server-state library (React Query/SWR) that cancels and dedupes. `try-catch` alone does not cover this **Format Rules** - Semicolon omission (follow Biome settings) @@ -195,10 +203,10 @@ Redact sensitive fields (password, token, apiKey, secret, creditCard) before log ## Performance Optimization -- Component Memoization: Use React.memo for expensive components +- Automatic memoization: when React Compiler is enabled, rely on it; reach for manual `React.memo`/`useMemo`/`useCallback` only as a profiler- or identity-justified escape hatch (a measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - State Optimization: Minimize re-renders with proper state structure -- Lazy Loading: Use React.lazy and Suspense for code splitting -- Bundle Size: Monitor with the `build` script and keep under 500KB +- Lazy Loading: Use `React.lazy` and `Suspense` for code splitting +- Bundle Size: Monitor via the build script against the project's budget ## Non-functional Requirements diff --git a/dev-workflows/.claude-plugin/plugin.json b/dev-workflows/.claude-plugin/plugin.json index 1a92dc9..4e492da 100644 --- a/dev-workflows/.claude-plugin/plugin.json +++ b/dev-workflows/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dev-workflows", "description": "Skills + Subagents for backend development - Use skills for coding guidance, or run recipe workflows for full orchestrated agentic coding with specialized agents", - "version": "0.20.4", + "version": "0.20.5", "author": { "name": "Shinsuke Kagawa", "url": "https://github.com/shinpr" diff --git a/dev-workflows/agents/code-reviewer.md b/dev-workflows/agents/code-reviewer.md index 3a875db..d04ca98 100644 --- a/dev-workflows/agents/code-reviewer.md +++ b/dev-workflows/agents/code-reviewer.md @@ -60,6 +60,7 @@ For each acceptance criterion extracted in Step 1: - For behavior-changing ACs, confirm the evidence covers the boundary paths, not only the main path: where a distinct branch, state, input class, lifecycle step, or fallback governs the behavior, verify it is exercised. Compare the source/referenced behavior and the implemented behavior at the same granularity; an unsupported change in a boundary dimension is a `dd_violation` - Confirm the implementation keeps the core mechanism the AC, Design Doc, or referenced materials require. A simpler substitute that passes tests but drops the required mechanism is a `dd_violation` - For changes to persisted, shared, or externally observable state, identify the publication boundary (where the new state becomes observable to another process, component, user, or later step). State that is observable as complete while still partial, uninitialized, stale, or rollback-only is a `reliability` finding, because a downstream consumer can treat the incomplete state as complete and fail +- When the reviewed change is classified as `bug-fix`, `regression`, `state-change`, or `boundary-change` (the task's `Change Category` field, when present, names the kind), check the cases sharing its path, contract, persisted state, or external boundary. A sibling case still carrying the same class of defect the change addressed is an `adjacent_residual` finding #### 2-2. Identifier Verification @@ -112,6 +113,7 @@ Classify each quality finding into one of: | **maintainability** | Code structure impedes future changes or comprehension | Long functions, deep nesting, multiple responsibilities, unclear naming | | **reliability** | Missing safeguards that could cause runtime failures | Unhandled error paths, missing validation at boundaries, silent failures | | **coverage_gap** | Acceptance criteria lack corresponding test verification | AC fulfilled in code but no test exercises it | +| **adjacent_residual** | A case sharing the change's path, contract, persisted state, or external boundary still carries the class of defect the change addressed | Fallback path left unfixed, sibling state transition still stale, another consumer of a changed contract not updated | Each finding must include a `rationale` field: @@ -121,6 +123,7 @@ Each finding must include a `rationale` field: | **maintainability** | What specific maintenance or comprehension risk this creates | | **reliability** | What failure scenario is unguarded and under what conditions it could occur | | **coverage_gap** | Which AC is untested and why test coverage matters for this specific case | +| **adjacent_residual** | Which adjacent case shares the path/contract/state/boundary and how it still exhibits the defect class | ### 4. Check Architecture Compliance @@ -173,14 +176,14 @@ identifierVerification[].codeValue: string (or "not found") identifierVerification[].location: string (file:line; null if not found) identifierVerification[].match: boolean -qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap") +qualityFindings[].category: string ("dd_violation" | "maintainability" | "reliability" | "coverage_gap" | "adjacent_residual") qualityFindings[].location: string (file:line or file:function) qualityFindings[].description: string qualityFindings[].rationale: string (category-specific) qualityFindings[].suggestion: string summary.{acsTotal, acsFulfilled, acsPartial, acsUnfulfilled, identifiersTotal, identifiersMatched, lowConfidenceItems}: number (integer >= 0) -summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap}: number (integer >= 0) +summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage_gap, adjacent_residual}: number (integer >= 0) ``` ### Minimal Shape Example @@ -191,22 +194,14 @@ summary.findingsByCategory.{dd_violation, maintainability, reliability, coverage "identifierMatchRate": 95, "verdict": "needs-improvement", "acceptanceCriteria": [ - { - "item": "User can log in with valid credentials", - "status": "fulfilled", - "confidence": "high", - "location": "src/auth/login.ts:42", - "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], - "gap": null, - "suggestion": null - } + {"item": "User can log in with valid credentials", "status": "fulfilled", "confidence": "high", "location": "src/auth/login.ts:42", "evidence": ["impl: src/auth/login.ts:42", "test: src/auth/login.test.ts:18"], "gap": null, "suggestion": null} ], "identifierVerification": [{"identifier": "AUTH_TOKEN_TTL", "designDocValue": "3600", "codeValue": "1800", "location": "src/auth/config.ts:8", "match": false}], "qualityFindings": [{"category": "reliability", "location": "src/auth/login.ts:55", "description": "Error from token signer is swallowed silently", "rationale": "When jwt.sign throws, the catch block returns null without logging", "suggestion": "Re-throw with context or log then propagate"}], "summary": { "acsTotal": 12, "acsFulfilled": 10, "acsPartial": 1, "acsUnfulfilled": 1, "identifiersTotal": 20, "identifiersMatched": 19, "lowConfidenceItems": 2, - "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0 } + "findingsByCategory": { "dd_violation": 1, "maintainability": 0, "reliability": 1, "coverage_gap": 0, "adjacent_residual": 0 } } } ``` diff --git a/dev-workflows/agents/solver.md b/dev-workflows/agents/solver.md index 26d7bae..f947488 100644 --- a/dev-workflows/agents/solver.md +++ b/dev-workflows/agents/solver.md @@ -71,6 +71,10 @@ Generate at least 3 solutions from the following perspectives: | mitigation | Measures to reduce impact | Temporary measure while waiting for root fix | | fundamental | Comprehensive fix including recurrence prevention | When similar problems have occurred repeatedly | +**Adjacent Case Coverage**: +- When the confirmed failure point concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the failure point itself), evaluate whether cases sharing the same path, contract, persisted state, or external boundary need the same fix +- Include those adjacent cases in the solution scope when they share the same class of defect; record in residualRisks why any are excluded + **Generated Solution Verification**: - Check if project rules have applicable guidelines - For areas without guidelines, research current best practices via WebSearch to verify solutions align with standard approaches @@ -116,24 +120,12 @@ Recommendation strategy based on coverage assessment: }, "solutions": [ { - "id": "S1", - "name": "Solution name", - "type": "direct|workaround|mitigation|fundamental", - "description": "Detailed solution description", - "implementation": { - "approach": "Implementation approach description", - "affectedFiles": ["Files requiring changes"], - "dependencies": ["Affected dependencies"] - }, + "id": "S1", "name": "Solution name", "type": "direct|workaround|mitigation|fundamental", "description": "Detailed solution description", + "implementation": {"approach": "Implementation approach description", "affectedFiles": ["Files requiring changes"], "dependencies": ["Affected dependencies"]}, "tradeoffs": { - "cost": {"level": "low|medium|high", "details": "Details"}, - "risk": {"level": "low|medium|high", "details": "Details"}, - "scope": {"level": "low|medium|high", "details": "Details"}, - "maintainability": {"level": "low|medium|high", "details": "Details"}, - "certainty": {"level": "low|medium|high", "details": "Details"} + "cost": {"level": "low|medium|high", "details": "Details"}, "risk": {"level": "low|medium|high", "details": "Details"}, "scope": {"level": "low|medium|high", "details": "Details"}, "maintainability": {"level": "low|medium|high", "details": "Details"}, "certainty": {"level": "low|medium|high", "details": "Details"} }, - "pros": ["Advantages"], - "cons": ["Disadvantages"] + "pros": ["Advantages"], "cons": ["Disadvantages"] } ], "recommendation": { @@ -144,12 +136,7 @@ Recommendation strategy based on coverage assessment: }, "implementationPlan": { "steps": [ - { - "order": 1, - "action": "Specific action", - "verification": "How to verify this step", - "rollback": "Rollback procedure if problems occur" - } + {"order": 1, "action": "Specific action", "verification": "How to verify this step", "rollback": "Rollback procedure if problems occur"} ], "criticalPoints": ["Points requiring special attention"] }, diff --git a/dev-workflows/agents/task-decomposer.md b/dev-workflows/agents/task-decomposer.md index 728867e..98a6d24 100644 --- a/dev-workflows/agents/task-decomposer.md +++ b/dev-workflows/agents/task-decomposer.md @@ -92,6 +92,7 @@ Decompose tasks based on implementation strategy patterns determined in implemen - Task overview - Target files - **Investigation Targets** (what the executor must read and understand before implementing) + - **Change Category** (when the task is a bug fix / regression / state-change / boundary-change — see Change Category Classification below) - Concrete implementation steps - **Quality Assurance Mechanisms** (derived from work plan header — see Quality Assurance Mechanism Propagation below) - **Operation Verification Methods** (derived from Verification Strategy in work plan) @@ -213,6 +214,21 @@ When the work plan contains a Design-to-Plan Traceability table, propagate the m 2. Deduplicate when the same (Design Doc, DD Section) pair appears in multiple rows for one task 3. Apply only when the work plan contains a Design-to-Plan Traceability table +## Change Category Classification + +When a task corrects observed behavior or alters how state or a boundary behaves, classify it so the executor and downstream reviewers run a scoped adjacent-case sweep from the field value, rather than re-inferring the task's intent: + +1. **Classify from the work plan and Design Doc**. A task can match more than one category (e.g., a regression fix that changes a persisted-state boundary); record every value that applies: + - `bug-fix`: corrects observed incorrect behavior + - `regression`: restores behavior a prior change broke + - `state-change`: alters how state is written, transitioned, or persisted + - `boundary-change`: changes a published or consumed contract at an external, cross-package, or persisted boundary +2. **Populate the task's `Change Category` field** with all matched values, comma-separated (see task template). +3. **Extend Investigation Targets with the adjacent cases**. For every matched category, add the files sharing the same path, contract, persisted state, or external boundary as the change — including the owner module on both sides of an affected boundary — so the executor can sweep them for the same class of defect. Union the targets across all matched categories. +4. **Apply only on a match**. Purely additive, config, or scaffolding tasks default to no `Change Category` field and skip this propagation. + +This is distinct from per-AC boundary-path proof (which proves a boundary path *within* an AC): Change Category drives a sweep of cases that sit *outside* the task's ACs but share its path, contract, state, or boundary. + ## Task File Template See task template in documentation-criteria skill for details. @@ -312,6 +328,7 @@ Please execute decomposed tasks according to the order. - [ ] Appropriate granularity (1-5 files/task) - [ ] Investigation Targets specified for every task (specific file paths, not vague categories) - [ ] Proof Obligations recorded for each claim-implementing task (primary failure mode + boundary to exercise) +- [ ] Change Category set for bug-fix / regression / state-change / boundary-change tasks, with adjacent path/boundary owners added to Investigation Targets - [ ] Quality Assurance Mechanisms from work plan header propagated to relevant tasks - [ ] UI Spec Component → Task Mapping rows propagated to matching tasks (when work plan has the table) - [ ] Connection Map boundary rows propagated to matching tasks (when work plan has the table) diff --git a/dev-workflows/agents/task-executor.md b/dev-workflows/agents/task-executor.md index b2fa617..fe47c66 100644 --- a/dev-workflows/agents/task-executor.md +++ b/dev-workflows/agents/task-executor.md @@ -134,6 +134,14 @@ This gate triggers only when the Investigation Targets section lists at least on #### Pre-implementation Verification (Pattern 5 Compliant) Read relevant Design Doc sections (interface contracts, data structures, dependency constraints); investigate existing implementations in the same domain/responsibility; determine continue/escalation per "Mandatory Judgment Criteria" above. +#### Adjacent Case Sweep (Required when the task file has a `Change Category` field set to one or more of `bug-fix`, `regression`, `state-change`, `boundary-change`) + +Runs after Pre-implementation Verification, before the Binding Decision Check. This step fires on the field value the task decomposition wrote — read the field value and treat it as authoritative for whether the sweep applies. + +1. From the Investigation Targets (the decomposition already extended them with the adjacent files), identify the cases sharing the same path, contract, persisted state, or external boundary as the change — fallback behavior, stale state, retries, and external calls related to the change. +2. Check each for the same class of defect this task corrects. +3. Fold adjacent residuals within the Target Files scope into this task's failing tests and implementation. Record any residual outside scope in the task file's Investigation Notes so downstream review (code-reviewer / verifier) can detect it. + #### Binding Decision Check (Required when the task file has a Binding Decisions section) Runs after Pre-implementation Verification, before the TDD cycle. @@ -206,18 +214,8 @@ Report in the following JSON format upon task completion (**without executing qu "testsAdded": ["created/test/file/path"], "requiresTestReview": true, "newTestsPassed": true, - "progressUpdated": { - "taskFile": "5/8 items completed", - "workPlan": "Relevant sections updated", - "designDoc": "Progress section updated or N/A" - }, - "runnableCheck": { - "level": "L1: Unit test / L2: Integration test / L3: E2E test", - "executed": true, - "command": "Executed test command", - "result": "passed / failed / skipped", - "reason": "Test execution reason/verification content" - }, + "progressUpdated": {"taskFile": "5/8 items completed", "workPlan": "Relevant sections updated", "designDoc": "Progress section updated or N/A"}, + "runnableCheck": {"level": "L1: Unit test / L2: Integration test / L3: E2E test", "executed": true, "command": "Executed test command", "result": "passed / failed / skipped", "reason": "Test execution reason/verification content"}, "readyForQualityCheck": true, "nextActions": "Overall quality verification by quality assurance process" } @@ -232,19 +230,10 @@ Report in the following JSON format upon task completion (**without executing qu "status": "escalation_needed", "reason": "Design Doc deviation", "taskName": "[Task name being executed]", - "details": { - "design_doc_expectation": "[Exact quote from relevant Design Doc section]", - "actual_situation": "[Details of situation actually encountered]", - "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", - "attempted_approaches": ["List of solution methods considered for trial"] - }, + "details": {"design_doc_expectation": "[Exact quote from relevant Design Doc section]", "actual_situation": "[Details of situation actually encountered]", "why_cannot_implement": "[Technical reason why cannot implement per Design Doc]", "attempted_approaches": ["List of solution methods considered for trial"]}, "escalation_type": "design_compliance_violation", "user_decision_required": true, - "suggested_options": [ - "Modify Design Doc to match reality", - "Implement missing components first", - "Reconsider requirements and change implementation approach" - ], + "suggested_options": ["Modify Design Doc to match reality", "Implement missing components first", "Reconsider requirements and change implementation approach"], "claude_recommendation": "[Specific proposal for most appropriate solution direction]" } ``` @@ -257,27 +246,12 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Similar function discovered", "taskName": "[Task name being executed]", "similar_functions": [ - { - "file_path": "[path to existing implementation]", - "function_name": "existingFunction", - "similarity_reason": "Same domain, same responsibility", - "code_snippet": "[Excerpt of relevant code]", - "technical_debt_assessment": "high/medium/low/unknown" - } + {"file_path": "[path to existing implementation]", "function_name": "existingFunction", "similarity_reason": "Same domain, same responsibility", "code_snippet": "[Excerpt of relevant code]", "technical_debt_assessment": "high/medium/low/unknown"} ], - "search_details": { - "keywords_used": ["domain keywords", "responsibility keywords"], - "files_searched": 15, - "matches_found": 3 - }, + "search_details": {"keywords_used": ["domain keywords", "responsibility keywords"], "files_searched": 15, "matches_found": 3}, "escalation_type": "similar_function_found", "user_decision_required": true, - "suggested_options": [ - "Extend and use existing function", - "Refactor existing function then use", - "New implementation as technical debt (create ADR)", - "New implementation (clarify differentiation from existing)" - ], + "suggested_options": ["Extend and use existing function", "Refactor existing function then use", "New implementation as technical debt (create ADR)", "New implementation (clarify differentiation from existing)"], "claude_recommendation": "[Recommended approach based on existing code analysis]" } ``` @@ -291,18 +265,10 @@ Report in the following JSON format upon task completion (**without executing qu "taskName": "[Task name being executed]", "escalation_type": "investigation_target_not_found", "missingTargets": [ - { - "path": "[path specified in task file]", - "searchHint": "[section/function hint if provided, or null]", - "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"] - } + {"path": "[path specified in task file]", "searchHint": "[section/function hint if provided, or null]", "searchAttempts": ["Checked path directly", "Searched for similar filenames in same directory"]} ], "user_decision_required": true, - "suggested_options": [ - "Provide correct file path", - "Remove this Investigation Target and proceed", - "Update task file with current paths" - ] + "suggested_options": ["Provide correct file path", "Remove this Investigation Target and proceed", "Update task file with current paths"] } ``` @@ -314,18 +280,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Dependency version uncertain", "taskName": "[Task name being executed]", "escalation_type": "dependency_version_uncertain", - "dependency": { - "name": "[dependency name]", - "versionsFound": ["list of versions found in repository"], - "filesChecked": ["file paths where dependency was found"], - "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]" - }, + "dependency": {"name": "[dependency name]", "versionsFound": ["list of versions found in repository"], "filesChecked": ["file paths where dependency was found"], "ambiguityReason": "[why repository state alone is insufficient — e.g., multiple versions coexist with no clear majority, no existing usage found]"}, "user_decision_required": true, - "suggested_options": [ - "Use version X (majority in repository)", - "Use version Y (specific reason)", - "Research latest stable version and advise" - ] + "suggested_options": ["Use version X (majority in repository)", "Use version Y (specific reason)", "Research latest stable version and advise"] } ``` @@ -337,17 +294,9 @@ Report in the following JSON format upon task completion (**without executing qu "reason": "Out of scope file", "taskName": "[Task name being executed]", "escalation_type": "out_of_scope_file", - "details": { - "file_path": "[path attempted to modify]", - "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], - "modification_reason": "[why modification was attempted]" - }, + "details": {"file_path": "[path attempted to modify]", "allowed_list": ["[union of Target Files entries, task file, work plan, Provides paths]"], "modification_reason": "[why modification was attempted]"}, "user_decision_required": true, - "suggested_options": [ - "Add this file to task Target files and retry", - "Split into a separate task for this file", - "Reconsider the implementation approach to stay within scope" - ] + "suggested_options": ["Add this file to task Target files and retry", "Split into a separate task for this file", "Reconsider the implementation approach to stay within scope"] } ``` @@ -364,21 +313,10 @@ Triggered by `N` at the pre-implementation check, or `N` or `Unknown` at the Exi "phase": "pre_implementation | exit_gate", "plannedApproach": "[1–2 sentence summary of the planned or actual implementation approach]", "failures": [ - { - "source": "[ADR file path with section hint, copied from Source column]", - "axis": "[Axis value copied from the Axis column]", - "decision": "[Decision text, copied from Decision column]", - "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", - "evaluation": "N | Unknown", - "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]" - } + {"source": "[ADR file path with section hint, copied from Source column]", "axis": "[Axis value copied from the Axis column]", "decision": "[Decision text, copied from Decision column]", "complianceCheck": "[Compliance Check predicate, copied from Compliance Check column]", "evaluation": "N | Unknown", "rationale": "[One line explaining why the implementation does not satisfy the check, or why it cannot be evaluated]"} ], "user_decision_required": true, - "suggested_options": [ - "Adjust the implementation plan to satisfy the binding decision", - "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", - "Provide additional context that resolves the Unknown evaluation" - ] + "suggested_options": ["Adjust the implementation plan to satisfy the binding decision", "Update the ADR (then update the work plan's ADR Bindings and this task's Binding Decisions)", "Provide additional context that resolves the Unknown evaluation"] } ``` diff --git a/dev-workflows/agents/verifier.md b/dev-workflows/agents/verifier.md index 21986ff..475e056 100644 --- a/dev-workflows/agents/verifier.md +++ b/dev-workflows/agents/verifier.md @@ -61,7 +61,8 @@ Check the upstream investigation's pathMap for completeness: 1. **Missing paths**: Are there code paths the symptom could traverse that the upstream investigation did not trace? (e.g., error handling branches, async forks, fallback paths) 2. **Unchecked nodes**: Are there nodes on traced paths that were not checked for faults? -3. **Additional failure points**: If missing paths or unchecked nodes reveal new faults, record them +3. **Adjacent cases**: When the investigation concerns a `bug-fix`, `regression`, `state-change`, or `boundary-change` (the debugging flow carries no Change Category field, so judge these from the investigation itself), are there cases sharing the same path, contract, persisted state, or external boundary that could carry the same fault? Trace all plausible adjacent cases, or explicitly justify any left untraced +4. **Additional failure points**: If missing paths, unchecked nodes, or adjacent cases reveal new faults, record them The goal is to verify that the upstream investigation's path coverage is sufficient. @@ -117,78 +118,33 @@ Evaluate each failure point independently (do NOT select a single "winner"): "identifiedGaps": ["Missing paths or unchecked nodes"] }, "triangulationSupplements": [ - { - "source": "Additional information source investigated", - "findings": "Content discovered", - "impactOnFailurePoints": "Impact on existing failure points" - } + {"source": "Additional information source investigated", "findings": "Content discovered", "impactOnFailurePoints": "Impact on existing failure points"} ], "externalResearch": [ - { - "query": "Search query used", - "source": "Information source", - "findings": "Related information discovered", - "impactOnFailurePoints": "Impact on failure points" - } + {"query": "Search query used", "source": "Information source", "findings": "Related information discovered", "impactOnFailurePoints": "Impact on failure points"} ], "coverageCheck": { "missingPaths": ["Paths not traced by upstream investigation"], "uncheckedNodes": ["Nodes on traced paths that were not checked"], "additionalFailurePoints": [ - { - "id": "AFP1", - "nodeId": "Node reference", - "symptomId": "Symptom reference", - "description": "Newly discovered fault", - "checkStatus": "supported|weakened|blocked|not_reached", - "evidence": [ - {"type": "supporting", "detail": "Evidence detail", "source": "file:line"} - ] - } + {"id": "AFP1", "nodeId": "Node reference", "symptomId": "Symptom reference", "description": "Newly discovered fault", "checkStatus": "supported|weakened|blocked|not_reached", "evidence": [{"type": "supporting", "detail": "Evidence detail", "source": "file:line"}]} ] }, "devilsAdvocateFindings": [ - { - "targetFailurePoint": "FP1", - "alternativeExplanation": "Could this be correct behavior?", - "hiddenAssumptions": ["Implicit assumptions"], - "potentialCounterEvidence": ["Potentially overlooked counter-evidence"] - } + {"targetFailurePoint": "FP1", "alternativeExplanation": "Could this be correct behavior?", "hiddenAssumptions": ["Implicit assumptions"], "potentialCounterEvidence": ["Potentially overlooked counter-evidence"]} ], "failurePointEvaluation": [ - { - "failurePointId": "FP1 or AFP1", - "description": "Failure point description", - "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", - "finalStatus": "supported|weakened|blocked|not_reached", - "statusChangeReason": "Why status changed (if changed)", - "remainingUncertainty": ["Remaining uncertainty"] - } + {"failurePointId": "FP1 or AFP1", "description": "Failure point description", "originalCheckStatus": "checkStatus from prior investigation input (null for items discovered during this verification)", "finalStatus": "supported|weakened|blocked|not_reached", "statusChangeReason": "Why status changed (if changed)", "remainingUncertainty": ["Remaining uncertainty"]} ], "conclusion": { "confirmedFailurePoints": [ - { - "failurePointId": "FP1", - "description": "What the fault is", - "location": "file:line", - "symptomId": "S1", - "symptomExplained": "How this fault leads to the observed symptom", - "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", - "finalStatus": "supported|weakened", - "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], - "impactScope": ["Affected file paths"], - "recurrenceRisk": "low|medium|high" - } + {"failurePointId": "FP1", "description": "What the fault is", "location": "file:line", "symptomId": "S1", "symptomExplained": "How this fault leads to the observed symptom", "causeCategory": "typo|logic_error|missing_constraint|design_gap|external_factor", "finalStatus": "supported|weakened", "causalChain": ["Phenomenon", "→ Direct cause", "→ Root cause"], "impactScope": ["Affected file paths"], "recurrenceRisk": "low|medium|high"} ], "refutedFailurePoints": [ {"failurePointId": "FP2", "reason": "Reason for refutation"} ], "failurePointRelationships": [ - { - "points": ["FP1", "FP3"], - "relationship": "independent|dependent|same_chain", - "detail": "Description of how the failure points relate" - } + {"points": ["FP1", "FP3"], "relationship": "independent|dependent|same_chain", "detail": "Description of how the failure points relate"} ], "coverageAssessment": "sufficient|partial|insufficient", "unresolvedSymptoms": ["Symptoms not fully explained by confirmed failure points"], diff --git a/dev-workflows/skills/documentation-criteria/references/task-template.md b/dev-workflows/skills/documentation-criteria/references/task-template.md index 28c65c3..6dd3c81 100644 --- a/dev-workflows/skills/documentation-criteria/references/task-template.md +++ b/dev-workflows/skills/documentation-criteria/references/task-template.md @@ -17,6 +17,13 @@ Metadata: Files to read before starting implementation (file path, with optional search hint): - [e.g., src/orders/checkout (processOrder function) — determined during task decomposition based on task nature] +## Change Category +(Include this field only when the task is a bug fix, regression, state-change, or boundary-change — populated during task decomposition. Omit otherwise.) + +`Change Category: ` + +When present, the implementation sweeps the cases sharing the same path, contract, persisted state, or external boundary for the same class of defect (see Implementation Steps Red Phase). + ## Binding Decisions (Include this section when the work plan's ADR Bindings table covers this task. Omit otherwise.) @@ -32,6 +39,7 @@ Each row is an ADR decision the implementation in this task must comply with. ## Implementation Steps (TDD: Red-Green-Refactor) ### 1. Red Phase - [ ] Read all Investigation Targets and record key observations +- [ ] (When Change Category is set) Sweep the adjacent cases sharing the same path/contract/state/boundary for the same class of defect; fold any found within scope into the failing tests - [ ] Review dependency deliverables (if any) - [ ] Verify/create contract definitions - [ ] Write failing tests diff --git a/dev-workflows/skills/testing-principles/SKILL.md b/dev-workflows/skills/testing-principles/SKILL.md index dd5831f..b6aac8b 100644 --- a/dev-workflows/skills/testing-principles/SKILL.md +++ b/dev-workflows/skills/testing-principles/SKILL.md @@ -33,12 +33,11 @@ description: Language-agnostic testing principles including TDD, test quality, c ## Quality Requirements -### Coverage Standards +### Coverage -- **Minimum 80% code coverage** for production code -- Prioritize critical paths and business logic -- Prioritize meaningful assertions over coverage percentage -- Use coverage as a guide, not a goal +- Treat coverage as a diagnostic signal for finding untested areas, not a target — a target gets gamed into trivial tests (Goodhart's Law) +- Concentrate tests on critical paths, business logic, and behavior whose regression would matter +- Prioritize meaningful assertions over the coverage number; any CI threshold is the project's config, not a quality goal in itself ### Test Characteristics diff --git a/package.json b/package.json index a488260..80fa223 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-code-workflows", - "version": "0.20.4", + "version": "0.20.5", "private": true, "type": "module", "engines": { diff --git a/skills/documentation-criteria/references/task-template.md b/skills/documentation-criteria/references/task-template.md index 28c65c3..6dd3c81 100644 --- a/skills/documentation-criteria/references/task-template.md +++ b/skills/documentation-criteria/references/task-template.md @@ -17,6 +17,13 @@ Metadata: Files to read before starting implementation (file path, with optional search hint): - [e.g., src/orders/checkout (processOrder function) — determined during task decomposition based on task nature] +## Change Category +(Include this field only when the task is a bug fix, regression, state-change, or boundary-change — populated during task decomposition. Omit otherwise.) + +`Change Category: ` + +When present, the implementation sweeps the cases sharing the same path, contract, persisted state, or external boundary for the same class of defect (see Implementation Steps Red Phase). + ## Binding Decisions (Include this section when the work plan's ADR Bindings table covers this task. Omit otherwise.) @@ -32,6 +39,7 @@ Each row is an ADR decision the implementation in this task must comply with. ## Implementation Steps (TDD: Red-Green-Refactor) ### 1. Red Phase - [ ] Read all Investigation Targets and record key observations +- [ ] (When Change Category is set) Sweep the adjacent cases sharing the same path/contract/state/boundary for the same class of defect; fold any found within scope into the failing tests - [ ] Review dependency deliverables (if any) - [ ] Verify/create contract definitions - [ ] Write failing tests diff --git a/skills/frontend-ai-guide/SKILL.md b/skills/frontend-ai-guide/SKILL.md index 8a05065..a20b940 100644 --- a/skills/frontend-ai-guide/SKILL.md +++ b/skills/frontend-ai-guide/SKILL.md @@ -141,7 +141,8 @@ To isolate problems, attempt reproduction with minimal code: - Create minimal configuration that reproduces problem - Use React DevTools to inspect component tree -### 4. Debug Log Output +### 4. Debug Log Output (temporary) +Add structured debug logs to isolate the issue, then remove them before commit (per "Delete debug `console.log()`" in typescript-rules): ```typescript console.log('DEBUG:', { context: 'user-form-submission', @@ -153,38 +154,19 @@ console.log('DEBUG:', { ## Quality Check Workflow -Use the appropriate run command based on the `packageManager` field in package.json. +Read `package.json` scripts and run them with the project's package manager (`packageManager` field). Map the project's actual script names to the phases below — do not assume fixed names. -### Build Commands -- `dev` - Development server -- `build` - Production build -- `preview` - Preview production build -- `type-check` - Type check (no emit) - -### Quality Check Phases - -**Phase 1-3: Basic Checks** -- `check` - Biome (lint + format) -- `build` - TypeScript build - -**Phase 4-5: Tests and Final Confirmation** -- `test` - Test execution -- `test:coverage:fresh` - Coverage measurement (fresh cache) -- `check:all` - Overall integrated check - -### Auxiliary Commands -- `test:coverage` - Run tests with coverage -- `test:safe` - Safe test execution (with auto cleanup) -- `cleanup:processes` - Cleanup Vitest processes -- `format` - Format fixes -- `lint:fix` - Lint fixes -- `open coverage/index.html` - Check coverage report +### Phases (run in order) +1. **Lint/format** — the project's formatter + linter (e.g., Biome, or ESLint + Prettier) +2. **Type check** — type check without emit +3. **Build** — production build +4. **Test** — unit/integration tests +5. **Coverage** — coverage run when the task added or changed behavior ### Troubleshooting -- **Port in use error**: Run `cleanup:processes` script -- **Cache issues**: Run `test:coverage:fresh` script -- **Dependency errors**: Clean reinstall dependencies -- **Vite preview not starting**: Check port 4173 availability +- **Port already in use** — stop the stale dev/preview/test process holding the port +- **Stale cache** — re-run with the project's fresh/clean-cache option +- **Dependency errors** — clean reinstall dependencies ## Situations Requiring Technical Decisions @@ -196,6 +178,7 @@ Use the appropriate run command based on the `packageManager` field in package.j ### Performance vs Readability - Prioritize readability unless React DevTools Profiler identifies a measurable bottleneck (e.g., render time exceeding 16ms, unnecessary re-renders) - Measure before optimizing with React DevTools Profiler +- When React Compiler is enabled, routine memoization is automatic; manual memoization is a profiler- or identity-justified exception (measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - Document reason with comments when optimizing ### Granularity of Component/Type Definitions diff --git a/skills/test-implement/references/frontend.md b/skills/test-implement/references/frontend.md index ff3098f..8f7acff 100644 --- a/skills/test-implement/references/frontend.md +++ b/skills/test-implement/references/frontend.md @@ -12,26 +12,13 @@ ## Basic Testing Policy ### Quality Requirements -- **Coverage**: Unit test coverage must be 60% or higher (Frontend standard 2025) +- **Coverage**: prioritize meaningful assertions on critical paths and high-reuse components; treat coverage as a signal for gaps, not a target. Any threshold is the project's CI config - **Independence**: Each test can run independently without depending on other tests - **Reproducibility**: Tests are environment-independent and always return the same results - **Readability**: Test code maintains the same quality as production code -### Coverage Requirements (ADR-0002 Compliant) -**Component-specific targets**: - -When the project adopts Atomic Design (atoms / molecules / organisms layering): -- Atoms (Button, Text, etc.): 70% or higher -- Molecules (FormField, etc.): 65% or higher -- Organisms (Header, Footer, etc.): 60% or higher - -When the project uses a different component architecture (Feature-based, Container-Presenter, etc.): apply 60% as the baseline and raise the target for foundational/leaf components (those reused across many features) to 70%. - -Component-architecture-independent targets: -- Custom Hooks: 65% or higher -- Utils: 70% or higher - -**Metrics**: Statements, Branches, Functions, Lines +### Where to concentrate test rigor +Test foundational, high-reuse units the hardest — shared components, custom hooks, and utils reused across many features carry the widest blast radius. Higher-composition surfaces (organisms, pages) lean on integration/E2E coverage instead. Any numeric threshold is the project's CI config. ### Test Types and Scope 1. **Unit Tests (React Testing Library)** diff --git a/skills/testing-principles/SKILL.md b/skills/testing-principles/SKILL.md index dd5831f..b6aac8b 100644 --- a/skills/testing-principles/SKILL.md +++ b/skills/testing-principles/SKILL.md @@ -33,12 +33,11 @@ description: Language-agnostic testing principles including TDD, test quality, c ## Quality Requirements -### Coverage Standards +### Coverage -- **Minimum 80% code coverage** for production code -- Prioritize critical paths and business logic -- Prioritize meaningful assertions over coverage percentage -- Use coverage as a guide, not a goal +- Treat coverage as a diagnostic signal for finding untested areas, not a target — a target gets gamed into trivial tests (Goodhart's Law) +- Concentrate tests on critical paths, business logic, and behavior whose regression would matter +- Prioritize meaningful assertions over the coverage number; any CI threshold is the project's config, not a quality goal in itself ### Test Characteristics diff --git a/skills/typescript-rules/SKILL.md b/skills/typescript-rules/SKILL.md index 947ab7b..a47574e 100644 --- a/skills/typescript-rules/SKILL.md +++ b/skills/typescript-rules/SKILL.md @@ -65,6 +65,11 @@ function isUser(value: unknown): value is User { - **Component Hierarchy**: Use the project's adopted component architecture. When the project uses Atomic Design: Atoms → Molecules → Organisms → Templates → Pages. When the project uses Feature-based, Container-Presenter, or another structure: follow that structure consistently and document the chosen layering in the project README or design doc - **Co-location**: Place tests, styles, and related files alongside components +**Server/Client Boundary (RSC frameworks only — e.g., Next.js App Router)** +- Default to server components for data fetching and rendering; isolate interactivity behind a `"use client"` boundary at the smallest scope that needs it +- Keep browser-only APIs (`window`, `localStorage`, event handlers) inside client components; calling them in a server component breaks the render +- N/A for client-only SPAs (e.g., Vite) — skip when the project has no server-component runtime + **State Management Patterns** - **Local State**: `useState` for component-specific state - **Context API**: For sharing state across component tree (theme, auth, etc.) @@ -93,15 +98,17 @@ setUsers(prev => [...prev, newUser]) - Type-safe: Always define Props type explicitly **Environment Variables** -- **Use build tool's environment variable system**: `process.env` does not work in browsers -- Centrally manage environment variables through configuration layer -- Define a typed config object with defaults for every environment variable +- **Use the build tool's env accessor**: read client-side env through the bundler's exposed accessor — Vite via `import.meta.env`, Next.js/CRA via prefixed `process.env`. Raw, unprefixed access is `undefined` in the browser bundle +- **Only prefixed vars reach the client**: build tools expose only vars carrying their public prefix; an unprefixed var is `undefined` in the browser. The prefix differs per tool — match the project's bundler (Vite `VITE_`, Next.js public `NEXT_PUBLIC_`, CRA `REACT_APP_`) +- Centrally manage env through a typed config object with a default for every variable ```typescript -// Use import.meta.env (not process.env — unavailable in browser bundles) +// Client-exposed env must carry the bundler's public prefix, or it is undefined in the browser. +// Vite: import.meta.env.VITE_API_URL +// Next.js: process.env.NEXT_PUBLIC_API_URL const config = { - apiUrl: import.meta.env.API_URL || 'http://localhost:3000', - appName: import.meta.env.APP_NAME || 'My App' + apiUrl: import.meta.env.VITE_API_URL || 'http://localhost:3000', // adjust accessor + prefix to the project's bundler + appName: import.meta.env.VITE_APP_NAME || 'My App' } ``` @@ -123,6 +130,7 @@ const response = await fetch('/api/data') // Backend handles API key authenticat - Promise Handling: Always use `async/await` - Error Handling: Always handle with `try-catch` or Error Boundary - Type Definition: Explicitly define return value types (e.g., `Promise`) +- Effect race/cleanup: guard `useEffect` data fetches against out-of-order responses and post-unmount state updates — abort or ignore stale results (`AbortController` or a mounted flag), or use a server-state library (React Query/SWR) that cancels and dedupes. `try-catch` alone does not cover this **Format Rules** - Semicolon omission (follow Biome settings) @@ -195,10 +203,10 @@ Redact sensitive fields (password, token, apiKey, secret, creditCard) before log ## Performance Optimization -- Component Memoization: Use React.memo for expensive components +- Automatic memoization: when React Compiler is enabled, rely on it; reach for manual `React.memo`/`useMemo`/`useCallback` only as a profiler- or identity-justified escape hatch (a measured bottleneck, or stable reference identity for third-party APIs / effect dependencies) - State Optimization: Minimize re-renders with proper state structure -- Lazy Loading: Use React.lazy and Suspense for code splitting -- Bundle Size: Monitor with the `build` script and keep under 500KB +- Lazy Loading: Use `React.lazy` and `Suspense` for code splitting +- Bundle Size: Monitor via the build script against the project's budget ## Non-functional Requirements