aw-spec-cli 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +291 -0
  2. package/assets/docs/ModularMonolith/ModularMonolith.Reference.pack.txt +25248 -0
  3. package/assets/docs/ModularMonolith/ModularMonolith.pack.txt +5726 -0
  4. package/assets/docs/ModularMonolith/pack-foundation.ps1 +145 -0
  5. package/assets/docs/ModularMonolith/pack-foundation.sh +196 -0
  6. package/assets/docs/ModularMonolith/pack-reference-foundation.ps1 +157 -0
  7. package/assets/docs/ModularMonolith/pack-reference-foundation.sh +209 -0
  8. package/assets/docs/ModularMonolith/unpack-foundation.ps1 +126 -0
  9. package/assets/docs/ModularMonolith/unpack-foundation.sh +217 -0
  10. package/assets/docs/ModularMonolith/unpack-reference-foundation.ps1 +129 -0
  11. package/assets/docs/ModularMonolith/unpack-reference-foundation.sh +218 -0
  12. package/assets/docs/UI.Visualization/PACKAGING.md +191 -0
  13. package/assets/docs/UI.Visualization/UI.Visualization.Reference.pack.txt +11768 -0
  14. package/assets/docs/UI.Visualization/UI.Visualization.pack.txt +11214 -0
  15. package/assets/docs/UI.Visualization/pack-foundation.ps1 +165 -0
  16. package/assets/docs/UI.Visualization/pack-foundation.sh +206 -0
  17. package/assets/docs/UI.Visualization/pack-reference-foundation.ps1 +159 -0
  18. package/assets/docs/UI.Visualization/pack-reference-foundation.sh +205 -0
  19. package/assets/docs/UI.Visualization/unpack-foundation.ps1 +126 -0
  20. package/assets/docs/UI.Visualization/unpack-foundation.sh +217 -0
  21. package/assets/docs/UI.Visualization/unpack-reference-foundation.ps1 +129 -0
  22. package/assets/docs/UI.Visualization/unpack-reference-foundation.sh +218 -0
  23. package/assets/docs/VerticalSlice/VerticalSlice.Reference.pack.txt +19318 -0
  24. package/assets/docs/VerticalSlice/pack-reference-foundation.ps1 +157 -0
  25. package/assets/docs/VerticalSlice/pack-reference-foundation.sh +209 -0
  26. package/assets/docs/VerticalSlice/unpack-reference-foundation.ps1 +129 -0
  27. package/assets/docs/VerticalSlice/unpack-reference-foundation.sh +218 -0
  28. package/assets/docs/components/Email/README.md +7 -0
  29. package/assets/docs/components/Email/ReferenceEndpoints/SendEmailEndpoint.cs +84 -0
  30. package/assets/docs/components/Email/integration.md +57 -17
  31. package/assets/docs/components/Jobs/integration.md +29 -15
  32. package/assets/docs/components/QrGenerator/README.md +7 -0
  33. package/assets/docs/components/QrGenerator/ReferenceEndpoints/GenerateQrEndpoint.cs +57 -0
  34. package/assets/docs/components/QrGenerator/integration.md +51 -6
  35. package/assets/docs/components/README.md +19 -2
  36. package/assets/docs/domainspecs/UIVisualization/chart-bubble.md +70 -0
  37. package/assets/docs/domainspecs/UIVisualization/chart-dimred.md +58 -0
  38. package/assets/docs/domainspecs/UIVisualization/chart-heatmap.md +62 -0
  39. package/assets/docs/domainspecs/UIVisualization/chart-network.md +69 -0
  40. package/assets/docs/domainspecs/UIVisualization/chart-parallel.md +75 -0
  41. package/assets/docs/domainspecs/UIVisualization/chart-scurve.md +66 -0
  42. package/assets/docs/domainspecs/UIVisualization/chart-survival.md +69 -0
  43. package/assets/docs/domainspecs/UIVisualization/chart-trellis.md +68 -0
  44. package/assets/docs/domainspecs/UIVisualization/chart-violin.md +61 -0
  45. package/assets/docs/domainspecs/UIVisualization/chart-volcano.md +63 -0
  46. package/assets/docs/domainspecs/UIVisualization/charting-standards.domain.md +80 -0
  47. package/assets/docs/domainspecs/UIVisualization/clean-architecture.domain.md +87 -0
  48. package/assets/docs/domainspecs/UIVisualization/coding-standards.domain.md +47 -0
  49. package/assets/docs/domainspecs/UIVisualization/comandrulemap.md +130 -0
  50. package/assets/docs/domainspecs/UIVisualization/component-contracts.domain.md +67 -0
  51. package/assets/docs/domainspecs/UIVisualization/data-source.domain.md +68 -0
  52. package/assets/docs/domainspecs/UIVisualization/domain-requirements.md +110 -0
  53. package/assets/docs/domainspecs/UIVisualization/folder-structure.domain.md +55 -0
  54. package/assets/docs/domainspecs/UIVisualization/state-management.domain.md +67 -0
  55. package/assets/docs/domainspecs/UIVisualization/testing.domain.md +52 -0
  56. package/assets/docs/domainspecs/UIVisualization/ui-viz-terms.md +39 -0
  57. package/assets/docs/domainspecs/healthcare/comandrulemap.md +47 -0
  58. package/assets/docs/domainspecs/pharma/comandrulemap.md +50 -0
  59. package/dist/commands/init.d.ts.map +1 -1
  60. package/dist/commands/init.js +54 -7
  61. package/dist/commands/init.js.map +1 -1
  62. package/dist/commands/update.d.ts +3 -0
  63. package/dist/commands/update.d.ts.map +1 -0
  64. package/dist/commands/update.js +142 -0
  65. package/dist/commands/update.js.map +1 -0
  66. package/dist/index.js +2 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/utils/manifest.d.ts +31 -0
  69. package/dist/utils/manifest.d.ts.map +1 -0
  70. package/dist/utils/manifest.js +91 -0
  71. package/dist/utils/manifest.js.map +1 -0
  72. package/dist/utils/update-engine.d.ts +52 -0
  73. package/dist/utils/update-engine.d.ts.map +1 -0
  74. package/dist/utils/update-engine.js +203 -0
  75. package/dist/utils/update-engine.js.map +1 -0
  76. package/package.json +5 -2
  77. package/assets/docs/requirement-spec.txt +0 -15
@@ -0,0 +1,142 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import chalk from 'chalk';
4
+ import fs from 'fs-extra';
5
+ import path from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { resolveAssetsPath } from '../utils/paths.js';
8
+ import { readManifest, updateManifest } from '../utils/manifest.js';
9
+ import { buildUpdatePlan, applyUpdatePlan } from '../utils/update-engine.js';
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const AGENT_FOLDER_MAP = {
12
+ claude: '.claude',
13
+ antigravity: '.agents',
14
+ kilocode: '.kilocode',
15
+ };
16
+ const ALWAYS_COPY = ['.aw-spec', 'docs'];
17
+ export const updateCommand = new Command('update')
18
+ .description('Update an existing AppWeaver Spec project with latest assets from registry')
19
+ .argument('[directory]', 'Target directory (default: current directory)', '.')
20
+ .option('-a, --agent <agent>', 'Agent to use: claude, antigravity, kilocode (detected from manifest if not specified)')
21
+ .option('-y, --yes', 'Skip prompts and apply non-conflicting updates automatically')
22
+ .option('--dry-run', 'Show what would be updated without making changes')
23
+ .action(async (directory, options) => {
24
+ const targetDir = directory === '.' ? process.cwd() : directory;
25
+ const manifestPath = path.join(targetDir, '.aw-spec', 'manifest.json');
26
+ console.log(`\n🔄 Checking for updates in: ${targetDir}\n`);
27
+ // Load existing manifest
28
+ const manifest = await readManifest(manifestPath);
29
+ if (!manifest) {
30
+ console.log(chalk.red('✗ No manifest found. This project was not initialized with aw-spec or is from an older version.'));
31
+ console.log(chalk.yellow(' Run `aw-spec init` to initialize a new project.'));
32
+ process.exit(1);
33
+ }
34
+ console.log(chalk.gray(` Current version: ${manifest.version}`));
35
+ console.log(chalk.gray(` Last updated: ${manifest.updatedAt}`));
36
+ console.log(chalk.gray(` Tracked files: ${Object.keys(manifest.files).length}`));
37
+ // Determine agent from manifest or options
38
+ let agent = options.agent;
39
+ if (agent === 'prompt') {
40
+ // Try to detect from init-options.json
41
+ const initOptionsPath = path.join(targetDir, '.aw-spec', 'init-options.json');
42
+ if (await fs.pathExists(initOptionsPath)) {
43
+ try {
44
+ const initOptions = await fs.readJSON(initOptionsPath);
45
+ if (initOptions.ai && ['claude', 'antigravity', 'kilocode'].includes(initOptions.ai)) {
46
+ agent = initOptions.ai;
47
+ console.log(chalk.gray(` Detected agent from init-options: ${agent}`));
48
+ }
49
+ }
50
+ catch {
51
+ // Ignore parse errors
52
+ }
53
+ }
54
+ }
55
+ // If still not determined, prompt
56
+ if (agent === 'prompt') {
57
+ if (options.yes) {
58
+ agent = 'claude';
59
+ }
60
+ else {
61
+ const { selectedAgent } = await inquirer.prompt([
62
+ {
63
+ type: 'list',
64
+ name: 'selectedAgent',
65
+ message: 'Which agent skills should be updated?',
66
+ choices: [
67
+ { name: 'Claude Code (.claude/skills)', value: 'claude' },
68
+ { name: 'Antigravity (.agents/skills)', value: 'antigravity' },
69
+ { name: 'KiloCode (.kilocode/skills)', value: 'kilocode' },
70
+ ],
71
+ default: 'claude',
72
+ },
73
+ ]);
74
+ agent = selectedAgent;
75
+ }
76
+ }
77
+ const agentFolder = AGENT_FOLDER_MAP[agent];
78
+ // Resolve new assets from registry
79
+ const assetsPath = await resolveAssetsPath();
80
+ console.log(chalk.gray(` Source assets: ${assetsPath}`));
81
+ if (options.dryRun) {
82
+ console.log('\n📋 Dry run - checking for updates...\n');
83
+ }
84
+ // Build update plan
85
+ console.log(chalk.bold('\n📊 Analyzing changes...\n'));
86
+ const plan = await buildUpdatePlan(manifest.files, targetDir, assetsPath);
87
+ // Print summary
88
+ console.log(chalk.bold('\n📋 Update Plan:'));
89
+ console.log(chalk.green(` Update: ${plan.summary.update}`));
90
+ console.log(chalk.blue(` Add: ${plan.summary.add}`));
91
+ console.log(chalk.yellow(` Preserve: ${plan.summary.preserve}`));
92
+ console.log(chalk.red(` Skip (conflicts): ${plan.summary.skip}`));
93
+ console.log(chalk.gray(` Remove: ${plan.summary.remove}`));
94
+ if (plan.summary.skip > 0) {
95
+ console.log(chalk.yellow('\n⚠️ Conflicts detected - these files have both user and upstream changes:'));
96
+ for (const file of plan.files.filter(f => f.disposition === 'skip')) {
97
+ console.log(chalk.yellow(` ⚠ ${file.relPath} - ${file.reason}`));
98
+ }
99
+ console.log(chalk.yellow('\n These files will be skipped. Resolve manually after update.'));
100
+ }
101
+ if (plan.summary.preserve > 0) {
102
+ console.log(chalk.blue('\nℹ️ User-modified files preserved:'));
103
+ for (const file of plan.files.filter(f => f.disposition === 'preserve')) {
104
+ console.log(chalk.blue(` ⊘ ${file.relPath} - ${file.reason}`));
105
+ }
106
+ }
107
+ if (options.dryRun) {
108
+ console.log(chalk.bold('\n🔍 Dry run complete - no changes made.'));
109
+ return;
110
+ }
111
+ // Confirm before applying if not --yes
112
+ if (!options.yes && (plan.summary.update > 0 || plan.summary.add > 0 || plan.summary.remove > 0)) {
113
+ const { confirm } = await inquirer.prompt([
114
+ {
115
+ type: 'confirm',
116
+ name: 'confirm',
117
+ message: 'Apply these updates?',
118
+ default: true,
119
+ },
120
+ ]);
121
+ if (!confirm) {
122
+ console.log(chalk.gray('\nUpdate cancelled.'));
123
+ return;
124
+ }
125
+ }
126
+ // Apply update plan
127
+ console.log(chalk.bold('\n📦 Applying updates...\n'));
128
+ await applyUpdatePlan(plan, targetDir, assetsPath, {
129
+ onProgress: (msg) => console.log(msg),
130
+ });
131
+ // Update manifest with new state
132
+ console.log(chalk.bold('\n📝 Updating manifest...'));
133
+ const newManifest = await updateManifest(manifestPath, targetDir, manifest.version);
134
+ console.log(chalk.green(` ✓ Manifest updated (${Object.keys(newManifest.files).length} files tracked)`));
135
+ console.log(chalk.bold('\n✅ Update complete!'));
136
+ console.log('\nNext steps:');
137
+ console.log(' aw-spec doctor # Verify the installation');
138
+ if (plan.summary.skip > 0) {
139
+ console.log(chalk.yellow(' Review skipped files and resolve conflicts manually'));
140
+ }
141
+ });
142
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { program } from 'commander';
3
3
  import { initCommand } from './commands/init.js';
4
4
  import { doctorCommand } from './commands/doctor.js';
5
+ import { updateCommand } from './commands/update.js';
5
6
  import fs from 'fs-extra';
6
7
  import path from 'path';
7
8
  import { fileURLToPath } from 'url';
@@ -12,6 +13,7 @@ program
12
13
  .description('AppWeaver Spec-Driven Development CLI')
13
14
  .version(packageJson.version)
14
15
  .addCommand(initCommand)
16
+ .addCommand(updateCommand)
15
17
  .addCommand(doctorCommand);
16
18
  program.parse();
17
19
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAElF,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,UAAU,CAAC,WAAW,CAAC;KACvB,UAAU,CAAC,aAAa,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAElF,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,UAAU,CAAC,WAAW,CAAC;KACvB,UAAU,CAAC,aAAa,CAAC;KACzB,UAAU,CAAC,aAAa,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -0,0 +1,31 @@
1
+ export interface Manifest {
2
+ version: string;
3
+ files: Record<string, string>;
4
+ updatedAt: string;
5
+ }
6
+ export interface ManifestOptions {
7
+ manifestPath: string;
8
+ }
9
+ /**
10
+ * Compute SHA256 hash of a file
11
+ */
12
+ export declare function computeFileHash(filePath: string): Promise<string>;
13
+ /**
14
+ * Read manifest from disk, returns null if not found
15
+ */
16
+ export declare function readManifest(manifestPath: string): Promise<Manifest | null>;
17
+ /**
18
+ * Write manifest to disk
19
+ */
20
+ export declare function writeManifest(manifestPath: string, manifest: Manifest): Promise<void>;
21
+ /**
22
+ * Create a new manifest from a source directory
23
+ * Walks the directory and computes hashes for all files
24
+ */
25
+ export declare function createManifest(sourceRoot: string, targetRoot: string, version: string): Promise<Manifest>;
26
+ /**
27
+ * Update manifest with new hashes from target directory
28
+ * Used after successful update to record new state
29
+ */
30
+ export declare function updateManifest(manifestPath: string, targetRoot: string, version: string): Promise<Manifest>;
31
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKvE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAUjF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3F;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,CAAC,CAyBnB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,QAAQ,CAAC,CA4BnB"}
@@ -0,0 +1,91 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { createHash } from 'crypto';
4
+ /**
5
+ * Compute SHA256 hash of a file
6
+ */
7
+ export async function computeFileHash(filePath) {
8
+ const content = await fs.readFile(filePath);
9
+ const hash = createHash('sha256');
10
+ hash.update(content);
11
+ return hash.digest('hex');
12
+ }
13
+ /**
14
+ * Read manifest from disk, returns null if not found
15
+ */
16
+ export async function readManifest(manifestPath) {
17
+ if (!(await fs.pathExists(manifestPath))) {
18
+ return null;
19
+ }
20
+ try {
21
+ const manifest = await fs.readJSON(manifestPath);
22
+ return manifest;
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * Write manifest to disk
30
+ */
31
+ export async function writeManifest(manifestPath, manifest) {
32
+ await fs.ensureDir(path.dirname(manifestPath));
33
+ await fs.writeJSON(manifestPath, manifest, { spaces: 2 });
34
+ }
35
+ /**
36
+ * Create a new manifest from a source directory
37
+ * Walks the directory and computes hashes for all files
38
+ */
39
+ export async function createManifest(sourceRoot, targetRoot, version) {
40
+ const files = {};
41
+ async function walk(dir, baseSource) {
42
+ const entries = await fs.readdir(dir, { withFileTypes: true });
43
+ for (const entry of entries) {
44
+ const fullPath = path.join(dir, entry.name);
45
+ const relPath = path.relative(baseSource, fullPath);
46
+ if (entry.isDirectory()) {
47
+ await walk(fullPath, baseSource);
48
+ }
49
+ else if (entry.isFile()) {
50
+ const hash = await computeFileHash(fullPath);
51
+ files[relPath] = hash;
52
+ }
53
+ }
54
+ }
55
+ await walk(sourceRoot, sourceRoot);
56
+ return {
57
+ version,
58
+ files,
59
+ updatedAt: new Date().toISOString(),
60
+ };
61
+ }
62
+ /**
63
+ * Update manifest with new hashes from target directory
64
+ * Used after successful update to record new state
65
+ */
66
+ export async function updateManifest(manifestPath, targetRoot, version) {
67
+ const files = {};
68
+ async function walk(dir, baseTarget) {
69
+ const entries = await fs.readdir(dir, { withFileTypes: true });
70
+ for (const entry of entries) {
71
+ const fullPath = path.join(dir, entry.name);
72
+ const relPath = path.relative(baseTarget, fullPath);
73
+ if (entry.isDirectory()) {
74
+ await walk(fullPath, baseTarget);
75
+ }
76
+ else if (entry.isFile()) {
77
+ const hash = await computeFileHash(fullPath);
78
+ files[relPath] = hash;
79
+ }
80
+ }
81
+ }
82
+ await walk(targetRoot, targetRoot);
83
+ const manifest = {
84
+ version,
85
+ files,
86
+ updatedAt: new Date().toISOString(),
87
+ };
88
+ await writeManifest(manifestPath, manifest);
89
+ return manifest;
90
+ }
91
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/utils/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ export type Disposition = 'update' | 'preserve' | 'skip' | 'remove' | 'add';
2
+ export interface FileDisposition {
3
+ relPath: string;
4
+ disposition: Disposition;
5
+ reason: string;
6
+ manifestHash?: string;
7
+ currentHash?: string;
8
+ sourceHash?: string;
9
+ }
10
+ export interface UpdatePlan {
11
+ files: FileDisposition[];
12
+ summary: {
13
+ update: number;
14
+ preserve: number;
15
+ skip: number;
16
+ remove: number;
17
+ add: number;
18
+ };
19
+ }
20
+ /**
21
+ * Compare three states and determine disposition for a single file
22
+ *
23
+ * Three-way comparison logic:
24
+ * - manifestHash: hash from original manifest (what we installed)
25
+ * - currentHash: hash of file currently on disk (user's version)
26
+ * - sourceHash: hash of file in new source (registry version)
27
+ *
28
+ * Cases:
29
+ * 1. All three same → no-op (not in plan)
30
+ * 2. manifest === current !== source → UPDATE (upstream changed, user didn't touch)
31
+ * 3. manifest !== current === source → PRESERVE (user changed, upstream same - but this is weird)
32
+ * 4. manifest === source !== current → PRESERVE (user changed, upstream didn't)
33
+ * 5. All three different → SKIP (conflict - both changed)
34
+ * 6. manifest exists, current missing, source exists → UPDATE (user deleted, restore from source)
35
+ * 7. manifest exists, current exists, source missing → REMOVE (upstream deleted)
36
+ * 8. manifest missing, current exists, source exists → SKIP (file added by user, also in new source - conflict)
37
+ * 9. manifest missing, current exists, source missing → PRESERVE (user added, not in upstream)
38
+ * 10. manifest missing, current missing, source exists → ADD (new file in upstream)
39
+ */
40
+ export declare function computeDisposition(relPath: string, manifestHash: string | undefined, currentHash: string | undefined, sourceHash: string | undefined): FileDisposition;
41
+ /**
42
+ * Build update plan by comparing manifest, current target, and new source
43
+ */
44
+ export declare function buildUpdatePlan(manifest: Record<string, string>, targetRoot: string, sourceRoot: string): Promise<UpdatePlan>;
45
+ /**
46
+ * Apply update plan to target directory
47
+ */
48
+ export declare function applyUpdatePlan(plan: UpdatePlan, targetRoot: string, sourceRoot: string, options?: {
49
+ dryRun?: boolean;
50
+ onProgress?: (msg: string) => void;
51
+ }): Promise<void>;
52
+ //# sourceMappingURL=update-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-engine.d.ts","sourceRoot":"","sources":["../../src/utils/update-engine.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE5E,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,eAAe,CAqEjB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAChC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC,CAyFrB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CAAO,GACrE,OAAO,CAAC,IAAI,CAAC,CAkCf"}
@@ -0,0 +1,203 @@
1
+ import { computeFileHash } from './manifest.js';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ /**
5
+ * Compare three states and determine disposition for a single file
6
+ *
7
+ * Three-way comparison logic:
8
+ * - manifestHash: hash from original manifest (what we installed)
9
+ * - currentHash: hash of file currently on disk (user's version)
10
+ * - sourceHash: hash of file in new source (registry version)
11
+ *
12
+ * Cases:
13
+ * 1. All three same → no-op (not in plan)
14
+ * 2. manifest === current !== source → UPDATE (upstream changed, user didn't touch)
15
+ * 3. manifest !== current === source → PRESERVE (user changed, upstream same - but this is weird)
16
+ * 4. manifest === source !== current → PRESERVE (user changed, upstream didn't)
17
+ * 5. All three different → SKIP (conflict - both changed)
18
+ * 6. manifest exists, current missing, source exists → UPDATE (user deleted, restore from source)
19
+ * 7. manifest exists, current exists, source missing → REMOVE (upstream deleted)
20
+ * 8. manifest missing, current exists, source exists → SKIP (file added by user, also in new source - conflict)
21
+ * 9. manifest missing, current exists, source missing → PRESERVE (user added, not in upstream)
22
+ * 10. manifest missing, current missing, source exists → ADD (new file in upstream)
23
+ */
24
+ export function computeDisposition(relPath, manifestHash, currentHash, sourceHash) {
25
+ // Case: file exists in all three
26
+ if (manifestHash && currentHash && sourceHash) {
27
+ if (manifestHash === currentHash && currentHash === sourceHash) {
28
+ // All same - no change needed (caller should filter these out)
29
+ return { relPath, disposition: 'update', reason: 'No changes (all identical)', manifestHash, currentHash, sourceHash };
30
+ }
31
+ if (manifestHash === currentHash && manifestHash !== sourceHash) {
32
+ // User didn't touch, upstream changed
33
+ return { relPath, disposition: 'update', reason: 'Upstream changed, user unmodified', manifestHash, currentHash, sourceHash };
34
+ }
35
+ if (manifestHash !== currentHash && manifestHash === sourceHash) {
36
+ // User changed, upstream didn't
37
+ return { relPath, disposition: 'preserve', reason: 'User modified, upstream unchanged', manifestHash, currentHash, sourceHash };
38
+ }
39
+ if (manifestHash === sourceHash && currentHash !== sourceHash) {
40
+ // Same as above - user changed, upstream same
41
+ return { relPath, disposition: 'preserve', reason: 'User modified, upstream unchanged', manifestHash, currentHash, sourceHash };
42
+ }
43
+ if (manifestHash !== currentHash && currentHash === sourceHash) {
44
+ // User changed to match upstream (e.g. user anticipated change)
45
+ return { relPath, disposition: 'preserve', reason: 'User version matches upstream', manifestHash, currentHash, sourceHash };
46
+ }
47
+ // All three different
48
+ return { relPath, disposition: 'skip', reason: 'Conflict: both user and upstream modified', manifestHash, currentHash, sourceHash };
49
+ }
50
+ // Case: manifest exists, current missing (user deleted)
51
+ if (manifestHash && !currentHash && sourceHash) {
52
+ return { relPath, disposition: 'update', reason: 'User deleted, restoring from upstream', manifestHash, currentHash, sourceHash };
53
+ }
54
+ // Case: manifest exists, current exists, source missing (upstream deleted)
55
+ if (manifestHash && currentHash && !sourceHash) {
56
+ return { relPath, disposition: 'remove', reason: 'Upstream removed file', manifestHash, currentHash, sourceHash };
57
+ }
58
+ // Case: manifest missing, current exists, source exists (user added, also in new upstream)
59
+ if (!manifestHash && currentHash && sourceHash) {
60
+ if (currentHash === sourceHash) {
61
+ // User added same content as upstream - treat as add
62
+ return { relPath, disposition: 'add', reason: 'New file in upstream (matches user)', manifestHash, currentHash, sourceHash };
63
+ }
64
+ // Different content - conflict
65
+ return { relPath, disposition: 'skip', reason: 'Conflict: user added file, upstream also added different version', manifestHash, currentHash, sourceHash };
66
+ }
67
+ // Case: manifest missing, current exists, source missing (user added, not in upstream)
68
+ if (!manifestHash && currentHash && !sourceHash) {
69
+ return { relPath, disposition: 'preserve', reason: 'User added file, not in upstream', manifestHash, currentHash, sourceHash };
70
+ }
71
+ // Case: manifest missing, current missing, source exists (new file in upstream)
72
+ if (!manifestHash && !currentHash && sourceHash) {
73
+ return { relPath, disposition: 'add', reason: 'New file in upstream', manifestHash, currentHash, sourceHash };
74
+ }
75
+ // Case: manifest exists, current missing, source missing (file was in manifest but deleted everywhere)
76
+ if (manifestHash && !currentHash && !sourceHash) {
77
+ return { relPath, disposition: 'remove', reason: 'File removed from upstream', manifestHash, currentHash, sourceHash };
78
+ }
79
+ // Should not reach here
80
+ return { relPath, disposition: 'skip', reason: 'Unknown state', manifestHash, currentHash, sourceHash };
81
+ }
82
+ /**
83
+ * Build update plan by comparing manifest, current target, and new source
84
+ */
85
+ export async function buildUpdatePlan(manifest, targetRoot, sourceRoot) {
86
+ const files = [];
87
+ // Collect all unique relative paths from all three sources
88
+ const allPaths = new Set();
89
+ // From manifest
90
+ for (const relPath of Object.keys(manifest)) {
91
+ allPaths.add(relPath);
92
+ }
93
+ // From target (current)
94
+ async function walkTarget(dir, base) {
95
+ try {
96
+ const entries = await fs.readdir(dir, { withFileTypes: true });
97
+ for (const entry of entries) {
98
+ const fullPath = path.join(dir, entry.name);
99
+ const relPath = path.relative(base, fullPath);
100
+ if (entry.isDirectory()) {
101
+ await walkTarget(fullPath, base);
102
+ }
103
+ else if (entry.isFile()) {
104
+ allPaths.add(relPath);
105
+ }
106
+ }
107
+ }
108
+ catch {
109
+ // Directory might not exist
110
+ }
111
+ }
112
+ await walkTarget(targetRoot, targetRoot);
113
+ // From source (new)
114
+ async function walkSource(dir, base) {
115
+ try {
116
+ const entries = await fs.readdir(dir, { withFileTypes: true });
117
+ for (const entry of entries) {
118
+ const fullPath = path.join(dir, entry.name);
119
+ const relPath = path.relative(base, fullPath);
120
+ if (entry.isDirectory()) {
121
+ await walkSource(fullPath, base);
122
+ }
123
+ else if (entry.isFile()) {
124
+ allPaths.add(relPath);
125
+ }
126
+ }
127
+ }
128
+ catch {
129
+ // Directory might not exist
130
+ }
131
+ }
132
+ await walkSource(sourceRoot, sourceRoot);
133
+ // Compute disposition for each path
134
+ for (const relPath of allPaths) {
135
+ const manifestHash = manifest[relPath];
136
+ // Get current hash
137
+ let currentHash;
138
+ const currentPath = path.join(targetRoot, relPath);
139
+ if (await fs.pathExists(currentPath)) {
140
+ currentHash = await computeFileHash(currentPath);
141
+ }
142
+ // Get source hash
143
+ let sourceHash;
144
+ const sourcePath = path.join(sourceRoot, relPath);
145
+ if (await fs.pathExists(sourcePath)) {
146
+ sourceHash = await computeFileHash(sourcePath);
147
+ }
148
+ const disposition = computeDisposition(relPath, manifestHash, currentHash, sourceHash);
149
+ // Only include files that need action (not 'no-op')
150
+ if (disposition.disposition !== 'update' || disposition.reason !== 'No changes (all identical)') {
151
+ files.push(disposition);
152
+ }
153
+ }
154
+ // Sort for consistent output: update, add, preserve, skip, remove
155
+ const order = { update: 0, add: 1, preserve: 2, skip: 3, remove: 4 };
156
+ files.sort((a, b) => order[a.disposition] - order[b.disposition]);
157
+ // Build summary
158
+ const summary = {
159
+ update: files.filter(f => f.disposition === 'update').length,
160
+ preserve: files.filter(f => f.disposition === 'preserve').length,
161
+ skip: files.filter(f => f.disposition === 'skip').length,
162
+ remove: files.filter(f => f.disposition === 'remove').length,
163
+ add: files.filter(f => f.disposition === 'add').length,
164
+ };
165
+ return { files, summary };
166
+ }
167
+ /**
168
+ * Apply update plan to target directory
169
+ */
170
+ export async function applyUpdatePlan(plan, targetRoot, sourceRoot, options = {}) {
171
+ const { dryRun = false, onProgress = () => { } } = options;
172
+ for (const file of plan.files) {
173
+ const targetPath = path.join(targetRoot, file.relPath);
174
+ const sourcePath = path.join(sourceRoot, file.relPath);
175
+ switch (file.disposition) {
176
+ case 'update':
177
+ case 'add': {
178
+ onProgress(` ✓ ${file.relPath} (${file.disposition})`);
179
+ if (!dryRun) {
180
+ await fs.ensureDir(path.dirname(targetPath));
181
+ await fs.copy(sourcePath, targetPath, { overwrite: true });
182
+ }
183
+ break;
184
+ }
185
+ case 'remove': {
186
+ onProgress(` ✗ ${file.relPath} (remove)`);
187
+ if (!dryRun) {
188
+ await fs.remove(targetPath);
189
+ }
190
+ break;
191
+ }
192
+ case 'preserve': {
193
+ onProgress(` ⊘ ${file.relPath} (preserved - user modified)`);
194
+ break;
195
+ }
196
+ case 'skip': {
197
+ onProgress(` ⚠ ${file.relPath} (skipped - conflict: ${file.reason})`);
198
+ break;
199
+ }
200
+ }
201
+ }
202
+ }
203
+ //# sourceMappingURL=update-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-engine.js","sourceRoot":"","sources":["../../src/utils/update-engine.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "aw-spec-cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "AppWeaver Spec-Driven Development CLI - scaffolds projects with vertical slices, DDD, CQRS, and agent skills",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "exports": {
8
+ ".": "./dist/index.js"
9
+ },
7
10
  "bin": {
8
- "aw-spec": "dist/index.js"
11
+ "aw-spec": "./dist/index.js"
9
12
  },
10
13
  "files": [
11
14
  "dist",
@@ -1,15 +0,0 @@
1
- /aw-spec-specify MedicinalProduct/RegisterMedicinalProduct
2
-
3
- Allow an authorized user to register a new medicinal product in the registry.
4
-
5
- On registration the user provides: product name, generic name, NDC, dosage form, strength, route of administration, manufacturer, one or more active ingredients with details, one or more packaging configurations and one or more ATC classification codes.
6
-
7
- The system validates the submission (required attributes, duplicate NDC, valid dosage form and route of administration) and creates the product in the Draft state. A successful registration is auditable and emits a registration event.
8
-
9
- Acceptance:
10
- - A valid submission creates a Draft MedicinalProduct and returns its identifier.
11
- - A malformed or duplicate NDC is rejected with a clear validation error.
12
- - A product missing a required attribute, an active ingredient, or a packaging configuration is rejected.
13
- - The creation is recorded in the audit trail.
14
-
15
- ==============================================================================================