agent-state-machine 2.1.8 → 2.2.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/README.md +55 -5
- package/bin/cli.js +1 -140
- package/lib/config-utils.js +259 -0
- package/lib/file-tree.js +366 -0
- package/lib/index.js +109 -2
- package/lib/llm.js +35 -5
- package/lib/runtime/agent.js +146 -118
- package/lib/runtime/model-resolution.js +128 -0
- package/lib/runtime/runtime.js +13 -2
- package/lib/runtime/track-changes.js +252 -0
- package/package.json +1 -1
- package/templates/project-builder/agents/assumptions-clarifier.md +0 -8
- package/templates/project-builder/agents/code-reviewer.md +0 -8
- package/templates/project-builder/agents/code-writer.md +0 -10
- package/templates/project-builder/agents/requirements-clarifier.md +0 -7
- package/templates/project-builder/agents/roadmap-generator.md +0 -10
- package/templates/project-builder/agents/scope-clarifier.md +0 -6
- package/templates/project-builder/agents/security-clarifier.md +0 -9
- package/templates/project-builder/agents/security-reviewer.md +0 -12
- package/templates/project-builder/agents/task-planner.md +0 -10
- package/templates/project-builder/agents/test-planner.md +0 -9
- package/templates/project-builder/config.js +13 -1
- package/templates/starter/config.js +12 -1
- package/vercel-server/public/remote/assets/{index-Cunx4VJE.js → index-BOKpYANC.js} +32 -27
- package/vercel-server/public/remote/assets/index-DHL_iHQW.css +1 -0
- package/vercel-server/public/remote/index.html +2 -2
- package/vercel-server/ui/src/components/ContentCard.jsx +6 -6
- package/vercel-server/public/remote/assets/index-D02x57pS.css +0 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File: /lib/runtime/track-changes.js
|
|
3
|
+
*
|
|
4
|
+
* Wraps agent execution with file change tracking.
|
|
5
|
+
* Captures baseline before agent runs, detects changes after,
|
|
6
|
+
* and updates memory.fileTree with the results.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import {
|
|
11
|
+
captureBaseline,
|
|
12
|
+
detectChanges,
|
|
13
|
+
normalizePath,
|
|
14
|
+
extractExportsFromFile,
|
|
15
|
+
DEFAULT_IGNORE
|
|
16
|
+
} from '../file-tree.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Wrap an async function with file change tracking.
|
|
20
|
+
* Captures baseline before execution, detects changes after,
|
|
21
|
+
* and updates the runtime's fileTree.
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} runtime - The workflow runtime instance
|
|
24
|
+
* @param {string} agentName - Name of the agent (for attribution)
|
|
25
|
+
* @param {Function} fn - Async function to execute
|
|
26
|
+
* @returns {Promise<any>} - Result of the function
|
|
27
|
+
*/
|
|
28
|
+
export async function withChangeTracking(runtime, agentName, fn) {
|
|
29
|
+
const projectRoot = runtime.workflowConfig.projectRoot;
|
|
30
|
+
const ignorePatterns = runtime.workflowConfig.fileTrackingIgnore || DEFAULT_IGNORE;
|
|
31
|
+
|
|
32
|
+
// Capture baseline before agent runs
|
|
33
|
+
const baseline = await captureBaseline(projectRoot, ignorePatterns);
|
|
34
|
+
|
|
35
|
+
// Run the agent
|
|
36
|
+
const result = await fn();
|
|
37
|
+
|
|
38
|
+
// Detect changes made during agent execution
|
|
39
|
+
const changes = await detectChanges(projectRoot, baseline, ignorePatterns);
|
|
40
|
+
|
|
41
|
+
// Update fileTree with detected changes
|
|
42
|
+
applyChangesToFileTree(runtime, changes, agentName);
|
|
43
|
+
|
|
44
|
+
// Merge _files annotations if present (preserves existing data unless explicitly overwritten)
|
|
45
|
+
if (result && typeof result === 'object' && Array.isArray(result._files)) {
|
|
46
|
+
mergeAnnotations(runtime, result._files);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Apply detected file changes to the runtime's fileTree.
|
|
54
|
+
*/
|
|
55
|
+
function applyChangesToFileTree(runtime, changes, agentName) {
|
|
56
|
+
const now = new Date().toISOString();
|
|
57
|
+
const projectRoot = runtime.workflowConfig.projectRoot;
|
|
58
|
+
|
|
59
|
+
// Initialize fileTree if needed
|
|
60
|
+
if (!runtime._rawMemory.fileTree) {
|
|
61
|
+
runtime._rawMemory.fileTree = {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Handle created files
|
|
65
|
+
for (const filePath of changes.created) {
|
|
66
|
+
try {
|
|
67
|
+
const normalized = normalizePath(filePath, projectRoot);
|
|
68
|
+
runtime._rawMemory.fileTree[normalized] = {
|
|
69
|
+
path: normalized,
|
|
70
|
+
status: 'created',
|
|
71
|
+
createdBy: agentName,
|
|
72
|
+
lastModifiedBy: agentName,
|
|
73
|
+
createdAt: now,
|
|
74
|
+
updatedAt: now
|
|
75
|
+
};
|
|
76
|
+
} catch (e) {
|
|
77
|
+
// Skip files with invalid paths
|
|
78
|
+
console.warn(`[file-tree] Skipping invalid path: ${filePath} - ${e.message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Handle modified files
|
|
83
|
+
for (const filePath of changes.modified) {
|
|
84
|
+
try {
|
|
85
|
+
const normalized = normalizePath(filePath, projectRoot);
|
|
86
|
+
const existing = runtime._rawMemory.fileTree[normalized] || {};
|
|
87
|
+
runtime._rawMemory.fileTree[normalized] = {
|
|
88
|
+
...existing,
|
|
89
|
+
path: normalized,
|
|
90
|
+
status: 'modified',
|
|
91
|
+
lastModifiedBy: agentName,
|
|
92
|
+
updatedAt: now,
|
|
93
|
+
createdAt: existing.createdAt || now,
|
|
94
|
+
createdBy: existing.createdBy || agentName
|
|
95
|
+
};
|
|
96
|
+
} catch (e) {
|
|
97
|
+
console.warn(`[file-tree] Skipping invalid path: ${filePath} - ${e.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Handle renamed files (MVP: from/to pairs)
|
|
102
|
+
for (const { from, to } of changes.renamed) {
|
|
103
|
+
try {
|
|
104
|
+
const normalizedFrom = normalizePath(from, projectRoot);
|
|
105
|
+
const normalizedTo = normalizePath(to, projectRoot);
|
|
106
|
+
const existing = runtime._rawMemory.fileTree[normalizedFrom] || {};
|
|
107
|
+
delete runtime._rawMemory.fileTree[normalizedFrom];
|
|
108
|
+
runtime._rawMemory.fileTree[normalizedTo] = {
|
|
109
|
+
...existing,
|
|
110
|
+
path: normalizedTo,
|
|
111
|
+
status: 'renamed',
|
|
112
|
+
renamedFrom: normalizedFrom,
|
|
113
|
+
lastModifiedBy: agentName,
|
|
114
|
+
updatedAt: now
|
|
115
|
+
};
|
|
116
|
+
} catch (e) {
|
|
117
|
+
console.warn(`[file-tree] Skipping invalid rename: ${from} -> ${to} - ${e.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Handle deleted files
|
|
122
|
+
for (const filePath of changes.deleted) {
|
|
123
|
+
try {
|
|
124
|
+
const normalized = normalizePath(filePath, projectRoot);
|
|
125
|
+
if (runtime.workflowConfig.fileTrackingKeepDeleted) {
|
|
126
|
+
runtime._rawMemory.fileTree[normalized] = {
|
|
127
|
+
...runtime._rawMemory.fileTree[normalized],
|
|
128
|
+
status: 'deleted',
|
|
129
|
+
deletedBy: agentName,
|
|
130
|
+
deletedAt: now
|
|
131
|
+
};
|
|
132
|
+
} else {
|
|
133
|
+
delete runtime._rawMemory.fileTree[normalized];
|
|
134
|
+
}
|
|
135
|
+
} catch (e) {
|
|
136
|
+
console.warn(`[file-tree] Skipping invalid path: ${filePath} - ${e.message}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Trigger persistence
|
|
141
|
+
runtime.memory.fileTree = runtime._rawMemory.fileTree;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Merge _files annotations from agent result into fileTree.
|
|
146
|
+
* Only annotates files that were actually detected by change tracking.
|
|
147
|
+
* Preserves existing values unless explicitly overwritten.
|
|
148
|
+
*/
|
|
149
|
+
function mergeAnnotations(runtime, files) {
|
|
150
|
+
const projectRoot = runtime.workflowConfig.projectRoot;
|
|
151
|
+
|
|
152
|
+
for (const file of files) {
|
|
153
|
+
if (!file.path) continue;
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
const normalizedPath = normalizePath(file.path, projectRoot);
|
|
157
|
+
const existing = runtime._rawMemory.fileTree?.[normalizedPath];
|
|
158
|
+
|
|
159
|
+
if (!existing) continue; // Only annotate files that were actually detected
|
|
160
|
+
|
|
161
|
+
// Preserve existing values unless _files explicitly provides new ones
|
|
162
|
+
if (file.caption !== undefined) existing.caption = file.caption;
|
|
163
|
+
if (file.exports !== undefined) existing.exports = file.exports;
|
|
164
|
+
if (file.metadata !== undefined) {
|
|
165
|
+
existing.metadata = { ...existing.metadata, ...file.metadata };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Trigger best-effort export extraction if requested
|
|
169
|
+
if (file.extractExports) {
|
|
170
|
+
const absolutePath = path.resolve(projectRoot, normalizedPath);
|
|
171
|
+
const exports = extractExportsFromFile(absolutePath);
|
|
172
|
+
if (exports) existing.exports = exports;
|
|
173
|
+
}
|
|
174
|
+
} catch (e) {
|
|
175
|
+
console.warn(`[file-tree] Skipping invalid annotation path: ${file.path} - ${e.message}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Trigger persistence
|
|
180
|
+
runtime.memory.fileTree = runtime._rawMemory.fileTree;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Manually track a file in the fileTree.
|
|
185
|
+
* Used for files created outside of agent execution.
|
|
186
|
+
*/
|
|
187
|
+
export function trackFile(runtime, relativePath, options = {}) {
|
|
188
|
+
const projectRoot = runtime.workflowConfig.projectRoot;
|
|
189
|
+
const normalized = normalizePath(relativePath, projectRoot);
|
|
190
|
+
const now = new Date().toISOString();
|
|
191
|
+
const agentName = options.agentName || 'manual';
|
|
192
|
+
|
|
193
|
+
// Initialize fileTree if needed
|
|
194
|
+
if (!runtime._rawMemory.fileTree) {
|
|
195
|
+
runtime._rawMemory.fileTree = {};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const existing = runtime._rawMemory.fileTree[normalized];
|
|
199
|
+
|
|
200
|
+
const entry = {
|
|
201
|
+
path: normalized,
|
|
202
|
+
status: existing?.status || 'created',
|
|
203
|
+
createdBy: existing?.createdBy || agentName,
|
|
204
|
+
lastModifiedBy: agentName,
|
|
205
|
+
createdAt: existing?.createdAt || now,
|
|
206
|
+
updatedAt: now
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// Apply options
|
|
210
|
+
if (options.caption !== undefined) entry.caption = options.caption;
|
|
211
|
+
if (options.exports !== undefined) entry.exports = options.exports;
|
|
212
|
+
if (options.metadata !== undefined) {
|
|
213
|
+
entry.metadata = { ...existing?.metadata, ...options.metadata };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Extract exports if requested
|
|
217
|
+
if (options.extractExports) {
|
|
218
|
+
const absolutePath = path.resolve(projectRoot, normalized);
|
|
219
|
+
const exports = extractExportsFromFile(absolutePath);
|
|
220
|
+
if (exports) entry.exports = exports;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
runtime._rawMemory.fileTree[normalized] = entry;
|
|
224
|
+
|
|
225
|
+
// Trigger persistence
|
|
226
|
+
runtime.memory.fileTree = runtime._rawMemory.fileTree;
|
|
227
|
+
|
|
228
|
+
return entry;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get the current fileTree.
|
|
233
|
+
*/
|
|
234
|
+
export function getFileTree(runtime) {
|
|
235
|
+
return runtime._rawMemory.fileTree || {};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Remove a file from tracking.
|
|
240
|
+
*/
|
|
241
|
+
export function untrackFile(runtime, relativePath) {
|
|
242
|
+
const projectRoot = runtime.workflowConfig.projectRoot;
|
|
243
|
+
const normalized = normalizePath(relativePath, projectRoot);
|
|
244
|
+
|
|
245
|
+
if (runtime._rawMemory.fileTree?.[normalized]) {
|
|
246
|
+
delete runtime._rawMemory.fileTree[normalized];
|
|
247
|
+
runtime.memory.fileTree = runtime._rawMemory.fileTree;
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return false;
|
|
252
|
+
}
|
package/package.json
CHANGED
|
@@ -9,14 +9,6 @@ response: choice
|
|
|
9
9
|
|
|
10
10
|
You are an assumptions and constraints analyst. Your job is to identify and validate assumptions before development.
|
|
11
11
|
|
|
12
|
-
## Context
|
|
13
|
-
Project Description: {{projectDescription}}
|
|
14
|
-
Scope: {{scope}}
|
|
15
|
-
Requirements: {{requirements}}
|
|
16
|
-
{{#if previousResponse}}
|
|
17
|
-
User's Previous Response: {{previousResponse}}
|
|
18
|
-
{{/if}}
|
|
19
|
-
|
|
20
12
|
## Instructions
|
|
21
13
|
|
|
22
14
|
Identify implicit assumptions that could impact the project. Consider:
|
|
@@ -7,14 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a senior code reviewer. Review implementations for quality, correctness, and best practices.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Task: {{task}}
|
|
12
|
-
Implementation: {{implementation}}
|
|
13
|
-
Test Plan: {{testPlan}}
|
|
14
|
-
{{#if feedback}}
|
|
15
|
-
Previous Feedback: {{feedback}}
|
|
16
|
-
{{/if}}
|
|
17
|
-
|
|
18
10
|
## Instructions
|
|
19
11
|
|
|
20
12
|
Perform a thorough code review covering:
|
|
@@ -7,16 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a senior software developer. Implement the task according to specifications.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Task: {{task}}
|
|
12
|
-
Phase: {{phase}}
|
|
13
|
-
Requirements: {{requirements}}
|
|
14
|
-
Test Plan: {{testPlan}}
|
|
15
|
-
Security Considerations: {{securityConsiderations}}
|
|
16
|
-
{{#if feedback}}
|
|
17
|
-
Previous Feedback (IMPORTANT - address these issues): {{feedback}}
|
|
18
|
-
{{/if}}
|
|
19
|
-
|
|
20
10
|
## Instructions
|
|
21
11
|
|
|
22
12
|
Implement the task following these principles:
|
|
@@ -9,13 +9,6 @@ response: choice
|
|
|
9
9
|
|
|
10
10
|
You are a requirements analysis specialist. Your job is to gather and clarify functional and non-functional requirements.
|
|
11
11
|
|
|
12
|
-
## Context
|
|
13
|
-
Project Description: {{projectDescription}}
|
|
14
|
-
Scope: {{scope}}
|
|
15
|
-
{{#if previousResponse}}
|
|
16
|
-
User's Previous Response: {{previousResponse}}
|
|
17
|
-
{{/if}}
|
|
18
|
-
|
|
19
12
|
## Instructions
|
|
20
13
|
|
|
21
14
|
Based on the project description and scope, identify requirements that need clarification. Consider:
|
|
@@ -7,16 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a project planning specialist. Generate a phased development roadmap as structured JSON.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Project Description: {{projectDescription}}
|
|
12
|
-
Scope: {{scope}}
|
|
13
|
-
Requirements: {{requirements}}
|
|
14
|
-
Assumptions: {{assumptions}}
|
|
15
|
-
Security: {{security}}
|
|
16
|
-
{{#if feedback}}
|
|
17
|
-
User Feedback: {{feedback}}
|
|
18
|
-
{{/if}}
|
|
19
|
-
|
|
20
10
|
## Instructions
|
|
21
11
|
|
|
22
12
|
Create a phased roadmap as a JSON object. Each phase should:
|
|
@@ -9,12 +9,6 @@ response: choice
|
|
|
9
9
|
|
|
10
10
|
You are a project scope clarification specialist. Your job is to ensure the project scope is well-defined before development begins.
|
|
11
11
|
|
|
12
|
-
## Context
|
|
13
|
-
Project Description: {{projectDescription}}
|
|
14
|
-
{{#if previousResponse}}
|
|
15
|
-
User's Previous Response: {{previousResponse}}
|
|
16
|
-
{{/if}}
|
|
17
|
-
|
|
18
12
|
## Instructions
|
|
19
13
|
|
|
20
14
|
Analyze the project description and determine if the scope is clear. Consider:
|
|
@@ -9,15 +9,6 @@ response: choice
|
|
|
9
9
|
|
|
10
10
|
You are a security requirements specialist. Your job is to identify security needs and concerns early in the project.
|
|
11
11
|
|
|
12
|
-
## Context
|
|
13
|
-
Project Description: {{projectDescription}}
|
|
14
|
-
Scope: {{scope}}
|
|
15
|
-
Requirements: {{requirements}}
|
|
16
|
-
Assumptions: {{assumptions}}
|
|
17
|
-
{{#if previousResponse}}
|
|
18
|
-
User's Previous Response: {{previousResponse}}
|
|
19
|
-
{{/if}}
|
|
20
|
-
|
|
21
12
|
## Instructions
|
|
22
13
|
|
|
23
14
|
Analyze the project for security implications. Consider:
|
|
@@ -7,18 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a security review specialist. Review tasks and implementations for security concerns.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Task: {{task}}
|
|
12
|
-
Phase: {{phase}}
|
|
13
|
-
Scope: {{scope}}
|
|
14
|
-
Stage: {{stage}}
|
|
15
|
-
{{#if implementation}}
|
|
16
|
-
Implementation: {{implementation}}
|
|
17
|
-
{{/if}}
|
|
18
|
-
{{#if feedback}}
|
|
19
|
-
Previous Feedback: {{feedback}}
|
|
20
|
-
{{/if}}
|
|
21
|
-
|
|
22
10
|
## Instructions
|
|
23
11
|
|
|
24
12
|
Perform a security review appropriate to the stage:
|
|
@@ -7,16 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a task breakdown specialist. Generate detailed task lists for a specific phase as structured JSON.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Project Description: {{projectDescription}}
|
|
12
|
-
Scope: {{scope}}
|
|
13
|
-
Requirements: {{requirements}}
|
|
14
|
-
Phase Number: {{phaseIndex}}
|
|
15
|
-
Phase Details: {{phase}}
|
|
16
|
-
{{#if feedback}}
|
|
17
|
-
User Feedback: {{feedback}}
|
|
18
|
-
{{/if}}
|
|
19
|
-
|
|
20
10
|
## Instructions
|
|
21
11
|
|
|
22
12
|
Break down the phase into specific, actionable tasks. Each task should:
|
|
@@ -7,15 +7,6 @@ format: json
|
|
|
7
7
|
|
|
8
8
|
You are a test planning specialist. Create test plans for tasks before implementation.
|
|
9
9
|
|
|
10
|
-
## Context
|
|
11
|
-
Task: {{task}}
|
|
12
|
-
Phase: {{phase}}
|
|
13
|
-
Requirements: {{requirements}}
|
|
14
|
-
Security Considerations: {{securityConsiderations}}
|
|
15
|
-
{{#if feedback}}
|
|
16
|
-
Previous Feedback: {{feedback}}
|
|
17
|
-
{{/if}}
|
|
18
|
-
|
|
19
10
|
## Instructions
|
|
20
11
|
|
|
21
12
|
Create a comprehensive test plan for the task. Include:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export const config = {
|
|
2
2
|
models: {
|
|
3
|
+
fast: "gemini",
|
|
3
4
|
low: "gemini",
|
|
4
5
|
med: "gemini",
|
|
5
6
|
high: "gemini",
|
|
@@ -8,5 +9,16 @@ export const config = {
|
|
|
8
9
|
gemini: process.env.GEMINI_API_KEY,
|
|
9
10
|
anthropic: process.env.ANTHROPIC_API_KEY,
|
|
10
11
|
openai: process.env.OPENAI_API_KEY,
|
|
11
|
-
}
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
// File tracking (all optional - shown with defaults)
|
|
15
|
+
// projectRoot: process.env.PROJECT_ROOT, // Defaults to ../.. from workflow
|
|
16
|
+
// fileTracking: true, // Enable/disable file tracking
|
|
17
|
+
// fileTrackingIgnore: [ // Glob patterns to ignore
|
|
18
|
+
// 'node_modules/**',
|
|
19
|
+
// '.git/**',
|
|
20
|
+
// 'dist/**',
|
|
21
|
+
// 'workflows/**'
|
|
22
|
+
// ],
|
|
23
|
+
// fileTrackingKeepDeleted: false // Keep deleted files in tree
|
|
12
24
|
};
|
|
@@ -8,5 +8,16 @@ export const config = {
|
|
|
8
8
|
gemini: process.env.GEMINI_API_KEY,
|
|
9
9
|
anthropic: process.env.ANTHROPIC_API_KEY,
|
|
10
10
|
openai: process.env.OPENAI_API_KEY,
|
|
11
|
-
}
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// File tracking (all optional - shown with defaults)
|
|
14
|
+
// projectRoot: process.env.PROJECT_ROOT, // Defaults to ../.. from workflow
|
|
15
|
+
// fileTracking: true, // Enable/disable file tracking
|
|
16
|
+
// fileTrackingIgnore: [ // Glob patterns to ignore
|
|
17
|
+
// 'node_modules/**',
|
|
18
|
+
// '.git/**',
|
|
19
|
+
// 'dist/**',
|
|
20
|
+
// 'workflows/**'
|
|
21
|
+
// ],
|
|
22
|
+
// fileTrackingKeepDeleted: false // Keep deleted files in tree
|
|
12
23
|
};
|