@popoverai/dotrequirements 0.33.0 → 0.34.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/cli.js +13 -1
- package/dist/cloud.d.ts +5 -1
- package/dist/cloud.js +6 -2
- package/dist/commands/acceptance-test.js +1 -1
- package/dist/commands/board/index.d.ts +13 -0
- package/dist/commands/board/index.js +96 -0
- package/dist/commands/branch-merge.d.ts +78 -0
- package/dist/commands/branch-merge.js +129 -0
- package/dist/commands/diff.js +15 -5
- package/dist/commands/mockup/index.d.ts +11 -0
- package/dist/commands/mockup/index.js +82 -0
- package/dist/commands/scores/index.d.ts +50 -0
- package/dist/commands/scores/index.js +190 -0
- package/dist/commands/solution/ask.d.ts +9 -0
- package/dist/commands/solution/ask.js +27 -0
- package/dist/commands/solution/author.d.ts +19 -0
- package/dist/commands/solution/author.js +202 -0
- package/dist/commands/solution/branch.d.ts +103 -0
- package/dist/commands/solution/branch.js +341 -0
- package/dist/commands/solution/brief.d.ts +81 -0
- package/dist/commands/solution/brief.js +47 -0
- package/dist/commands/solution/checkout.d.ts +27 -0
- package/dist/commands/solution/checkout.js +66 -0
- package/dist/commands/solution/client.d.ts +16 -0
- package/dist/commands/solution/client.js +46 -0
- package/dist/commands/solution/contract.d.ts +9 -0
- package/dist/commands/solution/contract.js +23 -0
- package/dist/commands/solution/create.d.ts +14 -0
- package/dist/commands/solution/create.js +52 -0
- package/dist/commands/solution/demo-script.d.ts +28 -0
- package/dist/commands/solution/demo-script.js +43 -0
- package/dist/commands/solution/image.d.ts +60 -0
- package/dist/commands/solution/image.js +148 -0
- package/dist/commands/solution/index.d.ts +12 -0
- package/dist/commands/solution/index.js +282 -0
- package/dist/commands/solution/look-up.d.ts +9 -0
- package/dist/commands/solution/look-up.js +69 -0
- package/dist/commands/solution/next.d.ts +12 -0
- package/dist/commands/solution/next.js +48 -0
- package/dist/commands/solution/plan-file.d.ts +22 -0
- package/dist/commands/solution/plan-file.js +33 -0
- package/dist/commands/solution/preview-screenshot.d.ts +21 -0
- package/dist/commands/solution/preview-screenshot.js +56 -0
- package/dist/commands/solution/pull-request.d.ts +25 -0
- package/dist/commands/solution/pull-request.js +117 -0
- package/dist/commands/solution/pushing.d.ts +66 -0
- package/dist/commands/solution/pushing.js +185 -0
- package/dist/commands/solution/rehearse.d.ts +10 -0
- package/dist/commands/solution/rehearse.js +24 -0
- package/dist/commands/solution/request.d.ts +3 -0
- package/dist/commands/solution/request.js +13 -0
- package/dist/commands/solution/review.d.ts +27 -0
- package/dist/commands/solution/review.js +104 -0
- package/dist/commands/solution/run-file.d.ts +43 -0
- package/dist/commands/solution/run-file.js +69 -0
- package/dist/commands/solution/share.d.ts +62 -0
- package/dist/commands/solution/share.js +346 -0
- package/dist/commands/solution/stall.d.ts +14 -0
- package/dist/commands/solution/stall.js +41 -0
- package/dist/commands/solution/start.d.ts +14 -0
- package/dist/commands/solution/start.js +31 -0
- package/dist/commands/solution/status.d.ts +39 -0
- package/dist/commands/solution/status.js +145 -0
- package/dist/commands/solution/summary.d.ts +13 -0
- package/dist/commands/solution/summary.js +5 -0
- package/dist/commands/solution/things.d.ts +118 -0
- package/dist/commands/solution/things.js +78 -0
- package/dist/commands/solution/thread.d.ts +13 -0
- package/dist/commands/solution/thread.js +53 -0
- package/dist/commands/solution/upload.d.ts +24 -0
- package/dist/commands/solution/upload.js +27 -0
- package/dist/commands/solution/video.d.ts +88 -0
- package/dist/commands/solution/video.js +364 -0
- package/dist/commands/solution/working-folder.d.ts +44 -0
- package/dist/commands/solution/working-folder.js +64 -0
- package/dist/commands/sync.d.ts +2 -1
- package/dist/commands/sync.js +21 -5
- package/dist/convex.d.ts +54 -0
- package/dist/convex.js +64 -0
- package/dist/push/core.js +7 -2
- package/dist/rehearsal/derive.d.ts +23 -0
- package/dist/rehearsal/derive.js +112 -0
- package/dist/rehearsal/driver.d.ts +44 -0
- package/dist/rehearsal/driver.js +337 -0
- package/dist/rehearsal/earlier.d.ts +25 -0
- package/dist/rehearsal/earlier.js +138 -0
- package/dist/rehearsal/index.d.ts +5 -0
- package/dist/rehearsal/index.js +4 -0
- package/dist/rehearsal/live.d.ts +72 -0
- package/dist/rehearsal/live.js +301 -0
- package/dist/rehearsal/report.d.ts +4 -0
- package/dist/rehearsal/report.js +69 -0
- package/dist/rehearsal/types.d.ts +377 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/requirements/index.d.ts +6 -0
- package/dist/requirements/index.js +24 -0
- package/dist/schema/browser.d.ts +2 -1
- package/dist/schema/browser.js +6 -1
- package/dist/schema/file-writer.d.ts +5 -0
- package/dist/schema/file-writer.js +4 -0
- package/dist/schema/parser.d.ts +11 -2
- package/dist/schema/parser.js +11 -7
- package/dist/schema/provenance.d.ts +27 -0
- package/dist/schema/provenance.js +66 -0
- package/dist/schema/schemas.d.ts +40 -0
- package/dist/schema/schemas.js +4 -0
- package/dist/sync/execute.d.ts +10 -1
- package/dist/sync/execute.js +68 -5
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/publish.d.ts +7 -0
- package/dist/sync/segment.js +4 -1
- package/dist/sync/snapshot.d.ts +23 -1
- package/dist/sync/snapshot.js +75 -3
- package/dist/sync/solution-documents.d.ts +74 -0
- package/dist/sync/solution-documents.js +135 -0
- package/dist/sync/types.d.ts +20 -0
- package/package.json +3 -2
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rehearsal (docs/working/rehearsing-steps.md): a plan of outcomes, the
|
|
3
|
+
* artifacts its inputs hold, and who plays each agent the backend sends
|
|
4
|
+
* for — a real one, or a script that plays it from the brief the agent
|
|
5
|
+
* would get.
|
|
6
|
+
*/
|
|
7
|
+
export type Thing = {
|
|
8
|
+
kind: "document";
|
|
9
|
+
documentId: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "board";
|
|
12
|
+
boardId: string;
|
|
13
|
+
} | {
|
|
14
|
+
kind: "mockup";
|
|
15
|
+
mockupId: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "file";
|
|
18
|
+
path: string;
|
|
19
|
+
branch?: string;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "link";
|
|
22
|
+
url: string;
|
|
23
|
+
title?: string;
|
|
24
|
+
}
|
|
25
|
+
/** Something running in the sandbox, with the title a script names it by, if any (SIGHT-12.3). */
|
|
26
|
+
| {
|
|
27
|
+
kind: "preview";
|
|
28
|
+
port: number;
|
|
29
|
+
page?: string;
|
|
30
|
+
command: string;
|
|
31
|
+
title?: string;
|
|
32
|
+
}
|
|
33
|
+
/** The solution's pull request: a script submits it as given, checked against no repository (PULL-3.3). */
|
|
34
|
+
| {
|
|
35
|
+
kind: "pull request";
|
|
36
|
+
url: string;
|
|
37
|
+
number: number;
|
|
38
|
+
}
|
|
39
|
+
/** An image kept under its file name (SIGHT-9), as a scenario gives one to an input (REHEARSE-4.7). */
|
|
40
|
+
| {
|
|
41
|
+
kind: "image";
|
|
42
|
+
storageId: string;
|
|
43
|
+
name: string;
|
|
44
|
+
} | ({
|
|
45
|
+
kind: "scores";
|
|
46
|
+
} & Scores);
|
|
47
|
+
/** One axis of a solution's scores: a whole number from 1 to 5, and why. */
|
|
48
|
+
export type AxisScore = {
|
|
49
|
+
score: number;
|
|
50
|
+
reason: string;
|
|
51
|
+
};
|
|
52
|
+
/** A solution's scores, by axis (SCORES-1), as `dotreq scores create` makes them. */
|
|
53
|
+
export type Scores = {
|
|
54
|
+
costOfDelay: AxisScore;
|
|
55
|
+
relevance: AxisScore;
|
|
56
|
+
entities: AxisScore;
|
|
57
|
+
api: AxisScore;
|
|
58
|
+
testing: AxisScore;
|
|
59
|
+
experience: AxisScore;
|
|
60
|
+
doubt: AxisScore;
|
|
61
|
+
};
|
|
62
|
+
/** A thing as a drafter submits it: where it is, or scores by the id `createScores` gave. */
|
|
63
|
+
export type Submission = Exclude<Thing, {
|
|
64
|
+
kind: "scores";
|
|
65
|
+
}> | {
|
|
66
|
+
kind: "scores";
|
|
67
|
+
scoresId: string;
|
|
68
|
+
};
|
|
69
|
+
/** One outcome in a plan (`PlanOutcome` in packages/convex/solutions/plan/format.ts). */
|
|
70
|
+
export type PlanOutcome = {
|
|
71
|
+
name: string;
|
|
72
|
+
/** A surface's name, or another outcome's, as the scores are on the pitch. */
|
|
73
|
+
on: string;
|
|
74
|
+
awaits?: string[];
|
|
75
|
+
reviewAwaits?: string[];
|
|
76
|
+
against?: string[];
|
|
77
|
+
/** One of the plan's agents; left out, an agent dedicated to it: "<name>/drafter". */
|
|
78
|
+
drafter?: string;
|
|
79
|
+
/** The plan's agents; left out, one dedicated to it: "<name>/reviewer". Empty: no review. */
|
|
80
|
+
reviewers?: string[];
|
|
81
|
+
/** The agent the owner makes it with in a conversation. */
|
|
82
|
+
createdWith?: string;
|
|
83
|
+
/** Someone outside the product who makes it. */
|
|
84
|
+
createdBy?: string;
|
|
85
|
+
model?: string;
|
|
86
|
+
instructions?: string;
|
|
87
|
+
reviewInstructions?: string;
|
|
88
|
+
};
|
|
89
|
+
/** The plan in its stored shape (`OutcomePlan` in packages/convex/solutions/plan/format.ts). */
|
|
90
|
+
export type Plan = {
|
|
91
|
+
format: "outcomes";
|
|
92
|
+
inputs: string[];
|
|
93
|
+
surfaces: Array<{
|
|
94
|
+
name: string;
|
|
95
|
+
kind: string;
|
|
96
|
+
}>;
|
|
97
|
+
phases: Array<{
|
|
98
|
+
name: string;
|
|
99
|
+
class?: string;
|
|
100
|
+
outcomes: PlanOutcome[];
|
|
101
|
+
}>;
|
|
102
|
+
checkpoints: Array<{
|
|
103
|
+
name: string;
|
|
104
|
+
on: string;
|
|
105
|
+
presents?: string[];
|
|
106
|
+
}>;
|
|
107
|
+
agents: Array<{
|
|
108
|
+
name: string;
|
|
109
|
+
model?: string;
|
|
110
|
+
instructions?: string;
|
|
111
|
+
}>;
|
|
112
|
+
loops: Array<{
|
|
113
|
+
name: string;
|
|
114
|
+
iterations?: string[];
|
|
115
|
+
through: string[];
|
|
116
|
+
}>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Part of a plan to rehearse (REHEARSE-1.0, 1.6): some of its outcomes,
|
|
120
|
+
* each by its name, run as though the outcomes before them were made.
|
|
121
|
+
*/
|
|
122
|
+
export type PlanPart = {
|
|
123
|
+
from: Plan;
|
|
124
|
+
outcomes: string[];
|
|
125
|
+
};
|
|
126
|
+
/** What a script does when the agent it plays gets its brief. */
|
|
127
|
+
export type Script = {
|
|
128
|
+
/** Assert on the brief; throw to fail the rehearsal here (REHEARSE-2.1). */
|
|
129
|
+
expect?: (brief: unknown) => void;
|
|
130
|
+
/** Submit these things (drafting), with a comment saying what changed and why. */
|
|
131
|
+
made?: Submission[];
|
|
132
|
+
/** Make these scores and submit them (drafting scores), as `dotreq scores create` then `author scores:<id>` do, with the comment. */
|
|
133
|
+
scores?: Scores;
|
|
134
|
+
comment?: string;
|
|
135
|
+
/**
|
|
136
|
+
* With `made` or `scores`: the drafter's executive summary, which an
|
|
137
|
+
* outcome no agent reviews asks for (VERB-1.6). A script records as a
|
|
138
|
+
* real agent does (REHEARSE-1.1), so where the outcome asks for one and
|
|
139
|
+
* the script gives none, the work is refused.
|
|
140
|
+
*/
|
|
141
|
+
summary?: string;
|
|
142
|
+
/**
|
|
143
|
+
* Give this review result (reviewing), with the comment every result
|
|
144
|
+
* carries. An approval, with or without revisions, carries an executive
|
|
145
|
+
* summary (VERB-2.5), and needs revision and escalate carry none; a
|
|
146
|
+
* script that breaks either is refused, as the agent would be
|
|
147
|
+
* (REHEARSE-1.1).
|
|
148
|
+
*/
|
|
149
|
+
review?: {
|
|
150
|
+
outcome: "approved" | "approved with revisions" | "needs revision" | "escalate";
|
|
151
|
+
comment: string;
|
|
152
|
+
summary?: string;
|
|
153
|
+
};
|
|
154
|
+
/** Put a decision to the person instead (drafting). */
|
|
155
|
+
ask?: unknown;
|
|
156
|
+
/** Stall instead. */
|
|
157
|
+
stall?: string;
|
|
158
|
+
};
|
|
159
|
+
/** Real, or a script; a list plays one script per turn, the last repeating. */
|
|
160
|
+
export type Party = "real" | Script | Script[];
|
|
161
|
+
/**
|
|
162
|
+
* What the person answers, in order asked: by an outcome's name, her answer
|
|
163
|
+
* to a question or an escalation on it; by a checkpoint's name, her
|
|
164
|
+
* decision there, which a rehearsal gives only as an approval.
|
|
165
|
+
*/
|
|
166
|
+
export type PersonScript = Record<string, Array<{
|
|
167
|
+
kind: "approval";
|
|
168
|
+
outcome: "approved" | "needs revision";
|
|
169
|
+
comment?: string;
|
|
170
|
+
} | {
|
|
171
|
+
kind: "choice";
|
|
172
|
+
option: string;
|
|
173
|
+
because?: string;
|
|
174
|
+
}>>;
|
|
175
|
+
/**
|
|
176
|
+
* The history a rehearsal starts from (REHEARSE-4.8): an earlier
|
|
177
|
+
* rehearsal's solution, the outcome it made that the new solution starts
|
|
178
|
+
* after, and the outcomes it holds as they stood then.
|
|
179
|
+
*/
|
|
180
|
+
export type StartingHistory = {
|
|
181
|
+
solution: string;
|
|
182
|
+
after: string;
|
|
183
|
+
outcomes: string[];
|
|
184
|
+
};
|
|
185
|
+
/** A document published from a scenario's file for an input (REHEARSE-4.1). */
|
|
186
|
+
export type Published = {
|
|
187
|
+
documentId: string;
|
|
188
|
+
isRequirementsDoc: boolean;
|
|
189
|
+
};
|
|
190
|
+
export type Scenario = {
|
|
191
|
+
title: string;
|
|
192
|
+
/** Live only: the scenario file's name, recorded on the solution so the next run of it replaces this one (REHEARSE-6). */
|
|
193
|
+
file?: string;
|
|
194
|
+
/** What the person wrote about the solution beyond its title, as Markdown. */
|
|
195
|
+
description?: string;
|
|
196
|
+
/**
|
|
197
|
+
* The whole plan, or some of its outcomes run on their own (REHEARSE-1.0,
|
|
198
|
+
* 1.6).
|
|
199
|
+
*/
|
|
200
|
+
plan: Plan | PlanPart;
|
|
201
|
+
/** The artifacts the plan's inputs hold, by outcome name. */
|
|
202
|
+
inputs?: Record<string, Thing[]>;
|
|
203
|
+
/**
|
|
204
|
+
* Live only: the documents published from the scenario's files for its
|
|
205
|
+
* inputs, each with whether its file's name makes it a requirements
|
|
206
|
+
* document (SOLDOC-3). Each comes to belong to the solution and the input
|
|
207
|
+
* that names it (REHEARSE-4.1.0).
|
|
208
|
+
*/
|
|
209
|
+
published?: Published[];
|
|
210
|
+
/**
|
|
211
|
+
* Live only: the branch the solution's branch is made from, rather than
|
|
212
|
+
* the repository's default branch, such as one frozen with the output of
|
|
213
|
+
* the outcomes before the rehearsed ones (REHEARSE-4.5).
|
|
214
|
+
*/
|
|
215
|
+
branch?: string;
|
|
216
|
+
/**
|
|
217
|
+
* Live only: an earlier rehearsal's solution and an outcome it made,
|
|
218
|
+
* whose history the solution starts with (REHEARSE-4.8), with the
|
|
219
|
+
* outcomes that solution holds, which may stand for inputs the scenario
|
|
220
|
+
* doesn't name.
|
|
221
|
+
*/
|
|
222
|
+
history?: StartingHistory;
|
|
223
|
+
/**
|
|
224
|
+
* Who plays each agent (`partiesOf` in driver.ts): by agent, as
|
|
225
|
+
* `Code Reviewer` or `Pitch/drafter`; by an outcome's name, its drafter,
|
|
226
|
+
* or whoever outside makes it; by "<outcome>/reviewer", its reviewers; or
|
|
227
|
+
* by "<outcome>/<agent>", that agent on that outcome alone. Unnamed
|
|
228
|
+
* agents are real.
|
|
229
|
+
*/
|
|
230
|
+
parties: Record<string, Party>;
|
|
231
|
+
person?: PersonScript;
|
|
232
|
+
/** How long to wait for a real agent, in ms (live only). */
|
|
233
|
+
waitMs?: number;
|
|
234
|
+
};
|
|
235
|
+
/** An outcome on the plan panel, as the driver reads it (`getPlan`). */
|
|
236
|
+
export type PanelOutcome = {
|
|
237
|
+
name: string;
|
|
238
|
+
status: string;
|
|
239
|
+
drafter?: string;
|
|
240
|
+
reviewers?: string[];
|
|
241
|
+
reason?: string;
|
|
242
|
+
/** Who it waits on, when someone outside makes it. */
|
|
243
|
+
party?: string;
|
|
244
|
+
};
|
|
245
|
+
/** The plan panel as the driver reads it: its outcomes by phase, and where each checkpoint stands. */
|
|
246
|
+
export type RehearsalPanel = {
|
|
247
|
+
phases: Array<{
|
|
248
|
+
outcomes: PanelOutcome[];
|
|
249
|
+
}>;
|
|
250
|
+
checkpoints?: Array<{
|
|
251
|
+
name: string;
|
|
252
|
+
stands: string;
|
|
253
|
+
}>;
|
|
254
|
+
};
|
|
255
|
+
/** The client the driver drives: convex-test in tests, the CLI client live. */
|
|
256
|
+
export type RehearsalClient = {
|
|
257
|
+
create(args: {
|
|
258
|
+
title: string;
|
|
259
|
+
/** The scenario file's name, when the rehearsal runs from one. */
|
|
260
|
+
scenario?: string;
|
|
261
|
+
description?: string;
|
|
262
|
+
plan: Plan;
|
|
263
|
+
inputs: Array<{
|
|
264
|
+
name: string;
|
|
265
|
+
things: Thing[];
|
|
266
|
+
}>;
|
|
267
|
+
/** The branch the solution's branch is made from, when the scenario names one. */
|
|
268
|
+
branch?: string;
|
|
269
|
+
/** The documents published from the scenario's files for its inputs. */
|
|
270
|
+
published?: Published[];
|
|
271
|
+
/** The earlier rehearsal whose history the solution starts with, when the scenario names one. */
|
|
272
|
+
history?: {
|
|
273
|
+
solution: string;
|
|
274
|
+
after: string;
|
|
275
|
+
};
|
|
276
|
+
}): Promise<string>;
|
|
277
|
+
/** The plan panel as it stands (`getPlan`). */
|
|
278
|
+
panel(solutionId: string): Promise<RehearsalPanel | null>;
|
|
279
|
+
/** What an agent picks up: its brief for the first part of an outcome's work it has due, or nothing ready. */
|
|
280
|
+
next(args: {
|
|
281
|
+
solutionId: string;
|
|
282
|
+
agent: string;
|
|
283
|
+
}): Promise<{
|
|
284
|
+
kind: string;
|
|
285
|
+
[key: string]: unknown;
|
|
286
|
+
}>;
|
|
287
|
+
/** Make scores, as `dotreq scores create` does: their id, to submit as `{ kind: "scores", scoresId }`. */
|
|
288
|
+
createScores(scores: Scores): Promise<string>;
|
|
289
|
+
/** Record an agent's work or result on an outcome; with no agent, someone outside closing it. */
|
|
290
|
+
complete(args: {
|
|
291
|
+
solutionId: string;
|
|
292
|
+
agent?: string;
|
|
293
|
+
outcome: string;
|
|
294
|
+
made?: Submission[];
|
|
295
|
+
comment?: string;
|
|
296
|
+
/** With `made`: the drafter's executive summary (VERB-1.6). */
|
|
297
|
+
summary?: string;
|
|
298
|
+
review?: {
|
|
299
|
+
outcome: "approved" | "approved with revisions" | "needs revision" | "escalate";
|
|
300
|
+
comment: string;
|
|
301
|
+
/** With an approval: the executive summary (VERB-2.5). */
|
|
302
|
+
summary?: string;
|
|
303
|
+
};
|
|
304
|
+
}): Promise<void>;
|
|
305
|
+
ask(args: {
|
|
306
|
+
solutionId: string;
|
|
307
|
+
agent: string;
|
|
308
|
+
outcome: string;
|
|
309
|
+
request: unknown;
|
|
310
|
+
}): Promise<void>;
|
|
311
|
+
stall(args: {
|
|
312
|
+
solutionId: string;
|
|
313
|
+
agent: string;
|
|
314
|
+
outcome: string;
|
|
315
|
+
reason: string;
|
|
316
|
+
}): Promise<void>;
|
|
317
|
+
/** The decision open on an outcome — a question or an escalation — or null. Absent when the client can't answer for the person. */
|
|
318
|
+
openDecision?(solutionId: string, outcome: string): Promise<{
|
|
319
|
+
id: string;
|
|
320
|
+
} | null>;
|
|
321
|
+
answer?(decisionId: string, answer: unknown): Promise<void>;
|
|
322
|
+
/** Approve a checkpoint's pass waiting on the person. Absent when the client can't decide for the person. */
|
|
323
|
+
approveCheckpoint?(solutionId: string, checkpoint: string, words?: string): Promise<void>;
|
|
324
|
+
thread(solutionId: string, outcome: string): Promise<unknown[]>;
|
|
325
|
+
things(solutionId: string, outcome: string): Promise<Thing[]>;
|
|
326
|
+
/** Live only: what a real agent did, from its sessions' logs. */
|
|
327
|
+
agentLog?(solutionId: string, agent: string): Promise<string | null>;
|
|
328
|
+
/** Live only: wait between polls. */
|
|
329
|
+
sleep?(ms: number): Promise<void>;
|
|
330
|
+
};
|
|
331
|
+
export type OutcomeReport = {
|
|
332
|
+
outcome: string;
|
|
333
|
+
status: string;
|
|
334
|
+
reason?: string;
|
|
335
|
+
things: Thing[];
|
|
336
|
+
thread: unknown[];
|
|
337
|
+
/** What each real agent on it did, from its log, by agent. */
|
|
338
|
+
agentLogs?: Record<string, string | null>;
|
|
339
|
+
};
|
|
340
|
+
/** What a live rehearsal did with the earlier runs of its scenario before it started (REHEARSE-6). */
|
|
341
|
+
export type EarlierRuns = {
|
|
342
|
+
/** The scenario file's name. */
|
|
343
|
+
scenario: string;
|
|
344
|
+
/** How many earlier runs it removed. */
|
|
345
|
+
removed: number;
|
|
346
|
+
/** Rehearsed with --keep: the earlier runs were left in place. */
|
|
347
|
+
keep?: boolean;
|
|
348
|
+
/** What an earlier run made that stayed: named by these scenario files, or, with none, used by another solution. */
|
|
349
|
+
kept: Array<{
|
|
350
|
+
reference: string;
|
|
351
|
+
namedBy: string[];
|
|
352
|
+
}>;
|
|
353
|
+
/** Earlier runs that stayed because these scenario files start from their history (REHEARSE-6.2.0). */
|
|
354
|
+
keptRuns?: Array<{
|
|
355
|
+
solutionId: string;
|
|
356
|
+
namedBy: string[];
|
|
357
|
+
}>;
|
|
358
|
+
/**
|
|
359
|
+
* The branches the earlier runs' solutions made (REHEARSE-6.7 to 6.10):
|
|
360
|
+
* deleted, already gone, kept and why, or still being deleted when the
|
|
361
|
+
* new run started.
|
|
362
|
+
*/
|
|
363
|
+
branches?: Array<{
|
|
364
|
+
name: string;
|
|
365
|
+
outcome: "deleted" | "gone" | "kept" | "pending";
|
|
366
|
+
why?: string;
|
|
367
|
+
}>;
|
|
368
|
+
};
|
|
369
|
+
export type RehearsalReport = {
|
|
370
|
+
solutionId: string;
|
|
371
|
+
/** Live only: the earlier runs of its scenario, and what of theirs stayed. */
|
|
372
|
+
earlier?: EarlierRuns;
|
|
373
|
+
/** Why it ended: nothing ready, a decision nobody scripted, a stall, or a script's expectation. */
|
|
374
|
+
ended: string;
|
|
375
|
+
outcomes: OutcomeReport[];
|
|
376
|
+
};
|
|
377
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rehearsal (docs/working/rehearsing-steps.md): a plan of outcomes, the
|
|
3
|
+
* artifacts its inputs hold, and who plays each agent the backend sends
|
|
4
|
+
* for — a real one, or a script that plays it from the brief the agent
|
|
5
|
+
* would get.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -26,6 +26,12 @@ export interface ParsedRequirementsFile {
|
|
|
26
26
|
* Excludes example files, test fixtures, and build artifacts.
|
|
27
27
|
*/
|
|
28
28
|
export declare function findRequirementsFiles(workspaceRoot: string): Promise<string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Every file a sync carries (SOLDOC-8): requirements files anywhere, plus
|
|
31
|
+
* the Markdown files directly inside solution directories. Other Markdown
|
|
32
|
+
* is left alone.
|
|
33
|
+
*/
|
|
34
|
+
export declare function findSyncedFiles(workspaceRoot: string): Promise<string[]>;
|
|
29
35
|
/**
|
|
30
36
|
* Synchronous variant of {@link findRequirementsFiles}. Used by code paths
|
|
31
37
|
* that can't await (e.g. the test-harness lookup-cache builder).
|
|
@@ -6,6 +6,8 @@ import { splitLeadingH1 } from "../schema/title-markdown.js";
|
|
|
6
6
|
* Glob pattern matching *.requirements.md files.
|
|
7
7
|
*/
|
|
8
8
|
const REQUIREMENTS_FILE_PATTERN = "**/*.requirements.md";
|
|
9
|
+
/** SOLDOC-8.1: a solution's other documents, directly inside a solution directory. */
|
|
10
|
+
const SOLUTION_DOCUMENT_PATTERN = "**/.requirements/solutions/*/*.md";
|
|
9
11
|
/**
|
|
10
12
|
* Directories ignored when discovering requirements files.
|
|
11
13
|
* Shared between async and sync discovery so the two never drift.
|
|
@@ -15,6 +17,9 @@ const REQUIREMENTS_IGNORE_PATTERNS = [
|
|
|
15
17
|
"**/dist/**",
|
|
16
18
|
"**/.git/**",
|
|
17
19
|
"**/build/**",
|
|
20
|
+
// Next.js's build output: a dev server's grows to gigabytes, and walking
|
|
21
|
+
// it made discovery take most of a minute.
|
|
22
|
+
"**/.next/**",
|
|
18
23
|
// Exclude example and test fixture directories
|
|
19
24
|
"**/example/**",
|
|
20
25
|
"**/examples/**",
|
|
@@ -40,6 +45,25 @@ export async function findRequirementsFiles(workspaceRoot) {
|
|
|
40
45
|
});
|
|
41
46
|
return matches.map((m) => path.join(workspaceRoot, m));
|
|
42
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Every file a sync carries (SOLDOC-8): requirements files anywhere, plus
|
|
50
|
+
* the Markdown files directly inside solution directories. Other Markdown
|
|
51
|
+
* is left alone.
|
|
52
|
+
*/
|
|
53
|
+
export async function findSyncedFiles(workspaceRoot) {
|
|
54
|
+
const [requirements, solutionDocs] = await Promise.all([
|
|
55
|
+
findRequirementsFiles(workspaceRoot),
|
|
56
|
+
glob(SOLUTION_DOCUMENT_PATTERN, {
|
|
57
|
+
cwd: workspaceRoot,
|
|
58
|
+
ignore: REQUIREMENTS_IGNORE_PATTERNS,
|
|
59
|
+
dot: true,
|
|
60
|
+
}),
|
|
61
|
+
]);
|
|
62
|
+
const all = new Set(requirements);
|
|
63
|
+
for (const m of solutionDocs)
|
|
64
|
+
all.add(path.join(workspaceRoot, m));
|
|
65
|
+
return [...all];
|
|
66
|
+
}
|
|
43
67
|
/**
|
|
44
68
|
* Synchronous variant of {@link findRequirementsFiles}. Used by code paths
|
|
45
69
|
* that can't await (e.g. the test-harness lookup-cache builder).
|
package/dist/schema/browser.d.ts
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
export { buildRequirementMarkdown, buildRequirementsMarkdown, DEFAULT_DELIMITER, } from "./builder.js";
|
|
7
7
|
export type { ConvexRequirement } from "./conversions.js";
|
|
8
8
|
export { buildMetadata, constructKey, convexToRequirements, extractRequirementKeys, groupByRoot, parseKey, requirementsToConvex, } from "./conversions.js";
|
|
9
|
-
export { DELIMITER_PATTERN, type ExtractedRequirementBlock, extractRequirementBlocks, findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementBlocksFromMarkdown, parseRootLine, ROOT_LABEL_MARKER, splitRequirementFenceContent, } from "./parser-core.js";
|
|
9
|
+
export { DELIMITER_PATTERN, type ExtractedRequirementBlock, extractRequirementBlocks, findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementBlocksFromMarkdown, parseRootLine, ROOT_LABEL_MARKER, splitRequirementFenceContent, stripFrontmatterBlock, } from "./parser-core.js";
|
|
10
|
+
export { carriesBranchVersion } from "./provenance.js";
|
|
10
11
|
export type { Metadata, ParsedCriterion, RequirementKey, RequirementNode, RequirementPrefix, RequirementsFile, } from "./schemas.js";
|
|
11
12
|
export { buildRequirementKey, canonicalRequirementKey, MetadataSchema, normalizePrefix, ParsedCriterionSchema, parseRequirementKey, REQUIREMENT_KEY_PATTERN, REQUIREMENT_PREFIX_PATTERN, RequirementKeySchema, RequirementNodeSchema, RequirementPrefixSchema, RequirementsFileSchema, ValidationError, validateKey, validateMetadata, validatePrefix, validateRequirementNode, validateRequirementsFile, } from "./schemas.js";
|
|
12
13
|
export { composeMarkdownWithTitle, effectiveTitle, type SplitMarkdown, splitLeadingH1, } from "./title-markdown.js";
|
package/dist/schema/browser.js
CHANGED
|
@@ -11,7 +11,12 @@ export { buildMetadata, constructKey, convexToRequirements, extractRequirementKe
|
|
|
11
11
|
export { DELIMITER_PATTERN, extractRequirementBlocks, findRequirementById, flattenRequirementTree, getAllRequirements, parseCriterionLine, parseRequirementBlock, parseRequirementBlocksFromMarkdown, parseRootLine,
|
|
12
12
|
// The web reaches parser-core only through this entry point, so without this
|
|
13
13
|
// its readers have no way to import the marker and must hard-code it.
|
|
14
|
-
ROOT_LABEL_MARKER, splitRequirementFenceContent,
|
|
14
|
+
ROOT_LABEL_MARKER, splitRequirementFenceContent,
|
|
15
|
+
// A requirements file read from a repository in the browser (SOLDOC-12).
|
|
16
|
+
stripFrontmatterBlock, } from "./parser-core.js";
|
|
17
|
+
// Whether a publish that says it lands a branch version matches it
|
|
18
|
+
// (BRANCH-7.11), checked by the web app's merge and by the backend alike
|
|
19
|
+
export { carriesBranchVersion } from "./provenance.js";
|
|
15
20
|
// Schemas and types (uses zod - browser-safe)
|
|
16
21
|
export { buildRequirementKey, canonicalRequirementKey,
|
|
17
22
|
// Zod schemas
|
|
@@ -60,6 +60,11 @@ export interface OwnedFrontmatter {
|
|
|
60
60
|
attachments?: AttachmentsDirective;
|
|
61
61
|
/** The cloud version this content is at. */
|
|
62
62
|
version: number;
|
|
63
|
+
/** SOLDOC-5: the belonging to write; absent means keep what the file says. */
|
|
64
|
+
belonging?: {
|
|
65
|
+
solutionId: string;
|
|
66
|
+
outcome: string;
|
|
67
|
+
};
|
|
63
68
|
}
|
|
64
69
|
/**
|
|
65
70
|
* Write `body` to `filePath` under the file's own frontmatter, with the owned
|
|
@@ -50,6 +50,10 @@ export function writeRequirementsFile(filePath, owned, body) {
|
|
|
50
50
|
frontmatter.setIn(["document", "attachments"],
|
|
51
51
|
// Omit absent titles rather than writing `title: null` into the file.
|
|
52
52
|
attachments.set.map((a) => a.title === undefined ? { url: a.url } : { url: a.url, title: a.title }));
|
|
53
|
+
if (owned.belonging) {
|
|
54
|
+
frontmatter.setIn(["document", "solution"], owned.belonging.solutionId);
|
|
55
|
+
frontmatter.setIn(["document", "outcome"], owned.belonging.outcome);
|
|
56
|
+
}
|
|
53
57
|
// SYNC-TITLE-1.2: `document.title` is a recognized-but-retired field — the
|
|
54
58
|
// title lives in the body as its leading H1 — so a rewrite drops it rather
|
|
55
59
|
// than carrying it forward as if it were one of the user's own fields.
|
package/dist/schema/parser.d.ts
CHANGED
|
@@ -13,7 +13,14 @@ export { findRequirementById, flattenRequirementTree, getAllRequirements, parseC
|
|
|
13
13
|
/**
|
|
14
14
|
* Parse a complete requirements Markdown file.
|
|
15
15
|
*/
|
|
16
|
-
export declare function parseRequirementsFile(markdownContent: string
|
|
16
|
+
export declare function parseRequirementsFile(markdownContent: string, options?: {
|
|
17
|
+
/**
|
|
18
|
+
* SOLDOC-3/4: a solution's other document (a pitch) carries no
|
|
19
|
+
* requirement blocks, and may carry no frontmatter yet, and is still a
|
|
20
|
+
* document.
|
|
21
|
+
*/
|
|
22
|
+
solutionDocument?: boolean;
|
|
23
|
+
}): {
|
|
17
24
|
metadata: RequirementsFile["_meta"];
|
|
18
25
|
requirements: RequirementNode[];
|
|
19
26
|
/** The markdown body (frontmatter stripped) — its leading H1 is the document's title (SYNC-TITLE-1). */
|
|
@@ -22,7 +29,9 @@ export declare function parseRequirementsFile(markdownContent: string): {
|
|
|
22
29
|
/**
|
|
23
30
|
* Parse requirements file from disk.
|
|
24
31
|
*/
|
|
25
|
-
export declare function parseRequirementsFromFile(filePath: string
|
|
32
|
+
export declare function parseRequirementsFromFile(filePath: string, options?: {
|
|
33
|
+
solutionDocument?: boolean;
|
|
34
|
+
}): {
|
|
26
35
|
metadata: RequirementsFile["_meta"];
|
|
27
36
|
requirements: RequirementNode[];
|
|
28
37
|
body: string;
|
package/dist/schema/parser.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
import YAML from "yaml";
|
|
12
|
-
import { parseRequirementBlocksFromMarkdown, splitFrontmatter, } from "./parser-core.js";
|
|
12
|
+
import { parseRequirementBlocksFromMarkdown, splitFrontmatter, stripFrontmatterBlock, } from "./parser-core.js";
|
|
13
13
|
import { ValidationError, validateMetadata, } from "./schemas.js";
|
|
14
14
|
// Block/criterion parsing and tree utilities live in parser-core; re-exported
|
|
15
15
|
// here so the schema module's public surface is unchanged.
|
|
@@ -18,11 +18,15 @@ export { findRequirementById, flattenRequirementTree, getAllRequirements, parseC
|
|
|
18
18
|
* Extract YAML frontmatter from Markdown content.
|
|
19
19
|
* Returns { frontmatter, body } where frontmatter is the parsed YAML object.
|
|
20
20
|
*/
|
|
21
|
-
function extractFrontmatter(content) {
|
|
21
|
+
function extractFrontmatter(content, optional = false) {
|
|
22
22
|
// Single fence match: yaml and body come from the same split, so they can
|
|
23
23
|
// never disagree about where the frontmatter closes.
|
|
24
24
|
const split = splitFrontmatter(content);
|
|
25
25
|
if (split === undefined) {
|
|
26
|
+
// SOLDOC-4.0: a solution's document written by hand has no frontmatter
|
|
27
|
+
// yet; the push writes it after the first sync.
|
|
28
|
+
if (optional)
|
|
29
|
+
return { frontmatter: {}, body: stripFrontmatterBlock(content) };
|
|
26
30
|
throw new ValidationError("Missing YAML frontmatter (should start with ---)");
|
|
27
31
|
}
|
|
28
32
|
let frontmatter;
|
|
@@ -37,14 +41,14 @@ function extractFrontmatter(content) {
|
|
|
37
41
|
/**
|
|
38
42
|
* Parse a complete requirements Markdown file.
|
|
39
43
|
*/
|
|
40
|
-
export function parseRequirementsFile(markdownContent) {
|
|
44
|
+
export function parseRequirementsFile(markdownContent, options = {}) {
|
|
41
45
|
// CRLF normalization (SYNC-FORMAT-1) happens inside the shared parser-core
|
|
42
46
|
// helpers (splitFrontmatter / parseRequirementBlocksFromMarkdown), so every
|
|
43
47
|
// entry point agrees.
|
|
44
|
-
const { frontmatter, body } = extractFrontmatter(markdownContent);
|
|
48
|
+
const { frontmatter, body } = extractFrontmatter(markdownContent, options.solutionDocument);
|
|
45
49
|
const metadata = validateMetadata(frontmatter);
|
|
46
50
|
const requirements = parseRequirementBlocksFromMarkdown(body);
|
|
47
|
-
if (requirements.length === 0) {
|
|
51
|
+
if (requirements.length === 0 && !options.solutionDocument) {
|
|
48
52
|
throw new ValidationError("No requirement blocks found in document");
|
|
49
53
|
}
|
|
50
54
|
return { metadata, requirements, body };
|
|
@@ -52,10 +56,10 @@ export function parseRequirementsFile(markdownContent) {
|
|
|
52
56
|
/**
|
|
53
57
|
* Parse requirements file from disk.
|
|
54
58
|
*/
|
|
55
|
-
export function parseRequirementsFromFile(filePath) {
|
|
59
|
+
export function parseRequirementsFromFile(filePath, options = {}) {
|
|
56
60
|
try {
|
|
57
61
|
const content = fs.readFileSync(filePath, "utf-8");
|
|
58
|
-
return parseRequirementsFile(content);
|
|
62
|
+
return parseRequirementsFile(content, options);
|
|
59
63
|
}
|
|
60
64
|
catch (error) {
|
|
61
65
|
if (error instanceof ValidationError) {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a publish that says it lands a branch version matches that version
|
|
3
|
+
* (BRANCH-7.11): its title, its default prefix, and each of its requirements,
|
|
4
|
+
* key and wording, in the same tree and order. Pure and browser-safe, so the web
|
|
5
|
+
* app's merge checks every document before landing any, and the backend
|
|
6
|
+
* checks each publish, by the same rule.
|
|
7
|
+
*
|
|
8
|
+
* The merge publishes each version as the app's editor stores it, so the
|
|
9
|
+
* comparison is of what the editor keeps, not of the text:
|
|
10
|
+
* - a criterion's position is its place in the tree, since the editor
|
|
11
|
+
* numbers criteria from 0 in order, and a label is compared without case,
|
|
12
|
+
* since it writes a Gherkin keyword as `Given` however it was written;
|
|
13
|
+
* - the title is the leading heading however it is written, `#` or
|
|
14
|
+
* underlined, falling back to the version's own title as the merge does;
|
|
15
|
+
* - the writing between requirements isn't compared at all (7.11.0): the
|
|
16
|
+
* editor lays lists and tables out its own way and drops what it doesn't
|
|
17
|
+
* keep, such as an HTML comment (BRANCH-2.2).
|
|
18
|
+
*/
|
|
19
|
+
export declare function carriesBranchVersion(published: {
|
|
20
|
+
markdownContent: string;
|
|
21
|
+
defaultPrefix?: string;
|
|
22
|
+
}, version: {
|
|
23
|
+
markdownContent: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
defaultPrefix?: string;
|
|
26
|
+
}): boolean;
|
|
27
|
+
//# sourceMappingURL=provenance.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { parseRequirementBlocksFromMarkdown } from "./parser-core.js";
|
|
2
|
+
import { splitLeadingH1 } from "./title-markdown.js";
|
|
3
|
+
/**
|
|
4
|
+
* Whether a publish that says it lands a branch version matches that version
|
|
5
|
+
* (BRANCH-7.11): its title, its default prefix, and each of its requirements,
|
|
6
|
+
* key and wording, in the same tree and order. Pure and browser-safe, so the web
|
|
7
|
+
* app's merge checks every document before landing any, and the backend
|
|
8
|
+
* checks each publish, by the same rule.
|
|
9
|
+
*
|
|
10
|
+
* The merge publishes each version as the app's editor stores it, so the
|
|
11
|
+
* comparison is of what the editor keeps, not of the text:
|
|
12
|
+
* - a criterion's position is its place in the tree, since the editor
|
|
13
|
+
* numbers criteria from 0 in order, and a label is compared without case,
|
|
14
|
+
* since it writes a Gherkin keyword as `Given` however it was written;
|
|
15
|
+
* - the title is the leading heading however it is written, `#` or
|
|
16
|
+
* underlined, falling back to the version's own title as the merge does;
|
|
17
|
+
* - the writing between requirements isn't compared at all (7.11.0): the
|
|
18
|
+
* editor lays lists and tables out its own way and drops what it doesn't
|
|
19
|
+
* keep, such as an HTML comment (BRANCH-2.2).
|
|
20
|
+
*/
|
|
21
|
+
export function carriesBranchVersion(published, version) {
|
|
22
|
+
const theirs = requirementsOf(published.markdownContent);
|
|
23
|
+
const ours = requirementsOf(version.markdownContent);
|
|
24
|
+
return (theirs !== null &&
|
|
25
|
+
ours !== null &&
|
|
26
|
+
theirs.length === ours.length &&
|
|
27
|
+
theirs.every((each, i) => each === ours[i]) &&
|
|
28
|
+
(titleOf(published.markdownContent) ?? "") ===
|
|
29
|
+
(titleOf(version.markdownContent) ?? version.title ?? "") &&
|
|
30
|
+
(published.defaultPrefix ?? "") === (version.defaultPrefix ?? ""));
|
|
31
|
+
}
|
|
32
|
+
/** Each requirement as the editor keeps it, in order; null when a block doesn't parse. */
|
|
33
|
+
function requirementsOf(markdown) {
|
|
34
|
+
let trees;
|
|
35
|
+
try {
|
|
36
|
+
trees = parseRequirementBlocksFromMarkdown(markdown);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const out = [];
|
|
42
|
+
const walk = (node, path) => {
|
|
43
|
+
out.push([path, node.label.trim().toLowerCase(), squash(node.content)].join("\u0000"));
|
|
44
|
+
node.children.forEach((child, index) => {
|
|
45
|
+
walk(child, `${path}.${index}`);
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
for (const tree of trees)
|
|
49
|
+
walk(tree, tree.id.split(".")[0]);
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function squash(text) {
|
|
53
|
+
return text.replace(/\s+/g, " ").trim();
|
|
54
|
+
}
|
|
55
|
+
/** The leading heading's text, `#` or underlined with `=`; undefined when there is none. */
|
|
56
|
+
function titleOf(markdown) {
|
|
57
|
+
const atx = splitLeadingH1(markdown).title;
|
|
58
|
+
if (atx != null)
|
|
59
|
+
return squash(atx);
|
|
60
|
+
const lines = markdown.replace(/^\s*\n/, "").split("\n");
|
|
61
|
+
if (lines.length >= 2 && lines[0].trim() && /^=+\s*$/.test(lines[1])) {
|
|
62
|
+
return squash(lines[0]);
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=provenance.js.map
|