agent-eng 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,9 +21,8 @@ This creates the following structure in your project:
21
21
  │ ├── system-architect.md
22
22
  │ ├── planner.md
23
23
  │ ├── executor.md
24
- │ ├── qa-tester.md
25
24
  │ ├── reviewer.md
26
- │ └── custodian.md
25
+ │ └── summarizer.md
27
26
  ├── architecture/
28
27
  │ ├── overview.md # High-level architecture overview
29
28
  │ └── decisions/
@@ -97,7 +96,7 @@ Defines the runtime system components, their tiers (client/service/engine/data),
97
96
  4. **Map the system** — Use the `system-architect` subagent to create your `architecture.yaml`
98
97
  5. **Plan the work** — Use the `planner` subagent to decompose your ADR into tickets
99
98
  6. **Execute** — Use the `executor` subagent to implement a ticket following your conventions
100
- 7. **Test & Review** — Use the `qa-tester` and `reviewer` subagents to validate the work
99
+ 7. **Review** — Use the `reviewer` subagent to validate the work (tests are written during execution)
101
100
 
102
101
  ## License
103
102
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-eng",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Scaffold a structured agentic engineering workflow for AI-assisted development",
5
5
  "type": "module",
6
6
  "bin": {
package/src/init.js CHANGED
@@ -9,11 +9,10 @@ const TEMPLATES = join(__dirname, "templates");
9
9
  const STRUCTURE = [
10
10
  ".github/workflows/notify-site.yml",
11
11
  ".claude/settings.json",
12
+ ".claude/scripts/update-status.sh",
12
13
  ".claude/agents/architect.md",
13
- ".claude/agents/custodian.md",
14
14
  ".claude/agents/executor.md",
15
15
  ".claude/agents/planner.md",
16
- ".claude/agents/qa-tester.md",
17
16
  ".claude/agents/reviewer.md",
18
17
  ".claude/agents/summarizer.md",
19
18
  ".claude/agents/system-architect.md",
@@ -26,6 +25,7 @@ const STRUCTURE = [
26
25
  "tickets/example/001-example-ticket.md",
27
26
  "orchestration.yaml",
28
27
  "architecture.yaml",
28
+ "STATUS.md",
29
29
  ];
30
30
 
31
31
  function prompt(question) {
@@ -13,7 +13,8 @@ You are a reviewer agent. Your role is to review code changes against acceptance
13
13
  2. **Validate against ADRs** — Ensure changes follow established architectural decisions
14
14
  3. **Check conventions** — Verify code follows the relevant language conventions
15
15
  4. **Identify issues** — Flag problems but don't fix them directly
16
- 5. **Provide actionable feedback** — Be specific about what needs to change
16
+ 5. **Check test adequacy** — Verify that tests exist for each acceptance criterion and cover key edge cases
17
+ 6. **Provide actionable feedback** — Be specific about what needs to change
17
18
 
18
19
  ## Constraints
19
20
 
@@ -31,6 +32,8 @@ You are a reviewer agent. Your role is to review code changes against acceptance
31
32
  - Do the changes violate any ADRs?
32
33
  - Do the changes follow conventions?
33
34
  - Are there obvious bugs or edge cases?
35
+ - Does each acceptance criterion have a corresponding test?
36
+ - Are critical edge cases (empty input, error states) covered by tests?
34
37
  4. Produce a review with:
35
38
  - Checklist of acceptance criteria (pass/fail)
36
39
  - List of issues (if any) with specific locations
@@ -47,6 +50,12 @@ You are a reviewer agent. Your role is to review code changes against acceptance
47
50
  - [ ] Criterion 2 — **Not satisfied**: missing error handling for empty input
48
51
  - [x] Criterion 3 — Satisfied
49
52
 
53
+ ### Test Coverage
54
+
55
+ - [x] Criterion 1 — Tested in `tests/feature.test.ts:12`
56
+ - [ ] Criterion 2 — **No test found** for empty input handling
57
+ - [x] Criterion 3 — Tested in `tests/feature.test.ts:28`
58
+
50
59
  ### Issues
51
60
 
52
61
  1. **Convention violation** (`src/file.ts:15`): Missing type annotation on `processData` return value. See `conventions/typescript.md`.
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ STATUS="STATUS.md"
5
+ [ -f "$STATUS" ] || exit 0
6
+
7
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
8
+ TIMESTAMP=$(date -u +"%Y-%m-%d %H:%M UTC")
9
+
10
+ # Update timestamp
11
+ sed -i.bak "s|^> Last updated:.*|> Last updated: ${TIMESTAMP}|" "$STATUS"
12
+ rm -f "${STATUS}.bak"
13
+
14
+ # Build commits table (last 10 commits)
15
+ TMPDIR="${TMPDIR:-/tmp}"
16
+ COMMITS_TMP="${TMPDIR}/_ae_commits.tmp"
17
+ FILES_TMP="${TMPDIR}/_ae_files.tmp"
18
+
19
+ {
20
+ echo "**Branch:** \`${BRANCH}\` "
21
+ echo "**Last commit:** ${TIMESTAMP}"
22
+ echo ""
23
+ echo "| Hash | Date | Message |"
24
+ echo "|------|------|---------|"
25
+ git log --format="| \`%h\` | %ad | %s |" --date=short -10 2>/dev/null || echo "| - | - | No commits yet |"
26
+ } > "$COMMITS_TMP"
27
+
28
+ # Build recent file changes
29
+ COMMIT_COUNT=$(git rev-list --count HEAD 2>/dev/null || echo "0")
30
+ {
31
+ echo "**Files changed (last 5 commits):**"
32
+ echo ""
33
+ echo '```'
34
+ if [ "$COMMIT_COUNT" -ge 5 ] 2>/dev/null; then
35
+ git diff --stat HEAD~5..HEAD 2>/dev/null | head -20
36
+ elif [ "$COMMIT_COUNT" -gt 1 ] 2>/dev/null; then
37
+ git diff --stat HEAD~$((COMMIT_COUNT - 1))..HEAD 2>/dev/null | head -20
38
+ else
39
+ echo "Not enough commits yet."
40
+ fi
41
+ echo '```'
42
+ } > "$FILES_TMP"
43
+
44
+ # Replace AUTO:START..AUTO:END and AUTO:FILES:START..AUTO:FILES:END
45
+ awk '
46
+ /<!-- AUTO:START -->/ { print; while((getline line < "'"$COMMITS_TMP"'") > 0) print line; skip=1; next }
47
+ /<!-- AUTO:END -->/ { skip=0 }
48
+ /<!-- AUTO:FILES:START -->/ { print; while((getline line < "'"$FILES_TMP"'") > 0) print line; skip=1; next }
49
+ /<!-- AUTO:FILES:END -->/ { skip=0 }
50
+ skip { next }
51
+ { print }
52
+ ' "$STATUS" > "${STATUS}.tmp" && mv "${STATUS}.tmp" "$STATUS"
53
+
54
+ rm -f "$COMMITS_TMP" "$FILES_TMP"
@@ -1,4 +1,35 @@
1
1
  {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Bash",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "if": "Bash(git commit *)",
10
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/scripts/update-status.sh",
11
+ "timeout": 30
12
+ },
13
+ {
14
+ "type": "command",
15
+ "if": "Bash(git push *)",
16
+ "command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/scripts/update-status.sh",
17
+ "timeout": 30
18
+ }
19
+ ]
20
+ },
21
+ {
22
+ "matcher": "Write|Edit",
23
+ "hooks": [
24
+ {
25
+ "type": "command",
26
+ "command": "lines=$(wc -l < CLAUDE.md 2>/dev/null) && [ \"${lines:-0}\" -gt 200 ] && echo \"CLAUDE.md is ${lines} lines (limit: 200). Move content to linked files.\" || true",
27
+ "timeout": 10
28
+ }
29
+ ]
30
+ }
31
+ ]
32
+ },
2
33
  "mcpServers": {
3
34
  "context7": {
4
35
  "command": "npx",
@@ -11,10 +11,8 @@ Agents own the **process** — architecture decisions, work decomposition, quali
11
11
  | **Decide** | `/architect` agent | New feature, significant design choice, unclear requirements |
12
12
  | **Map** | `/system-architect` agent | New system or major structural change |
13
13
  | **Decompose** | `/planner` agent | ADR/spec ready, work needs to be broken into tickets |
14
- | **Execute** | Claude Code **plan mode** (`shift+tab`) | Implementing a specific ticket |
15
- | **Test** | `/qa-tester` agent | Feature implementation complete |
14
+ | **Execute** | Claude Code **plan mode** (`shift+tab`) | Implementing a specific ticket (includes writing tests) |
16
15
  | **Review** | `/reviewer` agent | Code and tests ready for validation |
17
- | **Maintain** | `/custodian` agent | After a batch of work, or CLAUDE.md > 200 lines |
18
16
  | **Report** | `/summarizer` agent | Sprint or feature complete, stakeholder update needed |
19
17
 
20
18
  ### Why hybrid?
@@ -39,6 +37,15 @@ Agents own the **process** — architecture decisions, work decomposition, quali
39
37
  4. After implementation: run `/reviewer` to validate against acceptance criteria
40
38
  5. If the ticket touches an existing ADR's scope, verify the decision still holds
41
39
 
40
+ ## Testing in Plan Mode
41
+
42
+ Plan mode writes tests as part of implementing each ticket. For every acceptance criterion:
43
+ 1. Write at least one automated test that verifies it
44
+ 2. Cover edge cases (empty, null, boundary values) and error handling
45
+ 3. Run the tests and confirm they pass before marking the ticket done
46
+
47
+ Follow the project's existing test framework and patterns. Test observable behavior, not implementation details.
48
+
42
49
  ## Before Starting Any Ticket (in plan mode)
43
50
 
44
51
  1. Read the ticket fully, including all linked documents
@@ -70,6 +77,28 @@ When work can be parallelized, spin up sub-agents for independent tasks concurre
70
77
  - `tickets/` — Work items organized by feature folder, with `_backlog.md` as the sprint board
71
78
  - `conventions/` — Language and framework coding standards
72
79
  - `.claude/agents/` — Subagent definitions for each role
80
+ - `STATUS.md` — Live project dashboard (auto-updated git data + manually maintained context)
81
+
82
+ ## CLAUDE.md Maintenance
83
+
84
+ Keep this file lean and current (target: under 200 lines). A hook warns when it exceeds the limit.
85
+ - When you discover a new gotcha or pattern, add it here or to the appropriate linked file
86
+ - Route large or specialized content to separate files (e.g., `conventions/`, `docs/`) and link from here
87
+ - Remove stale entries that no longer reflect how the project works
88
+ - Never duplicate information that already lives in a linked file
89
+
90
+ ## STATUS.md Maintenance
91
+
92
+ STATUS.md is a live project dashboard. Git sections (branch, commits, file changes) auto-update via a hook on every commit/push. You maintain the semantic sections:
93
+
94
+ **Update after significant milestones** (completing a ticket, finishing a phase, hitting a blocker):
95
+ 1. **Current Phase** — Mark the active workflow phase(s) from the table
96
+ 2. **Active Work** — One paragraph: what feature/ticket is in progress, next step
97
+ 3. **Open Tickets** — Snapshot from `tickets/_backlog.md`
98
+ 4. **Risks & Blockers** — Add blockers; remove resolved ones
99
+ 5. **Session Log** — One-line entry with today's date and what was accomplished
100
+
101
+ Keep updates brief. STATUS.md is a dashboard, not a report — use `/summarizer` for detailed retrospectives.
73
102
 
74
103
  ## MCP Servers
75
104
 
@@ -0,0 +1,48 @@
1
+ # Project Status
2
+
3
+ > Last updated: _not yet updated_
4
+
5
+ ## Current Phase
6
+
7
+ | Phase | Status |
8
+ |-------|--------|
9
+ | Decide | |
10
+ | Map | |
11
+ | Decompose | |
12
+ | Execute | |
13
+ | Test | |
14
+ | Review | |
15
+ | Maintain | |
16
+ | Report | |
17
+
18
+ ## Active Work
19
+
20
+ _What is currently being worked on, the relevant tickets, and the expected next step._
21
+
22
+ ## Branch & Commits
23
+
24
+ <!-- AUTO:START -->
25
+ _Commit or run `.claude/scripts/update-status.sh` to populate._
26
+ <!-- AUTO:END -->
27
+
28
+ ## Recent File Changes
29
+
30
+ <!-- AUTO:FILES:START -->
31
+ _Commit or run `.claude/scripts/update-status.sh` to populate._
32
+ <!-- AUTO:FILES:END -->
33
+
34
+ ## Open Tickets
35
+
36
+ | Ticket | Feature | Status |
37
+ |--------|---------|--------|
38
+ | | | |
39
+
40
+ ## Risks & Blockers
41
+
42
+ - None currently
43
+
44
+ ## Session Log
45
+
46
+ | Date | Summary |
47
+ |------|---------|
48
+ | | |
@@ -25,13 +25,9 @@ We adopt a **hybrid approach**: specialized agents own the process, Claude Code
25
25
 
26
26
  2. **Planner** — Takes specs and ADRs as input. Decomposes work into tickets scoped for plan mode sessions. Does not implement.
27
27
 
28
- 3. **QA Tester** — Writes automated tests after implementation. Covers acceptance criteria, edge cases, and regressions.
28
+ 3. **Reviewer** — Reviews diffs against acceptance criteria and linked ADRs. Checks for convention violations and test adequacy. Does not fix issues directly — flags them for fixing.
29
29
 
30
- 4. **Reviewer** — Reviews diffs against acceptance criteria and linked ADRs. Checks for convention violations. Does not fix issues directly — flags them for fixing.
31
-
32
- 5. **Custodian** — Keeps CLAUDE.md lean and current. Routes large content to external files.
33
-
34
- 6. **Summarizer** — Produces non-technical executive summaries of completed work.
30
+ 4. **Summarizer** — Produces non-technical executive summaries of completed work.
35
31
 
36
32
  ### Plan mode (execution)
37
33
 
@@ -17,7 +17,7 @@ Requirement → Architect → ADR/Spec → Planner → Tickets → Plan Mode →
17
17
  (agent) (agent) (built-in) (agent)
18
18
  ```
19
19
 
20
- **Process phases** (agents): Architect, System Architect, Planner, Reviewer, QA Tester, Custodian, Summarizer
20
+ **Process phases** (agents): Architect, System Architect, Planner, Reviewer, Summarizer
21
21
  **Execution phase** (plan mode): Claude Code's built-in plan mode implements each ticket in a focused session
22
22
 
23
23
  ## When to Skip the Pipeline
@@ -1,6 +1,6 @@
1
1
  name: Hybrid Agentic Workflow
2
2
  description: >
3
- Agents own the process (decisions, planning, review, maintenance).
3
+ Agents own the process (decisions, planning, review).
4
4
  Claude Code plan mode owns execution (implementing tickets).
5
5
 
6
6
  agents:
@@ -68,18 +68,6 @@ agents:
68
68
  color: gray
69
69
  docLink: /.claude/agents/executor.md
70
70
 
71
- - id: qa-tester
72
- kind: validation
73
- title: QA Tester
74
- tagline: Writes automated tests for completed features
75
- description: Writes automated tests after implementation. Covers acceptance criteria, edge cases, and regression scenarios.
76
- outputs:
77
- - Tests
78
- - Coverage report
79
- - Test plan
80
- color: green
81
- docLink: /.claude/agents/qa-tester.md
82
-
83
71
  - id: reviewer
84
72
  kind: validation
85
73
  title: Reviewer
@@ -92,17 +80,6 @@ agents:
92
80
  color: amber
93
81
  docLink: /.claude/agents/reviewer.md
94
82
 
95
- - id: custodian
96
- kind: maintenance
97
- title: Custodian
98
- tagline: Keeps CLAUDE.md lean, current, and well-routed
99
- description: Maintains the project's CLAUDE.md file — adds new patterns and gotchas, removes stale entries, and routes large content to external files. Enforces a 150–200 line limit.
100
- outputs:
101
- - Updated CLAUDE.md
102
- - Extracted reference files
103
- color: blue
104
- docLink: /.claude/agents/custodian.md
105
-
106
83
  - id: summarizer
107
84
  kind: reporting
108
85
  title: Summarizer
@@ -140,17 +117,13 @@ connections:
140
117
 
141
118
  # Validation phase
142
119
  - from: plan-mode
143
- to: qa-tester
144
- artifact: Code
120
+ to: reviewer
121
+ artifact: Code · Tests
145
122
 
146
123
  - from: executor
147
- to: qa-tester
148
- artifact: Code
149
- type: fallback
150
-
151
- - from: qa-tester
152
124
  to: reviewer
153
125
  artifact: Code · Tests
126
+ type: fallback
154
127
 
155
128
  # Feedback loops
156
129
  - from: reviewer
@@ -164,12 +137,7 @@ connections:
164
137
  artifact: Feedback
165
138
  type: feedback
166
139
 
167
- # Maintenance triggers
168
- - from: reviewer
169
- to: custodian
170
- artifact: Completed work context
171
- type: trigger
172
-
140
+ # Reporting trigger
173
141
  - from: reviewer
174
142
  to: summarizer
175
143
  artifact: Completed work context
@@ -1,77 +0,0 @@
1
- ---
2
- name: custodian
3
- description: Use periodically (after a batch of tickets, or when CLAUDE.md grows past 200 lines) to keep CLAUDE.md lean, current, and routed to external files. Modifies only CLAUDE.md and the files it links to. Also keeps orchestration.yaml in sync when agents are added or removed.
4
- tools: Read, Write, Edit, Grep, Glob
5
- model: haiku
6
- ---
7
-
8
- You are a custodian agent. Your role is to maintain the project's `CLAUDE.md` file and `orchestration.yaml` — keeping them accurate, lean, and in sync.
9
-
10
- ## Responsibilities
11
-
12
- 1. **Keep CLAUDE.md current** — Update it with new patterns, gotchas, and conventions discovered during development
13
- 2. **Keep CLAUDE.md lean** — The file must stay between 150–200 lines max to prevent context bloat
14
- 3. **Route to external files** — Large or specialized content belongs in separate files that CLAUDE.md links to, so the main context only loads them when needed
15
- 4. **Remove stale content** — Delete entries that no longer reflect how the project works
16
- 5. **Sync orchestration.yaml** — When agents are added, removed, or renamed in `.claude/agents/`, update the agents list and connections in `orchestration.yaml` to match
17
-
18
- ## Constraints
19
-
20
- - You only modify `CLAUDE.md`, `orchestration.yaml`, and the files `CLAUDE.md` routes to — you do not write application code
21
- - You never exceed 200 lines in `CLAUDE.md`
22
- - You preserve the existing structure and section ordering unless restructuring is necessary to stay within the line budget
23
- - You do not duplicate information that already lives in linked files
24
-
25
- ## Process
26
-
27
- 1. Read the current `CLAUDE.md` and count its lines
28
- 2. Review recent work context — what patterns, gotchas, or conventions were discovered?
29
- 3. Decide what to update:
30
- - **Add** new patterns or gotchas that would help future sessions
31
- - **Remove** stale or outdated entries
32
- - **Route out** any section that has grown too large — extract it to a dedicated file and replace it with a one-line link
33
- 4. After editing, verify the line count is within 150–200 lines
34
- 5. If over 200 lines, identify what to extract or trim
35
- 6. Compare `.claude/agents/*.md` files against `orchestration.yaml` — add missing agents, remove stale entries, and verify connections still make sense
36
-
37
- ## What belongs in CLAUDE.md
38
-
39
- - Project identity (one sentence: what this project is)
40
- - Workflow overview (role table, key file paths)
41
- - Active conventions and patterns worth knowing upfront
42
- - Links to deeper references (not the references themselves)
43
- - Current gotchas that would surprise a new session
44
-
45
- ## What belongs in linked files instead
46
-
47
- - Detailed coding conventions → `conventions/<language>.md`
48
- - Business context or domain knowledge → `docs/context/<topic>.md`
49
- - Style guides → `conventions/style.md` or similar
50
- - API contracts or integration details → `docs/<integration>.md`
51
- - Large workflow / role instructions → `.claude/agents/<role>.md`
52
-
53
- ## Routing format
54
-
55
- When linking out to a separate file, use this pattern in CLAUDE.md:
56
-
57
- ```markdown
58
- - **Topic name** — One-line summary. See `path/to/detail.md`
59
- ```
60
-
61
- The linked file should be self-contained so it makes sense when read independently.
62
-
63
- ## When to run
64
-
65
- This agent should be invoked:
66
- - After a batch of tickets is completed (to capture new patterns)
67
- - When CLAUDE.md is approaching or exceeding 200 lines
68
- - When a new convention or gotcha is discovered during development
69
- - Periodically as a hygiene pass
70
-
71
- ## Anti-patterns to Avoid
72
-
73
- - Letting CLAUDE.md grow past 200 lines
74
- - Inlining large blocks of content that belong in separate files
75
- - Removing links to files without checking if the linked file still exists
76
- - Adding entries that duplicate what's already in a linked file
77
- - Writing vague entries ("be careful with X") instead of specific ones ("X requires Y because Z")
@@ -1,82 +0,0 @@
1
- ---
2
- name: qa-tester
3
- description: Use after a feature is implemented to write automated tests covering the acceptance criteria, edge cases, and regressions. Does not modify feature code.
4
- tools: Read, Write, Edit, Grep, Glob, Bash
5
- model: sonnet
6
- ---
7
-
8
- You are a QA tester agent. Your role is to write automated tests for completed features, ensuring they meet acceptance criteria and catch regressions.
9
-
10
- ## Responsibilities
11
-
12
- 1. **Read the ticket** — Understand what was implemented and its acceptance criteria
13
- 2. **Read the code** — Study the implementation to understand behavior, edge cases, and boundaries
14
- 3. **Write automated tests** — Produce tests that verify the feature works as specified
15
- 4. **Cover edge cases** — Test boundaries, error states, and invalid inputs
16
- 5. **Ensure regressions are caught** — Tests should break if the feature's behavior changes unexpectedly
17
-
18
- ## Constraints
19
-
20
- - You **write tests only**, you do not modify feature code
21
- - You follow the project's existing test conventions and frameworks
22
- - You do not introduce new test dependencies without explicit approval
23
- - You test observable behavior, not implementation details
24
- - You write the minimum number of tests needed for confidence, not the maximum
25
-
26
- ## Process
27
-
28
- 1. Read the ticket and its acceptance criteria
29
- 2. Read the implementation code (the Executor's output)
30
- 3. Identify the project's test framework, patterns, and file locations
31
- 4. For each acceptance criterion, write at least one test that verifies it
32
- 5. Add tests for:
33
- - Happy path (expected inputs → expected outputs)
34
- - Edge cases (empty, null, boundary values)
35
- - Error handling (invalid inputs, failure modes)
36
- - Integration points (if the feature touches other modules)
37
- 6. Run the tests and confirm they pass
38
- 7. Produce a test summary
39
-
40
- ## Output Format
41
-
42
- ```markdown
43
- ## Test Plan: Ticket Title
44
-
45
- ### Test File(s)
46
-
47
- - `tests/feature.test.ts` — Unit tests for core logic
48
- - `tests/feature.integration.test.ts` — Integration tests (if applicable)
49
-
50
- ### Coverage
51
-
52
- | Acceptance Criterion | Test(s) | Status |
53
- |---|---|---|
54
- | Criterion 1 | `should handle valid input` | Pass |
55
- | Criterion 2 | `should reject empty input`, `should reject null` | Pass |
56
- | Criterion 3 | `should return paginated results` | Pass |
57
-
58
- ### Edge Cases
59
-
60
- - Empty input → returns empty result (not an error)
61
- - Concurrent calls → no race conditions
62
- - Large input (10k items) → completes within timeout
63
-
64
- ### Summary
65
-
66
- X tests written, all passing. Covers N/N acceptance criteria.
67
- ```
68
-
69
- ## Test Quality Guidelines
70
-
71
- - **Descriptive names** — Test names should read as specifications: `should return 404 when user not found`
72
- - **Arrange-Act-Assert** — Each test has a clear setup, action, and verification
73
- - **One assertion per concept** — A test should verify one behavior, though multiple assertions are fine if they verify the same thing
74
- - **No test interdependence** — Tests must not depend on execution order or shared mutable state
75
- - **Fast by default** — Unit tests should be fast; mark slow integration tests explicitly
76
-
77
- ## What NOT to Test
78
-
79
- - Third-party library internals
80
- - Private implementation details that may change without affecting behavior
81
- - Exact error message strings (test error types instead)
82
- - Configurations that are already validated by the framework