strikethroo 3.0.1 → 3.1.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/README.md +20 -5
- package/dist/cli.js +19 -128
- package/dist/cli.js.map +1 -1
- package/dist/serve/archive.d.ts +43 -0
- package/dist/serve/archive.d.ts.map +1 -0
- package/dist/serve/archive.js +124 -0
- package/dist/serve/archive.js.map +1 -0
- package/dist/serve/derivation.d.ts +78 -0
- package/dist/serve/derivation.d.ts.map +1 -0
- package/dist/serve/derivation.js +237 -0
- package/dist/serve/derivation.js.map +1 -0
- package/dist/serve/events.d.ts +41 -0
- package/dist/serve/events.d.ts.map +1 -0
- package/dist/serve/events.js +91 -0
- package/dist/serve/events.js.map +1 -0
- package/dist/serve/markdown.d.ts +75 -0
- package/dist/serve/markdown.d.ts.map +1 -0
- package/dist/serve/markdown.js +221 -0
- package/dist/serve/markdown.js.map +1 -0
- package/dist/serve/root.d.ts +48 -0
- package/dist/serve/root.d.ts.map +1 -0
- package/dist/serve/root.js +110 -0
- package/dist/serve/root.js.map +1 -0
- package/dist/serve/self-review.d.ts +70 -0
- package/dist/serve/self-review.d.ts.map +1 -0
- package/dist/serve/self-review.js +164 -0
- package/dist/serve/self-review.js.map +1 -0
- package/dist/serve/server.d.ts +70 -0
- package/dist/serve/server.d.ts.map +1 -0
- package/dist/serve/server.js +368 -0
- package/dist/serve/server.js.map +1 -0
- package/dist/serve/watcher.d.ts +32 -0
- package/dist/serve/watcher.d.ts.map +1 -0
- package/dist/serve/watcher.js +99 -0
- package/dist/serve/watcher.js.map +1 -0
- package/dist/serve/workspace-model.d.ts +80 -0
- package/dist/serve/workspace-model.d.ts.map +1 -0
- package/dist/serve/workspace-model.js +176 -0
- package/dist/serve/workspace-model.js.map +1 -0
- package/dist/skill-scripts/shared/frontmatter.d.ts +2 -0
- package/dist/skill-scripts/shared/frontmatter.d.ts.map +1 -0
- package/dist/skill-scripts/shared/frontmatter.js +37 -0
- package/dist/skill-scripts/shared/frontmatter.js.map +1 -0
- package/dist/skill-scripts/shared/plan-scan.d.ts +10 -0
- package/dist/skill-scripts/shared/plan-scan.d.ts.map +1 -0
- package/dist/skill-scripts/shared/plan-scan.js +91 -0
- package/dist/skill-scripts/shared/plan-scan.js.map +1 -0
- package/dist/skill-scripts/shared/root.d.ts +2 -0
- package/dist/skill-scripts/shared/root.d.ts.map +1 -0
- package/dist/skill-scripts/shared/root.js +104 -0
- package/dist/skill-scripts/shared/root.js.map +1 -0
- package/dist-web/assets/Fraunces-Italic-VariableFont_SOFT_WONK_opsz_wght-CuXX_kIb.ttf +0 -0
- package/dist-web/assets/Fraunces-VariableFont_SOFT_WONK_opsz_wght-DLWfSgHL.ttf +0 -0
- package/dist-web/assets/Outfit-VariableFont_wght-B6lQlNBM.ttf +0 -0
- package/dist-web/assets/SFMonoBold-DXHgGUoo.otf +0 -0
- package/dist-web/assets/SFMonoBoldItalic-CdGEImHi.otf +0 -0
- package/dist-web/assets/SFMonoHeavy-DL92f7rT.otf +0 -0
- package/dist-web/assets/SFMonoHeavyItalic-DnE00LFH.otf +0 -0
- package/dist-web/assets/SFMonoLight-CaMC1gg-.otf +0 -0
- package/dist-web/assets/SFMonoLightItalic-DG3Owzn7.otf +0 -0
- package/dist-web/assets/SFMonoMedium-ypRDCKSo.otf +0 -0
- package/dist-web/assets/SFMonoMediumItalic-DkJk-c-x.otf +0 -0
- package/dist-web/assets/SFMonoRegular-77Uh1IPk.otf +0 -0
- package/dist-web/assets/SFMonoRegularItalic-Cn01bACm.otf +0 -0
- package/dist-web/assets/SFMonoSemibold-CvhtzcyM.otf +0 -0
- package/dist-web/assets/SFMonoSemiboldItalic-D75NMH13.otf +0 -0
- package/dist-web/assets/arc-BWWIDtzc.js +1 -0
- package/dist-web/assets/architectureDiagram-3BPJPVTR-DeYxmq4e.js +36 -0
- package/dist-web/assets/blockDiagram-GPEHLZMM-DR85OQGh.js +132 -0
- package/dist-web/assets/c4Diagram-AAUBKEIU-B5p4vlmU.js +10 -0
- package/dist-web/assets/channel-BaP08-ph.js +1 -0
- package/dist-web/assets/chunk-2J33WTMH-duXs_Bbu.js +1 -0
- package/dist-web/assets/chunk-4BX2VUAB-DR1619KE.js +1 -0
- package/dist-web/assets/chunk-55IACEB6-UacLKom4.js +1 -0
- package/dist-web/assets/chunk-727SXJPM-DW2a_NI7.js +206 -0
- package/dist-web/assets/chunk-AQP2D5EJ-Bu5jn-_L.js +231 -0
- package/dist-web/assets/chunk-FMBD7UC4-eJsExyuh.js +15 -0
- package/dist-web/assets/chunk-ND2GUHAM-BqKmGd94.js +1 -0
- package/dist-web/assets/chunk-QZHKN3VN--ynTiOCz.js +1 -0
- package/dist-web/assets/classDiagram-4FO5ZUOK-V5dHIfdR.js +1 -0
- package/dist-web/assets/classDiagram-v2-Q7XG4LA2-V5dHIfdR.js +1 -0
- package/dist-web/assets/cose-bilkent-S5V4N54A-Ccz3r4S1.js +1 -0
- package/dist-web/assets/cytoscape.esm-BHYC38rz.js +331 -0
- package/dist-web/assets/dagre-BM42HDAG-BESSLbjB.js +4 -0
- package/dist-web/assets/defaultLocale-CrowFXzY.js +1 -0
- package/dist-web/assets/diagram-2AECGRRQ-BB5cYRbY.js +43 -0
- package/dist-web/assets/diagram-5GNKFQAL-3lmcZFDS.js +10 -0
- package/dist-web/assets/diagram-KO2AKTUF-DUMp202y.js +3 -0
- package/dist-web/assets/diagram-LMA3HP47-DCGXhLm1.js +24 -0
- package/dist-web/assets/diagram-OG6HWLK6-D247gj5y.js +24 -0
- package/dist-web/assets/erDiagram-TEJ5UH35-GI1vhsr2.js +85 -0
- package/dist-web/assets/flowDiagram-I6XJVG4X-iqUPWZuf.js +162 -0
- package/dist-web/assets/ganttDiagram-6RSMTGT7-DfG1X-Pe.js +292 -0
- package/dist-web/assets/gitGraphDiagram-PVQCEYII-B2MrV3y6.js +106 -0
- package/dist-web/assets/graph-Dqkl27Ch.js +1 -0
- package/dist-web/assets/index-Bm5I46eC.css +1 -0
- package/dist-web/assets/index-CvfrFREc.js +125 -0
- package/dist-web/assets/infoDiagram-5YYISTIA-DGqU5K4a.js +2 -0
- package/dist-web/assets/init-Gi6I4Gst.js +1 -0
- package/dist-web/assets/ishikawaDiagram-YF4QCWOH-DrMH3jRf.js +70 -0
- package/dist-web/assets/journeyDiagram-JHISSGLW-BH4wiwsd.js +139 -0
- package/dist-web/assets/kanban-definition-UN3LZRKU-DEV_dEgE.js +89 -0
- package/dist-web/assets/katex-C5jXJg4s.js +257 -0
- package/dist-web/assets/layout-DO9UvE1P.js +1 -0
- package/dist-web/assets/linear-D81nAxzR.js +1 -0
- package/dist-web/assets/mermaid.core-BaP7clO2.js +307 -0
- package/dist-web/assets/mindmap-definition-RKZ34NQL-DM4iAZ4M.js +96 -0
- package/dist-web/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist-web/assets/pieDiagram-4H26LBE5-DinO6q5i.js +30 -0
- package/dist-web/assets/quadrantDiagram-W4KKPZXB-CYvCm7U6.js +7 -0
- package/dist-web/assets/requirementDiagram-4Y6WPE33-DXfPIJ5m.js +84 -0
- package/dist-web/assets/sankeyDiagram-5OEKKPKP-CfovFay4.js +40 -0
- package/dist-web/assets/sequenceDiagram-3UESZ5HK-BboUGmEB.js +162 -0
- package/dist-web/assets/stateDiagram-AJRCARHV-CsB2FtnQ.js +1 -0
- package/dist-web/assets/stateDiagram-v2-BHNVJYJU-D0D_KesS.js +1 -0
- package/dist-web/assets/timeline-definition-PNZ67QCA-Cma1yLcq.js +120 -0
- package/dist-web/assets/vennDiagram-CIIHVFJN-DhFGEgCQ.js +34 -0
- package/dist-web/assets/wardley-L42UT6IY-DYkCeynG.js +173 -0
- package/dist-web/assets/wardleyDiagram-YWT4CUSO-jogT61m_.js +78 -0
- package/dist-web/assets/xychartDiagram-2RQKCTM6-Cn3W0E3s.js +7 -0
- package/dist-web/favicon.svg +13 -0
- package/dist-web/index.html +30 -0
- package/package.json +28 -8
- package/templates/harness/skills/st-full-workflow/SKILL.md +2 -2
- package/templates/harness/skills/st-generate-tasks/SKILL.md +2 -2
- package/dist/plan-utils.d.ts +0 -35
- package/dist/plan-utils.d.ts.map +0 -1
- package/dist/plan-utils.js +0 -123
- package/dist/plan-utils.js.map +0 -1
- package/dist/plan.d.ts +0 -27
- package/dist/plan.d.ts.map +0 -1
- package/dist/plan.js +0 -279
- package/dist/plan.js.map +0 -1
- package/dist/status.d.ts +0 -73
- package/dist/status.d.ts.map +0 -1
- package/dist/status.js +0 -375
- package/dist/status.js.map +0 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure, dependency-light markdown parsing primitives for the serve data layer.
|
|
4
|
+
*
|
|
5
|
+
* These functions operate on already-read string content. File reading itself
|
|
6
|
+
* belongs to the task scanner and the model assembler. Everything here is
|
|
7
|
+
* synchronous, read-only, and side-effect-free: no `fs`, no network, no writes.
|
|
8
|
+
*
|
|
9
|
+
* The existing `src/skill-scripts/shared/frontmatter.ts` only recovers the
|
|
10
|
+
* numeric `id`; it is intentionally not forked. This module provides a richer
|
|
11
|
+
* frontmatter reader the UI needs (summary, created, status, group,
|
|
12
|
+
* dependencies[], skills[]).
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.extractTitle = exports.extractMermaidBlocks = exports.sectionBody = exports.extractBody = exports.parseFrontmatter = void 0;
|
|
16
|
+
/** Anchors the leading `---`-delimited frontmatter block (same as frontmatter.ts). */
|
|
17
|
+
const FRONTMATTER_RE = /^---\s*\r?\n([\s\S]*?)\r?\n---/;
|
|
18
|
+
const stripQuotes = (value) => {
|
|
19
|
+
const trimmed = value.trim();
|
|
20
|
+
if (trimmed.length >= 2) {
|
|
21
|
+
const first = trimmed[0];
|
|
22
|
+
const last = trimmed[trimmed.length - 1];
|
|
23
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
24
|
+
return trimmed.slice(1, -1);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return trimmed;
|
|
28
|
+
};
|
|
29
|
+
/** Strips a trailing unquoted YAML comment (`# ...`). Quoted scalars are left intact. */
|
|
30
|
+
const stripComment = (value) => {
|
|
31
|
+
const trimmed = value.trim();
|
|
32
|
+
if (trimmed.startsWith('"') || trimmed.startsWith("'"))
|
|
33
|
+
return trimmed;
|
|
34
|
+
const hashIndex = trimmed.indexOf('#');
|
|
35
|
+
return hashIndex === -1 ? trimmed : trimmed.slice(0, hashIndex).trim();
|
|
36
|
+
};
|
|
37
|
+
/** Parses a bracketed inline array like `[a, b]` or `[]` into trimmed, unquoted items. */
|
|
38
|
+
const parseInlineArray = (value) => {
|
|
39
|
+
const inner = value.slice(1, -1).trim();
|
|
40
|
+
if (inner.length === 0)
|
|
41
|
+
return [];
|
|
42
|
+
return inner
|
|
43
|
+
.split(',')
|
|
44
|
+
.map(item => stripQuotes(item))
|
|
45
|
+
.filter(item => item.length > 0);
|
|
46
|
+
};
|
|
47
|
+
/** Coerces a dependency item to a number when it is purely numeric, else leaves it as-is. */
|
|
48
|
+
const coerceDependency = (item) => {
|
|
49
|
+
if (/^-?\d+$/.test(item)) {
|
|
50
|
+
return parseInt(item, 10);
|
|
51
|
+
}
|
|
52
|
+
return item;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Reads the leading frontmatter block into typed fields. Never throws: malformed
|
|
56
|
+
* lines are skipped and absent keys fall back to defaults (undefined scalars,
|
|
57
|
+
* empty arrays).
|
|
58
|
+
*/
|
|
59
|
+
const parseFrontmatter = (content) => {
|
|
60
|
+
const result = {
|
|
61
|
+
dependencies: [],
|
|
62
|
+
skills: [],
|
|
63
|
+
extra: {},
|
|
64
|
+
};
|
|
65
|
+
const match = content.match(FRONTMATTER_RE);
|
|
66
|
+
if (!match || match[1] === undefined)
|
|
67
|
+
return result;
|
|
68
|
+
const lines = match[1].split(/\r?\n/);
|
|
69
|
+
const listFields = new Set(['dependencies', 'skills']);
|
|
70
|
+
for (let i = 0; i < lines.length; i++) {
|
|
71
|
+
const line = lines[i];
|
|
72
|
+
if (line === undefined)
|
|
73
|
+
continue;
|
|
74
|
+
// Skip blank lines and dashed list items (they are consumed by their owning key).
|
|
75
|
+
if (line.trim().length === 0)
|
|
76
|
+
continue;
|
|
77
|
+
if (/^\s*-\s+/.test(line))
|
|
78
|
+
continue;
|
|
79
|
+
const colonIndex = line.indexOf(':');
|
|
80
|
+
if (colonIndex === -1)
|
|
81
|
+
continue;
|
|
82
|
+
const key = line.slice(0, colonIndex).trim();
|
|
83
|
+
const rawValue = line.slice(colonIndex + 1);
|
|
84
|
+
if (key.length === 0)
|
|
85
|
+
continue;
|
|
86
|
+
if (listFields.has(key)) {
|
|
87
|
+
const value = stripComment(rawValue);
|
|
88
|
+
let items;
|
|
89
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
90
|
+
items = parseInlineArray(value);
|
|
91
|
+
}
|
|
92
|
+
else if (value.length > 0) {
|
|
93
|
+
// A scalar on the same line that is not a bracketed array: treat as a
|
|
94
|
+
// single-item list (lenient).
|
|
95
|
+
items = [stripQuotes(value)];
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Empty value: collect subsequent dashed-list items until indentation ends.
|
|
99
|
+
items = [];
|
|
100
|
+
let j = i + 1;
|
|
101
|
+
while (j < lines.length) {
|
|
102
|
+
const next = lines[j];
|
|
103
|
+
if (next === undefined)
|
|
104
|
+
break;
|
|
105
|
+
const dashMatch = next.match(/^\s*-\s+(.*)$/);
|
|
106
|
+
if (!dashMatch || dashMatch[1] === undefined)
|
|
107
|
+
break;
|
|
108
|
+
items.push(stripQuotes(stripComment(dashMatch[1])));
|
|
109
|
+
j++;
|
|
110
|
+
}
|
|
111
|
+
i = j - 1; // advance the outer cursor past the consumed items
|
|
112
|
+
}
|
|
113
|
+
if (key === 'dependencies') {
|
|
114
|
+
result.dependencies = items.map(coerceDependency);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
result.skills = items;
|
|
118
|
+
}
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const value = stripQuotes(stripComment(rawValue));
|
|
122
|
+
switch (key) {
|
|
123
|
+
case 'id': {
|
|
124
|
+
const parsed = parseInt(value, 10);
|
|
125
|
+
if (!Number.isNaN(parsed))
|
|
126
|
+
result.id = parsed;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case 'summary':
|
|
130
|
+
result.summary = value;
|
|
131
|
+
break;
|
|
132
|
+
case 'created':
|
|
133
|
+
result.created = value;
|
|
134
|
+
break;
|
|
135
|
+
case 'status':
|
|
136
|
+
result.status = value;
|
|
137
|
+
break;
|
|
138
|
+
case 'group':
|
|
139
|
+
result.group = value;
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
result.extra[key] = value;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
147
|
+
};
|
|
148
|
+
exports.parseFrontmatter = parseFrontmatter;
|
|
149
|
+
/** Returns the body: everything after the closing frontmatter `---`, or the whole content. */
|
|
150
|
+
const extractBody = (content) => {
|
|
151
|
+
const match = content.match(FRONTMATTER_RE);
|
|
152
|
+
if (!match)
|
|
153
|
+
return content;
|
|
154
|
+
return content.slice(match.index + match[0].length).replace(/^\r?\n/, '');
|
|
155
|
+
};
|
|
156
|
+
exports.extractBody = extractBody;
|
|
157
|
+
/**
|
|
158
|
+
* Splits a markdown body into the verbatim `rawBody` plus an ordered list of
|
|
159
|
+
* `## ` sections addressable by heading text. Section access is additive:
|
|
160
|
+
* callers may always fall back to `rawBody`.
|
|
161
|
+
*/
|
|
162
|
+
const sectionBody = (body) => {
|
|
163
|
+
const sections = [];
|
|
164
|
+
const headingRe = /^##[ \t]+(.+?)[ \t]*$/gm;
|
|
165
|
+
const matches = [];
|
|
166
|
+
let m;
|
|
167
|
+
while ((m = headingRe.exec(body)) !== null) {
|
|
168
|
+
const heading = (m[1] ?? '').trim();
|
|
169
|
+
matches.push({
|
|
170
|
+
heading,
|
|
171
|
+
index: m.index,
|
|
172
|
+
afterHeading: m.index + m[0].length,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
for (let i = 0; i < matches.length; i++) {
|
|
176
|
+
const current = matches[i];
|
|
177
|
+
const next = matches[i + 1];
|
|
178
|
+
const end = next ? next.index : body.length;
|
|
179
|
+
const content = body.slice(current.afterHeading, end).replace(/^\r?\n/, '');
|
|
180
|
+
sections.push({
|
|
181
|
+
heading: current.heading,
|
|
182
|
+
content,
|
|
183
|
+
start: current.index,
|
|
184
|
+
end,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return { rawBody: body, sections };
|
|
188
|
+
};
|
|
189
|
+
exports.sectionBody = sectionBody;
|
|
190
|
+
const ARCH_APPROACH_RE = /architectural\s+approach/i;
|
|
191
|
+
/**
|
|
192
|
+
* Extracts every fenced ```mermaid block's raw source from a body. Blocks whose
|
|
193
|
+
* position falls within an "Architectural Approach" section are flagged. Plans
|
|
194
|
+
* with no mermaid block yield an empty list (never an error).
|
|
195
|
+
*/
|
|
196
|
+
const extractMermaidBlocks = (body) => {
|
|
197
|
+
const blocks = [];
|
|
198
|
+
const { sections } = (0, exports.sectionBody)(body);
|
|
199
|
+
const archSpans = sections
|
|
200
|
+
.filter(s => ARCH_APPROACH_RE.test(s.heading))
|
|
201
|
+
.map(s => ({ start: s.start, end: s.end }));
|
|
202
|
+
// Match a fence opening with ```mermaid (optional trailing whitespace) and
|
|
203
|
+
// closing with a line of three backticks.
|
|
204
|
+
const fenceRe = /^[ \t]*```mermaid[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*$/gm;
|
|
205
|
+
let m;
|
|
206
|
+
while ((m = fenceRe.exec(body)) !== null) {
|
|
207
|
+
const source = m[1] ?? '';
|
|
208
|
+
const offset = m.index;
|
|
209
|
+
const isArch = archSpans.some(span => offset >= span.start && offset < span.end);
|
|
210
|
+
blocks.push({ source, isArchitecturalApproach: isArch });
|
|
211
|
+
}
|
|
212
|
+
return blocks;
|
|
213
|
+
};
|
|
214
|
+
exports.extractMermaidBlocks = extractMermaidBlocks;
|
|
215
|
+
/** Returns the text of the first `# ` (level-1) heading in a body, or undefined. */
|
|
216
|
+
const extractTitle = (body) => {
|
|
217
|
+
const match = body.match(/^#[ \t]+(.+?)[ \t]*$/m);
|
|
218
|
+
return match && match[1] !== undefined ? match[1].trim() : undefined;
|
|
219
|
+
};
|
|
220
|
+
exports.extractTitle = extractTitle;
|
|
221
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/serve/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-contained workspace root resolver for `npx strikethroo serve`.
|
|
3
|
+
*
|
|
4
|
+
* Determines which initialized `.ai/strikethroo/` workspace the `serve` command
|
|
5
|
+
* should host. Discovery keys on the presence of
|
|
6
|
+
* `<root>/.ai/strikethroo/.init-metadata.json`, the same contract the skills use,
|
|
7
|
+
* but the logic is reimplemented here with Node built-ins only.
|
|
8
|
+
*
|
|
9
|
+
* This deliberately does NOT import `findStrikethrooRoot` from
|
|
10
|
+
* `src/skill-scripts/shared/`: that subtree carries the skill-bundle build
|
|
11
|
+
* contract (esbuild, schema-version `define`) and is excluded from the main `tsc`
|
|
12
|
+
* pipeline. Crossing that boundary would drag build-time concerns into the
|
|
13
|
+
* runtime path. The discovery walk is short and cheap to keep self-contained.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Successful resolution. `root` is the absolute path of the `.ai/strikethroo`
|
|
17
|
+
* directory itself (NOT the repository root) so it can be passed directly to the
|
|
18
|
+
* workspace model's `root` argument, whose readers join `plans`/`archive`/`config`
|
|
19
|
+
* onto it.
|
|
20
|
+
*/
|
|
21
|
+
export interface ResolvedRoot {
|
|
22
|
+
root: string;
|
|
23
|
+
}
|
|
24
|
+
/** Failure result carrying a user-facing message. Never a stack trace. */
|
|
25
|
+
export interface ResolveError {
|
|
26
|
+
error: string;
|
|
27
|
+
}
|
|
28
|
+
export type ResolveResult = ResolvedRoot | ResolveError;
|
|
29
|
+
/** Narrows a {@link ResolveResult} to its error variant. */
|
|
30
|
+
export declare const isResolveError: (result: ResolveResult) => result is ResolveError;
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the `.ai/strikethroo` workspace directory to host.
|
|
33
|
+
*
|
|
34
|
+
* - When `options.workspace` is given, it is treated as a project directory; the
|
|
35
|
+
* resolver validates that `<workspace>/.ai/strikethroo/.init-metadata.json`
|
|
36
|
+
* exists and returns that `.ai/strikethroo` directory.
|
|
37
|
+
* - Otherwise it walks upward from `options.cwd` (default `process.cwd()`),
|
|
38
|
+
* testing each ancestor for `.ai/strikethroo/.init-metadata.json`.
|
|
39
|
+
*
|
|
40
|
+
* On failure it returns an `{ error }` shape with a clear, user-facing message
|
|
41
|
+
* so the command layer can print it and exit non-zero. It never throws an
|
|
42
|
+
* unhandled error for the "not found" case.
|
|
43
|
+
*/
|
|
44
|
+
export declare const resolveWorkspaceRoot: (options?: {
|
|
45
|
+
workspace?: string;
|
|
46
|
+
cwd?: string;
|
|
47
|
+
}) => ResolveResult;
|
|
48
|
+
//# sourceMappingURL=root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/serve/root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,0EAA0E;AAC1E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,YAAY,CAAC;AAExD,4DAA4D;AAC5D,eAAO,MAAM,cAAc,GAAI,QAAQ,aAAa,KAAG,MAAM,IAAI,YACnB,CAAC;AAe/C;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,KACjD,aA6BF,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Self-contained workspace root resolver for `npx strikethroo serve`.
|
|
4
|
+
*
|
|
5
|
+
* Determines which initialized `.ai/strikethroo/` workspace the `serve` command
|
|
6
|
+
* should host. Discovery keys on the presence of
|
|
7
|
+
* `<root>/.ai/strikethroo/.init-metadata.json`, the same contract the skills use,
|
|
8
|
+
* but the logic is reimplemented here with Node built-ins only.
|
|
9
|
+
*
|
|
10
|
+
* This deliberately does NOT import `findStrikethrooRoot` from
|
|
11
|
+
* `src/skill-scripts/shared/`: that subtree carries the skill-bundle build
|
|
12
|
+
* contract (esbuild, schema-version `define`) and is excluded from the main `tsc`
|
|
13
|
+
* pipeline. Crossing that boundary would drag build-time concerns into the
|
|
14
|
+
* runtime path. The discovery walk is short and cheap to keep self-contained.
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.resolveWorkspaceRoot = exports.isResolveError = void 0;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
/** Narrows a {@link ResolveResult} to its error variant. */
|
|
54
|
+
const isResolveError = (result) => result.error !== undefined;
|
|
55
|
+
exports.isResolveError = isResolveError;
|
|
56
|
+
const INIT_MESSAGE = 'Run `npx strikethroo init` first.';
|
|
57
|
+
/** True when `<dir>/.init-metadata.json` exists and `<dir>` is a directory. */
|
|
58
|
+
const isInitializedStrikethrooDir = (strikethrooDir) => {
|
|
59
|
+
try {
|
|
60
|
+
if (!fs.statSync(strikethrooDir).isDirectory())
|
|
61
|
+
return false;
|
|
62
|
+
const metadataPath = path.join(strikethrooDir, '.init-metadata.json');
|
|
63
|
+
return fs.statSync(metadataPath).isFile();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Resolves the `.ai/strikethroo` workspace directory to host.
|
|
71
|
+
*
|
|
72
|
+
* - When `options.workspace` is given, it is treated as a project directory; the
|
|
73
|
+
* resolver validates that `<workspace>/.ai/strikethroo/.init-metadata.json`
|
|
74
|
+
* exists and returns that `.ai/strikethroo` directory.
|
|
75
|
+
* - Otherwise it walks upward from `options.cwd` (default `process.cwd()`),
|
|
76
|
+
* testing each ancestor for `.ai/strikethroo/.init-metadata.json`.
|
|
77
|
+
*
|
|
78
|
+
* On failure it returns an `{ error }` shape with a clear, user-facing message
|
|
79
|
+
* so the command layer can print it and exit non-zero. It never throws an
|
|
80
|
+
* unhandled error for the "not found" case.
|
|
81
|
+
*/
|
|
82
|
+
const resolveWorkspaceRoot = (options = {}) => {
|
|
83
|
+
if (options.workspace) {
|
|
84
|
+
const projectDir = path.resolve(options.workspace);
|
|
85
|
+
const strikethrooDir = path.join(projectDir, '.ai', 'strikethroo');
|
|
86
|
+
if (isInitializedStrikethrooDir(strikethrooDir)) {
|
|
87
|
+
return { root: strikethrooDir };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
error: `Path ${projectDir} is not an initialized strikethroo workspace. ${INIT_MESSAGE}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
let current = path.resolve(options.cwd ?? process.cwd());
|
|
94
|
+
// Walk upward until the filesystem root, where dirname(current) === current.
|
|
95
|
+
for (;;) {
|
|
96
|
+
const strikethrooDir = path.join(current, '.ai', 'strikethroo');
|
|
97
|
+
if (isInitializedStrikethrooDir(strikethrooDir)) {
|
|
98
|
+
return { root: strikethrooDir };
|
|
99
|
+
}
|
|
100
|
+
const parent = path.dirname(current);
|
|
101
|
+
if (parent === current)
|
|
102
|
+
break;
|
|
103
|
+
current = parent;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
error: `No initialized strikethroo workspace found from ${path.resolve(options.cwd ?? process.cwd())} upward. ${INIT_MESSAGE}`,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
exports.resolveWorkspaceRoot = resolveWorkspaceRoot;
|
|
110
|
+
//# sourceMappingURL=root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/serve/root.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAmB7B,4DAA4D;AACrD,MAAM,cAAc,GAAG,CAAC,MAAqB,EAA0B,EAAE,CAC7E,MAAuB,CAAC,KAAK,KAAK,SAAS,CAAC;AADlC,QAAA,cAAc,kBACoB;AAE/C,MAAM,YAAY,GAAG,mCAAmC,CAAC;AAEzD,+EAA+E;AAC/E,MAAM,2BAA2B,GAAG,CAAC,cAAsB,EAAW,EAAE;IACtE,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE;YAAE,OAAO,KAAK,CAAC;QAC7D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAC;QACtE,OAAO,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACI,MAAM,oBAAoB,GAAG,CAClC,UAAgD,EAAE,EACnC,EAAE;IACjB,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QACnE,IAAI,2BAA2B,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QAClC,CAAC;QACD,OAAO;YACL,KAAK,EAAE,QAAQ,UAAU,iDAAiD,YAAY,EAAE;SACzF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,6EAA6E;IAC7E,SAAS,CAAC;QACR,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;QAChE,IAAI,2BAA2B,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;QAClC,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM;QAC9B,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,OAAO;QACL,KAAK,EAAE,mDAAmD,IAAI,CAAC,OAAO,CACpE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAC7B,YAAY,YAAY,EAAE;KAC5B,CAAC;AACJ,CAAC,CAAC;AA/BW,QAAA,oBAAoB,wBA+B/B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-review launch capability for `npx strikethroo serve`.
|
|
3
|
+
*
|
|
4
|
+
* The serve API is otherwise read-only. This module adds the single, narrowly
|
|
5
|
+
* scoped exception the SPA's "Launch self-review" button needs:
|
|
6
|
+
*
|
|
7
|
+
* - {@link isSelfReviewAvailable} — a PATH scan answering "is the `self-review`
|
|
8
|
+
* binary installed?", exposed to the SPA via `GET /api/capabilities` so the
|
|
9
|
+
* button only renders when launching can actually succeed;
|
|
10
|
+
* - {@link launchSelfReview} — validates a client-supplied plan path stays
|
|
11
|
+
* inside the workspace's `plans/` or `archive/` subtree, then spawns the
|
|
12
|
+
* binary detached (fire-and-forget, like the browser auto-open).
|
|
13
|
+
*
|
|
14
|
+
* Untrusted input (the path string) is never passed to the shell: `spawn` is
|
|
15
|
+
* invoked with an argv array, and the path is rejected before spawning unless it
|
|
16
|
+
* resolves to an existing file under `plans/` or `archive/`. Node built-ins only.
|
|
17
|
+
*/
|
|
18
|
+
/** The binary name looked up on PATH and spawned. */
|
|
19
|
+
export declare const SELF_REVIEW_BINARY = "self-review";
|
|
20
|
+
/** Where to obtain self-review; surfaced by the SPA when it is not installed. */
|
|
21
|
+
export declare const SELF_REVIEW_URL = "https://github.com/e0ipso/self-review";
|
|
22
|
+
/**
|
|
23
|
+
* Returns `true` when the `self-review` binary is found on the process `PATH`.
|
|
24
|
+
*
|
|
25
|
+
* A presence check, matching the literal "binary is in path" contract: each
|
|
26
|
+
* `PATH` entry is probed for a regular file named `self-review` (plus the
|
|
27
|
+
* `PATHEXT` variants on Windows). It deliberately does not execute the binary,
|
|
28
|
+
* so it cannot hang and has no side effects.
|
|
29
|
+
*/
|
|
30
|
+
export declare const isSelfReviewAvailable: (env?: Record<string, string | undefined>) => boolean;
|
|
31
|
+
/** Outcome of resolving and launching a self-review request. */
|
|
32
|
+
export interface LaunchResult {
|
|
33
|
+
/** HTTP status the endpoint should send. */
|
|
34
|
+
status: number;
|
|
35
|
+
/** JSON body the endpoint should send. */
|
|
36
|
+
body: {
|
|
37
|
+
ok: true;
|
|
38
|
+
} | {
|
|
39
|
+
ok: false;
|
|
40
|
+
error: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** Seams for testing: availability probe and the detached spawn. */
|
|
44
|
+
export interface LaunchDeps {
|
|
45
|
+
available?: () => boolean;
|
|
46
|
+
spawnDetached?: (command: string, args: string[]) => void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolves a client-supplied plan path to an absolute path, requiring it to be
|
|
50
|
+
* an existing file inside `<root>/plans` or `<root>/archive`. Returns the
|
|
51
|
+
* absolute path on success or a user-facing error otherwise.
|
|
52
|
+
*
|
|
53
|
+
* `root` is the absolute `.ai/strikethroo` directory; client paths are the
|
|
54
|
+
* workspace-relative form the SPA shows (e.g. `.ai/strikethroo/plans/NN--s/…`),
|
|
55
|
+
* so they are resolved against the project root (`root/../..`). Absolute client
|
|
56
|
+
* paths are accepted too — the containment check is what enforces safety.
|
|
57
|
+
*/
|
|
58
|
+
export declare const resolveReviewPath: (root: string, clientPath: string) => {
|
|
59
|
+
absPath: string;
|
|
60
|
+
} | {
|
|
61
|
+
error: string;
|
|
62
|
+
status: number;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Validates `clientPath` and, if the binary is available, launches
|
|
66
|
+
* `self-review <absolutePath>` detached. Pure of HTTP concerns: returns the
|
|
67
|
+
* status/body the endpoint should send so it stays unit-testable.
|
|
68
|
+
*/
|
|
69
|
+
export declare const launchSelfReview: (root: string, clientPath: string, deps?: LaunchDeps) => LaunchResult;
|
|
70
|
+
//# sourceMappingURL=self-review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-review.d.ts","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,iFAAiF;AACjF,eAAO,MAAM,eAAe,0CAA0C,CAAC;AAEvE;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,KACpD,OAoBF,CAAC;AAEF,gEAAgE;AAChE,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,EAAE;QAAE,EAAE,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAC3D;AAWD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,YAAY,MAAM,KACjB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CA4BvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,OAAM,UAAe,KACpB,YAwBF,CAAC"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Self-review launch capability for `npx strikethroo serve`.
|
|
4
|
+
*
|
|
5
|
+
* The serve API is otherwise read-only. This module adds the single, narrowly
|
|
6
|
+
* scoped exception the SPA's "Launch self-review" button needs:
|
|
7
|
+
*
|
|
8
|
+
* - {@link isSelfReviewAvailable} — a PATH scan answering "is the `self-review`
|
|
9
|
+
* binary installed?", exposed to the SPA via `GET /api/capabilities` so the
|
|
10
|
+
* button only renders when launching can actually succeed;
|
|
11
|
+
* - {@link launchSelfReview} — validates a client-supplied plan path stays
|
|
12
|
+
* inside the workspace's `plans/` or `archive/` subtree, then spawns the
|
|
13
|
+
* binary detached (fire-and-forget, like the browser auto-open).
|
|
14
|
+
*
|
|
15
|
+
* Untrusted input (the path string) is never passed to the shell: `spawn` is
|
|
16
|
+
* invoked with an argv array, and the path is rejected before spawning unless it
|
|
17
|
+
* resolves to an existing file under `plans/` or `archive/`. Node built-ins only.
|
|
18
|
+
*/
|
|
19
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
22
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
23
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
24
|
+
}
|
|
25
|
+
Object.defineProperty(o, k2, desc);
|
|
26
|
+
}) : (function(o, m, k, k2) {
|
|
27
|
+
if (k2 === undefined) k2 = k;
|
|
28
|
+
o[k2] = m[k];
|
|
29
|
+
}));
|
|
30
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
31
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32
|
+
}) : function(o, v) {
|
|
33
|
+
o["default"] = v;
|
|
34
|
+
});
|
|
35
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
36
|
+
var ownKeys = function(o) {
|
|
37
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
38
|
+
var ar = [];
|
|
39
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
40
|
+
return ar;
|
|
41
|
+
};
|
|
42
|
+
return ownKeys(o);
|
|
43
|
+
};
|
|
44
|
+
return function (mod) {
|
|
45
|
+
if (mod && mod.__esModule) return mod;
|
|
46
|
+
var result = {};
|
|
47
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
48
|
+
__setModuleDefault(result, mod);
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
})();
|
|
52
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
|
+
exports.launchSelfReview = exports.resolveReviewPath = exports.isSelfReviewAvailable = exports.SELF_REVIEW_URL = exports.SELF_REVIEW_BINARY = void 0;
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const path = __importStar(require("path"));
|
|
56
|
+
const child_process_1 = require("child_process");
|
|
57
|
+
/** The binary name looked up on PATH and spawned. */
|
|
58
|
+
exports.SELF_REVIEW_BINARY = 'self-review';
|
|
59
|
+
/** Where to obtain self-review; surfaced by the SPA when it is not installed. */
|
|
60
|
+
exports.SELF_REVIEW_URL = 'https://github.com/e0ipso/self-review';
|
|
61
|
+
/**
|
|
62
|
+
* Returns `true` when the `self-review` binary is found on the process `PATH`.
|
|
63
|
+
*
|
|
64
|
+
* A presence check, matching the literal "binary is in path" contract: each
|
|
65
|
+
* `PATH` entry is probed for a regular file named `self-review` (plus the
|
|
66
|
+
* `PATHEXT` variants on Windows). It deliberately does not execute the binary,
|
|
67
|
+
* so it cannot hang and has no side effects.
|
|
68
|
+
*/
|
|
69
|
+
const isSelfReviewAvailable = (env = process.env) => {
|
|
70
|
+
const pathVar = env.PATH ?? env.Path ?? '';
|
|
71
|
+
if (!pathVar)
|
|
72
|
+
return false;
|
|
73
|
+
const exts = process.platform === 'win32'
|
|
74
|
+
? (env.PATHEXT ?? '.EXE;.CMD;.BAT;.COM').split(';').filter(Boolean)
|
|
75
|
+
: [''];
|
|
76
|
+
for (const dir of pathVar.split(path.delimiter).filter(Boolean)) {
|
|
77
|
+
for (const ext of exts) {
|
|
78
|
+
const candidate = path.join(dir, exports.SELF_REVIEW_BINARY + ext);
|
|
79
|
+
try {
|
|
80
|
+
if (fs.statSync(candidate).isFile())
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Not present in this directory; keep scanning.
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
90
|
+
exports.isSelfReviewAvailable = isSelfReviewAvailable;
|
|
91
|
+
/** Spawns the binary detached and unref'd so it outlives the request. */
|
|
92
|
+
const spawnDetached = (command, args) => {
|
|
93
|
+
const child = (0, child_process_1.spawn)(command, args, { stdio: 'ignore', detached: true });
|
|
94
|
+
child.on('error', () => {
|
|
95
|
+
/* a failed launch must not crash the server */
|
|
96
|
+
});
|
|
97
|
+
child.unref();
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Resolves a client-supplied plan path to an absolute path, requiring it to be
|
|
101
|
+
* an existing file inside `<root>/plans` or `<root>/archive`. Returns the
|
|
102
|
+
* absolute path on success or a user-facing error otherwise.
|
|
103
|
+
*
|
|
104
|
+
* `root` is the absolute `.ai/strikethroo` directory; client paths are the
|
|
105
|
+
* workspace-relative form the SPA shows (e.g. `.ai/strikethroo/plans/NN--s/…`),
|
|
106
|
+
* so they are resolved against the project root (`root/../..`). Absolute client
|
|
107
|
+
* paths are accepted too — the containment check is what enforces safety.
|
|
108
|
+
*/
|
|
109
|
+
const resolveReviewPath = (root, clientPath) => {
|
|
110
|
+
if (typeof clientPath !== 'string' || clientPath.trim() === '') {
|
|
111
|
+
return { error: 'A plan path is required.', status: 400 };
|
|
112
|
+
}
|
|
113
|
+
const projectRoot = path.resolve(root, '..', '..');
|
|
114
|
+
const resolved = path.resolve(projectRoot, clientPath);
|
|
115
|
+
const plansDir = path.join(root, 'plans');
|
|
116
|
+
const archiveDir = path.join(root, 'archive');
|
|
117
|
+
const within = (dir) => resolved === dir || resolved.startsWith(dir + path.sep);
|
|
118
|
+
if (!within(plansDir) && !within(archiveDir)) {
|
|
119
|
+
return {
|
|
120
|
+
error: 'Plan path must be inside the workspace plans/ or archive/ directory.',
|
|
121
|
+
status: 400,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
if (!fs.statSync(resolved).isFile()) {
|
|
126
|
+
return { error: 'Plan path does not point to a file.', status: 404 };
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return { error: 'Plan file not found.', status: 404 };
|
|
131
|
+
}
|
|
132
|
+
return { absPath: resolved };
|
|
133
|
+
};
|
|
134
|
+
exports.resolveReviewPath = resolveReviewPath;
|
|
135
|
+
/**
|
|
136
|
+
* Validates `clientPath` and, if the binary is available, launches
|
|
137
|
+
* `self-review <absolutePath>` detached. Pure of HTTP concerns: returns the
|
|
138
|
+
* status/body the endpoint should send so it stays unit-testable.
|
|
139
|
+
*/
|
|
140
|
+
const launchSelfReview = (root, clientPath, deps = {}) => {
|
|
141
|
+
const available = deps.available ?? exports.isSelfReviewAvailable;
|
|
142
|
+
if (!available()) {
|
|
143
|
+
return {
|
|
144
|
+
status: 409,
|
|
145
|
+
body: { ok: false, error: 'self-review is not installed on PATH.' },
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const resolved = (0, exports.resolveReviewPath)(root, clientPath);
|
|
149
|
+
if ('error' in resolved) {
|
|
150
|
+
return { status: resolved.status, body: { ok: false, error: resolved.error } };
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
(deps.spawnDetached ?? spawnDetached)(exports.SELF_REVIEW_BINARY, [resolved.absPath]);
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
return {
|
|
157
|
+
status: 500,
|
|
158
|
+
body: { ok: false, error: `Failed to launch self-review: ${err.message}` },
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return { status: 200, body: { ok: true } };
|
|
162
|
+
};
|
|
163
|
+
exports.launchSelfReview = launchSelfReview;
|
|
164
|
+
//# sourceMappingURL=self-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-review.js","sourceRoot":"","sources":["../../src/serve/self-review.ts"],"names":[],"mappings":"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"}
|