@jonit-dev/night-watch-cli 1.7.49 → 1.7.51
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 +2817 -981
- package/dist/commands/cron.d.ts +8 -0
- package/dist/commands/cron.d.ts.map +1 -0
- package/dist/commands/cron.js +214 -0
- package/dist/commands/cron.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +28 -31
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/qa.d.ts.map +1 -1
- package/dist/commands/qa.js +3 -27
- package/dist/commands/qa.js.map +1 -1
- package/dist/commands/review.d.ts +20 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +98 -18
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +3 -18
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/shared/env-builder.d.ts +25 -0
- package/dist/commands/shared/env-builder.d.ts.map +1 -0
- package/dist/commands/shared/env-builder.js +48 -0
- package/dist/commands/shared/env-builder.js.map +1 -0
- package/dist/commands/slice.d.ts.map +1 -1
- package/dist/commands/slice.js +3 -23
- package/dist/commands/slice.js.map +1 -1
- package/dist/scripts/night-watch-audit-cron.sh +56 -33
- package/dist/scripts/night-watch-cron.sh +12 -2
- package/dist/scripts/night-watch-helpers.sh +84 -0
- package/dist/scripts/night-watch-pr-reviewer-cron.sh +389 -9
- package/dist/scripts/night-watch-qa-cron.sh +116 -4
- package/dist/templates/audit.md +87 -0
- package/dist/templates/executor.md +67 -0
- package/dist/templates/night-watch-pr-reviewer.md +153 -135
- package/dist/templates/night-watch-slicer.md +1 -1
- package/dist/templates/night-watch.md +1 -1
- package/dist/templates/pr-reviewer.md +203 -0
- package/dist/templates/qa.md +157 -0
- package/dist/templates/slicer.md +234 -0
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ source "${SCRIPT_DIR}/night-watch-helpers.sh"
|
|
|
32
32
|
PROJECT_RUNTIME_KEY=$(project_runtime_key "${PROJECT_DIR}")
|
|
33
33
|
# NOTE: Lock file path must match auditLockPath() in src/utils/status-data.ts
|
|
34
34
|
LOCK_FILE="/tmp/night-watch-audit-${PROJECT_RUNTIME_KEY}.lock"
|
|
35
|
-
AUDIT_PROMPT_TEMPLATE="${SCRIPT_DIR}/../templates/
|
|
35
|
+
AUDIT_PROMPT_TEMPLATE="${SCRIPT_DIR}/../templates/audit.md"
|
|
36
36
|
|
|
37
37
|
emit_result() {
|
|
38
38
|
local status="${1:?status required}"
|
|
@@ -106,42 +106,65 @@ fi
|
|
|
106
106
|
# Ensure the logs dir exists inside the worktree so the provider can write the report
|
|
107
107
|
mkdir -p "${AUDIT_WORKTREE_DIR}/logs"
|
|
108
108
|
|
|
109
|
+
AUDIT_MAX_RETRIES="${NW_AUDIT_MAX_RETRIES:-3}"
|
|
110
|
+
AUDIT_RETRY_DELAY="${NW_AUDIT_RETRY_DELAY:-120}"
|
|
111
|
+
|
|
109
112
|
log "START: Running code audit for ${PROJECT_NAME} (provider: ${PROVIDER_CMD})"
|
|
110
113
|
|
|
111
114
|
EXIT_CODE=0
|
|
112
115
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
116
|
+
for AUDIT_ATTEMPT in $(seq 1 "${AUDIT_MAX_RETRIES}"); do
|
|
117
|
+
LOG_LINE_BEFORE=$(wc -l < "${LOG_FILE}" 2>/dev/null || echo 0)
|
|
118
|
+
log "AUDIT: Attempt ${AUDIT_ATTEMPT}/${AUDIT_MAX_RETRIES}"
|
|
119
|
+
|
|
120
|
+
case "${PROVIDER_CMD}" in
|
|
121
|
+
claude)
|
|
122
|
+
if (
|
|
123
|
+
cd "${AUDIT_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
|
|
124
|
+
claude -p "${AUDIT_PROMPT}" \
|
|
125
|
+
--dangerously-skip-permissions \
|
|
126
|
+
>> "${LOG_FILE}" 2>&1
|
|
127
|
+
); then
|
|
128
|
+
EXIT_CODE=0
|
|
129
|
+
else
|
|
130
|
+
EXIT_CODE=$?
|
|
131
|
+
fi
|
|
132
|
+
;;
|
|
133
|
+
codex)
|
|
134
|
+
if (
|
|
135
|
+
cd "${AUDIT_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
|
|
136
|
+
codex --quiet \
|
|
137
|
+
--yolo \
|
|
138
|
+
--prompt "${AUDIT_PROMPT}" \
|
|
139
|
+
>> "${LOG_FILE}" 2>&1
|
|
140
|
+
); then
|
|
141
|
+
EXIT_CODE=0
|
|
142
|
+
else
|
|
143
|
+
EXIT_CODE=$?
|
|
144
|
+
fi
|
|
145
|
+
;;
|
|
146
|
+
*)
|
|
147
|
+
log "ERROR: Unknown provider: ${PROVIDER_CMD}"
|
|
148
|
+
emit_result "failure" "reason=unknown_provider"
|
|
149
|
+
exit 1
|
|
150
|
+
;;
|
|
151
|
+
esac
|
|
152
|
+
|
|
153
|
+
# Success or timeout — don't retry
|
|
154
|
+
if [ "${EXIT_CODE}" -eq 0 ] || [ "${EXIT_CODE}" -eq 124 ]; then
|
|
155
|
+
break
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Rate-limit retry with backoff
|
|
159
|
+
if check_rate_limited "${LOG_FILE}" "${LOG_LINE_BEFORE}" && [ "${AUDIT_ATTEMPT}" -lt "${AUDIT_MAX_RETRIES}" ]; then
|
|
160
|
+
log "RATE-LIMITED: 429 detected (attempt ${AUDIT_ATTEMPT}/${AUDIT_MAX_RETRIES}), retrying in ${AUDIT_RETRY_DELAY}s..."
|
|
161
|
+
sleep "${AUDIT_RETRY_DELAY}"
|
|
162
|
+
continue
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Non-retryable failure
|
|
166
|
+
break
|
|
167
|
+
done
|
|
145
168
|
|
|
146
169
|
# Copy report back to project dir (if it was written in the worktree)
|
|
147
170
|
WORKTREE_REPORT="${AUDIT_WORKTREE_DIR}/logs/audit-report.md"
|
|
@@ -304,6 +304,16 @@ Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>" || true
|
|
|
304
304
|
|
|
305
305
|
log "START: Processing ${ELIGIBLE_PRD} on branch ${BRANCH_NAME} (worktree: ${WORKTREE_DIR})"
|
|
306
306
|
|
|
307
|
+
EXECUTOR_PROMPT_PATH=$(resolve_instruction_path "${PROJECT_DIR}" "prd-executor.md" || true)
|
|
308
|
+
if [ -z "${EXECUTOR_PROMPT_PATH}" ]; then
|
|
309
|
+
log "FAIL: Missing PRD executor instructions. Checked instructions/, .claude/commands/, and bundled templates/"
|
|
310
|
+
restore_issue_to_ready "Failed to locate PRD executor instructions. Checked instructions/, .claude/commands/, and bundled templates/."
|
|
311
|
+
night_watch_history record "${PROJECT_DIR}" "${ELIGIBLE_PRD}" failure --exit-code 1 2>/dev/null || true
|
|
312
|
+
emit_result "failure" "reason=missing_executor_prompt"
|
|
313
|
+
exit 1
|
|
314
|
+
fi
|
|
315
|
+
EXECUTOR_PROMPT_REF=$(instruction_ref_for_prompt "${PROJECT_DIR}" "${EXECUTOR_PROMPT_PATH}")
|
|
316
|
+
|
|
307
317
|
if [ -n "${ISSUE_NUMBER}" ]; then
|
|
308
318
|
PROMPT="Implement the following PRD (GitHub issue #${ISSUE_NUMBER}: ${ISSUE_TITLE_RAW}):
|
|
309
319
|
|
|
@@ -317,7 +327,7 @@ ${ISSUE_BODY}
|
|
|
317
327
|
- Install dependencies if needed and implement in the current worktree only
|
|
318
328
|
|
|
319
329
|
## Implementation — PRD Executor Workflow
|
|
320
|
-
Read
|
|
330
|
+
Read ${EXECUTOR_PROMPT_REF} and follow the FULL execution pipeline:
|
|
321
331
|
1. Parse the PRD into phases and extract dependencies
|
|
322
332
|
2. Build a dependency graph to identify parallelism
|
|
323
333
|
3. Create a task list with one task per phase
|
|
@@ -345,7 +355,7 @@ else
|
|
|
345
355
|
- Install dependencies if needed and implement in the current worktree only
|
|
346
356
|
|
|
347
357
|
## Implementation — PRD Executor Workflow
|
|
348
|
-
Read
|
|
358
|
+
Read ${EXECUTOR_PROMPT_REF} and follow the FULL execution pipeline:
|
|
349
359
|
1. Parse the PRD into phases and extract dependencies
|
|
350
360
|
2. Build a dependency graph to identify parallelism
|
|
351
361
|
3. Create a task list with one task per phase
|
|
@@ -51,6 +51,90 @@ resolve_night_watch_cli() {
|
|
|
51
51
|
return 1
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
resolve_instruction_path() {
|
|
55
|
+
local project_dir="${1:?project_dir required}"
|
|
56
|
+
local instruction_file="${2:?instruction_file required}"
|
|
57
|
+
local script_dir=""
|
|
58
|
+
local candidate=""
|
|
59
|
+
|
|
60
|
+
if [ -n "${SCRIPT_DIR:-}" ]; then
|
|
61
|
+
script_dir="${SCRIPT_DIR}"
|
|
62
|
+
else
|
|
63
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
for candidate in \
|
|
67
|
+
"${project_dir}/instructions/${instruction_file}" \
|
|
68
|
+
"${project_dir}/.claude/commands/${instruction_file}" \
|
|
69
|
+
"${script_dir}/../templates/${instruction_file}"; do
|
|
70
|
+
if [ -f "${candidate}" ]; then
|
|
71
|
+
printf "%s" "${candidate}"
|
|
72
|
+
return 0
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
return 1
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
resolve_instruction_path_with_fallback() {
|
|
80
|
+
local project_dir="${1:?project_dir required}"
|
|
81
|
+
shift || true
|
|
82
|
+
local instruction_file=""
|
|
83
|
+
local resolved_path=""
|
|
84
|
+
|
|
85
|
+
for instruction_file in "$@"; do
|
|
86
|
+
[ -z "${instruction_file}" ] && continue
|
|
87
|
+
resolved_path=$(resolve_instruction_path "${project_dir}" "${instruction_file}" || true)
|
|
88
|
+
if [ -n "${resolved_path}" ]; then
|
|
89
|
+
printf "%s" "${resolved_path}"
|
|
90
|
+
return 0
|
|
91
|
+
fi
|
|
92
|
+
done
|
|
93
|
+
|
|
94
|
+
return 1
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
instruction_ref_for_prompt() {
|
|
98
|
+
local root_dir="${1:?root_dir required}"
|
|
99
|
+
local instruction_path="${2:?instruction_path required}"
|
|
100
|
+
|
|
101
|
+
if [[ "${instruction_path}" == "${root_dir}/"* ]]; then
|
|
102
|
+
printf "%s" "${instruction_path#${root_dir}/}"
|
|
103
|
+
else
|
|
104
|
+
printf "%s" "${instruction_path}"
|
|
105
|
+
fi
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
prefer_bundled_prompt_if_legacy_command() {
|
|
109
|
+
local project_root="${1:?project_root required}"
|
|
110
|
+
local resolved_prompt_path="${2:?resolved_prompt_path required}"
|
|
111
|
+
local bundled_prompt_name="${3:?bundled_prompt_name required}"
|
|
112
|
+
local script_dir=""
|
|
113
|
+
local bundled_prompt_path=""
|
|
114
|
+
local rel_path=""
|
|
115
|
+
|
|
116
|
+
if [ -n "${SCRIPT_DIR:-}" ]; then
|
|
117
|
+
script_dir="${SCRIPT_DIR}"
|
|
118
|
+
else
|
|
119
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
bundled_prompt_path="${script_dir}/../templates/${bundled_prompt_name}"
|
|
123
|
+
|
|
124
|
+
# Legacy .claude command prompt files often contain slash-command wrappers
|
|
125
|
+
# rather than the full automation prompt. Prefer bundled templates in that case.
|
|
126
|
+
if [[ "${resolved_prompt_path}" == "${project_root}/.claude/commands/"* ]] && [ -f "${bundled_prompt_path}" ]; then
|
|
127
|
+
rel_path="${resolved_prompt_path#${project_root}/}"
|
|
128
|
+
if grep -Eqi '^[[:space:]]*/[a-z0-9._/-]+' "${resolved_prompt_path}" 2>/dev/null; then
|
|
129
|
+
log "WARN: Prompt ${rel_path} looks like a slash-command wrapper; using bundled template ${bundled_prompt_name}"
|
|
130
|
+
printf "%s" "${bundled_prompt_path}"
|
|
131
|
+
return 0
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
printf "%s" "${resolved_prompt_path}"
|
|
136
|
+
}
|
|
137
|
+
|
|
54
138
|
night_watch_history() {
|
|
55
139
|
local cli_bin
|
|
56
140
|
cli_bin=$(resolve_night_watch_cli) || return 127
|