agileflow 2.91.0 → 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 (99) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +3 -3
  3. package/lib/README.md +178 -0
  4. package/lib/codebase-indexer.js +31 -23
  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.js +116 -52
  22. package/package.json +1 -1
  23. package/scripts/af +34 -0
  24. package/scripts/agent-loop.js +63 -9
  25. package/scripts/agileflow-configure.js +2 -2
  26. package/scripts/agileflow-welcome.js +435 -23
  27. package/scripts/archive-completed-stories.sh +57 -11
  28. package/scripts/claude-tmux.sh +102 -0
  29. package/scripts/damage-control-bash.js +3 -70
  30. package/scripts/damage-control-edit.js +3 -20
  31. package/scripts/damage-control-write.js +3 -20
  32. package/scripts/dependency-check.js +310 -0
  33. package/scripts/get-env.js +11 -4
  34. package/scripts/lib/configure-detect.js +23 -1
  35. package/scripts/lib/configure-features.js +43 -2
  36. package/scripts/lib/context-formatter.js +771 -0
  37. package/scripts/lib/context-loader.js +699 -0
  38. package/scripts/lib/damage-control-utils.js +107 -0
  39. package/scripts/lib/json-utils.sh +162 -0
  40. package/scripts/lib/state-migrator.js +353 -0
  41. package/scripts/lib/story-state-machine.js +437 -0
  42. package/scripts/obtain-context.js +80 -1248
  43. package/scripts/pre-push-check.sh +46 -0
  44. package/scripts/precompact-context.sh +23 -10
  45. package/scripts/query-codebase.js +122 -14
  46. package/scripts/ralph-loop.js +5 -5
  47. package/scripts/session-manager.js +220 -42
  48. package/scripts/spawn-parallel.js +651 -0
  49. package/scripts/tui/blessed/data/watcher.js +20 -15
  50. package/scripts/tui/blessed/index.js +2 -2
  51. package/scripts/tui/blessed/panels/output.js +14 -8
  52. package/scripts/tui/blessed/panels/sessions.js +22 -15
  53. package/scripts/tui/blessed/panels/trace.js +14 -8
  54. package/scripts/tui/blessed/ui/help.js +3 -3
  55. package/scripts/tui/blessed/ui/screen.js +4 -4
  56. package/scripts/tui/blessed/ui/statusbar.js +5 -9
  57. package/scripts/tui/blessed/ui/tabbar.js +11 -11
  58. package/scripts/validators/component-validator.js +41 -14
  59. package/scripts/validators/json-schema-validator.js +11 -4
  60. package/scripts/validators/markdown-validator.js +1 -2
  61. package/scripts/validators/migration-validator.js +17 -5
  62. package/scripts/validators/security-validator.js +137 -33
  63. package/scripts/validators/story-format-validator.js +31 -10
  64. package/scripts/validators/test-result-validator.js +19 -4
  65. package/scripts/validators/workflow-validator.js +12 -5
  66. package/src/core/agents/codebase-query.md +24 -0
  67. package/src/core/commands/adr.md +114 -0
  68. package/src/core/commands/agent.md +120 -0
  69. package/src/core/commands/assign.md +145 -0
  70. package/src/core/commands/babysit.md +32 -5
  71. package/src/core/commands/changelog.md +118 -0
  72. package/src/core/commands/configure.md +42 -6
  73. package/src/core/commands/diagnose.md +114 -0
  74. package/src/core/commands/epic.md +113 -0
  75. package/src/core/commands/handoff.md +128 -0
  76. package/src/core/commands/help.md +75 -0
  77. package/src/core/commands/pr.md +96 -0
  78. package/src/core/commands/roadmap/analyze.md +400 -0
  79. package/src/core/commands/session/new.md +113 -6
  80. package/src/core/commands/session/spawn.md +197 -0
  81. package/src/core/commands/sprint.md +22 -0
  82. package/src/core/commands/status.md +74 -0
  83. package/src/core/commands/story.md +143 -4
  84. package/src/core/templates/agileflow-metadata.json +55 -2
  85. package/src/core/templates/plan-template.md +125 -0
  86. package/src/core/templates/story-lifecycle.md +213 -0
  87. package/src/core/templates/story-template.md +4 -0
  88. package/src/core/templates/tdd-test-template.js +241 -0
  89. package/tools/cli/commands/setup.js +86 -0
  90. package/tools/cli/installers/core/installer.js +94 -0
  91. package/tools/cli/installers/ide/_base-ide.js +20 -11
  92. package/tools/cli/installers/ide/codex.js +29 -47
  93. package/tools/cli/lib/config-manager.js +17 -2
  94. package/tools/cli/lib/content-transformer.js +271 -0
  95. package/tools/cli/lib/error-handler.js +14 -22
  96. package/tools/cli/lib/ide-error-factory.js +421 -0
  97. package/tools/cli/lib/ide-health-monitor.js +364 -0
  98. package/tools/cli/lib/ide-registry.js +114 -1
  99. package/tools/cli/lib/ui.js +14 -25
@@ -0,0 +1,213 @@
1
+ # Story Lifecycle
2
+
3
+ This document describes how stories transition through different states in AgileFlow.
4
+
5
+ ---
6
+
7
+ ## State Diagram
8
+
9
+ ```mermaid
10
+ stateDiagram-v2
11
+ [*] --> draft: create
12
+
13
+ draft --> ready: validate (DoR met)
14
+ draft --> draft: edit
15
+
16
+ ready --> in_progress: start work
17
+ ready --> blocked: dependency issue
18
+
19
+ in_progress --> in_review: submit PR
20
+ in_progress --> blocked: blocker found
21
+ in_progress --> ready: pause work
22
+
23
+ blocked --> ready: unblocked
24
+ blocked --> in_progress: unblocked (continue)
25
+
26
+ in_review --> done: PR merged
27
+ in_review --> in_progress: changes requested
28
+
29
+ done --> [*]
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Story States
35
+
36
+ | State | Description | Next Actions |
37
+ |-------|-------------|--------------|
38
+ | **draft** | Story created but not ready for work | Validate, add AC, set estimate |
39
+ | **ready** | Definition of Ready (DoR) met | Start work, assign owner |
40
+ | **in-progress** | Actively being worked on | Complete, submit PR, or pause |
41
+ | **blocked** | Waiting on external dependency | Resolve blocker, escalate |
42
+ | **in-review** | Pull request submitted | Review, approve, merge |
43
+ | **done** | Work complete and merged | Archive, celebrate |
44
+
45
+ ---
46
+
47
+ ## State Transitions
48
+
49
+ ### draft → ready
50
+
51
+ **Trigger**: Story passes Definition of Ready (DoR)
52
+
53
+ **DoR Checklist**:
54
+ - [ ] Clear acceptance criteria (Given/When/Then)
55
+ - [ ] Estimate provided
56
+ - [ ] Dependencies identified
57
+ - [ ] Owner assigned
58
+ - [ ] Epic linked
59
+
60
+ **Command**: `/agileflow:story-validate STORY=US-XXXX`
61
+
62
+ ---
63
+
64
+ ### ready → in-progress
65
+
66
+ **Trigger**: Developer starts work
67
+
68
+ **Actions**:
69
+ 1. Update status.json: `status: "in-progress"`
70
+ 2. Set phase to `execute`
71
+ 3. Log to bus/log.jsonl
72
+
73
+ **Command**: `/agileflow:status STORY=US-XXXX STATUS=in-progress`
74
+
75
+ ---
76
+
77
+ ### in-progress → in-review
78
+
79
+ **Trigger**: Pull request created
80
+
81
+ **Actions**:
82
+ 1. Update status.json: `status: "in-review"`
83
+ 2. Set phase to `audit`
84
+ 3. Add PR link
85
+ 4. Log to bus/log.jsonl
86
+
87
+ **Command**: `/agileflow:status STORY=US-XXXX STATUS=in-review PR=<url>`
88
+
89
+ ---
90
+
91
+ ### in-review → done
92
+
93
+ **Trigger**: PR merged to main
94
+
95
+ **Actions**:
96
+ 1. Update status.json: `status: "done"`
97
+ 2. Set phase to `complete`
98
+ 3. Log completion to bus/log.jsonl
99
+ 4. Auto-archive after 7 days
100
+
101
+ **Command**: `/agileflow:status STORY=US-XXXX STATUS=done`
102
+
103
+ ---
104
+
105
+ ### → blocked
106
+
107
+ **Trigger**: External dependency or blocker found
108
+
109
+ **Actions**:
110
+ 1. Update status.json: `status: "blocked"`
111
+ 2. Add blocker reason
112
+ 3. Log to bus/log.jsonl
113
+ 4. Notify dependent teams
114
+
115
+ **Command**: `/agileflow:status STORY=US-XXXX STATUS=blocked SUMMARY="Waiting on API keys"`
116
+
117
+ ---
118
+
119
+ ## Phase Mapping
120
+
121
+ Stories have both a **status** and a **phase**. Phases group statuses for high-level tracking:
122
+
123
+ | Status | Phase | Description |
124
+ |--------|-------|-------------|
125
+ | draft | plan | Planning and scoping |
126
+ | ready | plan | Ready for planning/assignment |
127
+ | in-progress | execute | Active development |
128
+ | blocked | execute | Blocked but in execute phase |
129
+ | in-review | audit | Quality review |
130
+ | done | complete | Work finished |
131
+
132
+ ---
133
+
134
+ ## WIP Limits
135
+
136
+ AgileFlow enforces Work-In-Progress (WIP) limits to prevent overload:
137
+
138
+ - **Per Agent**: Max 2 stories in `in-progress` + `in-review`
139
+ - **Per Epic**: Configurable, typically 5-10 concurrent stories
140
+
141
+ **Violation handling**:
142
+ ```
143
+ ⚠️ WIP Limit Exceeded
144
+
145
+ AG-UI has 3 stories in progress (limit: 2):
146
+ - US-0042: Login Form
147
+ - US-0043: Profile Page
148
+ - US-0044: Dashboard
149
+
150
+ Complete or pause a story before starting new work.
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Lifecycle in status.json
156
+
157
+ ```json
158
+ {
159
+ "stories": {
160
+ "US-0042": {
161
+ "id": "US-0042",
162
+ "title": "Login Form with Validation",
163
+ "epic": "EP-0010",
164
+ "owner": "AG-UI",
165
+ "status": "in-progress",
166
+ "phase": "execute",
167
+ "estimate": "2h",
168
+ "deps": ["US-0041"],
169
+ "created": "2026-01-20T10:00:00Z",
170
+ "updated": "2026-01-21T14:30:00Z",
171
+ "history": [
172
+ {"status": "draft", "ts": "2026-01-20T10:00:00Z"},
173
+ {"status": "ready", "ts": "2026-01-20T11:00:00Z"},
174
+ {"status": "in-progress", "ts": "2026-01-21T09:00:00Z"}
175
+ ]
176
+ }
177
+ }
178
+ }
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Bus Messages
184
+
185
+ State transitions are logged to `docs/09-agents/bus/log.jsonl`:
186
+
187
+ ```jsonl
188
+ {"ts":"2026-01-21T09:00:00Z","type":"status","from":"AG-UI","to":"ALL","story":"US-0042","status":"in-progress","text":"Started work on login form"}
189
+ {"ts":"2026-01-21T14:30:00Z","type":"status","from":"AG-UI","to":"ALL","story":"US-0042","status":"in-review","pr":"https://github.com/.../pull/42"}
190
+ {"ts":"2026-01-21T16:00:00Z","type":"status","from":"AG-UI","to":"ALL","story":"US-0042","status":"done","text":"PR merged"}
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Related Commands
196
+
197
+ | Command | Purpose |
198
+ |---------|---------|
199
+ | `/agileflow:story` | Create new story |
200
+ | `/agileflow:status` | Update story status |
201
+ | `/agileflow:board` | View kanban board |
202
+ | `/agileflow:blockers` | View blocked stories |
203
+ | `/agileflow:story-validate` | Validate DoR |
204
+
205
+ ---
206
+
207
+ ## Best Practices
208
+
209
+ 1. **Keep stories small**: 1-3 days of work maximum
210
+ 2. **Update status promptly**: Reflect actual work state
211
+ 3. **Document blockers**: Include reason and expected resolution
212
+ 4. **Respect WIP limits**: Complete before starting new
213
+ 5. **Use phase handoffs**: Capture context at transitions
@@ -8,6 +8,8 @@ estimate: {{ESTIMATE}}
8
8
  created: {{CREATED}}
9
9
  updated: {{UPDATED}}
10
10
  dependencies: {{DEPENDENCIES}}
11
+ tdd_mode: {{TDD_MODE}}
12
+ test_file: {{TEST_FILE}}
11
13
  ---
12
14
 
13
15
  # {{STORY_ID}}: {{TITLE}}
@@ -15,6 +17,7 @@ dependencies: {{DEPENDENCIES}}
15
17
  **Epic**: {{EPIC_ID}}
16
18
  **Owner**: {{OWNER}}
17
19
  **Estimate**: {{ESTIMATE}}
20
+ {{TDD_BADGE}}
18
21
 
19
22
  ## Description
20
23
  {{DESCRIPTION}}
@@ -50,6 +53,7 @@ dependencies: {{DEPENDENCIES}}
50
53
 
51
54
  ## Testing Strategy
52
55
  See: `docs/07-testing/test-cases/{{STORY_ID}}.md`
56
+ {{TDD_TEST_FILE_REF}}
53
57
 
54
58
  ## Dependencies
55
59
  {{DEPENDENCIES}}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * TDD Test Template for AgileFlow Story Creation
3
+ *
4
+ * This template generates framework-specific test stubs from acceptance criteria.
5
+ * Used by /agileflow:story when TDD=true flag is set.
6
+ *
7
+ * Placeholders:
8
+ * - {{STORY_ID}} - Story identifier (e.g., US-0042)
9
+ * - {{TITLE}} - Story title
10
+ * - {{EPIC}} - Epic identifier (e.g., EP-0010)
11
+ * - {{AC_TESTS}} - Generated test cases from acceptance criteria
12
+ * - {{CREATED}} - ISO timestamp
13
+ */
14
+
15
+ // Template for Jest/Vitest (JavaScript/TypeScript)
16
+ const jestTemplate = `/**
17
+ * TDD Tests for {{STORY_ID}}: {{TITLE}}
18
+ *
19
+ * Story: docs/06-stories/{{EPIC}}/{{STORY_ID}}-*.md
20
+ * Created: {{CREATED}}
21
+ *
22
+ * These tests are generated from acceptance criteria.
23
+ * Implementation goal: Make all tests pass.
24
+ *
25
+ * Workflow:
26
+ * 1. Review each test case (currently skipped)
27
+ * 2. Implement the feature code
28
+ * 3. Remove .skip from tests one at a time
29
+ * 4. Run tests until all pass
30
+ */
31
+
32
+ describe('{{STORY_ID}}: {{TITLE}}', () => {
33
+ {{AC_TESTS}}
34
+ });
35
+ `;
36
+
37
+ // Template for individual AC test block (Jest)
38
+ const jestAcTemplate = `
39
+ // {{AC_LABEL}}: {{AC_SUMMARY}}
40
+ describe('{{AC_SUMMARY}}', () => {
41
+ it.skip('should {{THEN_CLAUSE}}', () => {
42
+ // Given: {{GIVEN_CLAUSE}}
43
+ // TODO: Set up test preconditions
44
+
45
+ // When: {{WHEN_CLAUSE}}
46
+ // TODO: Execute the action
47
+
48
+ // Then: {{THEN_CLAUSE}}
49
+ // TODO: Add assertions
50
+ expect(true).toBe(true);
51
+ });
52
+ });
53
+ `;
54
+
55
+ // Template for pytest (Python)
56
+ const pytestTemplate = `"""
57
+ TDD Tests for {{STORY_ID}}: {{TITLE}}
58
+
59
+ Story: docs/06-stories/{{EPIC}}/{{STORY_ID}}-*.md
60
+ Created: {{CREATED}}
61
+
62
+ These tests are generated from acceptance criteria.
63
+ Implementation goal: Make all tests pass.
64
+
65
+ Workflow:
66
+ 1. Review each test case (currently skipped)
67
+ 2. Implement the feature code
68
+ 3. Remove @pytest.mark.skip from tests one at a time
69
+ 4. Run tests until all pass
70
+ """
71
+
72
+ import pytest
73
+
74
+ {{AC_TESTS}}
75
+ `;
76
+
77
+ // Template for individual AC test block (pytest)
78
+ const pytestAcTemplate = `
79
+ # {{AC_LABEL}}: {{AC_SUMMARY}}
80
+ class Test{{AC_CLASS_NAME}}:
81
+ @pytest.mark.skip(reason="TDD: Implement feature first")
82
+ def test_{{TEST_NAME}}(self):
83
+ """
84
+ Given: {{GIVEN_CLAUSE}}
85
+ When: {{WHEN_CLAUSE}}
86
+ Then: {{THEN_CLAUSE}}
87
+ """
88
+ # TODO: Set up test preconditions (Given)
89
+
90
+ # TODO: Execute the action (When)
91
+
92
+ # TODO: Add assertions (Then)
93
+ assert True
94
+ `;
95
+
96
+ // Template for Go tests
97
+ const goTestTemplate = `package {{PACKAGE_NAME}}_test
98
+
99
+ /*
100
+ TDD Tests for {{STORY_ID}}: {{TITLE}}
101
+
102
+ Story: docs/06-stories/{{EPIC}}/{{STORY_ID}}-*.md
103
+ Created: {{CREATED}}
104
+
105
+ These tests are generated from acceptance criteria.
106
+ Implementation goal: Make all tests pass.
107
+ */
108
+
109
+ import (
110
+ "testing"
111
+ )
112
+
113
+ {{AC_TESTS}}
114
+ `;
115
+
116
+ // Template for individual AC test block (Go)
117
+ const goAcTemplate = `
118
+ // {{AC_LABEL}}: {{AC_SUMMARY}}
119
+ func Test{{AC_FUNC_NAME}}(t *testing.T) {
120
+ t.Skip("TDD: Implement feature first")
121
+
122
+ // Given: {{GIVEN_CLAUSE}}
123
+ // TODO: Set up test preconditions
124
+
125
+ // When: {{WHEN_CLAUSE}}
126
+ // TODO: Execute the action
127
+
128
+ // Then: {{THEN_CLAUSE}}
129
+ // TODO: Add assertions
130
+ }
131
+ `;
132
+
133
+ // Export templates for use by story.md command
134
+ module.exports = {
135
+ jest: {
136
+ file: jestTemplate,
137
+ ac: jestAcTemplate,
138
+ extension: '.test.ts',
139
+ directory: '__tests__'
140
+ },
141
+ vitest: {
142
+ file: jestTemplate, // Same format as Jest
143
+ ac: jestAcTemplate,
144
+ extension: '.test.ts',
145
+ directory: '__tests__'
146
+ },
147
+ pytest: {
148
+ file: pytestTemplate,
149
+ ac: pytestAcTemplate,
150
+ extension: '_test.py',
151
+ directory: 'tests'
152
+ },
153
+ go: {
154
+ file: goTestTemplate,
155
+ ac: goAcTemplate,
156
+ extension: '_test.go',
157
+ directory: ''
158
+ },
159
+
160
+ /**
161
+ * Parse acceptance criteria into structured format
162
+ * @param {string} acText - Raw AC text with Given/When/Then
163
+ * @returns {Array} Parsed AC objects
164
+ */
165
+ parseAcceptanceCriteria(acText) {
166
+ const criteria = [];
167
+ const acBlocks = acText.split(/(?=(?:AC\d+|###?\s*AC))/i);
168
+
169
+ for (const block of acBlocks) {
170
+ if (!block.trim()) continue;
171
+
172
+ // Extract label (AC1, AC2, etc.)
173
+ const labelMatch = block.match(/(?:AC\s*)?(\d+)/i);
174
+ const label = labelMatch ? `AC${labelMatch[1]}` : `AC${criteria.length + 1}`;
175
+
176
+ // Extract Given/When/Then
177
+ const givenMatch = block.match(/\*?\*?Given\*?\*?[:\s]+(.+?)(?=\*?\*?When|$)/is);
178
+ const whenMatch = block.match(/\*?\*?When\*?\*?[:\s]+(.+?)(?=\*?\*?Then|$)/is);
179
+ const thenMatch = block.match(/\*?\*?Then\*?\*?[:\s]+(.+?)(?=\*?\*?(?:Given|AC|###)|$)/is);
180
+
181
+ if (givenMatch || whenMatch || thenMatch) {
182
+ criteria.push({
183
+ label,
184
+ given: givenMatch ? givenMatch[1].trim() : 'preconditions are met',
185
+ when: whenMatch ? whenMatch[1].trim() : 'action is performed',
186
+ then: thenMatch ? thenMatch[1].trim() : 'expected result occurs',
187
+ summary: this.generateSummary(givenMatch, whenMatch, thenMatch)
188
+ });
189
+ }
190
+ }
191
+
192
+ // If no structured AC found, create one from the whole text
193
+ if (criteria.length === 0 && acText.trim()) {
194
+ criteria.push({
195
+ label: 'AC1',
196
+ given: 'the feature is implemented',
197
+ when: 'user interacts with it',
198
+ then: 'expected behavior occurs',
199
+ summary: acText.substring(0, 50).trim()
200
+ });
201
+ }
202
+
203
+ return criteria;
204
+ },
205
+
206
+ /**
207
+ * Generate a short summary from Given/When/Then
208
+ */
209
+ generateSummary(givenMatch, whenMatch, thenMatch) {
210
+ if (thenMatch) {
211
+ // Use Then clause, truncated
212
+ return thenMatch[1].trim().substring(0, 50).replace(/[^\w\s]/g, '');
213
+ }
214
+ if (whenMatch) {
215
+ return whenMatch[1].trim().substring(0, 50).replace(/[^\w\s]/g, '');
216
+ }
217
+ return 'acceptance criteria';
218
+ },
219
+
220
+ /**
221
+ * Convert string to valid function/class name
222
+ */
223
+ toIdentifier(str) {
224
+ return str
225
+ .replace(/[^\w\s]/g, '')
226
+ .split(/\s+/)
227
+ .map((word, i) => i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
228
+ .join('');
229
+ },
230
+
231
+ /**
232
+ * Convert string to PascalCase for class names
233
+ */
234
+ toPascalCase(str) {
235
+ return str
236
+ .replace(/[^\w\s]/g, '')
237
+ .split(/\s+/)
238
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
239
+ .join('');
240
+ }
241
+ };
@@ -7,6 +7,7 @@
7
7
 
8
8
  const chalk = require('chalk');
9
9
  const path = require('node:path');
10
+ const fs = require('node:fs');
10
11
  const { spawnSync } = require('node:child_process');
11
12
  const semver = require('semver');
12
13
  const { Installer } = require('../installers/core/installer');
@@ -90,6 +91,7 @@ module.exports = {
90
91
  agileflowFolder: '.agileflow',
91
92
  docsFolder: 'docs',
92
93
  updateGitignore: true,
94
+ claudeMdReinforcement: true,
93
95
  };
94
96
  } else {
95
97
  // Interactive prompts
@@ -110,6 +112,16 @@ module.exports = {
110
112
  success(`Installed ${coreResult.counts.commands} commands`);
111
113
  success(`Installed ${coreResult.counts.skills} skills`);
112
114
 
115
+ // Report shell alias setup
116
+ if (coreResult.shellAliases) {
117
+ if (coreResult.shellAliases.configured.length > 0) {
118
+ success(`Added 'af' alias to: ${coreResult.shellAliases.configured.join(', ')}`);
119
+ }
120
+ if (coreResult.shellAliases.skipped.length > 0) {
121
+ info(`Shell aliases skipped: ${coreResult.shellAliases.skipped.join(', ')}`);
122
+ }
123
+ }
124
+
113
125
  // Setup IDE configurations
114
126
  displaySection('Configuring IDEs');
115
127
 
@@ -133,6 +145,73 @@ module.exports = {
133
145
  }
134
146
  }
135
147
 
148
+ // CLAUDE.md reinforcement for /babysit AskUserQuestion rules
149
+ if (config.claudeMdReinforcement) {
150
+ const claudeMdPath = path.join(config.directory, 'CLAUDE.md');
151
+ const claudeMdMarker = '<!-- AGILEFLOW_BABYSIT_RULES -->';
152
+ const claudeMdContent = `
153
+
154
+ ${claudeMdMarker}
155
+ ## AgileFlow /babysit Context Preservation Rules
156
+
157
+ When \`/agileflow:babysit\` is active (check session-state.json), these rules are MANDATORY:
158
+
159
+ 1. **ALWAYS end responses with the AskUserQuestion tool** - Not text like "What next?" but the ACTUAL TOOL CALL
160
+ 2. **Use Plan Mode for non-trivial tasks** - Call \`EnterPlanMode\` before complex implementations
161
+ 3. **Delegate complex work to domain experts** - Use \`Task\` tool with appropriate \`subagent_type\`
162
+ 4. **Track progress with TodoWrite** - For any task with 3+ steps
163
+
164
+ These rules persist across conversation compaction. Check \`docs/09-agents/session-state.json\` for active commands.
165
+ ${claudeMdMarker}
166
+ `;
167
+
168
+ try {
169
+ let existingContent = '';
170
+ if (fs.existsSync(claudeMdPath)) {
171
+ existingContent = fs.readFileSync(claudeMdPath, 'utf8');
172
+ }
173
+
174
+ // Only append if marker doesn't exist
175
+ if (!existingContent.includes(claudeMdMarker)) {
176
+ fs.appendFileSync(claudeMdPath, claudeMdContent);
177
+ success('Added /babysit rules to CLAUDE.md');
178
+ } else {
179
+ info('CLAUDE.md already has /babysit rules');
180
+ }
181
+ } catch (err) {
182
+ warning(`Could not update CLAUDE.md: ${err.message}`);
183
+ }
184
+ }
185
+
186
+ // Update metadata with config tracking
187
+ try {
188
+ const metadataPath = path.join(config.directory, config.docsFolder, '00-meta', 'agileflow-metadata.json');
189
+ if (fs.existsSync(metadataPath)) {
190
+ const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
191
+ const packageJson = require(path.join(__dirname, '..', '..', '..', 'package.json'));
192
+
193
+ // Track config schema version and profile
194
+ metadata.config_schema_version = packageJson.version;
195
+ metadata.active_profile = options.yes ? 'default' : null; // null = custom
196
+
197
+ // Track config options that were configured
198
+ if (!metadata.agileflow) metadata.agileflow = {};
199
+ if (!metadata.agileflow.config_options) metadata.agileflow.config_options = {};
200
+
201
+ metadata.agileflow.config_options.claudeMdReinforcement = {
202
+ available_since: '2.92.0',
203
+ configured: true,
204
+ enabled: config.claudeMdReinforcement,
205
+ configured_at: new Date().toISOString(),
206
+ description: 'Add /babysit AskUserQuestion rules to CLAUDE.md',
207
+ };
208
+
209
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2) + '\n');
210
+ }
211
+ } catch (err) {
212
+ // Silently fail - metadata tracking is non-critical
213
+ }
214
+
136
215
  // Final summary
137
216
  console.log(chalk.green('\n✨ Setup complete!\n'));
138
217
 
@@ -141,6 +220,13 @@ module.exports = {
141
220
  info(`Run 'npx agileflow status' to check setup`);
142
221
  info(`Run 'npx agileflow update' to get updates`);
143
222
 
223
+ // Shell alias reload reminder
224
+ if (coreResult.shellAliases?.configured?.length > 0) {
225
+ console.log(chalk.bold('\nShell aliases:'));
226
+ info(`Reload shell to use: ${chalk.cyan('source ~/.bashrc')} or ${chalk.cyan('source ~/.zshrc')}`);
227
+ info(`Then run ${chalk.cyan('af')} to start Claude in tmux (or ${chalk.cyan('claude')} for normal)`);
228
+ }
229
+
144
230
  console.log(chalk.dim(`\nInstalled to: ${coreResult.path}\n`));
145
231
 
146
232
  process.exit(0);
@@ -164,6 +164,10 @@ class Installer {
164
164
  spinner.text = 'Installing changelog...';
165
165
  await this.installChangelog(agileflowDir, { force: effectiveForce });
166
166
 
167
+ // Set up shell aliases for claude command
168
+ spinner.text = 'Setting up shell aliases...';
169
+ const aliasResult = await this.setupShellAliases(directory, { force: effectiveForce });
170
+
167
171
  // Create config.yaml
168
172
  spinner.text = 'Creating configuration...';
169
173
  await this.createConfig(agileflowDir, userName, agileflowFolder, { force: effectiveForce });
@@ -191,6 +195,7 @@ class Installer {
191
195
  projectDir: directory,
192
196
  counts,
193
197
  fileOps,
198
+ shellAliases: aliasResult,
194
199
  };
195
200
  } catch (error) {
196
201
  spinner.fail('Installation failed');
@@ -813,6 +818,95 @@ class Installer {
813
818
  }
814
819
  }
815
820
 
821
+ /**
822
+ * Set up shell aliases for the claude command
823
+ * Adds aliases to ~/.bashrc and/or ~/.zshrc so 'claude' auto-spawns tmux
824
+ * @param {string} directory - Project directory (used for relative path in alias)
825
+ * @param {Object} options - Setup options
826
+ * @param {boolean} options.force - Overwrite existing aliases
827
+ * @returns {Promise<Object>} Result with shells configured
828
+ */
829
+ async setupShellAliases(directory, options = {}) {
830
+ const os = require('os');
831
+ const result = {
832
+ configured: [],
833
+ skipped: [],
834
+ error: null,
835
+ };
836
+
837
+ // Only set up aliases on Unix-like systems
838
+ if (process.platform === 'win32') {
839
+ result.skipped.push('Windows (not supported)');
840
+ return result;
841
+ }
842
+
843
+ const homeDir = os.homedir();
844
+ const aliasBlock = `
845
+ # AgileFlow tmux wrapper
846
+ # Use 'af' or 'agileflow' for tmux, 'claude' stays normal
847
+ alias af="bash .agileflow/scripts/af"
848
+ alias agileflow="bash .agileflow/scripts/af"
849
+ `;
850
+
851
+ const marker = '# AgileFlow tmux wrapper';
852
+ const rcFiles = [
853
+ { name: 'bash', path: path.join(homeDir, '.bashrc') },
854
+ { name: 'zsh', path: path.join(homeDir, '.zshrc') },
855
+ ];
856
+
857
+ for (const rc of rcFiles) {
858
+ try {
859
+ // Check if RC file exists
860
+ if (!(await fs.pathExists(rc.path))) {
861
+ result.skipped.push(`${rc.name} (no ${path.basename(rc.path)})`);
862
+ continue;
863
+ }
864
+
865
+ const content = await fs.readFile(rc.path, 'utf8');
866
+
867
+ // Check if aliases already exist
868
+ if (content.includes(marker)) {
869
+ if (options.force) {
870
+ // Remove existing block and re-add
871
+ const lines = content.split('\n');
872
+ const filteredLines = [];
873
+ let inBlock = false;
874
+
875
+ for (const line of lines) {
876
+ if (line.includes(marker)) {
877
+ inBlock = true;
878
+ continue;
879
+ }
880
+ if (inBlock && line.startsWith('alias ')) {
881
+ continue;
882
+ }
883
+ if (inBlock && line.trim() === '') {
884
+ inBlock = false;
885
+ continue;
886
+ }
887
+ inBlock = false;
888
+ filteredLines.push(line);
889
+ }
890
+
891
+ await fs.writeFile(rc.path, filteredLines.join('\n') + aliasBlock, 'utf8');
892
+ result.configured.push(rc.name);
893
+ } else {
894
+ result.skipped.push(`${rc.name} (already configured)`);
895
+ }
896
+ continue;
897
+ }
898
+
899
+ // Append aliases to RC file
900
+ await fs.appendFile(rc.path, aliasBlock);
901
+ result.configured.push(rc.name);
902
+ } catch (err) {
903
+ result.skipped.push(`${rc.name} (error: ${err.message})`);
904
+ }
905
+ }
906
+
907
+ return result;
908
+ }
909
+
816
910
  /**
817
911
  * Get installation status
818
912
  * @param {string} directory - Project directory