@rsaglobaltech/specgate 0.17.10 → 0.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 +56 -0
- package/README.md +4 -4
- package/bin/specgate.ts +1 -0
- package/dist/bin/specgate.js +1 -0
- package/dist/bin/specgate.js.map +1 -1
- package/dist/packages/core/src/application/ArchiveChangeUseCase.js +5 -1
- package/dist/packages/core/src/application/ArchiveChangeUseCase.js.map +1 -1
- package/dist/packages/core/src/domain/DraftChecklist.js +35 -3
- package/dist/packages/core/src/domain/DraftChecklist.js.map +1 -1
- package/dist/packages/core/src/domain/PackSpec.js +21 -2
- package/dist/packages/core/src/domain/PackSpec.js.map +1 -1
- package/dist/scripts/agents/commands.js +18 -0
- package/dist/scripts/agents/commands.js.map +1 -1
- package/dist/scripts/agents/init.js +9 -1
- package/dist/scripts/agents/init.js.map +1 -1
- package/dist/scripts/cli/commands/change/ChangeCommand.js +8 -4
- package/dist/scripts/cli/commands/change/ChangeCommand.js.map +1 -1
- package/dist/scripts/cli/commands/project/AdoptCommand.js +8 -1
- package/dist/scripts/cli/commands/project/AdoptCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/DraftCommand.js +637 -24
- package/dist/scripts/cli/commands/spec/DraftCommand.js.map +1 -1
- package/dist/scripts/cli/commands/spec/StatusCommand.js +41 -2
- package/dist/scripts/cli/commands/spec/StatusCommand.js.map +1 -1
- package/dist/scripts/docs/build-site.js +1 -1
- package/dist/scripts/docs/journey-storyboard.js +358 -0
- package/dist/scripts/docs/journey-storyboard.js.map +1 -0
- package/dist/scripts/docs/nav.js +112 -5
- package/dist/scripts/docs/nav.js.map +1 -1
- package/dist/scripts/docs/record-journey.js +376 -0
- package/dist/scripts/docs/record-journey.js.map +1 -0
- package/dist/scripts/docs/record-terminal.js +252 -35
- package/dist/scripts/docs/record-terminal.js.map +1 -1
- package/dist/scripts/docs/terminal-storyboard.js +151 -2
- package/dist/scripts/docs/terminal-storyboard.js.map +1 -1
- package/dist/scripts/draft/brief-setup.js +363 -0
- package/dist/scripts/draft/brief-setup.js.map +1 -0
- package/dist/scripts/draft/confined-agent.js +175 -0
- package/dist/scripts/draft/confined-agent.js.map +1 -0
- package/dist/scripts/draft/drafting-guide.js +145 -0
- package/dist/scripts/draft/drafting-guide.js.map +1 -0
- package/dist/scripts/lib/surface.js +8 -1
- package/dist/scripts/lib/surface.js.map +1 -1
- package/package.json +3 -1
- package/templates/base/AGENTS.md.tpl +6 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The brief's front matter: what it is for, how to write it, and what is
|
|
4
|
+
* wrong with one.
|
|
5
|
+
*
|
|
6
|
+
* `specgate draft` needs four facts the brief rarely states in a form a tool
|
|
7
|
+
* can read: the product, where people use it, who uses it where, and the
|
|
8
|
+
* pieces to draft one at a time. The user who tried the first version did
|
|
9
|
+
* not know who was meant to write them, or how (#95). So this module holds
|
|
10
|
+
* everything `draft` tells a person about them — the explanation, the
|
|
11
|
+
* template, the guide an agent follows to propose them — and checks a front
|
|
12
|
+
* matter in plain words, each problem with its fix.
|
|
13
|
+
*
|
|
14
|
+
* The parsing is the checklist's own (`actorSurfaces`, `briefModules`), so a
|
|
15
|
+
* front matter this module accepts is one the checklist can read.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.BRIEF_SETUP_PASTE = exports.BRIEF_SETUP_FILE = exports.BRIEF_TEMPLATE = exports.FRONT_MATTER_EXAMPLE = exports.SURFACES = void 0;
|
|
19
|
+
exports.frontMatter = frontMatter;
|
|
20
|
+
exports.briefBody = briefBody;
|
|
21
|
+
exports.checkFrontMatter = checkFrontMatter;
|
|
22
|
+
exports.frontMatterExplanation = frontMatterExplanation;
|
|
23
|
+
exports.noBriefExplanation = noBriefExplanation;
|
|
24
|
+
exports.briefSetupGuide = briefSetupGuide;
|
|
25
|
+
exports.briefSetupPrompt = briefSetupPrompt;
|
|
26
|
+
const DraftChecklist_1 = require("../../packages/core/src/domain/DraftChecklist");
|
|
27
|
+
/** The places D3 knows how to check: an HTTP call, or a screen. */
|
|
28
|
+
exports.SURFACES = ["api", "web", "mobile", "desktop"];
|
|
29
|
+
const FRONT = /^---\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/;
|
|
30
|
+
/** The YAML between the leading `---` lines, or null. */
|
|
31
|
+
function frontMatter(brief) {
|
|
32
|
+
const m = FRONT.exec(brief);
|
|
33
|
+
return m ? m[1] : null;
|
|
34
|
+
}
|
|
35
|
+
/** Everything after the front matter, without the blank lines that follow it. */
|
|
36
|
+
function briefBody(brief) {
|
|
37
|
+
const m = FRONT.exec(brief);
|
|
38
|
+
return (m ? brief.slice(m[0].length) : brief).replace(/^(?:[ \t]*\r?\n)+/, "");
|
|
39
|
+
}
|
|
40
|
+
const uncomment = (fm) => fm
|
|
41
|
+
.split("\n")
|
|
42
|
+
.filter((l) => !/^\s*#/.test(l))
|
|
43
|
+
.join("\n");
|
|
44
|
+
function field(fm, name) {
|
|
45
|
+
const m = new RegExp(`^${name}:[ \\t]*(.*)$`, "m").exec(uncomment(fm));
|
|
46
|
+
return m ? m[1].trim() : null;
|
|
47
|
+
}
|
|
48
|
+
function list(value) {
|
|
49
|
+
const m = /^\[([^\]]*)\]/.exec(value || "");
|
|
50
|
+
return m
|
|
51
|
+
? m[1]
|
|
52
|
+
.split(",")
|
|
53
|
+
.map((s) => s.trim())
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
: [];
|
|
56
|
+
}
|
|
57
|
+
const placeholder = (v) => /<[^>]+>/.test(v);
|
|
58
|
+
const kebab = (s) => s
|
|
59
|
+
.toLowerCase()
|
|
60
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
61
|
+
.replace(/^-|-$/g, "");
|
|
62
|
+
/** What is wrong with a front matter, in plain words. Empty when it is usable. */
|
|
63
|
+
function checkFrontMatter(brief) {
|
|
64
|
+
const fm = frontMatter(brief);
|
|
65
|
+
if (fm === null)
|
|
66
|
+
return [];
|
|
67
|
+
const text = uncomment(fm);
|
|
68
|
+
const out = [];
|
|
69
|
+
const known = (s) => exports.SURFACES.includes(s);
|
|
70
|
+
const surfaceList = exports.SURFACES.join(", ");
|
|
71
|
+
const product = field(fm, "product");
|
|
72
|
+
if (!product) {
|
|
73
|
+
out.push({
|
|
74
|
+
code: "brief_no_product",
|
|
75
|
+
message: "There is no `product:` line.",
|
|
76
|
+
fix: "Add one with the product in a few words, e.g. `product: Lingo — online lessons for a language school`.",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else if (placeholder(product)) {
|
|
80
|
+
out.push({
|
|
81
|
+
code: "brief_placeholder",
|
|
82
|
+
message: `\`product:\` still says ${product}.`,
|
|
83
|
+
fix: "Replace it with your product in a few words.",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const surfaces = list(field(fm, "surfaces"));
|
|
87
|
+
const unfilled = surfaces.filter(placeholder);
|
|
88
|
+
if (unfilled.length > 0) {
|
|
89
|
+
out.push({
|
|
90
|
+
code: "brief_placeholder",
|
|
91
|
+
message: `\`surfaces:\` still says ${unfilled.join(", ")}.`,
|
|
92
|
+
fix: `Use the places people reach the product: ${surfaceList}.`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
for (const s of surfaces.filter((x) => !placeholder(x))) {
|
|
96
|
+
if (!known(s.toLowerCase())) {
|
|
97
|
+
out.push({
|
|
98
|
+
code: "brief_unknown_surface",
|
|
99
|
+
message: `\`surfaces:\` names "${s}", which Specgate cannot check.`,
|
|
100
|
+
fix: `Use ${surfaceList}. A tablet or a kiosk is \`web\` or \`mobile\`; another system calling yours is \`api\`.`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Every `name:` is an actor; the checklist only reads `{ name: X, surfaces: [..] }`.
|
|
105
|
+
const named = [...text.matchAll(/\bname:\s*([^,}\n]+)/g)].map((m) => m[1].trim());
|
|
106
|
+
const actors = (0, DraftChecklist_1.actorSurfaces)(brief);
|
|
107
|
+
if (named.length === 0) {
|
|
108
|
+
out.push({
|
|
109
|
+
code: "brief_no_actors",
|
|
110
|
+
message: "There is no `actors:` list.",
|
|
111
|
+
fix: "Name everyone who uses the product and where: `- { name: Student, surfaces: [web, mobile] }`.",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
for (const name of named) {
|
|
115
|
+
if (placeholder(name)) {
|
|
116
|
+
out.push({
|
|
117
|
+
code: "brief_placeholder",
|
|
118
|
+
message: `An actor is still called ${name}.`,
|
|
119
|
+
fix: "Name the person or system, e.g. Teacher, Student, Payment provider.",
|
|
120
|
+
});
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const theirs = actors.get(name.toLowerCase());
|
|
124
|
+
if (!theirs || theirs.length === 0) {
|
|
125
|
+
out.push({
|
|
126
|
+
code: "brief_actor_without_surfaces",
|
|
127
|
+
message: `${name} has no surfaces.`,
|
|
128
|
+
fix: `Write it as \`- { name: ${name}, surfaces: [web] }\`, with every place ${name} uses.`,
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
for (const s of theirs) {
|
|
133
|
+
if (placeholder(s)) {
|
|
134
|
+
out.push({
|
|
135
|
+
code: "brief_placeholder",
|
|
136
|
+
message: `${name}'s surfaces still say ${s}.`,
|
|
137
|
+
fix: `Use ${surfaceList}.`,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
else if (!known(s)) {
|
|
141
|
+
out.push({
|
|
142
|
+
code: "brief_unknown_surface",
|
|
143
|
+
message: `${name} uses "${s}", which Specgate cannot check.`,
|
|
144
|
+
fix: `Use ${surfaceList}. A tablet or a kiosk is \`web\` or \`mobile\`.`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
else if (surfaces.length > 0 && !surfaces.map((x) => x.toLowerCase()).includes(s)) {
|
|
148
|
+
out.push({
|
|
149
|
+
code: "brief_surface_not_in_product",
|
|
150
|
+
message: `${name} uses ${s}, but \`surfaces:\` does not list it.`,
|
|
151
|
+
fix: `Add ${s} to \`surfaces:\`, or take it off ${name}.`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const modules = (0, DraftChecklist_1.briefModules)(brief);
|
|
157
|
+
if (modules.length === 0) {
|
|
158
|
+
out.push({
|
|
159
|
+
code: "brief_no_modules",
|
|
160
|
+
message: "There is no `modules:` list, or it is empty.",
|
|
161
|
+
fix: "List the pieces to build, in order: `modules: [courses, lessons, exercises]`.",
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const unnamed = modules.filter(placeholder);
|
|
165
|
+
if (unnamed.length > 0) {
|
|
166
|
+
out.push({
|
|
167
|
+
code: "brief_placeholder",
|
|
168
|
+
message: `\`modules:\` still says ${unnamed.join(", ")}.`,
|
|
169
|
+
fix: "Name the pieces of the product you will build, e.g. courses, lessons, exercises.",
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const seen = new Set();
|
|
173
|
+
for (const m of modules.filter((x) => !placeholder(x))) {
|
|
174
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(m)) {
|
|
175
|
+
out.push({
|
|
176
|
+
code: "brief_module_name",
|
|
177
|
+
message: `The module "${m}" has spaces, capitals or symbols.`,
|
|
178
|
+
fix: `Write it as ${kebab(m) || "lowercase-words"} — it becomes a folder and a command: specgate draft ${kebab(m) || "<module>"}.`,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
else if (seen.has(m)) {
|
|
182
|
+
out.push({
|
|
183
|
+
code: "brief_module_twice",
|
|
184
|
+
message: `The module "${m}" is listed twice.`,
|
|
185
|
+
fix: "Keep one.",
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
seen.add(m);
|
|
189
|
+
}
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
/** The front matter to paste, with every field explained beside an example. */
|
|
193
|
+
exports.FRONT_MATTER_EXAMPLE = [
|
|
194
|
+
"---",
|
|
195
|
+
"product: Lingo — online lessons for a language school",
|
|
196
|
+
"surfaces: [api, web, mobile]",
|
|
197
|
+
"actors:",
|
|
198
|
+
" - { name: Teacher, surfaces: [api, web] }",
|
|
199
|
+
" - { name: Student, surfaces: [api, web, mobile] }",
|
|
200
|
+
"modules: [courses, lessons, exercises, progress]",
|
|
201
|
+
"---",
|
|
202
|
+
].join("\n");
|
|
203
|
+
/** What `specgate draft` prints when the brief has no front matter. */
|
|
204
|
+
function frontMatterExplanation(brief) {
|
|
205
|
+
return [
|
|
206
|
+
` Your brief has no front matter yet: four fields at the very top of ${brief}`,
|
|
207
|
+
" that tell Specgate what to draft, and what to check each draft against.",
|
|
208
|
+
" Your text below them stays exactly as it is.",
|
|
209
|
+
"",
|
|
210
|
+
" product What you are building, in a few words.",
|
|
211
|
+
" product: Lingo — online lessons for a language school",
|
|
212
|
+
"",
|
|
213
|
+
` surfaces Where people reach it. Any of: ${exports.SURFACES.join(", ")}.`,
|
|
214
|
+
" api means another program calls it; web, mobile and desktop are screens.",
|
|
215
|
+
" surfaces: [api, web, mobile]",
|
|
216
|
+
"",
|
|
217
|
+
" actors Everyone who uses it, and where. Each gets a scenario on each of",
|
|
218
|
+
" their surfaces — so no screen is forgotten. (In the first pilot every",
|
|
219
|
+
" requirement was done and nobody could use the product: there was",
|
|
220
|
+
" not a single screen.) Only people and systems your brief mentions.",
|
|
221
|
+
" actors:",
|
|
222
|
+
" - { name: Teacher, surfaces: [api, web] }",
|
|
223
|
+
" - { name: Student, surfaces: [api, web, mobile] }",
|
|
224
|
+
"",
|
|
225
|
+
" modules The pieces to specify and build, in the order you will build them.",
|
|
226
|
+
" Each small enough to review in one sitting — 25 requirements at",
|
|
227
|
+
" most. Lowercase words with dashes; each becomes `specgate draft <module>`.",
|
|
228
|
+
" modules: [courses, lessons, exercises, progress]",
|
|
229
|
+
"",
|
|
230
|
+
" The whole block, to paste at the top and change:",
|
|
231
|
+
"",
|
|
232
|
+
...exports.FRONT_MATTER_EXAMPLE.split("\n").map((l) => ` ${l}`),
|
|
233
|
+
"",
|
|
234
|
+
].join("\n");
|
|
235
|
+
}
|
|
236
|
+
/** What a good brief is, for a person who has none yet. */
|
|
237
|
+
function noBriefExplanation(brief) {
|
|
238
|
+
return [
|
|
239
|
+
` No brief yet. Specgate drafts your specification from a brief: ${brief}.`,
|
|
240
|
+
"",
|
|
241
|
+
" A brief is whatever says what the product must do — your own plan, a",
|
|
242
|
+
" client's email, meeting notes. Any markdown. Paste it as it is: Specgate",
|
|
243
|
+
" never rewrites it, and checks every draft against its words.",
|
|
244
|
+
"",
|
|
245
|
+
" A good brief says:",
|
|
246
|
+
" · what the product is, and for whom",
|
|
247
|
+
" · who uses it, and where — on the web, on a phone, through an API",
|
|
248
|
+
" · what each of them must be able to do",
|
|
249
|
+
" · the rules and numbers you already know — prices, limits, deadlines",
|
|
250
|
+
" · what you don't know yet — those become questions, not guesses",
|
|
251
|
+
" · what is out of scope",
|
|
252
|
+
"",
|
|
253
|
+
" Already have one? Save it as docs/brief.md, then specgate draft",
|
|
254
|
+
" Starting fresh? specgate draft --new-brief writes one to fill in",
|
|
255
|
+
"",
|
|
256
|
+
].join("\n");
|
|
257
|
+
}
|
|
258
|
+
/** `docs/brief.md` from `specgate draft --new-brief`. */
|
|
259
|
+
exports.BRIEF_TEMPLATE = `---
|
|
260
|
+
# The product, in a few words.
|
|
261
|
+
# Example: Lingo — online lessons for a language school
|
|
262
|
+
product: <your product>
|
|
263
|
+
# Where people reach it. Any of: api, web, mobile, desktop.
|
|
264
|
+
# api means another program calls it; the others are screens.
|
|
265
|
+
# Example: [api, web, mobile]
|
|
266
|
+
surfaces: [<surface>, <surface>]
|
|
267
|
+
# Everyone who uses it, and where. Each gets a scenario on each of their
|
|
268
|
+
# surfaces, so no screen is forgotten. Example:
|
|
269
|
+
# - { name: Teacher, surfaces: [api, web] }
|
|
270
|
+
# - { name: Student, surfaces: [api, web, mobile] }
|
|
271
|
+
actors:
|
|
272
|
+
- { name: <Actor>, surfaces: [<surface>] }
|
|
273
|
+
# The pieces to specify and build, in the order you will build them, each
|
|
274
|
+
# small enough to review in one sitting. Lowercase words with dashes.
|
|
275
|
+
# Example: [courses, lessons, exercises, progress]
|
|
276
|
+
modules: [<first-module>, <second-module>]
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
# <your product>
|
|
280
|
+
|
|
281
|
+
## What the product is
|
|
282
|
+
|
|
283
|
+
<!-- Two or three sentences: what it does, and for whom. -->
|
|
284
|
+
|
|
285
|
+
## Who uses it and how
|
|
286
|
+
|
|
287
|
+
<!-- Each kind of person, or system, and where: on the web, on a phone, through an API. -->
|
|
288
|
+
|
|
289
|
+
## What each one must be able to do
|
|
290
|
+
|
|
291
|
+
<!-- For each of them, the things they do, in their own words. A line each is enough. -->
|
|
292
|
+
|
|
293
|
+
## Rules and numbers you already know
|
|
294
|
+
|
|
295
|
+
<!-- Prices, limits, deadlines, opening hours. Only real ones: if you are not sure, leave it out. -->
|
|
296
|
+
|
|
297
|
+
## What you don't know yet
|
|
298
|
+
|
|
299
|
+
<!-- Open questions. Each becomes a question for the client instead of a guess. -->
|
|
300
|
+
|
|
301
|
+
## Out of scope
|
|
302
|
+
|
|
303
|
+
<!-- What the product will not do, at least for now. -->
|
|
304
|
+
`;
|
|
305
|
+
/** Where the guide for an agent proposing the front matter is written. */
|
|
306
|
+
exports.BRIEF_SETUP_FILE = "docs/specs/BRIEF-SETUP.md";
|
|
307
|
+
/** The guide an agent follows to propose a front matter. */
|
|
308
|
+
function briefSetupGuide(brief) {
|
|
309
|
+
return [
|
|
310
|
+
"# Propose the brief's front matter",
|
|
311
|
+
"",
|
|
312
|
+
`Read \`${brief}\` and add a front matter at its very top: the lines between`,
|
|
313
|
+
"two `---` that tell Specgate what to draft. A person reviews what you write.",
|
|
314
|
+
"",
|
|
315
|
+
"## The rules",
|
|
316
|
+
"",
|
|
317
|
+
`- **Change nothing below the front matter.** The brief is the client's words;`,
|
|
318
|
+
" if a single character of it changes, your work is undone.",
|
|
319
|
+
"- **Only what the brief states.** Never invent an actor, a surface or a module",
|
|
320
|
+
" the brief does not support. When you are unsure, still propose it, with a",
|
|
321
|
+
" `# check: …` comment on the line above saying what is uncertain.",
|
|
322
|
+
`- Write only \`${brief}\`. Anything else you write is undone.`,
|
|
323
|
+
"",
|
|
324
|
+
"## The fields",
|
|
325
|
+
"",
|
|
326
|
+
"```yaml",
|
|
327
|
+
"---",
|
|
328
|
+
"product: <the product, in a few words>",
|
|
329
|
+
`surfaces: [<where people reach it: ${exports.SURFACES.join(", ")}>]`,
|
|
330
|
+
"actors:",
|
|
331
|
+
" - { name: <a person or system the brief names>, surfaces: [<where they use it>] }",
|
|
332
|
+
"modules: [<pieces to build, in build order>]",
|
|
333
|
+
"---",
|
|
334
|
+
"```",
|
|
335
|
+
"",
|
|
336
|
+
`- \`surfaces\`: only ${exports.SURFACES.join(", ")}. \`api\` means another program calls`,
|
|
337
|
+
" the product; `web`, `mobile` and `desktop` are screens.",
|
|
338
|
+
"- `actors`: one line each, in exactly that `{ name: …, surfaces: [...] }` form.",
|
|
339
|
+
" Every surface of an actor is also in `surfaces`.",
|
|
340
|
+
"- `modules`: lowercase words with dashes. In the order they can be built —",
|
|
341
|
+
" what others depend on first. Each small enough to review in one sitting:",
|
|
342
|
+
" 25 requirements at most; split a large area in two.",
|
|
343
|
+
"",
|
|
344
|
+
"## Then",
|
|
345
|
+
"",
|
|
346
|
+
"Run `specgate draft` and fix anything it reports about the front matter.",
|
|
347
|
+
"Stop there and show the front matter to the person: they review it before",
|
|
348
|
+
"anything is drafted. Do not run `specgate draft <module>`.",
|
|
349
|
+
"",
|
|
350
|
+
].join("\n");
|
|
351
|
+
}
|
|
352
|
+
/** The prompt `--agent` sends, and the line to paste into any agent. */
|
|
353
|
+
exports.BRIEF_SETUP_PASTE = `Propose the front matter of docs/brief.md: follow ${exports.BRIEF_SETUP_FILE}`;
|
|
354
|
+
function briefSetupPrompt(guide) {
|
|
355
|
+
return [
|
|
356
|
+
`Propose the front matter of docs/brief.md, following the guide below (also saved as ${exports.BRIEF_SETUP_FILE}).`,
|
|
357
|
+
"",
|
|
358
|
+
"---",
|
|
359
|
+
"",
|
|
360
|
+
guide,
|
|
361
|
+
].join("\n");
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=brief-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief-setup.js","sourceRoot":"","sources":["../../../scripts/draft/brief-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Run an agent on one change, and undo whatever it writes anywhere else.
|
|
4
|
+
*
|
|
5
|
+
* `change author` does the same with a precondition: a clean working tree, so
|
|
6
|
+
* that reverting can only ever discard the agent's own work. That is the
|
|
7
|
+
* safe rule, and on the brief-first path it is the wrong one — the person
|
|
8
|
+
* has just saved `docs/brief.md` and `specgate draft` has just created the
|
|
9
|
+
* change, so the tree is never clean when they reach for `--agent`.
|
|
10
|
+
*
|
|
11
|
+
* So this one remembers instead of refusing. Before the agent runs, it reads
|
|
12
|
+
* every file git already reports as changed or untracked; afterwards, any
|
|
13
|
+
* path outside the change that differs is put back the way it was — a file
|
|
14
|
+
* the person had edited returns to *their* edit, not to the last commit, and
|
|
15
|
+
* a file the agent created is removed. Git is still required: it is how the
|
|
16
|
+
* agent's footprint is found at all.
|
|
17
|
+
*/
|
|
18
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
21
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
22
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
23
|
+
}
|
|
24
|
+
Object.defineProperty(o, k2, desc);
|
|
25
|
+
}) : (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
o[k2] = m[k];
|
|
28
|
+
}));
|
|
29
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
30
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31
|
+
}) : function(o, v) {
|
|
32
|
+
o["default"] = v;
|
|
33
|
+
});
|
|
34
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
35
|
+
var ownKeys = function(o) {
|
|
36
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
37
|
+
var ar = [];
|
|
38
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
39
|
+
return ar;
|
|
40
|
+
};
|
|
41
|
+
return ownKeys(o);
|
|
42
|
+
};
|
|
43
|
+
return function (mod) {
|
|
44
|
+
if (mod && mod.__esModule) return mod;
|
|
45
|
+
var result = {};
|
|
46
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
47
|
+
__setModuleDefault(result, mod);
|
|
48
|
+
return result;
|
|
49
|
+
};
|
|
50
|
+
})();
|
|
51
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
52
|
+
exports.agentInvocation = agentInvocation;
|
|
53
|
+
exports.runConfinedAgent = runConfinedAgent;
|
|
54
|
+
const fs = __importStar(require("node:fs"));
|
|
55
|
+
const path = __importStar(require("node:path"));
|
|
56
|
+
const os = __importStar(require("node:os"));
|
|
57
|
+
const node_child_process_1 = require("node:child_process");
|
|
58
|
+
const AuthoringScope_1 = require("../../packages/core/src/domain/AuthoringScope");
|
|
59
|
+
/** Every path git sees as changed or untracked, one file per entry. */
|
|
60
|
+
function dirtyPaths(projectDir) {
|
|
61
|
+
const r = (0, node_child_process_1.spawnSync)("git", ["-C", projectDir, "status", "--porcelain", "--untracked-files=all", "-z"], { encoding: "utf8" });
|
|
62
|
+
if (r.status !== 0)
|
|
63
|
+
return null;
|
|
64
|
+
const out = [];
|
|
65
|
+
const parts = String(r.stdout).split("\0").filter(Boolean);
|
|
66
|
+
for (let i = 0; i < parts.length; i += 1) {
|
|
67
|
+
const code = parts[i].slice(0, 2);
|
|
68
|
+
out.push(parts[i].slice(3));
|
|
69
|
+
// A rename carries its old path as the next entry.
|
|
70
|
+
if (code[0] === "R" || code[0] === "C")
|
|
71
|
+
i += 1;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The command, with the prompt delivered: a `{prompt_file}` placeholder is
|
|
77
|
+
* replaced by a file holding it; otherwise the prompt goes to standard input,
|
|
78
|
+
* which is what `claude -p`, `codex exec -` and most agent CLIs read.
|
|
79
|
+
*/
|
|
80
|
+
function agentInvocation(command, promptFile) {
|
|
81
|
+
return command.includes("{prompt_file}")
|
|
82
|
+
? { command: command.split("{prompt_file}").join(promptFile), stdin: false }
|
|
83
|
+
: { command, stdin: true };
|
|
84
|
+
}
|
|
85
|
+
function runConfinedAgent(o) {
|
|
86
|
+
const inScope = o.allowed || ((rel) => (0, AuthoringScope_1.isInScope)(rel, o.changeId));
|
|
87
|
+
const before = dirtyPaths(o.projectDir);
|
|
88
|
+
if (before === null)
|
|
89
|
+
return { ok: false, problem: "no_git", wrote: [], reverted: [] };
|
|
90
|
+
// What the person had, outside the change, before the agent touched anything.
|
|
91
|
+
const saved = new Map();
|
|
92
|
+
for (const rel of before) {
|
|
93
|
+
if (inScope(rel))
|
|
94
|
+
continue;
|
|
95
|
+
const full = path.join(o.projectDir, rel);
|
|
96
|
+
saved.set(rel, fs.existsSync(full) && fs.statSync(full).isFile() ? fs.readFileSync(full) : null);
|
|
97
|
+
}
|
|
98
|
+
const promptFile = path.join(os.tmpdir(), `specgate-draft-${o.changeId}-${Date.now()}.md`);
|
|
99
|
+
fs.writeFileSync(promptFile, o.prompt, "utf8");
|
|
100
|
+
let agent;
|
|
101
|
+
try {
|
|
102
|
+
const call = agentInvocation(o.command, promptFile);
|
|
103
|
+
agent = (0, node_child_process_1.spawnSync)(call.command, {
|
|
104
|
+
shell: true,
|
|
105
|
+
cwd: o.projectDir,
|
|
106
|
+
encoding: "utf8",
|
|
107
|
+
input: call.stdin ? o.prompt : "",
|
|
108
|
+
// Shown, the agent talks in the same stream as the command around it, so
|
|
109
|
+
// its lines land in order. In --json mode it is captured: stdout is one
|
|
110
|
+
// document and nothing else.
|
|
111
|
+
stdio: ["pipe", o.showOutput ? 1 : "pipe", o.showOutput ? 2 : "pipe"],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
fs.rmSync(promptFile, { force: true });
|
|
116
|
+
}
|
|
117
|
+
const after = dirtyPaths(o.projectDir) || [];
|
|
118
|
+
const wrote = [];
|
|
119
|
+
const reverted = [];
|
|
120
|
+
for (const rel of after) {
|
|
121
|
+
if (inScope(rel)) {
|
|
122
|
+
if (!before.includes(rel))
|
|
123
|
+
wrote.push(rel);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const full = path.join(o.projectDir, rel);
|
|
127
|
+
if (saved.has(rel)) {
|
|
128
|
+
const was = saved.get(rel);
|
|
129
|
+
const now = fs.existsSync(full) && fs.statSync(full).isFile() ? fs.readFileSync(full) : null;
|
|
130
|
+
if (was === null && now === null)
|
|
131
|
+
continue;
|
|
132
|
+
if (was !== null && now !== null && was.equals(now))
|
|
133
|
+
continue;
|
|
134
|
+
if (was === null)
|
|
135
|
+
fs.rmSync(full, { recursive: true, force: true });
|
|
136
|
+
else
|
|
137
|
+
fs.writeFileSync(full, was);
|
|
138
|
+
reverted.push(rel);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
// Clean before, changed now: the agent did it.
|
|
142
|
+
const tracked = (0, node_child_process_1.spawnSync)("git", ["-C", o.projectDir, "ls-files", "--error-unmatch", "--", rel], {
|
|
143
|
+
encoding: "utf8",
|
|
144
|
+
}).status === 0;
|
|
145
|
+
if (tracked)
|
|
146
|
+
(0, node_child_process_1.spawnSync)("git", ["-C", o.projectDir, "checkout", "--", rel]);
|
|
147
|
+
else
|
|
148
|
+
fs.rmSync(full, { recursive: true, force: true });
|
|
149
|
+
reverted.push(rel);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// A file the person had changed and the agent deleted is gone from `after`.
|
|
153
|
+
for (const [rel, was] of saved) {
|
|
154
|
+
if (was === null || after.includes(rel))
|
|
155
|
+
continue;
|
|
156
|
+
const full = path.join(o.projectDir, rel);
|
|
157
|
+
if (!fs.existsSync(full)) {
|
|
158
|
+
fs.mkdirSync(path.dirname(full), { recursive: true });
|
|
159
|
+
fs.writeFileSync(full, was);
|
|
160
|
+
reverted.push(rel);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (agent.status !== 0) {
|
|
164
|
+
const tail = `${agent.stdout || ""}${agent.stderr || ""}`.trim().slice(-500);
|
|
165
|
+
return {
|
|
166
|
+
ok: false,
|
|
167
|
+
problem: "agent_failed",
|
|
168
|
+
detail: `exited ${agent.status ?? "on a signal"}${tail ? `: ${tail}` : ""}`,
|
|
169
|
+
wrote,
|
|
170
|
+
reverted,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return { ok: true, wrote, reverted };
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=confined-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confined-agent.js","sourceRoot":"","sources":["../../../scripts/draft/confined-agent.ts"],"names":[],"mappings":"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"}
|