@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.
Files changed (39) hide show
  1. package/dist/cli.js +2817 -981
  2. package/dist/commands/cron.d.ts +8 -0
  3. package/dist/commands/cron.d.ts.map +1 -0
  4. package/dist/commands/cron.js +214 -0
  5. package/dist/commands/cron.js.map +1 -0
  6. package/dist/commands/init.d.ts.map +1 -1
  7. package/dist/commands/init.js +28 -31
  8. package/dist/commands/init.js.map +1 -1
  9. package/dist/commands/qa.d.ts.map +1 -1
  10. package/dist/commands/qa.js +3 -27
  11. package/dist/commands/qa.js.map +1 -1
  12. package/dist/commands/review.d.ts +20 -0
  13. package/dist/commands/review.d.ts.map +1 -1
  14. package/dist/commands/review.js +98 -18
  15. package/dist/commands/review.js.map +1 -1
  16. package/dist/commands/run.d.ts.map +1 -1
  17. package/dist/commands/run.js +3 -18
  18. package/dist/commands/run.js.map +1 -1
  19. package/dist/commands/shared/env-builder.d.ts +25 -0
  20. package/dist/commands/shared/env-builder.d.ts.map +1 -0
  21. package/dist/commands/shared/env-builder.js +48 -0
  22. package/dist/commands/shared/env-builder.js.map +1 -0
  23. package/dist/commands/slice.d.ts.map +1 -1
  24. package/dist/commands/slice.js +3 -23
  25. package/dist/commands/slice.js.map +1 -1
  26. package/dist/scripts/night-watch-audit-cron.sh +56 -33
  27. package/dist/scripts/night-watch-cron.sh +12 -2
  28. package/dist/scripts/night-watch-helpers.sh +84 -0
  29. package/dist/scripts/night-watch-pr-reviewer-cron.sh +389 -9
  30. package/dist/scripts/night-watch-qa-cron.sh +116 -4
  31. package/dist/templates/audit.md +87 -0
  32. package/dist/templates/executor.md +67 -0
  33. package/dist/templates/night-watch-pr-reviewer.md +153 -135
  34. package/dist/templates/night-watch-slicer.md +1 -1
  35. package/dist/templates/night-watch.md +1 -1
  36. package/dist/templates/pr-reviewer.md +203 -0
  37. package/dist/templates/qa.md +157 -0
  38. package/dist/templates/slicer.md +234 -0
  39. 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/night-watch-audit.md"
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
- case "${PROVIDER_CMD}" in
114
- claude)
115
- if (
116
- cd "${AUDIT_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
117
- claude -p "${AUDIT_PROMPT}" \
118
- --dangerously-skip-permissions \
119
- >> "${LOG_FILE}" 2>&1
120
- ); then
121
- EXIT_CODE=0
122
- else
123
- EXIT_CODE=$?
124
- fi
125
- ;;
126
- codex)
127
- if (
128
- cd "${AUDIT_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
129
- codex --quiet \
130
- --yolo \
131
- --prompt "${AUDIT_PROMPT}" \
132
- >> "${LOG_FILE}" 2>&1
133
- ); then
134
- EXIT_CODE=0
135
- else
136
- EXIT_CODE=$?
137
- fi
138
- ;;
139
- *)
140
- log "ERROR: Unknown provider: ${PROVIDER_CMD}"
141
- emit_result "failure" "reason=unknown_provider"
142
- exit 1
143
- ;;
144
- esac
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 .claude/skills/prd-executor/SKILL.md (preferred) or .claude/commands/prd-executor.md (fallback), and follow the FULL execution pipeline:
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 .claude/skills/prd-executor/SKILL.md (preferred) or .claude/commands/prd-executor.md (fallback), and follow the FULL execution pipeline:
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