@jonit-dev/night-watch-cli 1.1.3 → 1.1.5
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/README.md +48 -426
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts +16 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +155 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +15 -9
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +10 -2
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/prd.d.ts +24 -0
- package/dist/commands/prd.d.ts.map +1 -0
- package/dist/commands/prd.js +283 -0
- package/dist/commands/prd.js.map +1 -0
- package/dist/commands/review.d.ts.map +1 -1
- package/dist/commands/review.js +28 -0
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/run.d.ts +19 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +64 -6
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +27 -6
- package/dist/commands/status.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +67 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +5 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -0
- package/dist/constants.js.map +1 -1
- package/dist/templates/prd-template.d.ts +11 -0
- package/dist/templates/prd-template.d.ts.map +1 -0
- package/dist/templates/prd-template.js +166 -0
- package/dist/templates/prd-template.js.map +1 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/github.d.ts +30 -0
- package/dist/utils/github.d.ts.map +1 -0
- package/dist/utils/github.js +104 -0
- package/dist/utils/github.js.map +1 -0
- package/dist/utils/notify.d.ts +63 -0
- package/dist/utils/notify.d.ts.map +1 -0
- package/dist/utils/notify.js +237 -0
- package/dist/utils/notify.js.map +1 -0
- package/package.json +4 -4
- package/scripts/night-watch-cron.sh +13 -2
- package/scripts/night-watch-helpers.sh +51 -0
- package/scripts/test-helpers.bats +77 -0
- package/templates/prd.md +26 -0
package/dist/constants.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Default configuration values for Night Watch CLI
|
|
3
3
|
*/
|
|
4
|
-
import { Provider } from "./types.js";
|
|
4
|
+
import { NotificationConfig, Provider } from "./types.js";
|
|
5
|
+
export declare const DEFAULT_DEFAULT_BRANCH = "";
|
|
5
6
|
export declare const DEFAULT_PRD_DIR = "docs/PRDs/night-watch";
|
|
6
7
|
export declare const DEFAULT_MAX_RUNTIME = 7200;
|
|
7
8
|
export declare const DEFAULT_REVIEWER_MAX_RUNTIME = 3600;
|
|
@@ -13,9 +14,12 @@ export declare const DEFAULT_MIN_REVIEW_SCORE = 80;
|
|
|
13
14
|
export declare const DEFAULT_MAX_LOG_SIZE = 524288;
|
|
14
15
|
export declare const DEFAULT_PROVIDER: Provider;
|
|
15
16
|
export declare const DEFAULT_REVIEWER_ENABLED = true;
|
|
17
|
+
export declare const DEFAULT_PROVIDER_ENV: Record<string, string>;
|
|
18
|
+
export declare const DEFAULT_NOTIFICATIONS: NotificationConfig;
|
|
16
19
|
export declare const VALID_PROVIDERS: Provider[];
|
|
17
20
|
export declare const PROVIDER_COMMANDS: Record<Provider, string>;
|
|
18
21
|
export declare const CONFIG_FILE_NAME = "night-watch.config.json";
|
|
19
22
|
export declare const LOCK_FILE_PREFIX = "/tmp/night-watch-";
|
|
20
23
|
export declare const LOG_DIR = "logs";
|
|
24
|
+
export declare const CLAIM_FILE_EXTENSION = ".claim";
|
|
21
25
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG1D,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,eAAe,0BAA0B,CAAC;AAGvD,eAAO,MAAM,mBAAmB,OAAO,CAAC;AACxC,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAGjD,eAAO,MAAM,qBAAqB,iBAAiB,CAAC;AACpD,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAGvE,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AACnD,eAAO,MAAM,uBAAuB,UAA4B,CAAC;AAGjE,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAG3C,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAG3C,eAAO,MAAM,gBAAgB,EAAE,QAAmB,CAAC;AACnD,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAC7C,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,CAAC;AAG/D,eAAO,MAAM,qBAAqB,EAAE,kBAAqC,CAAC;AAG1E,eAAO,MAAM,eAAe,EAAE,QAAQ,EAAwB,CAAC;AAG/D,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAGtD,CAAC;AAGF,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAC1D,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AACpD,eAAO,MAAM,OAAO,SAAS,CAAC;AAC9B,eAAO,MAAM,oBAAoB,WAAW,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Default configuration values for Night Watch CLI
|
|
3
3
|
*/
|
|
4
|
+
// Branch Configuration (default branch)
|
|
5
|
+
export const DEFAULT_DEFAULT_BRANCH = ""; // empty = auto-detect
|
|
4
6
|
// PRD Configuration
|
|
5
7
|
export const DEFAULT_PRD_DIR = "docs/PRDs/night-watch";
|
|
6
8
|
// Runtime Configuration (in seconds)
|
|
@@ -19,6 +21,9 @@ export const DEFAULT_MAX_LOG_SIZE = 524288; // 512 KB
|
|
|
19
21
|
// Provider Configuration
|
|
20
22
|
export const DEFAULT_PROVIDER = "claude";
|
|
21
23
|
export const DEFAULT_REVIEWER_ENABLED = true;
|
|
24
|
+
export const DEFAULT_PROVIDER_ENV = {};
|
|
25
|
+
// Notification Configuration
|
|
26
|
+
export const DEFAULT_NOTIFICATIONS = { webhooks: [] };
|
|
22
27
|
// Valid providers
|
|
23
28
|
export const VALID_PROVIDERS = ["claude", "codex"];
|
|
24
29
|
// Provider commands configuration
|
|
@@ -30,4 +35,5 @@ export const PROVIDER_COMMANDS = {
|
|
|
30
35
|
export const CONFIG_FILE_NAME = "night-watch.config.json";
|
|
31
36
|
export const LOCK_FILE_PREFIX = "/tmp/night-watch-";
|
|
32
37
|
export const LOG_DIR = "logs";
|
|
38
|
+
export const CLAIM_FILE_EXTENSION = ".claim";
|
|
33
39
|
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,oBAAoB;AACpB,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAEvD,qCAAqC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD,8BAA8B;AAC9B,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AACpD,MAAM,CAAC,MAAM,yBAAyB,GAAG,6BAA6B,CAAC;AAEvE,uBAAuB;AACvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAEjE,uBAAuB;AACvB,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,oBAAoB;AACpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,SAAS;AAErD,yBAAyB;AACzB,MAAM,CAAC,MAAM,gBAAgB,GAAa,QAAQ,CAAC;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,wCAAwC;AACxC,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC,CAAC,sBAAsB;AAEhE,oBAAoB;AACpB,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAEvD,qCAAqC;AACrC,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACxC,MAAM,CAAC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAEjD,8BAA8B;AAC9B,MAAM,CAAC,MAAM,qBAAqB,GAAG,cAAc,CAAC;AACpD,MAAM,CAAC,MAAM,yBAAyB,GAAG,6BAA6B,CAAC;AAEvE,uBAAuB;AACvB,MAAM,CAAC,MAAM,qBAAqB,GAAG,aAAa,CAAC;AACnD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAEjE,uBAAuB;AACvB,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,oBAAoB;AACpB,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,CAAC,SAAS;AAErD,yBAAyB;AACzB,MAAM,CAAC,MAAM,gBAAgB,GAAa,QAAQ,CAAC;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAC7C,MAAM,CAAC,MAAM,oBAAoB,GAA2B,EAAE,CAAC;AAE/D,6BAA6B;AAC7B,MAAM,CAAC,MAAM,qBAAqB,GAAuB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAE1E,kBAAkB;AAClB,MAAM,CAAC,MAAM,eAAe,GAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAE/D,kCAAkC;AAClC,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,uBAAuB;AACvB,MAAM,CAAC,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAC1D,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC;AAC9B,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const PRD_TEMPLATE = "# PRD: {{TITLE}}\n\n{{DEPENDS_ON}}\n\n**Complexity: {{COMPLEXITY_SCORE}} \u2192 {{COMPLEXITY_LEVEL}} mode**\n{{COMPLEXITY_BREAKDOWN}}\n\n```\nCOMPLEXITY SCORE (sum all that apply):\n+1 Touches 1-5 files\n+2 Touches 6-10 files\n+3 Touches 10+ files\n+2 New system/module from scratch\n+2 Complex state logic / concurrency\n+2 Multi-package changes\n+1 Database schema changes\n+1 External API integration\n\n| Score | Level | Template Mode |\n| ----- | ------ | ----------------------------------------------- |\n| 1-3 | LOW | Minimal (skip sections marked with MEDIUM/HIGH) |\n| 4-6 | MEDIUM | Standard (all sections) |\n| 7+ | HIGH | Full + mandatory checkpoints every phase |\n```\n\n---\n\n## 1. Context\n\n**Problem:** <!-- 1-2 sentences describing the issue being solved -->\n\n**Files Analyzed:**\n<!-- List all files you've inspected before planning -->\n\n**Current Behavior:**\n<!-- 3-5 bullets describing current state -->\n\n### Integration Points Checklist\n\n**How will this feature be reached?**\n- [ ] Entry point identified: <!-- e.g., route, event, cron, CLI command -->\n- [ ] Caller file identified: <!-- file that will invoke this new code -->\n- [ ] Registration/wiring needed: <!-- e.g., add route to router, register handler, add menu item -->\n\n**Is this user-facing?**\n- [ ] YES \u2192 UI components required (list them)\n- [ ] NO \u2192 Internal/background feature (explain how it's triggered)\n\n**Full user flow:**\n1. User does: <!-- action -->\n2. Triggers: <!-- what code path -->\n3. Reaches new feature via: <!-- specific connection point -->\n4. Result displayed in: <!-- where user sees outcome -->\n\n---\n\n## 2. Solution\n\n**Approach:**\n<!-- 3-5 bullets explaining the chosen solution -->\n\n**Architecture Diagram** <!-- (MEDIUM/HIGH complexity) -->:\n\n```mermaid\nflowchart LR\n A[Component A] --> B[Component B] --> C[Component C]\n```\n\n**Key Decisions:**\n<!-- Library/framework choices, error-handling strategy, reused utilities -->\n\n**Data Changes:** <!-- New schemas/migrations, or \"None\" -->\n\n---\n\n## 3. Sequence Flow <!-- (MEDIUM/HIGH complexity) -->\n\n```mermaid\nsequenceDiagram\n participant A as Component A\n participant B as Component B\n A->>B: methodName(args)\n alt Error case\n B-->>A: ErrorType\n else Success\n B-->>A: Response\n end\n```\n\n---\n\n## 4. Execution Phases\n\n**CRITICAL RULES:**\n1. Each phase = ONE user-testable vertical slice\n2. Max 5 files per phase (split if larger)\n3. Each phase MUST include concrete tests\n4. Checkpoint after each phase (automated ALWAYS required)\n\n{{PHASES}}\n\n---\n\n## 5. Acceptance Criteria\n\n- [ ] All phases complete\n- [ ] All specified tests pass\n- [ ] Verification commands pass\n- [ ] All automated checkpoint reviews passed\n- [ ] Feature is reachable (entry point connected, not orphaned code)\n- [ ] <!-- additional criterion -->\n- [ ] <!-- additional criterion -->\n";
|
|
2
|
+
export interface PrdTemplateVars {
|
|
3
|
+
title: string;
|
|
4
|
+
dependsOn: string[];
|
|
5
|
+
complexityScore: number;
|
|
6
|
+
complexityLevel: "LOW" | "MEDIUM" | "HIGH";
|
|
7
|
+
complexityBreakdown: string[];
|
|
8
|
+
phaseCount: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function renderPrdTemplate(vars: PrdTemplateVars, customTemplate?: string): string;
|
|
11
|
+
//# sourceMappingURL=prd-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-template.d.ts","sourceRoot":"","sources":["../../src/templates/prd-template.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,u9FAgHxB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB;AA8CD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,eAAe,EACrB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAkBR"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
export const PRD_TEMPLATE = `# PRD: {{TITLE}}
|
|
2
|
+
|
|
3
|
+
{{DEPENDS_ON}}
|
|
4
|
+
|
|
5
|
+
**Complexity: {{COMPLEXITY_SCORE}} → {{COMPLEXITY_LEVEL}} mode**
|
|
6
|
+
{{COMPLEXITY_BREAKDOWN}}
|
|
7
|
+
|
|
8
|
+
\`\`\`
|
|
9
|
+
COMPLEXITY SCORE (sum all that apply):
|
|
10
|
+
+1 Touches 1-5 files
|
|
11
|
+
+2 Touches 6-10 files
|
|
12
|
+
+3 Touches 10+ files
|
|
13
|
+
+2 New system/module from scratch
|
|
14
|
+
+2 Complex state logic / concurrency
|
|
15
|
+
+2 Multi-package changes
|
|
16
|
+
+1 Database schema changes
|
|
17
|
+
+1 External API integration
|
|
18
|
+
|
|
19
|
+
| Score | Level | Template Mode |
|
|
20
|
+
| ----- | ------ | ----------------------------------------------- |
|
|
21
|
+
| 1-3 | LOW | Minimal (skip sections marked with MEDIUM/HIGH) |
|
|
22
|
+
| 4-6 | MEDIUM | Standard (all sections) |
|
|
23
|
+
| 7+ | HIGH | Full + mandatory checkpoints every phase |
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. Context
|
|
29
|
+
|
|
30
|
+
**Problem:** <!-- 1-2 sentences describing the issue being solved -->
|
|
31
|
+
|
|
32
|
+
**Files Analyzed:**
|
|
33
|
+
<!-- List all files you've inspected before planning -->
|
|
34
|
+
|
|
35
|
+
**Current Behavior:**
|
|
36
|
+
<!-- 3-5 bullets describing current state -->
|
|
37
|
+
|
|
38
|
+
### Integration Points Checklist
|
|
39
|
+
|
|
40
|
+
**How will this feature be reached?**
|
|
41
|
+
- [ ] Entry point identified: <!-- e.g., route, event, cron, CLI command -->
|
|
42
|
+
- [ ] Caller file identified: <!-- file that will invoke this new code -->
|
|
43
|
+
- [ ] Registration/wiring needed: <!-- e.g., add route to router, register handler, add menu item -->
|
|
44
|
+
|
|
45
|
+
**Is this user-facing?**
|
|
46
|
+
- [ ] YES → UI components required (list them)
|
|
47
|
+
- [ ] NO → Internal/background feature (explain how it's triggered)
|
|
48
|
+
|
|
49
|
+
**Full user flow:**
|
|
50
|
+
1. User does: <!-- action -->
|
|
51
|
+
2. Triggers: <!-- what code path -->
|
|
52
|
+
3. Reaches new feature via: <!-- specific connection point -->
|
|
53
|
+
4. Result displayed in: <!-- where user sees outcome -->
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 2. Solution
|
|
58
|
+
|
|
59
|
+
**Approach:**
|
|
60
|
+
<!-- 3-5 bullets explaining the chosen solution -->
|
|
61
|
+
|
|
62
|
+
**Architecture Diagram** <!-- (MEDIUM/HIGH complexity) -->:
|
|
63
|
+
|
|
64
|
+
\`\`\`mermaid
|
|
65
|
+
flowchart LR
|
|
66
|
+
A[Component A] --> B[Component B] --> C[Component C]
|
|
67
|
+
\`\`\`
|
|
68
|
+
|
|
69
|
+
**Key Decisions:**
|
|
70
|
+
<!-- Library/framework choices, error-handling strategy, reused utilities -->
|
|
71
|
+
|
|
72
|
+
**Data Changes:** <!-- New schemas/migrations, or "None" -->
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 3. Sequence Flow <!-- (MEDIUM/HIGH complexity) -->
|
|
77
|
+
|
|
78
|
+
\`\`\`mermaid
|
|
79
|
+
sequenceDiagram
|
|
80
|
+
participant A as Component A
|
|
81
|
+
participant B as Component B
|
|
82
|
+
A->>B: methodName(args)
|
|
83
|
+
alt Error case
|
|
84
|
+
B-->>A: ErrorType
|
|
85
|
+
else Success
|
|
86
|
+
B-->>A: Response
|
|
87
|
+
end
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## 4. Execution Phases
|
|
93
|
+
|
|
94
|
+
**CRITICAL RULES:**
|
|
95
|
+
1. Each phase = ONE user-testable vertical slice
|
|
96
|
+
2. Max 5 files per phase (split if larger)
|
|
97
|
+
3. Each phase MUST include concrete tests
|
|
98
|
+
4. Checkpoint after each phase (automated ALWAYS required)
|
|
99
|
+
|
|
100
|
+
{{PHASES}}
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 5. Acceptance Criteria
|
|
105
|
+
|
|
106
|
+
- [ ] All phases complete
|
|
107
|
+
- [ ] All specified tests pass
|
|
108
|
+
- [ ] Verification commands pass
|
|
109
|
+
- [ ] All automated checkpoint reviews passed
|
|
110
|
+
- [ ] Feature is reachable (entry point connected, not orphaned code)
|
|
111
|
+
- [ ] <!-- additional criterion -->
|
|
112
|
+
- [ ] <!-- additional criterion -->
|
|
113
|
+
`;
|
|
114
|
+
function renderDependsOn(deps) {
|
|
115
|
+
if (deps.length === 0) {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
const formatted = deps.map((d) => `\`${d}\``).join(", ");
|
|
119
|
+
return `**Depends on:** ${formatted}`;
|
|
120
|
+
}
|
|
121
|
+
function renderComplexityBreakdown(items) {
|
|
122
|
+
if (items.length === 0) {
|
|
123
|
+
return "";
|
|
124
|
+
}
|
|
125
|
+
return items.map((item) => `- ${item}`).join("\n");
|
|
126
|
+
}
|
|
127
|
+
function renderPhases(count) {
|
|
128
|
+
const phases = [];
|
|
129
|
+
for (let i = 1; i <= count; i++) {
|
|
130
|
+
phases.push(`### Phase ${i}: [Name] — [User-visible outcome in 1 sentence]
|
|
131
|
+
|
|
132
|
+
**Files (max 5):**
|
|
133
|
+
- \`src/path/file.ts\` — what changes
|
|
134
|
+
|
|
135
|
+
**Implementation:**
|
|
136
|
+
- [ ] Step 1
|
|
137
|
+
- [ ] Step 2
|
|
138
|
+
|
|
139
|
+
**Tests Required:**
|
|
140
|
+
| Test File | Test Name | Assertion |
|
|
141
|
+
|-----------|-----------|-----------|
|
|
142
|
+
| \`src/__tests__/feature.test.ts\` | \`should do X when Y\` | \`expect(result).toBe(Z)\` |
|
|
143
|
+
|
|
144
|
+
**Verification Plan:**
|
|
145
|
+
1. **Unit Tests:** File and test names
|
|
146
|
+
2. **Integration Test:** (if applicable)
|
|
147
|
+
3. **User Verification:**
|
|
148
|
+
- Action: [what to do]
|
|
149
|
+
- Expected: [what should happen]
|
|
150
|
+
|
|
151
|
+
**Checkpoint:** Run automated review after this phase completes.`);
|
|
152
|
+
}
|
|
153
|
+
return phases.join("\n\n---\n\n");
|
|
154
|
+
}
|
|
155
|
+
export function renderPrdTemplate(vars, customTemplate) {
|
|
156
|
+
const template = customTemplate ?? PRD_TEMPLATE;
|
|
157
|
+
let result = template;
|
|
158
|
+
result = result.replace("{{TITLE}}", vars.title);
|
|
159
|
+
result = result.replace("{{DEPENDS_ON}}", renderDependsOn(vars.dependsOn));
|
|
160
|
+
result = result.replace("{{COMPLEXITY_SCORE}}", String(vars.complexityScore));
|
|
161
|
+
result = result.replace("{{COMPLEXITY_LEVEL}}", vars.complexityLevel);
|
|
162
|
+
result = result.replace("{{COMPLEXITY_BREAKDOWN}}", renderComplexityBreakdown(vars.complexityBreakdown));
|
|
163
|
+
result = result.replace("{{PHASES}}", renderPhases(vars.phaseCount));
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=prd-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-template.js","sourceRoot":"","sources":["../../src/templates/prd-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgH3B,CAAC;AAWF,SAAS,eAAe,CAAC,IAAc;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO,mBAAmB,SAAS,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAe;IAChD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;iEAqBmC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAqB,EACrB,cAAuB;IAEvB,MAAM,QAAQ,GAAG,cAAc,IAAI,YAAY,CAAC;IAEhD,IAAI,MAAM,GAAG,QAAQ,CAAC;IACtB,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3E,MAAM,GAAG,MAAM,CAAC,OAAO,CACrB,sBAAsB,EACtB,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAC7B,CAAC;IACF,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;IACtE,MAAM,GAAG,MAAM,CAAC,OAAO,CACrB,0BAA0B,EAC1B,yBAAyB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CACpD,CAAC;IACF,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAErE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type Provider = "claude" | "codex";
|
|
|
9
9
|
* Complete Night Watch configuration
|
|
10
10
|
*/
|
|
11
11
|
export interface INightWatchConfig {
|
|
12
|
+
/** Default branch name (e.g. "main" or "master"). Empty string means auto-detect. */
|
|
13
|
+
defaultBranch: string;
|
|
12
14
|
/** Directory containing PRD files (relative to project root) */
|
|
13
15
|
prdDir: string;
|
|
14
16
|
/** Maximum runtime in seconds for PRD execution */
|
|
@@ -31,5 +33,21 @@ export interface INightWatchConfig {
|
|
|
31
33
|
provider: Provider;
|
|
32
34
|
/** Whether the reviewer is enabled */
|
|
33
35
|
reviewerEnabled: boolean;
|
|
36
|
+
/** Extra environment variables to pass to the provider CLI (e.g. API keys, base URLs) */
|
|
37
|
+
providerEnv: Record<string, string>;
|
|
38
|
+
/** Notification webhook configuration */
|
|
39
|
+
notifications: NotificationConfig;
|
|
40
|
+
}
|
|
41
|
+
export type WebhookType = "slack" | "discord" | "telegram";
|
|
42
|
+
export type NotificationEvent = "run_succeeded" | "run_failed" | "run_timeout" | "review_completed";
|
|
43
|
+
export interface WebhookConfig {
|
|
44
|
+
type: WebhookType;
|
|
45
|
+
url?: string;
|
|
46
|
+
botToken?: string;
|
|
47
|
+
chatId?: string;
|
|
48
|
+
events: NotificationEvent[];
|
|
49
|
+
}
|
|
50
|
+
export interface NotificationConfig {
|
|
51
|
+
webhooks: WebhookConfig[];
|
|
34
52
|
}
|
|
35
53
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAGhC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAE3B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IAEvB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IAInB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IAIzB,uCAAuC;IACvC,QAAQ,EAAE,QAAQ,CAAC;IAEnB,sCAAsC;IACtC,eAAe,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAGhC,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAC;IAEtB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IAEnB,iDAAiD;IACjD,kBAAkB,EAAE,MAAM,CAAC;IAE3B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IAEvB,qDAAqD;IACrD,UAAU,EAAE,MAAM,CAAC;IAInB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IAErB,oCAAoC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IAIzB,uCAAuC;IACvC,QAAQ,EAAE,QAAQ,CAAC;IAEnB,sCAAsC;IACtC,eAAe,EAAE,OAAO,CAAC;IAEzB,yFAAyF;IACzF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEpC,yCAAyC;IACzC,aAAa,EAAE,kBAAkB,CAAC;CACnC;AAED,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;AAC3D,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,YAAY,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEpG,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,iBAAiB,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub utilities for Night Watch CLI
|
|
3
|
+
* Fetches PR details using the gh CLI
|
|
4
|
+
*/
|
|
5
|
+
export interface PrDetails {
|
|
6
|
+
number: number;
|
|
7
|
+
title: string;
|
|
8
|
+
url: string;
|
|
9
|
+
body: string;
|
|
10
|
+
additions: number;
|
|
11
|
+
deletions: number;
|
|
12
|
+
changedFiles: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Fetch PR details for the most recently created PR matching a branch prefix.
|
|
16
|
+
* Returns null if gh is unavailable, not authenticated, or no PR found.
|
|
17
|
+
*/
|
|
18
|
+
export declare function fetchPrDetails(branchPrefix: string, cwd: string): PrDetails | null;
|
|
19
|
+
/**
|
|
20
|
+
* Fetch PR details for the most recently updated PR matching any of the given branch patterns.
|
|
21
|
+
* Used by the review command to find the PR that was just reviewed.
|
|
22
|
+
* Returns null on any failure.
|
|
23
|
+
*/
|
|
24
|
+
export declare function fetchReviewedPrDetails(branchPatterns: string[], cwd: string): PrDetails | null;
|
|
25
|
+
/**
|
|
26
|
+
* Extract a summary from a PR body.
|
|
27
|
+
* Takes the first meaningful paragraph, strips markdown headers, truncates to maxLength.
|
|
28
|
+
*/
|
|
29
|
+
export declare function extractSummary(body: string, maxLength?: number): string;
|
|
30
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/utils/github.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAyClF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwC9F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,GAAG,MAAM,CAgC5E"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub utilities for Night Watch CLI
|
|
3
|
+
* Fetches PR details using the gh CLI
|
|
4
|
+
*/
|
|
5
|
+
import { execSync } from "child_process";
|
|
6
|
+
/**
|
|
7
|
+
* Fetch PR details for the most recently created PR matching a branch prefix.
|
|
8
|
+
* Returns null if gh is unavailable, not authenticated, or no PR found.
|
|
9
|
+
*/
|
|
10
|
+
export function fetchPrDetails(branchPrefix, cwd) {
|
|
11
|
+
try {
|
|
12
|
+
// Find the most recently created open PR on a matching branch
|
|
13
|
+
const listOutput = execSync(`gh pr list --state open --json number,headRefName --limit 20`, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
14
|
+
const prs = JSON.parse(listOutput);
|
|
15
|
+
// Filter PRs matching the branch prefix
|
|
16
|
+
const matching = prs.filter((pr) => pr.headRefName.startsWith(branchPrefix + "/"));
|
|
17
|
+
if (matching.length === 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
// Use the first match (most recent)
|
|
21
|
+
const prNumber = matching[0].number;
|
|
22
|
+
// Fetch full details for this PR
|
|
23
|
+
const viewOutput = execSync(`gh pr view ${prNumber} --json number,title,url,body,additions,deletions,changedFiles`, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
24
|
+
const details = JSON.parse(viewOutput);
|
|
25
|
+
return {
|
|
26
|
+
number: details.number,
|
|
27
|
+
title: details.title ?? "",
|
|
28
|
+
url: details.url ?? "",
|
|
29
|
+
body: details.body ?? "",
|
|
30
|
+
additions: details.additions ?? 0,
|
|
31
|
+
deletions: details.deletions ?? 0,
|
|
32
|
+
changedFiles: details.changedFiles ?? 0,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// gh CLI not available, not authenticated, or command failed
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Fetch PR details for the most recently updated PR matching any of the given branch patterns.
|
|
42
|
+
* Used by the review command to find the PR that was just reviewed.
|
|
43
|
+
* Returns null on any failure.
|
|
44
|
+
*/
|
|
45
|
+
export function fetchReviewedPrDetails(branchPatterns, cwd) {
|
|
46
|
+
try {
|
|
47
|
+
const listOutput = execSync(`gh pr list --state open --json number,headRefName --limit 20`, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
48
|
+
const prs = JSON.parse(listOutput);
|
|
49
|
+
// Filter PRs matching any branch pattern
|
|
50
|
+
const matching = prs.filter((pr) => branchPatterns.some((pattern) => pr.headRefName.startsWith(pattern)));
|
|
51
|
+
if (matching.length === 0) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
// Use the first match
|
|
55
|
+
const prNumber = matching[0].number;
|
|
56
|
+
const viewOutput = execSync(`gh pr view ${prNumber} --json number,title,url,body,additions,deletions,changedFiles`, { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
57
|
+
const details = JSON.parse(viewOutput);
|
|
58
|
+
return {
|
|
59
|
+
number: details.number,
|
|
60
|
+
title: details.title ?? "",
|
|
61
|
+
url: details.url ?? "",
|
|
62
|
+
body: details.body ?? "",
|
|
63
|
+
additions: details.additions ?? 0,
|
|
64
|
+
deletions: details.deletions ?? 0,
|
|
65
|
+
changedFiles: details.changedFiles ?? 0,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Extract a summary from a PR body.
|
|
74
|
+
* Takes the first meaningful paragraph, strips markdown headers, truncates to maxLength.
|
|
75
|
+
*/
|
|
76
|
+
export function extractSummary(body, maxLength = 500) {
|
|
77
|
+
if (!body || body.trim().length === 0) {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
// Split into lines and filter out markdown headers and empty lines
|
|
81
|
+
const lines = body.split("\n");
|
|
82
|
+
const contentLines = [];
|
|
83
|
+
for (const line of lines) {
|
|
84
|
+
const trimmed = line.trim();
|
|
85
|
+
// Skip empty lines, markdown headers, and horizontal rules
|
|
86
|
+
if (trimmed === "" || trimmed.startsWith("#") || trimmed === "---" || trimmed === "***") {
|
|
87
|
+
// If we already have content, a blank line means end of first paragraph
|
|
88
|
+
if (contentLines.length > 0 && trimmed === "") {
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
contentLines.push(trimmed);
|
|
94
|
+
}
|
|
95
|
+
const summary = contentLines.join("\n");
|
|
96
|
+
if (summary.length <= maxLength) {
|
|
97
|
+
return summary;
|
|
98
|
+
}
|
|
99
|
+
// Truncate at word boundary
|
|
100
|
+
const truncated = summary.slice(0, maxLength);
|
|
101
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
102
|
+
return (lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated) + "...";
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../../src/utils/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification utilities for Night Watch CLI
|
|
3
|
+
* Sends webhook notifications to Slack, Discord, and Telegram
|
|
4
|
+
*/
|
|
5
|
+
import { INightWatchConfig, WebhookConfig, NotificationEvent } from "../types.js";
|
|
6
|
+
export interface NotificationContext {
|
|
7
|
+
event: NotificationEvent;
|
|
8
|
+
projectName: string;
|
|
9
|
+
prdName?: string;
|
|
10
|
+
branchName?: string;
|
|
11
|
+
prNumber?: number;
|
|
12
|
+
exitCode: number;
|
|
13
|
+
duration?: number;
|
|
14
|
+
provider: string;
|
|
15
|
+
prUrl?: string;
|
|
16
|
+
prTitle?: string;
|
|
17
|
+
prBody?: string;
|
|
18
|
+
filesChanged?: number;
|
|
19
|
+
additions?: number;
|
|
20
|
+
deletions?: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get the emoji for a notification event
|
|
24
|
+
*/
|
|
25
|
+
export declare function getEventEmoji(event: NotificationEvent): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get a human-readable title for a notification event
|
|
28
|
+
*/
|
|
29
|
+
export declare function getEventTitle(event: NotificationEvent): string;
|
|
30
|
+
/**
|
|
31
|
+
* Get the Discord embed color for a notification event
|
|
32
|
+
*/
|
|
33
|
+
export declare function getEventColor(event: NotificationEvent): number;
|
|
34
|
+
/**
|
|
35
|
+
* Build a description string from notification context
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildDescription(ctx: NotificationContext): string;
|
|
38
|
+
/**
|
|
39
|
+
* Format a notification payload for Slack incoming webhooks
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatSlackPayload(ctx: NotificationContext): object;
|
|
42
|
+
/**
|
|
43
|
+
* Format a notification payload for Discord webhooks
|
|
44
|
+
*/
|
|
45
|
+
export declare function formatDiscordPayload(ctx: NotificationContext): object;
|
|
46
|
+
/**
|
|
47
|
+
* Build a structured Telegram message when PR details are available.
|
|
48
|
+
* Falls back to the basic format when they are not.
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatTelegramPayload(ctx: NotificationContext): {
|
|
51
|
+
text: string;
|
|
52
|
+
parse_mode: string;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Send a notification to a single webhook endpoint
|
|
56
|
+
* Silently catches errors — never throws
|
|
57
|
+
*/
|
|
58
|
+
export declare function sendWebhook(webhook: WebhookConfig, ctx: NotificationContext): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Send notifications to all configured webhooks
|
|
61
|
+
*/
|
|
62
|
+
export declare function sendNotifications(config: INightWatchConfig, ctx: NotificationContext): Promise<void>;
|
|
63
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/utils/notify.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIlF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,iBAAiB,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAW9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAW9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAW9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAkBjE;AASD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CA8BnE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAerE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,mBAAmB,GAAG;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB,CAqDA;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCjG;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,GAAG,EAAE,mBAAmB,GACvB,OAAO,CAAC,IAAI,CAAC,CAWf"}
|