hub-launch 1.16.0 → 1.18.0
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/CHANGELOG.md +14 -0
- package/README.md +102 -2
- package/dist/commands/init.d.ts +61 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +125 -114
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/instructions.d.ts +17 -0
- package/dist/commands/instructions.d.ts.map +1 -0
- package/dist/commands/instructions.js +51 -0
- package/dist/commands/instructions.js.map +1 -0
- package/dist/commands/launch.d.ts +21 -0
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +61 -0
- package/dist/commands/launch.js.map +1 -1
- package/dist/commands/script.d.ts +28 -0
- package/dist/commands/script.d.ts.map +1 -0
- package/dist/commands/script.js +69 -0
- package/dist/commands/script.js.map +1 -0
- package/dist/commands/session-hook.d.ts +26 -0
- package/dist/commands/session-hook.d.ts.map +1 -0
- package/dist/commands/session-hook.js +146 -0
- package/dist/commands/session-hook.js.map +1 -0
- package/dist/index.js +22 -1
- package/dist/index.js.map +1 -1
- package/dist/scripts/fix-commit.d.ts +2 -0
- package/dist/scripts/fix-commit.d.ts.map +1 -0
- package/dist/scripts/fix-commit.js +125 -0
- package/dist/scripts/fix-commit.js.map +1 -0
- package/dist/scripts/fix-setup.d.ts +2 -0
- package/dist/scripts/fix-setup.d.ts.map +1 -0
- package/dist/scripts/fix-setup.js +161 -0
- package/dist/scripts/fix-setup.js.map +1 -0
- package/dist/scripts/launch-run.d.ts +14 -0
- package/dist/scripts/launch-run.d.ts.map +1 -0
- package/dist/scripts/launch-run.js +117 -0
- package/dist/scripts/launch-run.js.map +1 -0
- package/dist/scripts/lib/exec.d.ts +48 -0
- package/dist/scripts/lib/exec.d.ts.map +1 -0
- package/dist/scripts/lib/exec.js +61 -0
- package/dist/scripts/lib/exec.js.map +1 -0
- package/dist/scripts/lib/io.d.ts +48 -0
- package/dist/scripts/lib/io.d.ts.map +1 -0
- package/dist/scripts/lib/io.js +72 -0
- package/dist/scripts/lib/io.js.map +1 -0
- package/dist/scripts/lib/read-config.d.ts +26 -0
- package/dist/scripts/lib/read-config.d.ts.map +1 -0
- package/dist/scripts/lib/read-config.js +65 -0
- package/dist/scripts/lib/read-config.js.map +1 -0
- package/dist/scripts/merge-local.d.ts +2 -0
- package/dist/scripts/merge-local.d.ts.map +1 -0
- package/dist/scripts/merge-local.js +146 -0
- package/dist/scripts/merge-local.js.map +1 -0
- package/dist/scripts/merge-remote.d.ts +12 -0
- package/dist/scripts/merge-remote.d.ts.map +1 -0
- package/dist/scripts/merge-remote.js +71 -0
- package/dist/scripts/merge-remote.js.map +1 -0
- package/dist/scripts/schedule-manage.d.ts +2 -0
- package/dist/scripts/schedule-manage.d.ts.map +1 -0
- package/dist/scripts/schedule-manage.js +151 -0
- package/dist/scripts/schedule-manage.js.map +1 -0
- package/dist/scripts/schedule-run.d.ts +2 -0
- package/dist/scripts/schedule-run.d.ts.map +1 -0
- package/dist/scripts/schedule-run.js +146 -0
- package/dist/scripts/schedule-run.js.map +1 -0
- package/dist/scripts/verify-gather.d.ts +2 -0
- package/dist/scripts/verify-gather.d.ts.map +1 -0
- package/dist/scripts/verify-gather.js +206 -0
- package/dist/scripts/verify-gather.js.map +1 -0
- package/dist/scripts/verify-post.d.ts +12 -0
- package/dist/scripts/verify-post.d.ts.map +1 -0
- package/dist/scripts/verify-post.js +91 -0
- package/dist/scripts/verify-post.js.map +1 -0
- package/dist/templates/planning-instructions.md +7 -7
- package/dist/templates/skill-creation-instructions.md +2 -2
- package/dist/templates/skills/hula-confirm/SKILL.md +3 -3
- package/dist/templates/skills/hula-fix/SKILL.md +3 -3
- package/dist/templates/skills/hula-help/SKILL.md +117 -0
- package/dist/templates/skills/hula-launch/SKILL.md +14 -8
- package/dist/templates/skills/hula-merge/SKILL.md +2 -2
- package/dist/templates/skills/hula-plan/SKILL.md +5 -5
- package/dist/templates/skills/hula-schedule/SKILL.md +16 -16
- package/dist/templates/skills/hula-verify/SKILL.md +32 -33
- package/dist/types/config.schema.d.ts +235 -0
- package/dist/types/config.schema.d.ts.map +1 -1
- package/dist/types/config.schema.js +66 -0
- package/dist/types/config.schema.js.map +1 -1
- package/dist/utils/client-session.d.ts +2 -2
- package/dist/utils/client-session.js +2 -2
- package/package.json +6 -5
- package/scripts/postinstall.mjs +102 -0
- package/dist/templates/scripts/hula-fix-commit.sh +0 -114
- package/dist/templates/scripts/hula-fix-setup.sh +0 -152
- package/dist/templates/scripts/hula-launch-run.sh +0 -140
- package/dist/templates/scripts/hula-merge-local.sh +0 -138
- package/dist/templates/scripts/hula-merge-remote.sh +0 -94
- package/dist/templates/scripts/hula-read-config.sh +0 -38
- package/dist/templates/scripts/hula-schedule-manage.sh +0 -159
- package/dist/templates/scripts/hula-schedule-run.sh +0 -148
- package/dist/templates/scripts/hula-session-hook.sh +0 -68
- package/dist/templates/scripts/hula-verify-gather.sh +0 -135
- package/dist/templates/scripts/hula-verify-post.sh +0 -84
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* merge-remote — Path B of the hula.merge workflow (remote-only merge).
|
|
3
|
+
* Invoked as: `hula script merge-remote -- <issue-number> [--session-path <path>]`
|
|
4
|
+
*
|
|
5
|
+
* Merges the PR directly on GitHub, then optionally cleans up a stale session
|
|
6
|
+
* file. Emits structured JSON to stdout; all other output goes to stderr.
|
|
7
|
+
* Exit codes: 0=success, 1=user error, 2=tool error.
|
|
8
|
+
*
|
|
9
|
+
* Node port of `hula-merge-remote.sh` (cross-platform: no bash, no jq).
|
|
10
|
+
*/
|
|
11
|
+
export declare function main(args: string[]): Promise<number>;
|
|
12
|
+
//# sourceMappingURL=merge-remote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-remote.d.ts","sourceRoot":"","sources":["../../src/scripts/merge-remote.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAoEpD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { rm } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { runHula } from './lib/exec.js';
|
|
5
|
+
import { emitJson, fail, logStderr, runScript } from './lib/io.js';
|
|
6
|
+
import { resolveRepoRoot } from './lib/read-config.js';
|
|
7
|
+
/**
|
|
8
|
+
* merge-remote — Path B of the hula.merge workflow (remote-only merge).
|
|
9
|
+
* Invoked as: `hula script merge-remote -- <issue-number> [--session-path <path>]`
|
|
10
|
+
*
|
|
11
|
+
* Merges the PR directly on GitHub, then optionally cleans up a stale session
|
|
12
|
+
* file. Emits structured JSON to stdout; all other output goes to stderr.
|
|
13
|
+
* Exit codes: 0=success, 1=user error, 2=tool error.
|
|
14
|
+
*
|
|
15
|
+
* Node port of `hula-merge-remote.sh` (cross-platform: no bash, no jq).
|
|
16
|
+
*/
|
|
17
|
+
export function main(args) {
|
|
18
|
+
return runScript(async () => {
|
|
19
|
+
// ── argument parsing ──────────────────────────────────────────────────
|
|
20
|
+
let issueNumber = '';
|
|
21
|
+
let sessionPath = '';
|
|
22
|
+
for (let i = 0; i < args.length; i++) {
|
|
23
|
+
const a = args[i];
|
|
24
|
+
if (a === '--session-path') {
|
|
25
|
+
sessionPath = args[++i] ?? '';
|
|
26
|
+
}
|
|
27
|
+
else if (a.startsWith('--session-path=')) {
|
|
28
|
+
sessionPath = a.slice('--session-path='.length);
|
|
29
|
+
}
|
|
30
|
+
else if (/^[0-9]/.test(a)) {
|
|
31
|
+
issueNumber = a;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
fail(1, `Unknown argument: ${a}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!issueNumber) {
|
|
38
|
+
fail(1, 'Usage: hula script merge-remote -- <issue-number> [--session-path <path>]');
|
|
39
|
+
}
|
|
40
|
+
// ── Step B1: Merge the PR via hula CLI ────────────────────────────────
|
|
41
|
+
logStderr(`🔀 Merging PR for issue #${issueNumber} (remote-only)...`);
|
|
42
|
+
const merge = await runHula(['merge', issueNumber]);
|
|
43
|
+
const mergeOutput = `${merge.stdout}${merge.stderr}`;
|
|
44
|
+
logStderr(mergeOutput);
|
|
45
|
+
if (merge.code !== 0) {
|
|
46
|
+
fail(2, `Failed to merge PR for issue #${issueNumber}. Check the PR on GitHub.`);
|
|
47
|
+
}
|
|
48
|
+
// Detect whether `hula merge` fast-forwarded the local default branch.
|
|
49
|
+
const localUpdated = /Local.*fast-forwarded/.test(mergeOutput);
|
|
50
|
+
// ── Step B2: Clean up stale session file (if applicable) ──────────────
|
|
51
|
+
let resolvedSessionPath = sessionPath;
|
|
52
|
+
if (!resolvedSessionPath) {
|
|
53
|
+
const repoRoot = await resolveRepoRoot();
|
|
54
|
+
resolvedSessionPath = join(repoRoot, '.hublaunch', '.fix-sessions', `issue-${issueNumber}.json`);
|
|
55
|
+
}
|
|
56
|
+
let sessionCleaned = false;
|
|
57
|
+
if (existsSync(resolvedSessionPath)) {
|
|
58
|
+
await rm(resolvedSessionPath, { force: true });
|
|
59
|
+
sessionCleaned = true;
|
|
60
|
+
logStderr('🧹 Cleaned up stale session file');
|
|
61
|
+
}
|
|
62
|
+
// ── Output result ─────────────────────────────────────────────────────
|
|
63
|
+
emitJson({
|
|
64
|
+
status: 'success',
|
|
65
|
+
issueNumber: Number(issueNumber),
|
|
66
|
+
sessionCleaned,
|
|
67
|
+
localUpdated,
|
|
68
|
+
});
|
|
69
|
+
}, args);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=merge-remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-remote.js","sourceRoot":"","sources":["../../src/scripts/merge-remote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-manage.d.ts","sourceRoot":"","sources":["../../src/scripts/schedule-manage.ts"],"names":[],"mappings":"AAoDA,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4IpD"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { runHula } from './lib/exec.js';
|
|
2
|
+
import { emitJson, fail, logStderr, runScript } from './lib/io.js';
|
|
3
|
+
/** First line matching `^\s*<label>:` with the label + surrounding space stripped. */
|
|
4
|
+
function extractField(output, label) {
|
|
5
|
+
const re = new RegExp(`^\\s*${label}:\\s*(.*)$`);
|
|
6
|
+
for (const line of output.split('\n')) {
|
|
7
|
+
const m = line.match(re);
|
|
8
|
+
if (m)
|
|
9
|
+
return (m[1] ?? '').trim();
|
|
10
|
+
}
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
/** Validate a skill path: repo-relative, under .hublaunch/skills/, no traversal. */
|
|
14
|
+
function validateSkillPath(p) {
|
|
15
|
+
if (p.startsWith('/')) {
|
|
16
|
+
fail(1, `Skill path must be repo-relative, not absolute: ${p}`);
|
|
17
|
+
}
|
|
18
|
+
if (p.includes('..')) {
|
|
19
|
+
fail(1, `Invalid skill path (path traversal not allowed): ${p}`);
|
|
20
|
+
}
|
|
21
|
+
if (!p.startsWith('.hublaunch/skills/')) {
|
|
22
|
+
fail(1, `Skill path must be under .hublaunch/skills/ — got ${p}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function main(args) {
|
|
26
|
+
return runScript(async () => {
|
|
27
|
+
// ── argument parsing (exactly one action flag per call) ───────────────
|
|
28
|
+
let action = '';
|
|
29
|
+
let arg = '';
|
|
30
|
+
const setAction = (name, token) => {
|
|
31
|
+
if (action) {
|
|
32
|
+
fail(1, `Provide exactly one action (got --${action} and ${token}).`);
|
|
33
|
+
}
|
|
34
|
+
action = name;
|
|
35
|
+
};
|
|
36
|
+
const withArg = {
|
|
37
|
+
'--show': 'show',
|
|
38
|
+
'--run-now': 'run-now',
|
|
39
|
+
'--cancel-schedule': 'cancel-schedule',
|
|
40
|
+
'--publish-skill': 'publish-skill',
|
|
41
|
+
'--delete-skill': 'delete-skill',
|
|
42
|
+
};
|
|
43
|
+
for (let i = 0; i < args.length; i++) {
|
|
44
|
+
const a = args[i];
|
|
45
|
+
if (a === '--list') {
|
|
46
|
+
setAction('list', a);
|
|
47
|
+
}
|
|
48
|
+
else if (a === '--list-schedules') {
|
|
49
|
+
setAction('list-schedules', a);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Handle the value-taking flags in both `--flag val` and `--flag=val` forms.
|
|
53
|
+
let matched = false;
|
|
54
|
+
for (const [flag, name] of Object.entries(withArg)) {
|
|
55
|
+
if (a === flag) {
|
|
56
|
+
setAction(name, a);
|
|
57
|
+
arg = args[++i] ?? '';
|
|
58
|
+
matched = true;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
if (a.startsWith(`${flag}=`)) {
|
|
62
|
+
setAction(name, a);
|
|
63
|
+
arg = a.slice(`${flag}=`.length);
|
|
64
|
+
matched = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!matched) {
|
|
69
|
+
fail(1, `Unexpected argument: ${a}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (!action) {
|
|
74
|
+
fail(1, 'Usage: hula script schedule-manage -- (--list | --list-schedules | --show <id> | --run-now <id> | --cancel-schedule <id> | --publish-skill <path> | --delete-skill <path>)');
|
|
75
|
+
}
|
|
76
|
+
// Actions that require an argument.
|
|
77
|
+
if (['show', 'run-now', 'cancel-schedule', 'publish-skill', 'delete-skill'].includes(action) &&
|
|
78
|
+
!arg) {
|
|
79
|
+
fail(1, `--${action} requires an argument.`);
|
|
80
|
+
}
|
|
81
|
+
// Path validation for skill file actions.
|
|
82
|
+
if (action === 'publish-skill' || action === 'delete-skill') {
|
|
83
|
+
validateSkillPath(arg);
|
|
84
|
+
}
|
|
85
|
+
// ── Build and run the hula schedule invocation ────────────────────────
|
|
86
|
+
const cliArgs = ['schedule'];
|
|
87
|
+
switch (action) {
|
|
88
|
+
case 'list':
|
|
89
|
+
cliArgs.push('--list');
|
|
90
|
+
break;
|
|
91
|
+
case 'list-schedules':
|
|
92
|
+
cliArgs.push('--list-schedules');
|
|
93
|
+
break;
|
|
94
|
+
case 'show':
|
|
95
|
+
cliArgs.push('--show', arg);
|
|
96
|
+
break;
|
|
97
|
+
case 'run-now':
|
|
98
|
+
cliArgs.push('--run-now', arg);
|
|
99
|
+
break;
|
|
100
|
+
case 'cancel-schedule':
|
|
101
|
+
cliArgs.push('--cancel-schedule', arg);
|
|
102
|
+
break;
|
|
103
|
+
case 'publish-skill':
|
|
104
|
+
cliArgs.push('--publish-skill', arg);
|
|
105
|
+
break;
|
|
106
|
+
case 'delete-skill':
|
|
107
|
+
cliArgs.push('--delete-skill', arg);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
logStderr(`⚙️ hula schedule --${action}...`);
|
|
111
|
+
const res = await runHula(cliArgs);
|
|
112
|
+
const output = `${res.stdout}${res.stderr}`;
|
|
113
|
+
if (res.code !== 0) {
|
|
114
|
+
fail(2, `Management action failed: ${output}`);
|
|
115
|
+
}
|
|
116
|
+
// ── Emit the structured JSON result ───────────────────────────────────
|
|
117
|
+
switch (action) {
|
|
118
|
+
case 'list':
|
|
119
|
+
case 'list-schedules':
|
|
120
|
+
case 'show':
|
|
121
|
+
emitJson({ status: 'success', kind: action, cliOutput: output });
|
|
122
|
+
break;
|
|
123
|
+
case 'run-now':
|
|
124
|
+
emitJson({
|
|
125
|
+
status: 'success',
|
|
126
|
+
kind: 'run-now',
|
|
127
|
+
runId: extractField(output, 'ID'),
|
|
128
|
+
cliOutput: output,
|
|
129
|
+
});
|
|
130
|
+
break;
|
|
131
|
+
case 'cancel-schedule':
|
|
132
|
+
emitJson({
|
|
133
|
+
status: 'success',
|
|
134
|
+
kind: 'cancel-schedule',
|
|
135
|
+
scheduleId: arg,
|
|
136
|
+
cliOutput: output,
|
|
137
|
+
});
|
|
138
|
+
break;
|
|
139
|
+
case 'publish-skill':
|
|
140
|
+
case 'delete-skill':
|
|
141
|
+
emitJson({
|
|
142
|
+
status: 'success',
|
|
143
|
+
kind: action,
|
|
144
|
+
path: arg,
|
|
145
|
+
cliOutput: output,
|
|
146
|
+
});
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}, args);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=schedule-manage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-manage.js","sourceRoot":"","sources":["../../src/scripts/schedule-manage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-run.d.ts","sourceRoot":"","sources":["../../src/scripts/schedule-run.ts"],"names":[],"mappings":"AA2BA,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0HpD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { runHula } from './lib/exec.js';
|
|
2
|
+
import { emitJson, fail, logStderr, runScript } from './lib/io.js';
|
|
3
|
+
/**
|
|
4
|
+
* schedule-run — runs the hula schedule workflow for the /hula-schedule skill.
|
|
5
|
+
* Invoked as:
|
|
6
|
+
* `hula script schedule-run -- (--built-in <name> | --action-path <path>)
|
|
7
|
+
* [--entry-point <path>] [--outcome-type <pr|plan|feedback>]
|
|
8
|
+
* [--schedule "<cron>"] [--pr-policy <always|skip-if-open|close-previous>]
|
|
9
|
+
* [--update-notification-url <url>]`
|
|
10
|
+
*
|
|
11
|
+
* Emits a single structured JSON object to stdout; other output to stderr.
|
|
12
|
+
* Exit codes: 0=success, 1=user error, 2=tool error.
|
|
13
|
+
*
|
|
14
|
+
* Node port of `hula-schedule-run.sh` (cross-platform: no bash, no jq).
|
|
15
|
+
*/
|
|
16
|
+
/** First line matching `^\s*<label>:` with the label + surrounding space stripped. */
|
|
17
|
+
function extractField(output, label) {
|
|
18
|
+
const re = new RegExp(`^\\s*${label}:\\s*(.*)$`);
|
|
19
|
+
for (const line of output.split('\n')) {
|
|
20
|
+
const m = line.match(re);
|
|
21
|
+
if (m)
|
|
22
|
+
return (m[1] ?? '').trim();
|
|
23
|
+
}
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
export function main(args) {
|
|
27
|
+
return runScript(async () => {
|
|
28
|
+
// ── argument parsing ──────────────────────────────────────────────────
|
|
29
|
+
let builtIn = '';
|
|
30
|
+
let actionPath = '';
|
|
31
|
+
let entryPoint = '';
|
|
32
|
+
let outcomeType = '';
|
|
33
|
+
let schedule = '';
|
|
34
|
+
let prPolicy = '';
|
|
35
|
+
let updateNotificationUrl = '';
|
|
36
|
+
const takeVal = (a, i, flag) => {
|
|
37
|
+
if (a === flag)
|
|
38
|
+
return { value: args[i + 1] ?? '', next: i + 1 };
|
|
39
|
+
return { value: a.slice(`${flag}=`.length), next: i };
|
|
40
|
+
};
|
|
41
|
+
for (let i = 0; i < args.length; i++) {
|
|
42
|
+
const a = args[i];
|
|
43
|
+
if (a === '--built-in' || a.startsWith('--built-in=')) {
|
|
44
|
+
({ value: builtIn, next: i } = takeVal(a, i, '--built-in'));
|
|
45
|
+
}
|
|
46
|
+
else if (a === '--action-path' || a.startsWith('--action-path=')) {
|
|
47
|
+
({ value: actionPath, next: i } = takeVal(a, i, '--action-path'));
|
|
48
|
+
}
|
|
49
|
+
else if (a === '--entry-point' || a.startsWith('--entry-point=')) {
|
|
50
|
+
({ value: entryPoint, next: i } = takeVal(a, i, '--entry-point'));
|
|
51
|
+
}
|
|
52
|
+
else if (a === '--outcome-type' || a.startsWith('--outcome-type=')) {
|
|
53
|
+
({ value: outcomeType, next: i } = takeVal(a, i, '--outcome-type'));
|
|
54
|
+
}
|
|
55
|
+
else if (a === '--schedule' || a.startsWith('--schedule=')) {
|
|
56
|
+
({ value: schedule, next: i } = takeVal(a, i, '--schedule'));
|
|
57
|
+
}
|
|
58
|
+
else if (a === '--pr-policy' || a.startsWith('--pr-policy=')) {
|
|
59
|
+
({ value: prPolicy, next: i } = takeVal(a, i, '--pr-policy'));
|
|
60
|
+
}
|
|
61
|
+
else if (a === '--update-notification-url' ||
|
|
62
|
+
a.startsWith('--update-notification-url=')) {
|
|
63
|
+
({ value: updateNotificationUrl, next: i } = takeVal(a, i, '--update-notification-url'));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
fail(1, `Unexpected argument: ${a}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Exactly one of --built-in / --action-path is required.
|
|
70
|
+
if (builtIn && actionPath) {
|
|
71
|
+
fail(1, 'Provide either --built-in or --action-path, not both.');
|
|
72
|
+
}
|
|
73
|
+
if (!builtIn && !actionPath) {
|
|
74
|
+
fail(1, 'Usage: hula script schedule-run -- (--built-in <name> | --action-path <path>) [--entry-point <path>] [--outcome-type <pr|plan|feedback>] [--schedule "<cron>"] [--pr-policy <always|skip-if-open|close-previous>]');
|
|
75
|
+
}
|
|
76
|
+
// Reject directory-traversal in --action-path, except for https:// URLs.
|
|
77
|
+
if (actionPath && !actionPath.startsWith('https://') && actionPath.includes('..')) {
|
|
78
|
+
fail(1, `Invalid action path (path traversal not allowed): ${actionPath}`);
|
|
79
|
+
}
|
|
80
|
+
// ── Run hula schedule ─────────────────────────────────────────────────
|
|
81
|
+
const cliArgs = ['schedule'];
|
|
82
|
+
if (builtIn)
|
|
83
|
+
cliArgs.push('--built-in', builtIn);
|
|
84
|
+
else
|
|
85
|
+
cliArgs.push('--action-path', actionPath);
|
|
86
|
+
if (entryPoint)
|
|
87
|
+
cliArgs.push('--entry-point', entryPoint);
|
|
88
|
+
if (outcomeType)
|
|
89
|
+
cliArgs.push('--outcome-type', outcomeType);
|
|
90
|
+
if (schedule)
|
|
91
|
+
cliArgs.push('--schedule', schedule);
|
|
92
|
+
if (prPolicy)
|
|
93
|
+
cliArgs.push('--pr-policy', prPolicy);
|
|
94
|
+
if (updateNotificationUrl)
|
|
95
|
+
cliArgs.push('--update-notification-url', updateNotificationUrl);
|
|
96
|
+
if (schedule) {
|
|
97
|
+
logStderr(`⏰ Scheduling action (${schedule})...`);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
logStderr('🚀 Running action...');
|
|
101
|
+
}
|
|
102
|
+
const res = await runHula(cliArgs);
|
|
103
|
+
const output = `${res.stdout}${res.stderr}`;
|
|
104
|
+
if (res.code !== 0) {
|
|
105
|
+
fail(2, `Execute failed: ${output}`);
|
|
106
|
+
}
|
|
107
|
+
// ── Parse identifiers from the human-readable CLI output ──────────────
|
|
108
|
+
let kind;
|
|
109
|
+
if (output.includes('Schedule created successfully')) {
|
|
110
|
+
kind = 'schedule';
|
|
111
|
+
}
|
|
112
|
+
else if (output.includes('Execute action queued successfully')) {
|
|
113
|
+
kind = 'run';
|
|
114
|
+
}
|
|
115
|
+
else if (schedule) {
|
|
116
|
+
kind = 'schedule';
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
kind = 'run';
|
|
120
|
+
}
|
|
121
|
+
const parsedId = extractField(output, 'ID');
|
|
122
|
+
if (kind === 'schedule') {
|
|
123
|
+
let cronExpr = extractField(output, 'Cron');
|
|
124
|
+
if (!cronExpr)
|
|
125
|
+
cronExpr = schedule;
|
|
126
|
+
emitJson({
|
|
127
|
+
status: 'success',
|
|
128
|
+
kind: 'schedule',
|
|
129
|
+
scheduleId: parsedId,
|
|
130
|
+
cronExpr,
|
|
131
|
+
cliOutput: output,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const prUrl = extractField(output, 'PR');
|
|
136
|
+
emitJson({
|
|
137
|
+
status: 'success',
|
|
138
|
+
kind: 'run',
|
|
139
|
+
runId: parsedId,
|
|
140
|
+
prUrl,
|
|
141
|
+
cliOutput: output,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}, args);
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=schedule-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-run.js","sourceRoot":"","sources":["../../src/scripts/schedule-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-gather.d.ts","sourceRoot":"","sources":["../../src/scripts/verify-gather.ts"],"names":[],"mappings":"AA8DA,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0MpD"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { runGh } from './lib/exec.js';
|
|
4
|
+
import { emitJson, fail, logStderr, runScript } from './lib/io.js';
|
|
5
|
+
import { resolveRepoRoot } from './lib/read-config.js';
|
|
6
|
+
/**
|
|
7
|
+
* verify-gather — Steps 2-5 of the hula.verify workflow.
|
|
8
|
+
* Invoked as: `hula script verify-gather -- <issue-number> [--repo-root <path>]`
|
|
9
|
+
*
|
|
10
|
+
* Fetches issue details, finds the associated PR, gathers PR files and diff.
|
|
11
|
+
* Emits structured JSON to stdout; all other output goes to stderr.
|
|
12
|
+
* Exit codes: 0=success, 1=user error, 2=tool error.
|
|
13
|
+
*
|
|
14
|
+
* Node port of `hula-verify-gather.sh` (cross-platform: no bash, no jq).
|
|
15
|
+
*/
|
|
16
|
+
function prBodyMatchesIssue(body, issue) {
|
|
17
|
+
const re = new RegExp(`(Fixes|Closes|Resolves)[ ]+([A-Za-z0-9._-]+/[A-Za-z0-9._-]+)?#${issue}([^0-9]|$)` +
|
|
18
|
+
`|(^|[^0-9])#${issue}([^0-9]|$)`, 'i');
|
|
19
|
+
return re.test(body);
|
|
20
|
+
}
|
|
21
|
+
/** Categorize a changed file path (first match wins, mirroring the bash case). */
|
|
22
|
+
function categorize(p) {
|
|
23
|
+
if (/\.test\./.test(p) ||
|
|
24
|
+
/\.spec\./.test(p) ||
|
|
25
|
+
p.includes('/__tests__/') ||
|
|
26
|
+
p.includes('/test/') ||
|
|
27
|
+
p.includes('/tests/')) {
|
|
28
|
+
return 'test';
|
|
29
|
+
}
|
|
30
|
+
if (p.endsWith('.md') ||
|
|
31
|
+
p.startsWith('docs/') ||
|
|
32
|
+
p.startsWith('README') ||
|
|
33
|
+
p.startsWith('CHANGELOG') ||
|
|
34
|
+
p.startsWith('DOCUMENTATION')) {
|
|
35
|
+
return 'doc';
|
|
36
|
+
}
|
|
37
|
+
if (p === 'package.json' ||
|
|
38
|
+
p === 'package-lock.json' ||
|
|
39
|
+
p.startsWith('tsconfig') ||
|
|
40
|
+
/\.config\./.test(p) ||
|
|
41
|
+
p.endsWith('.json') ||
|
|
42
|
+
p.endsWith('.yaml') ||
|
|
43
|
+
p.endsWith('.yml')) {
|
|
44
|
+
return 'config';
|
|
45
|
+
}
|
|
46
|
+
return 'code';
|
|
47
|
+
}
|
|
48
|
+
export function main(args) {
|
|
49
|
+
return runScript(async () => {
|
|
50
|
+
// ── argument parsing ──────────────────────────────────────────────────
|
|
51
|
+
let issueNumber = '';
|
|
52
|
+
let repoRootArg = '';
|
|
53
|
+
for (let i = 0; i < args.length; i++) {
|
|
54
|
+
const a = args[i];
|
|
55
|
+
if (a === '--repo-root') {
|
|
56
|
+
repoRootArg = args[++i] ?? '';
|
|
57
|
+
}
|
|
58
|
+
else if (a.startsWith('--repo-root=')) {
|
|
59
|
+
repoRootArg = a.slice('--repo-root='.length);
|
|
60
|
+
}
|
|
61
|
+
else if (/^[0-9]/.test(a)) {
|
|
62
|
+
issueNumber = a;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
fail(1, `Unknown argument: ${a}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!issueNumber) {
|
|
69
|
+
fail(1, 'Usage: hula script verify-gather -- <issue-number> [--repo-root <path>]');
|
|
70
|
+
}
|
|
71
|
+
const cwd = repoRootArg || undefined;
|
|
72
|
+
// Resolve the repo root and ensure the repo-local tmp directory exists so
|
|
73
|
+
// the diff (and later the report/comment scratch files) land inside the
|
|
74
|
+
// project root — no permission prompt, and gitignored.
|
|
75
|
+
const repoRoot = await resolveRepoRoot(cwd);
|
|
76
|
+
const tmpDir = join(repoRoot, '.hublaunch', 'tmp');
|
|
77
|
+
await mkdir(tmpDir, { recursive: true });
|
|
78
|
+
// ── Step 2: Fetch issue details ───────────────────────────────────────
|
|
79
|
+
logStderr(`🔍 Fetching issue #${issueNumber}...`);
|
|
80
|
+
const issueRes = await runGh(['issue', 'view', issueNumber, '--json', 'title,body,number,url,state'], { cwd });
|
|
81
|
+
if (issueRes.code !== 0) {
|
|
82
|
+
fail(1, `Issue #${issueNumber} not found or not accessible.`);
|
|
83
|
+
}
|
|
84
|
+
const issue = JSON.parse(issueRes.stdout);
|
|
85
|
+
const issueTitle = issue.title ?? '';
|
|
86
|
+
const issueState = issue.state ?? '';
|
|
87
|
+
const issueUrl = issue.url ?? '';
|
|
88
|
+
// ── Step 3: Find associated PR ────────────────────────────────────────
|
|
89
|
+
logStderr(`🔗 Looking for PR linked to issue #${issueNumber}...`);
|
|
90
|
+
let prNumber = '';
|
|
91
|
+
const linked = await runGh([
|
|
92
|
+
'pr',
|
|
93
|
+
'list',
|
|
94
|
+
'--search',
|
|
95
|
+
`linked:${issueNumber}`,
|
|
96
|
+
'--json',
|
|
97
|
+
'number',
|
|
98
|
+
'-q',
|
|
99
|
+
'.[0].number',
|
|
100
|
+
], { cwd });
|
|
101
|
+
if (linked.code === 0)
|
|
102
|
+
prNumber = linked.stdout.trim();
|
|
103
|
+
if (!prNumber) {
|
|
104
|
+
const listRes = await runGh(['pr', 'list', '--json', 'number,body', '--limit', '100'], { cwd });
|
|
105
|
+
if (listRes.code === 0) {
|
|
106
|
+
try {
|
|
107
|
+
const prs = JSON.parse(listRes.stdout);
|
|
108
|
+
const match = prs.find((pr) => typeof pr.body === 'string' &&
|
|
109
|
+
prBodyMatchesIssue(pr.body, issueNumber));
|
|
110
|
+
if (match?.number !== undefined)
|
|
111
|
+
prNumber = String(match.number);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// ignore parse failure
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!prNumber) {
|
|
119
|
+
fail(1, `No PR found for issue #${issueNumber}. The implementation may not have started yet.`);
|
|
120
|
+
}
|
|
121
|
+
// Fetch full PR details.
|
|
122
|
+
const prRes = await runGh([
|
|
123
|
+
'pr',
|
|
124
|
+
'view',
|
|
125
|
+
prNumber,
|
|
126
|
+
'--json',
|
|
127
|
+
'number,title,url,state,headRefName,isDraft',
|
|
128
|
+
], { cwd });
|
|
129
|
+
if (prRes.code !== 0) {
|
|
130
|
+
fail(2, `Failed to fetch details for PR #${prNumber}.`);
|
|
131
|
+
}
|
|
132
|
+
const pr = JSON.parse(prRes.stdout);
|
|
133
|
+
const prTitle = pr.title ?? '';
|
|
134
|
+
const prUrl = pr.url ?? '';
|
|
135
|
+
const prState = pr.state ?? '';
|
|
136
|
+
const prBranch = pr.headRefName ?? '';
|
|
137
|
+
const prIsDraft = pr.isDraft ?? false;
|
|
138
|
+
// ── Step 4: Fetch PR file changes ─────────────────────────────────────
|
|
139
|
+
logStderr(`📊 Fetching changed files for PR #${prNumber}...`);
|
|
140
|
+
const filesRes = await runGh(['pr', 'view', prNumber, '--json', 'files,additions,deletions'], { cwd });
|
|
141
|
+
if (filesRes.code !== 0) {
|
|
142
|
+
fail(2, `Failed to fetch PR files for PR #${prNumber}.`);
|
|
143
|
+
}
|
|
144
|
+
const filesData = JSON.parse(filesRes.stdout);
|
|
145
|
+
const totalAdditions = filesData.additions ?? 0;
|
|
146
|
+
const totalDeletions = filesData.deletions ?? 0;
|
|
147
|
+
let codeCount = 0;
|
|
148
|
+
let testCount = 0;
|
|
149
|
+
let docCount = 0;
|
|
150
|
+
let configCount = 0;
|
|
151
|
+
let totalCount = 0;
|
|
152
|
+
for (const f of filesData.files ?? []) {
|
|
153
|
+
const p = f.path;
|
|
154
|
+
if (!p)
|
|
155
|
+
continue;
|
|
156
|
+
totalCount++;
|
|
157
|
+
switch (categorize(p)) {
|
|
158
|
+
case 'test':
|
|
159
|
+
testCount++;
|
|
160
|
+
break;
|
|
161
|
+
case 'doc':
|
|
162
|
+
docCount++;
|
|
163
|
+
break;
|
|
164
|
+
case 'config':
|
|
165
|
+
configCount++;
|
|
166
|
+
break;
|
|
167
|
+
default:
|
|
168
|
+
codeCount++;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ── Step 5: Fetch PR diff ─────────────────────────────────────────────
|
|
172
|
+
logStderr('📄 Fetching PR diff...');
|
|
173
|
+
const diffFile = join(tmpDir, `hula-verify-diff-${prNumber}.patch`);
|
|
174
|
+
const diffRes = await runGh(['pr', 'diff', prNumber], { cwd });
|
|
175
|
+
if (diffRes.code === 0) {
|
|
176
|
+
await writeFile(diffFile, diffRes.stdout, 'utf-8');
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
logStderr('⚠️ Could not fetch PR diff (PR may be too large or not accessible)');
|
|
180
|
+
}
|
|
181
|
+
// ── Output result ─────────────────────────────────────────────────────
|
|
182
|
+
emitJson({
|
|
183
|
+
status: 'success',
|
|
184
|
+
issueNumber: Number(issueNumber),
|
|
185
|
+
issueTitle,
|
|
186
|
+
issueState,
|
|
187
|
+
issueUrl,
|
|
188
|
+
prNumber: Number(prNumber),
|
|
189
|
+
prTitle,
|
|
190
|
+
prUrl,
|
|
191
|
+
prState,
|
|
192
|
+
prBranch,
|
|
193
|
+
prIsDraft,
|
|
194
|
+
diffFile,
|
|
195
|
+
filesChanged: {
|
|
196
|
+
total: totalCount,
|
|
197
|
+
code: codeCount,
|
|
198
|
+
test: testCount,
|
|
199
|
+
doc: docCount,
|
|
200
|
+
config: configCount,
|
|
201
|
+
},
|
|
202
|
+
lines: { additions: totalAdditions, deletions: totalDeletions },
|
|
203
|
+
});
|
|
204
|
+
}, args);
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=verify-gather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-gather.js","sourceRoot":"","sources":["../../src/scripts/verify-gather.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;;;;;;GASG;AAEH,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAa;IACrD,MAAM,EAAE,GAAG,IAAI,MAAM,CACnB,iEAAiE,KAAK,YAAY;QAChF,eAAe,KAAK,YAAY,EAClC,GAAG,CACJ,CAAC;IACF,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAID,kFAAkF;AAClF,SAAS,UAAU,CAAC,CAAS;IAC3B,IACE,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAClB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC;QACzB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACpB,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EACrB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IACE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QACjB,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QACrB,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC;QACtB,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC;QACzB,CAAC,CAAC,UAAU,CAAC,eAAe,CAAC,EAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IACE,CAAC,KAAK,cAAc;QACpB,CAAC,KAAK,mBAAmB;QACzB,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;QACxB,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACpB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QACnB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QACnB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAClB,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAc;IACjC,OAAO,SAAS,CAAC,KAAK,IAAI,EAAE;QAC1B,yEAAyE;QACzE,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;YACnB,IAAI,CAAC,KAAK,aAAa,EAAE,CAAC;gBACxB,WAAW,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAChC,CAAC;iBAAM,IAAI,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBACxC,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAC/C,CAAC;iBAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5B,WAAW,GAAG,CAAC,CAAC;YAClB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,CAAC,EAAE,qBAAqB,CAAC,EAAE,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,IAAI,CACF,CAAC,EACD,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,WAAW,IAAI,SAAS,CAAC;QAErC,0EAA0E;QAC1E,wEAAwE;QACxE,uDAAuD;QACvD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC;QACnD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEzC,yEAAyE;QACzE,SAAS,CAAC,sBAAsB,WAAW,KAAK,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,6BAA6B,CAAC,EACvE,EAAE,GAAG,EAAE,CACR,CAAC;QACF,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,EAAE,UAAU,WAAW,+BAA+B,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAIvC,CAAC;QACF,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC;QAEjC,yEAAyE;QACzE,SAAS,CAAC,sCAAsC,WAAW,KAAK,CAAC,CAAC;QAClE,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,KAAK,CACxB;YACE,IAAI;YACJ,MAAM;YACN,UAAU;YACV,UAAU,WAAW,EAAE;YACvB,QAAQ;YACR,QAAQ;YACR,IAAI;YACJ,aAAa;SACd,EACD,EAAE,GAAG,EAAE,CACR,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,OAAO,GAAG,MAAM,KAAK,CACzB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,CAAC,EACzD,EAAE,GAAG,EAAE,CACR,CAAC;YACF,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACvB,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAGnC,CAAC;oBACH,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CACpB,CAAC,EAAE,EAAE,EAAE,CACL,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ;wBAC3B,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,CAC3C,CAAC;oBACF,IAAI,KAAK,EAAE,MAAM,KAAK,SAAS;wBAAE,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBACnE,CAAC;gBAAC,MAAM,CAAC;oBACP,uBAAuB;gBACzB,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,CACF,CAAC,EACD,0BAA0B,WAAW,gDAAgD,CACtF,CAAC;QACJ,CAAC;QAED,yBAAyB;QACzB,MAAM,KAAK,GAAG,MAAM,KAAK,CACvB;YACE,IAAI;YACJ,MAAM;YACN,QAAQ;YACR,QAAQ;YACR,4CAA4C;SAC7C,EACD,EAAE,GAAG,EAAE,CACR,CAAC;QACF,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,CAAC,EAAE,mCAAmC,QAAQ,GAAG,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAMjC,CAAC;QACF,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,EAAE,CAAC,OAAO,IAAI,KAAK,CAAC;QAEtC,yEAAyE;QACzE,SAAS,CAAC,qCAAqC,QAAQ,KAAK,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,2BAA2B,CAAC,EAC/D,EAAE,GAAG,EAAE,CACR,CAAC;QACF,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,EAAE,oCAAoC,QAAQ,GAAG,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAI3C,CAAC;QACF,MAAM,cAAc,GAAG,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,SAAS,CAAC,SAAS,IAAI,CAAC,CAAC;QAEhD,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACjB,IAAI,CAAC,CAAC;gBAAE,SAAS;YACjB,UAAU,EAAE,CAAC;YACb,QAAQ,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,KAAK,MAAM;oBACT,SAAS,EAAE,CAAC;oBACZ,MAAM;gBACR,KAAK,KAAK;oBACR,QAAQ,EAAE,CAAC;oBACX,MAAM;gBACR,KAAK,QAAQ;oBACX,WAAW,EAAE,CAAC;oBACd,MAAM;gBACR;oBACE,SAAS,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,SAAS,CAAC,wBAAwB,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,oBAAoB,QAAQ,QAAQ,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/D,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,SAAS,CACP,qEAAqE,CACtE,CAAC;QACJ,CAAC;QAED,yEAAyE;QACzE,QAAQ,CAAC;YACP,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC;YAChC,UAAU;YACV,UAAU;YACV,QAAQ;YACR,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;YAC1B,OAAO;YACP,KAAK;YACL,OAAO;YACP,QAAQ;YACR,SAAS;YACT,QAAQ;YACR,YAAY,EAAE;gBACZ,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;gBACf,GAAG,EAAE,QAAQ;gBACb,MAAM,EAAE,WAAW;aACpB;YACD,KAAK,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE;SAChE,CAAC,CAAC;IACL,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC"}
|