@jonit-dev/night-watch-cli 1.8.6-beta.0 → 1.8.6-beta.1

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
@@ -308,7 +308,7 @@ function resolveProviderBucketKey(provider, providerEnv) {
308
308
  return `claude-proxy:${baseUrl}`;
309
309
  }
310
310
  }
311
- var DEFAULT_DEFAULT_BRANCH, DEFAULT_PRD_DIR, DEFAULT_MAX_RUNTIME, DEFAULT_REVIEWER_MAX_RUNTIME, DEFAULT_CRON_SCHEDULE, DEFAULT_REVIEWER_SCHEDULE, DEFAULT_CRON_SCHEDULE_OFFSET, DEFAULT_MAX_RETRIES, DEFAULT_REVIEWER_MAX_RETRIES, DEFAULT_REVIEWER_RETRY_DELAY, DEFAULT_REVIEWER_MAX_PRS_PER_RUN, DEFAULT_BRANCH_PREFIX, DEFAULT_BRANCH_PATTERNS, DEFAULT_MIN_REVIEW_SCORE, DEFAULT_MAX_LOG_SIZE, DEFAULT_PROVIDER, DEFAULT_EXECUTOR_ENABLED, DEFAULT_REVIEWER_ENABLED, DEFAULT_PROVIDER_ENV, DEFAULT_FALLBACK_ON_RATE_LIMIT, DEFAULT_CLAUDE_MODEL, DEFAULT_PRIMARY_FALLBACK_MODEL, DEFAULT_SECONDARY_FALLBACK_MODEL, VALID_CLAUDE_MODELS, CLAUDE_MODEL_IDS, DEFAULT_NOTIFICATIONS, DEFAULT_PRD_PRIORITY, DEFAULT_SLICER_SCHEDULE, DEFAULT_SLICER_MAX_RUNTIME, DEFAULT_ROADMAP_SCANNER, DEFAULT_TEMPLATES_DIR, DEFAULT_BOARD_PROVIDER, DEFAULT_LOCAL_BOARD_INFO, DEFAULT_AUTO_MERGE, DEFAULT_AUTO_MERGE_METHOD, VALID_MERGE_METHODS, DEFAULT_QA_ENABLED, DEFAULT_QA_SCHEDULE, DEFAULT_QA_MAX_RUNTIME, DEFAULT_QA_ARTIFACTS, DEFAULT_QA_SKIP_LABEL, DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT, DEFAULT_QA, QA_LOG_NAME, DEFAULT_AUDIT_ENABLED, DEFAULT_AUDIT_SCHEDULE, DEFAULT_AUDIT_MAX_RUNTIME, DEFAULT_AUDIT, DEFAULT_ANALYTICS_ENABLED, DEFAULT_ANALYTICS_SCHEDULE, DEFAULT_ANALYTICS_MAX_RUNTIME, DEFAULT_ANALYTICS_LOOKBACK_DAYS, DEFAULT_ANALYTICS_TARGET_COLUMN, DEFAULT_ANALYTICS_PROMPT, DEFAULT_ANALYTICS, AUDIT_LOG_NAME, PLANNER_LOG_NAME, ANALYTICS_LOG_NAME, VALID_PROVIDERS, VALID_JOB_TYPES, DEFAULT_JOB_PROVIDERS, BUILT_IN_PRESETS, BUILT_IN_PRESET_IDS, PROVIDER_COMMANDS, CONFIG_FILE_NAME, LOCK_FILE_PREFIX, LOG_DIR, CLAIM_FILE_EXTENSION, EXECUTOR_LOG_NAME, REVIEWER_LOG_NAME, EXECUTOR_LOG_FILE, REVIEWER_LOG_FILE, LOG_FILE_NAMES, GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME, HISTORY_FILE_NAME, PRD_STATES_FILE_NAME, STATE_DB_FILE_NAME, GLOBAL_NOTIFICATIONS_FILE_NAME, MAX_HISTORY_RECORDS_PER_PRD, DEFAULT_QUEUE_ENABLED, DEFAULT_QUEUE_MODE, DEFAULT_QUEUE_MAX_CONCURRENCY, DEFAULT_QUEUE_MAX_WAIT_TIME, DEFAULT_QUEUE_PRIORITY, DEFAULT_QUEUE, DEFAULT_SCHEDULING_PRIORITY;
311
+ var DEFAULT_DEFAULT_BRANCH, DEFAULT_PRD_DIR, DEFAULT_MAX_RUNTIME, DEFAULT_REVIEWER_MAX_RUNTIME, DEFAULT_CRON_SCHEDULE, DEFAULT_REVIEWER_SCHEDULE, DEFAULT_CRON_SCHEDULE_OFFSET, DEFAULT_MAX_RETRIES, DEFAULT_REVIEWER_MAX_RETRIES, DEFAULT_REVIEWER_RETRY_DELAY, DEFAULT_REVIEWER_MAX_PRS_PER_RUN, DEFAULT_BRANCH_PREFIX, DEFAULT_BRANCH_PATTERNS, DEFAULT_MIN_REVIEW_SCORE, DEFAULT_MAX_LOG_SIZE, DEFAULT_PROVIDER, DEFAULT_EXECUTOR_ENABLED, DEFAULT_REVIEWER_ENABLED, DEFAULT_PROVIDER_ENV, DEFAULT_FALLBACK_ON_RATE_LIMIT, DEFAULT_CLAUDE_MODEL, DEFAULT_PRIMARY_FALLBACK_MODEL, DEFAULT_SECONDARY_FALLBACK_MODEL, VALID_CLAUDE_MODELS, CLAUDE_MODEL_IDS, DEFAULT_NOTIFICATIONS, DEFAULT_PRD_PRIORITY, DEFAULT_SLICER_SCHEDULE, DEFAULT_SLICER_MAX_RUNTIME, DEFAULT_ROADMAP_SCANNER, DEFAULT_TEMPLATES_DIR, DEFAULT_BOARD_PROVIDER, DEFAULT_LOCAL_BOARD_INFO, DEFAULT_AUTO_MERGE, DEFAULT_AUTO_MERGE_METHOD, VALID_MERGE_METHODS, DEFAULT_QA_ENABLED, DEFAULT_QA_SCHEDULE, DEFAULT_QA_MAX_RUNTIME, DEFAULT_QA_ARTIFACTS, DEFAULT_QA_SKIP_LABEL, DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT, DEFAULT_QA, QA_LOG_NAME, DEFAULT_AUDIT_ENABLED, DEFAULT_AUDIT_SCHEDULE, DEFAULT_AUDIT_MAX_RUNTIME, DEFAULT_AUDIT, DEFAULT_ANALYTICS_ENABLED, DEFAULT_ANALYTICS_SCHEDULE, DEFAULT_ANALYTICS_MAX_RUNTIME, DEFAULT_ANALYTICS_LOOKBACK_DAYS, DEFAULT_ANALYTICS_TARGET_COLUMN, DEFAULT_ANALYTICS_PROMPT, DEFAULT_ANALYTICS, AUDIT_LOG_NAME, PLANNER_LOG_NAME, ANALYTICS_LOG_NAME, VALID_PROVIDERS, VALID_JOB_TYPES, DEFAULT_JOB_PROVIDERS, DEFAULT_PROVIDER_SCHEDULE_OVERRIDES, BUILT_IN_PRESETS, BUILT_IN_PRESET_IDS, PROVIDER_COMMANDS, CONFIG_FILE_NAME, LOCK_FILE_PREFIX, LOG_DIR, CLAIM_FILE_EXTENSION, EXECUTOR_LOG_NAME, REVIEWER_LOG_NAME, EXECUTOR_LOG_FILE, REVIEWER_LOG_FILE, LOG_FILE_NAMES, GLOBAL_CONFIG_DIR, REGISTRY_FILE_NAME, HISTORY_FILE_NAME, PRD_STATES_FILE_NAME, STATE_DB_FILE_NAME, GLOBAL_NOTIFICATIONS_FILE_NAME, MAX_HISTORY_RECORDS_PER_PRD, DEFAULT_QUEUE_ENABLED, DEFAULT_QUEUE_MODE, DEFAULT_QUEUE_MAX_CONCURRENCY, DEFAULT_QUEUE_MAX_WAIT_TIME, DEFAULT_QUEUE_PRIORITY, DEFAULT_QUEUE, DEFAULT_SCHEDULING_PRIORITY;
312
312
  var init_constants = __esm({
313
313
  "../core/dist/constants.js"() {
314
314
  "use strict";
@@ -411,6 +411,7 @@ If no issues are warranted, output an empty array: []`;
411
411
  VALID_PROVIDERS = ["claude", "codex"];
412
412
  VALID_JOB_TYPES = getValidJobTypes();
413
413
  DEFAULT_JOB_PROVIDERS = {};
414
+ DEFAULT_PROVIDER_SCHEDULE_OVERRIDES = [];
414
415
  BUILT_IN_PRESETS = {
415
416
  claude: {
416
417
  name: "Claude",
@@ -701,6 +702,67 @@ function normalizeConfig(rawConfig) {
701
702
  normalized.jobProviders = jobProviders;
702
703
  }
703
704
  }
705
+ const rawScheduleOverrides = readObject(rawConfig.providerScheduleOverrides);
706
+ if (rawScheduleOverrides) {
707
+ if (Array.isArray(rawScheduleOverrides)) {
708
+ const overrides = [];
709
+ const timeRegex = /^([01]\d|2[0-3]):[0-5]\d$/;
710
+ for (const rawOverride of rawScheduleOverrides) {
711
+ if (rawOverride && typeof rawOverride === "object") {
712
+ const overrideObj = rawOverride;
713
+ const label2 = readString(overrideObj.label);
714
+ const presetId = readString(overrideObj.presetId);
715
+ const startTime = readString(overrideObj.startTime);
716
+ const endTime = readString(overrideObj.endTime);
717
+ const rawDays = overrideObj.days;
718
+ const rawJobTypes = overrideObj.jobTypes;
719
+ const enabled = readBoolean(overrideObj.enabled);
720
+ if (!label2 || !presetId || !startTime || !endTime) {
721
+ continue;
722
+ }
723
+ if (!timeRegex.test(startTime) || !timeRegex.test(endTime)) {
724
+ continue;
725
+ }
726
+ const days = [];
727
+ if (Array.isArray(rawDays)) {
728
+ for (const day of rawDays) {
729
+ if (typeof day === "number" && Number.isInteger(day) && day >= 0 && day <= 6) {
730
+ days.push(day);
731
+ }
732
+ }
733
+ }
734
+ if (days.length === 0) {
735
+ continue;
736
+ }
737
+ let jobTypes;
738
+ if (Array.isArray(rawJobTypes) && rawJobTypes.length > 0) {
739
+ jobTypes = [];
740
+ for (const jt of rawJobTypes) {
741
+ if (typeof jt === "string" && VALID_JOB_TYPES.includes(jt)) {
742
+ jobTypes.push(jt);
743
+ }
744
+ }
745
+ if (jobTypes.length === 0) {
746
+ jobTypes = void 0;
747
+ }
748
+ }
749
+ overrides.push({
750
+ label: label2.trim(),
751
+ presetId: presetId.trim(),
752
+ days,
753
+ startTime,
754
+ endTime,
755
+ jobTypes,
756
+ enabled: enabled ?? true
757
+ // Default to true if not specified
758
+ });
759
+ }
760
+ }
761
+ if (overrides.length > 0) {
762
+ normalized.providerScheduleOverrides = overrides;
763
+ }
764
+ }
765
+ }
704
766
  const rawQueue = readObject(rawConfig.queue);
705
767
  if (rawQueue) {
706
768
  const rawMode = readString(rawQueue.mode);
@@ -1029,6 +1091,7 @@ function getDefaultConfig() {
1029
1091
  audit: { ...DEFAULT_AUDIT },
1030
1092
  analytics: { ...DEFAULT_ANALYTICS },
1031
1093
  jobProviders: { ...DEFAULT_JOB_PROVIDERS },
1094
+ providerScheduleOverrides: [...DEFAULT_PROVIDER_SCHEDULE_OVERRIDES],
1032
1095
  queue: { ...DEFAULT_QUEUE }
1033
1096
  };
1034
1097
  }
@@ -1101,6 +1164,10 @@ function mergeConfigLayer(base, layer) {
1101
1164
  };
1102
1165
  } else if (_key === "roadmapScanner" || _key === "jobProviders") {
1103
1166
  base[_key] = { ...value };
1167
+ } else if (_key === "providerScheduleOverrides") {
1168
+ base[_key] = [
1169
+ ...value
1170
+ ];
1104
1171
  } else if (_key === "branchPatterns" || _key === "prdPriority") {
1105
1172
  base[_key] = [...value];
1106
1173
  } else {
@@ -1129,9 +1196,67 @@ function loadConfig(projectDir) {
1129
1196
  const envConfig = buildEnvOverrideConfig(fileConfig);
1130
1197
  return mergeConfigs(defaults, fileConfig, envConfig);
1131
1198
  }
1132
- function resolveJobProvider(config, jobType) {
1199
+ function parseTimeToMinutes(time) {
1200
+ const match = time.match(/^(\d{1,2}):(\d{2})$/);
1201
+ if (!match) {
1202
+ throw new Error(`Invalid time format: "${time}". Expected "HH:mm" in 24-hour format.`);
1203
+ }
1204
+ const hours = parseInt(match[1], 10);
1205
+ const minutes = parseInt(match[2], 10);
1206
+ if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {
1207
+ throw new Error(`Invalid time value: "${time}". Hours must be 0-23, minutes must be 0-59.`);
1208
+ }
1209
+ return hours * 60 + minutes;
1210
+ }
1211
+ function isTimeInWindow(now, override) {
1212
+ const currentDay = now.getDay();
1213
+ const currentMinutes = now.getHours() * 60 + now.getMinutes();
1214
+ const startMinutes = parseTimeToMinutes(override.startTime);
1215
+ const endMinutes = parseTimeToMinutes(override.endTime);
1216
+ if (!override.days.includes(currentDay)) {
1217
+ if (endMinutes < startMinutes && currentMinutes < endMinutes) {
1218
+ const prevDay = currentDay === 0 ? 6 : currentDay - 1;
1219
+ if (!override.days.includes(prevDay)) {
1220
+ return false;
1221
+ }
1222
+ } else {
1223
+ return false;
1224
+ }
1225
+ }
1226
+ if (startMinutes <= endMinutes) {
1227
+ return currentMinutes >= startMinutes && currentMinutes <= endMinutes;
1228
+ } else {
1229
+ if (currentMinutes >= startMinutes) {
1230
+ return override.days.includes(currentDay);
1231
+ } else if (currentMinutes < endMinutes) {
1232
+ const prevDay = currentDay === 0 ? 6 : currentDay - 1;
1233
+ return override.days.includes(prevDay);
1234
+ }
1235
+ return false;
1236
+ }
1237
+ }
1238
+ function findActiveScheduleOverride(overrides, jobType, now) {
1239
+ const currentTime = now ?? /* @__PURE__ */ new Date();
1240
+ const jobSpecificOverrides = overrides.filter((o) => o.enabled && o.jobTypes && o.jobTypes.includes(jobType));
1241
+ const globalOverrides = overrides.filter((o) => o.enabled && (!o.jobTypes || o.jobTypes.length === 0));
1242
+ for (const override of jobSpecificOverrides) {
1243
+ if (isTimeInWindow(currentTime, override)) {
1244
+ return override.presetId;
1245
+ }
1246
+ }
1247
+ for (const override of globalOverrides) {
1248
+ if (isTimeInWindow(currentTime, override)) {
1249
+ return override.presetId;
1250
+ }
1251
+ }
1252
+ return null;
1253
+ }
1254
+ function resolveJobProvider(config, jobType, now) {
1133
1255
  if (config._cliProviderOverride)
1134
1256
  return config._cliProviderOverride;
1257
+ const scheduleOverride = findActiveScheduleOverride(config.providerScheduleOverrides ?? [], jobType, now);
1258
+ if (scheduleOverride)
1259
+ return scheduleOverride;
1135
1260
  if (config.jobProviders[jobType])
1136
1261
  return config.jobProviders[jobType];
1137
1262
  return config.provider;
@@ -7352,6 +7477,7 @@ __export(dist_exports, {
7352
7477
  DEFAULT_PRIMARY_FALLBACK_MODEL: () => DEFAULT_PRIMARY_FALLBACK_MODEL,
7353
7478
  DEFAULT_PROVIDER: () => DEFAULT_PROVIDER,
7354
7479
  DEFAULT_PROVIDER_ENV: () => DEFAULT_PROVIDER_ENV,
7480
+ DEFAULT_PROVIDER_SCHEDULE_OVERRIDES: () => DEFAULT_PROVIDER_SCHEDULE_OVERRIDES,
7355
7481
  DEFAULT_QA: () => DEFAULT_QA,
7356
7482
  DEFAULT_QA_ARTIFACTS: () => DEFAULT_QA_ARTIFACTS,
7357
7483
  DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT: () => DEFAULT_QA_AUTO_INSTALL_PLAYWRIGHT,
@@ -7474,6 +7600,7 @@ __export(dist_exports, {
7474
7600
  fetchQaScreenshotUrlsForPr: () => fetchQaScreenshotUrlsForPr,
7475
7601
  fetchReviewedPrDetails: () => fetchReviewedPrDetails,
7476
7602
  fetchStatusSnapshot: () => fetchStatusSnapshot,
7603
+ findActiveScheduleOverride: () => findActiveScheduleOverride,
7477
7604
  findEligibleBoardIssue: () => findEligibleBoardIssue,
7478
7605
  findMatchingIssue: () => findMatchingIssue,
7479
7606
  formatDiscordPayload: () => formatDiscordPayload,
@@ -7558,6 +7685,7 @@ __export(dist_exports, {
7558
7685
  parsePrdDependencies: () => parsePrdDependencies,
7559
7686
  parseRoadmap: () => parseRoadmap,
7560
7687
  parseScriptResult: () => parseScriptResult,
7688
+ parseTimeToMinutes: () => parseTimeToMinutes,
7561
7689
  performCancel: () => performCancel,
7562
7690
  plannerLockPath: () => plannerLockPath,
7563
7691
  prepareBranchWorktree: () => prepareBranchWorktree,
@@ -13623,6 +13751,59 @@ function validateConfigChanges(changes, currentConfig) {
13623
13751
  }
13624
13752
  }
13625
13753
  }
13754
+ if (changes.providerScheduleOverrides !== void 0) {
13755
+ if (!Array.isArray(changes.providerScheduleOverrides)) {
13756
+ return "providerScheduleOverrides must be an array";
13757
+ }
13758
+ const timeRegex = /^([01]\d|2[0-3]):[0-5]\d$/;
13759
+ const validDays = [0, 1, 2, 3, 4, 5, 6];
13760
+ for (let i = 0; i < changes.providerScheduleOverrides.length; i++) {
13761
+ const override = changes.providerScheduleOverrides[i];
13762
+ const prefix = `providerScheduleOverrides[${i}]`;
13763
+ if (typeof override !== "object" || override === null) {
13764
+ return `${prefix} must be an object`;
13765
+ }
13766
+ if (typeof override.label !== "string" || override.label.trim().length === 0) {
13767
+ return `${prefix}.label must be a non-empty string`;
13768
+ }
13769
+ if (typeof override.presetId !== "string" || override.presetId.trim().length === 0) {
13770
+ return `${prefix}.presetId must be a non-empty string`;
13771
+ }
13772
+ if (typeof override.startTime !== "string") {
13773
+ return `${prefix}.startTime must be a string`;
13774
+ }
13775
+ if (!timeRegex.test(override.startTime)) {
13776
+ return `${prefix}.startTime must be in HH:mm format (00:00-23:59)`;
13777
+ }
13778
+ if (typeof override.endTime !== "string") {
13779
+ return `${prefix}.endTime must be a string`;
13780
+ }
13781
+ if (!timeRegex.test(override.endTime)) {
13782
+ return `${prefix}.endTime must be in HH:mm format (00:00-23:59)`;
13783
+ }
13784
+ if (!Array.isArray(override.days) || override.days.length === 0) {
13785
+ return `${prefix}.days must be a non-empty array`;
13786
+ }
13787
+ for (const day of override.days) {
13788
+ if (!validDays.includes(day)) {
13789
+ return `${prefix}.days contains invalid day: ${day}. Must be integers 0-6 (0=Sunday, 6=Saturday)`;
13790
+ }
13791
+ }
13792
+ if (override.jobTypes !== void 0 && override.jobTypes !== null) {
13793
+ if (!Array.isArray(override.jobTypes)) {
13794
+ return `${prefix}.jobTypes must be an array or null`;
13795
+ }
13796
+ for (const jt of override.jobTypes) {
13797
+ if (!VALID_JOB_TYPES.includes(jt)) {
13798
+ return `${prefix}.jobTypes contains invalid job type: ${jt}. Must be one of: ${VALID_JOB_TYPES.join(", ")}`;
13799
+ }
13800
+ }
13801
+ }
13802
+ if (override.enabled !== void 0 && typeof override.enabled !== "boolean") {
13803
+ return `${prefix}.enabled must be a boolean`;
13804
+ }
13805
+ }
13806
+ }
13626
13807
  if (changes.providerPresets !== void 0) {
13627
13808
  if (typeof changes.providerPresets !== "object" || changes.providerPresets === null) {
13628
13809
  return "providerPresets must be an object";