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/templates.mjs
CHANGED
|
@@ -1,224 +1,225 @@
|
|
|
1
|
-
// templates.mjs - Project template and role installation/refresh helpers
|
|
2
|
-
|
|
3
|
-
import { existsSync, mkdirSync, readdirSync, cpSync, unlinkSync } from 'fs';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
-
import { fileHash, readManifest } from './manifest.mjs';
|
|
6
|
-
|
|
7
|
-
export function installProjectTemplates({ planningDir, distilledDir, agentsDir }) {
|
|
8
|
-
const localTemplatesDir = join(planningDir, 'templates');
|
|
9
|
-
const globalTemplatesDir = join(distilledDir, 'templates');
|
|
10
|
-
|
|
11
|
-
if (!existsSync(localTemplatesDir)) {
|
|
12
|
-
if (existsSync(globalTemplatesDir)) {
|
|
13
|
-
cpSync(globalTemplatesDir, localTemplatesDir, { recursive: true });
|
|
14
|
-
console.log(' - copied templates to .planning/templates/');
|
|
15
|
-
// Warn-only by design: init should not fail on missing templates because
|
|
16
|
-
// the user may still proceed and fix later. The hard gate lives in
|
|
17
|
-
// `gsdd health` (E6/E7/E8) which reports these as errors. This is the
|
|
18
|
-
// first layer of the 3-layer scaffold defense (warn at init, error at
|
|
19
|
-
// health, regression tests in manifest suite).
|
|
20
|
-
const expectedSubdirs = ['delegates', 'research', 'codebase'];
|
|
21
|
-
for (const subdir of expectedSubdirs) {
|
|
22
|
-
if (!existsSync(join(localTemplatesDir, subdir))) {
|
|
23
|
-
console.log(` - WARN: missing expected template subdir: ${subdir}/`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const expectedRootFiles = ['spec.md', 'roadmap.md', 'auth-matrix.md'];
|
|
27
|
-
for (const file of expectedRootFiles) {
|
|
28
|
-
if (!existsSync(join(localTemplatesDir, file))) {
|
|
29
|
-
console.log(` - WARN: missing expected root template file: ${file}`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
console.log(' - WARN: missing distilled/templates/; cannot copy templates');
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
console.log(' - .planning/templates/ already exists');
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const localRolesDir = join(localTemplatesDir, 'roles');
|
|
40
|
-
if (!existsSync(localRolesDir)) {
|
|
41
|
-
if (existsSync(agentsDir)) {
|
|
42
|
-
mkdirSync(localRolesDir, { recursive: true });
|
|
43
|
-
for (const file of listRoleFiles(agentsDir)) {
|
|
44
|
-
cpSync(join(agentsDir, file), join(localRolesDir, file));
|
|
45
|
-
}
|
|
46
|
-
console.log(' - copied role contracts to .planning/templates/roles/');
|
|
47
|
-
} else {
|
|
48
|
-
console.log(' - WARN: missing agents/; cannot copy role contracts');
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
console.log(' - .planning/templates/roles/ already exists');
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function refreshTemplates({ planningDir, distilledDir, agentsDir, isDry = false }) {
|
|
56
|
-
const existingManifest = readManifest(planningDir);
|
|
57
|
-
const globalTemplatesDir = join(distilledDir, 'templates');
|
|
58
|
-
const localTemplatesDir = join(planningDir, 'templates');
|
|
59
|
-
|
|
60
|
-
const categories = [
|
|
61
|
-
{ name: 'delegates', src: join(globalTemplatesDir, 'delegates'), dest: join(localTemplatesDir, 'delegates'), manifestKey: 'delegates' },
|
|
62
|
-
{ name: 'research', src: join(globalTemplatesDir, 'research'), dest: join(localTemplatesDir, 'research'), manifestKey: 'research' },
|
|
63
|
-
{ name: 'codebase', src: join(globalTemplatesDir, 'codebase'), dest: join(localTemplatesDir, 'codebase'), manifestKey: 'codebase' },
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!existsSync(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (!existsSync(
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
1
|
+
// templates.mjs - Project template and role installation/refresh helpers
|
|
2
|
+
|
|
3
|
+
import { existsSync, mkdirSync, readdirSync, cpSync, unlinkSync } from 'fs';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { fileHash, readManifest } from './manifest.mjs';
|
|
6
|
+
|
|
7
|
+
export function installProjectTemplates({ planningDir, distilledDir, agentsDir }) {
|
|
8
|
+
const localTemplatesDir = join(planningDir, 'templates');
|
|
9
|
+
const globalTemplatesDir = join(distilledDir, 'templates');
|
|
10
|
+
|
|
11
|
+
if (!existsSync(localTemplatesDir)) {
|
|
12
|
+
if (existsSync(globalTemplatesDir)) {
|
|
13
|
+
cpSync(globalTemplatesDir, localTemplatesDir, { recursive: true });
|
|
14
|
+
console.log(' - copied templates to .planning/templates/');
|
|
15
|
+
// Warn-only by design: init should not fail on missing templates because
|
|
16
|
+
// the user may still proceed and fix later. The hard gate lives in
|
|
17
|
+
// `gsdd health` (E6/E7/E8) which reports these as errors. This is the
|
|
18
|
+
// first layer of the 3-layer scaffold defense (warn at init, error at
|
|
19
|
+
// health, regression tests in manifest suite).
|
|
20
|
+
const expectedSubdirs = ['delegates', 'research', 'codebase', 'brownfield-change'];
|
|
21
|
+
for (const subdir of expectedSubdirs) {
|
|
22
|
+
if (!existsSync(join(localTemplatesDir, subdir))) {
|
|
23
|
+
console.log(` - WARN: missing expected template subdir: ${subdir}/`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const expectedRootFiles = ['spec.md', 'roadmap.md', 'auth-matrix.md'];
|
|
27
|
+
for (const file of expectedRootFiles) {
|
|
28
|
+
if (!existsSync(join(localTemplatesDir, file))) {
|
|
29
|
+
console.log(` - WARN: missing expected root template file: ${file}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
console.log(' - WARN: missing distilled/templates/; cannot copy templates');
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
console.log(' - .planning/templates/ already exists');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const localRolesDir = join(localTemplatesDir, 'roles');
|
|
40
|
+
if (!existsSync(localRolesDir)) {
|
|
41
|
+
if (existsSync(agentsDir)) {
|
|
42
|
+
mkdirSync(localRolesDir, { recursive: true });
|
|
43
|
+
for (const file of listRoleFiles(agentsDir)) {
|
|
44
|
+
cpSync(join(agentsDir, file), join(localRolesDir, file));
|
|
45
|
+
}
|
|
46
|
+
console.log(' - copied role contracts to .planning/templates/roles/');
|
|
47
|
+
} else {
|
|
48
|
+
console.log(' - WARN: missing agents/; cannot copy role contracts');
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
console.log(' - .planning/templates/roles/ already exists');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function refreshTemplates({ planningDir, distilledDir, agentsDir, isDry = false }) {
|
|
56
|
+
const existingManifest = readManifest(planningDir);
|
|
57
|
+
const globalTemplatesDir = join(distilledDir, 'templates');
|
|
58
|
+
const localTemplatesDir = join(planningDir, 'templates');
|
|
59
|
+
|
|
60
|
+
const categories = [
|
|
61
|
+
{ name: 'delegates', src: join(globalTemplatesDir, 'delegates'), dest: join(localTemplatesDir, 'delegates'), manifestKey: 'delegates' },
|
|
62
|
+
{ name: 'research', src: join(globalTemplatesDir, 'research'), dest: join(localTemplatesDir, 'research'), manifestKey: 'research' },
|
|
63
|
+
{ name: 'codebase', src: join(globalTemplatesDir, 'codebase'), dest: join(localTemplatesDir, 'codebase'), manifestKey: 'codebase' },
|
|
64
|
+
{ name: 'brownfield-change', src: join(globalTemplatesDir, 'brownfield-change'), dest: join(localTemplatesDir, 'brownfield-change'), manifestKey: 'brownfieldChange' },
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
for (const category of categories) {
|
|
68
|
+
refreshCategory(category, existingManifest, isDry);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
refreshRootTemplates(globalTemplatesDir, localTemplatesDir, existingManifest, isDry);
|
|
72
|
+
refreshRoles(agentsDir, join(localTemplatesDir, 'roles'), existingManifest, isDry);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function listRoleFiles(agentsDir) {
|
|
76
|
+
return readdirSync(agentsDir).filter(
|
|
77
|
+
(file) => file.endsWith('.md') && file !== 'README.md' && !file.startsWith('_')
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function refreshCategory({ name, src, dest, manifestKey }, existingManifest, isDry) {
|
|
82
|
+
if (!existsSync(src)) return;
|
|
83
|
+
if (!existsSync(dest) && !isDry) {
|
|
84
|
+
mkdirSync(dest, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const manifestHashes = existingManifest?.templates?.[manifestKey] || null;
|
|
88
|
+
const sourceFiles = readdirSync(src).filter((file) => file.endsWith('.md'));
|
|
89
|
+
const installedFiles = existsSync(dest) ? readdirSync(dest).filter((file) => file.endsWith('.md')) : [];
|
|
90
|
+
|
|
91
|
+
for (const file of sourceFiles) {
|
|
92
|
+
const srcPath = join(src, file);
|
|
93
|
+
const destPath = join(dest, file);
|
|
94
|
+
const srcHash = fileHash(srcPath);
|
|
95
|
+
|
|
96
|
+
if (existsSync(destPath)) {
|
|
97
|
+
const destHash = fileHash(destPath);
|
|
98
|
+
if (destHash === srcHash) continue;
|
|
99
|
+
|
|
100
|
+
const manifestHash = manifestHashes?.[file];
|
|
101
|
+
if (manifestHash && destHash !== manifestHash) {
|
|
102
|
+
console.log(` - WARN: ${name}/${file} was modified locally; overwriting with framework source`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (isDry) {
|
|
107
|
+
console.log(` - would refresh ${name}/${file}`);
|
|
108
|
+
} else {
|
|
109
|
+
cpSync(srcPath, destPath);
|
|
110
|
+
console.log(` - refreshed ${name}/${file}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (const file of installedFiles) {
|
|
115
|
+
if (!sourceFiles.includes(file)) {
|
|
116
|
+
if (isDry) {
|
|
117
|
+
console.log(` - would remove orphan ${name}/${file}`);
|
|
118
|
+
} else {
|
|
119
|
+
const orphanPath = join(dest, file);
|
|
120
|
+
if (existsSync(orphanPath)) {
|
|
121
|
+
unlinkSync(orphanPath);
|
|
122
|
+
}
|
|
123
|
+
console.log(` - removed orphan ${name}/${file}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function refreshRootTemplates(globalTemplatesDir, localTemplatesDir, existingManifest, isDry) {
|
|
130
|
+
if (!existsSync(globalTemplatesDir)) return;
|
|
131
|
+
|
|
132
|
+
const manifestHashes = existingManifest?.templates?.root || null;
|
|
133
|
+
const sourceFiles = readdirSync(globalTemplatesDir).filter((file) => file.endsWith('.md'));
|
|
134
|
+
|
|
135
|
+
for (const file of sourceFiles) {
|
|
136
|
+
const srcPath = join(globalTemplatesDir, file);
|
|
137
|
+
const destPath = join(localTemplatesDir, file);
|
|
138
|
+
const srcHash = fileHash(srcPath);
|
|
139
|
+
|
|
140
|
+
if (existsSync(destPath)) {
|
|
141
|
+
const destHash = fileHash(destPath);
|
|
142
|
+
if (destHash === srcHash) continue;
|
|
143
|
+
|
|
144
|
+
const manifestHash = manifestHashes?.[file];
|
|
145
|
+
if (manifestHash && destHash !== manifestHash) {
|
|
146
|
+
console.log(` - WARN: templates/${file} was modified locally; overwriting with framework source`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (isDry) {
|
|
151
|
+
console.log(` - would refresh templates/${file}`);
|
|
152
|
+
} else {
|
|
153
|
+
cpSync(srcPath, destPath);
|
|
154
|
+
console.log(` - refreshed templates/${file}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const installedRootFiles = existsSync(localTemplatesDir)
|
|
159
|
+
? readdirSync(localTemplatesDir).filter((file) => file.endsWith('.md'))
|
|
160
|
+
: [];
|
|
161
|
+
|
|
162
|
+
for (const file of installedRootFiles) {
|
|
163
|
+
if (!sourceFiles.includes(file)) {
|
|
164
|
+
if (isDry) {
|
|
165
|
+
console.log(` - would remove orphan templates/${file}`);
|
|
166
|
+
} else {
|
|
167
|
+
const orphanPath = join(localTemplatesDir, file);
|
|
168
|
+
if (existsSync(orphanPath)) {
|
|
169
|
+
unlinkSync(orphanPath);
|
|
170
|
+
}
|
|
171
|
+
console.log(` - removed orphan templates/${file}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function refreshRoles(agentsDir, localRolesDir, existingManifest, isDry) {
|
|
178
|
+
if (!existsSync(agentsDir)) return;
|
|
179
|
+
if (!existsSync(localRolesDir) && !isDry) {
|
|
180
|
+
mkdirSync(localRolesDir, { recursive: true });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const manifestHashes = existingManifest?.roles || null;
|
|
184
|
+
const sourceFiles = listRoleFiles(agentsDir);
|
|
185
|
+
const installedFiles = existsSync(localRolesDir)
|
|
186
|
+
? readdirSync(localRolesDir).filter((file) => file.endsWith('.md'))
|
|
187
|
+
: [];
|
|
188
|
+
|
|
189
|
+
for (const file of sourceFiles) {
|
|
190
|
+
const srcPath = join(agentsDir, file);
|
|
191
|
+
const destPath = join(localRolesDir, file);
|
|
192
|
+
const srcHash = fileHash(srcPath);
|
|
193
|
+
|
|
194
|
+
if (existsSync(destPath)) {
|
|
195
|
+
const destHash = fileHash(destPath);
|
|
196
|
+
if (destHash === srcHash) continue;
|
|
197
|
+
|
|
198
|
+
const manifestHash = manifestHashes?.[file];
|
|
199
|
+
if (manifestHash && destHash !== manifestHash) {
|
|
200
|
+
console.log(` - WARN: roles/${file} was modified locally; overwriting with framework source`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (isDry) {
|
|
205
|
+
console.log(` - would refresh roles/${file}`);
|
|
206
|
+
} else {
|
|
207
|
+
cpSync(srcPath, destPath);
|
|
208
|
+
console.log(` - refreshed roles/${file}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const file of installedFiles) {
|
|
213
|
+
if (!sourceFiles.includes(file)) {
|
|
214
|
+
if (isDry) {
|
|
215
|
+
console.log(` - would remove orphan roles/${file}`);
|
|
216
|
+
} else {
|
|
217
|
+
const orphanPath = join(localRolesDir, file);
|
|
218
|
+
if (existsSync(orphanPath)) {
|
|
219
|
+
unlinkSync(orphanPath);
|
|
220
|
+
}
|
|
221
|
+
console.log(` - removed orphan roles/${file}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
@@ -91,11 +91,12 @@ export function resolveWorkspaceContext(rawArgs = [], { cwd = process.cwd(), env
|
|
|
91
91
|
const candidates = [];
|
|
92
92
|
|
|
93
93
|
if (workspaceRootArg) candidates.push(normalizePath(workspaceRootArg, cwd));
|
|
94
|
-
if (env.GSDD_WORKSPACE_ROOT) candidates.push(normalizePath(env.GSDD_WORKSPACE_ROOT, cwd));
|
|
95
94
|
|
|
96
95
|
const discovered = findWorkspaceRoot(cwd);
|
|
97
96
|
if (discovered) candidates.push(discovered);
|
|
98
97
|
|
|
98
|
+
if (env.GSDD_WORKSPACE_ROOT) candidates.push(normalizePath(env.GSDD_WORKSPACE_ROOT, cwd));
|
|
99
|
+
|
|
99
100
|
candidates.push(resolve(cwd));
|
|
100
101
|
|
|
101
102
|
for (const candidate of candidates) {
|