@hstm-labs/forge-deliverer 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 ADDED
@@ -0,0 +1,44 @@
1
+ # @hstm-labs/forge-deliverer
2
+
3
+ Output packaging and delivery for Forge — merges artifacts from all generation stages, validates self-containment, creates compressed archives, and writes deliverables to configurable targets.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hstm-labs/forge-deliverer
9
+ ```
10
+
11
+ ## Public API
12
+
13
+ ### Types
14
+
15
+ - `DeliveryResult` — complete delivery output with manifest and archive path
16
+ - `DeliveryManifest`, `DeliveryStageEntry` — manifest tracking all delivered files
17
+ - `SelfContainmentResult`, `SelfContainmentCheck` — self-containment validation
18
+ - `DeliveryOptions` — delivery configuration
19
+
20
+ ### Classes
21
+
22
+ - `DeliverStage` — pipeline stage implementing `PipelineStage` interface
23
+
24
+ ### Functions
25
+
26
+ - `mergeArtifacts(stageOutputs)` — merge artifacts from all pipeline stages
27
+ - `validateSelfContainment(outputDir)` — verify no dangling imports/references
28
+ - `createArchive(outputDir, archivePath)` — create .tgz archive
29
+ - `deliverToTarget(archive, target)` — write to configured delivery target
30
+ - `formatDeliveryResult()`, `deliveryResultToJson()` — output formatters
31
+
32
+ ## Usage
33
+
34
+ ```typescript
35
+ import { DeliverStage } from '@hstm-labs/forge-deliverer';
36
+
37
+ const stage = new DeliverStage();
38
+ const result = await stage.execute(input);
39
+ console.log(`Delivered to: ${result.data.archivePath}`);
40
+ ```
41
+
42
+ ## License
43
+
44
+ [MIT](../../LICENSE)
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Archive creation for the Forge delivery stage.
3
+ *
4
+ * Creates a tgz or zip archive from the staging directory,
5
+ * excluding `.git`, `node_modules`, and `.DS_Store`.
6
+ */
7
+ /**
8
+ * Create an archive from the staging directory.
9
+ *
10
+ * Uses the system `tar` command for tgz archives. Falls back
11
+ * gracefully with a warning if archive creation fails.
12
+ *
13
+ * @param stagingDir - Source directory to archive
14
+ * @param outputPath - Full path for the output archive file
15
+ * @param format - Archive format: 'tgz' or 'zip'
16
+ * @returns Archive path and size in bytes
17
+ * @throws {ForgeError} FORGE-DLVR-001 if archive creation fails
18
+ */
19
+ export declare function createArchive(stagingDir: string, outputPath: string, format: 'tgz' | 'zip'): Promise<{
20
+ archivePath: string;
21
+ sizeBytes: number;
22
+ }>;
23
+ //# sourceMappingURL=archiver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archiver.d.ts","sourceRoot":"","sources":["../src/archiver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,KAAK,GAAG,KAAK,GACpB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BrD"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Archive creation for the Forge delivery stage.
3
+ *
4
+ * Creates a tgz or zip archive from the staging directory,
5
+ * excluding `.git`, `node_modules`, and `.DS_Store`.
6
+ */
7
+ import { execSync } from 'node:child_process';
8
+ import { statSync } from 'node:fs';
9
+ import { ForgeError, ErrorCodes } from '@hstm-labs/forge-common';
10
+ // ---------------------------------------------------------------------------
11
+ // Public API
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Create an archive from the staging directory.
15
+ *
16
+ * Uses the system `tar` command for tgz archives. Falls back
17
+ * gracefully with a warning if archive creation fails.
18
+ *
19
+ * @param stagingDir - Source directory to archive
20
+ * @param outputPath - Full path for the output archive file
21
+ * @param format - Archive format: 'tgz' or 'zip'
22
+ * @returns Archive path and size in bytes
23
+ * @throws {ForgeError} FORGE-DLVR-001 if archive creation fails
24
+ */
25
+ export async function createArchive(stagingDir, outputPath, format) {
26
+ try {
27
+ if (format === 'tgz') {
28
+ execSync(`tar -czf "${outputPath}" --exclude='.git' --exclude='node_modules' --exclude='.DS_Store' -C "${stagingDir}" .`, { stdio: 'pipe' });
29
+ }
30
+ else {
31
+ execSync(`zip -r "${outputPath}" . -x '.git/*' -x 'node_modules/*' -x '.DS_Store'`, { cwd: stagingDir, stdio: 'pipe' });
32
+ }
33
+ const stat = statSync(outputPath);
34
+ return { archivePath: outputPath, sizeBytes: stat.size };
35
+ }
36
+ catch (error) {
37
+ const cause = error instanceof Error ? error : undefined;
38
+ throw new ForgeError(ErrorCodes.DLVR.PACKAGING_FAILURE, `Failed to create ${format} archive at '${outputPath}'. ` +
39
+ 'Ensure tar/zip is available on your system. ' +
40
+ `Error: ${cause?.message ?? 'Unknown error'}`, cause !== undefined ? { cause } : undefined);
41
+ }
42
+ }
43
+ //# sourceMappingURL=archiver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archiver.js","sourceRoot":"","sources":["../src/archiver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEjE,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,UAAkB,EAClB,UAAkB,EAClB,MAAqB;IAErB,IAAI,CAAC;QACH,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;YACrB,QAAQ,CACN,aAAa,UAAU,yEAAyE,UAAU,KAAK,EAC/G,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,QAAQ,CACN,WAAW,UAAU,oDAAoD,EACzE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CACnC,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;QAClC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3D,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;QACzD,MAAM,IAAI,UAAU,CAClB,UAAU,CAAC,IAAI,CAAC,iBAAiB,EACjC,oBAAoB,MAAM,gBAAgB,UAAU,KAAK;YACvD,8CAA8C;YAC9C,UAAU,KAAK,EAAE,OAAO,IAAI,eAAe,EAAE,EAC/C,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAC5C,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Artifact merger for the Forge delivery stage.
3
+ *
4
+ * Merges generated artifacts from all pipeline stages into a cohesive
5
+ * project structure in a target directory (staging or project root).
6
+ * For layouts like scalable-monorepo, service grouping (e.g. services/identity/...)
7
+ * is achieved by generator-emitted artifact paths under the stage's target base.
8
+ */
9
+ import type { StageName, Workspace, RunStore } from '@hstm-labs/forge-common';
10
+ import type { DeliveryStageEntry } from './types.js';
11
+ /**
12
+ * Merge artifacts from all pipeline stages into a target directory.
13
+ *
14
+ * Reads artifact files from their on-disk locations and copies them
15
+ * into a project-like directory structure using the layout's stage mapping.
16
+ *
17
+ * @param workspace - Resolved workspace paths
18
+ * @param runId - Run ID to merge artifacts for
19
+ * @param store - RunStore for artifact metadata
20
+ * @param stageMapping - Maps stage name to target directory (from project layout)
21
+ * @param targetDir - Directory to merge into (e.g. staging dir or project root)
22
+ * @returns Stage entries for the manifest
23
+ */
24
+ export declare function mergeArtifacts(workspace: Workspace, runId: string, store: RunStore, stageMapping: Partial<Record<StageName, string>>, targetDir: string): {
25
+ stageEntries: DeliveryStageEntry[];
26
+ };
27
+ //# sourceMappingURL=artifact-merger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-merger.d.ts","sourceRoot":"","sources":["../src/artifact-merger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAMrD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,QAAQ,EACf,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,EAChD,SAAS,EAAE,MAAM,GAChB;IAAE,YAAY,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAsDxC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Artifact merger for the Forge delivery stage.
3
+ *
4
+ * Merges generated artifacts from all pipeline stages into a cohesive
5
+ * project structure in a target directory (staging or project root).
6
+ * For layouts like scalable-monorepo, service grouping (e.g. services/identity/...)
7
+ * is achieved by generator-emitted artifact paths under the stage's target base.
8
+ */
9
+ import { join } from 'node:path';
10
+ import { mkdirSync, readFileSync, writeFileSync, existsSync } from 'node:fs';
11
+ // ---------------------------------------------------------------------------
12
+ // Public API
13
+ // ---------------------------------------------------------------------------
14
+ /**
15
+ * Merge artifacts from all pipeline stages into a target directory.
16
+ *
17
+ * Reads artifact files from their on-disk locations and copies them
18
+ * into a project-like directory structure using the layout's stage mapping.
19
+ *
20
+ * @param workspace - Resolved workspace paths
21
+ * @param runId - Run ID to merge artifacts for
22
+ * @param store - RunStore for artifact metadata
23
+ * @param stageMapping - Maps stage name to target directory (from project layout)
24
+ * @param targetDir - Directory to merge into (e.g. staging dir or project root)
25
+ * @returns Stage entries for the manifest
26
+ */
27
+ export function mergeArtifacts(workspace, runId, store, stageMapping, targetDir) {
28
+ mkdirSync(targetDir, { recursive: true });
29
+ const stageEntries = [];
30
+ const stages = store.getStages(runId);
31
+ for (const stage of stages) {
32
+ if (stage.status !== 'COMPLETED')
33
+ continue;
34
+ const artifacts = store.getArtifacts(runId, stage.stageName);
35
+ if (artifacts.length === 0)
36
+ continue;
37
+ const stageTargetDir = stageMapping[stage.stageName];
38
+ if (stageTargetDir === undefined)
39
+ continue;
40
+ const files = [];
41
+ for (const artifact of artifacts) {
42
+ const sourcePath = join(workspace.forgeDir, 'runs', runId, 'stages', artifact.stageName, 'artifacts', artifact.filePath);
43
+ // Determine target file path within target directory
44
+ const relativeTarget = stageTargetDir === '.'
45
+ ? artifact.filePath
46
+ : join(stageTargetDir, artifact.filePath);
47
+ const destPath = join(targetDir, relativeTarget);
48
+ const destDir = join(destPath, '..');
49
+ mkdirSync(destDir, { recursive: true });
50
+ if (existsSync(sourcePath)) {
51
+ const content = readFileSync(sourcePath);
52
+ writeFileSync(destPath, content);
53
+ }
54
+ files.push(relativeTarget);
55
+ }
56
+ stageEntries.push({
57
+ stageName: stage.stageName,
58
+ artifactCount: files.length,
59
+ files,
60
+ });
61
+ }
62
+ return { stageEntries };
63
+ }
64
+ //# sourceMappingURL=artifact-merger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-merger.js","sourceRoot":"","sources":["../src/artifact-merger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI7E,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAoB,EACpB,KAAa,EACb,KAAe,EACf,YAAgD,EAChD,SAAiB;IAEjB,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE1C,MAAM,YAAY,GAAyB,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW;YAAE,SAAS;QAE3C,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAErC,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,SAAsB,CAAC,CAAC;QAClE,IAAI,cAAc,KAAK,SAAS;YAAE,SAAS;QAE3C,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,IAAI,CACrB,SAAS,CAAC,QAAQ,EAClB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,QAAQ,CAAC,SAAS,EAClB,WAAW,EACX,QAAQ,CAAC,QAAQ,CAClB,CAAC;YAEF,qDAAqD;YACrD,MAAM,cAAc,GAClB,cAAc,KAAK,GAAG;gBACpB,CAAC,CAAC,QAAQ,CAAC,QAAQ;gBACnB,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAE9C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAExC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3B,MAAM,OAAO,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;gBACzC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACnC,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC7B,CAAC;QAED,YAAY,CAAC,IAAI,CAAC;YAChB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,aAAa,EAAE,KAAK,CAAC,MAAM;YAC3B,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * DeliverStage — final pipeline stage that packages and delivers
3
+ * all generated artifacts.
4
+ *
5
+ * Merges artifacts from all completed stages into a cohesive project
6
+ * structure, validates self-containment, creates an archive, and
7
+ * delivers to a target directory.
8
+ */
9
+ import type { StageName } from '@hstm-labs/forge-common';
10
+ import type { PipelineStage, PipelineStageInput, PipelineStageOutput, PipelineContext } from '@hstm-labs/forge-core';
11
+ /**
12
+ * Pipeline stage that packages and delivers all generated artifacts.
13
+ *
14
+ * This is the final stage in the Forge pipeline. It:
15
+ * 1. Merges artifacts from all completed stages into a project structure
16
+ * 2. Generates minimal package.json and README.md if missing
17
+ * 3. Validates self-containment
18
+ * 4. Delivers to a target directory
19
+ * 5. Creates an archive (tgz)
20
+ * 6. Writes a delivery manifest
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const stage = new DeliverStage();
25
+ * const output = await stage.execute(input, context);
26
+ * const result = output.data?.delivery as DeliveryResult;
27
+ * ```
28
+ */
29
+ export declare class DeliverStage implements PipelineStage {
30
+ readonly name: StageName;
31
+ readonly dependsOn: StageName[];
32
+ readonly requiresLLM = false;
33
+ /**
34
+ * Execute the delivery stage.
35
+ *
36
+ * @param _input - Pipeline stage input (not used — reads from disk)
37
+ * @param context - Pipeline context with config, workspace, and store
38
+ * @returns Stage output with delivery manifest and DeliveryResult in data
39
+ * @throws {ForgeError} FORGE-PIPE-001 if store is missing
40
+ * @throws {ForgeError} FORGE-DLVR-001 if archive creation fails
41
+ */
42
+ execute(_input: PipelineStageInput, context: PipelineContext): Promise<PipelineStageOutput>;
43
+ }
44
+ //# sourceMappingURL=deliver-stage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver-stage.d.ts","sourceRoot":"","sources":["../src/deliver-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAOzD,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAmG/B;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,YAAa,YAAW,aAAa;IAChD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAa;IACrC,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAc;IAC7C,QAAQ,CAAC,WAAW,SAAS;IAE7B;;;;;;;;OAQG;IACG,OAAO,CACX,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;CA+GhC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * DeliverStage — final pipeline stage that packages and delivers
3
+ * all generated artifacts.
4
+ *
5
+ * Merges artifacts from all completed stages into a cohesive project
6
+ * structure, validates self-containment, creates an archive, and
7
+ * delivers to a target directory.
8
+ */
9
+ import { join } from 'node:path';
10
+ import { existsSync, writeFileSync } from 'node:fs';
11
+ import { ForgeError, ErrorCodes, hashContent, getLayout, } from '@hstm-labs/forge-common';
12
+ import { mergeArtifacts } from './artifact-merger.js';
13
+ import { validateSelfContainment } from './self-containment.js';
14
+ import { createArchive } from './archiver.js';
15
+ import { deliverToTarget } from './delivery-writer.js';
16
+ // ---------------------------------------------------------------------------
17
+ // Constants
18
+ // ---------------------------------------------------------------------------
19
+ /** Forge version placeholder — replaced by semantic-release in CI. */
20
+ const FORGE_VERSION = '0.0.0';
21
+ // ---------------------------------------------------------------------------
22
+ // Helpers
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Generate a minimal package.json for the delivered project.
26
+ *
27
+ * @param stagingDir - Staging directory to write to
28
+ */
29
+ function generateMinimalPackageJson(stagingDir) {
30
+ const pkg = {
31
+ name: 'forge-generated-project',
32
+ version: '1.0.0',
33
+ private: true,
34
+ scripts: {
35
+ build: 'echo "Add your build command here"',
36
+ start: 'echo "Add your start command here"',
37
+ test: 'echo "Add your test command here"',
38
+ },
39
+ };
40
+ writeFileSync(join(stagingDir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
41
+ }
42
+ /**
43
+ * Generate a minimal README.md for the delivered project.
44
+ *
45
+ * @param stagingDir - Staging directory to write to
46
+ * @param runId - Run ID for reference
47
+ */
48
+ function generateMinimalReadme(stagingDir, runId) {
49
+ const content = [
50
+ '# Generated Project',
51
+ '',
52
+ `This project was generated by [Forge](https://github.com/hstm-labs/forge) (run: \`${runId}\`).`,
53
+ '',
54
+ '## Setup',
55
+ '',
56
+ '1. Install dependencies:',
57
+ ' ```bash',
58
+ ' npm install',
59
+ ' ```',
60
+ '',
61
+ '2. Build the project:',
62
+ ' ```bash',
63
+ ' npm run build',
64
+ ' ```',
65
+ '',
66
+ '3. Start the application:',
67
+ ' ```bash',
68
+ ' npm start',
69
+ ' ```',
70
+ '',
71
+ '## Project Structure',
72
+ '',
73
+ '- `src/api/` — API routes and handlers',
74
+ '- `src/ui/` — UI pages and components',
75
+ '- `src/security/` — Security middleware and configuration',
76
+ '- `data/` — Seed data and migrations',
77
+ '- `tests/` — Generated test suites',
78
+ '- `docs/` — Architecture and compliance reports',
79
+ '',
80
+ '## Documentation',
81
+ '',
82
+ 'See the `docs/` directory for architecture decisions and compliance reports.',
83
+ '',
84
+ ].join('\n');
85
+ writeFileSync(join(stagingDir, 'README.md'), content, 'utf-8');
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Stage
89
+ // ---------------------------------------------------------------------------
90
+ /**
91
+ * Pipeline stage that packages and delivers all generated artifacts.
92
+ *
93
+ * This is the final stage in the Forge pipeline. It:
94
+ * 1. Merges artifacts from all completed stages into a project structure
95
+ * 2. Generates minimal package.json and README.md if missing
96
+ * 3. Validates self-containment
97
+ * 4. Delivers to a target directory
98
+ * 5. Creates an archive (tgz)
99
+ * 6. Writes a delivery manifest
100
+ *
101
+ * @example
102
+ * ```ts
103
+ * const stage = new DeliverStage();
104
+ * const output = await stage.execute(input, context);
105
+ * const result = output.data?.delivery as DeliveryResult;
106
+ * ```
107
+ */
108
+ export class DeliverStage {
109
+ name = 'deliver';
110
+ dependsOn = ['verify'];
111
+ requiresLLM = false;
112
+ /**
113
+ * Execute the delivery stage.
114
+ *
115
+ * @param _input - Pipeline stage input (not used — reads from disk)
116
+ * @param context - Pipeline context with config, workspace, and store
117
+ * @returns Stage output with delivery manifest and DeliveryResult in data
118
+ * @throws {ForgeError} FORGE-PIPE-001 if store is missing
119
+ * @throws {ForgeError} FORGE-DLVR-001 if archive creation fails
120
+ */
121
+ async execute(_input, context) {
122
+ // 1. Validate store is available
123
+ if (context.store === undefined) {
124
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Deliver stage requires a RunStore, but none was provided.');
125
+ }
126
+ // 2. Resolve layout and merge artifacts into staging directory
127
+ const layoutName = context.config.layout ?? 'standard';
128
+ const layout = getLayout(layoutName);
129
+ const stagingDir = join(context.workspace.forgeDir, 'runs', context.runId, 'staging');
130
+ const { stageEntries } = mergeArtifacts(context.workspace, context.runId, context.store, layout.stageMapping, stagingDir);
131
+ // 3. Generate minimal package.json and README.md if not present
132
+ if (!existsSync(join(stagingDir, 'package.json'))) {
133
+ generateMinimalPackageJson(stagingDir);
134
+ }
135
+ if (!existsSync(join(stagingDir, 'README.md'))) {
136
+ generateMinimalReadme(stagingDir, context.runId);
137
+ }
138
+ // 4. Deliver to project root (layout-aware target)
139
+ const targetPath = context.workspace.rootDir;
140
+ const { fileCount, totalSizeBytes } = deliverToTarget(stagingDir, targetPath);
141
+ // 5. Validate self-containment on project root
142
+ const selfContainment = validateSelfContainment(targetPath);
143
+ // 6. Create archive from staging (clean tree, not project root)
144
+ let archivePath;
145
+ try {
146
+ const archiveOutputPath = join(context.workspace.forgeDir, 'runs', context.runId, 'project.tgz');
147
+ const archiveResult = await createArchive(stagingDir, archiveOutputPath, 'tgz');
148
+ archivePath = archiveResult.archivePath;
149
+ }
150
+ catch {
151
+ // Archive creation failure is non-fatal
152
+ }
153
+ // 7. Build manifest
154
+ const manifest = {
155
+ runId: context.runId,
156
+ deliveredAt: new Date().toISOString(),
157
+ fileCount,
158
+ totalSizeBytes,
159
+ stages: stageEntries,
160
+ forgeVersion: FORGE_VERSION,
161
+ };
162
+ // 8. Write delivery.json to .forge/runs/{id}/ (Forge metadata, not project root)
163
+ const runsDir = join(context.workspace.forgeDir, 'runs', context.runId);
164
+ const manifestJson = JSON.stringify(manifest, null, 2);
165
+ writeFileSync(join(runsDir, 'delivery.json'), manifestJson, 'utf-8');
166
+ // 9. Build DeliveryResult
167
+ const deliveryResult = {
168
+ runId: context.runId,
169
+ targetPath,
170
+ archivePath,
171
+ manifest,
172
+ selfContainment,
173
+ };
174
+ // 10. Return pipeline output
175
+ const manifestContent = JSON.stringify(deliveryResult, null, 2);
176
+ return {
177
+ artifacts: [
178
+ {
179
+ filePath: 'delivery.json',
180
+ content: manifestContent,
181
+ contentHash: hashContent(manifestContent),
182
+ sizeBytes: Buffer.byteLength(manifestContent, 'utf-8'),
183
+ },
184
+ ],
185
+ data: {
186
+ delivery: deliveryResult,
187
+ },
188
+ };
189
+ }
190
+ }
191
+ //# sourceMappingURL=deliver-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver-stage.js","sourceRoot":"","sources":["../src/deliver-stage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Delivery writer for the Forge delivery stage.
3
+ *
4
+ * Copies staged artifacts to the target delivery directory,
5
+ * preserving directory structure.
6
+ */
7
+ /**
8
+ * Deliver staged artifacts to the target directory.
9
+ *
10
+ * Copies all files from the staging directory to the target,
11
+ * preserving the directory structure.
12
+ *
13
+ * @param stagingDir - Source staging directory with merged artifacts
14
+ * @param targetPath - Target delivery directory
15
+ * @returns File count and total size in bytes
16
+ */
17
+ export declare function deliverToTarget(stagingDir: string, targetPath: string): {
18
+ fileCount: number;
19
+ totalSizeBytes: number;
20
+ };
21
+ //# sourceMappingURL=delivery-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-writer.d.ts","sourceRoot":"","sources":["../src/delivery-writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuDH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAE/C"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Delivery writer for the Forge delivery stage.
3
+ *
4
+ * Copies staged artifacts to the target delivery directory,
5
+ * preserving directory structure.
6
+ */
7
+ import { join } from 'node:path';
8
+ import { mkdirSync, readFileSync, writeFileSync, readdirSync, statSync, } from 'node:fs';
9
+ // ---------------------------------------------------------------------------
10
+ // Helpers
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Recursively copy a directory, preserving structure.
14
+ *
15
+ * @param src - Source directory
16
+ * @param dest - Destination directory
17
+ * @returns File count and total size in bytes
18
+ */
19
+ function copyDirRecursive(src, dest) {
20
+ mkdirSync(dest, { recursive: true });
21
+ let fileCount = 0;
22
+ let totalSizeBytes = 0;
23
+ const entries = readdirSync(src, { withFileTypes: true });
24
+ for (const entry of entries) {
25
+ const srcPath = join(src, entry.name);
26
+ const destPath = join(dest, entry.name);
27
+ if (entry.isDirectory()) {
28
+ const sub = copyDirRecursive(srcPath, destPath);
29
+ fileCount += sub.fileCount;
30
+ totalSizeBytes += sub.totalSizeBytes;
31
+ }
32
+ else {
33
+ const content = readFileSync(srcPath);
34
+ writeFileSync(destPath, content);
35
+ const stat = statSync(srcPath);
36
+ fileCount++;
37
+ totalSizeBytes += stat.size;
38
+ }
39
+ }
40
+ return { fileCount, totalSizeBytes };
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Public API
44
+ // ---------------------------------------------------------------------------
45
+ /**
46
+ * Deliver staged artifacts to the target directory.
47
+ *
48
+ * Copies all files from the staging directory to the target,
49
+ * preserving the directory structure.
50
+ *
51
+ * @param stagingDir - Source staging directory with merged artifacts
52
+ * @param targetPath - Target delivery directory
53
+ * @returns File count and total size in bytes
54
+ */
55
+ export function deliverToTarget(stagingDir, targetPath) {
56
+ return copyDirRecursive(stagingDir, targetPath);
57
+ }
58
+ //# sourceMappingURL=delivery-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-writer.js","sourceRoot":"","sources":["../src/delivery-writer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,EACX,QAAQ,GACT,MAAM,SAAS,CAAC;AAEjB,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,gBAAgB,CACvB,GAAW,EACX,IAAY;IAEZ,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAChD,SAAS,IAAI,GAAG,CAAC,SAAS,CAAC;YAC3B,cAAc,IAAI,GAAG,CAAC,cAAc,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACtC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC/B,SAAS,EAAE,CAAC;YACZ,cAAc,IAAI,IAAI,CAAC,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AACvC,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,UAAkB,EAClB,UAAkB;IAElB,OAAO,gBAAgB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Delivery result formatters for the Forge CLI.
3
+ *
4
+ * Produces human-readable console output and JSON representations
5
+ * of the delivery result.
6
+ */
7
+ import type { DeliveryResult } from './types.js';
8
+ /**
9
+ * Format a delivery result into human-readable console output.
10
+ *
11
+ * @param result - The delivery result to format
12
+ * @returns Multi-line formatted string
13
+ */
14
+ export declare function formatDeliveryResult(result: DeliveryResult): string;
15
+ /**
16
+ * Convert a delivery result to a JSON-serializable object.
17
+ *
18
+ * @param result - The delivery result
19
+ * @returns Plain object suitable for JSON output
20
+ */
21
+ export declare function deliveryResultToJson(result: DeliveryResult): Record<string, unknown>;
22
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAoCjD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAyDnE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,GACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Delivery result formatters for the Forge CLI.
3
+ *
4
+ * Produces human-readable console output and JSON representations
5
+ * of the delivery result.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Helpers
9
+ // ---------------------------------------------------------------------------
10
+ /**
11
+ * Format byte size into a human-readable string.
12
+ *
13
+ * @param bytes - Size in bytes
14
+ * @returns Human-readable size string (e.g., "245 KB")
15
+ */
16
+ function formatSize(bytes) {
17
+ if (bytes < 1024)
18
+ return `${String(bytes)} B`;
19
+ const kb = bytes / 1024;
20
+ if (kb < 1024)
21
+ return `${kb.toFixed(1)} KB`;
22
+ const mb = kb / 1024;
23
+ return `${mb.toFixed(1)} MB`;
24
+ }
25
+ /**
26
+ * Pad or truncate a string to a fixed width.
27
+ *
28
+ * @param str - Input string
29
+ * @param width - Target width
30
+ * @returns Padded string
31
+ */
32
+ function pad(str, width) {
33
+ if (str.length >= width)
34
+ return str.slice(0, width);
35
+ return str + ' '.repeat(width - str.length);
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Public API
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Format a delivery result into human-readable console output.
42
+ *
43
+ * @param result - The delivery result to format
44
+ * @returns Multi-line formatted string
45
+ */
46
+ export function formatDeliveryResult(result) {
47
+ const lines = [];
48
+ // Header box
49
+ lines.push('\u2554' + '\u2550'.repeat(44) + '\u2557');
50
+ lines.push('\u2551' + pad(' Delivery Complete', 44) + '\u2551');
51
+ lines.push('\u2560' + '\u2550'.repeat(44) + '\u2563');
52
+ lines.push('\u2551' + pad(` Run: ${result.runId}`, 44) + '\u2551');
53
+ lines.push('\u2551' +
54
+ pad(` Target: ${result.targetPath}`, 44) +
55
+ '\u2551');
56
+ lines.push('\u2551' +
57
+ pad(` Files: ${String(result.manifest.fileCount)}`, 44) +
58
+ '\u2551');
59
+ lines.push('\u2551' +
60
+ pad(` Size: ${formatSize(result.manifest.totalSizeBytes)}`, 44) +
61
+ '\u2551');
62
+ if (result.archivePath !== undefined) {
63
+ lines.push('\u2551' +
64
+ pad(` Archive: ${result.archivePath}`, 44) +
65
+ '\u2551');
66
+ }
67
+ lines.push('\u255A' + '\u2550'.repeat(44) + '\u255D');
68
+ // Self-containment checks
69
+ lines.push('');
70
+ lines.push('Self-Containment:');
71
+ for (const check of result.selfContainment.checks) {
72
+ const symbol = check.passed ? '\u2713' : '\u2717';
73
+ lines.push(` ${symbol} ${check.name}`);
74
+ }
75
+ // Stages included
76
+ lines.push('');
77
+ lines.push('Stages Included:');
78
+ for (const stage of result.manifest.stages) {
79
+ const count = stage.artifactCount === 1
80
+ ? '1 file'
81
+ : `${String(stage.artifactCount)} files`;
82
+ lines.push(` ${pad(stage.stageName, 18)} ${count}`);
83
+ }
84
+ return lines.join('\n');
85
+ }
86
+ /**
87
+ * Convert a delivery result to a JSON-serializable object.
88
+ *
89
+ * @param result - The delivery result
90
+ * @returns Plain object suitable for JSON output
91
+ */
92
+ export function deliveryResultToJson(result) {
93
+ return {
94
+ runId: result.runId,
95
+ targetPath: result.targetPath,
96
+ archivePath: result.archivePath,
97
+ manifest: result.manifest,
98
+ selfContainment: result.selfContainment,
99
+ };
100
+ }
101
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @hstm-labs/forge-deliverer — Output packaging and delivery for Forge.
3
+ *
4
+ * Provides the {@link DeliverStage} pipeline stage, artifact merging,
5
+ * self-containment validation, archiving, delivery writing, and
6
+ * result formatting.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export type { DeliveryResult, DeliveryManifest, DeliveryStageEntry, SelfContainmentResult, SelfContainmentCheck, DeliveryOptions, } from './types.js';
11
+ export { DeliverStage } from './deliver-stage.js';
12
+ export { mergeArtifacts } from './artifact-merger.js';
13
+ export { validateSelfContainment } from './self-containment.js';
14
+ export { createArchive } from './archiver.js';
15
+ export { deliverToTarget } from './delivery-writer.js';
16
+ export { formatDeliveryResult, deliveryResultToJson } from './formatters.js';
17
+ //# 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,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @hstm-labs/forge-deliverer — Output packaging and delivery for Forge.
3
+ *
4
+ * Provides the {@link DeliverStage} pipeline stage, artifact merging,
5
+ * self-containment validation, archiving, delivery writing, and
6
+ * result formatting.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+ export { DeliverStage } from './deliver-stage.js';
11
+ export { mergeArtifacts } from './artifact-merger.js';
12
+ export { validateSelfContainment } from './self-containment.js';
13
+ export { createArchive } from './archiver.js';
14
+ export { deliverToTarget } from './delivery-writer.js';
15
+ export { formatDeliveryResult, deliveryResultToJson } from './formatters.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Self-containment validator for the Forge delivery stage.
3
+ *
4
+ * Checks whether the staged project output is self-contained,
5
+ * including presence of package.json, build scripts, README,
6
+ * and absence of hardcoded Forge paths.
7
+ */
8
+ import type { SelfContainmentResult } from './types.js';
9
+ /**
10
+ * Validate that a staged project directory is self-contained.
11
+ *
12
+ * Performs the following checks (non-blocking — warnings only):
13
+ * 1. `package.json` exists
14
+ * 2. Build scripts are defined in `package.json`
15
+ * 3. `README.md` exists
16
+ * 4. No hardcoded `.forge/` paths in generated code
17
+ *
18
+ * @param stagingDir - Path to the staging directory
19
+ * @returns Self-containment validation result
20
+ */
21
+ export declare function validateSelfContainment(stagingDir: string): SelfContainmentResult;
22
+ //# sourceMappingURL=self-containment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-containment.d.ts","sourceRoot":"","sources":["../src/self-containment.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAwB,MAAM,YAAY,CAAC;AAiC9E;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,GACjB,qBAAqB,CA0FvB"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Self-containment validator for the Forge delivery stage.
3
+ *
4
+ * Checks whether the staged project output is self-contained,
5
+ * including presence of package.json, build scripts, README,
6
+ * and absence of hardcoded Forge paths.
7
+ */
8
+ import { join } from 'node:path';
9
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
10
+ // ---------------------------------------------------------------------------
11
+ // Helpers
12
+ // ---------------------------------------------------------------------------
13
+ /**
14
+ * Recursively collect all file paths under a directory.
15
+ *
16
+ * @param dir - Directory to scan
17
+ * @param base - Base path for relative paths
18
+ * @returns Array of relative file paths
19
+ */
20
+ function collectFiles(dir, base = dir) {
21
+ const results = [];
22
+ if (!existsSync(dir))
23
+ return results;
24
+ const entries = readdirSync(dir, { withFileTypes: true });
25
+ for (const entry of entries) {
26
+ const fullPath = join(dir, entry.name);
27
+ if (entry.isDirectory()) {
28
+ results.push(...collectFiles(fullPath, base));
29
+ }
30
+ else {
31
+ results.push(fullPath.slice(base.length + 1));
32
+ }
33
+ }
34
+ return results;
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // Public API
38
+ // ---------------------------------------------------------------------------
39
+ /**
40
+ * Validate that a staged project directory is self-contained.
41
+ *
42
+ * Performs the following checks (non-blocking — warnings only):
43
+ * 1. `package.json` exists
44
+ * 2. Build scripts are defined in `package.json`
45
+ * 3. `README.md` exists
46
+ * 4. No hardcoded `.forge/` paths in generated code
47
+ *
48
+ * @param stagingDir - Path to the staging directory
49
+ * @returns Self-containment validation result
50
+ */
51
+ export function validateSelfContainment(stagingDir) {
52
+ const checks = [];
53
+ // 1. package.json exists
54
+ const pkgJsonPath = join(stagingDir, 'package.json');
55
+ const hasPkgJson = existsSync(pkgJsonPath);
56
+ checks.push({
57
+ name: 'package.json present',
58
+ passed: hasPkgJson,
59
+ description: hasPkgJson
60
+ ? 'package.json found in project root'
61
+ : 'package.json not found — project may not be installable',
62
+ });
63
+ // 2. Build scripts defined
64
+ let hasBuildScripts = false;
65
+ if (hasPkgJson) {
66
+ try {
67
+ const pkgContent = readFileSync(pkgJsonPath, 'utf-8');
68
+ const pkg = JSON.parse(pkgContent);
69
+ if (typeof pkg === 'object' &&
70
+ pkg !== null &&
71
+ 'scripts' in pkg &&
72
+ typeof pkg['scripts'] === 'object') {
73
+ const scripts = pkg['scripts'];
74
+ hasBuildScripts =
75
+ 'build' in scripts || 'start' in scripts || 'dev' in scripts;
76
+ }
77
+ }
78
+ catch {
79
+ // Malformed package.json — treat as no build scripts
80
+ }
81
+ }
82
+ checks.push({
83
+ name: 'Build scripts defined',
84
+ passed: hasBuildScripts,
85
+ description: hasBuildScripts
86
+ ? 'Build/start scripts found in package.json'
87
+ : 'No build or start scripts found in package.json',
88
+ });
89
+ // 3. README.md exists
90
+ const readmePath = join(stagingDir, 'README.md');
91
+ const hasReadme = existsSync(readmePath);
92
+ checks.push({
93
+ name: 'README.md present',
94
+ passed: hasReadme,
95
+ description: hasReadme
96
+ ? 'README.md found in project root'
97
+ : 'README.md not found — project lacks documentation',
98
+ });
99
+ // 4. No hardcoded Forge paths
100
+ let forgePathFound = false;
101
+ const files = collectFiles(stagingDir);
102
+ for (const filePath of files) {
103
+ // Only scan text-like files
104
+ if (filePath.endsWith('.ts') ||
105
+ filePath.endsWith('.js') ||
106
+ filePath.endsWith('.json') ||
107
+ filePath.endsWith('.md') ||
108
+ filePath.endsWith('.yml') ||
109
+ filePath.endsWith('.yaml')) {
110
+ try {
111
+ const content = readFileSync(join(stagingDir, filePath), 'utf-8');
112
+ if (content.includes('.forge/')) {
113
+ forgePathFound = true;
114
+ break;
115
+ }
116
+ }
117
+ catch {
118
+ // Skip unreadable files
119
+ }
120
+ }
121
+ }
122
+ checks.push({
123
+ name: 'No hardcoded Forge paths',
124
+ passed: !forgePathFound,
125
+ description: forgePathFound
126
+ ? 'References to .forge/ found in generated code'
127
+ : 'No hardcoded .forge/ paths detected',
128
+ });
129
+ // Self-containment is valid if core checks pass (package.json + README)
130
+ // Build scripts and forge paths are advisory
131
+ const valid = checks.every((c) => c.passed);
132
+ return { valid, checks };
133
+ }
134
+ //# sourceMappingURL=self-containment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-containment.js","sourceRoot":"","sources":["../src/self-containment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Type definitions for the Forge delivery stage.
3
+ *
4
+ * Defines the output structures for artifact packaging, self-containment
5
+ * validation, delivery manifests, and delivery options.
6
+ */
7
+ /** Complete delivery result returned by the deliver stage. */
8
+ export interface DeliveryResult {
9
+ /** Run ID. */
10
+ runId: string;
11
+ /** Target delivery path. */
12
+ targetPath: string;
13
+ /** Archive file path (if created). */
14
+ archivePath?: string | undefined;
15
+ /** Delivery manifest. */
16
+ manifest: DeliveryManifest;
17
+ /** Self-containment validation result. */
18
+ selfContainment: SelfContainmentResult;
19
+ }
20
+ /** Delivery manifest written as delivery.json. */
21
+ export interface DeliveryManifest {
22
+ /** Run ID. */
23
+ runId: string;
24
+ /** ISO timestamp. */
25
+ deliveredAt: string;
26
+ /** Total files delivered. */
27
+ fileCount: number;
28
+ /** Total size in bytes. */
29
+ totalSizeBytes: number;
30
+ /** Stage artifacts included. */
31
+ stages: DeliveryStageEntry[];
32
+ /** Forge version. */
33
+ forgeVersion: string;
34
+ }
35
+ /** Entry for a single stage in the delivery manifest. */
36
+ export interface DeliveryStageEntry {
37
+ /** Stage name. */
38
+ stageName: string;
39
+ /** Number of artifacts from this stage. */
40
+ artifactCount: number;
41
+ /** Artifact file paths (relative). */
42
+ files: string[];
43
+ }
44
+ /** Result of self-containment validation checks. */
45
+ export interface SelfContainmentResult {
46
+ /** Whether the project passes self-containment checks. */
47
+ valid: boolean;
48
+ /** Checks performed. */
49
+ checks: SelfContainmentCheck[];
50
+ }
51
+ /** A single self-containment check result. */
52
+ export interface SelfContainmentCheck {
53
+ /** Check name. */
54
+ name: string;
55
+ /** Whether this check passed. */
56
+ passed: boolean;
57
+ /** Description of what was checked. */
58
+ description: string;
59
+ }
60
+ /** Options controlling delivery behavior. */
61
+ export interface DeliveryOptions {
62
+ /** Target directory for delivery (overrides config). */
63
+ target?: string | undefined;
64
+ /** Skip verification check. */
65
+ skipVerify?: boolean | undefined;
66
+ /** Create archive (tgz). */
67
+ archive?: boolean | undefined;
68
+ /** Archive format. */
69
+ archiveFormat?: 'tgz' | 'zip' | undefined;
70
+ }
71
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,8DAA8D;AAC9D,MAAM,WAAW,cAAc;IAC7B,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,yBAAyB;IACzB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,0CAA0C;IAC1C,eAAe,EAAE,qBAAqB,CAAC;CACxC;AAMD,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,qBAAqB;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IACjC,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAMD,oDAAoD;AACpD,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,KAAK,EAAE,OAAO,CAAC;IACf,wBAAwB;IACxB,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,kBAAkB;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,6CAA6C;AAC7C,MAAM,WAAW,eAAe;IAC9B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,+BAA+B;IAC/B,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,4BAA4B;IAC5B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,sBAAsB;IACtB,aAAa,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;CAC3C"}
package/dist/types.js ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Type definitions for the Forge delivery stage.
3
+ *
4
+ * Defines the output structures for artifact packaging, self-containment
5
+ * validation, delivery manifests, and delivery options.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@hstm-labs/forge-deliverer",
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
+ }
22
+ }