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.
Files changed (144) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/README.md +178 -0
  4. package/lib/codebase-indexer.js +818 -0
  5. package/lib/colors.js +190 -12
  6. package/lib/consent.js +232 -0
  7. package/lib/correlation.js +277 -0
  8. package/lib/error-codes.js +46 -0
  9. package/lib/errors.js +48 -6
  10. package/lib/file-cache.js +182 -0
  11. package/lib/format-error.js +156 -0
  12. package/lib/path-resolver.js +155 -7
  13. package/lib/paths.js +212 -20
  14. package/lib/placeholder-registry.js +205 -0
  15. package/lib/registry-di.js +358 -0
  16. package/lib/result-schema.js +363 -0
  17. package/lib/result.js +210 -0
  18. package/lib/session-registry.js +13 -0
  19. package/lib/session-state-machine.js +465 -0
  20. package/lib/validate-commands.js +308 -0
  21. package/lib/validate-names.js +3 -3
  22. package/lib/validate.js +116 -52
  23. package/package.json +4 -1
  24. package/scripts/af +34 -0
  25. package/scripts/agent-loop.js +63 -9
  26. package/scripts/agileflow-configure.js +2 -2
  27. package/scripts/agileflow-welcome.js +435 -23
  28. package/scripts/archive-completed-stories.sh +57 -11
  29. package/scripts/claude-tmux.sh +102 -0
  30. package/scripts/damage-control-bash.js +3 -70
  31. package/scripts/damage-control-edit.js +3 -20
  32. package/scripts/damage-control-write.js +3 -20
  33. package/scripts/dependency-check.js +310 -0
  34. package/scripts/get-env.js +11 -4
  35. package/scripts/lib/configure-detect.js +23 -1
  36. package/scripts/lib/configure-features.js +43 -2
  37. package/scripts/lib/context-formatter.js +771 -0
  38. package/scripts/lib/context-loader.js +699 -0
  39. package/scripts/lib/damage-control-utils.js +107 -0
  40. package/scripts/lib/json-utils.sh +162 -0
  41. package/scripts/lib/state-migrator.js +353 -0
  42. package/scripts/lib/story-state-machine.js +437 -0
  43. package/scripts/obtain-context.js +118 -1048
  44. package/scripts/pre-push-check.sh +46 -0
  45. package/scripts/precompact-context.sh +36 -11
  46. package/scripts/query-codebase.js +538 -0
  47. package/scripts/ralph-loop.js +5 -5
  48. package/scripts/session-manager.js +220 -42
  49. package/scripts/spawn-parallel.js +651 -0
  50. package/scripts/tui/blessed/data/watcher.js +180 -0
  51. package/scripts/tui/blessed/index.js +244 -0
  52. package/scripts/tui/blessed/panels/output.js +101 -0
  53. package/scripts/tui/blessed/panels/sessions.js +150 -0
  54. package/scripts/tui/blessed/panels/trace.js +97 -0
  55. package/scripts/tui/blessed/ui/help.js +77 -0
  56. package/scripts/tui/blessed/ui/screen.js +52 -0
  57. package/scripts/tui/blessed/ui/statusbar.js +47 -0
  58. package/scripts/tui/blessed/ui/tabbar.js +99 -0
  59. package/scripts/tui/index.js +38 -30
  60. package/scripts/validators/README.md +143 -0
  61. package/scripts/validators/component-validator.js +239 -0
  62. package/scripts/validators/json-schema-validator.js +186 -0
  63. package/scripts/validators/markdown-validator.js +152 -0
  64. package/scripts/validators/migration-validator.js +129 -0
  65. package/scripts/validators/security-validator.js +380 -0
  66. package/scripts/validators/story-format-validator.js +197 -0
  67. package/scripts/validators/test-result-validator.js +114 -0
  68. package/scripts/validators/workflow-validator.js +247 -0
  69. package/src/core/agents/accessibility.md +6 -0
  70. package/src/core/agents/adr-writer.md +6 -0
  71. package/src/core/agents/analytics.md +6 -0
  72. package/src/core/agents/api.md +6 -0
  73. package/src/core/agents/ci.md +6 -0
  74. package/src/core/agents/codebase-query.md +261 -0
  75. package/src/core/agents/compliance.md +6 -0
  76. package/src/core/agents/configuration-damage-control.md +6 -0
  77. package/src/core/agents/configuration-visual-e2e.md +6 -0
  78. package/src/core/agents/database.md +10 -0
  79. package/src/core/agents/datamigration.md +6 -0
  80. package/src/core/agents/design.md +6 -0
  81. package/src/core/agents/devops.md +6 -0
  82. package/src/core/agents/documentation.md +6 -0
  83. package/src/core/agents/epic-planner.md +6 -0
  84. package/src/core/agents/integrations.md +6 -0
  85. package/src/core/agents/mentor.md +6 -0
  86. package/src/core/agents/mobile.md +6 -0
  87. package/src/core/agents/monitoring.md +6 -0
  88. package/src/core/agents/multi-expert.md +6 -0
  89. package/src/core/agents/performance.md +6 -0
  90. package/src/core/agents/product.md +6 -0
  91. package/src/core/agents/qa.md +6 -0
  92. package/src/core/agents/readme-updater.md +6 -0
  93. package/src/core/agents/refactor.md +6 -0
  94. package/src/core/agents/research.md +6 -0
  95. package/src/core/agents/security.md +6 -0
  96. package/src/core/agents/testing.md +10 -0
  97. package/src/core/agents/ui.md +6 -0
  98. package/src/core/commands/adr.md +114 -0
  99. package/src/core/commands/agent.md +120 -0
  100. package/src/core/commands/assign.md +145 -0
  101. package/src/core/commands/audit.md +401 -0
  102. package/src/core/commands/babysit.md +32 -5
  103. package/src/core/commands/board.md +1 -0
  104. package/src/core/commands/changelog.md +118 -0
  105. package/src/core/commands/configure.md +42 -6
  106. package/src/core/commands/diagnose.md +114 -0
  107. package/src/core/commands/epic.md +205 -1
  108. package/src/core/commands/handoff.md +128 -0
  109. package/src/core/commands/help.md +76 -0
  110. package/src/core/commands/metrics.md +1 -0
  111. package/src/core/commands/pr.md +96 -0
  112. package/src/core/commands/research/analyze.md +1 -0
  113. package/src/core/commands/research/ask.md +2 -0
  114. package/src/core/commands/research/import.md +1 -0
  115. package/src/core/commands/research/list.md +2 -0
  116. package/src/core/commands/research/synthesize.md +584 -0
  117. package/src/core/commands/research/view.md +2 -0
  118. package/src/core/commands/roadmap/analyze.md +400 -0
  119. package/src/core/commands/session/new.md +113 -6
  120. package/src/core/commands/session/spawn.md +197 -0
  121. package/src/core/commands/sprint.md +22 -0
  122. package/src/core/commands/status.md +200 -1
  123. package/src/core/commands/story/list.md +9 -9
  124. package/src/core/commands/story/view.md +1 -0
  125. package/src/core/commands/story.md +143 -4
  126. package/src/core/experts/codebase-query/expertise.yaml +190 -0
  127. package/src/core/experts/codebase-query/question.md +73 -0
  128. package/src/core/experts/codebase-query/self-improve.md +105 -0
  129. package/src/core/templates/agileflow-metadata.json +55 -2
  130. package/src/core/templates/plan-template.md +125 -0
  131. package/src/core/templates/story-lifecycle.md +213 -0
  132. package/src/core/templates/story-template.md +4 -0
  133. package/src/core/templates/tdd-test-template.js +241 -0
  134. package/tools/cli/commands/setup.js +86 -0
  135. package/tools/cli/installers/core/installer.js +94 -0
  136. package/tools/cli/installers/ide/_base-ide.js +20 -11
  137. package/tools/cli/installers/ide/codex.js +29 -47
  138. package/tools/cli/lib/config-manager.js +17 -2
  139. package/tools/cli/lib/content-transformer.js +271 -0
  140. package/tools/cli/lib/error-handler.js +14 -22
  141. package/tools/cli/lib/ide-error-factory.js +421 -0
  142. package/tools/cli/lib/ide-health-monitor.js +364 -0
  143. package/tools/cli/lib/ide-registry.js +114 -1
  144. 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
+ };
@@ -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
- statusPath: this.getStatusPath(),
277
- sessionStatePath: this.getSessionStatePath(),
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 fs = require('fs');
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
- let dir = startDir;
19
- while (!fs.existsSync(path.join(dir, '.agileflow')) && dir !== '/') {
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
- const root = rootDir || getProjectRoot();
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
- const root = rootDir || getProjectRoot();
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
- const root = rootDir || getProjectRoot();
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
- const root = rootDir || getProjectRoot();
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
- const root = rootDir || getProjectRoot();
77
- return path.join(root, 'docs', '09-agents', 'session-state.json');
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
- const root = getProjectRoot(dir);
88
- return fs.existsSync(path.join(root, '.agileflow'));
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
  };