agileflow 2.90.7 → 2.92.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/CHANGELOG.md +10 -0
- package/README.md +6 -6
- package/lib/README.md +178 -0
- package/lib/codebase-indexer.js +818 -0
- package/lib/colors.js +190 -12
- package/lib/consent.js +232 -0
- package/lib/correlation.js +277 -0
- package/lib/error-codes.js +46 -0
- package/lib/errors.js +48 -6
- package/lib/file-cache.js +182 -0
- package/lib/format-error.js +156 -0
- package/lib/path-resolver.js +155 -7
- package/lib/paths.js +212 -20
- package/lib/placeholder-registry.js +205 -0
- package/lib/registry-di.js +358 -0
- package/lib/result-schema.js +363 -0
- package/lib/result.js +210 -0
- package/lib/session-registry.js +13 -0
- package/lib/session-state-machine.js +465 -0
- package/lib/validate-commands.js +308 -0
- package/lib/validate-names.js +3 -3
- package/lib/validate.js +116 -52
- package/package.json +4 -1
- package/scripts/af +34 -0
- package/scripts/agent-loop.js +63 -9
- package/scripts/agileflow-configure.js +2 -2
- package/scripts/agileflow-welcome.js +435 -23
- package/scripts/archive-completed-stories.sh +57 -11
- package/scripts/claude-tmux.sh +102 -0
- package/scripts/damage-control-bash.js +3 -70
- package/scripts/damage-control-edit.js +3 -20
- package/scripts/damage-control-write.js +3 -20
- package/scripts/dependency-check.js +310 -0
- package/scripts/get-env.js +11 -4
- package/scripts/lib/configure-detect.js +23 -1
- package/scripts/lib/configure-features.js +43 -2
- package/scripts/lib/context-formatter.js +771 -0
- package/scripts/lib/context-loader.js +699 -0
- package/scripts/lib/damage-control-utils.js +107 -0
- package/scripts/lib/json-utils.sh +162 -0
- package/scripts/lib/state-migrator.js +353 -0
- package/scripts/lib/story-state-machine.js +437 -0
- package/scripts/obtain-context.js +118 -1048
- package/scripts/pre-push-check.sh +46 -0
- package/scripts/precompact-context.sh +36 -11
- package/scripts/query-codebase.js +538 -0
- package/scripts/ralph-loop.js +5 -5
- package/scripts/session-manager.js +220 -42
- package/scripts/spawn-parallel.js +651 -0
- package/scripts/tui/blessed/data/watcher.js +180 -0
- package/scripts/tui/blessed/index.js +244 -0
- package/scripts/tui/blessed/panels/output.js +101 -0
- package/scripts/tui/blessed/panels/sessions.js +150 -0
- package/scripts/tui/blessed/panels/trace.js +97 -0
- package/scripts/tui/blessed/ui/help.js +77 -0
- package/scripts/tui/blessed/ui/screen.js +52 -0
- package/scripts/tui/blessed/ui/statusbar.js +47 -0
- package/scripts/tui/blessed/ui/tabbar.js +99 -0
- package/scripts/tui/index.js +38 -30
- package/scripts/validators/README.md +143 -0
- package/scripts/validators/component-validator.js +239 -0
- package/scripts/validators/json-schema-validator.js +186 -0
- package/scripts/validators/markdown-validator.js +152 -0
- package/scripts/validators/migration-validator.js +129 -0
- package/scripts/validators/security-validator.js +380 -0
- package/scripts/validators/story-format-validator.js +197 -0
- package/scripts/validators/test-result-validator.js +114 -0
- package/scripts/validators/workflow-validator.js +247 -0
- package/src/core/agents/accessibility.md +6 -0
- package/src/core/agents/adr-writer.md +6 -0
- package/src/core/agents/analytics.md +6 -0
- package/src/core/agents/api.md +6 -0
- package/src/core/agents/ci.md +6 -0
- package/src/core/agents/codebase-query.md +261 -0
- package/src/core/agents/compliance.md +6 -0
- package/src/core/agents/configuration-damage-control.md +6 -0
- package/src/core/agents/configuration-visual-e2e.md +6 -0
- package/src/core/agents/database.md +10 -0
- package/src/core/agents/datamigration.md +6 -0
- package/src/core/agents/design.md +6 -0
- package/src/core/agents/devops.md +6 -0
- package/src/core/agents/documentation.md +6 -0
- package/src/core/agents/epic-planner.md +6 -0
- package/src/core/agents/integrations.md +6 -0
- package/src/core/agents/mentor.md +6 -0
- package/src/core/agents/mobile.md +6 -0
- package/src/core/agents/monitoring.md +6 -0
- package/src/core/agents/multi-expert.md +6 -0
- package/src/core/agents/performance.md +6 -0
- package/src/core/agents/product.md +6 -0
- package/src/core/agents/qa.md +6 -0
- package/src/core/agents/readme-updater.md +6 -0
- package/src/core/agents/refactor.md +6 -0
- package/src/core/agents/research.md +6 -0
- package/src/core/agents/security.md +6 -0
- package/src/core/agents/testing.md +10 -0
- package/src/core/agents/ui.md +6 -0
- package/src/core/commands/adr.md +114 -0
- package/src/core/commands/agent.md +120 -0
- package/src/core/commands/assign.md +145 -0
- package/src/core/commands/audit.md +401 -0
- package/src/core/commands/babysit.md +32 -5
- package/src/core/commands/board.md +1 -0
- package/src/core/commands/changelog.md +118 -0
- package/src/core/commands/configure.md +42 -6
- package/src/core/commands/diagnose.md +114 -0
- package/src/core/commands/epic.md +205 -1
- package/src/core/commands/handoff.md +128 -0
- package/src/core/commands/help.md +76 -0
- package/src/core/commands/metrics.md +1 -0
- package/src/core/commands/pr.md +96 -0
- package/src/core/commands/research/analyze.md +1 -0
- package/src/core/commands/research/ask.md +2 -0
- package/src/core/commands/research/import.md +1 -0
- package/src/core/commands/research/list.md +2 -0
- package/src/core/commands/research/synthesize.md +584 -0
- package/src/core/commands/research/view.md +2 -0
- package/src/core/commands/roadmap/analyze.md +400 -0
- package/src/core/commands/session/new.md +113 -6
- package/src/core/commands/session/spawn.md +197 -0
- package/src/core/commands/sprint.md +22 -0
- package/src/core/commands/status.md +200 -1
- package/src/core/commands/story/list.md +9 -9
- package/src/core/commands/story/view.md +1 -0
- package/src/core/commands/story.md +143 -4
- package/src/core/experts/codebase-query/expertise.yaml +190 -0
- package/src/core/experts/codebase-query/question.md +73 -0
- package/src/core/experts/codebase-query/self-improve.md +105 -0
- package/src/core/templates/agileflow-metadata.json +55 -2
- package/src/core/templates/plan-template.md +125 -0
- package/src/core/templates/story-lifecycle.md +213 -0
- package/src/core/templates/story-template.md +4 -0
- package/src/core/templates/tdd-test-template.js +241 -0
- package/tools/cli/commands/setup.js +86 -0
- package/tools/cli/installers/core/installer.js +94 -0
- package/tools/cli/installers/ide/_base-ide.js +20 -11
- package/tools/cli/installers/ide/codex.js +29 -47
- package/tools/cli/lib/config-manager.js +17 -2
- package/tools/cli/lib/content-transformer.js +271 -0
- package/tools/cli/lib/error-handler.js +14 -22
- package/tools/cli/lib/ide-error-factory.js +421 -0
- package/tools/cli/lib/ide-health-monitor.js +364 -0
- package/tools/cli/lib/ide-registry.js +114 -1
- package/tools/cli/lib/ui.js +14 -25
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* format-error.js - Standalone error formatting helpers
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ErrorHandler for use without class instantiation.
|
|
5
|
+
* Provides consistent error/warning formatting with actionable guidance.
|
|
6
|
+
*
|
|
7
|
+
* Format: "X <problem> | Action: <what to do> | Run: <command>"
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* const { formatError, formatWarning, formatSuccess, formatInfo } = require('./format-error');
|
|
11
|
+
* console.error(formatError('File not found', 'Check the path', 'ls -la'));
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { c } = require('./colors');
|
|
15
|
+
|
|
16
|
+
// Unicode symbols
|
|
17
|
+
const SYMBOLS = {
|
|
18
|
+
error: '\u2716', // ✖
|
|
19
|
+
warning: '\u26A0', // ⚠
|
|
20
|
+
success: '\u2714', // ✔
|
|
21
|
+
info: '\u2139', // ℹ
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Format a message with optional action and command hints
|
|
26
|
+
*
|
|
27
|
+
* @param {string} symbol - Unicode symbol to use
|
|
28
|
+
* @param {string} symbolColor - Color for the symbol
|
|
29
|
+
* @param {string} message - The message to display
|
|
30
|
+
* @param {Object} [options={}] - Formatting options
|
|
31
|
+
* @param {string} [options.action] - Action text (what user should do)
|
|
32
|
+
* @param {string} [options.command] - Command to run
|
|
33
|
+
* @param {string} [options.detail] - Additional detail line
|
|
34
|
+
* @returns {string} Formatted message string
|
|
35
|
+
*/
|
|
36
|
+
function formatMessage(symbol, symbolColor, message, options = {}) {
|
|
37
|
+
const { action, command, detail } = options;
|
|
38
|
+
|
|
39
|
+
let output = `${symbolColor}${symbol}${c.reset} ${message}`;
|
|
40
|
+
|
|
41
|
+
if (action) {
|
|
42
|
+
output += ` ${c.dim}|${c.reset} ${c.cyan}Action:${c.reset} ${action}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (command) {
|
|
46
|
+
output += ` ${c.dim}|${c.reset} ${c.green}Run:${c.reset} ${c.bold}${command}${c.reset}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (detail) {
|
|
50
|
+
output += `\n ${c.dim}${detail}${c.reset}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return output;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Format an error message (red X)
|
|
58
|
+
*
|
|
59
|
+
* @param {string} message - Error message
|
|
60
|
+
* @param {string} [action] - What user should do
|
|
61
|
+
* @param {string} [command] - Command to run
|
|
62
|
+
* @returns {string} Formatted error string
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* formatError('Config not found', 'Create config file', 'npx agileflow setup')
|
|
66
|
+
* // Output: ✖ Config not found | Action: Create config file | Run: npx agileflow setup
|
|
67
|
+
*/
|
|
68
|
+
function formatError(message, action, command) {
|
|
69
|
+
return formatMessage(SYMBOLS.error, c.red, message, { action, command });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Format a warning message (yellow warning sign)
|
|
74
|
+
*
|
|
75
|
+
* @param {string} message - Warning message
|
|
76
|
+
* @param {string} [action] - What user should do
|
|
77
|
+
* @param {string} [command] - Command to run
|
|
78
|
+
* @returns {string} Formatted warning string
|
|
79
|
+
*/
|
|
80
|
+
function formatWarning(message, action, command) {
|
|
81
|
+
return formatMessage(SYMBOLS.warning, c.yellow, message, { action, command });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Format a success message (green checkmark)
|
|
86
|
+
*
|
|
87
|
+
* @param {string} message - Success message
|
|
88
|
+
* @param {string} [detail] - Additional detail
|
|
89
|
+
* @returns {string} Formatted success string
|
|
90
|
+
*/
|
|
91
|
+
function formatSuccess(message, detail) {
|
|
92
|
+
return formatMessage(SYMBOLS.success, c.green, message, { detail });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Format an info message (blue info symbol)
|
|
97
|
+
*
|
|
98
|
+
* @param {string} message - Info message
|
|
99
|
+
* @param {string} [detail] - Additional detail
|
|
100
|
+
* @returns {string} Formatted info string
|
|
101
|
+
*/
|
|
102
|
+
function formatInfo(message, detail) {
|
|
103
|
+
return formatMessage(SYMBOLS.info, c.blue, message, { detail });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Format multiple issues for display
|
|
108
|
+
*
|
|
109
|
+
* @param {Array<{type: 'error'|'warning'|'success'|'info', message: string, action?: string, command?: string}>} issues
|
|
110
|
+
* @returns {string[]} Array of formatted strings
|
|
111
|
+
*/
|
|
112
|
+
function formatIssues(issues) {
|
|
113
|
+
return issues.map(issue => {
|
|
114
|
+
switch (issue.type) {
|
|
115
|
+
case 'error':
|
|
116
|
+
return formatError(issue.message, issue.action, issue.command);
|
|
117
|
+
case 'warning':
|
|
118
|
+
return formatWarning(issue.message, issue.action, issue.command);
|
|
119
|
+
case 'success':
|
|
120
|
+
return formatSuccess(issue.message, issue.detail);
|
|
121
|
+
case 'info':
|
|
122
|
+
return formatInfo(issue.message, issue.detail);
|
|
123
|
+
default:
|
|
124
|
+
return formatInfo(issue.message);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Format error with stack trace (for DEBUG mode)
|
|
131
|
+
*
|
|
132
|
+
* @param {string} message - Error message
|
|
133
|
+
* @param {Error} error - Error object with stack
|
|
134
|
+
* @param {Object} [options={}] - Formatting options
|
|
135
|
+
* @returns {string} Formatted error with optional stack trace
|
|
136
|
+
*/
|
|
137
|
+
function formatErrorWithStack(message, error, options = {}) {
|
|
138
|
+
const base = formatError(message, options.action, options.command);
|
|
139
|
+
|
|
140
|
+
if (process.env.DEBUG === '1' && error?.stack) {
|
|
141
|
+
return `${base}\n\n${c.dim}Stack trace:${c.reset}\n${c.dim}${error.stack}${c.reset}`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return base;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
module.exports = {
|
|
148
|
+
formatError,
|
|
149
|
+
formatWarning,
|
|
150
|
+
formatSuccess,
|
|
151
|
+
formatInfo,
|
|
152
|
+
formatIssues,
|
|
153
|
+
formatErrorWithStack,
|
|
154
|
+
formatMessage,
|
|
155
|
+
SYMBOLS,
|
|
156
|
+
};
|
package/lib/path-resolver.js
CHANGED
|
@@ -48,11 +48,17 @@ class PathResolver {
|
|
|
48
48
|
this._defaultDocsFolder = docsFolder;
|
|
49
49
|
|
|
50
50
|
// Find project root
|
|
51
|
-
if (projectRoot) {
|
|
51
|
+
if (projectRoot && autoDetect) {
|
|
52
|
+
// Auto-detect from provided starting directory
|
|
53
|
+
this._projectRoot = this._findProjectRoot(projectRoot);
|
|
54
|
+
} else if (projectRoot) {
|
|
55
|
+
// Use provided directory directly (no auto-detection)
|
|
52
56
|
this._projectRoot = projectRoot;
|
|
53
57
|
} else if (autoDetect) {
|
|
58
|
+
// Auto-detect from current working directory
|
|
54
59
|
this._projectRoot = this._findProjectRoot(process.cwd());
|
|
55
60
|
} else {
|
|
61
|
+
// Use current working directory directly
|
|
56
62
|
this._projectRoot = process.cwd();
|
|
57
63
|
}
|
|
58
64
|
|
|
@@ -256,31 +262,173 @@ class PathResolver {
|
|
|
256
262
|
}
|
|
257
263
|
|
|
258
264
|
/**
|
|
259
|
-
* Get the agents directory path
|
|
265
|
+
* Get the agents directory path (.agileflow/agents)
|
|
260
266
|
* @returns {string}
|
|
261
267
|
*/
|
|
262
268
|
getAgentsDir() {
|
|
263
269
|
return path.join(this.getAgileflowDir(), 'agents');
|
|
264
270
|
}
|
|
265
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Get the skills directory path
|
|
274
|
+
* @returns {string}
|
|
275
|
+
*/
|
|
276
|
+
getSkillsDir() {
|
|
277
|
+
return path.join(this.getAgileflowDir(), 'skills');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Get the _cfg directory path
|
|
282
|
+
* @returns {string}
|
|
283
|
+
*/
|
|
284
|
+
getCfgDir() {
|
|
285
|
+
return path.join(this.getAgileflowDir(), '_cfg');
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ============================================================================
|
|
289
|
+
// Claude Settings Paths (new in ConfigResolver pattern)
|
|
290
|
+
// ============================================================================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get the .claude/settings.json path
|
|
294
|
+
* @returns {string}
|
|
295
|
+
*/
|
|
296
|
+
getSettingsPath() {
|
|
297
|
+
return path.join(this.getClaudeDir(), 'settings.json');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Get the .claude/settings.local.json path
|
|
302
|
+
* @returns {string}
|
|
303
|
+
*/
|
|
304
|
+
getSettingsLocalPath() {
|
|
305
|
+
return path.join(this.getClaudeDir(), 'settings.local.json');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Get the .claude/settings.local.example.json path
|
|
310
|
+
* @returns {string}
|
|
311
|
+
*/
|
|
312
|
+
getSettingsLocalExamplePath() {
|
|
313
|
+
return path.join(this.getClaudeDir(), 'settings.local.example.json');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// ============================================================================
|
|
317
|
+
// Docs Subdirectory Paths (new in ConfigResolver pattern)
|
|
318
|
+
// ============================================================================
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Get the docs/09-agents directory path
|
|
322
|
+
* @returns {string}
|
|
323
|
+
*/
|
|
324
|
+
getDocsAgentsDir() {
|
|
325
|
+
return path.join(this.getDocsDir(), '09-agents');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get the bus log path (docs/09-agents/bus/log.jsonl)
|
|
330
|
+
* @returns {string}
|
|
331
|
+
*/
|
|
332
|
+
getBusLogPath() {
|
|
333
|
+
return path.join(this.getDocsAgentsDir(), 'bus', 'log.jsonl');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Get the archive directory path (docs/09-agents/archive)
|
|
338
|
+
* @returns {string}
|
|
339
|
+
*/
|
|
340
|
+
getArchiveDir() {
|
|
341
|
+
return path.join(this.getDocsAgentsDir(), 'archive');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Get the epics directory path (docs/05-epics)
|
|
346
|
+
* @returns {string}
|
|
347
|
+
*/
|
|
348
|
+
getEpicsDir() {
|
|
349
|
+
return path.join(this.getDocsDir(), '05-epics');
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get the stories directory path (docs/06-stories)
|
|
354
|
+
* @returns {string}
|
|
355
|
+
*/
|
|
356
|
+
getStoriesDir() {
|
|
357
|
+
return path.join(this.getDocsDir(), '06-stories');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Get the decisions (ADR) directory path (docs/03-decisions)
|
|
362
|
+
* @returns {string}
|
|
363
|
+
*/
|
|
364
|
+
getDecisionsDir() {
|
|
365
|
+
return path.join(this.getDocsDir(), '03-decisions');
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get the research directory path (docs/10-research)
|
|
370
|
+
* @returns {string}
|
|
371
|
+
*/
|
|
372
|
+
getResearchDir() {
|
|
373
|
+
return path.join(this.getDocsDir(), '10-research');
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Get the testing directory path (docs/07-testing)
|
|
378
|
+
* @returns {string}
|
|
379
|
+
*/
|
|
380
|
+
getTestingDir() {
|
|
381
|
+
return path.join(this.getDocsDir(), '07-testing');
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Get the architecture directory path (docs/04-architecture)
|
|
386
|
+
* @returns {string}
|
|
387
|
+
*/
|
|
388
|
+
getArchitectureDir() {
|
|
389
|
+
return path.join(this.getDocsDir(), '04-architecture');
|
|
390
|
+
}
|
|
391
|
+
|
|
266
392
|
/**
|
|
267
393
|
* Get all paths at once
|
|
268
394
|
* @returns {Object} Object with all path values
|
|
269
395
|
*/
|
|
270
396
|
getAllPaths() {
|
|
271
397
|
return {
|
|
398
|
+
// Project root and main directories
|
|
272
399
|
projectRoot: this.getProjectRoot(),
|
|
273
400
|
agileflowDir: this.getAgileflowDir(),
|
|
274
401
|
docsDir: this.getDocsDir(),
|
|
275
402
|
claudeDir: this.getClaudeDir(),
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
metadataPath: this.getMetadataPath(),
|
|
279
|
-
configPath: this.getConfigPath(),
|
|
280
|
-
manifestPath: this.getManifestPath(),
|
|
403
|
+
|
|
404
|
+
// AgileFlow subdirectories
|
|
281
405
|
scriptsDir: this.getScriptsDir(),
|
|
282
406
|
commandsDir: this.getCommandsDir(),
|
|
283
407
|
agentsDir: this.getAgentsDir(),
|
|
408
|
+
skillsDir: this.getSkillsDir(),
|
|
409
|
+
cfgDir: this.getCfgDir(),
|
|
410
|
+
|
|
411
|
+
// Configuration files
|
|
412
|
+
configPath: this.getConfigPath(),
|
|
413
|
+
manifestPath: this.getManifestPath(),
|
|
414
|
+
settingsPath: this.getSettingsPath(),
|
|
415
|
+
settingsLocalPath: this.getSettingsLocalPath(),
|
|
416
|
+
|
|
417
|
+
// Status and state files
|
|
418
|
+
statusPath: this.getStatusPath(),
|
|
419
|
+
sessionStatePath: this.getSessionStatePath(),
|
|
420
|
+
metadataPath: this.getMetadataPath(),
|
|
421
|
+
busLogPath: this.getBusLogPath(),
|
|
422
|
+
|
|
423
|
+
// Docs subdirectories
|
|
424
|
+
docsAgentsDir: this.getDocsAgentsDir(),
|
|
425
|
+
archiveDir: this.getArchiveDir(),
|
|
426
|
+
epicsDir: this.getEpicsDir(),
|
|
427
|
+
storiesDir: this.getStoriesDir(),
|
|
428
|
+
decisionsDir: this.getDecisionsDir(),
|
|
429
|
+
researchDir: this.getResearchDir(),
|
|
430
|
+
testingDir: this.getTestingDir(),
|
|
431
|
+
architectureDir: this.getArchitectureDir(),
|
|
284
432
|
};
|
|
285
433
|
}
|
|
286
434
|
|
package/lib/paths.js
CHANGED
|
@@ -2,11 +2,43 @@
|
|
|
2
2
|
* AgileFlow CLI - Shared Path Utilities
|
|
3
3
|
*
|
|
4
4
|
* Centralized path resolution functions used across scripts.
|
|
5
|
+
*
|
|
6
|
+
* NOTE: This module delegates to PathResolver for the implementation.
|
|
7
|
+
* Functions accept optional rootDir for backwards compatibility, but
|
|
8
|
+
* if not provided, use PathResolver's manifest-aware auto-detection.
|
|
9
|
+
*
|
|
10
|
+
* For new code, prefer using PathResolver directly:
|
|
11
|
+
* const { PathResolver, getDefaultResolver } = require('./path-resolver');
|
|
12
|
+
* const resolver = getDefaultResolver();
|
|
13
|
+
* const statusPath = resolver.getStatusPath();
|
|
5
14
|
*/
|
|
6
15
|
|
|
7
|
-
const
|
|
16
|
+
const { PathResolver, getDefaultResolver } = require('./path-resolver');
|
|
8
17
|
const path = require('path');
|
|
9
18
|
|
|
19
|
+
// Cache for resolvers by rootDir
|
|
20
|
+
const resolverCache = new Map();
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get a PathResolver for the given rootDir.
|
|
24
|
+
* Uses singleton for default (no rootDir) case, caches others.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
27
|
+
* @returns {PathResolver}
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
function getResolver(rootDir) {
|
|
31
|
+
if (!rootDir) {
|
|
32
|
+
return getDefaultResolver();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Cache resolvers by rootDir to avoid repeated construction
|
|
36
|
+
if (!resolverCache.has(rootDir)) {
|
|
37
|
+
resolverCache.set(rootDir, new PathResolver(rootDir, { autoDetect: false }));
|
|
38
|
+
}
|
|
39
|
+
return resolverCache.get(rootDir);
|
|
40
|
+
}
|
|
41
|
+
|
|
10
42
|
/**
|
|
11
43
|
* Find the project root by looking for .agileflow directory.
|
|
12
44
|
* Walks up from current directory until .agileflow is found.
|
|
@@ -15,11 +47,8 @@ const path = require('path');
|
|
|
15
47
|
* @returns {string} Project root path, or startDir if not found
|
|
16
48
|
*/
|
|
17
49
|
function getProjectRoot(startDir = process.cwd()) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
dir = path.dirname(dir);
|
|
21
|
-
}
|
|
22
|
-
return dir !== '/' ? dir : startDir;
|
|
50
|
+
const resolver = new PathResolver(startDir, { autoDetect: true });
|
|
51
|
+
return resolver.getProjectRoot();
|
|
23
52
|
}
|
|
24
53
|
|
|
25
54
|
/**
|
|
@@ -29,8 +58,7 @@ function getProjectRoot(startDir = process.cwd()) {
|
|
|
29
58
|
* @returns {string} Path to .agileflow directory
|
|
30
59
|
*/
|
|
31
60
|
function getAgileflowDir(rootDir) {
|
|
32
|
-
|
|
33
|
-
return path.join(root, '.agileflow');
|
|
61
|
+
return getResolver(rootDir).getAgileflowDir();
|
|
34
62
|
}
|
|
35
63
|
|
|
36
64
|
/**
|
|
@@ -40,8 +68,7 @@ function getAgileflowDir(rootDir) {
|
|
|
40
68
|
* @returns {string} Path to .claude directory
|
|
41
69
|
*/
|
|
42
70
|
function getClaudeDir(rootDir) {
|
|
43
|
-
|
|
44
|
-
return path.join(root, '.claude');
|
|
71
|
+
return getResolver(rootDir).getClaudeDir();
|
|
45
72
|
}
|
|
46
73
|
|
|
47
74
|
/**
|
|
@@ -51,8 +78,7 @@ function getClaudeDir(rootDir) {
|
|
|
51
78
|
* @returns {string} Path to docs directory
|
|
52
79
|
*/
|
|
53
80
|
function getDocsDir(rootDir) {
|
|
54
|
-
|
|
55
|
-
return path.join(root, 'docs');
|
|
81
|
+
return getResolver(rootDir).getDocsDir();
|
|
56
82
|
}
|
|
57
83
|
|
|
58
84
|
/**
|
|
@@ -62,8 +88,7 @@ function getDocsDir(rootDir) {
|
|
|
62
88
|
* @returns {string} Path to status.json
|
|
63
89
|
*/
|
|
64
90
|
function getStatusPath(rootDir) {
|
|
65
|
-
|
|
66
|
-
return path.join(root, 'docs', '09-agents', 'status.json');
|
|
91
|
+
return getResolver(rootDir).getStatusPath();
|
|
67
92
|
}
|
|
68
93
|
|
|
69
94
|
/**
|
|
@@ -73,27 +98,194 @@ function getStatusPath(rootDir) {
|
|
|
73
98
|
* @returns {string} Path to session-state.json
|
|
74
99
|
*/
|
|
75
100
|
function getSessionStatePath(rootDir) {
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
return getResolver(rootDir).getSessionStatePath();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the agileflow-metadata.json path.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
108
|
+
* @returns {string} Path to agileflow-metadata.json
|
|
109
|
+
*/
|
|
110
|
+
function getMetadataPath(rootDir) {
|
|
111
|
+
return getResolver(rootDir).getMetadataPath();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Get the message bus log path.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
118
|
+
* @returns {string} Path to bus/log.jsonl
|
|
119
|
+
*/
|
|
120
|
+
function getBusLogPath(rootDir) {
|
|
121
|
+
return getResolver(rootDir).getBusLogPath();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get the epics directory path.
|
|
126
|
+
*
|
|
127
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
128
|
+
* @returns {string} Path to epics directory
|
|
129
|
+
*/
|
|
130
|
+
function getEpicsDir(rootDir) {
|
|
131
|
+
return getResolver(rootDir).getEpicsDir();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Get the stories directory path.
|
|
136
|
+
*
|
|
137
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
138
|
+
* @returns {string} Path to stories directory
|
|
139
|
+
*/
|
|
140
|
+
function getStoriesDir(rootDir) {
|
|
141
|
+
return getResolver(rootDir).getStoriesDir();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Get the archive directory path for completed stories.
|
|
146
|
+
*
|
|
147
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
148
|
+
* @returns {string} Path to archive directory
|
|
149
|
+
*/
|
|
150
|
+
function getArchiveDir(rootDir) {
|
|
151
|
+
return getResolver(rootDir).getArchiveDir();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get the agents directory path (docs/09-agents).
|
|
156
|
+
*
|
|
157
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
158
|
+
* @returns {string} Path to agents directory (docs/09-agents)
|
|
159
|
+
*/
|
|
160
|
+
function getAgentsDir(rootDir) {
|
|
161
|
+
return getResolver(rootDir).getDocsAgentsDir();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get the decisions (ADR) directory path.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
168
|
+
* @returns {string} Path to decisions directory
|
|
169
|
+
*/
|
|
170
|
+
function getDecisionsDir(rootDir) {
|
|
171
|
+
return getResolver(rootDir).getDecisionsDir();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get the research directory path.
|
|
176
|
+
*
|
|
177
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
178
|
+
* @returns {string} Path to research directory
|
|
179
|
+
*/
|
|
180
|
+
function getResearchDir(rootDir) {
|
|
181
|
+
return getResolver(rootDir).getResearchDir();
|
|
78
182
|
}
|
|
79
183
|
|
|
80
184
|
/**
|
|
81
185
|
* Check if we're in an AgileFlow project.
|
|
186
|
+
* Walks up from dir to find .agileflow directory.
|
|
82
187
|
*
|
|
83
|
-
* @param {string} [dir=process.cwd()] - Directory to check
|
|
84
|
-
* @returns {boolean} True if .agileflow directory exists
|
|
188
|
+
* @param {string} [dir=process.cwd()] - Directory to check from
|
|
189
|
+
* @returns {boolean} True if .agileflow directory exists in dir or any parent
|
|
85
190
|
*/
|
|
86
191
|
function isAgileflowProject(dir = process.cwd()) {
|
|
87
|
-
|
|
88
|
-
|
|
192
|
+
// Use auto-detection to walk up and find project root
|
|
193
|
+
const resolver = new PathResolver(dir, { autoDetect: true });
|
|
194
|
+
return resolver.isAgileflowProject();
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ============================================================================
|
|
198
|
+
// New functions (added in ConfigResolver consolidation)
|
|
199
|
+
// ============================================================================
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get the .claude/settings.json path.
|
|
203
|
+
*
|
|
204
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
205
|
+
* @returns {string} Path to settings.json
|
|
206
|
+
*/
|
|
207
|
+
function getSettingsPath(rootDir) {
|
|
208
|
+
return getResolver(rootDir).getSettingsPath();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get the .claude/settings.local.json path.
|
|
213
|
+
*
|
|
214
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
215
|
+
* @returns {string} Path to settings.local.json
|
|
216
|
+
*/
|
|
217
|
+
function getSettingsLocalPath(rootDir) {
|
|
218
|
+
return getResolver(rootDir).getSettingsLocalPath();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get the skills directory path.
|
|
223
|
+
*
|
|
224
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
225
|
+
* @returns {string} Path to skills directory
|
|
226
|
+
*/
|
|
227
|
+
function getSkillsDir(rootDir) {
|
|
228
|
+
return getResolver(rootDir).getSkillsDir();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get the scripts directory path.
|
|
233
|
+
*
|
|
234
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
235
|
+
* @returns {string} Path to scripts directory
|
|
236
|
+
*/
|
|
237
|
+
function getScriptsDir(rootDir) {
|
|
238
|
+
return getResolver(rootDir).getScriptsDir();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Get the commands directory path.
|
|
243
|
+
*
|
|
244
|
+
* @param {string} [rootDir] - Project root (auto-detected if not provided)
|
|
245
|
+
* @returns {string} Path to commands directory
|
|
246
|
+
*/
|
|
247
|
+
function getCommandsDir(rootDir) {
|
|
248
|
+
return getResolver(rootDir).getCommandsDir();
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Clear the resolver cache (useful for testing or after config changes).
|
|
253
|
+
*/
|
|
254
|
+
function clearResolverCache() {
|
|
255
|
+
resolverCache.clear();
|
|
89
256
|
}
|
|
90
257
|
|
|
91
258
|
module.exports = {
|
|
259
|
+
// Root and base directories
|
|
92
260
|
getProjectRoot,
|
|
93
261
|
getAgileflowDir,
|
|
94
262
|
getClaudeDir,
|
|
95
263
|
getDocsDir,
|
|
264
|
+
|
|
265
|
+
// Status and session files
|
|
96
266
|
getStatusPath,
|
|
97
267
|
getSessionStatePath,
|
|
268
|
+
getMetadataPath,
|
|
269
|
+
getBusLogPath,
|
|
270
|
+
|
|
271
|
+
// Documentation directories
|
|
272
|
+
getEpicsDir,
|
|
273
|
+
getStoriesDir,
|
|
274
|
+
getArchiveDir,
|
|
275
|
+
getAgentsDir,
|
|
276
|
+
getDecisionsDir,
|
|
277
|
+
getResearchDir,
|
|
278
|
+
|
|
279
|
+
// Configuration files (new in ConfigResolver consolidation)
|
|
280
|
+
getSettingsPath,
|
|
281
|
+
getSettingsLocalPath,
|
|
282
|
+
|
|
283
|
+
// AgileFlow subdirectories (new in ConfigResolver consolidation)
|
|
284
|
+
getSkillsDir,
|
|
285
|
+
getScriptsDir,
|
|
286
|
+
getCommandsDir,
|
|
287
|
+
|
|
288
|
+
// Utilities
|
|
98
289
|
isAgileflowProject,
|
|
290
|
+
clearResolverCache,
|
|
99
291
|
};
|