@hstm-labs/forge-seed-data 0.1.11
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 +37 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/seed-data-stage.d.ts +57 -0
- package/dist/seed-data-stage.d.ts.map +1 -0
- package/dist/seed-data-stage.js +174 -0
- package/dist/seed-data-stage.js.map +1 -0
- package/dist/types.d.ts +54 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +43 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +197 -0
- package/dist/validator.js.map +1 -0
- package/package.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# @hstm-labs/forge-seed-data
|
|
2
|
+
|
|
3
|
+
Seed data generation stage for Forge — produces deterministic seed data files and ORM seed scripts from architecture output, ensuring reproducible data seeding via `randomSeed=42`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @hstm-labs/forge-seed-data
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
### Types
|
|
14
|
+
|
|
15
|
+
- `SeedDataArtifact` — complete seed data output
|
|
16
|
+
- `SeedFile` — raw seed data file (JSON, SQL, CSV)
|
|
17
|
+
- `OrmSeedScript` — ORM-specific seed script
|
|
18
|
+
- `SeedMetadata` — seed generation metadata (entity counts, relationships)
|
|
19
|
+
|
|
20
|
+
### Classes
|
|
21
|
+
|
|
22
|
+
- `SeedDataStage` — pipeline stage implementing `PipelineStage` interface
|
|
23
|
+
- `SeedDataOutputValidator` — validates LLM-produced seed data (enforces determinism via BR-014)
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { SeedDataStage } from '@hstm-labs/forge-seed-data';
|
|
29
|
+
|
|
30
|
+
const stage = new SeedDataStage();
|
|
31
|
+
const result = await stage.execute(input);
|
|
32
|
+
// result.data contains SeedDataArtifact
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## License
|
|
36
|
+
|
|
37
|
+
[MIT](../../LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hstm-labs/forge-seed-data — Seed data generation stage for Forge.
|
|
3
|
+
*
|
|
4
|
+
* Provides the {@link SeedDataStage} pipeline stage, the
|
|
5
|
+
* {@link SeedDataOutputValidator}, and the {@link SeedDataArtifact}
|
|
6
|
+
* type family describing deterministic seed data output.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export type { SeedDataArtifact, SeedFile, OrmSeedScript, SeedMetadata, } from './types.js';
|
|
11
|
+
export { SeedDataStage } from './seed-data-stage.js';
|
|
12
|
+
export { SeedDataOutputValidator } from './validator.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hstm-labs/forge-seed-data — Seed data generation stage for Forge.
|
|
3
|
+
*
|
|
4
|
+
* Provides the {@link SeedDataStage} pipeline stage, the
|
|
5
|
+
* {@link SeedDataOutputValidator}, and the {@link SeedDataArtifact}
|
|
6
|
+
* type family describing deterministic seed data output.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export { SeedDataStage } from './seed-data-stage.js';
|
|
11
|
+
export { SeedDataOutputValidator } from './validator.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data generation pipeline stage.
|
|
3
|
+
*
|
|
4
|
+
* Produces deterministic seed data files (SQL inserts, JSON fixtures)
|
|
5
|
+
* and ORM-specific seed scripts from the architecture data model and
|
|
6
|
+
* specification entities. Enforces BR-014 (fixed random seed for
|
|
7
|
+
* deterministic generation).
|
|
8
|
+
*
|
|
9
|
+
* In API mode, renders prompt templates, calls the LLM via
|
|
10
|
+
* {@link ApiStageExecutor}, validates the output, unpacks individual
|
|
11
|
+
* files, and returns the parsed {@link SeedDataArtifact} in the
|
|
12
|
+
* stage output data.
|
|
13
|
+
*
|
|
14
|
+
* In agent mode, the pipeline runner intercepts before calling
|
|
15
|
+
* `execute()` and exports a prompt via {@link AgentStageExecutor}.
|
|
16
|
+
*/
|
|
17
|
+
import type { StageName } from '@hstm-labs/forge-common';
|
|
18
|
+
import type { PipelineStage, PipelineStageInput, PipelineStageOutput, PipelineContext, AgentPromptContext } from '@hstm-labs/forge-core';
|
|
19
|
+
/**
|
|
20
|
+
* Pipeline stage that generates deterministic seed data.
|
|
21
|
+
*
|
|
22
|
+
* Produces a {@link SeedDataArtifact} containing SQL/JSON seed files,
|
|
23
|
+
* optional ORM seed scripts, and generation metadata. Each element is
|
|
24
|
+
* written as a separate file artifact.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const stage = new SeedDataStage();
|
|
29
|
+
* const output = await stage.execute(input, context);
|
|
30
|
+
* const seedData = output.data?.seedData as SeedDataArtifact;
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class SeedDataStage implements PipelineStage {
|
|
34
|
+
readonly name: StageName;
|
|
35
|
+
readonly dependsOn: StageName[];
|
|
36
|
+
readonly requiresLLM = true;
|
|
37
|
+
/**
|
|
38
|
+
* Return rendered agent-mode prompt context using `seed-data-agent.hbs`.
|
|
39
|
+
*
|
|
40
|
+
* @param input - Input from prior stages
|
|
41
|
+
* @param context - Pipeline context with config, workspace, and runId
|
|
42
|
+
* @returns Agent prompt context with rendered template and output schema
|
|
43
|
+
*/
|
|
44
|
+
getAgentContext(input: PipelineStageInput, context: PipelineContext): AgentPromptContext;
|
|
45
|
+
/**
|
|
46
|
+
* Execute the seed data generation stage.
|
|
47
|
+
*
|
|
48
|
+
* @param input - Input from prior stages (expects validate + architect output)
|
|
49
|
+
* @param context - Pipeline context with config, workspace, and adapter
|
|
50
|
+
* @returns Stage output with seed data artifacts and parsed SeedDataArtifact in data
|
|
51
|
+
* @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
|
|
52
|
+
* @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
|
|
53
|
+
* @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
|
|
54
|
+
*/
|
|
55
|
+
execute(input: PipelineStageInput, context: PipelineContext): Promise<PipelineStageOutput>;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=seed-data-stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-data-stage.d.ts","sourceRoot":"","sources":["../src/seed-data-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EAEf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAU/B;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAc,YAAW,aAAa;IACjD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAe;IACvC,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAiB;IAChD,QAAQ,CAAC,WAAW,QAAQ;IAE5B;;;;;;OAMG;IACH,eAAe,CACb,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,kBAAkB;IAwCrB;;;;;;;;;OASG;IACG,OAAO,CACX,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;CAqJhC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data generation pipeline stage.
|
|
3
|
+
*
|
|
4
|
+
* Produces deterministic seed data files (SQL inserts, JSON fixtures)
|
|
5
|
+
* and ORM-specific seed scripts from the architecture data model and
|
|
6
|
+
* specification entities. Enforces BR-014 (fixed random seed for
|
|
7
|
+
* deterministic generation).
|
|
8
|
+
*
|
|
9
|
+
* In API mode, renders prompt templates, calls the LLM via
|
|
10
|
+
* {@link ApiStageExecutor}, validates the output, unpacks individual
|
|
11
|
+
* files, and returns the parsed {@link SeedDataArtifact} in the
|
|
12
|
+
* stage output data.
|
|
13
|
+
*
|
|
14
|
+
* In agent mode, the pipeline runner intercepts before calling
|
|
15
|
+
* `execute()` and exports a prompt via {@link AgentStageExecutor}.
|
|
16
|
+
*/
|
|
17
|
+
import { join, dirname } from 'node:path';
|
|
18
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
19
|
+
import { ForgeError, ErrorCodes, hashContent } from '@hstm-labs/forge-common';
|
|
20
|
+
import { ApiStageExecutor } from '@hstm-labs/forge-core';
|
|
21
|
+
import { loadProfile } from '@hstm-labs/forge-profiles';
|
|
22
|
+
import { loadTemplate, renderTemplate } from '@hstm-labs/forge-templates';
|
|
23
|
+
import { SeedDataOutputValidator } from './validator.js';
|
|
24
|
+
/**
|
|
25
|
+
* Pipeline stage that generates deterministic seed data.
|
|
26
|
+
*
|
|
27
|
+
* Produces a {@link SeedDataArtifact} containing SQL/JSON seed files,
|
|
28
|
+
* optional ORM seed scripts, and generation metadata. Each element is
|
|
29
|
+
* written as a separate file artifact.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* const stage = new SeedDataStage();
|
|
34
|
+
* const output = await stage.execute(input, context);
|
|
35
|
+
* const seedData = output.data?.seedData as SeedDataArtifact;
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class SeedDataStage {
|
|
39
|
+
name = 'seed-data';
|
|
40
|
+
dependsOn = ['architect'];
|
|
41
|
+
requiresLLM = true;
|
|
42
|
+
/**
|
|
43
|
+
* Return rendered agent-mode prompt context using `seed-data-agent.hbs`.
|
|
44
|
+
*
|
|
45
|
+
* @param input - Input from prior stages
|
|
46
|
+
* @param context - Pipeline context with config, workspace, and runId
|
|
47
|
+
* @returns Agent prompt context with rendered template and output schema
|
|
48
|
+
*/
|
|
49
|
+
getAgentContext(input, context) {
|
|
50
|
+
const parsedSpec = input['validate']?.data?.['parsedSpec'];
|
|
51
|
+
const architecture = input['architect']?.data?.['architecture'];
|
|
52
|
+
const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
|
|
53
|
+
const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'seed-data', 'artifacts');
|
|
54
|
+
const agentTemplate = loadTemplate('seed-data-agent', context.workspace.rootDir);
|
|
55
|
+
const rendered = renderTemplate(agentTemplate, {
|
|
56
|
+
spec: (parsedSpec ?? {}),
|
|
57
|
+
profile: profile,
|
|
58
|
+
architecture: (architecture ?? {}),
|
|
59
|
+
stage: { outputDir },
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
prompt: rendered.content,
|
|
63
|
+
outputSchema: { format: 'json' },
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Execute the seed data generation stage.
|
|
68
|
+
*
|
|
69
|
+
* @param input - Input from prior stages (expects validate + architect output)
|
|
70
|
+
* @param context - Pipeline context with config, workspace, and adapter
|
|
71
|
+
* @returns Stage output with seed data artifacts and parsed SeedDataArtifact in data
|
|
72
|
+
* @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
|
|
73
|
+
* @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
|
|
74
|
+
* @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
|
|
75
|
+
*/
|
|
76
|
+
async execute(input, context) {
|
|
77
|
+
// 1. Get parsed spec from validate stage output
|
|
78
|
+
const validateOutput = input['validate'];
|
|
79
|
+
if (validateOutput === undefined) {
|
|
80
|
+
throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Seed data stage requires 'validate' stage output, but it was not found. " +
|
|
81
|
+
'Ensure the validate stage runs before the seed-data stage.');
|
|
82
|
+
}
|
|
83
|
+
const parsedSpec = validateOutput.data?.['parsedSpec'];
|
|
84
|
+
if (parsedSpec === undefined) {
|
|
85
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Validate stage did not produce a parsed specification in its output data. ' +
|
|
86
|
+
'Ensure the validate stage includes parsedSpec in its data output.');
|
|
87
|
+
}
|
|
88
|
+
// 2. Get architecture from architect stage output
|
|
89
|
+
const architectOutput = input['architect'];
|
|
90
|
+
if (architectOutput === undefined) {
|
|
91
|
+
throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Seed data stage requires 'architect' stage output, but it was not found. " +
|
|
92
|
+
'Ensure the architect stage runs before the seed-data stage.');
|
|
93
|
+
}
|
|
94
|
+
const architecture = architectOutput.data?.['architecture'];
|
|
95
|
+
if (architecture === undefined) {
|
|
96
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Architect stage did not produce an architecture in its output data. ' +
|
|
97
|
+
'Ensure the architect stage includes architecture in its data output.');
|
|
98
|
+
}
|
|
99
|
+
// 3. Load profile
|
|
100
|
+
const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
|
|
101
|
+
// 4. Compute output directory
|
|
102
|
+
const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'seed-data', 'artifacts');
|
|
103
|
+
// 5. Load and render templates
|
|
104
|
+
const systemTemplate = loadTemplate('seed-data-system', context.workspace.rootDir);
|
|
105
|
+
const userTemplate = loadTemplate('seed-data-user', context.workspace.rootDir);
|
|
106
|
+
const templateContext = {
|
|
107
|
+
spec: parsedSpec,
|
|
108
|
+
profile: profile,
|
|
109
|
+
architecture: architecture,
|
|
110
|
+
stage: {
|
|
111
|
+
outputDir,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
const systemPrompt = renderTemplate(systemTemplate, templateContext);
|
|
115
|
+
const userPrompt = renderTemplate(userTemplate, templateContext);
|
|
116
|
+
// 6. Execute via API mode StageExecutor
|
|
117
|
+
if (context.adapter === undefined) {
|
|
118
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Seed data stage requires an LLM adapter in API mode, but none was provided. ' +
|
|
119
|
+
'Configure an LLM provider in forge.config.json or use agent mode.');
|
|
120
|
+
}
|
|
121
|
+
const entityNames = architecture.dataModel.map((e) => e.name);
|
|
122
|
+
const validator = new SeedDataOutputValidator(entityNames);
|
|
123
|
+
const executor = new ApiStageExecutor({
|
|
124
|
+
adapter: context.adapter,
|
|
125
|
+
validator,
|
|
126
|
+
retryPolicy: {
|
|
127
|
+
maxRetries: 3,
|
|
128
|
+
backoffMs: 1000,
|
|
129
|
+
includeErrorInRetry: true,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
const result = await executor.execute({
|
|
133
|
+
prompt: userPrompt.content,
|
|
134
|
+
systemPrompt: systemPrompt.content,
|
|
135
|
+
stageName: 'seed-data',
|
|
136
|
+
outputDir,
|
|
137
|
+
runId: context.runId,
|
|
138
|
+
mode: 'api',
|
|
139
|
+
outputSchema: { format: 'json' },
|
|
140
|
+
});
|
|
141
|
+
// 7. Parse SeedDataArtifact from LLM output
|
|
142
|
+
const rawContent = result.artifacts[0]?.content ?? '';
|
|
143
|
+
const seedDataArtifact = JSON.parse(rawContent);
|
|
144
|
+
// 8. Write individual files to artifacts directory
|
|
145
|
+
const artifacts = [];
|
|
146
|
+
const writeArtifact = (filePath, content) => {
|
|
147
|
+
const fullPath = join(outputDir, filePath);
|
|
148
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
149
|
+
writeFileSync(fullPath, content, 'utf-8');
|
|
150
|
+
artifacts.push({
|
|
151
|
+
filePath,
|
|
152
|
+
content,
|
|
153
|
+
contentHash: hashContent(content),
|
|
154
|
+
sizeBytes: Buffer.byteLength(content, 'utf-8'),
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
// Seed files (SQL inserts, JSON fixtures, etc.)
|
|
158
|
+
for (const seedFile of seedDataArtifact.seedFiles) {
|
|
159
|
+
writeArtifact(seedFile.fileName, seedFile.content);
|
|
160
|
+
}
|
|
161
|
+
// ORM seed scripts
|
|
162
|
+
for (const ormSeed of seedDataArtifact.ormSeeds) {
|
|
163
|
+
writeArtifact(ormSeed.fileName, ormSeed.content);
|
|
164
|
+
}
|
|
165
|
+
// 9. Return PipelineStageOutput with all artifacts and data
|
|
166
|
+
return {
|
|
167
|
+
artifacts,
|
|
168
|
+
data: {
|
|
169
|
+
seedData: seedDataArtifact,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=seed-data-stage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-data-stage.js","sourceRoot":"","sources":["../src/seed-data-stage.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data artifact type definitions for the Forge seed data generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Defines the output schema produced by the seed data generation stage,
|
|
5
|
+
* including SQL/JSON fixture files, ORM-specific seed scripts, and
|
|
6
|
+
* generation metadata.
|
|
7
|
+
*/
|
|
8
|
+
/** Complete seed data output produced by the seed-data stage. */
|
|
9
|
+
export interface SeedDataArtifact {
|
|
10
|
+
/** Database engine the seed data targets. */
|
|
11
|
+
databaseEngine: string;
|
|
12
|
+
/** Seed data files (SQL inserts, JSON fixtures, or script files). */
|
|
13
|
+
seedFiles: SeedFile[];
|
|
14
|
+
/** ORM-specific seed scripts (e.g., Prisma seed.ts). */
|
|
15
|
+
ormSeeds: OrmSeedScript[];
|
|
16
|
+
/** Data generation metadata. */
|
|
17
|
+
metadata: SeedMetadata;
|
|
18
|
+
}
|
|
19
|
+
/** A seed data file for a single entity. */
|
|
20
|
+
export interface SeedFile {
|
|
21
|
+
/** Entity this seed file populates. */
|
|
22
|
+
entity: string;
|
|
23
|
+
/** File format. */
|
|
24
|
+
format: 'sql' | 'json' | 'csv';
|
|
25
|
+
/** File name (e.g., "seed-pets.sql", "pets.json"). */
|
|
26
|
+
fileName: string;
|
|
27
|
+
/** File content. */
|
|
28
|
+
content: string;
|
|
29
|
+
/** Number of records in this file. */
|
|
30
|
+
recordCount: number;
|
|
31
|
+
}
|
|
32
|
+
/** An ORM-specific seed script. */
|
|
33
|
+
export interface OrmSeedScript {
|
|
34
|
+
/** ORM name (e.g., "prisma", "typeorm", "drizzle"). */
|
|
35
|
+
orm: string;
|
|
36
|
+
/** File name (e.g., "seed.ts", "seed.js"). */
|
|
37
|
+
fileName: string;
|
|
38
|
+
/** File content. */
|
|
39
|
+
content: string;
|
|
40
|
+
/** Description. */
|
|
41
|
+
description: string;
|
|
42
|
+
}
|
|
43
|
+
/** Seed data generation metadata. */
|
|
44
|
+
export interface SeedMetadata {
|
|
45
|
+
/** Total number of seed records across all files. */
|
|
46
|
+
totalRecords: number;
|
|
47
|
+
/** Entities covered by seed data. */
|
|
48
|
+
entitiesCovered: string[];
|
|
49
|
+
/** Fixed random seed used for deterministic generation (BR-014). */
|
|
50
|
+
randomSeed: number;
|
|
51
|
+
/** Data volume tier. */
|
|
52
|
+
volumeTier: 'minimal' | 'standard' | 'large';
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,wDAAwD;IACxD,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,gCAAgC;IAChC,QAAQ,EAAE,YAAY,CAAC;CACxB;AAMD,4CAA4C;AAC5C,MAAM,WAAW,QAAQ;IACvB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC/B,sDAAsD;IACtD,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,mCAAmC;AACnC,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,qCAAqC;AACrC,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,UAAU,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;CAC9C"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data artifact type definitions for the Forge seed data generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Defines the output schema produced by the seed data generation stage,
|
|
5
|
+
* including SQL/JSON fixture files, ORM-specific seed scripts, and
|
|
6
|
+
* generation metadata.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data output validator for the Forge seed data generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Validates LLM-generated seed data output against the
|
|
5
|
+
* {@link SeedDataArtifact} schema with structural and semantic checks
|
|
6
|
+
* including entity coverage and determinism verification.
|
|
7
|
+
*/
|
|
8
|
+
import type { OutputValidator, OutputSchema, ValidationResult } from '@hstm-labs/forge-core';
|
|
9
|
+
/**
|
|
10
|
+
* Validator for seed data generation stage output.
|
|
11
|
+
*
|
|
12
|
+
* Performs the following checks:
|
|
13
|
+
* 1. JSON parse validation
|
|
14
|
+
* 2. Required top-level keys
|
|
15
|
+
* 3. Non-empty seedFiles with required fields
|
|
16
|
+
* 4. Entity coverage (every data model entity has a seed file)
|
|
17
|
+
* 5. Metadata totalRecords > 0
|
|
18
|
+
* 6. Metadata entitiesCovered includes all data model entities
|
|
19
|
+
* 7. Metadata randomSeed present (determinism — BR-014)
|
|
20
|
+
* 8. Each seedFile recordCount > 0
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* const validator = new SeedDataOutputValidator(['User', 'Post']);
|
|
25
|
+
* const result = validator.validate(llmOutput, { format: 'json' });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class SeedDataOutputValidator implements OutputValidator {
|
|
29
|
+
private readonly entityNames;
|
|
30
|
+
/**
|
|
31
|
+
* @param entityNames - Entity names from architecture data model for coverage checks
|
|
32
|
+
*/
|
|
33
|
+
constructor(entityNames: string[]);
|
|
34
|
+
/**
|
|
35
|
+
* Validate seed data output against the SeedDataArtifact schema.
|
|
36
|
+
*
|
|
37
|
+
* @param output - Raw LLM output text
|
|
38
|
+
* @param _schema - Output schema (format expected to be 'json')
|
|
39
|
+
* @returns Validation result with descriptive errors
|
|
40
|
+
*/
|
|
41
|
+
validate(output: string, _schema: OutputSchema): ValidationResult;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AAiB/B;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,uBAAwB,YAAW,eAAe;IAC7D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAW;IAEvC;;OAEG;gBACS,WAAW,EAAE,MAAM,EAAE;IAIjC;;;;;;OAMG;IAEH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,gBAAgB;CA+JlE"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seed data output validator for the Forge seed data generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Validates LLM-generated seed data output against the
|
|
5
|
+
* {@link SeedDataArtifact} schema with structural and semantic checks
|
|
6
|
+
* including entity coverage and determinism verification.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const REQUIRED_TOP_LEVEL_KEYS = [
|
|
12
|
+
'databaseEngine',
|
|
13
|
+
'seedFiles',
|
|
14
|
+
'ormSeeds',
|
|
15
|
+
'metadata',
|
|
16
|
+
];
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Implementation
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Validator for seed data generation stage output.
|
|
22
|
+
*
|
|
23
|
+
* Performs the following checks:
|
|
24
|
+
* 1. JSON parse validation
|
|
25
|
+
* 2. Required top-level keys
|
|
26
|
+
* 3. Non-empty seedFiles with required fields
|
|
27
|
+
* 4. Entity coverage (every data model entity has a seed file)
|
|
28
|
+
* 5. Metadata totalRecords > 0
|
|
29
|
+
* 6. Metadata entitiesCovered includes all data model entities
|
|
30
|
+
* 7. Metadata randomSeed present (determinism — BR-014)
|
|
31
|
+
* 8. Each seedFile recordCount > 0
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const validator = new SeedDataOutputValidator(['User', 'Post']);
|
|
36
|
+
* const result = validator.validate(llmOutput, { format: 'json' });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class SeedDataOutputValidator {
|
|
40
|
+
entityNames;
|
|
41
|
+
/**
|
|
42
|
+
* @param entityNames - Entity names from architecture data model for coverage checks
|
|
43
|
+
*/
|
|
44
|
+
constructor(entityNames) {
|
|
45
|
+
this.entityNames = entityNames;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate seed data output against the SeedDataArtifact schema.
|
|
49
|
+
*
|
|
50
|
+
* @param output - Raw LLM output text
|
|
51
|
+
* @param _schema - Output schema (format expected to be 'json')
|
|
52
|
+
* @returns Validation result with descriptive errors
|
|
53
|
+
*/
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
55
|
+
validate(output, _schema) {
|
|
56
|
+
const errors = [];
|
|
57
|
+
// 1. Parse as JSON
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(output);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
errors.push({
|
|
64
|
+
message: 'Seed data output is not valid JSON. Ensure the LLM produces only raw JSON without markdown fences or explanatory text.',
|
|
65
|
+
severity: 'error',
|
|
66
|
+
});
|
|
67
|
+
return { valid: false, errors };
|
|
68
|
+
}
|
|
69
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
70
|
+
errors.push({
|
|
71
|
+
message: 'Seed data output must be a JSON object, not an array or primitive.',
|
|
72
|
+
severity: 'error',
|
|
73
|
+
});
|
|
74
|
+
return { valid: false, errors };
|
|
75
|
+
}
|
|
76
|
+
const obj = parsed;
|
|
77
|
+
// 2. Verify required top-level keys
|
|
78
|
+
for (const key of REQUIRED_TOP_LEVEL_KEYS) {
|
|
79
|
+
if (!(key in obj)) {
|
|
80
|
+
errors.push({
|
|
81
|
+
message: `Missing required top-level key: '${key}'.`,
|
|
82
|
+
path: key,
|
|
83
|
+
severity: 'error',
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (errors.length > 0) {
|
|
88
|
+
return { valid: false, errors };
|
|
89
|
+
}
|
|
90
|
+
// 3. Verify seedFiles is non-empty array with required fields
|
|
91
|
+
const seedFiles = obj['seedFiles'];
|
|
92
|
+
if (!Array.isArray(seedFiles) || seedFiles.length === 0) {
|
|
93
|
+
errors.push({
|
|
94
|
+
message: "Key 'seedFiles' must be a non-empty array of seed file definitions.",
|
|
95
|
+
path: 'seedFiles',
|
|
96
|
+
severity: 'error',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
for (let i = 0; i < seedFiles.length; i++) {
|
|
101
|
+
const sf = seedFiles[i];
|
|
102
|
+
if (sf === undefined || typeof sf !== 'object' || sf === null) {
|
|
103
|
+
errors.push({
|
|
104
|
+
message: `seedFiles[${String(i)}] is not a valid object.`,
|
|
105
|
+
path: `seedFiles[${String(i)}]`,
|
|
106
|
+
severity: 'error',
|
|
107
|
+
});
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
for (const field of ['entity', 'format', 'fileName', 'content']) {
|
|
111
|
+
if (typeof sf[field] !== 'string' || sf[field].length === 0) {
|
|
112
|
+
errors.push({
|
|
113
|
+
message: `seedFiles[${String(i)}] is missing required field '${field}'.`,
|
|
114
|
+
path: `seedFiles[${String(i)}].${field}`,
|
|
115
|
+
severity: 'error',
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// 8. Each recordCount > 0
|
|
120
|
+
if (typeof sf['recordCount'] !== 'number' || sf['recordCount'] <= 0) {
|
|
121
|
+
errors.push({
|
|
122
|
+
message: `seedFiles[${String(i)}] has invalid 'recordCount' — must be a positive number.`,
|
|
123
|
+
path: `seedFiles[${String(i)}].recordCount`,
|
|
124
|
+
severity: 'error',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// 4. Entity coverage — every data model entity has a seed file
|
|
130
|
+
if (Array.isArray(seedFiles) && seedFiles.length > 0) {
|
|
131
|
+
const seedEntities = new Set(seedFiles
|
|
132
|
+
.filter((sf) => typeof sf['entity'] === 'string')
|
|
133
|
+
.map((sf) => sf['entity'].toLowerCase()));
|
|
134
|
+
for (const entityName of this.entityNames) {
|
|
135
|
+
if (!seedEntities.has(entityName.toLowerCase())) {
|
|
136
|
+
errors.push({
|
|
137
|
+
message: `Data model entity '${entityName}' has no seed file. Every entity must have seed data.`,
|
|
138
|
+
path: 'seedFiles',
|
|
139
|
+
severity: 'error',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 5-7. Validate metadata
|
|
145
|
+
const metadata = obj['metadata'];
|
|
146
|
+
if (typeof metadata !== 'object' || metadata === null || Array.isArray(metadata)) {
|
|
147
|
+
errors.push({
|
|
148
|
+
message: "Key 'metadata' must be an object.",
|
|
149
|
+
path: 'metadata',
|
|
150
|
+
severity: 'error',
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
const m = metadata;
|
|
155
|
+
// 5. totalRecords > 0
|
|
156
|
+
if (typeof m['totalRecords'] !== 'number' || m['totalRecords'] <= 0) {
|
|
157
|
+
errors.push({
|
|
158
|
+
message: "metadata.totalRecords must be a positive number.",
|
|
159
|
+
path: 'metadata.totalRecords',
|
|
160
|
+
severity: 'error',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// 6. entitiesCovered includes all data model entities
|
|
164
|
+
if (!Array.isArray(m['entitiesCovered'])) {
|
|
165
|
+
errors.push({
|
|
166
|
+
message: "metadata.entitiesCovered must be an array.",
|
|
167
|
+
path: 'metadata.entitiesCovered',
|
|
168
|
+
severity: 'error',
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const covered = new Set(m['entitiesCovered']
|
|
173
|
+
.filter((e) => typeof e === 'string')
|
|
174
|
+
.map((e) => e.toLowerCase()));
|
|
175
|
+
for (const entityName of this.entityNames) {
|
|
176
|
+
if (!covered.has(entityName.toLowerCase())) {
|
|
177
|
+
errors.push({
|
|
178
|
+
message: `Entity '${entityName}' is missing from metadata.entitiesCovered.`,
|
|
179
|
+
path: 'metadata.entitiesCovered',
|
|
180
|
+
severity: 'error',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// 7. randomSeed present (BR-014)
|
|
186
|
+
if (typeof m['randomSeed'] !== 'number') {
|
|
187
|
+
errors.push({
|
|
188
|
+
message: "metadata.randomSeed must be present as a number for deterministic generation (BR-014).",
|
|
189
|
+
path: 'metadata.randomSeed',
|
|
190
|
+
severity: 'error',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return { valid: errors.length === 0, errors };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hstm-labs/forge-seed-data",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@hstm-labs/forge-common": "0.1.11",
|
|
20
|
+
"@hstm-labs/forge-core": "0.1.11",
|
|
21
|
+
"@hstm-labs/forge-architect": "0.1.11",
|
|
22
|
+
"@hstm-labs/forge-spec-parser": "0.1.11",
|
|
23
|
+
"@hstm-labs/forge-profiles": "0.1.11",
|
|
24
|
+
"@hstm-labs/forge-templates": "0.1.11"
|
|
25
|
+
}
|
|
26
|
+
}
|