@bradygaster/squad-cli 0.9.2-insider.5 → 0.9.3-insider.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/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +27 -5
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/loop.d.ts +51 -0
- package/dist/cli/commands/loop.d.ts.map +1 -0
- package/dist/cli/commands/loop.js +352 -0
- package/dist/cli/commands/loop.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/budget-check.d.ts +29 -0
- package/dist/cli/commands/watch/capabilities/budget-check.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/budget-check.js +38 -0
- package/dist/cli/commands/watch/capabilities/budget-check.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/circuit-breaker.d.ts +52 -0
- package/dist/cli/commands/watch/capabilities/circuit-breaker.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/circuit-breaker.js +152 -0
- package/dist/cli/commands/watch/capabilities/circuit-breaker.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/cleanup.d.ts +18 -0
- package/dist/cli/commands/watch/capabilities/cleanup.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/cleanup.js +135 -0
- package/dist/cli/commands/watch/capabilities/cleanup.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/execute.d.ts +15 -3
- package/dist/cli/commands/watch/capabilities/execute.d.ts.map +1 -1
- package/dist/cli/commands/watch/capabilities/execute.js +108 -51
- package/dist/cli/commands/watch/capabilities/execute.js.map +1 -1
- package/dist/cli/commands/watch/capabilities/fleet-dispatch.d.ts +20 -0
- package/dist/cli/commands/watch/capabilities/fleet-dispatch.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/fleet-dispatch.js +144 -0
- package/dist/cli/commands/watch/capabilities/fleet-dispatch.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/health-check.d.ts +29 -0
- package/dist/cli/commands/watch/capabilities/health-check.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/health-check.js +139 -0
- package/dist/cli/commands/watch/capabilities/health-check.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/heartbeat.d.ts +48 -0
- package/dist/cli/commands/watch/capabilities/heartbeat.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/heartbeat.js +115 -0
- package/dist/cli/commands/watch/capabilities/heartbeat.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/index.d.ts.map +1 -1
- package/dist/cli/commands/watch/capabilities/index.js +4 -0
- package/dist/cli/commands/watch/capabilities/index.js.map +1 -1
- package/dist/cli/commands/watch/capabilities/lockfile.d.ts +30 -0
- package/dist/cli/commands/watch/capabilities/lockfile.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/lockfile.js +100 -0
- package/dist/cli/commands/watch/capabilities/lockfile.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/machine-capabilities.d.ts +30 -0
- package/dist/cli/commands/watch/capabilities/machine-capabilities.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/machine-capabilities.js +103 -0
- package/dist/cli/commands/watch/capabilities/machine-capabilities.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/post-failure.d.ts +19 -0
- package/dist/cli/commands/watch/capabilities/post-failure.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/post-failure.js +58 -0
- package/dist/cli/commands/watch/capabilities/post-failure.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/priority.d.ts +59 -0
- package/dist/cli/commands/watch/capabilities/priority.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/priority.js +101 -0
- package/dist/cli/commands/watch/capabilities/priority.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/rate-pool.d.ts +67 -0
- package/dist/cli/commands/watch/capabilities/rate-pool.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/rate-pool.js +187 -0
- package/dist/cli/commands/watch/capabilities/rate-pool.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/self-pull.d.ts +4 -1
- package/dist/cli/commands/watch/capabilities/self-pull.d.ts.map +1 -1
- package/dist/cli/commands/watch/capabilities/self-pull.js +53 -5
- package/dist/cli/commands/watch/capabilities/self-pull.js.map +1 -1
- package/dist/cli/commands/watch/capabilities/stale-reclaim.d.ts +23 -0
- package/dist/cli/commands/watch/capabilities/stale-reclaim.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/stale-reclaim.js +87 -0
- package/dist/cli/commands/watch/capabilities/stale-reclaim.js.map +1 -0
- package/dist/cli/commands/watch/capabilities/webhook-alerts.d.ts +29 -0
- package/dist/cli/commands/watch/capabilities/webhook-alerts.d.ts.map +1 -0
- package/dist/cli/commands/watch/capabilities/webhook-alerts.js +114 -0
- package/dist/cli/commands/watch/capabilities/webhook-alerts.js.map +1 -0
- package/dist/cli/commands/watch/config.d.ts +18 -0
- package/dist/cli/commands/watch/config.d.ts.map +1 -1
- package/dist/cli/commands/watch/config.js +20 -1
- package/dist/cli/commands/watch/config.js.map +1 -1
- package/dist/cli/commands/watch/health.d.ts +41 -0
- package/dist/cli/commands/watch/health.d.ts.map +1 -0
- package/dist/cli/commands/watch/health.js +141 -0
- package/dist/cli/commands/watch/health.js.map +1 -0
- package/dist/cli/commands/watch/index.d.ts +9 -2
- package/dist/cli/commands/watch/index.d.ts.map +1 -1
- package/dist/cli/commands/watch/index.js +115 -8
- package/dist/cli/commands/watch/index.js.map +1 -1
- package/dist/cli/commands/watch/types.d.ts +2 -0
- package/dist/cli/commands/watch/types.d.ts.map +1 -1
- package/dist/cli/commands/watch/verbose.d.ts +12 -0
- package/dist/cli/commands/watch/verbose.d.ts.map +1 -0
- package/dist/cli/commands/watch/verbose.js +28 -0
- package/dist/cli/commands/watch/verbose.js.map +1 -0
- package/dist/cli/core/detect-squad-dir.d.ts.map +1 -1
- package/dist/cli/core/detect-squad-dir.js +9 -12
- package/dist/cli/core/detect-squad-dir.js.map +1 -1
- package/dist/cli/core/nap.d.ts.map +1 -1
- package/dist/cli/core/nap.js +9 -4
- package/dist/cli/core/nap.js.map +1 -1
- package/dist/cli/core/upgrade.d.ts +18 -0
- package/dist/cli/core/upgrade.d.ts.map +1 -1
- package/dist/cli/core/upgrade.js +119 -0
- package/dist/cli/core/upgrade.js.map +1 -1
- package/dist/cli-entry.js +208 -12
- package/dist/cli-entry.js.map +1 -1
- package/package.json +5 -1
- package/templates/ceremonies.md +28 -0
- package/templates/issue-lifecycle.md +2 -1
- package/templates/loop.md +46 -0
- package/templates/ralph-triage.js +3 -1
- package/templates/scribe-charter.md +20 -1
- package/templates/squad.agent.md.template +9 -7
- package/templates/workflows/squad-triage.yml +4 -2
- package/templates/workflows/sync-squad-labels.yml +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/execute.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAqB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/execute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FleetDispatch capability — batches read-heavy issues into a single
|
|
3
|
+
* `/fleet`-style parallel Copilot session for efficient triage.
|
|
4
|
+
*
|
|
5
|
+
* Runs in the `post-execute` phase. When `dispatchMode` is `'fleet'` or
|
|
6
|
+
* `'hybrid'`, this capability picks up issues classified as read-heavy
|
|
7
|
+
* (research, review, audit, etc.) and dispatches them as parallel
|
|
8
|
+
* analysis tracks inside one Copilot invocation.
|
|
9
|
+
*/
|
|
10
|
+
import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } from '../types.js';
|
|
11
|
+
export declare class FleetDispatchCapability implements WatchCapability {
|
|
12
|
+
readonly name = "fleet-dispatch";
|
|
13
|
+
readonly description = "Batch read-heavy issues into a parallel /fleet Copilot session";
|
|
14
|
+
readonly configShape: "boolean";
|
|
15
|
+
readonly requires: string[];
|
|
16
|
+
readonly phase: "post-execute";
|
|
17
|
+
preflight(_context: WatchContext): Promise<PreflightResult>;
|
|
18
|
+
execute(context: WatchContext): Promise<CapabilityResult>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=fleet-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-dispatch.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/fleet-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoFpG,qBAAa,uBAAwB,YAAW,eAAe;IAC7D,QAAQ,CAAC,IAAI,oBAAoB;IACjC,QAAQ,CAAC,WAAW,oEAAoE;IACxF,QAAQ,CAAC,WAAW,EAAG,SAAS,CAAU;IAC1C,QAAQ,CAAC,QAAQ,WAAqB;IACtC,QAAQ,CAAC,KAAK,EAAG,cAAc,CAAU;IAEnC,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAU3D,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAyDhE"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FleetDispatch capability — batches read-heavy issues into a single
|
|
3
|
+
* `/fleet`-style parallel Copilot session for efficient triage.
|
|
4
|
+
*
|
|
5
|
+
* Runs in the `post-execute` phase. When `dispatchMode` is `'fleet'` or
|
|
6
|
+
* `'hybrid'`, this capability picks up issues classified as read-heavy
|
|
7
|
+
* (research, review, audit, etc.) and dispatches them as parallel
|
|
8
|
+
* analysis tracks inside one Copilot invocation.
|
|
9
|
+
*/
|
|
10
|
+
import { execSync, execFileSync } from 'node:child_process';
|
|
11
|
+
import { writeFileSync, readFileSync, unlinkSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { tmpdir } from 'node:os';
|
|
14
|
+
import { findExecutableIssues, classifyIssue, } from './execute.js';
|
|
15
|
+
/** Map a roster member label to a display-friendly agent name. */
|
|
16
|
+
function agentForIssue(issue, roster) {
|
|
17
|
+
const memberLabels = new Map(roster.map(m => [m.label, m.name]));
|
|
18
|
+
for (const label of issue.labels) {
|
|
19
|
+
const name = memberLabels.get(label.name);
|
|
20
|
+
if (name)
|
|
21
|
+
return name;
|
|
22
|
+
}
|
|
23
|
+
return 'Copilot';
|
|
24
|
+
}
|
|
25
|
+
/** Build the multi-track fleet prompt for a set of read-heavy issues. */
|
|
26
|
+
function buildFleetPrompt(issues, roster) {
|
|
27
|
+
const tracks = issues.map((issue, idx) => {
|
|
28
|
+
const agent = agentForIssue(issue, roster);
|
|
29
|
+
return [
|
|
30
|
+
`Track ${idx + 1} (${agent}): Issue #${issue.number}: ${issue.title}`,
|
|
31
|
+
` Read the issue body. Analyze, assess urgency (P0/P1/P2), recommend next step.`,
|
|
32
|
+
` Write findings as an issue comment.`,
|
|
33
|
+
` Do NOT create branches or modify files.`,
|
|
34
|
+
].join('\n');
|
|
35
|
+
});
|
|
36
|
+
return [
|
|
37
|
+
`/fleet Execute these ${issues.length} read-only analysis tracks in parallel:`,
|
|
38
|
+
'',
|
|
39
|
+
...tracks,
|
|
40
|
+
'',
|
|
41
|
+
'Rules: All tracks READ-ONLY. Write findings as issue comments. Run in parallel.',
|
|
42
|
+
].join('\n');
|
|
43
|
+
}
|
|
44
|
+
/** Invoke a fleet prompt via the Copilot CLI. */
|
|
45
|
+
function invokeFleet(prompt, cwd, timeoutMs) {
|
|
46
|
+
const promptFile = join(tmpdir(), `fleet-prompt-${Date.now()}.txt`);
|
|
47
|
+
writeFileSync(promptFile, prompt, 'utf-8');
|
|
48
|
+
try {
|
|
49
|
+
// Read the prompt from file
|
|
50
|
+
const promptContent = readFileSync(promptFile, 'utf-8');
|
|
51
|
+
// Use execFileSync with args array — no shell, no injection risk
|
|
52
|
+
const copilotBin = process.platform === 'win32' ? 'copilot.cmd' : 'copilot';
|
|
53
|
+
const result = execFileSync(copilotBin, [
|
|
54
|
+
'-p', promptContent,
|
|
55
|
+
'--allow-all',
|
|
56
|
+
'--no-ask-user',
|
|
57
|
+
'--autopilot',
|
|
58
|
+
], {
|
|
59
|
+
cwd,
|
|
60
|
+
timeout: timeoutMs,
|
|
61
|
+
encoding: 'utf-8',
|
|
62
|
+
});
|
|
63
|
+
return { success: true, output: String(result) };
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
const err = e;
|
|
67
|
+
const msg = err.killed
|
|
68
|
+
? `Fleet dispatch timed out after ${Math.round(timeoutMs / 60_000)}m`
|
|
69
|
+
: err.stderr || err.message;
|
|
70
|
+
return { success: false, error: msg };
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
try {
|
|
74
|
+
unlinkSync(promptFile);
|
|
75
|
+
}
|
|
76
|
+
catch { /* best-effort cleanup */ }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export class FleetDispatchCapability {
|
|
80
|
+
name = 'fleet-dispatch';
|
|
81
|
+
description = 'Batch read-heavy issues into a parallel /fleet Copilot session';
|
|
82
|
+
configShape = 'boolean';
|
|
83
|
+
requires = ['gh', 'copilot'];
|
|
84
|
+
phase = 'post-execute';
|
|
85
|
+
async preflight(_context) {
|
|
86
|
+
// Fleet dispatch requires the copilot CLI — quick sanity check
|
|
87
|
+
try {
|
|
88
|
+
execSync('copilot --version', { encoding: 'utf-8', stdio: 'pipe' });
|
|
89
|
+
return { ok: true };
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return { ok: false, reason: 'copilot CLI not found — required for fleet dispatch' };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async execute(context) {
|
|
96
|
+
try {
|
|
97
|
+
const dispatchMode = context.config['dispatchMode'] ?? 'task';
|
|
98
|
+
// Only run when fleet or hybrid dispatch is active
|
|
99
|
+
if (dispatchMode !== 'fleet' && dispatchMode !== 'hybrid') {
|
|
100
|
+
return { success: true, summary: 'fleet-dispatch: skipped (dispatch mode is task)' };
|
|
101
|
+
}
|
|
102
|
+
const timeoutMs = (context.config['timeout'] ?? 30) * 60_000;
|
|
103
|
+
// Fetch the same issue set as the execute capability
|
|
104
|
+
const sdkItems = await context.adapter.listWorkItems({ tags: ['squad'], state: 'open', limit: 50 });
|
|
105
|
+
const issues = sdkItems.map(wi => ({
|
|
106
|
+
number: wi.id,
|
|
107
|
+
title: wi.title,
|
|
108
|
+
labels: wi.tags.map(t => ({ name: t })),
|
|
109
|
+
assignees: wi.assignedTo ? [{ login: wi.assignedTo }] : [],
|
|
110
|
+
}));
|
|
111
|
+
const { filterByCapabilities, loadCapabilities } = await import('@bradygaster/squad-sdk/ralph/capabilities');
|
|
112
|
+
const capabilities = await loadCapabilities(context.teamRoot);
|
|
113
|
+
const { handled } = filterByCapabilities(issues, capabilities);
|
|
114
|
+
const executable = findExecutableIssues(context.roster, capabilities, handled);
|
|
115
|
+
// Pick only read-heavy issues (or all in pure fleet mode)
|
|
116
|
+
const readIssues = dispatchMode === 'fleet'
|
|
117
|
+
? executable
|
|
118
|
+
: executable.filter(i => classifyIssue(i.title) === 'read');
|
|
119
|
+
if (readIssues.length === 0) {
|
|
120
|
+
return { success: true, summary: 'fleet-dispatch: no read-heavy issues to batch' };
|
|
121
|
+
}
|
|
122
|
+
// Build and invoke fleet prompt
|
|
123
|
+
const prompt = buildFleetPrompt(readIssues, context.roster);
|
|
124
|
+
const fleetTimeout = Math.max(timeoutMs, 300_000); // at least 5 min for fleet
|
|
125
|
+
const result = invokeFleet(prompt, context.teamRoot, fleetTimeout);
|
|
126
|
+
if (result.success) {
|
|
127
|
+
return {
|
|
128
|
+
success: true,
|
|
129
|
+
summary: `fleet-dispatch: ${readIssues.length} issues analyzed in parallel`,
|
|
130
|
+
data: { dispatched: readIssues.length, issues: readIssues.map(i => i.number) },
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
summary: `fleet-dispatch: failed — ${result.error}`,
|
|
136
|
+
data: { dispatched: 0, error: result.error },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
return { success: false, summary: `fleet-dispatch error: ${e.message}` };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=fleet-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fleet-dispatch.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/fleet-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health-check capability — pre-round watchdog.
|
|
3
|
+
*
|
|
4
|
+
* Ported from ralph-watch.ps1 `Invoke-RalphHealthCheck`.
|
|
5
|
+
* Runs in the `pre-scan` phase and verifies:
|
|
6
|
+
* 1. gh CLI authenticated
|
|
7
|
+
* 2. Circuit breaker state file is valid
|
|
8
|
+
* 3. Disk space above threshold (configurable, default 500 MB)
|
|
9
|
+
* 4. Git branch matches expected (optional)
|
|
10
|
+
*
|
|
11
|
+
* Config (via squad.config.ts → watch.capabilities["health-check"]):
|
|
12
|
+
* diskThresholdMB – minimum free disk in MB (default: 500)
|
|
13
|
+
* expectedBranch – warn if not on this branch (optional)
|
|
14
|
+
*/
|
|
15
|
+
import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } from '../types.js';
|
|
16
|
+
export interface HealthCheckResult {
|
|
17
|
+
healed: string[];
|
|
18
|
+
warnings: string[];
|
|
19
|
+
}
|
|
20
|
+
export declare class HealthCheckCapability implements WatchCapability {
|
|
21
|
+
readonly name = "health-check";
|
|
22
|
+
readonly description = "Pre-round watchdog: verify auth, disk space, branch, CB state";
|
|
23
|
+
readonly configShape: "object";
|
|
24
|
+
readonly requires: string[];
|
|
25
|
+
readonly phase: "pre-scan";
|
|
26
|
+
preflight(_context: WatchContext): Promise<PreflightResult>;
|
|
27
|
+
execute(context: WatchContext): Promise<CapabilityResult>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=health-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-check.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/health-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAIpG,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,qBAAa,qBAAsB,YAAW,eAAe;IAC3D,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,WAAW,mEAAmE;IACvF,QAAQ,CAAC,WAAW,EAAG,QAAQ,CAAU;IACzC,QAAQ,CAAC,QAAQ,WAAU;IAC3B,QAAQ,CAAC,KAAK,EAAG,UAAU,CAAU;IAE/B,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAI3D,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA0EhE"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health-check capability — pre-round watchdog.
|
|
3
|
+
*
|
|
4
|
+
* Ported from ralph-watch.ps1 `Invoke-RalphHealthCheck`.
|
|
5
|
+
* Runs in the `pre-scan` phase and verifies:
|
|
6
|
+
* 1. gh CLI authenticated
|
|
7
|
+
* 2. Circuit breaker state file is valid
|
|
8
|
+
* 3. Disk space above threshold (configurable, default 500 MB)
|
|
9
|
+
* 4. Git branch matches expected (optional)
|
|
10
|
+
*
|
|
11
|
+
* Config (via squad.config.ts → watch.capabilities["health-check"]):
|
|
12
|
+
* diskThresholdMB – minimum free disk in MB (default: 500)
|
|
13
|
+
* expectedBranch – warn if not on this branch (optional)
|
|
14
|
+
*/
|
|
15
|
+
import { execFile } from 'node:child_process';
|
|
16
|
+
import { promisify } from 'node:util';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import fs from 'node:fs';
|
|
19
|
+
const execFileAsync = promisify(execFile);
|
|
20
|
+
export class HealthCheckCapability {
|
|
21
|
+
name = 'health-check';
|
|
22
|
+
description = 'Pre-round watchdog: verify auth, disk space, branch, CB state';
|
|
23
|
+
configShape = 'object';
|
|
24
|
+
requires = ['gh'];
|
|
25
|
+
phase = 'pre-scan';
|
|
26
|
+
async preflight(_context) {
|
|
27
|
+
return { ok: true };
|
|
28
|
+
}
|
|
29
|
+
async execute(context) {
|
|
30
|
+
const healed = [];
|
|
31
|
+
const warnings = [];
|
|
32
|
+
const config = context.config;
|
|
33
|
+
const diskThresholdMB = config['diskThresholdMB'] ?? 500;
|
|
34
|
+
const expectedBranch = config['expectedBranch'];
|
|
35
|
+
// 1. Verify gh auth
|
|
36
|
+
try {
|
|
37
|
+
await execFileAsync('gh', ['auth', 'status'], { timeout: 10_000 });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Try extracting auth info from git remote (P3 auth fallback)
|
|
41
|
+
const patFromRemote = await extractPatFromRemote(context.teamRoot);
|
|
42
|
+
if (patFromRemote) {
|
|
43
|
+
healed.push('Detected PAT in git remote URL — gh auth may need refresh');
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
warnings.push('gh auth: not authenticated — run "gh auth login"');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// 2. Validate circuit breaker state file
|
|
50
|
+
const cbPath = path.join(context.teamRoot, '.squad', 'ralph-circuit-breaker.json');
|
|
51
|
+
try {
|
|
52
|
+
if (fs.existsSync(cbPath)) {
|
|
53
|
+
const rawContent = fs.readFileSync(cbPath, 'utf-8');
|
|
54
|
+
const parsed = JSON.parse(rawContent);
|
|
55
|
+
// Check for nested schema (legacy)
|
|
56
|
+
if (!parsed.preferredModel && parsed.model_fallback) {
|
|
57
|
+
healed.push('CB schema: would convert nested→flat on next use');
|
|
58
|
+
}
|
|
59
|
+
// Check for empty model
|
|
60
|
+
if (parsed.currentModel === '' || parsed.currentModel === null) {
|
|
61
|
+
warnings.push('CB state has empty currentModel — circuit-breaker will auto-reset');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// No CB file is fine — will be created on demand
|
|
67
|
+
}
|
|
68
|
+
// 3. Disk space check
|
|
69
|
+
try {
|
|
70
|
+
const freeBytes = await getFreeDiskSpace(context.teamRoot);
|
|
71
|
+
const freeMB = Math.floor(freeBytes / (1024 * 1024));
|
|
72
|
+
if (freeMB < diskThresholdMB) {
|
|
73
|
+
warnings.push(`Low disk space: ${freeMB} MB free (threshold: ${diskThresholdMB} MB)`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// Disk check failed — non-blocking
|
|
78
|
+
}
|
|
79
|
+
// 4. Branch drift check
|
|
80
|
+
if (expectedBranch) {
|
|
81
|
+
try {
|
|
82
|
+
const { stdout } = await execFileAsync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
83
|
+
cwd: context.teamRoot,
|
|
84
|
+
timeout: 5_000,
|
|
85
|
+
});
|
|
86
|
+
const current = stdout.trim();
|
|
87
|
+
if (current && current !== expectedBranch) {
|
|
88
|
+
warnings.push(`Branch drift: on "${current}" (expected "${expectedBranch}")`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch { /* not a git repo or other error */ }
|
|
92
|
+
}
|
|
93
|
+
const summary = healed.length > 0 || warnings.length > 0
|
|
94
|
+
? `healed: ${healed.length}, warnings: ${warnings.length}`
|
|
95
|
+
: 'all checks passed';
|
|
96
|
+
return {
|
|
97
|
+
success: warnings.length === 0,
|
|
98
|
+
summary,
|
|
99
|
+
data: { healed, warnings },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Try extracting a PAT from git remote URL (https://<pat>@github.com/...) */
|
|
104
|
+
async function extractPatFromRemote(cwd) {
|
|
105
|
+
try {
|
|
106
|
+
const { stdout } = await execFileAsync('git', ['config', '--get', 'remote.origin.url'], {
|
|
107
|
+
cwd,
|
|
108
|
+
timeout: 5_000,
|
|
109
|
+
});
|
|
110
|
+
const url = stdout.trim();
|
|
111
|
+
// Pattern: https://<token>@github.com/...
|
|
112
|
+
const match = url.match(/https:\/\/([^@]+)@github\.com/);
|
|
113
|
+
if (match && match[1] && match[1] !== 'oauth2') {
|
|
114
|
+
return match[1];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch { /* not available */ }
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/** Get free disk space in bytes for the drive containing the given path. */
|
|
121
|
+
async function getFreeDiskSpace(dirPath) {
|
|
122
|
+
const platform = process.platform;
|
|
123
|
+
if (platform === 'win32') {
|
|
124
|
+
const drive = path.parse(path.resolve(dirPath)).root;
|
|
125
|
+
const { stdout } = await execFileAsync('wmic', [
|
|
126
|
+
'logicaldisk', 'where', `DeviceID='${drive.replace('\\', '')}'`,
|
|
127
|
+
'get', 'FreeSpace', '/value',
|
|
128
|
+
], { timeout: 5_000 });
|
|
129
|
+
const match = stdout.match(/FreeSpace=(\d+)/);
|
|
130
|
+
return match ? parseInt(match[1], 10) : Infinity;
|
|
131
|
+
}
|
|
132
|
+
// Unix: use df
|
|
133
|
+
const { stdout } = await execFileAsync('df', ['--output=avail', '-B1', dirPath], {
|
|
134
|
+
timeout: 5_000,
|
|
135
|
+
});
|
|
136
|
+
const lines = stdout.trim().split('\n');
|
|
137
|
+
return parseInt(lines[lines.length - 1].trim(), 10) || Infinity;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=health-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-check.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/health-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat capability — write status JSON every round.
|
|
3
|
+
*
|
|
4
|
+
* Ported from ralph-watch.ps1 `Update-Heartbeat`.
|
|
5
|
+
* Writes to `.squad/ralph-heartbeat.json` every round with:
|
|
6
|
+
* - round number, status, PID, timestamp
|
|
7
|
+
* - consecutive failures counter
|
|
8
|
+
* - duration of last round
|
|
9
|
+
*
|
|
10
|
+
* Also maintains a structured log at `.squad/ralph-watch.log` with rotation.
|
|
11
|
+
*
|
|
12
|
+
* Runs in the `housekeeping` phase.
|
|
13
|
+
*
|
|
14
|
+
* Config (via squad.config.ts → watch.capabilities["heartbeat"]):
|
|
15
|
+
* heartbeatPath – override heartbeat file location (default: .squad/ralph-heartbeat.json)
|
|
16
|
+
* logPath – override log file location (default: .squad/ralph-watch.log)
|
|
17
|
+
* maxLogEntries – max log lines before rotation (default: 500)
|
|
18
|
+
* maxLogBytes – max log file size before rotation (default: 1MB)
|
|
19
|
+
*/
|
|
20
|
+
import type { WatchCapability, WatchContext, PreflightResult, CapabilityResult } from '../types.js';
|
|
21
|
+
export interface HeartbeatData {
|
|
22
|
+
lastRun: string;
|
|
23
|
+
lastHeartbeat: string;
|
|
24
|
+
round: number;
|
|
25
|
+
status: string;
|
|
26
|
+
exitCode: number;
|
|
27
|
+
durationSeconds: number;
|
|
28
|
+
consecutiveFailures: number;
|
|
29
|
+
pid: number;
|
|
30
|
+
}
|
|
31
|
+
export declare class HeartbeatCapability implements WatchCapability {
|
|
32
|
+
readonly name = "heartbeat";
|
|
33
|
+
readonly description = "Write heartbeat JSON and structured log every round";
|
|
34
|
+
readonly configShape: "object";
|
|
35
|
+
readonly requires: never[];
|
|
36
|
+
readonly phase: "housekeeping";
|
|
37
|
+
preflight(_context: WatchContext): Promise<PreflightResult>;
|
|
38
|
+
execute(context: WatchContext): Promise<CapabilityResult>;
|
|
39
|
+
}
|
|
40
|
+
/** Increment consecutive failure counter (called by the main loop on error). */
|
|
41
|
+
export declare function recordFailure(): void;
|
|
42
|
+
/** Reset consecutive failure counter (called by the main loop on success). */
|
|
43
|
+
export declare function recordSuccess(): void;
|
|
44
|
+
/** Get current consecutive failure count. */
|
|
45
|
+
export declare function getConsecutiveFailures(): number;
|
|
46
|
+
/** Mark round start time for duration tracking. */
|
|
47
|
+
export declare function markRoundStart(): void;
|
|
48
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/heartbeat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpG,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAMD,qBAAa,mBAAoB,YAAW,eAAe;IACzD,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,yDAAyD;IAC7E,QAAQ,CAAC,WAAW,EAAG,QAAQ,CAAU;IACzC,QAAQ,CAAC,QAAQ,UAAM;IACvB,QAAQ,CAAC,KAAK,EAAG,cAAc,CAAU;IAEnC,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC;IAI3D,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;CA2ChE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,IAAI,CAEpC;AAED,6CAA6C;AAC7C,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED,mDAAmD;AACnD,wBAAgB,cAAc,IAAI,IAAI,CAErC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat capability — write status JSON every round.
|
|
3
|
+
*
|
|
4
|
+
* Ported from ralph-watch.ps1 `Update-Heartbeat`.
|
|
5
|
+
* Writes to `.squad/ralph-heartbeat.json` every round with:
|
|
6
|
+
* - round number, status, PID, timestamp
|
|
7
|
+
* - consecutive failures counter
|
|
8
|
+
* - duration of last round
|
|
9
|
+
*
|
|
10
|
+
* Also maintains a structured log at `.squad/ralph-watch.log` with rotation.
|
|
11
|
+
*
|
|
12
|
+
* Runs in the `housekeeping` phase.
|
|
13
|
+
*
|
|
14
|
+
* Config (via squad.config.ts → watch.capabilities["heartbeat"]):
|
|
15
|
+
* heartbeatPath – override heartbeat file location (default: .squad/ralph-heartbeat.json)
|
|
16
|
+
* logPath – override log file location (default: .squad/ralph-watch.log)
|
|
17
|
+
* maxLogEntries – max log lines before rotation (default: 500)
|
|
18
|
+
* maxLogBytes – max log file size before rotation (default: 1MB)
|
|
19
|
+
*/
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import fs from 'node:fs';
|
|
22
|
+
// Module-level state tracked across rounds
|
|
23
|
+
let consecutiveFailures = 0;
|
|
24
|
+
let lastRoundStart = Date.now();
|
|
25
|
+
export class HeartbeatCapability {
|
|
26
|
+
name = 'heartbeat';
|
|
27
|
+
description = 'Write heartbeat JSON and structured log every round';
|
|
28
|
+
configShape = 'object';
|
|
29
|
+
requires = [];
|
|
30
|
+
phase = 'housekeeping';
|
|
31
|
+
async preflight(_context) {
|
|
32
|
+
return { ok: true };
|
|
33
|
+
}
|
|
34
|
+
async execute(context) {
|
|
35
|
+
const config = context.config;
|
|
36
|
+
const squadDir = path.join(context.teamRoot, '.squad');
|
|
37
|
+
const heartbeatPath = config['heartbeatPath'] ?? path.join(squadDir, 'ralph-heartbeat.json');
|
|
38
|
+
const logPath = config['logPath'] ?? path.join(squadDir, 'ralph-watch.log');
|
|
39
|
+
const maxLogEntries = config['maxLogEntries'] ?? 500;
|
|
40
|
+
const maxLogBytes = config['maxLogBytes'] ?? 1_048_576; // 1 MB
|
|
41
|
+
const now = new Date();
|
|
42
|
+
const durationSeconds = Math.round((Date.now() - lastRoundStart) / 1000 * 100) / 100;
|
|
43
|
+
lastRoundStart = Date.now();
|
|
44
|
+
// Write heartbeat
|
|
45
|
+
const heartbeat = {
|
|
46
|
+
lastRun: now.toISOString(),
|
|
47
|
+
lastHeartbeat: now.toISOString(),
|
|
48
|
+
round: context.round,
|
|
49
|
+
status: 'idle',
|
|
50
|
+
exitCode: 0,
|
|
51
|
+
durationSeconds,
|
|
52
|
+
consecutiveFailures,
|
|
53
|
+
pid: process.pid,
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
ensureDir(path.dirname(heartbeatPath));
|
|
57
|
+
fs.writeFileSync(heartbeatPath, JSON.stringify(heartbeat, null, 2), 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
catch { /* best-effort */ }
|
|
60
|
+
// Append structured log entry
|
|
61
|
+
const logEntry = `${now.toISOString()} | Round=${context.round} | Duration=${durationSeconds}s | Failures=${consecutiveFailures} | Status=idle`;
|
|
62
|
+
try {
|
|
63
|
+
ensureDir(path.dirname(logPath));
|
|
64
|
+
fs.appendFileSync(logPath, logEntry + '\n', 'utf-8');
|
|
65
|
+
rotateLog(logPath, maxLogEntries, maxLogBytes);
|
|
66
|
+
}
|
|
67
|
+
catch { /* best-effort */ }
|
|
68
|
+
return {
|
|
69
|
+
success: true,
|
|
70
|
+
summary: `heartbeat written (round ${context.round})`,
|
|
71
|
+
data: { heartbeatPath, durationSeconds },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Increment consecutive failure counter (called by the main loop on error). */
|
|
76
|
+
export function recordFailure() {
|
|
77
|
+
consecutiveFailures++;
|
|
78
|
+
}
|
|
79
|
+
/** Reset consecutive failure counter (called by the main loop on success). */
|
|
80
|
+
export function recordSuccess() {
|
|
81
|
+
consecutiveFailures = 0;
|
|
82
|
+
}
|
|
83
|
+
/** Get current consecutive failure count. */
|
|
84
|
+
export function getConsecutiveFailures() {
|
|
85
|
+
return consecutiveFailures;
|
|
86
|
+
}
|
|
87
|
+
/** Mark round start time for duration tracking. */
|
|
88
|
+
export function markRoundStart() {
|
|
89
|
+
lastRoundStart = Date.now();
|
|
90
|
+
}
|
|
91
|
+
function ensureDir(dir) {
|
|
92
|
+
if (!fs.existsSync(dir)) {
|
|
93
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function rotateLog(logPath, maxEntries, maxBytes) {
|
|
97
|
+
try {
|
|
98
|
+
const stat = fs.statSync(logPath);
|
|
99
|
+
let needsRotation = stat.size > maxBytes;
|
|
100
|
+
if (!needsRotation) {
|
|
101
|
+
const content = fs.readFileSync(logPath, 'utf-8');
|
|
102
|
+
const lines = content.split('\n').filter(Boolean);
|
|
103
|
+
needsRotation = lines.length > maxEntries;
|
|
104
|
+
}
|
|
105
|
+
if (needsRotation) {
|
|
106
|
+
const content = fs.readFileSync(logPath, 'utf-8');
|
|
107
|
+
const lines = content.split('\n').filter(Boolean);
|
|
108
|
+
const kept = lines.slice(-Math.max(maxEntries - 1, 1));
|
|
109
|
+
const header = `# Ralph Watch Log — Rotated ${new Date().toISOString()} (kept last ${kept.length} entries)`;
|
|
110
|
+
fs.writeFileSync(logPath, [header, ...kept].join('\n') + '\n', 'utf-8');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch { /* best-effort */ }
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/heartbeat.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAapD,mEAAmE;AACnE,wBAAgB,qBAAqB,IAAI,kBAAkB,CAc1D"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { CapabilityRegistry } from '../registry.js';
|
|
5
5
|
import { SelfPullCapability } from './self-pull.js';
|
|
6
6
|
import { ExecuteCapability } from './execute.js';
|
|
7
|
+
import { FleetDispatchCapability } from './fleet-dispatch.js';
|
|
7
8
|
import { BoardCapability } from './board.js';
|
|
8
9
|
import { MonitorTeamsCapability } from './monitor-teams.js';
|
|
9
10
|
import { MonitorEmailCapability } from './monitor-email.js';
|
|
@@ -11,11 +12,13 @@ import { TwoPassCapability } from './two-pass.js';
|
|
|
11
12
|
import { WaveDispatchCapability } from './wave-dispatch.js';
|
|
12
13
|
import { RetroCapability } from './retro.js';
|
|
13
14
|
import { DecisionHygieneCapability } from './decision-hygiene.js';
|
|
15
|
+
import { CleanupCapability } from './cleanup.js';
|
|
14
16
|
/** Create a registry pre-loaded with all built-in capabilities. */
|
|
15
17
|
export function createDefaultRegistry() {
|
|
16
18
|
const registry = new CapabilityRegistry();
|
|
17
19
|
registry.register(new SelfPullCapability());
|
|
18
20
|
registry.register(new ExecuteCapability());
|
|
21
|
+
registry.register(new FleetDispatchCapability());
|
|
19
22
|
registry.register(new BoardCapability());
|
|
20
23
|
registry.register(new MonitorTeamsCapability());
|
|
21
24
|
registry.register(new MonitorEmailCapability());
|
|
@@ -23,6 +26,7 @@ export function createDefaultRegistry() {
|
|
|
23
26
|
registry.register(new WaveDispatchCapability());
|
|
24
27
|
registry.register(new RetroCapability());
|
|
25
28
|
registry.register(new DecisionHygieneCapability());
|
|
29
|
+
registry.register(new CleanupCapability());
|
|
26
30
|
return registry;
|
|
27
31
|
}
|
|
28
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/cli/commands/watch/capabilities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,mEAAmE;AACnE,MAAM,UAAU,qBAAqB;IACnC,MAAM,QAAQ,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC1C,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,IAAI,uBAAuB,EAAE,CAAC,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC;IAChD,QAAQ,CAAC,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,IAAI,yBAAyB,EAAE,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAC3C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|