@jonit-dev/night-watch-cli 1.5.8 → 1.6.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/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +39 -11
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +23 -0
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/slice.d.ts +26 -0
- package/dist/commands/slice.d.ts.map +1 -0
- package/dist/commands/slice.js +175 -0
- package/dist/commands/slice.js.map +1 -0
- package/dist/commands/state.d.ts +8 -0
- package/dist/commands/state.d.ts.map +1 -0
- package/dist/commands/state.js +56 -0
- package/dist/commands/state.js.map +1 -0
- package/dist/commands/uninstall.js +2 -2
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +32 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +7 -0
- package/dist/constants.js.map +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +11 -13
- package/dist/server/index.js.map +1 -1
- package/dist/storage/json-state-migrator.d.ts +24 -0
- package/dist/storage/json-state-migrator.d.ts.map +1 -0
- package/dist/storage/json-state-migrator.js +197 -0
- package/dist/storage/json-state-migrator.js.map +1 -0
- package/dist/storage/repositories/index.d.ts +23 -0
- package/dist/storage/repositories/index.d.ts.map +1 -0
- package/dist/storage/repositories/index.js +37 -0
- package/dist/storage/repositories/index.js.map +1 -0
- package/dist/storage/repositories/interfaces.d.ts +37 -0
- package/dist/storage/repositories/interfaces.d.ts.map +1 -0
- package/dist/storage/repositories/interfaces.js +6 -0
- package/dist/storage/repositories/interfaces.js.map +1 -0
- package/dist/storage/repositories/sqlite/execution-history-repository.d.ts +21 -0
- package/dist/storage/repositories/sqlite/execution-history-repository.d.ts.map +1 -0
- package/dist/storage/repositories/sqlite/execution-history-repository.js +94 -0
- package/dist/storage/repositories/sqlite/execution-history-repository.js.map +1 -0
- package/dist/storage/repositories/sqlite/prd-state-repository.d.ts +17 -0
- package/dist/storage/repositories/sqlite/prd-state-repository.d.ts.map +1 -0
- package/dist/storage/repositories/sqlite/prd-state-repository.js +74 -0
- package/dist/storage/repositories/sqlite/prd-state-repository.js.map +1 -0
- package/dist/storage/repositories/sqlite/project-registry-repository.d.ts +16 -0
- package/dist/storage/repositories/sqlite/project-registry-repository.d.ts.map +1 -0
- package/dist/storage/repositories/sqlite/project-registry-repository.js +34 -0
- package/dist/storage/repositories/sqlite/project-registry-repository.js.map +1 -0
- package/dist/storage/repositories/sqlite/roadmap-state-repository.d.ts +14 -0
- package/dist/storage/repositories/sqlite/roadmap-state-repository.d.ts.map +1 -0
- package/dist/storage/repositories/sqlite/roadmap-state-repository.js +47 -0
- package/dist/storage/repositories/sqlite/roadmap-state-repository.js.map +1 -0
- package/dist/storage/sqlite/client.d.ts +23 -0
- package/dist/storage/sqlite/client.d.ts.map +1 -0
- package/dist/storage/sqlite/client.js +47 -0
- package/dist/storage/sqlite/client.js.map +1 -0
- package/dist/storage/sqlite/migrations.d.ts +11 -0
- package/dist/storage/sqlite/migrations.d.ts.map +1 -0
- package/dist/storage/sqlite/migrations.js +57 -0
- package/dist/storage/sqlite/migrations.js.map +1 -0
- package/dist/templates/slicer-prompt.d.ts +54 -0
- package/dist/templates/slicer-prompt.d.ts.map +1 -0
- package/dist/templates/slicer-prompt.js +163 -0
- package/dist/templates/slicer-prompt.js.map +1 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/execution-history.d.ts +11 -5
- package/dist/utils/execution-history.d.ts.map +1 -1
- package/dist/utils/execution-history.js +27 -130
- package/dist/utils/execution-history.js.map +1 -1
- package/dist/utils/prd-states.d.ts +1 -2
- package/dist/utils/prd-states.d.ts.map +1 -1
- package/dist/utils/prd-states.js +10 -42
- package/dist/utils/prd-states.js.map +1 -1
- package/dist/utils/registry.d.ts +9 -4
- package/dist/utils/registry.d.ts.map +1 -1
- package/dist/utils/registry.js +21 -33
- package/dist/utils/registry.js.map +1 -1
- package/dist/utils/roadmap-scanner.d.ts +34 -2
- package/dist/utils/roadmap-scanner.d.ts.map +1 -1
- package/dist/utils/roadmap-scanner.js +218 -105
- package/dist/utils/roadmap-scanner.js.map +1 -1
- package/dist/utils/roadmap-state.d.ts +13 -6
- package/dist/utils/roadmap-state.d.ts.map +1 -1
- package/dist/utils/roadmap-state.js +50 -27
- package/dist/utils/roadmap-state.js.map +1 -1
- package/package.json +6 -1
- package/scripts/night-watch-cron.sh +65 -24
- package/scripts/night-watch-slicer-cron.sh +90 -0
- package/templates/night-watch-slicer.md +219 -0
- package/templates/night-watch.config.json +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jonit-dev/night-watch-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Autonomous PRD execution using AI Provider CLIs + cron",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"build:cli": "tsc",
|
|
20
20
|
"test": "vitest run",
|
|
21
21
|
"dev": "tsx src/cli.ts",
|
|
22
|
+
"dev:sandbox": "NIGHT_WATCH_HOME=/tmp/nw-sandbox tsx src/cli.ts",
|
|
23
|
+
"dev:sandbox:inspect": "sqlite3 /tmp/nw-sandbox/state.db",
|
|
24
|
+
"dev:sandbox:reset": "rm -rf /tmp/nw-sandbox && echo 'Sandbox cleared'",
|
|
22
25
|
"dev:web": "concurrently --names \"api,vite\" --prefix-colors \"cyan,magenta\" \"tsx src/cli.ts serve\" \"yarn --cwd web dev\"",
|
|
23
26
|
"prepublishOnly": "npm run build && npm test",
|
|
24
27
|
"publish:npm": "npm publish --access public",
|
|
@@ -54,6 +57,7 @@
|
|
|
54
57
|
"url": "https://github.com/jonit-dev/night-watch-cli/issues"
|
|
55
58
|
},
|
|
56
59
|
"dependencies": {
|
|
60
|
+
"better-sqlite3": "^12.6.2",
|
|
57
61
|
"blessed": "^0.1.81",
|
|
58
62
|
"chalk": "^5.6.2",
|
|
59
63
|
"cli-table3": "^0.6.5",
|
|
@@ -66,6 +70,7 @@
|
|
|
66
70
|
},
|
|
67
71
|
"devDependencies": {
|
|
68
72
|
"@eslint/js": "^10.0.1",
|
|
73
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
69
74
|
"@types/blessed": "^0.1.27",
|
|
70
75
|
"@types/cors": "^2.8.19",
|
|
71
76
|
"@types/express": "^5.0.6",
|
|
@@ -84,6 +84,48 @@ else
|
|
|
84
84
|
BOOKKEEP_PRD_DIR="${BOOKKEEP_WORKTREE_DIR}/${PRD_DIR_REL}"
|
|
85
85
|
fi
|
|
86
86
|
|
|
87
|
+
count_prs_for_branch() {
|
|
88
|
+
local pr_state="${1:?pr_state required}"
|
|
89
|
+
local branch_name="${2:?branch_name required}"
|
|
90
|
+
local count
|
|
91
|
+
count=$(
|
|
92
|
+
{ gh pr list --state "${pr_state}" --json headRefName --jq '.[].headRefName' 2>/dev/null || true; } \
|
|
93
|
+
| { grep -xF "${branch_name}" || true; } \
|
|
94
|
+
| wc -l \
|
|
95
|
+
| tr -d '[:space:]'
|
|
96
|
+
)
|
|
97
|
+
echo "${count:-0}"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
finalize_prd_done() {
|
|
101
|
+
local reason="${1:?reason required}"
|
|
102
|
+
|
|
103
|
+
release_claim "${PRD_DIR}" "${ELIGIBLE_PRD}"
|
|
104
|
+
# NOTE: PRDs are moved to done/ immediately when a PR is opened (or already merged)
|
|
105
|
+
# rather than waiting for reviewer/merge loops.
|
|
106
|
+
if prepare_detached_worktree "${PROJECT_DIR}" "${BOOKKEEP_WORKTREE_DIR}" "${DEFAULT_BRANCH}" "${LOG_FILE}"; then
|
|
107
|
+
if mark_prd_done "${BOOKKEEP_PRD_DIR}" "${ELIGIBLE_PRD}"; then
|
|
108
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" success --exit-code 0 2>/dev/null || true
|
|
109
|
+
if [[ "${PRD_DIR_REL}" = /* ]]; then
|
|
110
|
+
git -C "${BOOKKEEP_WORKTREE_DIR}" add -A "${PRD_DIR_REL}" || true
|
|
111
|
+
else
|
|
112
|
+
git -C "${BOOKKEEP_WORKTREE_DIR}" add -A "${PRD_DIR_REL}/" || true
|
|
113
|
+
fi
|
|
114
|
+
git -C "${BOOKKEEP_WORKTREE_DIR}" commit -m "chore: mark ${ELIGIBLE_PRD} as done (${reason})
|
|
115
|
+
|
|
116
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" || true
|
|
117
|
+
git -C "${BOOKKEEP_WORKTREE_DIR}" push origin "HEAD:${DEFAULT_BRANCH}" || true
|
|
118
|
+
log "DONE: ${ELIGIBLE_PRD} ${reason}, PRD moved to done/"
|
|
119
|
+
return 0
|
|
120
|
+
fi
|
|
121
|
+
log "WARN: Failed to move ${ELIGIBLE_PRD} to done/ in bookkeeping worktree"
|
|
122
|
+
return 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
log "WARN: Unable to prepare bookkeeping worktree for ${ELIGIBLE_PRD}"
|
|
126
|
+
return 1
|
|
127
|
+
}
|
|
128
|
+
|
|
87
129
|
log "START: Processing ${ELIGIBLE_PRD} on branch ${BRANCH_NAME} (worktree: ${WORKTREE_DIR})"
|
|
88
130
|
|
|
89
131
|
PROMPT="Implement the PRD at docs/PRDs/night-watch/${ELIGIBLE_PRD}
|
|
@@ -127,6 +169,17 @@ if [ "${NW_DRY_RUN:-0}" = "1" ]; then
|
|
|
127
169
|
exit 0
|
|
128
170
|
fi
|
|
129
171
|
|
|
172
|
+
# If this PRD already has a merged PR for its branch, finalize it immediately.
|
|
173
|
+
MERGED_PR_COUNT=$(count_prs_for_branch merged "${BRANCH_NAME}")
|
|
174
|
+
if [ "${MERGED_PR_COUNT}" -gt 0 ]; then
|
|
175
|
+
log "INFO: Found merged PR for ${BRANCH_NAME}; skipping provider run"
|
|
176
|
+
if finalize_prd_done "already merged on ${BRANCH_NAME}"; then
|
|
177
|
+
exit 0
|
|
178
|
+
fi
|
|
179
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
|
|
130
183
|
if ! prepare_branch_worktree "${PROJECT_DIR}" "${WORKTREE_DIR}" "${BRANCH_NAME}" "${DEFAULT_BRANCH}" "${LOG_FILE}"; then
|
|
131
184
|
log "FAIL: Unable to create isolated worktree ${WORKTREE_DIR} for ${BRANCH_NAME}"
|
|
132
185
|
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
@@ -203,33 +256,21 @@ while [ "${ATTEMPT}" -lt "${MAX_RETRIES}" ]; do
|
|
|
203
256
|
done
|
|
204
257
|
|
|
205
258
|
if [ ${EXIT_CODE} -eq 0 ]; then
|
|
206
|
-
|
|
207
|
-
if [ "${
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
git -C "${BOOKKEEP_WORKTREE_DIR}" add -A "${PRD_DIR_REL}" || true
|
|
217
|
-
else
|
|
218
|
-
git -C "${BOOKKEEP_WORKTREE_DIR}" add -A "${PRD_DIR_REL}/" || true
|
|
219
|
-
fi
|
|
220
|
-
git -C "${BOOKKEEP_WORKTREE_DIR}" commit -m "chore: mark ${ELIGIBLE_PRD} as done (PR opened on ${BRANCH_NAME})
|
|
221
|
-
|
|
222
|
-
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" || true
|
|
223
|
-
git -C "${BOOKKEEP_WORKTREE_DIR}" push origin "HEAD:${DEFAULT_BRANCH}" || true
|
|
224
|
-
log "DONE: ${ELIGIBLE_PRD} implemented, PR opened, PRD moved to done/"
|
|
225
|
-
else
|
|
226
|
-
log "WARN: Failed to move ${ELIGIBLE_PRD} to done/ in bookkeeping worktree"
|
|
259
|
+
OPEN_PR_COUNT=$(count_prs_for_branch open "${BRANCH_NAME}")
|
|
260
|
+
if [ "${OPEN_PR_COUNT}" -gt 0 ]; then
|
|
261
|
+
if ! finalize_prd_done "implemented, PR opened on ${BRANCH_NAME}"; then
|
|
262
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
263
|
+
fi
|
|
264
|
+
else
|
|
265
|
+
MERGED_PR_COUNT=$(count_prs_for_branch merged "${BRANCH_NAME}")
|
|
266
|
+
if [ "${MERGED_PR_COUNT}" -gt 0 ]; then
|
|
267
|
+
if ! finalize_prd_done "already merged on ${BRANCH_NAME}"; then
|
|
268
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
227
269
|
fi
|
|
228
270
|
else
|
|
229
|
-
log "WARN:
|
|
271
|
+
log "WARN: ${PROVIDER_CMD} exited 0 but no open/merged PR found on ${BRANCH_NAME} — recording cooldown to avoid repeated stuck runs"
|
|
272
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
230
273
|
fi
|
|
231
|
-
else
|
|
232
|
-
log "WARN: ${PROVIDER_CMD} exited 0 but no PR found on ${BRANCH_NAME} — PRD NOT moved to done"
|
|
233
274
|
fi
|
|
234
275
|
elif [ ${EXIT_CODE} -eq 124 ]; then
|
|
235
276
|
log "TIMEOUT: Night watch killed after ${MAX_RUNTIME}s while processing ${ELIGIBLE_PRD}"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Night Watch Slicer Cron Runner (project-agnostic)
|
|
5
|
+
# Usage: night-watch-slicer-cron.sh /path/to/project
|
|
6
|
+
#
|
|
7
|
+
# This is a thin wrapper that acquires a lock and calls `night-watch slice`.
|
|
8
|
+
# The CLI command handles all the logic directly in TypeScript.
|
|
9
|
+
#
|
|
10
|
+
# NOTE: This script expects environment variables to be set by the caller.
|
|
11
|
+
# The Node.js CLI will inject config values via environment variables.
|
|
12
|
+
# Required env vars (with defaults shown):
|
|
13
|
+
# NW_SLICER_MAX_RUNTIME=600 - Maximum runtime in seconds (10 minutes)
|
|
14
|
+
# NW_PROVIDER_CMD=claude - AI provider CLI to use (claude, codex, etc.)
|
|
15
|
+
# NW_DRY_RUN=0 - Set to 1 for dry-run mode (prints diagnostics only)
|
|
16
|
+
|
|
17
|
+
PROJECT_DIR="${1:?Usage: $0 /path/to/project}"
|
|
18
|
+
PROJECT_NAME=$(basename "${PROJECT_DIR}")
|
|
19
|
+
LOG_DIR="${PROJECT_DIR}/logs"
|
|
20
|
+
LOG_FILE="${LOG_DIR}/night-watch-slicer.log"
|
|
21
|
+
LOCK_FILE=""
|
|
22
|
+
MAX_RUNTIME="${NW_SLICER_MAX_RUNTIME:-600}" # 10 minutes
|
|
23
|
+
MAX_LOG_SIZE="524288" # 512 KB
|
|
24
|
+
PROVIDER_CMD="${NW_PROVIDER_CMD:-claude}"
|
|
25
|
+
|
|
26
|
+
# Ensure NVM / Node / Night Watch CLI are on PATH
|
|
27
|
+
export NVM_DIR="${HOME}/.nvm"
|
|
28
|
+
[ -s "${NVM_DIR}/nvm.sh" ] && . "${NVM_DIR}/nvm.sh"
|
|
29
|
+
|
|
30
|
+
mkdir -p "${LOG_DIR}"
|
|
31
|
+
|
|
32
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
33
|
+
# shellcheck source=night-watch-helpers.sh
|
|
34
|
+
source "${SCRIPT_DIR}/night-watch-helpers.sh"
|
|
35
|
+
PROJECT_RUNTIME_KEY=$(project_runtime_key "${PROJECT_DIR}")
|
|
36
|
+
LOCK_FILE="/tmp/night-watch-slicer-${PROJECT_RUNTIME_KEY}.lock"
|
|
37
|
+
|
|
38
|
+
# Validate provider
|
|
39
|
+
if ! validate_provider "${PROVIDER_CMD}"; then
|
|
40
|
+
echo "ERROR: Unknown provider: ${PROVIDER_CMD}" >&2
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
rotate_log
|
|
45
|
+
|
|
46
|
+
if ! acquire_lock "${LOCK_FILE}"; then
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
cleanup_on_exit() {
|
|
51
|
+
rm -f "${LOCK_FILE}"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
trap cleanup_on_exit EXIT
|
|
55
|
+
|
|
56
|
+
log "START: Running roadmap slicer for ${PROJECT_DIR}"
|
|
57
|
+
|
|
58
|
+
# Dry-run mode: print diagnostics and exit
|
|
59
|
+
if [ "${NW_DRY_RUN:-0}" = "1" ]; then
|
|
60
|
+
echo "=== Dry Run: Roadmap Slicer ==="
|
|
61
|
+
echo "Provider: ${PROVIDER_CMD}"
|
|
62
|
+
echo "Project Dir: ${PROJECT_DIR}"
|
|
63
|
+
echo "Timeout: ${MAX_RUNTIME}s"
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Resolve night-watch CLI
|
|
68
|
+
CLI_BIN=""
|
|
69
|
+
if ! CLI_BIN=$(resolve_night_watch_cli); then
|
|
70
|
+
log "ERROR: Could not resolve night-watch CLI"
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# Run the slice command with timeout
|
|
75
|
+
EXIT_CODE=0
|
|
76
|
+
if timeout "${MAX_RUNTIME}" "${CLI_BIN}" slice >> "${LOG_FILE}" 2>&1; then
|
|
77
|
+
EXIT_CODE=0
|
|
78
|
+
else
|
|
79
|
+
EXIT_CODE=$?
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [ ${EXIT_CODE} -eq 0 ]; then
|
|
83
|
+
log "DONE: Slicer completed successfully"
|
|
84
|
+
elif [ ${EXIT_CODE} -eq 124 ]; then
|
|
85
|
+
log "TIMEOUT: Slicer killed after ${MAX_RUNTIME}s"
|
|
86
|
+
else
|
|
87
|
+
log "FAIL: Slicer exited with code ${EXIT_CODE}"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
exit ${EXIT_CODE}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
You are a **PRD Creator Agent**. Your job: analyze the codebase and write a complete Product Requirements Document (PRD) for a feature.
|
|
2
|
+
|
|
3
|
+
When this activates: `PRD Creator: Initializing`
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Input
|
|
8
|
+
|
|
9
|
+
You are creating a PRD for the following roadmap item:
|
|
10
|
+
|
|
11
|
+
**Section:** {{SECTION}}
|
|
12
|
+
**Title:** {{TITLE}}
|
|
13
|
+
**Description:** {{DESCRIPTION}}
|
|
14
|
+
|
|
15
|
+
The PRD must be written to this exact file path:
|
|
16
|
+
**Output File:** `{{OUTPUT_FILE_PATH}}`
|
|
17
|
+
|
|
18
|
+
The PRD directory is: `{{PRD_DIR}}`
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Your Task
|
|
23
|
+
|
|
24
|
+
1. **Explore the Codebase** - Read relevant existing files to understand the project structure, patterns, and conventions. Look for:
|
|
25
|
+
- CLAUDE.md or similar AI assistant documentation files
|
|
26
|
+
- Existing code patterns in the area you'll be modifying
|
|
27
|
+
- Related features or modules that this feature interacts with
|
|
28
|
+
- Test patterns and verification commands
|
|
29
|
+
|
|
30
|
+
2. **Assess Complexity** - Score the complexity using the rubric below and determine whether this is LOW, MEDIUM, or HIGH complexity.
|
|
31
|
+
|
|
32
|
+
3. **Write a Complete PRD** - Create a full PRD following the template structure below. The PRD must be actionable, with concrete file paths, implementation steps, and test specifications.
|
|
33
|
+
|
|
34
|
+
4. **Write the PRD File** - Use the Write tool to create the PRD file at the exact path specified in `{{OUTPUT_FILE_PATH}}`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Complexity Scoring
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
COMPLEXITY SCORE (sum all that apply):
|
|
42
|
+
+1 Touches 1-5 files
|
|
43
|
+
+2 Touches 6-10 files
|
|
44
|
+
+3 Touches 10+ files
|
|
45
|
+
+2 New system/module from scratch
|
|
46
|
+
+2 Complex state logic / concurrency
|
|
47
|
+
+2 Multi-package changes
|
|
48
|
+
+1 Database schema changes
|
|
49
|
+
+1 External API integration
|
|
50
|
+
|
|
51
|
+
| Score | Level | Template Mode |
|
|
52
|
+
| ----- | ------ | ----------------------------------------------- |
|
|
53
|
+
| 1-3 | LOW | Minimal (skip sections marked with MEDIUM/HIGH) |
|
|
54
|
+
| 4-6 | MEDIUM | Standard (all sections) |
|
|
55
|
+
| 7+ | HIGH | Full + mandatory checkpoints every phase |
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## PRD Template Structure
|
|
61
|
+
|
|
62
|
+
Your PRD MUST follow this exact structure:
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
# PRD: [Title from roadmap item]
|
|
66
|
+
|
|
67
|
+
**Depends on:** [List any prerequisite PRDs/files, or omit if none]
|
|
68
|
+
|
|
69
|
+
**Complexity: [SCORE] → [LEVEL] mode**
|
|
70
|
+
|
|
71
|
+
- [Complexity breakdown as bullet list]
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 1. Context
|
|
76
|
+
|
|
77
|
+
**Problem:** [1-2 sentences describing the issue being solved]
|
|
78
|
+
|
|
79
|
+
**Files Analyzed:**
|
|
80
|
+
- `path/to/file.ts` — [what the file does]
|
|
81
|
+
- [List all files you inspected before planning]
|
|
82
|
+
|
|
83
|
+
**Current Behavior:**
|
|
84
|
+
- [3-5 bullets describing current state]
|
|
85
|
+
|
|
86
|
+
### Integration Points Checklist
|
|
87
|
+
|
|
88
|
+
**How will this feature be reached?**
|
|
89
|
+
- [ ] Entry point identified: [e.g., route, event, cron, CLI command]
|
|
90
|
+
- [ ] Caller file identified: [file that will invoke this new code]
|
|
91
|
+
- [ ] Registration/wiring needed: [e.g., add route to router, register handler, add menu item]
|
|
92
|
+
|
|
93
|
+
**Is this user-facing?**
|
|
94
|
+
- [ ] YES → UI components required (list them)
|
|
95
|
+
- [ ] NO → Internal/background feature (explain how it's triggered)
|
|
96
|
+
|
|
97
|
+
**Full user flow:**
|
|
98
|
+
1. User does: [action]
|
|
99
|
+
2. Triggers: [what code path]
|
|
100
|
+
3. Reaches new feature via: [specific connection point]
|
|
101
|
+
4. Result displayed in: [where user sees outcome]
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 2. Solution
|
|
106
|
+
|
|
107
|
+
**Approach:**
|
|
108
|
+
- [3-5 bullets explaining the chosen solution]
|
|
109
|
+
|
|
110
|
+
**Architecture Diagram** <!-- (MEDIUM/HIGH complexity) -->:
|
|
111
|
+
|
|
112
|
+
```mermaid
|
|
113
|
+
flowchart LR
|
|
114
|
+
A[Component A] --> B[Component B] --> C[Component C]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Key Decisions:**
|
|
118
|
+
- [Library/framework choices, error-handling strategy, reused utilities]
|
|
119
|
+
|
|
120
|
+
**Data Changes:** [New schemas/migrations, or "None"]
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 3. Sequence Flow <!-- (MEDIUM/HIGH complexity) -->
|
|
125
|
+
|
|
126
|
+
```mermaid
|
|
127
|
+
sequenceDiagram
|
|
128
|
+
participant A as Component A
|
|
129
|
+
participant B as Component B
|
|
130
|
+
A->>B: methodName(args)
|
|
131
|
+
alt Error case
|
|
132
|
+
B-->>A: ErrorType
|
|
133
|
+
else Success
|
|
134
|
+
B-->>A: Response
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## 4. Execution Phases
|
|
141
|
+
|
|
142
|
+
**CRITICAL RULES:**
|
|
143
|
+
1. Each phase = ONE user-testable vertical slice
|
|
144
|
+
2. Max 5 files per phase (split if larger)
|
|
145
|
+
3. Each phase MUST include concrete tests
|
|
146
|
+
4. Checkpoint after each phase (automated ALWAYS required)
|
|
147
|
+
|
|
148
|
+
### Phase 1: [Name] — [User-visible outcome in 1 sentence]
|
|
149
|
+
|
|
150
|
+
**Files (max 5):**
|
|
151
|
+
- `src/path/file.ts` — [what changes]
|
|
152
|
+
|
|
153
|
+
**Implementation:**
|
|
154
|
+
- [ ] Step 1
|
|
155
|
+
- [ ] Step 2
|
|
156
|
+
|
|
157
|
+
**Tests Required:**
|
|
158
|
+
| Test File | Test Name | Assertion |
|
|
159
|
+
|-----------|-----------|-----------|
|
|
160
|
+
| `src/__tests__/feature.test.ts` | `should do X when Y` | `expect(result).toBe(Z)` |
|
|
161
|
+
|
|
162
|
+
**Verification Plan:**
|
|
163
|
+
1. **Unit Tests:** File and test names
|
|
164
|
+
2. **Integration Test:** (if applicable)
|
|
165
|
+
3. **User Verification:**
|
|
166
|
+
- Action: [what to do]
|
|
167
|
+
- Expected: [what should happen]
|
|
168
|
+
|
|
169
|
+
**Checkpoint:** Run automated review after this phase completes.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
[Repeat for additional phases as needed]
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## 5. Acceptance Criteria
|
|
178
|
+
|
|
179
|
+
- [ ] All phases complete
|
|
180
|
+
- [ ] All specified tests pass
|
|
181
|
+
- [ ] Verification commands pass
|
|
182
|
+
- [ ] All automated checkpoint reviews passed
|
|
183
|
+
- [ ] Feature is reachable (entry point connected, not orphaned code)
|
|
184
|
+
- [ ] [additional criterion specific to this feature]
|
|
185
|
+
- [ ] [additional criterion specific to this feature]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Critical Instructions
|
|
191
|
+
|
|
192
|
+
1. **Read all relevant existing files BEFORE writing any code**
|
|
193
|
+
2. **Follow existing patterns in the codebase**
|
|
194
|
+
3. **Write the PRD with concrete file paths and implementation details**
|
|
195
|
+
4. **Include specific test names and assertions**
|
|
196
|
+
5. **Use the Write tool to create the PRD file at `{{OUTPUT_FILE_PATH}}`**
|
|
197
|
+
6. **The PRD must be complete and actionable - no TODO placeholders**
|
|
198
|
+
|
|
199
|
+
DO NOT leave placeholder text like "[Name]" or "[description]" in the final PRD.
|
|
200
|
+
DO NOT skip any sections.
|
|
201
|
+
DO NOT forget to write the file.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Output
|
|
206
|
+
|
|
207
|
+
After writing the PRD file, report:
|
|
208
|
+
|
|
209
|
+
```markdown
|
|
210
|
+
## PRD Creation Complete
|
|
211
|
+
|
|
212
|
+
**File:** {{OUTPUT_FILE_PATH}}
|
|
213
|
+
**Title:** [PRD title]
|
|
214
|
+
**Complexity:** [score] → [level]
|
|
215
|
+
**Phases:** [count]
|
|
216
|
+
|
|
217
|
+
### Summary
|
|
218
|
+
[1-2 sentences summarizing the PRD content]
|
|
219
|
+
```
|