gsdd-cli 0.18.5 → 0.19.0
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/LICENSE +21 -21
- package/README.md +609 -608
- package/agents/DISTILLATION.md +421 -421
- package/agents/README.md +62 -62
- package/agents/approach-explorer.md +361 -361
- package/agents/debugger.md +82 -82
- package/agents/executor.md +394 -394
- package/agents/integration-checker.md +318 -318
- package/agents/mapper.md +103 -103
- package/agents/planner.md +313 -313
- package/agents/researcher.md +84 -84
- package/agents/roadmapper.md +296 -296
- package/agents/synthesizer.md +236 -236
- package/agents/verifier.md +337 -337
- package/bin/adapters/agents.mjs +34 -34
- package/bin/adapters/claude.mjs +191 -191
- package/bin/adapters/codex.mjs +85 -85
- package/bin/adapters/index.mjs +20 -20
- package/bin/adapters/opencode.mjs +278 -278
- package/bin/gsdd.mjs +123 -116
- package/bin/lib/cli-utils.mjs +28 -28
- package/bin/lib/evidence-contract.mjs +112 -112
- package/bin/lib/file-ops.mjs +186 -144
- package/bin/lib/health-truth.mjs +181 -178
- package/bin/lib/health.mjs +246 -226
- package/bin/lib/init-flow.mjs +247 -231
- package/bin/lib/init-prompts.mjs +248 -247
- package/bin/lib/init-runtime.mjs +191 -190
- package/bin/lib/init.mjs +17 -17
- package/bin/lib/lifecycle-preflight.mjs +347 -325
- package/bin/lib/lifecycle-state.mjs +351 -267
- package/bin/lib/manifest.mjs +116 -114
- package/bin/lib/models.mjs +411 -411
- package/bin/lib/phase.mjs +360 -358
- package/bin/lib/plan-constants.mjs +30 -30
- package/bin/lib/provenance.mjs +109 -106
- package/bin/lib/rendering.mjs +115 -83
- package/bin/lib/runtime-freshness.mjs +214 -214
- package/bin/lib/templates.mjs +225 -224
- package/bin/lib/workspace-root.mjs +2 -1
- package/distilled/DESIGN.md +2333 -2323
- package/distilled/EVIDENCE-INDEX.md +394 -392
- package/distilled/README.md +196 -193
- package/distilled/SKILL.md +86 -85
- package/distilled/templates/agents.block.md +21 -21
- package/distilled/templates/agents.md +6 -6
- package/distilled/templates/approach.md +232 -232
- package/distilled/templates/auth-matrix.md +78 -78
- package/distilled/templates/brownfield-change/CHANGE.md +99 -0
- package/distilled/templates/brownfield-change/HANDOFF.md +38 -0
- package/distilled/templates/brownfield-change/VERIFICATION.md +56 -0
- package/distilled/templates/codebase/architecture.md +110 -110
- package/distilled/templates/codebase/concerns.md +95 -95
- package/distilled/templates/codebase/conventions.md +193 -193
- package/distilled/templates/codebase/stack.md +96 -96
- package/distilled/templates/delegates/approach-explorer.md +25 -25
- package/distilled/templates/delegates/mapper-arch.md +26 -26
- package/distilled/templates/delegates/mapper-concerns.md +27 -27
- package/distilled/templates/delegates/mapper-quality.md +28 -28
- package/distilled/templates/delegates/mapper-tech.md +25 -25
- package/distilled/templates/delegates/plan-checker.md +68 -68
- package/distilled/templates/delegates/researcher-architecture.md +30 -30
- package/distilled/templates/delegates/researcher-features.md +30 -30
- package/distilled/templates/delegates/researcher-pitfalls.md +30 -30
- package/distilled/templates/delegates/researcher-stack.md +30 -30
- package/distilled/templates/delegates/researcher-synthesizer.md +31 -31
- package/distilled/templates/research/architecture.md +57 -57
- package/distilled/templates/research/features.md +23 -23
- package/distilled/templates/research/pitfalls.md +46 -46
- package/distilled/templates/research/stack.md +45 -45
- package/distilled/templates/research/summary.md +67 -67
- package/distilled/templates/roadmap.md +74 -62
- package/distilled/templates/spec.md +110 -110
- package/distilled/workflows/audit-milestone.md +275 -271
- package/distilled/workflows/complete-milestone.md +336 -332
- package/distilled/workflows/execute.md +454 -449
- package/distilled/workflows/map-codebase.md +253 -253
- package/distilled/workflows/new-milestone.md +242 -238
- package/distilled/workflows/new-project.md +398 -398
- package/distilled/workflows/pause.md +160 -156
- package/distilled/workflows/plan-milestone-gaps.md +183 -183
- package/distilled/workflows/plan.md +451 -447
- package/distilled/workflows/progress.md +227 -223
- package/distilled/workflows/quick.md +351 -347
- package/distilled/workflows/resume.md +220 -212
- package/distilled/workflows/verify-work.md +260 -260
- package/distilled/workflows/verify.md +431 -429
- package/docs/BROWNFIELD-PROOF.md +95 -95
- package/docs/RUNTIME-SUPPORT.md +80 -69
- package/docs/USER-GUIDE.md +394 -386
- package/docs/VERIFICATION-DISCIPLINE.md +59 -59
- package/docs/claude/context-monitor.md +98 -98
- package/docs/proof/consumer-node-cli/README.md +37 -37
- package/docs/proof/consumer-node-cli/ROADMAP.md +14 -14
- package/docs/proof/consumer-node-cli/SPEC.md +17 -17
- package/docs/proof/consumer-node-cli/brief.md +9 -9
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-PLAN.md +34 -34
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-01-SUMMARY.md +10 -10
- package/docs/proof/consumer-node-cli/phases/01-foundation/01-VERIFICATION.md +30 -30
- package/package.json +62 -61
package/bin/lib/manifest.mjs
CHANGED
|
@@ -1,65 +1,66 @@
|
|
|
1
|
-
// manifest.mjs — Generation manifest for template versioning
|
|
2
|
-
|
|
3
|
-
import { createHash } from 'crypto';
|
|
4
|
-
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
5
|
-
import { join, relative } from 'path';
|
|
6
|
-
|
|
7
|
-
const MANIFEST_FILENAME = 'generation-manifest.json';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* SHA-256 hex digest of file contents.
|
|
11
|
-
*/
|
|
12
|
-
export function fileHash(filePath) {
|
|
13
|
-
const content = readFileSync(filePath);
|
|
14
|
-
return createHash('sha256').update(content).digest('hex');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Recursive { relativePath: sha256 } map for a directory.
|
|
19
|
-
* Normalizes backslashes to forward slashes for cross-platform consistency.
|
|
20
|
-
*/
|
|
21
|
-
export function hashDirectory(dir, baseDir = dir) {
|
|
22
|
-
const result = {};
|
|
23
|
-
if (!existsSync(dir)) return result;
|
|
24
|
-
|
|
25
|
-
for (const entry of readdirSync(dir)) {
|
|
26
|
-
const fullPath = join(dir, entry);
|
|
27
|
-
const stat = statSync(fullPath);
|
|
28
|
-
if (stat.isDirectory()) {
|
|
29
|
-
Object.assign(result, hashDirectory(fullPath, baseDir));
|
|
30
|
-
} else {
|
|
31
|
-
const rel = relative(baseDir, fullPath).replace(/\\/g, '/');
|
|
32
|
-
result[rel] = fileHash(fullPath);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return result;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Build a full manifest snapshot from installed project files.
|
|
41
|
-
*/
|
|
1
|
+
// manifest.mjs — Generation manifest for template versioning
|
|
2
|
+
|
|
3
|
+
import { createHash } from 'crypto';
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
5
|
+
import { join, relative } from 'path';
|
|
6
|
+
|
|
7
|
+
const MANIFEST_FILENAME = 'generation-manifest.json';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* SHA-256 hex digest of file contents.
|
|
11
|
+
*/
|
|
12
|
+
export function fileHash(filePath) {
|
|
13
|
+
const content = readFileSync(filePath);
|
|
14
|
+
return createHash('sha256').update(content).digest('hex');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Recursive { relativePath: sha256 } map for a directory.
|
|
19
|
+
* Normalizes backslashes to forward slashes for cross-platform consistency.
|
|
20
|
+
*/
|
|
21
|
+
export function hashDirectory(dir, baseDir = dir) {
|
|
22
|
+
const result = {};
|
|
23
|
+
if (!existsSync(dir)) return result;
|
|
24
|
+
|
|
25
|
+
for (const entry of readdirSync(dir)) {
|
|
26
|
+
const fullPath = join(dir, entry);
|
|
27
|
+
const stat = statSync(fullPath);
|
|
28
|
+
if (stat.isDirectory()) {
|
|
29
|
+
Object.assign(result, hashDirectory(fullPath, baseDir));
|
|
30
|
+
} else {
|
|
31
|
+
const rel = relative(baseDir, fullPath).replace(/\\/g, '/');
|
|
32
|
+
result[rel] = fileHash(fullPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build a full manifest snapshot from installed project files.
|
|
41
|
+
*/
|
|
42
42
|
export function buildManifest({ planningDir, frameworkVersion }) {
|
|
43
43
|
const templatesDir = join(planningDir, 'templates');
|
|
44
44
|
const rolesDir = join(templatesDir, 'roles');
|
|
45
45
|
const runtimeHelpersDir = join(planningDir, 'bin');
|
|
46
|
-
|
|
47
|
-
// Template subcategories
|
|
48
|
-
const delegatesHashes = hashDirectory(join(templatesDir, 'delegates'), join(templatesDir, 'delegates'));
|
|
49
|
-
const researchHashes = hashDirectory(join(templatesDir, 'research'), join(templatesDir, 'research'));
|
|
50
|
-
const codebaseHashes = hashDirectory(join(templatesDir, 'codebase'), join(templatesDir, 'codebase'));
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
|
|
47
|
+
// Template subcategories
|
|
48
|
+
const delegatesHashes = hashDirectory(join(templatesDir, 'delegates'), join(templatesDir, 'delegates'));
|
|
49
|
+
const researchHashes = hashDirectory(join(templatesDir, 'research'), join(templatesDir, 'research'));
|
|
50
|
+
const codebaseHashes = hashDirectory(join(templatesDir, 'codebase'), join(templatesDir, 'codebase'));
|
|
51
|
+
const brownfieldChangeHashes = hashDirectory(join(templatesDir, 'brownfield-change'), join(templatesDir, 'brownfield-change'));
|
|
52
|
+
|
|
53
|
+
// Root-level template .md files (agents.block.md, spec.md, roadmap.md, etc.)
|
|
54
|
+
const rootHashes = {};
|
|
55
|
+
if (existsSync(templatesDir)) {
|
|
56
|
+
for (const entry of readdirSync(templatesDir)) {
|
|
57
|
+
const fullPath = join(templatesDir, entry);
|
|
58
|
+
if (statSync(fullPath).isFile() && entry.endsWith('.md')) {
|
|
59
|
+
rootHashes[entry] = fileHash(fullPath);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
63
64
|
// Role contracts
|
|
64
65
|
const rolesHashes = {};
|
|
65
66
|
if (existsSync(rolesDir)) {
|
|
@@ -75,64 +76,65 @@ export function buildManifest({ planningDir, frameworkVersion }) {
|
|
|
75
76
|
return {
|
|
76
77
|
frameworkVersion,
|
|
77
78
|
generatedAt: new Date().toISOString(),
|
|
78
|
-
templates: {
|
|
79
|
-
delegates: delegatesHashes,
|
|
80
|
-
research: researchHashes,
|
|
81
|
-
codebase: codebaseHashes,
|
|
82
|
-
|
|
79
|
+
templates: {
|
|
80
|
+
delegates: delegatesHashes,
|
|
81
|
+
research: researchHashes,
|
|
82
|
+
codebase: codebaseHashes,
|
|
83
|
+
brownfieldChange: brownfieldChangeHashes,
|
|
84
|
+
root: rootHashes,
|
|
83
85
|
},
|
|
84
86
|
roles: rolesHashes,
|
|
85
87
|
runtimeHelpers: runtimeHelpersHashes,
|
|
86
88
|
};
|
|
87
89
|
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Read existing manifest from planningDir, or return null if missing/corrupt.
|
|
91
|
-
*/
|
|
92
|
-
export function readManifest(planningDir) {
|
|
93
|
-
const manifestPath = join(planningDir, MANIFEST_FILENAME);
|
|
94
|
-
if (!existsSync(manifestPath)) return null;
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
return JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
98
|
-
} catch {
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Write generation-manifest.json to planningDir.
|
|
105
|
-
*/
|
|
106
|
-
export function writeManifest(planningDir, manifest) {
|
|
107
|
-
const manifestPath = join(planningDir, MANIFEST_FILENAME);
|
|
108
|
-
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Compare installed files vs manifest hashes.
|
|
113
|
-
* Returns { modified: string[], unchanged: string[], missing: string[] }
|
|
114
|
-
* where each string is a relative filename.
|
|
115
|
-
*/
|
|
116
|
-
export function detectModifications(installedDir, manifestHashes) {
|
|
117
|
-
const modified = [];
|
|
118
|
-
const unchanged = [];
|
|
119
|
-
const missing = [];
|
|
120
|
-
|
|
121
|
-
if (!manifestHashes) return { modified, unchanged, missing };
|
|
122
|
-
|
|
123
|
-
for (const [file, expectedHash] of Object.entries(manifestHashes)) {
|
|
124
|
-
const fullPath = join(installedDir, file);
|
|
125
|
-
if (!existsSync(fullPath)) {
|
|
126
|
-
missing.push(file);
|
|
127
|
-
continue;
|
|
128
|
-
}
|
|
129
|
-
const currentHash = fileHash(fullPath);
|
|
130
|
-
if (currentHash === expectedHash) {
|
|
131
|
-
unchanged.push(file);
|
|
132
|
-
} else {
|
|
133
|
-
modified.push(file);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return { modified, unchanged, missing };
|
|
138
|
-
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Read existing manifest from planningDir, or return null if missing/corrupt.
|
|
93
|
+
*/
|
|
94
|
+
export function readManifest(planningDir) {
|
|
95
|
+
const manifestPath = join(planningDir, MANIFEST_FILENAME);
|
|
96
|
+
if (!existsSync(manifestPath)) return null;
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
return JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
100
|
+
} catch {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Write generation-manifest.json to planningDir.
|
|
107
|
+
*/
|
|
108
|
+
export function writeManifest(planningDir, manifest) {
|
|
109
|
+
const manifestPath = join(planningDir, MANIFEST_FILENAME);
|
|
110
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Compare installed files vs manifest hashes.
|
|
115
|
+
* Returns { modified: string[], unchanged: string[], missing: string[] }
|
|
116
|
+
* where each string is a relative filename.
|
|
117
|
+
*/
|
|
118
|
+
export function detectModifications(installedDir, manifestHashes) {
|
|
119
|
+
const modified = [];
|
|
120
|
+
const unchanged = [];
|
|
121
|
+
const missing = [];
|
|
122
|
+
|
|
123
|
+
if (!manifestHashes) return { modified, unchanged, missing };
|
|
124
|
+
|
|
125
|
+
for (const [file, expectedHash] of Object.entries(manifestHashes)) {
|
|
126
|
+
const fullPath = join(installedDir, file);
|
|
127
|
+
if (!existsSync(fullPath)) {
|
|
128
|
+
missing.push(file);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const currentHash = fileHash(fullPath);
|
|
132
|
+
if (currentHash === expectedHash) {
|
|
133
|
+
unchanged.push(file);
|
|
134
|
+
} else {
|
|
135
|
+
modified.push(file);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { modified, unchanged, missing };
|
|
140
|
+
}
|