@jonit-dev/night-watch-cli 1.7.83 → 1.7.85

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 CHANGED
@@ -4792,13 +4792,52 @@ var init_prd_utils = __esm({
4792
4792
  import * as fs12 from "fs";
4793
4793
  import * as os5 from "os";
4794
4794
  import * as path11 from "path";
4795
+ function readLegacyRegistryEntries() {
4796
+ const registryPath = getRegistryPath();
4797
+ if (!fs12.existsSync(registryPath)) {
4798
+ return [];
4799
+ }
4800
+ try {
4801
+ const raw = fs12.readFileSync(registryPath, "utf-8");
4802
+ const parsed = JSON.parse(raw);
4803
+ if (!Array.isArray(parsed)) {
4804
+ return [];
4805
+ }
4806
+ return parsed.filter((entry) => typeof entry === "object" && entry !== null && typeof entry.name === "string" && entry.name.length > 0 && typeof entry.path === "string" && entry.path.length > 0);
4807
+ } catch {
4808
+ return [];
4809
+ }
4810
+ }
4811
+ function loadRegistryEntriesWithLegacyFallback() {
4812
+ const { projectRegistry } = getRepositories();
4813
+ const entries = projectRegistry.getAll();
4814
+ if (entries.length > 0) {
4815
+ return entries;
4816
+ }
4817
+ const db = getDb();
4818
+ const alreadyHydrated = db.prepare("SELECT value FROM schema_meta WHERE key = 'legacy_projects_json_hydrated'").get();
4819
+ if (alreadyHydrated) {
4820
+ return [];
4821
+ }
4822
+ const legacyEntries = readLegacyRegistryEntries();
4823
+ if (legacyEntries.length === 0) {
4824
+ return [];
4825
+ }
4826
+ db.transaction(() => {
4827
+ for (const entry of legacyEntries) {
4828
+ projectRegistry.upsert(entry);
4829
+ }
4830
+ db.prepare(`INSERT INTO schema_meta (key, value) VALUES ('legacy_projects_json_hydrated', ?)
4831
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run((/* @__PURE__ */ new Date()).toISOString());
4832
+ })();
4833
+ return projectRegistry.getAll();
4834
+ }
4795
4835
  function getRegistryPath() {
4796
4836
  const base = process.env.NIGHT_WATCH_HOME || path11.join(os5.homedir(), GLOBAL_CONFIG_DIR);
4797
4837
  return path11.join(base, REGISTRY_FILE_NAME);
4798
4838
  }
4799
4839
  function loadRegistry() {
4800
- const { projectRegistry } = getRepositories();
4801
- return projectRegistry.getAll();
4840
+ return loadRegistryEntriesWithLegacyFallback();
4802
4841
  }
4803
4842
  function saveRegistry(entries) {
4804
4843
  const { projectRegistry } = getRepositories();
@@ -4810,7 +4849,7 @@ function saveRegistry(entries) {
4810
4849
  function registerProject(projectDir) {
4811
4850
  const resolvedPath = path11.resolve(projectDir);
4812
4851
  const { projectRegistry } = getRepositories();
4813
- const entries = projectRegistry.getAll();
4852
+ const entries = loadRegistryEntriesWithLegacyFallback();
4814
4853
  const existing = entries.find((e) => e.path === resolvedPath);
4815
4854
  if (existing) {
4816
4855
  return existing;
@@ -4824,6 +4863,7 @@ function registerProject(projectDir) {
4824
4863
  }
4825
4864
  function unregisterProject(projectDir) {
4826
4865
  const resolvedPath = path11.resolve(projectDir);
4866
+ loadRegistryEntriesWithLegacyFallback();
4827
4867
  const { projectRegistry } = getRepositories();
4828
4868
  return projectRegistry.remove(resolvedPath);
4829
4869
  }
@@ -4846,6 +4886,7 @@ var init_registry = __esm({
4846
4886
  init_constants();
4847
4887
  init_repositories();
4848
4888
  init_client();
4889
+ init_client();
4849
4890
  init_status_data();
4850
4891
  }
4851
4892
  });
@@ -7026,7 +7067,7 @@ var init_dist = __esm({
7026
7067
  // src/cli.ts
7027
7068
  import "reflect-metadata";
7028
7069
  import { Command as Command3 } from "commander";
7029
- import { existsSync as existsSync29, readFileSync as readFileSync17 } from "fs";
7070
+ import { existsSync as existsSync29, readFileSync as readFileSync18 } from "fs";
7030
7071
  import { fileURLToPath as fileURLToPath4 } from "url";
7031
7072
  import { dirname as dirname8, join as join34 } from "path";
7032
7073
 
@@ -15335,7 +15376,7 @@ function findPackageRoot(dir) {
15335
15376
  return dir;
15336
15377
  }
15337
15378
  var packageRoot = findPackageRoot(__dirname4);
15338
- var packageJson = JSON.parse(readFileSync17(join34(packageRoot, "package.json"), "utf-8"));
15379
+ var packageJson = JSON.parse(readFileSync18(join34(packageRoot, "package.json"), "utf-8"));
15339
15380
  var program = new Command3();
15340
15381
  program.name("night-watch").description("Autonomous PRD execution using Claude CLI + cron").version(packageJson.version);
15341
15382
  initCommand(program);
@@ -90,6 +90,14 @@ emit_result() {
90
90
  fi
91
91
  }
92
92
 
93
+ extract_review_score_from_text() {
94
+ local review_text="${1:-}"
95
+ printf '%s' "${review_text}" \
96
+ | grep -oP '(?:Overall\s+)?Score:\*?\*?\s*\d+/100' \
97
+ | tail -1 \
98
+ | grep -oP '\d+(?=/100)' || echo ""
99
+ }
100
+
93
101
  # ── Global Job Queue Gate ────────────────────────────────────────────────────
94
102
  # Acquire global gate before per-project lock to serialize jobs across projects.
95
103
  # When gate is busy, enqueue the job and exit cleanly.
@@ -393,10 +401,7 @@ get_pr_score() {
393
401
  fi
394
402
  } | sort -u
395
403
  )
396
- echo "${all_comments}" \
397
- | grep -oP 'Overall Score:\*?\*?\s*(\d+)/100' \
398
- | tail -1 \
399
- | grep -oP '\d+(?=/100)' || echo ""
404
+ extract_review_score_from_text "${all_comments}"
400
405
  }
401
406
 
402
407
  # Count failed CI checks for a PR.
@@ -645,10 +650,7 @@ while IFS=$'\t' read -r pr_number pr_branch; do
645
650
  fi
646
651
  } | sort -u
647
652
  )
648
- LATEST_SCORE=$(echo "${ALL_COMMENTS}" \
649
- | grep -oP 'Overall Score:\*?\*?\s*(\d+)/100' \
650
- | tail -1 \
651
- | grep -oP '\d+(?=/100)' || echo "")
653
+ LATEST_SCORE=$(extract_review_score_from_text "${ALL_COMMENTS}")
652
654
  if [ -n "${LATEST_SCORE}" ] && [ "${LATEST_SCORE}" -lt "${MIN_REVIEW_SCORE}" ]; then
653
655
  log "INFO: PR #${pr_number} (${pr_branch}) has review score ${LATEST_SCORE}/100 (threshold: ${MIN_REVIEW_SCORE})"
654
656
  NEEDS_WORK=1
@@ -686,10 +688,7 @@ if [ "${NEEDS_WORK}" -eq 0 ]; then
686
688
  fi
687
689
  } | sort -u
688
690
  )
689
- PR_SCORE=$(echo "${PR_COMMENTS}" \
690
- | grep -oP 'Overall Score:\*?\*?\s*(\d+)/100' \
691
- | tail -1 \
692
- | grep -oP '\d+(?=/100)' || echo "")
691
+ PR_SCORE=$(extract_review_score_from_text "${PR_COMMENTS}")
693
692
 
694
693
  # Skip PRs without a score or with score below threshold
695
694
  [ -z "${PR_SCORE}" ] && continue
@@ -915,9 +914,14 @@ if ! assert_isolated_worktree "${PROJECT_DIR}" "${REVIEW_WORKTREE_DIR}" "reviewe
915
914
  exit 1
916
915
  fi
917
916
 
918
- REVIEWER_PROMPT_PATH=$(resolve_instruction_path_with_fallback "${REVIEW_WORKTREE_DIR}" "pr-reviewer.md" "night-watch-pr-reviewer.md" || true)
917
+ SHARED_REVIEW_PROMPT_PATH="${REVIEW_WORKTREE_DIR}/.github/prompts/pr-review.md"
918
+ if [ -f "${SHARED_REVIEW_PROMPT_PATH}" ]; then
919
+ REVIEWER_PROMPT_PATH="${SHARED_REVIEW_PROMPT_PATH}"
920
+ else
921
+ REVIEWER_PROMPT_PATH=$(resolve_instruction_path_with_fallback "${REVIEW_WORKTREE_DIR}" "pr-reviewer.md" "night-watch-pr-reviewer.md" || true)
922
+ fi
919
923
  if [ -z "${REVIEWER_PROMPT_PATH}" ]; then
920
- log "FAIL: Missing reviewer prompt file. Checked pr-reviewer.md/night-watch-pr-reviewer.md in instructions/, .claude/commands/, and bundled templates/"
924
+ log "FAIL: Missing reviewer prompt file. Checked .github/prompts/pr-review.md plus pr-reviewer.md/night-watch-pr-reviewer.md in instructions/, .claude/commands/, and bundled templates/"
921
925
  emit_result "failure" "reason=missing_reviewer_prompt"
922
926
  exit 1
923
927
  fi
@@ -1225,10 +1229,7 @@ if [ "${AUTO_MERGE}" = "1" ] && [ ${EXIT_CODE} -eq 0 ]; then
1225
1229
  fi
1226
1230
  } | sort -u
1227
1231
  )
1228
- LATEST_SCORE=$(echo "${ALL_COMMENTS}" \
1229
- | grep -oP 'Overall Score:\*?\*?\s*(\d+)/100' \
1230
- | tail -1 \
1231
- | grep -oP '\d+(?=/100)' || echo "")
1232
+ LATEST_SCORE=$(extract_review_score_from_text "${ALL_COMMENTS}")
1232
1233
 
1233
1234
  # Skip PRs without a score
1234
1235
  if [ -z "${LATEST_SCORE}" ]; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jonit-dev/night-watch-cli",
3
- "version": "1.7.83",
3
+ "version": "1.7.85",
4
4
  "description": "Autonomous PRD execution using AI Provider CLIs + cron",
5
5
  "type": "module",
6
6
  "bin": {