@clemrig/factory 0.18.3 → 0.20.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 +25 -23
- package/dist/app/board.js +1 -0
- package/dist/app/board.js.map +1 -1
- package/dist/app/factory.d.ts +2 -0
- package/dist/app/factory.js +5 -1
- package/dist/app/factory.js.map +1 -1
- package/dist/app/review.d.ts +16 -0
- package/dist/app/review.js +87 -0
- package/dist/app/review.js.map +1 -0
- package/dist/app/spec-page.d.ts +11 -0
- package/dist/app/spec-page.js +37 -0
- package/dist/app/spec-page.js.map +1 -0
- package/dist/app/workflows/implement.js +3 -7
- package/dist/app/workflows/implement.js.map +1 -1
- package/dist/app/workflows/issue-save.d.ts +4 -1
- package/dist/app/workflows/issue-save.js +35 -4
- package/dist/app/workflows/issue-save.js.map +1 -1
- package/dist/app/workflows/stages/deliver.d.ts +5 -4
- package/dist/app/workflows/stages/deliver.js +47 -53
- package/dist/app/workflows/stages/deliver.js.map +1 -1
- package/dist/app/workflows/stages/prepare.js +11 -7
- package/dist/app/workflows/stages/prepare.js.map +1 -1
- package/dist/app/workflows/stages/resume.js +0 -4
- package/dist/app/workflows/stages/resume.js.map +1 -1
- package/dist/app/workflows/stages/run.d.ts +1 -2
- package/dist/app/workflows/tidy.js +2 -3
- package/dist/app/workflows/tidy.js.map +1 -1
- package/dist/cli/ui.d.ts +5 -2
- package/dist/cli/ui.js +24 -5
- package/dist/cli/ui.js.map +1 -1
- package/dist/domain/board.d.ts +6 -0
- package/dist/domain/board.js +5 -1
- package/dist/domain/board.js.map +1 -1
- package/dist/domain/description.d.ts +57 -5
- package/dist/domain/description.js +133 -12
- package/dist/domain/description.js.map +1 -1
- package/dist/domain/diff.d.ts +8 -0
- package/dist/domain/diff.js +90 -0
- package/dist/domain/diff.js.map +1 -0
- package/dist/domain/pull-request.d.ts +9 -21
- package/dist/domain/pull-request.js +43 -228
- package/dist/domain/pull-request.js.map +1 -1
- package/dist/domain/review-page.d.ts +171 -0
- package/dist/domain/review-page.js +200 -0
- package/dist/domain/review-page.js.map +1 -0
- package/dist/domain/spec-page.d.ts +132 -0
- package/dist/domain/spec-page.js +155 -0
- package/dist/domain/spec-page.js.map +1 -0
- package/dist/system/environment.d.ts +6 -0
- package/dist/system/environment.js +19 -0
- package/dist/system/environment.js.map +1 -1
- package/dist/system/factory.d.ts +2 -0
- package/dist/system/factory.js +4 -0
- package/dist/system/factory.js.map +1 -1
- package/dist/system/git.d.ts +5 -1
- package/dist/system/git.js +19 -2
- package/dist/system/git.js.map +1 -1
- package/dist/system/github.d.ts +3 -12
- package/dist/system/github.js +7 -31
- package/dist/system/github.js.map +1 -1
- package/dist/system/issues.d.ts +10 -0
- package/dist/system/issues.js +57 -1
- package/dist/system/issues.js.map +1 -1
- package/dist/system/run-files.d.ts +14 -0
- package/dist/system/run-files.js +51 -8
- package/dist/system/run-files.js.map +1 -1
- package/package.json +2 -2
- package/prompts/describe.md +36 -15
- package/templates/init/gitignore +1 -0
- package/templates/skills/issue/SKILL.md +49 -7
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { z } from "@clemrig/flow";
|
|
2
|
+
import { diffExcerpt } from "./diff.js";
|
|
3
|
+
import { isBlocking, } from "./review.js";
|
|
4
|
+
const finding = ({ nature, file, summary, }) => ({
|
|
5
|
+
nature,
|
|
6
|
+
blocking: isBlocking(nature),
|
|
7
|
+
...(file ? { file } : {}),
|
|
8
|
+
summary,
|
|
9
|
+
});
|
|
10
|
+
const count = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
|
|
11
|
+
/** The decisions on what the review left: its non-blocking findings, and what the operator delivered open. */
|
|
12
|
+
function reviewDecisions(facts, criteria) {
|
|
13
|
+
const { review, acceptedReview } = facts;
|
|
14
|
+
const nonBlocking = review.findings.filter(({ nature }) => !isBlocking(nature));
|
|
15
|
+
const unmet = acceptedReview
|
|
16
|
+
? criteria.filter(({ status }) => status === "not_met")
|
|
17
|
+
: [];
|
|
18
|
+
const blocking = acceptedReview
|
|
19
|
+
? review.findings.filter(({ nature }) => isBlocking(nature))
|
|
20
|
+
: [];
|
|
21
|
+
return [
|
|
22
|
+
...(unmet.length + blocking.length > 0
|
|
23
|
+
? [
|
|
24
|
+
{
|
|
25
|
+
id: "open",
|
|
26
|
+
kind: "open",
|
|
27
|
+
title: `Delivered by the operator with ${[
|
|
28
|
+
...(unmet.length > 0
|
|
29
|
+
? [count(unmet.length, "unmet criterion", "unmet criteria")]
|
|
30
|
+
: []),
|
|
31
|
+
...(blocking.length > 0
|
|
32
|
+
? [count(blocking.length, "blocking finding")]
|
|
33
|
+
: []),
|
|
34
|
+
].join(" and ")}`,
|
|
35
|
+
advice: "revise",
|
|
36
|
+
recommendation: "The review did not approve them: have them fixed, or merge knowing they stay open.",
|
|
37
|
+
why: "The run was resumed to deliver the change as its last review left it.",
|
|
38
|
+
findings: blocking.map(finding),
|
|
39
|
+
unmet,
|
|
40
|
+
},
|
|
41
|
+
]
|
|
42
|
+
: []),
|
|
43
|
+
...(nonBlocking.length > 0
|
|
44
|
+
? [
|
|
45
|
+
{
|
|
46
|
+
id: "non-blocking",
|
|
47
|
+
kind: "non_blocking",
|
|
48
|
+
title: `${count(nonBlocking.length, "non-blocking finding")} left by the review`,
|
|
49
|
+
advice: "accept",
|
|
50
|
+
recommendation: "The review approved the change without them: merge, and note them for later.",
|
|
51
|
+
why: "None blocks the change; whether they go with it, or come later, is yours to decide.",
|
|
52
|
+
findings: nonBlocking.map(finding),
|
|
53
|
+
},
|
|
54
|
+
]
|
|
55
|
+
: []),
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
/** The page's data, from the run that delivered the change. */
|
|
59
|
+
export function reviewPage(facts) {
|
|
60
|
+
const { description, review, plan, implementation } = facts;
|
|
61
|
+
const judged = new Map(review.criteria.map((c) => [c.id, c]));
|
|
62
|
+
const criteria = facts.criteria.map(({ id, text }) => ({
|
|
63
|
+
id,
|
|
64
|
+
text,
|
|
65
|
+
status: judged.get(id)?.status ?? "not_met",
|
|
66
|
+
evidence: judged.get(id)?.evidence ?? "",
|
|
67
|
+
}));
|
|
68
|
+
const byPath = new Map(facts.files.map((file) => [file.path, file]));
|
|
69
|
+
const shown = (path) => {
|
|
70
|
+
const file = byPath.get(path);
|
|
71
|
+
return file ? [{ ...file, url: facts.fileUrl(path) }] : [];
|
|
72
|
+
};
|
|
73
|
+
const grouped = new Set(description.guide.groups.flatMap(({ files }) => files));
|
|
74
|
+
const others = facts.files.filter(({ path }) => !grouped.has(path));
|
|
75
|
+
const screenshots = description.screenshots.map(({ file, caption }) => ({
|
|
76
|
+
file,
|
|
77
|
+
caption,
|
|
78
|
+
url: facts.screenshotUrl(file),
|
|
79
|
+
}));
|
|
80
|
+
const interpretations = plan.interpretations ?? [];
|
|
81
|
+
// The interpretations and deviations a decision shows, by position.
|
|
82
|
+
const used = {
|
|
83
|
+
interpretation: new Set(),
|
|
84
|
+
deviation: new Set(),
|
|
85
|
+
};
|
|
86
|
+
const sourceOf = (id) => {
|
|
87
|
+
if (id === undefined)
|
|
88
|
+
return undefined;
|
|
89
|
+
const kind = id.startsWith("I") ? "interpretation" : "deviation";
|
|
90
|
+
const position = Number(id.slice(1)) - 1;
|
|
91
|
+
const text = (kind === "interpretation" ? interpretations : implementation.deviations)[position];
|
|
92
|
+
if (text === undefined)
|
|
93
|
+
return undefined;
|
|
94
|
+
used[kind].add(position);
|
|
95
|
+
return { kind, text };
|
|
96
|
+
};
|
|
97
|
+
const decisions = (description.decisions ?? []).map((decision, index) => {
|
|
98
|
+
const { visual } = decision;
|
|
99
|
+
const source = sourceOf(decision.source);
|
|
100
|
+
const excerpt = visual?.kind === "diff" && visual.file && visual.from && visual.to
|
|
101
|
+
? diffExcerpt(facts.diff, visual.file, visual.from, visual.to)
|
|
102
|
+
: undefined;
|
|
103
|
+
const drawn = visual?.kind === "reading" && visual.spec && visual.read
|
|
104
|
+
? { kind: "reading", spec: visual.spec, read: visual.read }
|
|
105
|
+
: visual?.kind === "diff" && visual.file && excerpt
|
|
106
|
+
? { kind: "diff", file: visual.file, content: excerpt }
|
|
107
|
+
: visual?.kind === "screenshots" && visual.files
|
|
108
|
+
? {
|
|
109
|
+
kind: "screenshots",
|
|
110
|
+
items: screenshots.filter(({ file }) => visual.files?.includes(file)),
|
|
111
|
+
}
|
|
112
|
+
: visual?.kind === "list" && visual.items
|
|
113
|
+
? { kind: "list", items: visual.items }
|
|
114
|
+
: undefined;
|
|
115
|
+
return {
|
|
116
|
+
id: `decision-${index + 1}`,
|
|
117
|
+
kind: decision.kind,
|
|
118
|
+
title: decision.title,
|
|
119
|
+
...(decision.criterion ? { criterion: decision.criterion } : {}),
|
|
120
|
+
advice: decision.advice,
|
|
121
|
+
recommendation: decision.recommendation,
|
|
122
|
+
why: decision.why,
|
|
123
|
+
...(source ? { source } : {}),
|
|
124
|
+
...(decision.file
|
|
125
|
+
? { file: { path: decision.file, url: facts.fileUrl(decision.file) } }
|
|
126
|
+
: {}),
|
|
127
|
+
...(drawn ? { visual: drawn } : {}),
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
const reviews = facts.reviews ?? [review];
|
|
131
|
+
return {
|
|
132
|
+
run: facts.run,
|
|
133
|
+
title: facts.title,
|
|
134
|
+
objective: facts.objective,
|
|
135
|
+
pullRequest: {
|
|
136
|
+
url: facts.pullRequest,
|
|
137
|
+
number: Number(/\/pull\/(\d+)/.exec(facts.pullRequest)?.[1] ?? 0),
|
|
138
|
+
},
|
|
139
|
+
links: facts.links,
|
|
140
|
+
danger: description.danger,
|
|
141
|
+
changes: description.changes,
|
|
142
|
+
visuals: description.visuals,
|
|
143
|
+
screenshots,
|
|
144
|
+
...(description.noScreenshots
|
|
145
|
+
? { noScreenshots: description.noScreenshots }
|
|
146
|
+
: {}),
|
|
147
|
+
guide: {
|
|
148
|
+
start: {
|
|
149
|
+
...description.guide.start,
|
|
150
|
+
url: facts.fileUrl(description.guide.start.file),
|
|
151
|
+
},
|
|
152
|
+
groups: [
|
|
153
|
+
...description.guide.groups.map(({ title, files }) => ({
|
|
154
|
+
title,
|
|
155
|
+
files: files.flatMap(shown),
|
|
156
|
+
})),
|
|
157
|
+
...(others.length > 0
|
|
158
|
+
? [
|
|
159
|
+
{
|
|
160
|
+
title: description.guide.groups.length > 0 ? "Other files" : "Files",
|
|
161
|
+
files: others.flatMap(({ path }) => shown(path)),
|
|
162
|
+
},
|
|
163
|
+
]
|
|
164
|
+
: []),
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
rounds: reviews.map(({ criteria: judgedCriteria, findings, resolved = [] }) => ({
|
|
168
|
+
met: judgedCriteria.filter(({ status }) => status === "met").length,
|
|
169
|
+
total: facts.criteria.length,
|
|
170
|
+
blocking: findings.filter(({ nature }) => isBlocking(nature)).length,
|
|
171
|
+
nonBlocking: findings.filter(({ nature }) => !isBlocking(nature))
|
|
172
|
+
.length,
|
|
173
|
+
resolved,
|
|
174
|
+
})),
|
|
175
|
+
criteria,
|
|
176
|
+
checks: facts.checks.map(({ name, durationMs }) => ({ name, durationMs })),
|
|
177
|
+
skippedChecks: facts.skippedChecks,
|
|
178
|
+
decisions: [...decisions, ...reviewDecisions(facts, criteria)],
|
|
179
|
+
manualChecks: (description.manualChecks ?? []).map((check, index) => ({
|
|
180
|
+
id: `check-${index + 1}`,
|
|
181
|
+
...check,
|
|
182
|
+
})),
|
|
183
|
+
assumptions: plan.risks,
|
|
184
|
+
otherInterpretations: interpretations.filter((_, index) => !used.interpretation.has(index)),
|
|
185
|
+
otherDeviations: implementation.deviations.filter((_, index) => !used.deviation.has(index)),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const answer = z.enum(["ok", "no", "skip"]);
|
|
189
|
+
/** A card's id, as the page and this module give them. */
|
|
190
|
+
const cardId = z.string().regex(/^[a-z][a-z0-9-]{0,63}$/);
|
|
191
|
+
/** Where a person is in a run's review, as the page sends it: kept with the run. */
|
|
192
|
+
export const reviewAnswers = z.strictObject({
|
|
193
|
+
answers: z.record(cardId, answer),
|
|
194
|
+
notes: z.record(cardId, z.string().max(4000)),
|
|
195
|
+
seen: z.array(cardId).max(500),
|
|
196
|
+
position: z.number().int().min(0).max(500),
|
|
197
|
+
startedAt: z.number().int().min(0).nullable(),
|
|
198
|
+
endedAt: z.number().int().min(0).nullable(),
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=review-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-page.js","sourceRoot":"","sources":["../../src/domain/review-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { z } from "@clemrig/flow";
|
|
2
|
+
import type { Parsed } from "./parsed.js";
|
|
3
|
+
import { type Spec } from "./spec.js";
|
|
4
|
+
/** Above this size, a mockup is refused: a sketch of an interface fits well below it. */
|
|
5
|
+
export declare const maxMockupBytes: number;
|
|
6
|
+
/**
|
|
7
|
+
* How the agent that wrote a spec with the operator presents it, for the
|
|
8
|
+
* operator to validate it on the spec page: in plain words, in the spec's
|
|
9
|
+
* language, each change with a mockup when it brings an interface.
|
|
10
|
+
*/
|
|
11
|
+
export declare const specPresentation: z.ZodObject<{
|
|
12
|
+
need: z.ZodString;
|
|
13
|
+
changes: z.ZodArray<z.ZodObject<{
|
|
14
|
+
title: z.ZodString;
|
|
15
|
+
text: z.ZodString;
|
|
16
|
+
mockup: z.ZodOptional<z.ZodObject<{
|
|
17
|
+
caption: z.ZodString;
|
|
18
|
+
html: z.ZodString;
|
|
19
|
+
width: z.ZodNumber;
|
|
20
|
+
height: z.ZodNumber;
|
|
21
|
+
}, z.core.$strict>>;
|
|
22
|
+
}, z.core.$strict>>;
|
|
23
|
+
decisions: z.ZodArray<z.ZodObject<{
|
|
24
|
+
id: z.ZodString;
|
|
25
|
+
title: z.ZodString;
|
|
26
|
+
why: z.ZodString;
|
|
27
|
+
options: z.ZodArray<z.ZodObject<{
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
title: z.ZodString;
|
|
30
|
+
text: z.ZodString;
|
|
31
|
+
}, z.core.$strict>>;
|
|
32
|
+
chosen: z.ZodString;
|
|
33
|
+
}, z.core.$strict>>;
|
|
34
|
+
criteria: z.ZodArray<z.ZodObject<{
|
|
35
|
+
title: z.ZodString;
|
|
36
|
+
criteria: z.ZodArray<z.ZodObject<{
|
|
37
|
+
id: z.ZodString;
|
|
38
|
+
plain: z.ZodString;
|
|
39
|
+
check: z.ZodString;
|
|
40
|
+
}, z.core.$strict>>;
|
|
41
|
+
}, z.core.$strict>>;
|
|
42
|
+
outOfScope: z.ZodArray<z.ZodString>;
|
|
43
|
+
}, z.core.$strict>;
|
|
44
|
+
export type SpecPresentation = z.output<typeof specPresentation>;
|
|
45
|
+
/** What the factory keeps of a presented spec: the presentation, and the spec it presents, word for word. */
|
|
46
|
+
export declare const presentedSpec: z.ZodObject<{
|
|
47
|
+
spec: z.ZodString;
|
|
48
|
+
presentation: z.ZodObject<{
|
|
49
|
+
need: z.ZodString;
|
|
50
|
+
changes: z.ZodArray<z.ZodObject<{
|
|
51
|
+
title: z.ZodString;
|
|
52
|
+
text: z.ZodString;
|
|
53
|
+
mockup: z.ZodOptional<z.ZodObject<{
|
|
54
|
+
caption: z.ZodString;
|
|
55
|
+
html: z.ZodString;
|
|
56
|
+
width: z.ZodNumber;
|
|
57
|
+
height: z.ZodNumber;
|
|
58
|
+
}, z.core.$strict>>;
|
|
59
|
+
}, z.core.$strict>>;
|
|
60
|
+
decisions: z.ZodArray<z.ZodObject<{
|
|
61
|
+
id: z.ZodString;
|
|
62
|
+
title: z.ZodString;
|
|
63
|
+
why: z.ZodString;
|
|
64
|
+
options: z.ZodArray<z.ZodObject<{
|
|
65
|
+
id: z.ZodString;
|
|
66
|
+
title: z.ZodString;
|
|
67
|
+
text: z.ZodString;
|
|
68
|
+
}, z.core.$strict>>;
|
|
69
|
+
chosen: z.ZodString;
|
|
70
|
+
}, z.core.$strict>>;
|
|
71
|
+
criteria: z.ZodArray<z.ZodObject<{
|
|
72
|
+
title: z.ZodString;
|
|
73
|
+
criteria: z.ZodArray<z.ZodObject<{
|
|
74
|
+
id: z.ZodString;
|
|
75
|
+
plain: z.ZodString;
|
|
76
|
+
check: z.ZodString;
|
|
77
|
+
}, z.core.$strict>>;
|
|
78
|
+
}, z.core.$strict>>;
|
|
79
|
+
outOfScope: z.ZodArray<z.ZodString>;
|
|
80
|
+
}, z.core.$strict>;
|
|
81
|
+
}, z.core.$strict>;
|
|
82
|
+
export type PresentedSpec = z.output<typeof presentedSpec>;
|
|
83
|
+
/** What is wrong with a presentation of `spec`: criteria not presented once each, choices whose options do not hold. */
|
|
84
|
+
export declare function presentationProblems(presentation: SpecPresentation, spec: Spec): string[];
|
|
85
|
+
/** A presentation an agent drafted, checked against the spec it presents. */
|
|
86
|
+
export declare function parsePresentation(draft: string, spec: Spec): Parsed<SpecPresentation>;
|
|
87
|
+
/** What the spec page shows of a presented spec; `@clemrig/factory-ui` draws it. */
|
|
88
|
+
export interface SpecPage {
|
|
89
|
+
issue: string;
|
|
90
|
+
title: string;
|
|
91
|
+
stale: boolean;
|
|
92
|
+
need: string;
|
|
93
|
+
changes: SpecPresentation["changes"];
|
|
94
|
+
decisions: SpecPresentation["decisions"];
|
|
95
|
+
criteria: {
|
|
96
|
+
title: string;
|
|
97
|
+
criteria: {
|
|
98
|
+
id: string;
|
|
99
|
+
text: string;
|
|
100
|
+
plain: string;
|
|
101
|
+
check: string;
|
|
102
|
+
}[];
|
|
103
|
+
}[];
|
|
104
|
+
outOfScope: string[];
|
|
105
|
+
spec: {
|
|
106
|
+
objective: string;
|
|
107
|
+
scope: string;
|
|
108
|
+
outOfScope: string;
|
|
109
|
+
constraints: string;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The page of issue `slug`'s presented spec, in the words of the spec it
|
|
114
|
+
* presents; stale when `current`, the spec now, says something else.
|
|
115
|
+
* `undefined` when the spec it presents no longer reads.
|
|
116
|
+
*/
|
|
117
|
+
export declare function specPage(slug: string, { spec: text, presentation }: PresentedSpec, current: string | undefined): SpecPage | undefined;
|
|
118
|
+
/** Where a person is in a spec's validation, as the page sends it: the review's answers, and the options taken. */
|
|
119
|
+
export declare const specAnswers: z.ZodObject<{
|
|
120
|
+
answers: z.ZodRecord<z.ZodString, z.ZodEnum<{
|
|
121
|
+
no: "no";
|
|
122
|
+
ok: "ok";
|
|
123
|
+
skip: "skip";
|
|
124
|
+
}>>;
|
|
125
|
+
notes: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
126
|
+
seen: z.ZodArray<z.ZodString>;
|
|
127
|
+
position: z.ZodNumber;
|
|
128
|
+
startedAt: z.ZodNullable<z.ZodNumber>;
|
|
129
|
+
endedAt: z.ZodNullable<z.ZodNumber>;
|
|
130
|
+
choices: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
131
|
+
}, z.core.$strict>;
|
|
132
|
+
export type SpecAnswers = z.output<typeof specAnswers>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { z } from "@clemrig/flow";
|
|
2
|
+
import { reviewAnswers } from "./review-page.js";
|
|
3
|
+
import { parseSpec } from "./spec.js";
|
|
4
|
+
/** An id a card is kept under: a choice's, an option's. */
|
|
5
|
+
const id = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^[a-z][a-z0-9-]{0,39}$/, "Expected a lowercase letter, then lowercase letters, digits or hyphens: 40 characters at most");
|
|
8
|
+
const text = (max) => z.string().trim().min(1).max(max);
|
|
9
|
+
/** Above this size, a mockup is refused: a sketch of an interface fits well below it. */
|
|
10
|
+
export const maxMockupBytes = 256 * 1024;
|
|
11
|
+
const mockup = z.strictObject({
|
|
12
|
+
caption: text(300),
|
|
13
|
+
html: z
|
|
14
|
+
.string()
|
|
15
|
+
.min(1)
|
|
16
|
+
.refine((html) => new TextEncoder().encode(html).length <= maxMockupBytes, `At most ${maxMockupBytes / 1024} KiB`),
|
|
17
|
+
width: z.number().int().min(320).max(1600),
|
|
18
|
+
height: z.number().int().min(200).max(4000),
|
|
19
|
+
});
|
|
20
|
+
/**
|
|
21
|
+
* How the agent that wrote a spec with the operator presents it, for the
|
|
22
|
+
* operator to validate it on the spec page: in plain words, in the spec's
|
|
23
|
+
* language, each change with a mockup when it brings an interface.
|
|
24
|
+
*/
|
|
25
|
+
export const specPresentation = z.strictObject({
|
|
26
|
+
need: text(4000),
|
|
27
|
+
changes: z
|
|
28
|
+
.array(z.strictObject({
|
|
29
|
+
title: text(200),
|
|
30
|
+
text: text(4000),
|
|
31
|
+
mockup: mockup.optional(),
|
|
32
|
+
}))
|
|
33
|
+
.min(1)
|
|
34
|
+
.max(20),
|
|
35
|
+
decisions: z
|
|
36
|
+
.array(z.strictObject({
|
|
37
|
+
id,
|
|
38
|
+
title: text(300),
|
|
39
|
+
why: text(2000),
|
|
40
|
+
options: z
|
|
41
|
+
.array(z.strictObject({ id, title: text(200), text: text(2000) }))
|
|
42
|
+
.min(2)
|
|
43
|
+
.max(5),
|
|
44
|
+
chosen: id,
|
|
45
|
+
}))
|
|
46
|
+
.max(20),
|
|
47
|
+
criteria: z
|
|
48
|
+
.array(z.strictObject({
|
|
49
|
+
title: text(200),
|
|
50
|
+
criteria: z
|
|
51
|
+
.array(z.strictObject({
|
|
52
|
+
id: z.string().regex(/^AC[1-9]\d*$/, "Expected AC<n>"),
|
|
53
|
+
plain: text(1000),
|
|
54
|
+
check: text(500),
|
|
55
|
+
}))
|
|
56
|
+
.min(1),
|
|
57
|
+
}))
|
|
58
|
+
.min(1)
|
|
59
|
+
.max(20),
|
|
60
|
+
outOfScope: z.array(text(500)).max(30),
|
|
61
|
+
});
|
|
62
|
+
/** What the factory keeps of a presented spec: the presentation, and the spec it presents, word for word. */
|
|
63
|
+
export const presentedSpec = z.strictObject({
|
|
64
|
+
spec: z.string(),
|
|
65
|
+
presentation: specPresentation,
|
|
66
|
+
});
|
|
67
|
+
/** What is wrong with a presentation of `spec`: criteria not presented once each, choices whose options do not hold. */
|
|
68
|
+
export function presentationProblems(presentation, spec) {
|
|
69
|
+
const problems = [];
|
|
70
|
+
const presented = presentation.criteria.flatMap(({ criteria }) => criteria.map(({ id }) => id));
|
|
71
|
+
const known = new Set(spec.criteria.map(({ id }) => id));
|
|
72
|
+
for (const criterion of spec.criteria)
|
|
73
|
+
if (!presented.includes(criterion.id))
|
|
74
|
+
problems.push(`criteria: ${criterion.id} is not presented`);
|
|
75
|
+
for (const criterion of new Set(presented)) {
|
|
76
|
+
if (!known.has(criterion))
|
|
77
|
+
problems.push(`criteria: ${criterion} is not a criterion of the spec`);
|
|
78
|
+
if (presented.indexOf(criterion) !== presented.lastIndexOf(criterion))
|
|
79
|
+
problems.push(`criteria: ${criterion} is presented more than once`);
|
|
80
|
+
}
|
|
81
|
+
const decisions = presentation.decisions.map(({ id }) => id);
|
|
82
|
+
presentation.decisions.forEach((decision, index) => {
|
|
83
|
+
const where = `decisions[${index}]`;
|
|
84
|
+
if (decisions.indexOf(decision.id) !== index)
|
|
85
|
+
problems.push(`${where}: ${decision.id} is the id of another choice`);
|
|
86
|
+
const options = decision.options.map(({ id }) => id);
|
|
87
|
+
for (const option of new Set(options))
|
|
88
|
+
if (options.indexOf(option) !== options.lastIndexOf(option))
|
|
89
|
+
problems.push(`${where}: option ${option} is listed twice`);
|
|
90
|
+
if (!options.includes(decision.chosen))
|
|
91
|
+
problems.push(`${where}.chosen: ${decision.chosen} is not an option`);
|
|
92
|
+
});
|
|
93
|
+
return problems;
|
|
94
|
+
}
|
|
95
|
+
/** A presentation an agent drafted, checked against the spec it presents. */
|
|
96
|
+
export function parsePresentation(draft, spec) {
|
|
97
|
+
let value;
|
|
98
|
+
try {
|
|
99
|
+
value = JSON.parse(draft);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
problems: [`Not JSON: ${error instanceof Error ? error.message : error}`],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const parsed = specPresentation.safeParse(value);
|
|
108
|
+
if (!parsed.success)
|
|
109
|
+
return { ok: false, problems: [z.prettifyError(parsed.error)] };
|
|
110
|
+
const problems = presentationProblems(parsed.data, spec);
|
|
111
|
+
return problems.length > 0
|
|
112
|
+
? { ok: false, problems }
|
|
113
|
+
: { ok: true, value: parsed.data };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The page of issue `slug`'s presented spec, in the words of the spec it
|
|
117
|
+
* presents; stale when `current`, the spec now, says something else.
|
|
118
|
+
* `undefined` when the spec it presents no longer reads.
|
|
119
|
+
*/
|
|
120
|
+
export function specPage(slug, { spec: text, presentation }, current) {
|
|
121
|
+
const parsed = parseSpec(text, slug);
|
|
122
|
+
if (!parsed.ok)
|
|
123
|
+
return undefined;
|
|
124
|
+
const spec = parsed.value;
|
|
125
|
+
const words = new Map(spec.criteria.map(({ id, text }) => [id, text]));
|
|
126
|
+
return {
|
|
127
|
+
issue: slug,
|
|
128
|
+
title: spec.title,
|
|
129
|
+
stale: current !== text,
|
|
130
|
+
need: presentation.need,
|
|
131
|
+
changes: presentation.changes,
|
|
132
|
+
decisions: presentation.decisions,
|
|
133
|
+
criteria: presentation.criteria.map((group) => ({
|
|
134
|
+
title: group.title,
|
|
135
|
+
criteria: group.criteria.map((criterion) => ({
|
|
136
|
+
id: criterion.id,
|
|
137
|
+
text: words.get(criterion.id) ?? "",
|
|
138
|
+
plain: criterion.plain,
|
|
139
|
+
check: criterion.check,
|
|
140
|
+
})),
|
|
141
|
+
})),
|
|
142
|
+
outOfScope: presentation.outOfScope,
|
|
143
|
+
spec: {
|
|
144
|
+
objective: spec.objective,
|
|
145
|
+
scope: spec.scope,
|
|
146
|
+
outOfScope: spec.outOfScope,
|
|
147
|
+
constraints: spec.constraints,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Where a person is in a spec's validation, as the page sends it: the review's answers, and the options taken. */
|
|
152
|
+
export const specAnswers = reviewAnswers.extend({
|
|
153
|
+
choices: z.record(id, id),
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=spec-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-page.js","sourceRoot":"","sources":["../../src/domain/spec-page.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
/** Optional `.factory/.env` secrets; existing shell variables retain precedence. */
|
|
2
2
|
export declare function loadLocalEnvironment(factoryDir: string): void;
|
|
3
|
+
/**
|
|
4
|
+
* Where others reach `factory ui`, such as the address `tailscale serve`
|
|
5
|
+
* gives it: `FACTORY_UI_URL`, from the shell or `.factory/.env`, always
|
|
6
|
+
* ending with `/`; `undefined` when unset.
|
|
7
|
+
*/
|
|
8
|
+
export declare function uiUrl(): URL | undefined;
|
|
@@ -10,4 +10,23 @@ export function loadLocalEnvironment(factoryDir) {
|
|
|
10
10
|
throw new Error(`Cannot load .env from ${factoryDir}`);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Where others reach `factory ui`, such as the address `tailscale serve`
|
|
15
|
+
* gives it: `FACTORY_UI_URL`, from the shell or `.factory/.env`, always
|
|
16
|
+
* ending with `/`; `undefined` when unset.
|
|
17
|
+
*/
|
|
18
|
+
export function uiUrl() {
|
|
19
|
+
const value = process.env.FACTORY_UI_URL?.trim();
|
|
20
|
+
if (!value)
|
|
21
|
+
return undefined;
|
|
22
|
+
const url = URL.parse(value);
|
|
23
|
+
if (!url ||
|
|
24
|
+
!["http:", "https:"].includes(url.protocol) ||
|
|
25
|
+
url.search ||
|
|
26
|
+
url.hash)
|
|
27
|
+
throw new Error(`FACTORY_UI_URL must be the http or https address of factory ui, such as https://forge.example.ts.net/; it is ${value}`);
|
|
28
|
+
if (!url.pathname.endsWith("/"))
|
|
29
|
+
url.pathname += "/";
|
|
30
|
+
return url;
|
|
31
|
+
}
|
|
13
32
|
//# sourceMappingURL=environment.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/system/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,oFAAoF;AACpF,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YACpD,MAAM,IAAI,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"environment.js","sourceRoot":"","sources":["../../src/system/environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,oFAAoF;AACpF,MAAM,UAAU,oBAAoB,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YACpD,MAAM,IAAI,KAAK,CAAC,yBAAyB,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK;IACnB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IACjD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,IACE,CAAC,GAAG;QACJ,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC3C,GAAG,CAAC,MAAM;QACV,GAAG,CAAC,IAAI;QAER,MAAM,IAAI,KAAK,CACb,gHAAgH,KAAK,EAAE,CACxH,CAAC;IACJ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC;IACrD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/system/factory.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface Factory {
|
|
|
11
11
|
}
|
|
12
12
|
/** A factory without workflows, to read runs when `factory.ts` cannot load. */
|
|
13
13
|
export declare function emptyFactory(factoryDir: string): Factory;
|
|
14
|
+
/** A run's directory, where it keeps its files. */
|
|
15
|
+
export declare function runDir(factory: Factory, id: string): string;
|
|
14
16
|
/** Imports `.factory/factory.ts` and returns its default export, unchecked. */
|
|
15
17
|
export declare function importFactory(factoryDir: string): Promise<unknown>;
|
|
16
18
|
export declare function workflowOf(factory: Factory, name: string): Workflow;
|
package/dist/system/factory.js
CHANGED
|
@@ -12,6 +12,10 @@ export function emptyFactory(factoryDir) {
|
|
|
12
12
|
packaged: new Set(),
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
+
/** A run's directory, where it keeps its files. */
|
|
16
|
+
export function runDir(factory, id) {
|
|
17
|
+
return join(factory.runsDir, id);
|
|
18
|
+
}
|
|
15
19
|
/** Imports `.factory/factory.ts` and returns its default export, unchecked. */
|
|
16
20
|
export async function importFactory(factoryDir) {
|
|
17
21
|
const module = (await import(pathToFileURL(join(factoryDir, "factory.ts")).href));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/system/factory.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/system/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAcxD,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC;QACxB,UAAU;QACV,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;QACjC,SAAS,EAAE,IAAI,GAAG,EAAE;QACpB,QAAQ,EAAE,IAAI,GAAG,EAAE;KACpB,CAAC;AACJ,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,MAAM,CAAC,OAAgB,EAAE,EAAU;IACjD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,UAAkB;IACpD,MAAM,MAAM,GAAG,CAAC,MAAM,MAAM,CAC1B,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CACnD,CAA0B,CAAC;IAC5B,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAgB,EAAE,IAAY;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ;QACX,MAAM,IAAI,KAAK,CACb,oBAAoB,IAAI,gBAAgB,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAC7F,CAAC;IACJ,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,mFAAmF;AACnF,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAEtE;;;;GAIG;AACH,SAAS,UAAU,CAAC,OAAgB,EAAE,QAAkB;IACtD,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACtE,CAAC;AAED,4CAA4C;AAC5C,MAAM,OAAO,GAAW,IAAI,CAAC,KAAK,CAChC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CACxD,CAAC,OAAO,CAAC;AAEV;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAgB,EAChB,QAAkB;IAElB,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC1C,CAAC,CAAC,oBAAoB,OAAO,EAAE;YAC/B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAgB,EAChB,QAAkB;IAElB,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC;YAAE,SAAS;QAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;QAC/D,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC;YACpE,QAAQ,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/system/git.d.ts
CHANGED
|
@@ -35,7 +35,11 @@ export declare function recentCommits(dir: string, since: {
|
|
|
35
35
|
} | {
|
|
36
36
|
days: number;
|
|
37
37
|
}, max: number): Promise<RecentCommit[]>;
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* The diff from one commit or tree to another, as its readers take it
|
|
40
|
+
* whatever Git's configuration says: names after `a/` and `b/`, unescaped
|
|
41
|
+
* letters, no colors, each line as the files have it.
|
|
42
|
+
*/
|
|
39
43
|
export declare function diff(dir: string, before: string, after: string): Promise<{
|
|
40
44
|
text: string;
|
|
41
45
|
truncated: boolean;
|
package/dist/system/git.js
CHANGED
|
@@ -134,9 +134,26 @@ export async function recentCommits(dir, since, max) {
|
|
|
134
134
|
}
|
|
135
135
|
return commits;
|
|
136
136
|
}
|
|
137
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* The diff from one commit or tree to another, as its readers take it
|
|
139
|
+
* whatever Git's configuration says: names after `a/` and `b/`, unescaped
|
|
140
|
+
* letters, no colors, each line as the files have it.
|
|
141
|
+
*/
|
|
138
142
|
export async function diff(dir, before, after) {
|
|
139
|
-
const result = await git(dir, [
|
|
143
|
+
const result = await git(dir, [
|
|
144
|
+
"-c",
|
|
145
|
+
"core.quotePath=false",
|
|
146
|
+
"-c",
|
|
147
|
+
"diff.suppressBlankEmpty=false",
|
|
148
|
+
"diff",
|
|
149
|
+
"--no-ext-diff",
|
|
150
|
+
"--no-textconv",
|
|
151
|
+
"--no-color",
|
|
152
|
+
"--src-prefix=a/",
|
|
153
|
+
"--dst-prefix=b/",
|
|
154
|
+
before,
|
|
155
|
+
after,
|
|
156
|
+
]);
|
|
140
157
|
return { text: result.stdout, truncated: result.stdoutTruncated };
|
|
141
158
|
}
|
|
142
159
|
/** Each file that differs from one commit or tree to another, with its added and removed lines, renames seen as `diff` sees them. */
|