@12ui/design 0.2.13 → 0.2.14
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 +35 -9
- package/dist/branch-client.d.ts +155 -0
- package/dist/branch-client.d.ts.map +1 -0
- package/dist/branch-client.js +179 -0
- package/dist/branch-client.js.map +1 -0
- package/dist/branch-completion.d.ts +37 -0
- package/dist/branch-completion.d.ts.map +1 -0
- package/dist/branch-completion.js +137 -0
- package/dist/branch-completion.js.map +1 -0
- package/dist/branch-dispatch-loop.d.ts +84 -0
- package/dist/branch-dispatch-loop.d.ts.map +1 -0
- package/dist/branch-dispatch-loop.js +206 -0
- package/dist/branch-dispatch-loop.js.map +1 -0
- package/dist/branch-downloads.d.ts +43 -0
- package/dist/branch-downloads.d.ts.map +1 -0
- package/dist/branch-downloads.js +94 -0
- package/dist/branch-downloads.js.map +1 -0
- package/dist/branch-execution-types.d.ts +54 -0
- package/dist/branch-execution-types.d.ts.map +1 -0
- package/dist/branch-execution-types.js +2 -0
- package/dist/branch-execution-types.js.map +1 -0
- package/dist/branch-execution.d.ts +18 -0
- package/dist/branch-execution.d.ts.map +1 -0
- package/dist/branch-execution.js +261 -0
- package/dist/branch-execution.js.map +1 -0
- package/dist/branch-identity.d.ts +71 -0
- package/dist/branch-identity.d.ts.map +1 -0
- package/dist/branch-identity.js +72 -0
- package/dist/branch-identity.js.map +1 -0
- package/dist/branch-materialize.d.ts +22 -0
- package/dist/branch-materialize.d.ts.map +1 -0
- package/dist/branch-materialize.js +47 -0
- package/dist/branch-materialize.js.map +1 -0
- package/dist/branch-page-conversion.d.ts +39 -0
- package/dist/branch-page-conversion.d.ts.map +1 -0
- package/dist/branch-page-conversion.js +206 -0
- package/dist/branch-page-conversion.js.map +1 -0
- package/dist/branch-plan.d.ts +63 -0
- package/dist/branch-plan.d.ts.map +1 -0
- package/dist/branch-plan.js +95 -0
- package/dist/branch-plan.js.map +1 -0
- package/dist/branch-progress.d.ts +75 -0
- package/dist/branch-progress.d.ts.map +1 -0
- package/dist/branch-progress.js +159 -0
- package/dist/branch-progress.js.map +1 -0
- package/dist/branch-run-record.d.ts +153 -0
- package/dist/branch-run-record.d.ts.map +1 -0
- package/dist/branch-run-record.js +94 -0
- package/dist/branch-run-record.js.map +1 -0
- package/dist/branch-schedule.d.ts +74 -0
- package/dist/branch-schedule.d.ts.map +1 -0
- package/dist/branch-schedule.js +130 -0
- package/dist/branch-schedule.js.map +1 -0
- package/dist/branch-status.d.ts +11 -0
- package/dist/branch-status.d.ts.map +1 -0
- package/dist/branch-status.js +115 -0
- package/dist/branch-status.js.map +1 -0
- package/dist/branch-viewport-normalization.d.ts +74 -0
- package/dist/branch-viewport-normalization.d.ts.map +1 -0
- package/dist/branch-viewport-normalization.js +120 -0
- package/dist/branch-viewport-normalization.js.map +1 -0
- package/dist/cli-arguments.d.ts.map +1 -1
- package/dist/cli-arguments.js +4 -0
- package/dist/cli-arguments.js.map +1 -1
- package/dist/cli-branch-command.d.ts +46 -0
- package/dist/cli-branch-command.d.ts.map +1 -0
- package/dist/cli-branch-command.js +426 -0
- package/dist/cli-branch-command.js.map +1 -0
- package/dist/cli-capabilities.d.ts +28 -0
- package/dist/cli-capabilities.d.ts.map +1 -1
- package/dist/cli-capabilities.js +29 -1
- package/dist/cli-capabilities.js.map +1 -1
- package/dist/cli-create-command.d.ts +21 -0
- package/dist/cli-create-command.d.ts.map +1 -0
- package/dist/cli-create-command.js +319 -0
- package/dist/cli-create-command.js.map +1 -0
- package/dist/cli-detach.d.ts +62 -0
- package/dist/cli-detach.d.ts.map +1 -0
- package/dist/cli-detach.js +123 -0
- package/dist/cli-detach.js.map +1 -0
- package/dist/cli-draft-command.d.ts +63 -0
- package/dist/cli-draft-command.d.ts.map +1 -0
- package/dist/cli-draft-command.js +220 -0
- package/dist/cli-draft-command.js.map +1 -0
- package/dist/cli-export-command.d.ts.map +1 -1
- package/dist/cli-export-command.js +2 -3
- package/dist/cli-export-command.js.map +1 -1
- package/dist/cli-image-batch-command.d.ts +21 -0
- package/dist/cli-image-batch-command.d.ts.map +1 -1
- package/dist/cli-image-batch-command.js +65 -4
- package/dist/cli-image-batch-command.js.map +1 -1
- package/dist/cli-image-batch-resume.d.ts +7 -0
- package/dist/cli-image-batch-resume.d.ts.map +1 -1
- package/dist/cli-image-batch-resume.js +19 -2
- package/dist/cli-image-batch-resume.js.map +1 -1
- package/dist/cli-package-command.d.ts +18 -0
- package/dist/cli-package-command.d.ts.map +1 -0
- package/dist/cli-package-command.js +112 -0
- package/dist/cli-package-command.js.map +1 -0
- package/dist/cli-progress.d.ts +61 -0
- package/dist/cli-progress.d.ts.map +1 -1
- package/dist/cli-progress.js +53 -0
- package/dist/cli-progress.js.map +1 -1
- package/dist/cli-select-command.d.ts +12 -0
- package/dist/cli-select-command.d.ts.map +1 -0
- package/dist/cli-select-command.js +66 -0
- package/dist/cli-select-command.js.map +1 -0
- package/dist/cli.js +140 -7
- package/dist/cli.js.map +1 -1
- package/dist/create-identity.d.ts +25 -0
- package/dist/create-identity.d.ts.map +1 -0
- package/dist/create-identity.js +0 -0
- package/dist/create-identity.js.map +1 -0
- package/dist/draft-identity.d.ts +30 -0
- package/dist/draft-identity.d.ts.map +1 -0
- package/dist/draft-identity.js +0 -0
- package/dist/draft-identity.js.map +1 -0
- package/dist/draft-prompts.d.ts +35 -0
- package/dist/draft-prompts.d.ts.map +1 -0
- package/dist/draft-prompts.js +51 -0
- package/dist/draft-prompts.js.map +1 -0
- package/dist/draft-run.d.ts +32 -0
- package/dist/draft-run.d.ts.map +1 -0
- package/dist/draft-run.js +152 -0
- package/dist/draft-run.js.map +1 -0
- package/dist/draft-workspace.d.ts +90 -0
- package/dist/draft-workspace.d.ts.map +1 -0
- package/dist/draft-workspace.js +64 -0
- package/dist/draft-workspace.js.map +1 -0
- package/dist/image-batch-status.d.ts +42 -0
- package/dist/image-batch-status.d.ts.map +1 -0
- package/dist/image-batch-status.js +142 -0
- package/dist/image-batch-status.js.map +1 -0
- package/dist/image-dimensions.d.ts +12 -0
- package/dist/image-dimensions.d.ts.map +1 -0
- package/dist/image-dimensions.js +14 -0
- package/dist/image-dimensions.js.map +1 -0
- package/dist/image-generation-resume.d.ts +13 -0
- package/dist/image-generation-resume.d.ts.map +1 -1
- package/dist/image-generation-resume.js +13 -0
- package/dist/image-generation-resume.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/legacy-skill-catalog.d.ts.map +1 -1
- package/dist/legacy-skill-catalog.js +115 -0
- package/dist/legacy-skill-catalog.js.map +1 -1
- package/dist/package-manifest-file.d.ts +21 -0
- package/dist/package-manifest-file.d.ts.map +1 -0
- package/dist/package-manifest-file.js +119 -0
- package/dist/package-manifest-file.js.map +1 -0
- package/dist/package-manifest-template.d.ts +23 -0
- package/dist/package-manifest-template.d.ts.map +1 -0
- package/dist/package-manifest-template.js +60 -0
- package/dist/package-manifest-template.js.map +1 -0
- package/dist/package-submission.d.ts +103 -0
- package/dist/package-submission.d.ts.map +1 -0
- package/dist/package-submission.js +173 -0
- package/dist/package-submission.js.map +1 -0
- package/dist/selection-record.d.ts +95 -0
- package/dist/selection-record.d.ts.map +1 -0
- package/dist/selection-record.js +121 -0
- package/dist/selection-record.js.map +1 -0
- package/package.json +1 -1
- package/skills/design/SKILL.md +40 -266
- package/skills/design-branch/SKILL.md +36 -116
- package/skills/design-convert/SKILL.md +62 -148
- package/skills/design-draft/SKILL.md +71 -135
- package/skills/design-search/SKILL.md +29 -78
- package/skills/design/references/continuation-contract.md +0 -60
- package/skills/design/references/selection-contract.md +0 -112
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { branchPackageKey } from './branch-identity.js';
|
|
3
|
+
import { normalizePageViewports, } from './branch-viewport-normalization.js';
|
|
4
|
+
import { submitConversionPackage, } from './package-submission.js';
|
|
5
|
+
export const WINNER_VIEWPORT_ID = 'winner';
|
|
6
|
+
const readScreenBytes = async (screen) => (new Uint8Array(await readFile(screen.path)));
|
|
7
|
+
const orderedViewports = (plan, page) => plan.screens
|
|
8
|
+
.filter((screen) => page.slots.includes(screen.slot))
|
|
9
|
+
.sort((left, right) => left.viewportOrdinal - right.viewportOrdinal)
|
|
10
|
+
.map((screen) => ({ slot: screen.slot, ordinal: screen.viewportOrdinal }));
|
|
11
|
+
export const convertBranchPages = async (args) => {
|
|
12
|
+
const conversions = new Map();
|
|
13
|
+
for (const page of args.plan.pages) {
|
|
14
|
+
const planned = orderedViewports(args.plan, page);
|
|
15
|
+
const missing = planned.filter((viewport) => !args.screens.has(viewport.slot));
|
|
16
|
+
if (missing.length > 0) {
|
|
17
|
+
conversions.set(page.id, {
|
|
18
|
+
status: 'skipped',
|
|
19
|
+
reason: `Page ${page.id} is missing screen(s) ${missing.map((entry) => entry.slot).join(', ')},`
|
|
20
|
+
+ ' so its viewports do not stack into a whole page. The screens that did land are on'
|
|
21
|
+
+ ' disk; redraw the gap and re-run with --resume before converting this page.',
|
|
22
|
+
});
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
// Collect the page's pixels first, tagging which side declares the width.
|
|
26
|
+
const sources = [];
|
|
27
|
+
if (page.startsFromWinner) {
|
|
28
|
+
if (!args.winner) {
|
|
29
|
+
conversions.set(page.id, {
|
|
30
|
+
status: 'skipped',
|
|
31
|
+
reason: `Page ${page.id} starts from the approved screen, whose bytes are not available`
|
|
32
|
+
+ ' locally, so viewport 1 of the page is missing.',
|
|
33
|
+
});
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const bytes = await readScreenBytes(args.winner);
|
|
37
|
+
sources.push({
|
|
38
|
+
ordinal: 1,
|
|
39
|
+
path: args.winner.path,
|
|
40
|
+
input: {
|
|
41
|
+
id: WINNER_VIEWPORT_ID,
|
|
42
|
+
bytes,
|
|
43
|
+
mediaType: 'image/png',
|
|
44
|
+
width: args.winner.width,
|
|
45
|
+
height: args.winner.height,
|
|
46
|
+
// The winner came from somewhere else; it is the side that moves.
|
|
47
|
+
canonical: false,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
for (const viewport of planned) {
|
|
52
|
+
const screen = args.screens.get(viewport.slot);
|
|
53
|
+
sources.push({
|
|
54
|
+
ordinal: viewport.ordinal,
|
|
55
|
+
path: screen.path,
|
|
56
|
+
input: {
|
|
57
|
+
id: viewport.slot,
|
|
58
|
+
bytes: await readScreenBytes(screen),
|
|
59
|
+
mediaType: 'image/png',
|
|
60
|
+
width: screen.width,
|
|
61
|
+
height: screen.height,
|
|
62
|
+
// Drawn by the server on the run's fixed canvas: this is the width.
|
|
63
|
+
canonical: true,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
let normalization;
|
|
68
|
+
try {
|
|
69
|
+
normalization = await normalizePageViewports(sources.map((entry) => entry.input));
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
conversions.set(page.id, {
|
|
73
|
+
status: 'failed',
|
|
74
|
+
output: args.settings.output,
|
|
75
|
+
error: error instanceof Error ? error.message : String(error),
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const normalizedById = new Map(normalization.viewports.map((entry) => [entry.id, entry]));
|
|
80
|
+
const viewports = sources.map((entry) => {
|
|
81
|
+
const resolved = normalizedById.get(entry.input.id);
|
|
82
|
+
// A normalized winner is no longer the bytes any earlier conversion was
|
|
83
|
+
// admitted with, so the reuse claim would be false. Buy it instead of
|
|
84
|
+
// asserting a digest the server will disprove.
|
|
85
|
+
const reuse = entry.input.id === WINNER_VIEWPORT_ID
|
|
86
|
+
&& args.settings.sourceConversionId
|
|
87
|
+
&& !resolved.normalized;
|
|
88
|
+
return {
|
|
89
|
+
id: entry.input.id,
|
|
90
|
+
ordinal: entry.ordinal,
|
|
91
|
+
imagePath: entry.path,
|
|
92
|
+
bytes: resolved.bytes,
|
|
93
|
+
mediaType: resolved.mediaType,
|
|
94
|
+
...(reuse ? { sourceConversionId: args.settings.sourceConversionId } : {}),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
if (viewports.length === 0) {
|
|
98
|
+
conversions.set(page.id, {
|
|
99
|
+
status: 'skipped',
|
|
100
|
+
reason: `Page ${page.id} has no viewport to convert.`,
|
|
101
|
+
});
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (viewports.length === 1 && page.startsFromWinner) {
|
|
105
|
+
conversions.set(page.id, {
|
|
106
|
+
status: 'skipped',
|
|
107
|
+
reason: 'The approved screen already is the whole page — the server planned no'
|
|
108
|
+
+ ' continuations for it. Convert it on its own with'
|
|
109
|
+
+ ' `12ui convert <winner> --output layerdoc --export html`.',
|
|
110
|
+
});
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const input = {
|
|
114
|
+
id: page.id,
|
|
115
|
+
ordinal: page.index,
|
|
116
|
+
kind: page.kind,
|
|
117
|
+
...(page.title ? { title: page.title } : {}),
|
|
118
|
+
...(page.purpose ? { purpose: page.purpose } : {}),
|
|
119
|
+
viewports,
|
|
120
|
+
};
|
|
121
|
+
// Keyed on the bytes actually submitted, so a retry after normalization
|
|
122
|
+
// replays the same package instead of buying the page again.
|
|
123
|
+
const idempotencyKey = branchPackageKey({
|
|
124
|
+
runId: args.plan.runId,
|
|
125
|
+
pageIndex: page.index,
|
|
126
|
+
viewportSha256s: viewports.map((viewport) => normalizedById.get(viewport.id).sha256),
|
|
127
|
+
output: args.settings.output,
|
|
128
|
+
...(args.settings.model ? { model: args.settings.model } : {}),
|
|
129
|
+
...(args.settings.responsiveQuality
|
|
130
|
+
? { responsiveQuality: args.settings.responsiveQuality }
|
|
131
|
+
: {}),
|
|
132
|
+
});
|
|
133
|
+
const normalizedRecord = normalization.viewports
|
|
134
|
+
.filter((viewport) => viewport.normalized)
|
|
135
|
+
.map((viewport) => ({
|
|
136
|
+
id: viewport.id,
|
|
137
|
+
fromWidth: viewport.original.width,
|
|
138
|
+
fromHeight: viewport.original.height,
|
|
139
|
+
fromSha256: viewport.original.sha256,
|
|
140
|
+
toWidth: viewport.width,
|
|
141
|
+
toHeight: viewport.height,
|
|
142
|
+
toSha256: viewport.sha256,
|
|
143
|
+
}));
|
|
144
|
+
const normalizationRecord = {
|
|
145
|
+
...(normalization.canonicalWidth === null
|
|
146
|
+
? {}
|
|
147
|
+
: { canonicalWidth: normalization.canonicalWidth }),
|
|
148
|
+
...(normalizedRecord.length > 0 ? { normalizedViewports: normalizedRecord } : {}),
|
|
149
|
+
};
|
|
150
|
+
try {
|
|
151
|
+
const result = await submitConversionPackage({
|
|
152
|
+
client: args.client,
|
|
153
|
+
outDir: args.pagesDirectory,
|
|
154
|
+
submission: {
|
|
155
|
+
output: args.settings.output,
|
|
156
|
+
...(args.settings.model ? { model: args.settings.model } : {}),
|
|
157
|
+
...(args.settings.responsiveQuality
|
|
158
|
+
? { responsiveQuality: args.settings.responsiveQuality }
|
|
159
|
+
: {}),
|
|
160
|
+
pages: [input],
|
|
161
|
+
idempotencyKey,
|
|
162
|
+
},
|
|
163
|
+
...(args.timeoutMs === undefined ? {} : { timeoutMs: args.timeoutMs }),
|
|
164
|
+
...(args.onProgress
|
|
165
|
+
? { onProgress: (event) => args.onProgress(page.id, event) }
|
|
166
|
+
: {}),
|
|
167
|
+
...(args.signal ? { signal: args.signal } : {}),
|
|
168
|
+
});
|
|
169
|
+
const converted = result.pages[0];
|
|
170
|
+
conversions.set(page.id, converted?.status === 'succeeded'
|
|
171
|
+
? {
|
|
172
|
+
status: 'succeeded',
|
|
173
|
+
packageId: result.packageId,
|
|
174
|
+
idempotencyKey,
|
|
175
|
+
output: args.settings.output,
|
|
176
|
+
...normalizationRecord,
|
|
177
|
+
...(converted.conversionId ? { conversionId: converted.conversionId } : {}),
|
|
178
|
+
...(converted.outFile ? { outFile: converted.outFile } : {}),
|
|
179
|
+
...(converted.sha256 ? { sha256: converted.sha256 } : {}),
|
|
180
|
+
...(converted.bytes === undefined ? {} : { bytes: converted.bytes }),
|
|
181
|
+
}
|
|
182
|
+
: {
|
|
183
|
+
status: 'failed',
|
|
184
|
+
packageId: result.packageId,
|
|
185
|
+
idempotencyKey,
|
|
186
|
+
output: args.settings.output,
|
|
187
|
+
...normalizationRecord,
|
|
188
|
+
error: converted?.error ?? `Package ${result.packageId} produced no page.`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
// The reconciliation is a fact about what was submitted, so it belongs in
|
|
193
|
+
// the record whether or not the submission was accepted — a failed page
|
|
194
|
+
// is exactly when an operator needs to know what the bytes were.
|
|
195
|
+
conversions.set(page.id, {
|
|
196
|
+
status: 'failed',
|
|
197
|
+
idempotencyKey,
|
|
198
|
+
output: args.settings.output,
|
|
199
|
+
...normalizationRecord,
|
|
200
|
+
error: error instanceof Error ? error.message : String(error),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return conversions;
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=branch-page-conversion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-page-conversion.js","sourceRoot":"","sources":["../src/branch-page-conversion.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { BranchRunEnvelope, BranchScreenStatus } from './branch-client.js';
|
|
2
|
+
import type { BranchScope } from './branch-identity.js';
|
|
3
|
+
/**
|
|
4
|
+
* Plan normalisation. The wire envelope keeps ordering and per-screen facts in
|
|
5
|
+
* two different places — `plan.pages[].slots` and `candidates[]` — so this is
|
|
6
|
+
* the one module that joins them back into the page/viewport structure the
|
|
7
|
+
* scheduler, the downloads, and the package manifests all read.
|
|
8
|
+
*
|
|
9
|
+
* The approved winner is NOT a slot. The server plans continuations of the
|
|
10
|
+
* source page starting at `viewportOrdinal` 2; ordinal 1 of that page is the
|
|
11
|
+
* image the run branched from. Additional pages start at ordinal 1 because
|
|
12
|
+
* every one of their viewports is generated.
|
|
13
|
+
*/
|
|
14
|
+
export type BranchPlannedScreen = {
|
|
15
|
+
slot: string;
|
|
16
|
+
pageIndex: number;
|
|
17
|
+
viewportOrdinal: number;
|
|
18
|
+
status: BranchScreenStatus;
|
|
19
|
+
direction: string;
|
|
20
|
+
header: boolean | null;
|
|
21
|
+
footer: boolean | null;
|
|
22
|
+
pageEndsHere: boolean;
|
|
23
|
+
dependsOnSlot: string | null;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
content?: string;
|
|
27
|
+
error?: {
|
|
28
|
+
code: string;
|
|
29
|
+
message: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export type BranchPlannedPage = {
|
|
33
|
+
index: number;
|
|
34
|
+
id: string;
|
|
35
|
+
kind: 'source' | 'additional';
|
|
36
|
+
title: string;
|
|
37
|
+
pageType: string;
|
|
38
|
+
surfaceType: string;
|
|
39
|
+
purpose: string;
|
|
40
|
+
/** True when viewport 1 of this page is the approved winner, not a slot. */
|
|
41
|
+
startsFromWinner: boolean;
|
|
42
|
+
slots: string[];
|
|
43
|
+
};
|
|
44
|
+
export type BranchNormalizedPlan = {
|
|
45
|
+
runId: string;
|
|
46
|
+
concept: string;
|
|
47
|
+
aspect: string;
|
|
48
|
+
scope: BranchScope;
|
|
49
|
+
sitePurpose: string;
|
|
50
|
+
statusUpdate: string;
|
|
51
|
+
approvedScreenSummary: string;
|
|
52
|
+
pages: BranchPlannedPage[];
|
|
53
|
+
screens: BranchPlannedScreen[];
|
|
54
|
+
};
|
|
55
|
+
/** Stable, filesystem-safe, and self-describing: `p0-pricing`, `p2`. */
|
|
56
|
+
export declare const branchPageId: (index: number, title: string) => string;
|
|
57
|
+
export declare const normalizeBranchPlan: (envelope: BranchRunEnvelope, options: {
|
|
58
|
+
scope: BranchScope;
|
|
59
|
+
maxScreens?: number;
|
|
60
|
+
}) => BranchNormalizedPlan;
|
|
61
|
+
/** Refresh statuses from a later envelope without re-deriving the structure. */
|
|
62
|
+
export declare const applyBranchEnvelope: (plan: BranchNormalizedPlan, envelope: BranchRunEnvelope) => BranchNormalizedPlan;
|
|
63
|
+
//# sourceMappingURL=branch-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-plan.d.ts","sourceRoot":"","sources":["../src/branch-plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAEjB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,OAAO,EAAE,mBAAmB,EAAE,CAAC;CAChC,CAAC;AASF,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,OAAO,MAAM,KAAG,MAQ3D,CAAC;AAqBF,eAAO,MAAM,mBAAmB,GAC9B,UAAU,iBAAiB,EAC3B,SAAS;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,KACnD,oBA0DF,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,GAC9B,MAAM,oBAAoB,EAC1B,UAAU,iBAAiB,KAC1B,oBAWF,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const PAGE_TITLE_LIMIT = 200;
|
|
2
|
+
const PAGE_PURPOSE_LIMIT = 1_000;
|
|
3
|
+
const clamp = (value, limit) => (value.length <= limit ? value : `${value.slice(0, limit - 1)}…`);
|
|
4
|
+
/** Stable, filesystem-safe, and self-describing: `p0-pricing`, `p2`. */
|
|
5
|
+
export const branchPageId = (index, title) => {
|
|
6
|
+
const slug = title
|
|
7
|
+
.toLowerCase()
|
|
8
|
+
.replace(/[^a-z0-9]+/gu, '-')
|
|
9
|
+
.replace(/^-+|-+$/gu, '')
|
|
10
|
+
.slice(0, 40)
|
|
11
|
+
.replace(/-+$/u, '');
|
|
12
|
+
return slug ? `p${index}-${slug}` : `p${index}`;
|
|
13
|
+
};
|
|
14
|
+
const screenFor = (candidate) => {
|
|
15
|
+
if (candidate.pageIndex === undefined || candidate.viewportOrdinal === undefined)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
slot: candidate.slot,
|
|
19
|
+
pageIndex: candidate.pageIndex,
|
|
20
|
+
viewportOrdinal: candidate.viewportOrdinal,
|
|
21
|
+
status: candidate.status,
|
|
22
|
+
direction: candidate.direction,
|
|
23
|
+
header: candidate.header ?? null,
|
|
24
|
+
footer: candidate.footer ?? null,
|
|
25
|
+
pageEndsHere: candidate.pageEndsHere ?? false,
|
|
26
|
+
dependsOnSlot: candidate.dependsOnSlot ?? null,
|
|
27
|
+
width: candidate.width,
|
|
28
|
+
height: candidate.height,
|
|
29
|
+
...(candidate.content ? { content: candidate.content } : {}),
|
|
30
|
+
...(candidate.error ? { error: candidate.error } : {}),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export const normalizeBranchPlan = (envelope, options) => {
|
|
34
|
+
const plan = envelope.plan;
|
|
35
|
+
if (!plan || !Array.isArray(plan.pages)) {
|
|
36
|
+
throw new Error(`Run ${envelope.id} carries no build plan. Only a run started with source "build" can be`
|
|
37
|
+
+ ' branched.');
|
|
38
|
+
}
|
|
39
|
+
const bySlot = new Map(envelope.candidates.map((candidate) => [candidate.slot, candidate]));
|
|
40
|
+
// Plan order is page order then viewport order, which is also slot order.
|
|
41
|
+
// Everything downstream — the footer seed, the dependency chains, the
|
|
42
|
+
// `--max-screens` trim — depends on keeping exactly that sequence.
|
|
43
|
+
const orderedSlots = plan.pages.flatMap((page) => ((page.slots ?? []).filter((slot) => bySlot.has(slot))));
|
|
44
|
+
const scopedPages = options.scope === 'page'
|
|
45
|
+
? plan.pages.filter((page) => page.kind === 'source')
|
|
46
|
+
: plan.pages;
|
|
47
|
+
const scopedSlots = new Set(scopedPages.flatMap((page) => page.slots ?? []));
|
|
48
|
+
const trimmed = options.maxScreens === undefined
|
|
49
|
+
? null
|
|
50
|
+
: new Set(orderedSlots.filter((slot) => scopedSlots.has(slot)).slice(0, options.maxScreens));
|
|
51
|
+
const keeps = (slot) => (scopedSlots.has(slot) && (trimmed === null || trimmed.has(slot)));
|
|
52
|
+
const pages = scopedPages.map((page) => ({
|
|
53
|
+
index: page.index,
|
|
54
|
+
id: branchPageId(page.index, page.title ?? ''),
|
|
55
|
+
kind: page.kind,
|
|
56
|
+
title: clamp(page.title ?? `Page ${page.index}`, PAGE_TITLE_LIMIT),
|
|
57
|
+
pageType: page.pageType ?? 'other',
|
|
58
|
+
surfaceType: page.surfaceType ?? 'web_page',
|
|
59
|
+
purpose: clamp(page.purpose ?? '', PAGE_PURPOSE_LIMIT),
|
|
60
|
+
startsFromWinner: page.kind === 'source',
|
|
61
|
+
slots: (page.slots ?? []).filter(keeps),
|
|
62
|
+
}));
|
|
63
|
+
const screens = orderedSlots
|
|
64
|
+
.filter(keeps)
|
|
65
|
+
.flatMap((slot) => {
|
|
66
|
+
const screen = screenFor(bySlot.get(slot));
|
|
67
|
+
return screen ? [screen] : [];
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
runId: envelope.id,
|
|
71
|
+
concept: envelope.concept,
|
|
72
|
+
aspect: envelope.aspect,
|
|
73
|
+
scope: options.scope,
|
|
74
|
+
sitePurpose: plan.sitePurpose ?? '',
|
|
75
|
+
statusUpdate: plan.statusUpdate ?? '',
|
|
76
|
+
approvedScreenSummary: plan.approvedScreenSummary ?? '',
|
|
77
|
+
pages,
|
|
78
|
+
screens,
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Refresh statuses from a later envelope without re-deriving the structure. */
|
|
82
|
+
export const applyBranchEnvelope = (plan, envelope) => {
|
|
83
|
+
const bySlot = new Map(envelope.candidates.map((candidate) => [candidate.slot, candidate]));
|
|
84
|
+
return {
|
|
85
|
+
...plan,
|
|
86
|
+
screens: plan.screens.map((screen) => {
|
|
87
|
+
const candidate = bySlot.get(screen.slot);
|
|
88
|
+
if (!candidate)
|
|
89
|
+
return screen;
|
|
90
|
+
const next = screenFor(candidate);
|
|
91
|
+
return next ? { ...screen, ...next } : screen;
|
|
92
|
+
}),
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=branch-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-plan.js","sourceRoot":"","sources":["../src/branch-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { BranchNormalizedPlan } from './branch-plan.js';
|
|
2
|
+
import type { BranchCompletion } from './branch-run-record.js';
|
|
3
|
+
/**
|
|
4
|
+
* The motion surface. A long command that answers a poll with bare absence is
|
|
5
|
+
* the measured trigger for a caller deciding the process stalled and improvising
|
|
6
|
+
* around it, so every observation of a branch run — the command's own streamed
|
|
7
|
+
* lines and `12ui branch status` from another session — reports what changed,
|
|
8
|
+
* how long each screen has been running against its typical duration, and what
|
|
9
|
+
* to do next.
|
|
10
|
+
*/
|
|
11
|
+
export declare const BRANCH_PROGRESS_FILENAME = "branch.progress.json";
|
|
12
|
+
export type BranchProgressPhase = 'claiming' | 'dispatching' | 'downloading' | 'converting' | 'terminal';
|
|
13
|
+
export type BranchProgressScreen = {
|
|
14
|
+
slot: string;
|
|
15
|
+
status: 'pending' | 'dispatched' | 'succeeded' | 'failed' | 'blocked';
|
|
16
|
+
pageIndex: number;
|
|
17
|
+
viewportOrdinal: number;
|
|
18
|
+
dispatchedAt?: string;
|
|
19
|
+
waitingOn?: string;
|
|
20
|
+
};
|
|
21
|
+
export type BranchProgressRecord = {
|
|
22
|
+
version: 1;
|
|
23
|
+
runId: string;
|
|
24
|
+
phase: BranchProgressPhase;
|
|
25
|
+
startedAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
screens: BranchProgressScreen[];
|
|
28
|
+
};
|
|
29
|
+
export declare const branchProgressPath: (outDir: string) => string;
|
|
30
|
+
export declare const writeBranchProgress: (file: string, record: BranchProgressRecord) => Promise<void>;
|
|
31
|
+
export declare const readBranchProgress: (file: string) => Promise<BranchProgressRecord | undefined>;
|
|
32
|
+
export declare const branchProgressScreens: (plan: BranchNormalizedPlan, dispatchedAt: Readonly<Record<string, string>>) => BranchProgressScreen[];
|
|
33
|
+
export type BranchStatusCounts = {
|
|
34
|
+
total: number;
|
|
35
|
+
complete: number;
|
|
36
|
+
generating: number;
|
|
37
|
+
waiting: number;
|
|
38
|
+
blocked: number;
|
|
39
|
+
failed: number;
|
|
40
|
+
};
|
|
41
|
+
export type BranchStatusReport = {
|
|
42
|
+
outDir: string;
|
|
43
|
+
runId?: string;
|
|
44
|
+
phase: BranchProgressPhase;
|
|
45
|
+
complete: boolean;
|
|
46
|
+
counts: BranchStatusCounts;
|
|
47
|
+
screens: BranchProgressScreen[];
|
|
48
|
+
/** Always populated: what is moving, and how long it has been moving. */
|
|
49
|
+
narrative: string;
|
|
50
|
+
/** Present only while work remains. A finished run has no next action. */
|
|
51
|
+
nextAction?: string;
|
|
52
|
+
startedAt?: string;
|
|
53
|
+
updatedAt?: string;
|
|
54
|
+
elapsedSeconds?: number;
|
|
55
|
+
completionPath?: string;
|
|
56
|
+
planPath?: string;
|
|
57
|
+
pages?: BranchCompletion['pages'];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* One line of motion plus, while anything remains, one line of instruction.
|
|
61
|
+
* A terminal report carries neither: there is nothing in flight to narrate and
|
|
62
|
+
* nothing left to check.
|
|
63
|
+
*/
|
|
64
|
+
export declare const summarizeBranchProgress: (args: {
|
|
65
|
+
outDir: string;
|
|
66
|
+
runId?: string;
|
|
67
|
+
phase: BranchProgressPhase;
|
|
68
|
+
screens: readonly BranchProgressScreen[];
|
|
69
|
+
startedAt?: string;
|
|
70
|
+
updatedAt?: string;
|
|
71
|
+
completion?: BranchCompletion;
|
|
72
|
+
statusCommand?: string;
|
|
73
|
+
now?: number;
|
|
74
|
+
}) => BranchStatusReport;
|
|
75
|
+
//# sourceMappingURL=branch-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-progress.d.ts","sourceRoot":"","sources":["../src/branch-progress.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { OPERATION_DURATION_HINTS, elapsedAgainstTypical, formatDuration, narrateCounts, nextActionLine, secondsSince, } from './cli-progress.js';
|
|
5
|
+
import { branchBlockedSlots } from './branch-schedule.js';
|
|
6
|
+
/**
|
|
7
|
+
* The motion surface. A long command that answers a poll with bare absence is
|
|
8
|
+
* the measured trigger for a caller deciding the process stalled and improvising
|
|
9
|
+
* around it, so every observation of a branch run — the command's own streamed
|
|
10
|
+
* lines and `12ui branch status` from another session — reports what changed,
|
|
11
|
+
* how long each screen has been running against its typical duration, and what
|
|
12
|
+
* to do next.
|
|
13
|
+
*/
|
|
14
|
+
export const BRANCH_PROGRESS_FILENAME = 'branch.progress.json';
|
|
15
|
+
export const branchProgressPath = (outDir) => (path.join(outDir, BRANCH_PROGRESS_FILENAME));
|
|
16
|
+
export const writeBranchProgress = async (file, record) => {
|
|
17
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
18
|
+
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
19
|
+
try {
|
|
20
|
+
await writeFile(temporary, `${JSON.stringify(record, null, 2)}\n`, {
|
|
21
|
+
encoding: 'utf8',
|
|
22
|
+
flag: 'wx',
|
|
23
|
+
mode: 0o600,
|
|
24
|
+
});
|
|
25
|
+
await rename(temporary, file);
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
await rm(temporary, { force: true });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
export const readBranchProgress = async (file) => {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(await readFile(file, 'utf8'));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
export const branchProgressScreens = (plan, dispatchedAt) => {
|
|
40
|
+
const blocked = new Map(branchBlockedSlots(plan.screens.map((screen) => ({
|
|
41
|
+
slot: screen.slot,
|
|
42
|
+
status: screen.status,
|
|
43
|
+
footer: screen.footer,
|
|
44
|
+
dependsOnSlot: screen.dependsOnSlot,
|
|
45
|
+
}))).map((entry) => [entry.slot, entry]));
|
|
46
|
+
return plan.screens.map((screen) => {
|
|
47
|
+
const block = blocked.get(screen.slot);
|
|
48
|
+
return {
|
|
49
|
+
slot: screen.slot,
|
|
50
|
+
status: block ? 'blocked' : screen.status,
|
|
51
|
+
pageIndex: screen.pageIndex,
|
|
52
|
+
viewportOrdinal: screen.viewportOrdinal,
|
|
53
|
+
...(dispatchedAt[screen.slot] ? { dispatchedAt: dispatchedAt[screen.slot] } : {}),
|
|
54
|
+
...(block
|
|
55
|
+
? { waitingOn: block.waitingOn }
|
|
56
|
+
: screen.status === 'pending' && screen.dependsOnSlot
|
|
57
|
+
? { waitingOn: screen.dependsOnSlot }
|
|
58
|
+
: {}),
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const countScreens = (screens) => ({
|
|
63
|
+
total: screens.length,
|
|
64
|
+
complete: screens.filter((screen) => screen.status === 'succeeded').length,
|
|
65
|
+
generating: screens.filter((screen) => screen.status === 'dispatched').length,
|
|
66
|
+
waiting: screens.filter((screen) => screen.status === 'pending').length,
|
|
67
|
+
blocked: screens.filter((screen) => screen.status === 'blocked').length,
|
|
68
|
+
failed: screens.filter((screen) => screen.status === 'failed').length,
|
|
69
|
+
});
|
|
70
|
+
const generatingDetail = (screens, now) => {
|
|
71
|
+
const running = screens
|
|
72
|
+
.filter((screen) => screen.status === 'dispatched')
|
|
73
|
+
.map((screen) => secondsSince(screen.dispatchedAt, now))
|
|
74
|
+
.filter((seconds) => seconds !== undefined);
|
|
75
|
+
if (running.length === 0)
|
|
76
|
+
return undefined;
|
|
77
|
+
return elapsedAgainstTypical(Math.max(...running), OPERATION_DURATION_HINTS.branchScreen);
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* One line of motion plus, while anything remains, one line of instruction.
|
|
81
|
+
* A terminal report carries neither: there is nothing in flight to narrate and
|
|
82
|
+
* nothing left to check.
|
|
83
|
+
*/
|
|
84
|
+
export const summarizeBranchProgress = (args) => {
|
|
85
|
+
const now = args.now ?? Date.now();
|
|
86
|
+
const counts = countScreens(args.screens);
|
|
87
|
+
const complete = args.phase === 'terminal' || Boolean(args.completion);
|
|
88
|
+
const elapsedSeconds = secondsSince(args.startedAt, now);
|
|
89
|
+
const statusCommand = args.statusCommand ?? `12ui branch status --out-dir ${args.outDir}`;
|
|
90
|
+
if (complete) {
|
|
91
|
+
const settled = args.completion;
|
|
92
|
+
const narrative = settled
|
|
93
|
+
? `Branch run ${settled.runId} finished ${settled.status}:`
|
|
94
|
+
+ ` ${settled.succeededCount} of ${settled.screenCount} screen(s) generated,`
|
|
95
|
+
+ ` ${settled.failedCount} failed, ${settled.blockedCount} blocked.`
|
|
96
|
+
+ ` Screens and pages are on disk under ${settled.outDir}.`
|
|
97
|
+
: `Branch run ${args.runId ?? '(unclaimed)'} is finished; read the completion sentinel.`;
|
|
98
|
+
return {
|
|
99
|
+
outDir: args.outDir,
|
|
100
|
+
...(args.runId ? { runId: args.runId } : {}),
|
|
101
|
+
phase: 'terminal',
|
|
102
|
+
complete: true,
|
|
103
|
+
counts,
|
|
104
|
+
screens: [...args.screens],
|
|
105
|
+
narrative,
|
|
106
|
+
...(args.startedAt ? { startedAt: args.startedAt } : {}),
|
|
107
|
+
...(args.updatedAt ? { updatedAt: args.updatedAt } : {}),
|
|
108
|
+
...(elapsedSeconds === undefined ? {} : { elapsedSeconds: Math.round(elapsedSeconds) }),
|
|
109
|
+
...(settled ? { pages: settled.pages } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const phaseNarrative = args.phase === 'claiming'
|
|
113
|
+
? `Planning the screens (${elapsedAgainstTypical(elapsedSeconds ?? 0, OPERATION_DURATION_HINTS.branchClaim)}); no image bought yet.`
|
|
114
|
+
: args.phase === 'downloading'
|
|
115
|
+
? `Screens settled; downloading ${counts.complete} image(s).`
|
|
116
|
+
: args.phase === 'converting'
|
|
117
|
+
? `Screens on disk; converting each whole page as one package (${formatDuration(OPERATION_DURATION_HINTS.package)} typical per page).`
|
|
118
|
+
: `screens: ${narrateCounts([
|
|
119
|
+
{ label: 'complete', count: counts.complete },
|
|
120
|
+
{
|
|
121
|
+
label: 'generating',
|
|
122
|
+
count: counts.generating,
|
|
123
|
+
...(generatingDetail(args.screens, now) ? { detail: generatingDetail(args.screens, now) } : {}),
|
|
124
|
+
},
|
|
125
|
+
{ label: 'waiting on dependencies', count: counts.waiting },
|
|
126
|
+
{ label: 'blocked', count: counts.blocked },
|
|
127
|
+
{ label: 'failed', count: counts.failed },
|
|
128
|
+
])}`;
|
|
129
|
+
const typicalSeconds = args.phase === 'claiming'
|
|
130
|
+
? OPERATION_DURATION_HINTS.branchClaim
|
|
131
|
+
: args.phase === 'converting'
|
|
132
|
+
? OPERATION_DURATION_HINTS.package
|
|
133
|
+
: OPERATION_DURATION_HINTS.branchScreen;
|
|
134
|
+
return {
|
|
135
|
+
outDir: args.outDir,
|
|
136
|
+
...(args.runId ? { runId: args.runId } : {}),
|
|
137
|
+
phase: args.phase,
|
|
138
|
+
complete: false,
|
|
139
|
+
counts,
|
|
140
|
+
screens: [...args.screens],
|
|
141
|
+
narrative: elapsedSeconds === undefined
|
|
142
|
+
? phaseNarrative
|
|
143
|
+
: `${phaseNarrative} — ${formatDuration(elapsedSeconds)} into the run`,
|
|
144
|
+
nextAction: nextActionLine({
|
|
145
|
+
what: args.phase === 'converting'
|
|
146
|
+
? 'A page conversion'
|
|
147
|
+
: args.phase === 'claiming'
|
|
148
|
+
? 'The plan call'
|
|
149
|
+
: 'Each screen',
|
|
150
|
+
typicalSeconds,
|
|
151
|
+
statusCommand,
|
|
152
|
+
waitHint: 'or leave `12ui branch execute` running, which blocks until the whole run finishes',
|
|
153
|
+
}),
|
|
154
|
+
...(args.startedAt ? { startedAt: args.startedAt } : {}),
|
|
155
|
+
...(args.updatedAt ? { updatedAt: args.updatedAt } : {}),
|
|
156
|
+
...(elapsedSeconds === undefined ? {} : { elapsedSeconds: Math.round(elapsedSeconds) }),
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=branch-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-progress.js","sourceRoot":"","sources":["../src/branch-progress.ts"],"names":[],"mappings":"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"}
|