@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.
Files changed (172) hide show
  1. package/README.md +35 -9
  2. package/dist/branch-client.d.ts +155 -0
  3. package/dist/branch-client.d.ts.map +1 -0
  4. package/dist/branch-client.js +179 -0
  5. package/dist/branch-client.js.map +1 -0
  6. package/dist/branch-completion.d.ts +37 -0
  7. package/dist/branch-completion.d.ts.map +1 -0
  8. package/dist/branch-completion.js +137 -0
  9. package/dist/branch-completion.js.map +1 -0
  10. package/dist/branch-dispatch-loop.d.ts +84 -0
  11. package/dist/branch-dispatch-loop.d.ts.map +1 -0
  12. package/dist/branch-dispatch-loop.js +206 -0
  13. package/dist/branch-dispatch-loop.js.map +1 -0
  14. package/dist/branch-downloads.d.ts +43 -0
  15. package/dist/branch-downloads.d.ts.map +1 -0
  16. package/dist/branch-downloads.js +94 -0
  17. package/dist/branch-downloads.js.map +1 -0
  18. package/dist/branch-execution-types.d.ts +54 -0
  19. package/dist/branch-execution-types.d.ts.map +1 -0
  20. package/dist/branch-execution-types.js +2 -0
  21. package/dist/branch-execution-types.js.map +1 -0
  22. package/dist/branch-execution.d.ts +18 -0
  23. package/dist/branch-execution.d.ts.map +1 -0
  24. package/dist/branch-execution.js +261 -0
  25. package/dist/branch-execution.js.map +1 -0
  26. package/dist/branch-identity.d.ts +71 -0
  27. package/dist/branch-identity.d.ts.map +1 -0
  28. package/dist/branch-identity.js +72 -0
  29. package/dist/branch-identity.js.map +1 -0
  30. package/dist/branch-materialize.d.ts +22 -0
  31. package/dist/branch-materialize.d.ts.map +1 -0
  32. package/dist/branch-materialize.js +47 -0
  33. package/dist/branch-materialize.js.map +1 -0
  34. package/dist/branch-page-conversion.d.ts +39 -0
  35. package/dist/branch-page-conversion.d.ts.map +1 -0
  36. package/dist/branch-page-conversion.js +206 -0
  37. package/dist/branch-page-conversion.js.map +1 -0
  38. package/dist/branch-plan.d.ts +63 -0
  39. package/dist/branch-plan.d.ts.map +1 -0
  40. package/dist/branch-plan.js +95 -0
  41. package/dist/branch-plan.js.map +1 -0
  42. package/dist/branch-progress.d.ts +75 -0
  43. package/dist/branch-progress.d.ts.map +1 -0
  44. package/dist/branch-progress.js +159 -0
  45. package/dist/branch-progress.js.map +1 -0
  46. package/dist/branch-run-record.d.ts +153 -0
  47. package/dist/branch-run-record.d.ts.map +1 -0
  48. package/dist/branch-run-record.js +94 -0
  49. package/dist/branch-run-record.js.map +1 -0
  50. package/dist/branch-schedule.d.ts +74 -0
  51. package/dist/branch-schedule.d.ts.map +1 -0
  52. package/dist/branch-schedule.js +130 -0
  53. package/dist/branch-schedule.js.map +1 -0
  54. package/dist/branch-status.d.ts +11 -0
  55. package/dist/branch-status.d.ts.map +1 -0
  56. package/dist/branch-status.js +115 -0
  57. package/dist/branch-status.js.map +1 -0
  58. package/dist/branch-viewport-normalization.d.ts +74 -0
  59. package/dist/branch-viewport-normalization.d.ts.map +1 -0
  60. package/dist/branch-viewport-normalization.js +120 -0
  61. package/dist/branch-viewport-normalization.js.map +1 -0
  62. package/dist/cli-arguments.d.ts.map +1 -1
  63. package/dist/cli-arguments.js +4 -0
  64. package/dist/cli-arguments.js.map +1 -1
  65. package/dist/cli-branch-command.d.ts +46 -0
  66. package/dist/cli-branch-command.d.ts.map +1 -0
  67. package/dist/cli-branch-command.js +426 -0
  68. package/dist/cli-branch-command.js.map +1 -0
  69. package/dist/cli-capabilities.d.ts +28 -0
  70. package/dist/cli-capabilities.d.ts.map +1 -1
  71. package/dist/cli-capabilities.js +29 -1
  72. package/dist/cli-capabilities.js.map +1 -1
  73. package/dist/cli-create-command.d.ts +21 -0
  74. package/dist/cli-create-command.d.ts.map +1 -0
  75. package/dist/cli-create-command.js +319 -0
  76. package/dist/cli-create-command.js.map +1 -0
  77. package/dist/cli-detach.d.ts +62 -0
  78. package/dist/cli-detach.d.ts.map +1 -0
  79. package/dist/cli-detach.js +123 -0
  80. package/dist/cli-detach.js.map +1 -0
  81. package/dist/cli-draft-command.d.ts +63 -0
  82. package/dist/cli-draft-command.d.ts.map +1 -0
  83. package/dist/cli-draft-command.js +220 -0
  84. package/dist/cli-draft-command.js.map +1 -0
  85. package/dist/cli-export-command.d.ts.map +1 -1
  86. package/dist/cli-export-command.js +2 -3
  87. package/dist/cli-export-command.js.map +1 -1
  88. package/dist/cli-image-batch-command.d.ts +21 -0
  89. package/dist/cli-image-batch-command.d.ts.map +1 -1
  90. package/dist/cli-image-batch-command.js +65 -4
  91. package/dist/cli-image-batch-command.js.map +1 -1
  92. package/dist/cli-image-batch-resume.d.ts +7 -0
  93. package/dist/cli-image-batch-resume.d.ts.map +1 -1
  94. package/dist/cli-image-batch-resume.js +19 -2
  95. package/dist/cli-image-batch-resume.js.map +1 -1
  96. package/dist/cli-package-command.d.ts +18 -0
  97. package/dist/cli-package-command.d.ts.map +1 -0
  98. package/dist/cli-package-command.js +112 -0
  99. package/dist/cli-package-command.js.map +1 -0
  100. package/dist/cli-progress.d.ts +61 -0
  101. package/dist/cli-progress.d.ts.map +1 -1
  102. package/dist/cli-progress.js +53 -0
  103. package/dist/cli-progress.js.map +1 -1
  104. package/dist/cli-select-command.d.ts +12 -0
  105. package/dist/cli-select-command.d.ts.map +1 -0
  106. package/dist/cli-select-command.js +66 -0
  107. package/dist/cli-select-command.js.map +1 -0
  108. package/dist/cli.js +140 -7
  109. package/dist/cli.js.map +1 -1
  110. package/dist/create-identity.d.ts +25 -0
  111. package/dist/create-identity.d.ts.map +1 -0
  112. package/dist/create-identity.js +0 -0
  113. package/dist/create-identity.js.map +1 -0
  114. package/dist/draft-identity.d.ts +30 -0
  115. package/dist/draft-identity.d.ts.map +1 -0
  116. package/dist/draft-identity.js +0 -0
  117. package/dist/draft-identity.js.map +1 -0
  118. package/dist/draft-prompts.d.ts +35 -0
  119. package/dist/draft-prompts.d.ts.map +1 -0
  120. package/dist/draft-prompts.js +51 -0
  121. package/dist/draft-prompts.js.map +1 -0
  122. package/dist/draft-run.d.ts +32 -0
  123. package/dist/draft-run.d.ts.map +1 -0
  124. package/dist/draft-run.js +152 -0
  125. package/dist/draft-run.js.map +1 -0
  126. package/dist/draft-workspace.d.ts +90 -0
  127. package/dist/draft-workspace.d.ts.map +1 -0
  128. package/dist/draft-workspace.js +64 -0
  129. package/dist/draft-workspace.js.map +1 -0
  130. package/dist/image-batch-status.d.ts +42 -0
  131. package/dist/image-batch-status.d.ts.map +1 -0
  132. package/dist/image-batch-status.js +142 -0
  133. package/dist/image-batch-status.js.map +1 -0
  134. package/dist/image-dimensions.d.ts +12 -0
  135. package/dist/image-dimensions.d.ts.map +1 -0
  136. package/dist/image-dimensions.js +14 -0
  137. package/dist/image-dimensions.js.map +1 -0
  138. package/dist/image-generation-resume.d.ts +13 -0
  139. package/dist/image-generation-resume.d.ts.map +1 -1
  140. package/dist/image-generation-resume.js +13 -0
  141. package/dist/image-generation-resume.js.map +1 -1
  142. package/dist/index.d.ts +5 -0
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +4 -0
  145. package/dist/index.js.map +1 -1
  146. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  147. package/dist/legacy-skill-catalog.js +115 -0
  148. package/dist/legacy-skill-catalog.js.map +1 -1
  149. package/dist/package-manifest-file.d.ts +21 -0
  150. package/dist/package-manifest-file.d.ts.map +1 -0
  151. package/dist/package-manifest-file.js +119 -0
  152. package/dist/package-manifest-file.js.map +1 -0
  153. package/dist/package-manifest-template.d.ts +23 -0
  154. package/dist/package-manifest-template.d.ts.map +1 -0
  155. package/dist/package-manifest-template.js +60 -0
  156. package/dist/package-manifest-template.js.map +1 -0
  157. package/dist/package-submission.d.ts +103 -0
  158. package/dist/package-submission.d.ts.map +1 -0
  159. package/dist/package-submission.js +173 -0
  160. package/dist/package-submission.js.map +1 -0
  161. package/dist/selection-record.d.ts +95 -0
  162. package/dist/selection-record.d.ts.map +1 -0
  163. package/dist/selection-record.js +121 -0
  164. package/dist/selection-record.js.map +1 -0
  165. package/package.json +1 -1
  166. package/skills/design/SKILL.md +40 -266
  167. package/skills/design-branch/SKILL.md +36 -116
  168. package/skills/design-convert/SKILL.md +62 -148
  169. package/skills/design-draft/SKILL.md +71 -135
  170. package/skills/design-search/SKILL.md +29 -78
  171. package/skills/design/references/continuation-contract.md +0 -60
  172. package/skills/design/references/selection-contract.md +0 -112
@@ -0,0 +1,153 @@
1
+ import type { BranchScope } from './branch-identity.js';
2
+ import type { BranchNormalizedPlan } from './branch-plan.js';
3
+ /**
4
+ * The two durable records of a branch run.
5
+ *
6
+ * `branch.attempt.json` is written BEFORE any spend, exclusively, so a plain
7
+ * re-run in the same directory refuses instead of buying a second run; only
8
+ * `--resume` may proceed. `branch.complete.json` is the sentinel: written once,
9
+ * atomically, only at a terminal state. Its ABSENCE means the run is still
10
+ * going — never that it failed. It is deliberately not named
11
+ * `generation.complete.json`, which is `image generate-batch`'s record and a
12
+ * different thing entirely.
13
+ */
14
+ export declare const BRANCH_ATTEMPT_FILENAME = "branch.attempt.json";
15
+ export declare const BRANCH_COMPLETION_FILENAME = "branch.complete.json";
16
+ export declare const BRANCH_PLAN_FILENAME = "branch.plan.json";
17
+ export declare const BRANCH_SCREENS_DIRECTORY = "screens";
18
+ export declare const BRANCH_PAGES_DIRECTORY = "pages";
19
+ export type BranchAttemptStatus = 'claiming' | 'dispatching' | 'downloading' | 'converting' | 'succeeded' | 'partial' | 'failed';
20
+ export type BranchAttempt = {
21
+ version: 1;
22
+ status: BranchAttemptStatus;
23
+ runKey: string;
24
+ runId?: string;
25
+ origin: string;
26
+ scope: BranchScope;
27
+ concept: string;
28
+ conceptSha256: string;
29
+ winner: {
30
+ kind: 'run';
31
+ runId: string;
32
+ slot: string;
33
+ } | {
34
+ kind: 'image';
35
+ imagePath: string;
36
+ sha256: string;
37
+ mediaType: 'image/png' | 'image/jpeg' | 'image/webp';
38
+ };
39
+ aspect?: string;
40
+ maxScreens?: number;
41
+ convert?: {
42
+ output: 'html';
43
+ model: string;
44
+ responsiveQuality?: string;
45
+ };
46
+ sourceConversionId?: string;
47
+ createdAt: string;
48
+ resumedAt?: string[];
49
+ completionPath?: string;
50
+ completedAt?: string;
51
+ errors?: string[];
52
+ };
53
+ export declare const branchAttemptPath: (outDir: string) => string;
54
+ export declare const branchCompletionPath: (outDir: string) => string;
55
+ export declare const branchPlanPath: (outDir: string) => string;
56
+ export declare const writeBranchAttempt: (file: string, attempt: BranchAttempt, exclusive?: boolean) => Promise<void>;
57
+ export declare const readBranchAttempt: (file: string) => Promise<BranchAttempt | undefined>;
58
+ export declare const writeBranchPlanRecord: (file: string, plan: BranchNormalizedPlan) => Promise<void>;
59
+ export type BranchCompletionScreen = {
60
+ slot: string;
61
+ pageIndex: number;
62
+ pageId: string;
63
+ viewportOrdinal: number;
64
+ /** `blocked` is a screen a FAILED dependency put permanently out of reach. */
65
+ status: 'succeeded' | 'failed' | 'blocked';
66
+ direction: string;
67
+ path?: string;
68
+ sha256?: string;
69
+ bytes?: number;
70
+ width?: number;
71
+ height?: number;
72
+ dependsOnSlot?: string;
73
+ footer?: boolean;
74
+ blockedBy?: string;
75
+ blockedReason?: 'dependency' | 'footer-seed';
76
+ error?: {
77
+ code: string;
78
+ message: string;
79
+ };
80
+ };
81
+ export type BranchCompletionPage = {
82
+ index: number;
83
+ id: string;
84
+ kind: 'source' | 'additional';
85
+ title: string;
86
+ slots: string[];
87
+ /** Viewport 1 of a source page is the approved winner, not a generated slot. */
88
+ startsFromWinner: boolean;
89
+ conversion?: {
90
+ status: 'succeeded' | 'failed' | 'skipped';
91
+ reason?: string;
92
+ packageId?: string;
93
+ idempotencyKey?: string;
94
+ conversionId?: string;
95
+ output?: string;
96
+ outFile?: string;
97
+ sha256?: string;
98
+ bytes?: number;
99
+ error?: string;
100
+ /** The width every viewport of this page was reconciled to. */
101
+ canonicalWidth?: number;
102
+ /**
103
+ * Viewports resized to reach it, with both digests. The winner comes from a
104
+ * different canvas than the server's screens, and a page only stitches when
105
+ * they share a width, so the resize is recorded rather than silent.
106
+ */
107
+ normalizedViewports?: {
108
+ id: string;
109
+ fromWidth: number;
110
+ fromHeight: number;
111
+ fromSha256: string;
112
+ toWidth: number;
113
+ toHeight: number;
114
+ toSha256: string;
115
+ }[];
116
+ };
117
+ };
118
+ export type BranchCompletion = {
119
+ version: 1;
120
+ /** `partial` means some screens or pages are missing and were reported. */
121
+ status: 'succeeded' | 'partial' | 'failed';
122
+ runId: string;
123
+ runKey: string;
124
+ workflowRevision: string;
125
+ scope: BranchScope;
126
+ concept: string;
127
+ conceptSha256: string;
128
+ origin: string;
129
+ outDir: string;
130
+ attemptPath: string;
131
+ planPath: string;
132
+ startedAt: string;
133
+ completedAt: string;
134
+ screenCount: number;
135
+ succeededCount: number;
136
+ failedCount: number;
137
+ blockedCount: number;
138
+ /** The approved design the run branched from: viewport 1 of the source page. */
139
+ winner?: {
140
+ path: string;
141
+ sha256: string;
142
+ bytes: number;
143
+ width: number;
144
+ height: number;
145
+ sourceConversionId?: string;
146
+ };
147
+ screens: BranchCompletionScreen[];
148
+ pages: BranchCompletionPage[];
149
+ notes?: string[];
150
+ };
151
+ export declare const writeBranchCompletion: (file: string, completion: BranchCompletion) => Promise<void>;
152
+ export declare const readBranchCompletion: (file: string) => Promise<BranchCompletion | undefined>;
153
+ //# sourceMappingURL=branch-run-record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-run-record.d.ts","sourceRoot":"","sources":["../src/branch-run-record.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ /**
5
+ * The two durable records of a branch run.
6
+ *
7
+ * `branch.attempt.json` is written BEFORE any spend, exclusively, so a plain
8
+ * re-run in the same directory refuses instead of buying a second run; only
9
+ * `--resume` may proceed. `branch.complete.json` is the sentinel: written once,
10
+ * atomically, only at a terminal state. Its ABSENCE means the run is still
11
+ * going — never that it failed. It is deliberately not named
12
+ * `generation.complete.json`, which is `image generate-batch`'s record and a
13
+ * different thing entirely.
14
+ */
15
+ export const BRANCH_ATTEMPT_FILENAME = 'branch.attempt.json';
16
+ export const BRANCH_COMPLETION_FILENAME = 'branch.complete.json';
17
+ export const BRANCH_PLAN_FILENAME = 'branch.plan.json';
18
+ export const BRANCH_SCREENS_DIRECTORY = 'screens';
19
+ export const BRANCH_PAGES_DIRECTORY = 'pages';
20
+ export const branchAttemptPath = (outDir) => (path.join(outDir, BRANCH_ATTEMPT_FILENAME));
21
+ export const branchCompletionPath = (outDir) => (path.join(outDir, BRANCH_COMPLETION_FILENAME));
22
+ export const branchPlanPath = (outDir) => (path.join(outDir, BRANCH_PLAN_FILENAME));
23
+ const writeJsonAtomically = async (file, value) => {
24
+ await mkdir(path.dirname(file), { recursive: true });
25
+ const temporary = `${file}.${randomUUID()}.tmp`;
26
+ try {
27
+ await writeFile(temporary, `${JSON.stringify(value, null, 2)}\n`, {
28
+ encoding: 'utf8',
29
+ flag: 'wx',
30
+ mode: 0o600,
31
+ });
32
+ await rename(temporary, file);
33
+ }
34
+ finally {
35
+ await rm(temporary, { force: true });
36
+ }
37
+ };
38
+ export const writeBranchAttempt = async (file, attempt, exclusive = false) => {
39
+ if (!exclusive) {
40
+ await writeJsonAtomically(file, attempt);
41
+ return;
42
+ }
43
+ await mkdir(path.dirname(file), { recursive: true });
44
+ await writeFile(file, `${JSON.stringify(attempt, null, 2)}\n`, {
45
+ encoding: 'utf8',
46
+ flag: 'wx',
47
+ mode: 0o600,
48
+ });
49
+ };
50
+ export const readBranchAttempt = async (file) => {
51
+ let source;
52
+ try {
53
+ source = await readFile(file, 'utf8');
54
+ }
55
+ catch (error) {
56
+ if (error.code === 'ENOENT')
57
+ return undefined;
58
+ throw error;
59
+ }
60
+ try {
61
+ const value = JSON.parse(source);
62
+ if (typeof value !== 'object' || value === null)
63
+ return undefined;
64
+ return value;
65
+ }
66
+ catch {
67
+ return undefined;
68
+ }
69
+ };
70
+ export const writeBranchPlanRecord = async (file, plan) => {
71
+ await rm(file, { force: true });
72
+ await writeJsonAtomically(file, { version: 1, ...plan });
73
+ };
74
+ export const writeBranchCompletion = async (file, completion) => {
75
+ await writeJsonAtomically(file, completion);
76
+ };
77
+ export const readBranchCompletion = async (file) => {
78
+ let source;
79
+ try {
80
+ source = await readFile(file, 'utf8');
81
+ }
82
+ catch (error) {
83
+ if (error.code === 'ENOENT')
84
+ return undefined;
85
+ throw error;
86
+ }
87
+ try {
88
+ return JSON.parse(source);
89
+ }
90
+ catch {
91
+ return undefined;
92
+ }
93
+ };
94
+ //# sourceMappingURL=branch-run-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-run-record.js","sourceRoot":"","sources":["../src/branch-run-record.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * The branch scheduler — the one place that decides which screens may be
3
+ * dispatched right now. It is a near-verbatim port of the web board's
4
+ * `apps/web/src/pages/branch/branchSchedule.ts`, which in turn mirrors the
5
+ * worker's dispatch gate (`workers/api/src/create/branchReferences.ts`). One
6
+ * policy, three surfaces: the worker stays the authority and answers a nested
7
+ * 409 when any client disagrees.
8
+ *
9
+ * Two rules gate a screen:
10
+ * 1. DEPENDENCY — the previous viewport of the same page must have SUCCEEDED,
11
+ * because it is the screen's continuation reference.
12
+ * 2. FOOTER SEED — the first footer-bearing slot in plan order draws the
13
+ * site's footer with no example; every later footer screen waits for it.
14
+ * Once the seed has FAILED they proceed without it rather than deadlock.
15
+ *
16
+ * Slots are assigned in plan order (page order then viewport order), so slot
17
+ * order IS plan order and the seed is simply the first footer-bearing slot.
18
+ *
19
+ * The one addition over the web copy is `branchBlockedSlots`, which reports the
20
+ * screens `branchRunSettled` counts as terminal-but-unreachable. It derives
21
+ * that from `branchSlotGate` rather than re-deciding it, so there is still only
22
+ * one gate predicate here.
23
+ */
24
+ export type BranchScheduleStatus = 'pending' | 'dispatched' | 'succeeded' | 'failed';
25
+ export type BranchScheduleCandidate = {
26
+ slot: string;
27
+ status: BranchScheduleStatus;
28
+ /** null on non-webpage surfaces, where footer semantics do not apply. */
29
+ footer?: boolean | null;
30
+ dependsOnSlot?: string | null;
31
+ };
32
+ export type BranchSlotGate = {
33
+ ready: true;
34
+ } | {
35
+ ready: false;
36
+ reason: 'dependency' | 'footer-seed';
37
+ waitingOn: string;
38
+ /** The awaited slot failed, so waiting can never resolve on its own. */
39
+ blocked: boolean;
40
+ };
41
+ /** THE footer seed: first footer-bearing slot in plan (= slot) order. */
42
+ export declare const branchFooterSeedSlot: (candidates: readonly BranchScheduleCandidate[]) => string | null;
43
+ /** Whether one screen's references are all in place, and what it waits on. */
44
+ export declare const branchSlotGate: (slot: string, candidates: readonly BranchScheduleCandidate[]) => BranchSlotGate;
45
+ export type BranchScheduleOptions = {
46
+ /** Slots this client already has a dispatch in flight for. */
47
+ inFlight?: ReadonlySet<string>;
48
+ /** Slot -> epoch ms before which a gate-refused slot is not retried. */
49
+ heldUntil?: Readonly<Record<string, number>>;
50
+ now?: number;
51
+ };
52
+ /**
53
+ * Every slot that may be dispatched now: still pending, not already in flight,
54
+ * not inside a gate-refusal backoff, and with both gates satisfied. Settled
55
+ * slots are never rescheduled — a regenerate is always an explicit user action.
56
+ */
57
+ export declare const branchDispatchableSlots: (candidates: readonly BranchScheduleCandidate[], options?: BranchScheduleOptions) => string[];
58
+ /** True while any screen is still expected to move without user action. */
59
+ export declare const branchRunActive: (candidates: readonly BranchScheduleCandidate[]) => boolean;
60
+ /** True once no screen can progress further without a user action. */
61
+ export declare const branchRunSettled: (candidates: readonly BranchScheduleCandidate[]) => boolean;
62
+ export type BranchBlockedSlot = {
63
+ slot: string;
64
+ reason: 'dependency' | 'footer-seed';
65
+ waitingOn: string;
66
+ };
67
+ /**
68
+ * The screens a failed dependency put permanently out of reach. These are the
69
+ * slots `branchRunSettled` treats as terminal without them ever running, so a
70
+ * caller must be able to name them and their cause rather than waiting on a
71
+ * status that will never change.
72
+ */
73
+ export declare const branchBlockedSlots: (candidates: readonly BranchScheduleCandidate[]) => BranchBlockedSlot[];
74
+ //# sourceMappingURL=branch-schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-schedule.d.ts","sourceRoot":"","sources":["../src/branch-schedule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;AAErF,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,oBAAoB,CAAC;IAC7B,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IACA,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,YAAY,GAAG,aAAa,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAIJ,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,GAC/B,YAAY,SAAS,uBAAuB,EAAE,KAC7C,MAAM,GAAG,IAIX,CAAC;AA6EF,8EAA8E;AAC9E,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,YAAY,SAAS,uBAAuB,EAAE,KAC7C,cAKF,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,wEAAwE;IACxE,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,YAAY,SAAS,uBAAuB,EAAE,EAC9C,UAAS,qBAA0B,KAClC,MAAM,EAaR,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,eAAe,GAC1B,YAAY,SAAS,uBAAuB,EAAE,KAC7C,OAA4E,CAAC;AAEhF,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,GAC3B,YAAY,SAAS,uBAAuB,EAAE,KAC7C,OAWF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,GAAG,aAAa,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,YAAY,SAAS,uBAAuB,EAAE,KAC7C,iBAAiB,EAKyC,CAAC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The branch scheduler — the one place that decides which screens may be
3
+ * dispatched right now. It is a near-verbatim port of the web board's
4
+ * `apps/web/src/pages/branch/branchSchedule.ts`, which in turn mirrors the
5
+ * worker's dispatch gate (`workers/api/src/create/branchReferences.ts`). One
6
+ * policy, three surfaces: the worker stays the authority and answers a nested
7
+ * 409 when any client disagrees.
8
+ *
9
+ * Two rules gate a screen:
10
+ * 1. DEPENDENCY — the previous viewport of the same page must have SUCCEEDED,
11
+ * because it is the screen's continuation reference.
12
+ * 2. FOOTER SEED — the first footer-bearing slot in plan order draws the
13
+ * site's footer with no example; every later footer screen waits for it.
14
+ * Once the seed has FAILED they proceed without it rather than deadlock.
15
+ *
16
+ * Slots are assigned in plan order (page order then viewport order), so slot
17
+ * order IS plan order and the seed is simply the first footer-bearing slot.
18
+ *
19
+ * The one addition over the web copy is `branchBlockedSlots`, which reports the
20
+ * screens `branchRunSettled` counts as terminal-but-unreachable. It derives
21
+ * that from `branchSlotGate` rather than re-deciding it, so there is still only
22
+ * one gate predicate here.
23
+ */
24
+ const READY = { ready: true };
25
+ /** THE footer seed: first footer-bearing slot in plan (= slot) order. */
26
+ export const branchFooterSeedSlot = (candidates) => ([...candidates]
27
+ .sort((left, right) => left.slot.localeCompare(right.slot))
28
+ .find((candidate) => candidate.footer === true)?.slot ?? null);
29
+ /**
30
+ * Unreachability is TRANSITIVE. A screen waiting on a screen that itself can
31
+ * never run is just as terminal as one waiting on a screen that already failed
32
+ * — and a footer screen waiting on a seed in that state is the case that
33
+ * deadlocks a run without either of them ever being marked failed.
34
+ */
35
+ const neverSettles = (slot, candidates, bySlot, seen) => {
36
+ if (seen.has(slot))
37
+ return false;
38
+ const candidate = bySlot.get(slot);
39
+ if (!candidate || candidate.status !== 'pending')
40
+ return false;
41
+ const gate = gateFor(slot, candidates, bySlot, new Set(seen).add(slot));
42
+ return !gate.ready && gate.blocked;
43
+ };
44
+ const neverSucceeds = (slot, candidates, bySlot, seen) => {
45
+ const candidate = bySlot.get(slot);
46
+ if (!candidate)
47
+ return false;
48
+ if (candidate.status === 'failed')
49
+ return true;
50
+ return neverSettles(slot, candidates, bySlot, seen);
51
+ };
52
+ const gateFor = (slot, candidates, bySlot, seen) => {
53
+ const candidate = bySlot.get(slot);
54
+ if (!candidate)
55
+ return READY;
56
+ const dependsOn = candidate.dependsOnSlot ?? null;
57
+ if (dependsOn) {
58
+ const dependency = bySlot.get(dependsOn);
59
+ if (!dependency || dependency.status !== 'succeeded') {
60
+ return {
61
+ ready: false,
62
+ reason: 'dependency',
63
+ waitingOn: dependsOn,
64
+ blocked: neverSucceeds(dependsOn, candidates, bySlot, seen),
65
+ };
66
+ }
67
+ }
68
+ if (candidate.footer === true) {
69
+ const seedSlot = branchFooterSeedSlot(candidates);
70
+ if (seedSlot && seedSlot !== slot) {
71
+ const seed = bySlot.get(seedSlot);
72
+ // A failed seed releases the wave: later footers draw without an example.
73
+ // A seed that can never settle at all releases nothing, ever.
74
+ if (seed && seed.status !== 'succeeded' && seed.status !== 'failed') {
75
+ return {
76
+ ready: false,
77
+ reason: 'footer-seed',
78
+ waitingOn: seedSlot,
79
+ blocked: neverSettles(seedSlot, candidates, bySlot, seen),
80
+ };
81
+ }
82
+ }
83
+ }
84
+ return READY;
85
+ };
86
+ /** Whether one screen's references are all in place, and what it waits on. */
87
+ export const branchSlotGate = (slot, candidates) => gateFor(slot, candidates, new Map(candidates.map((candidate) => [candidate.slot, candidate])), new Set());
88
+ /**
89
+ * Every slot that may be dispatched now: still pending, not already in flight,
90
+ * not inside a gate-refusal backoff, and with both gates satisfied. Settled
91
+ * slots are never rescheduled — a regenerate is always an explicit user action.
92
+ */
93
+ export const branchDispatchableSlots = (candidates, options = {}) => {
94
+ const inFlight = options.inFlight ?? new Set();
95
+ const heldUntil = options.heldUntil ?? {};
96
+ const now = options.now ?? Date.now();
97
+ return candidates
98
+ .filter((candidate) => (candidate.status === 'pending'
99
+ && !inFlight.has(candidate.slot)
100
+ && !((heldUntil[candidate.slot] ?? 0) > now)
101
+ && branchSlotGate(candidate.slot, candidates).ready))
102
+ .map((candidate) => candidate.slot)
103
+ .sort((left, right) => left.localeCompare(right));
104
+ };
105
+ /** True while any screen is still expected to move without user action. */
106
+ export const branchRunActive = (candidates) => candidates.some((candidate) => candidate.status === 'dispatched');
107
+ /** True once no screen can progress further without a user action. */
108
+ export const branchRunSettled = (candidates) => (candidates.length > 0
109
+ && candidates.every((candidate) => (candidate.status === 'succeeded'
110
+ || candidate.status === 'failed'
111
+ // A pending screen whose dependency failed will never run itself.
112
+ || (candidate.status === 'pending' && (() => {
113
+ const gate = branchSlotGate(candidate.slot, candidates);
114
+ return !gate.ready && gate.blocked;
115
+ })()))));
116
+ /**
117
+ * The screens a failed dependency put permanently out of reach. These are the
118
+ * slots `branchRunSettled` treats as terminal without them ever running, so a
119
+ * caller must be able to name them and their cause rather than waiting on a
120
+ * status that will never change.
121
+ */
122
+ export const branchBlockedSlots = (candidates) => candidates.flatMap((candidate) => {
123
+ if (candidate.status !== 'pending')
124
+ return [];
125
+ const gate = branchSlotGate(candidate.slot, candidates);
126
+ if (gate.ready || !gate.blocked)
127
+ return [];
128
+ return [{ slot: candidate.slot, reason: gate.reason, waitingOn: gate.waitingOn }];
129
+ }).sort((left, right) => left.slot.localeCompare(right.slot));
130
+ //# sourceMappingURL=branch-schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-schedule.js","sourceRoot":"","sources":["../src/branch-schedule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { BranchRunEnvelope } from './branch-client.js';
2
+ import { type BranchProgressScreen, type BranchStatusReport } from './branch-progress.js';
3
+ /** Fold a live run envelope onto the last local snapshot. */
4
+ export declare const mergeLiveBranchScreens: (screens: readonly BranchProgressScreen[], envelope: BranchRunEnvelope) => BranchProgressScreen[];
5
+ export declare const readBranchStatus: (args: {
6
+ outDir: string;
7
+ /** Optional live read of the run; omitted or failing falls back to disk. */
8
+ refresh?: (runId: string) => Promise<BranchRunEnvelope | null>;
9
+ now?: number;
10
+ }) => Promise<BranchStatusReport>;
11
+ //# sourceMappingURL=branch-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-status.d.ts","sourceRoot":"","sources":["../src/branch-status.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAmC9B,6DAA6D;AAC7D,eAAO,MAAM,sBAAsB,GACjC,SAAS,SAAS,oBAAoB,EAAE,EACxC,UAAU,iBAAiB,KAC1B,oBAAoB,EAkBtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,MAAM;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,KAAG,OAAO,CAAC,kBAAkB,CAsE7B,CAAC"}
@@ -0,0 +1,115 @@
1
+ import path from 'node:path';
2
+ import { branchBlockedSlots } from './branch-schedule.js';
3
+ import { branchProgressPath, readBranchProgress, summarizeBranchProgress, } from './branch-progress.js';
4
+ import { branchAttemptPath, branchCompletionPath, branchPlanPath, readBranchAttempt, readBranchCompletion, } from './branch-run-record.js';
5
+ /**
6
+ * `12ui branch status` — the answer to "is it still going?" that a second
7
+ * session, or the same agent after a sleep, can ask without touching the run.
8
+ * It always narrates motion: which screens are complete, which are generating
9
+ * and for how long against the typical duration, which are waiting on a
10
+ * dependency, and which are permanently blocked. It never answers with bare
11
+ * absence, because that is what makes a caller conclude the run died.
12
+ */
13
+ const phaseFor = (attemptStatus, progressPhase) => {
14
+ if (progressPhase)
15
+ return progressPhase;
16
+ switch (attemptStatus) {
17
+ case 'downloading': return 'downloading';
18
+ case 'converting': return 'converting';
19
+ case 'dispatching': return 'dispatching';
20
+ case 'succeeded':
21
+ case 'partial':
22
+ case 'failed':
23
+ return 'terminal';
24
+ default: return 'claiming';
25
+ }
26
+ };
27
+ /** Fold a live run envelope onto the last local snapshot. */
28
+ export const mergeLiveBranchScreens = (screens, envelope) => {
29
+ const live = new Map(envelope.candidates.map((candidate) => [candidate.slot, candidate]));
30
+ const blocked = new Map(branchBlockedSlots(envelope.candidates.map((candidate) => ({
31
+ slot: candidate.slot,
32
+ status: candidate.status,
33
+ footer: candidate.footer ?? null,
34
+ dependsOnSlot: candidate.dependsOnSlot ?? null,
35
+ }))).map((entry) => [entry.slot, entry]));
36
+ return screens.map((screen) => {
37
+ const candidate = live.get(screen.slot);
38
+ if (!candidate)
39
+ return screen;
40
+ const block = blocked.get(screen.slot);
41
+ return {
42
+ ...screen,
43
+ status: block ? 'blocked' : candidate.status,
44
+ ...(block ? { waitingOn: block.waitingOn } : {}),
45
+ };
46
+ });
47
+ };
48
+ export const readBranchStatus = async (args) => {
49
+ const outDir = path.resolve(args.outDir);
50
+ const attempt = await readBranchAttempt(branchAttemptPath(outDir));
51
+ const completion = await readBranchCompletion(branchCompletionPath(outDir));
52
+ const progress = await readBranchProgress(branchProgressPath(outDir));
53
+ if (!attempt && !completion && !progress) {
54
+ // Never started is not a failure and not a stall. Name the command that
55
+ // starts it rather than reporting an absence the caller has to interpret.
56
+ throw new Error(`This branch run has never been started — there is nothing to report, and nothing has`
57
+ + ` failed. ${outDir} holds no branch attempt, progress, or completion record.`
58
+ + ' Start one with `12ui branch execute --winner-run <crt-id> --winner-slot <slot>'
59
+ + ' --concept <text> --scope page|site --out-dir <directory>`, which blocks for the whole'
60
+ + ' run and streams progress.');
61
+ }
62
+ if (completion) {
63
+ return {
64
+ ...summarizeBranchProgress({
65
+ outDir,
66
+ ...(completion.runId ? { runId: completion.runId } : {}),
67
+ phase: 'terminal',
68
+ screens: (progress?.screens ?? []),
69
+ startedAt: completion.startedAt,
70
+ updatedAt: completion.completedAt,
71
+ completion,
72
+ now: args.now ?? Date.now(),
73
+ }),
74
+ completionPath: branchCompletionPath(outDir),
75
+ planPath: branchPlanPath(outDir),
76
+ };
77
+ }
78
+ const runId = progress?.runId ?? attempt?.runId;
79
+ let screens = progress?.screens ?? [];
80
+ if (runId && args.refresh) {
81
+ try {
82
+ const envelope = await args.refresh(runId);
83
+ if (envelope) {
84
+ screens = screens.length > 0
85
+ ? mergeLiveBranchScreens(screens, envelope)
86
+ : envelope.candidates.map((candidate) => ({
87
+ slot: candidate.slot,
88
+ status: candidate.status,
89
+ pageIndex: candidate.pageIndex ?? 0,
90
+ viewportOrdinal: candidate.viewportOrdinal ?? 0,
91
+ ...(candidate.dependsOnSlot ? { waitingOn: candidate.dependsOnSlot } : {}),
92
+ }));
93
+ }
94
+ }
95
+ catch {
96
+ // A status call must never fail because the network did; the local
97
+ // snapshot is still a truthful account of motion.
98
+ }
99
+ }
100
+ return {
101
+ ...summarizeBranchProgress({
102
+ outDir,
103
+ ...(runId ? { runId } : {}),
104
+ phase: phaseFor(attempt?.status, progress?.phase),
105
+ screens,
106
+ ...(progress?.startedAt ?? attempt?.createdAt
107
+ ? { startedAt: progress?.startedAt ?? attempt.createdAt }
108
+ : {}),
109
+ ...(progress?.updatedAt ? { updatedAt: progress.updatedAt } : {}),
110
+ now: args.now ?? Date.now(),
111
+ }),
112
+ planPath: branchPlanPath(outDir),
113
+ };
114
+ };
115
+ //# sourceMappingURL=branch-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch-status.js","sourceRoot":"","sources":["../src/branch-status.ts"],"names":[],"mappings":"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"}