@abarcenas/ai-workflow-template 1.14.0 → 1.16.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/scripts/sync.js CHANGED
@@ -76,7 +76,7 @@ function syncFile(sourceFile, targetFile) {
76
76
  copyFileSync(sourceFile, targetFile)
77
77
  }
78
78
 
79
- const rootFiles = ['AGENTS.md', 'opencode.mcp.example.json']
79
+ const rootFiles = ['AGENTS.md', 'opencode.mcp.example.json', 'skills-lock.json']
80
80
 
81
81
  if (!existsSync(sourceAgentsDir)) {
82
82
  console.warn('[ai-workflow-template] No .agents directory found to sync.')
@@ -124,6 +124,48 @@ for (const sourceFile of sourceFiles) {
124
124
  console.warn(`[ai-workflow-template] Skipped locally modified file: ${relativePath}`)
125
125
  }
126
126
 
127
+ /* ── Sync .opencode/ directory ────────────────────────────── */
128
+
129
+ const sourceOpenCodeDir = resolve(packageRoot, '.opencode')
130
+ const openCodeExcluded = new Set(['node_modules', 'package.json', 'package-lock.json', 'bun.lock', '.gitignore'])
131
+
132
+ if (existsSync(sourceOpenCodeDir)) {
133
+ const openCodeFiles = collectFiles(sourceOpenCodeDir)
134
+
135
+ for (const sourceFile of openCodeFiles) {
136
+ const relativePath = relative(sourceOpenCodeDir, sourceFile)
137
+ if (openCodeExcluded.has(relativePath) || openCodeExcluded.has(relativePath.split('/')[0])) {
138
+ continue
139
+ }
140
+
141
+ const targetFile = resolve(consumerRoot, '.opencode', relativePath)
142
+ const sourceHash = hashFile(sourceFile)
143
+ const existingHash = existsSync(targetFile) ? hashFile(targetFile) : null
144
+ const trackedKey = `__opencode__/${relativePath}`
145
+ const recordedHash = manifest.files[trackedKey] ?? null
146
+
147
+ if (!existsSync(targetFile)) {
148
+ syncFile(sourceFile, targetFile)
149
+ manifest.files[trackedKey] = sourceHash
150
+ copied += 1
151
+ added += 1
152
+ continue
153
+ }
154
+
155
+ const isUntouched = recordedHash !== null && existingHash === recordedHash
156
+
157
+ if (forceOverwrite || isUntouched) {
158
+ syncFile(sourceFile, targetFile)
159
+ manifest.files[trackedKey] = sourceHash
160
+ copied += 1
161
+ continue
162
+ }
163
+
164
+ skipped += 1
165
+ console.warn(`[ai-workflow-template] Skipped locally modified opencode file: ${relativePath}`)
166
+ }
167
+ }
168
+
127
169
  for (const rootFile of rootFiles) {
128
170
  const sourceFile = resolve(packageRoot, rootFile)
129
171
  if (!existsSync(sourceFile)) {
@@ -157,9 +199,92 @@ for (const rootFile of rootFiles) {
157
199
  console.warn(`[ai-workflow-template] Skipped locally modified root file: ${rootFile}`)
158
200
  }
159
201
 
202
+ /* ── Scaffold memory-bank/ directory ──────────────────────────── */
203
+
204
+ const memoryBankStubs = {
205
+ 'projectbrief.md': `# projectbrief
206
+
207
+ > Foundation document — defines core requirements and goals.
208
+
209
+ - **Purpose**: {{describe project purpose}}
210
+ - **Goals**: {{list project goals}}
211
+ - **Scope**: {{define scope}}
212
+ `,
213
+ 'productContext.md': `# productContext
214
+
215
+ > Why this project exists and what problems it solves.
216
+
217
+ - **Problem**: {{describe the problem}}
218
+ - **Solution**: {{describe the solution}}
219
+ - **User Experience**: {{describe UX goals}}
220
+ `,
221
+ 'activeContext.md': `# activeContext
222
+
223
+ > Current work focus, recent changes, next steps.
224
+
225
+ - **Current Focus**: {{current task or goal}}
226
+ - **Recent Changes**: {{list of recent changes}}
227
+ - **Next Steps**: {{next actions}}
228
+ `,
229
+ 'systemPatterns.md': `# systemPatterns
230
+
231
+ > Architecture, key decisions, design patterns.
232
+
233
+ - **Architecture**: {{describe architecture}}
234
+ - **Key Decisions**: {{list key technical decisions}}
235
+ - **Patterns**: {{list design patterns in use}}
236
+ `,
237
+ 'techContext.md': `# techContext
238
+
239
+ > Technologies, setup, constraints, dependencies.
240
+
241
+ - **Stack**: {{list technologies}}
242
+ - **Setup**: {{describe dev setup}}
243
+ - **Constraints**: {{list technical constraints}}
244
+ `,
245
+ 'progress.md': `# progress
246
+
247
+ > What works, what's left, current status.
248
+
249
+ - **Working**: {{what's implemented and working}}
250
+ - **To Build**: {{what remains}}
251
+ - **Status**: {{overall project status}}
252
+ - **Known Issues**: {{list known issues}}
253
+ `,
254
+ }
255
+
256
+ const memoryBankDir = resolve(consumerRoot, 'memory-bank')
257
+ let scaffolded = 0
258
+
259
+ for (const [fileName, fileContent] of Object.entries(memoryBankStubs)) {
260
+ const targetFile = resolve(memoryBankDir, fileName)
261
+ const trackedKey = `__memory-bank__/${fileName}`
262
+
263
+ if (existsSync(targetFile)) {
264
+ continue
265
+ }
266
+
267
+ ensureParentDirectory(targetFile)
268
+ writeFileSync(targetFile, fileContent, 'utf8')
269
+ manifest.files[trackedKey] = hashFile(targetFile)
270
+ scaffolded += 1
271
+ }
272
+
273
+ /* ── Auto-copy opencode.mcp.json from example ────────────────── */
274
+
275
+ const exampleMcpFile = resolve(packageRoot, 'opencode.mcp.example.json')
276
+ const targetMcpFile = resolve(consumerRoot, 'opencode.mcp.json')
277
+ const mcpTrackedKey = '__root__/opencode.mcp.json'
278
+
279
+ if (existsSync(exampleMcpFile) && !existsSync(targetMcpFile)) {
280
+ copyFileSync(exampleMcpFile, targetMcpFile)
281
+ manifest.files[mcpTrackedKey] = hashFile(targetMcpFile)
282
+ scaffolded += 1
283
+ }
284
+
160
285
  if (!dryRun) {
161
286
  writeManifest(manifest)
162
287
  }
163
288
 
164
289
  const modeLabel = forceOverwrite ? 'force' : dryRun ? 'dry-run' : 'safe'
165
- console.log(`[ai-workflow-template] Synced ${copied} files (${added} new), skipped ${skipped} modified files. Mode: ${modeLabel}.`)
290
+ console.log(`[ai-workflow-template] Synced ${copied} files (${added} new), scaffolded ${scaffolded} files, skipped ${skipped} modified files. Mode: ${modeLabel}.`)
@@ -0,0 +1,53 @@
1
+ {
2
+ "version": 1,
3
+ "skills": {
4
+ "cavecrew": {
5
+ "source": "JuliusBrussee/caveman",
6
+ "sourceType": "github",
7
+ "skillPath": "skills/cavecrew/SKILL.md",
8
+ "computedHash": "06d45a7308d8603365313decf400020106b985cb5ce500ee169bfba9c71dd147"
9
+ },
10
+ "caveman": {
11
+ "source": "JuliusBrussee/caveman",
12
+ "sourceType": "github",
13
+ "skillPath": "caveman/SKILL.md",
14
+ "computedHash": "259cb6ef69b4e9eeb07155c925ce9895ed509b0feb6a7e29cbc9e70d3c7bcfb2"
15
+ },
16
+ "caveman-commit": {
17
+ "source": "JuliusBrussee/caveman",
18
+ "sourceType": "github",
19
+ "skillPath": "skills/caveman-commit/SKILL.md",
20
+ "computedHash": "76994afc39b68f4dbe098df76262b68d9928a23ee0f6aaebb11ba0e0f55bfa13"
21
+ },
22
+ "caveman-compress": {
23
+ "source": "JuliusBrussee/caveman",
24
+ "sourceType": "github",
25
+ "skillPath": "caveman-compress/SKILL.md",
26
+ "computedHash": "25520dcbf1cc98a372ea9e53abc6a5be20ebf1c7bcbc2008cdc9a118de0311c6"
27
+ },
28
+ "caveman-help": {
29
+ "source": "JuliusBrussee/caveman",
30
+ "sourceType": "github",
31
+ "skillPath": "skills/caveman-help/SKILL.md",
32
+ "computedHash": "3cd5f7d3f88c8ef7b16a6555dc61f5a11b14151386697609ab6887ab8b5f059d"
33
+ },
34
+ "caveman-review": {
35
+ "source": "JuliusBrussee/caveman",
36
+ "sourceType": "github",
37
+ "skillPath": "skills/caveman-review/SKILL.md",
38
+ "computedHash": "1dc59e7e896bc9dd449e43116c4c8b2e656b88c3370df91848330c17347af3d0"
39
+ },
40
+ "caveman-stats": {
41
+ "source": "JuliusBrussee/caveman",
42
+ "sourceType": "github",
43
+ "skillPath": "skills/caveman-stats/SKILL.md",
44
+ "computedHash": "d45d54b5d4dc0372476bbb9245a412a7ad6b2495f7435321ff0b18a16be3465c"
45
+ },
46
+ "compress": {
47
+ "source": "JuliusBrussee/caveman",
48
+ "sourceType": "github",
49
+ "skillPath": "skills/compress/SKILL.md",
50
+ "computedHash": "c91bdf427a68b686ee9d6f63766c72d164b16915434736edfedf13e24dae0e8c"
51
+ }
52
+ }
53
+ }