@gordon.gan/specflow 1.4.4-beta → 1.4.6-beta

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.
@@ -0,0 +1,244 @@
1
+ import { z } from 'zod';
2
+ import type { ApprovalIndex } from './types.js';
3
+ export declare const approvalIndexSchema: z.ZodObject<{
4
+ schema: z.ZodLiteral<"specflow.approval.index/v1">;
5
+ change: z.ZodString;
6
+ generated_at: z.ZodEffects<z.ZodString, string, unknown>;
7
+ mode: z.ZodDefault<z.ZodEnum<["segmented", "monolithic"]>>;
8
+ ui_in_scope: z.ZodDefault<z.ZodBoolean>;
9
+ db_in_scope: z.ZodDefault<z.ZodBoolean>;
10
+ api_in_scope: z.ZodDefault<z.ZodBoolean>;
11
+ optional: z.ZodDefault<z.ZodObject<{
12
+ s5: z.ZodDefault<z.ZodBoolean>;
13
+ s7: z.ZodDefault<z.ZodBoolean>;
14
+ s8: z.ZodDefault<z.ZodBoolean>;
15
+ }, "strip", z.ZodTypeAny, {
16
+ s5: boolean;
17
+ s7: boolean;
18
+ s8: boolean;
19
+ }, {
20
+ s5?: boolean | undefined;
21
+ s7?: boolean | undefined;
22
+ s8?: boolean | undefined;
23
+ }>>;
24
+ parts_order: z.ZodArray<z.ZodString, "many">;
25
+ design_points: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
26
+ decisions: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
27
+ tables: z.ZodDefault<z.ZodArray<z.ZodObject<{
28
+ id: z.ZodString;
29
+ name: z.ZodString;
30
+ action: z.ZodString;
31
+ part: z.ZodString;
32
+ }, "strip", z.ZodTypeAny, {
33
+ id: string;
34
+ name: string;
35
+ action: string;
36
+ part: string;
37
+ }, {
38
+ id: string;
39
+ name: string;
40
+ action: string;
41
+ part: string;
42
+ }>, "many">>;
43
+ interfaces: z.ZodDefault<z.ZodArray<z.ZodObject<{
44
+ id: z.ZodString;
45
+ short: z.ZodString;
46
+ change: z.ZodString;
47
+ part: z.ZodString;
48
+ }, "strip", z.ZodTypeAny, {
49
+ id: string;
50
+ part: string;
51
+ short: string;
52
+ change: string;
53
+ }, {
54
+ id: string;
55
+ part: string;
56
+ short: string;
57
+ change: string;
58
+ }>, "many">>;
59
+ pages: z.ZodDefault<z.ZodArray<z.ZodObject<{
60
+ id: z.ZodString;
61
+ route: z.ZodString;
62
+ apis: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
63
+ part: z.ZodString;
64
+ }, "strip", z.ZodTypeAny, {
65
+ id: string;
66
+ part: string;
67
+ route: string;
68
+ apis: string[];
69
+ }, {
70
+ id: string;
71
+ part: string;
72
+ route: string;
73
+ apis?: string[] | undefined;
74
+ }>, "many">>;
75
+ capabilities: z.ZodDefault<z.ZodArray<z.ZodObject<{
76
+ id: z.ZodString;
77
+ part: z.ZodString;
78
+ }, "strip", z.ZodTypeAny, {
79
+ id: string;
80
+ part: string;
81
+ }, {
82
+ id: string;
83
+ part: string;
84
+ }>, "many">>;
85
+ batching: z.ZodDefault<z.ZodObject<{
86
+ tables_per_call: z.ZodDefault<z.ZodNumber>;
87
+ interfaces_per_call: z.ZodDefault<z.ZodNumber>;
88
+ pages_per_call: z.ZodDefault<z.ZodNumber>;
89
+ capabilities_per_call: z.ZodDefault<z.ZodNumber>;
90
+ }, "strip", z.ZodTypeAny, {
91
+ tables_per_call: number;
92
+ interfaces_per_call: number;
93
+ pages_per_call: number;
94
+ capabilities_per_call: number;
95
+ }, {
96
+ tables_per_call?: number | undefined;
97
+ interfaces_per_call?: number | undefined;
98
+ pages_per_call?: number | undefined;
99
+ capabilities_per_call?: number | undefined;
100
+ }>>;
101
+ conventions: z.ZodDefault<z.ZodObject<{
102
+ architecture: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
103
+ database: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
104
+ api: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
105
+ frontend: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
106
+ }, "strip", z.ZodTypeAny, {
107
+ architecture?: string[] | undefined;
108
+ api?: string[] | undefined;
109
+ database?: string[] | undefined;
110
+ frontend?: string[] | undefined;
111
+ }, {
112
+ architecture?: string[] | undefined;
113
+ api?: string[] | undefined;
114
+ database?: string[] | undefined;
115
+ frontend?: string[] | undefined;
116
+ }>>;
117
+ meta: z.ZodOptional<z.ZodObject<{
118
+ language: z.ZodOptional<z.ZodString>;
119
+ tech_stack: z.ZodOptional<z.ZodString>;
120
+ project_mode: z.ZodOptional<z.ZodString>;
121
+ }, "strip", z.ZodTypeAny, {
122
+ language?: string | undefined;
123
+ tech_stack?: string | undefined;
124
+ project_mode?: string | undefined;
125
+ }, {
126
+ language?: string | undefined;
127
+ tech_stack?: string | undefined;
128
+ project_mode?: string | undefined;
129
+ }>>;
130
+ }, "strip", z.ZodTypeAny, {
131
+ schema: "specflow.approval.index/v1";
132
+ conventions: {
133
+ architecture?: string[] | undefined;
134
+ api?: string[] | undefined;
135
+ database?: string[] | undefined;
136
+ frontend?: string[] | undefined;
137
+ };
138
+ change: string;
139
+ generated_at: string;
140
+ mode: "segmented" | "monolithic";
141
+ ui_in_scope: boolean;
142
+ db_in_scope: boolean;
143
+ api_in_scope: boolean;
144
+ optional: {
145
+ s5: boolean;
146
+ s7: boolean;
147
+ s8: boolean;
148
+ };
149
+ parts_order: string[];
150
+ design_points: string[];
151
+ decisions: string[];
152
+ tables: {
153
+ id: string;
154
+ name: string;
155
+ action: string;
156
+ part: string;
157
+ }[];
158
+ interfaces: {
159
+ id: string;
160
+ part: string;
161
+ short: string;
162
+ change: string;
163
+ }[];
164
+ pages: {
165
+ id: string;
166
+ part: string;
167
+ route: string;
168
+ apis: string[];
169
+ }[];
170
+ capabilities: {
171
+ id: string;
172
+ part: string;
173
+ }[];
174
+ batching: {
175
+ tables_per_call: number;
176
+ interfaces_per_call: number;
177
+ pages_per_call: number;
178
+ capabilities_per_call: number;
179
+ };
180
+ meta?: {
181
+ language?: string | undefined;
182
+ tech_stack?: string | undefined;
183
+ project_mode?: string | undefined;
184
+ } | undefined;
185
+ }, {
186
+ schema: "specflow.approval.index/v1";
187
+ change: string;
188
+ parts_order: string[];
189
+ conventions?: {
190
+ architecture?: string[] | undefined;
191
+ api?: string[] | undefined;
192
+ database?: string[] | undefined;
193
+ frontend?: string[] | undefined;
194
+ } | undefined;
195
+ generated_at?: unknown;
196
+ mode?: "segmented" | "monolithic" | undefined;
197
+ ui_in_scope?: boolean | undefined;
198
+ db_in_scope?: boolean | undefined;
199
+ api_in_scope?: boolean | undefined;
200
+ optional?: {
201
+ s5?: boolean | undefined;
202
+ s7?: boolean | undefined;
203
+ s8?: boolean | undefined;
204
+ } | undefined;
205
+ design_points?: string[] | undefined;
206
+ decisions?: string[] | undefined;
207
+ tables?: {
208
+ id: string;
209
+ name: string;
210
+ action: string;
211
+ part: string;
212
+ }[] | undefined;
213
+ interfaces?: {
214
+ id: string;
215
+ part: string;
216
+ short: string;
217
+ change: string;
218
+ }[] | undefined;
219
+ pages?: {
220
+ id: string;
221
+ part: string;
222
+ route: string;
223
+ apis?: string[] | undefined;
224
+ }[] | undefined;
225
+ capabilities?: {
226
+ id: string;
227
+ part: string;
228
+ }[] | undefined;
229
+ batching?: {
230
+ tables_per_call?: number | undefined;
231
+ interfaces_per_call?: number | undefined;
232
+ pages_per_call?: number | undefined;
233
+ capabilities_per_call?: number | undefined;
234
+ } | undefined;
235
+ meta?: {
236
+ language?: string | undefined;
237
+ tech_stack?: string | undefined;
238
+ project_mode?: string | undefined;
239
+ } | undefined;
240
+ }>;
241
+ export declare function parseApprovalIndex(raw: unknown): ApprovalIndex;
242
+ /** Returns true when segmented fast-path (monolithic) is allowed. */
243
+ export declare function isLightweightApproval(index: ApprovalIndex): boolean;
244
+ export declare function shouldForceSegmented(index: ApprovalIndex): boolean;
@@ -0,0 +1,90 @@
1
+ import { z } from 'zod';
2
+ const tableRefSchema = z.object({
3
+ id: z.string().min(1),
4
+ name: z.string().min(1),
5
+ action: z.string().min(1),
6
+ part: z.string().min(1),
7
+ });
8
+ const interfaceRefSchema = z.object({
9
+ id: z.string().min(1),
10
+ short: z.string().min(1),
11
+ change: z.string().min(1),
12
+ part: z.string().min(1),
13
+ });
14
+ const pageRefSchema = z.object({
15
+ id: z.string().min(1),
16
+ route: z.string().min(1),
17
+ apis: z.array(z.string()).default([]),
18
+ part: z.string().min(1),
19
+ });
20
+ const capabilityRefSchema = z.object({
21
+ id: z.string().min(1),
22
+ part: z.string().min(1),
23
+ });
24
+ export const approvalIndexSchema = z.object({
25
+ schema: z.literal('specflow.approval.index/v1'),
26
+ change: z.string().min(1),
27
+ generated_at: z.preprocess((val) => (val instanceof Date ? val.toISOString() : val), z.string().min(1)),
28
+ mode: z.enum(['segmented', 'monolithic']).default('segmented'),
29
+ ui_in_scope: z.boolean().default(false),
30
+ db_in_scope: z.boolean().default(false),
31
+ api_in_scope: z.boolean().default(false),
32
+ optional: z
33
+ .object({
34
+ s5: z.boolean().default(false),
35
+ s7: z.boolean().default(false),
36
+ s8: z.boolean().default(false),
37
+ })
38
+ .default({ s5: false, s7: false, s8: false }),
39
+ parts_order: z.array(z.string().min(1)).min(1),
40
+ design_points: z.array(z.string()).default([]),
41
+ decisions: z.array(z.string()).default([]),
42
+ tables: z.array(tableRefSchema).default([]),
43
+ interfaces: z.array(interfaceRefSchema).default([]),
44
+ pages: z.array(pageRefSchema).default([]),
45
+ capabilities: z.array(capabilityRefSchema).default([]),
46
+ batching: z
47
+ .object({
48
+ tables_per_call: z.number().int().positive().default(3),
49
+ interfaces_per_call: z.number().int().positive().default(3),
50
+ pages_per_call: z.number().int().positive().default(3),
51
+ capabilities_per_call: z.number().int().positive().default(1),
52
+ })
53
+ .default({
54
+ tables_per_call: 3,
55
+ interfaces_per_call: 3,
56
+ pages_per_call: 3,
57
+ capabilities_per_call: 1,
58
+ }),
59
+ conventions: z
60
+ .object({
61
+ architecture: z.array(z.string()).optional(),
62
+ database: z.array(z.string()).optional(),
63
+ api: z.array(z.string()).optional(),
64
+ frontend: z.array(z.string()).optional(),
65
+ })
66
+ .default({}),
67
+ meta: z
68
+ .object({
69
+ language: z.string().optional(),
70
+ tech_stack: z.string().optional(),
71
+ project_mode: z.string().optional(),
72
+ })
73
+ .optional(),
74
+ });
75
+ export function parseApprovalIndex(raw) {
76
+ return approvalIndexSchema.parse(raw);
77
+ }
78
+ /** Returns true when segmented fast-path (monolithic) is allowed. */
79
+ export function isLightweightApproval(index) {
80
+ return (index.tables.length <= 2 &&
81
+ index.interfaces.length <= 3 &&
82
+ index.pages.length <= 2 &&
83
+ !index.optional.s5);
84
+ }
85
+ export function shouldForceSegmented(index) {
86
+ if (index.mode === 'monolithic') {
87
+ return false;
88
+ }
89
+ return !isLightweightApproval(index);
90
+ }
@@ -0,0 +1,4 @@
1
+ export type { ApprovalAssembleResult, ApprovalDiagnostic, ApprovalIndex, ApprovalManifest, ApprovalGenerationMode, } from './types.js';
2
+ export { parseApprovalIndex, isLightweightApproval, shouldForceSegmented, approvalIndexSchema, } from './index-schema.js';
3
+ export { getChangeDirectory, getApprovalWorkspaceDir, getApprovalIndexPath, getApprovalManifestPath, getApprovalPartsDir, getApprovalPartPath, getApprovalOutputPath, getApprovalAnalysisPath, } from './paths.js';
4
+ export { assembleApprovalDocument, readApprovalIndex, readApprovalManifest, } from './assemble.js';
@@ -0,0 +1,3 @@
1
+ export { parseApprovalIndex, isLightweightApproval, shouldForceSegmented, approvalIndexSchema, } from './index-schema.js';
2
+ export { getChangeDirectory, getApprovalWorkspaceDir, getApprovalIndexPath, getApprovalManifestPath, getApprovalPartsDir, getApprovalPartPath, getApprovalOutputPath, getApprovalAnalysisPath, } from './paths.js';
3
+ export { assembleApprovalDocument, readApprovalIndex, readApprovalManifest, } from './assemble.js';
@@ -0,0 +1,8 @@
1
+ export declare function getChangeDirectory(projectRoot: string, changeName: string): string;
2
+ export declare function getApprovalWorkspaceDir(changeDir: string): string;
3
+ export declare function getApprovalIndexPath(changeDir: string): string;
4
+ export declare function getApprovalManifestPath(changeDir: string): string;
5
+ export declare function getApprovalPartsDir(changeDir: string): string;
6
+ export declare function getApprovalPartPath(changeDir: string, partId: string): string;
7
+ export declare function getApprovalOutputPath(changeDir: string): string;
8
+ export declare function getApprovalAnalysisPath(changeDir: string): string;
@@ -0,0 +1,28 @@
1
+ import { join } from 'node:path';
2
+ import { validateChangeName } from '../../utils/change-utils.js';
3
+ const CHANGES_REL = 'specflow/changes';
4
+ export function getChangeDirectory(projectRoot, changeName) {
5
+ validateChangeName(changeName);
6
+ return join(projectRoot, CHANGES_REL, changeName);
7
+ }
8
+ export function getApprovalWorkspaceDir(changeDir) {
9
+ return join(changeDir, 'approval');
10
+ }
11
+ export function getApprovalIndexPath(changeDir) {
12
+ return join(getApprovalWorkspaceDir(changeDir), 'index.yaml');
13
+ }
14
+ export function getApprovalManifestPath(changeDir) {
15
+ return join(getApprovalWorkspaceDir(changeDir), 'manifest.json');
16
+ }
17
+ export function getApprovalPartsDir(changeDir) {
18
+ return join(getApprovalWorkspaceDir(changeDir), 'parts');
19
+ }
20
+ export function getApprovalPartPath(changeDir, partId) {
21
+ return join(getApprovalPartsDir(changeDir), `${partId}.md`);
22
+ }
23
+ export function getApprovalOutputPath(changeDir) {
24
+ return join(changeDir, 'approval.md');
25
+ }
26
+ export function getApprovalAnalysisPath(changeDir) {
27
+ return join(getApprovalWorkspaceDir(changeDir), 'analysis.json');
28
+ }
@@ -0,0 +1,92 @@
1
+ export type ApprovalGenerationMode = 'segmented' | 'monolithic';
2
+ export type ApprovalPartStatus = 'draft' | 'ok' | 'retry';
3
+ export interface ApprovalOptionalChapters {
4
+ readonly s5: boolean;
5
+ readonly s7: boolean;
6
+ readonly s8: boolean;
7
+ }
8
+ export interface ApprovalBatching {
9
+ readonly tables_per_call: number;
10
+ readonly interfaces_per_call: number;
11
+ readonly pages_per_call: number;
12
+ readonly capabilities_per_call: number;
13
+ }
14
+ export interface ApprovalTableRef {
15
+ readonly id: string;
16
+ readonly name: string;
17
+ readonly action: string;
18
+ readonly part: string;
19
+ }
20
+ export interface ApprovalInterfaceRef {
21
+ readonly id: string;
22
+ readonly short: string;
23
+ readonly change: string;
24
+ readonly part: string;
25
+ }
26
+ export interface ApprovalPageRef {
27
+ readonly id: string;
28
+ readonly route: string;
29
+ readonly apis: readonly string[];
30
+ readonly part: string;
31
+ }
32
+ export interface ApprovalCapabilityRef {
33
+ readonly id: string;
34
+ readonly part: string;
35
+ }
36
+ export interface ApprovalConventionsResolved {
37
+ readonly architecture?: readonly string[];
38
+ readonly database?: readonly string[];
39
+ readonly api?: readonly string[];
40
+ readonly frontend?: readonly string[];
41
+ }
42
+ export interface ApprovalIndex {
43
+ readonly schema: 'specflow.approval.index/v1';
44
+ readonly change: string;
45
+ readonly generated_at: string;
46
+ readonly mode: ApprovalGenerationMode;
47
+ readonly ui_in_scope: boolean;
48
+ readonly db_in_scope: boolean;
49
+ readonly api_in_scope: boolean;
50
+ readonly optional: ApprovalOptionalChapters;
51
+ readonly parts_order: readonly string[];
52
+ readonly design_points: readonly string[];
53
+ readonly decisions: readonly string[];
54
+ readonly tables: readonly ApprovalTableRef[];
55
+ readonly interfaces: readonly ApprovalInterfaceRef[];
56
+ readonly pages: readonly ApprovalPageRef[];
57
+ readonly capabilities: readonly ApprovalCapabilityRef[];
58
+ readonly batching: ApprovalBatching;
59
+ readonly conventions: ApprovalConventionsResolved;
60
+ readonly meta?: {
61
+ readonly language?: string;
62
+ readonly tech_stack?: string;
63
+ readonly project_mode?: string;
64
+ };
65
+ }
66
+ export interface ApprovalManifestPart {
67
+ readonly id: string;
68
+ readonly path: string;
69
+ readonly status: ApprovalPartStatus;
70
+ readonly sha256?: string;
71
+ readonly updated_at?: string;
72
+ }
73
+ export interface ApprovalManifest {
74
+ readonly schema: 'specflow.approval.manifest/v1';
75
+ readonly change: string;
76
+ readonly parts: readonly ApprovalManifestPart[];
77
+ readonly assembled_at?: string;
78
+ readonly approval_sha256?: string;
79
+ }
80
+ export type ApprovalDiagnosticSeverity = 'error' | 'warning';
81
+ export interface ApprovalDiagnostic {
82
+ readonly code: string;
83
+ readonly severity: ApprovalDiagnosticSeverity;
84
+ readonly message: string;
85
+ readonly part?: string;
86
+ }
87
+ export interface ApprovalAssembleResult {
88
+ readonly markdown?: string;
89
+ readonly outputPath?: string;
90
+ readonly diagnostics: readonly ApprovalDiagnostic[];
91
+ readonly ok: boolean;
92
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gordon.gan/specflow",
3
- "version": "1.4.4-beta",
3
+ "version": "1.4.6-beta",
4
4
  "type": "module",
5
5
  "description": "SpecFlow — unified spec-driven development: OpenSpec planning + Superpowers execution in one CLI and cross-IDE workflow",
6
6
  "keywords": [