agileflow 3.4.3 → 4.0.0-alpha.2

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 (762) hide show
  1. package/CHANGELOG.md +238 -473
  2. package/README.md +22 -114
  3. package/bin/agileflow.js +15 -0
  4. package/bin/hooks/pre-bash.js +35 -0
  5. package/bin/hooks/pre-compact.js +34 -0
  6. package/bin/hooks/pre-edit.js +32 -0
  7. package/bin/hooks/pre-write.js +32 -0
  8. package/bin/hooks/session-start.js +42 -0
  9. package/bin/hooks/stop.js +34 -0
  10. package/content/plugins/ads/plugin.yaml +14 -0
  11. package/content/plugins/audit/plugin.yaml +14 -0
  12. package/content/plugins/core/hooks/babysit-mentor-injector.js +55 -0
  13. package/content/plugins/core/hooks/context-loader.js +169 -0
  14. package/content/plugins/core/hooks/damage-control-bash.js +78 -0
  15. package/content/plugins/core/hooks/damage-control-edit.js +76 -0
  16. package/content/plugins/core/hooks/damage-control-patterns.yaml +100 -0
  17. package/content/plugins/core/hooks/damage-control-write.js +72 -0
  18. package/content/plugins/core/hooks/pre-compact-state.js +90 -0
  19. package/content/plugins/core/hooks/session-welcome.js +19 -0
  20. package/content/plugins/core/plugin.yaml +82 -0
  21. package/content/plugins/core/skills/agileflow-adr/SKILL.md +179 -0
  22. package/content/plugins/core/skills/agileflow-babysit-mentor/SKILL.md +144 -0
  23. package/content/plugins/core/skills/agileflow-epic-planner/SKILL.md +179 -0
  24. package/content/plugins/core/skills/agileflow-status-updater/SKILL.md +132 -0
  25. package/content/plugins/core/skills/agileflow-story-writer/SKILL.md +200 -0
  26. package/content/plugins/council/plugin.yaml +14 -0
  27. package/content/plugins/seo/plugin.yaml +14 -0
  28. package/package.json +29 -49
  29. package/src/cli/commands/doctor.js +159 -0
  30. package/src/cli/commands/hook.js +80 -0
  31. package/src/cli/commands/setup.js +292 -0
  32. package/src/cli/commands/status.js +47 -0
  33. package/src/cli/commands/update.js +83 -0
  34. package/src/cli/index.js +73 -0
  35. package/src/cli/wizard/behaviors-picker.js +108 -0
  36. package/src/cli/wizard/ide-picker.js +57 -0
  37. package/src/cli/wizard/personalization.js +64 -0
  38. package/src/cli/wizard/plugin-picker.js +106 -0
  39. package/src/lib/hash.js +41 -0
  40. package/src/runtime/config/defaults.js +61 -0
  41. package/src/runtime/config/loader.js +117 -0
  42. package/src/runtime/config/schema.json +99 -0
  43. package/src/runtime/config/writer.js +55 -0
  44. package/src/runtime/hooks/aggregator.js +157 -0
  45. package/src/runtime/hooks/chain.js +93 -0
  46. package/src/runtime/hooks/logger.js +68 -0
  47. package/src/runtime/hooks/manifest-loader.js +228 -0
  48. package/src/runtime/hooks/orchestrator.js +322 -0
  49. package/src/runtime/ide/capabilities.js +111 -0
  50. package/src/runtime/ide/claude-code-settings.js +234 -0
  51. package/src/runtime/ide/claude-code-skills.js +202 -0
  52. package/src/runtime/installer/file-index.js +112 -0
  53. package/src/runtime/installer/install.js +329 -0
  54. package/src/runtime/installer/stash.js +61 -0
  55. package/src/runtime/installer/sync-engine.js +205 -0
  56. package/src/runtime/plugins/registry.js +132 -0
  57. package/src/runtime/plugins/resolver.js +138 -0
  58. package/src/runtime/plugins/validator.js +196 -0
  59. package/src/runtime/skills/validator.js +335 -0
  60. package/lib/README.md +0 -178
  61. package/lib/api-routes.js +0 -625
  62. package/lib/api-server.js +0 -278
  63. package/lib/cache-provider.js +0 -155
  64. package/lib/codebase-indexer.js +0 -819
  65. package/lib/colors.generated.js +0 -117
  66. package/lib/colors.js +0 -341
  67. package/lib/consent.js +0 -232
  68. package/lib/content-sanitizer.js +0 -464
  69. package/lib/correlation.js +0 -277
  70. package/lib/drivers/claude-driver.ts +0 -312
  71. package/lib/drivers/codex-driver.ts +0 -464
  72. package/lib/drivers/driver-manager.ts +0 -159
  73. package/lib/drivers/gemini-driver.ts +0 -498
  74. package/lib/drivers/index.ts +0 -17
  75. package/lib/error-codes.js +0 -590
  76. package/lib/errors.js +0 -670
  77. package/lib/feature-flags.js +0 -171
  78. package/lib/feedback.js +0 -595
  79. package/lib/file-cache.js +0 -541
  80. package/lib/flag-detection.js +0 -344
  81. package/lib/format-error.js +0 -156
  82. package/lib/gate-runner.js +0 -282
  83. package/lib/generator-factory.js +0 -333
  84. package/lib/git-operations.js +0 -266
  85. package/lib/lazy-require.js +0 -59
  86. package/lib/lock-file.js +0 -144
  87. package/lib/logger.js +0 -106
  88. package/lib/merge-operations.js +0 -1006
  89. package/lib/path-resolver.js +0 -544
  90. package/lib/path-utils.js +0 -49
  91. package/lib/paths.js +0 -291
  92. package/lib/placeholder-registry.js +0 -822
  93. package/lib/process-executor.js +0 -214
  94. package/lib/progress.js +0 -334
  95. package/lib/protocol/driver.ts +0 -354
  96. package/lib/protocol/index.ts +0 -12
  97. package/lib/protocol/ir.ts +0 -271
  98. package/lib/registry-cache.js +0 -80
  99. package/lib/registry-di.js +0 -358
  100. package/lib/result-schema.js +0 -363
  101. package/lib/result.js +0 -210
  102. package/lib/session-display.js +0 -331
  103. package/lib/session-operations.js +0 -611
  104. package/lib/session-registry.js +0 -484
  105. package/lib/session-state-machine.js +0 -465
  106. package/lib/session-switching.js +0 -191
  107. package/lib/skill-loader.js +0 -213
  108. package/lib/smart-json-file.js +0 -682
  109. package/lib/state-machine.js +0 -286
  110. package/lib/table-formatter.js +0 -519
  111. package/lib/template-loader.js +0 -143
  112. package/lib/transient-status.js +0 -374
  113. package/lib/ui-manager.js +0 -612
  114. package/lib/validate-args.js +0 -213
  115. package/lib/validate-commands.js +0 -308
  116. package/lib/validate-names.js +0 -143
  117. package/lib/validate-paths.js +0 -434
  118. package/lib/validate.js +0 -134
  119. package/lib/worktree-operations.js +0 -201
  120. package/lib/yaml-utils.js +0 -164
  121. package/scripts/README.md +0 -267
  122. package/scripts/af +0 -34
  123. package/scripts/agent-loop.js +0 -879
  124. package/scripts/agileflow-configure.js +0 -368
  125. package/scripts/agileflow-statusline.sh +0 -857
  126. package/scripts/agileflow-welcome.js +0 -2246
  127. package/scripts/api-server-runner.js +0 -177
  128. package/scripts/archive-completed-stories.sh +0 -308
  129. package/scripts/auto-self-improve.js +0 -326
  130. package/scripts/automation-run-due.js +0 -128
  131. package/scripts/babysit-clear-restore.js +0 -154
  132. package/scripts/babysit-context-restore.js +0 -89
  133. package/scripts/backfill-ideation-status.js +0 -128
  134. package/scripts/batch-pmap-loop.js +0 -551
  135. package/scripts/check-sessions.js +0 -116
  136. package/scripts/check-update.js +0 -282
  137. package/scripts/ci-summary.js +0 -294
  138. package/scripts/claude-smart.sh +0 -85
  139. package/scripts/claude-tmux.sh +0 -737
  140. package/scripts/claude-watchdog.sh +0 -225
  141. package/scripts/clear-active-command.js +0 -48
  142. package/scripts/compress-status.sh +0 -116
  143. package/scripts/context-loader.js +0 -310
  144. package/scripts/damage-control/bash-tool-damage-control.js +0 -22
  145. package/scripts/damage-control/edit-tool-damage-control.js +0 -19
  146. package/scripts/damage-control/patterns.yaml +0 -227
  147. package/scripts/damage-control/write-tool-damage-control.js +0 -19
  148. package/scripts/damage-control-bash.js +0 -51
  149. package/scripts/damage-control-edit.js +0 -48
  150. package/scripts/damage-control-multi-agent.js +0 -231
  151. package/scripts/damage-control-write.js +0 -48
  152. package/scripts/dependency-check.js +0 -311
  153. package/scripts/document-repl.js +0 -793
  154. package/scripts/expertise-metrics.sh +0 -264
  155. package/scripts/generate-all.sh +0 -77
  156. package/scripts/generate-colors.js +0 -314
  157. package/scripts/generators/agent-registry.js +0 -183
  158. package/scripts/generators/command-registry.js +0 -166
  159. package/scripts/generators/index.js +0 -85
  160. package/scripts/generators/inject-babysit.js +0 -191
  161. package/scripts/generators/inject-help.js +0 -125
  162. package/scripts/generators/inject-readme.js +0 -166
  163. package/scripts/generators/skill-registry.js +0 -188
  164. package/scripts/get-env.js +0 -225
  165. package/scripts/init.sh +0 -76
  166. package/scripts/lib/README-portable-tasks.md +0 -424
  167. package/scripts/lib/ac-test-matcher.js +0 -452
  168. package/scripts/lib/audit-cleanup.js +0 -250
  169. package/scripts/lib/audit-registry.js +0 -340
  170. package/scripts/lib/automation-registry.js +0 -544
  171. package/scripts/lib/automation-runner.js +0 -476
  172. package/scripts/lib/browser-qa-evidence.js +0 -409
  173. package/scripts/lib/browser-qa-status.js +0 -192
  174. package/scripts/lib/bus-utils.js +0 -473
  175. package/scripts/lib/colors.generated.sh +0 -82
  176. package/scripts/lib/colors.sh +0 -46
  177. package/scripts/lib/command-prereqs.js +0 -280
  178. package/scripts/lib/concurrency-limiter.js +0 -511
  179. package/scripts/lib/configure-detect.js +0 -596
  180. package/scripts/lib/configure-features.js +0 -1927
  181. package/scripts/lib/configure-repair.js +0 -327
  182. package/scripts/lib/configure-utils.js +0 -114
  183. package/scripts/lib/context-formatter.js +0 -1158
  184. package/scripts/lib/context-loader.js +0 -840
  185. package/scripts/lib/counter.js +0 -103
  186. package/scripts/lib/damage-control-utils.js +0 -619
  187. package/scripts/lib/feature-catalog.js +0 -332
  188. package/scripts/lib/file-lock.js +0 -392
  189. package/scripts/lib/file-tracking.js +0 -735
  190. package/scripts/lib/frontmatter-parser.js +0 -133
  191. package/scripts/lib/gate-enforcer.js +0 -295
  192. package/scripts/lib/hook-metrics.js +0 -324
  193. package/scripts/lib/ideation-index.js +0 -1205
  194. package/scripts/lib/json-utils.sh +0 -162
  195. package/scripts/lib/lifecycle-detector.js +0 -125
  196. package/scripts/lib/model-profiles.js +0 -118
  197. package/scripts/lib/portable-tasks-cli.js +0 -274
  198. package/scripts/lib/portable-tasks.js +0 -479
  199. package/scripts/lib/process-cleanup.js +0 -527
  200. package/scripts/lib/quality-gates.js +0 -788
  201. package/scripts/lib/scale-detector.js +0 -396
  202. package/scripts/lib/sessionRegistry.js +0 -678
  203. package/scripts/lib/signal-detectors.js +0 -867
  204. package/scripts/lib/skill-catalog.js +0 -557
  205. package/scripts/lib/skill-recommender.js +0 -311
  206. package/scripts/lib/state-migrator.js +0 -353
  207. package/scripts/lib/status-task-bridge.js +0 -522
  208. package/scripts/lib/status-writer.js +0 -255
  209. package/scripts/lib/story-claiming.js +0 -704
  210. package/scripts/lib/story-state-machine.js +0 -437
  211. package/scripts/lib/sync-ideation-status.js +0 -291
  212. package/scripts/lib/task-registry-cache.js +0 -490
  213. package/scripts/lib/task-registry.js +0 -1191
  214. package/scripts/lib/task-sync.js +0 -230
  215. package/scripts/lib/tdd-phase-manager.js +0 -455
  216. package/scripts/lib/team-events.js +0 -510
  217. package/scripts/lib/tmux-audit-monitor.js +0 -612
  218. package/scripts/lib/tmux-group-colors.js +0 -113
  219. package/scripts/lib/tool-registry.yaml +0 -241
  220. package/scripts/lib/tool-shed.js +0 -441
  221. package/scripts/lib/validation-registry.js +0 -177
  222. package/scripts/messaging-bridge.js +0 -561
  223. package/scripts/migrate-ideation-index.js +0 -553
  224. package/scripts/native-team-observer.js +0 -219
  225. package/scripts/obtain-context.js +0 -272
  226. package/scripts/pre-push-check.sh +0 -46
  227. package/scripts/precompact-context.sh +0 -306
  228. package/scripts/query-codebase.js +0 -543
  229. package/scripts/ralph-loop.js +0 -1278
  230. package/scripts/resume-session.sh +0 -121
  231. package/scripts/screenshot-verifier.js +0 -215
  232. package/scripts/session-boundary.js +0 -138
  233. package/scripts/session-coordinator.sh +0 -232
  234. package/scripts/session-manager.js +0 -546
  235. package/scripts/smart-detect.js +0 -449
  236. package/scripts/spawn-audit-sessions.js +0 -877
  237. package/scripts/spawn-parallel.js +0 -751
  238. package/scripts/strip-ai-attribution.js +0 -63
  239. package/scripts/task-completed-gate.js +0 -237
  240. package/scripts/team-manager.js +0 -596
  241. package/scripts/team-status-display.js +0 -200
  242. package/scripts/teammate-idle-gate.js +0 -237
  243. package/scripts/test-session-boundary.js +0 -80
  244. package/scripts/tmux-close-windows.sh +0 -180
  245. package/scripts/tmux-restore-window.sh +0 -67
  246. package/scripts/tmux-save-closed-window.sh +0 -35
  247. package/scripts/tui/App.js +0 -151
  248. package/scripts/tui/Dashboard.js +0 -277
  249. package/scripts/tui/blessed/data/watcher.js +0 -180
  250. package/scripts/tui/blessed/index.js +0 -244
  251. package/scripts/tui/blessed/panels/output.js +0 -101
  252. package/scripts/tui/blessed/panels/sessions.js +0 -150
  253. package/scripts/tui/blessed/panels/trace.js +0 -97
  254. package/scripts/tui/blessed/ui/help.js +0 -77
  255. package/scripts/tui/blessed/ui/screen.js +0 -52
  256. package/scripts/tui/blessed/ui/statusbar.js +0 -47
  257. package/scripts/tui/blessed/ui/tabbar.js +0 -99
  258. package/scripts/tui/index.js +0 -70
  259. package/scripts/tui/lib/crashRecovery.js +0 -304
  260. package/scripts/tui/lib/eventStream.js +0 -309
  261. package/scripts/tui/lib/keyboard.js +0 -261
  262. package/scripts/tui/lib/loopControl.js +0 -371
  263. package/scripts/tui/panels/OutputPanel.js +0 -240
  264. package/scripts/tui/panels/SessionPanel.js +0 -170
  265. package/scripts/tui/panels/TracePanel.js +0 -298
  266. package/scripts/tui/simple-tui.js +0 -510
  267. package/scripts/validate-expertise.sh +0 -263
  268. package/scripts/validate-tokens.sh +0 -73
  269. package/scripts/validators/README.md +0 -143
  270. package/scripts/validators/component-validator.js +0 -239
  271. package/scripts/validators/json-schema-validator.js +0 -186
  272. package/scripts/validators/markdown-validator.js +0 -152
  273. package/scripts/validators/migration-validator.js +0 -129
  274. package/scripts/validators/security-validator.js +0 -380
  275. package/scripts/validators/story-format-validator.js +0 -197
  276. package/scripts/validators/test-result-validator.js +0 -114
  277. package/scripts/validators/workflow-validator.js +0 -247
  278. package/scripts/welcome-deferred.js +0 -437
  279. package/scripts/worktree-create.sh +0 -111
  280. package/src/core/agents/a11y-analyzer-aria.md +0 -155
  281. package/src/core/agents/a11y-analyzer-forms.md +0 -162
  282. package/src/core/agents/a11y-analyzer-keyboard.md +0 -175
  283. package/src/core/agents/a11y-analyzer-semantic.md +0 -153
  284. package/src/core/agents/a11y-analyzer-visual.md +0 -158
  285. package/src/core/agents/a11y-consensus.md +0 -248
  286. package/src/core/agents/accessibility.md +0 -515
  287. package/src/core/agents/adr-writer.md +0 -463
  288. package/src/core/agents/ads-audit-budget.md +0 -181
  289. package/src/core/agents/ads-audit-compliance.md +0 -169
  290. package/src/core/agents/ads-audit-creative.md +0 -164
  291. package/src/core/agents/ads-audit-google.md +0 -226
  292. package/src/core/agents/ads-audit-meta.md +0 -183
  293. package/src/core/agents/ads-audit-tracking.md +0 -197
  294. package/src/core/agents/ads-consensus.md +0 -396
  295. package/src/core/agents/ads-generate.md +0 -145
  296. package/src/core/agents/ads-performance-tracker.md +0 -197
  297. package/src/core/agents/analytics.md +0 -617
  298. package/src/core/agents/api-quality-analyzer-conventions.md +0 -148
  299. package/src/core/agents/api-quality-analyzer-docs.md +0 -176
  300. package/src/core/agents/api-quality-analyzer-errors.md +0 -183
  301. package/src/core/agents/api-quality-analyzer-pagination.md +0 -171
  302. package/src/core/agents/api-quality-analyzer-versioning.md +0 -143
  303. package/src/core/agents/api-quality-consensus.md +0 -214
  304. package/src/core/agents/api-validator.md +0 -183
  305. package/src/core/agents/api.md +0 -665
  306. package/src/core/agents/arch-analyzer-circular.md +0 -148
  307. package/src/core/agents/arch-analyzer-complexity.md +0 -171
  308. package/src/core/agents/arch-analyzer-coupling.md +0 -146
  309. package/src/core/agents/arch-analyzer-layering.md +0 -151
  310. package/src/core/agents/arch-analyzer-patterns.md +0 -162
  311. package/src/core/agents/arch-consensus.md +0 -227
  312. package/src/core/agents/brainstorm-analyzer-features.md +0 -169
  313. package/src/core/agents/brainstorm-analyzer-growth.md +0 -161
  314. package/src/core/agents/brainstorm-analyzer-integration.md +0 -172
  315. package/src/core/agents/brainstorm-analyzer-market.md +0 -147
  316. package/src/core/agents/brainstorm-analyzer-ux.md +0 -167
  317. package/src/core/agents/brainstorm-consensus.md +0 -237
  318. package/src/core/agents/browser-qa.md +0 -328
  319. package/src/core/agents/ci.md +0 -511
  320. package/src/core/agents/code-reviewer.md +0 -288
  321. package/src/core/agents/codebase-query.md +0 -266
  322. package/src/core/agents/completeness-analyzer-api.md +0 -190
  323. package/src/core/agents/completeness-analyzer-conditional.md +0 -201
  324. package/src/core/agents/completeness-analyzer-handlers.md +0 -159
  325. package/src/core/agents/completeness-analyzer-imports.md +0 -159
  326. package/src/core/agents/completeness-analyzer-routes.md +0 -182
  327. package/src/core/agents/completeness-analyzer-state.md +0 -188
  328. package/src/core/agents/completeness-analyzer-stubs.md +0 -198
  329. package/src/core/agents/completeness-consensus.md +0 -286
  330. package/src/core/agents/compliance.md +0 -509
  331. package/src/core/agents/council-advocate.md +0 -206
  332. package/src/core/agents/council-analyst.md +0 -252
  333. package/src/core/agents/council-optimist.md +0 -170
  334. package/src/core/agents/database.md +0 -601
  335. package/src/core/agents/datamigration.md +0 -699
  336. package/src/core/agents/design.md +0 -525
  337. package/src/core/agents/devops.md +0 -720
  338. package/src/core/agents/documentation.md +0 -504
  339. package/src/core/agents/epic-planner.md +0 -480
  340. package/src/core/agents/error-analyzer.md +0 -201
  341. package/src/core/agents/integrations.md +0 -603
  342. package/src/core/agents/legal-analyzer-a11y.md +0 -110
  343. package/src/core/agents/legal-analyzer-ai.md +0 -117
  344. package/src/core/agents/legal-analyzer-consumer.md +0 -108
  345. package/src/core/agents/legal-analyzer-content.md +0 -113
  346. package/src/core/agents/legal-analyzer-international.md +0 -115
  347. package/src/core/agents/legal-analyzer-licensing.md +0 -115
  348. package/src/core/agents/legal-analyzer-privacy.md +0 -108
  349. package/src/core/agents/legal-analyzer-security.md +0 -112
  350. package/src/core/agents/legal-analyzer-terms.md +0 -111
  351. package/src/core/agents/legal-consensus.md +0 -242
  352. package/src/core/agents/logic-analyzer-edge.md +0 -170
  353. package/src/core/agents/logic-analyzer-flow.md +0 -253
  354. package/src/core/agents/logic-analyzer-invariant.md +0 -206
  355. package/src/core/agents/logic-analyzer-race.md +0 -266
  356. package/src/core/agents/logic-analyzer-type.md +0 -217
  357. package/src/core/agents/logic-consensus.md +0 -253
  358. package/src/core/agents/mentor.md +0 -654
  359. package/src/core/agents/mobile.md +0 -501
  360. package/src/core/agents/monitoring.md +0 -537
  361. package/src/core/agents/multi-expert.md +0 -311
  362. package/src/core/agents/orchestrator.md +0 -749
  363. package/src/core/agents/perf-analyzer-assets.md +0 -174
  364. package/src/core/agents/perf-analyzer-bundle.md +0 -165
  365. package/src/core/agents/perf-analyzer-caching.md +0 -160
  366. package/src/core/agents/perf-analyzer-compute.md +0 -165
  367. package/src/core/agents/perf-analyzer-memory.md +0 -182
  368. package/src/core/agents/perf-analyzer-network.md +0 -157
  369. package/src/core/agents/perf-analyzer-queries.md +0 -155
  370. package/src/core/agents/perf-analyzer-rendering.md +0 -156
  371. package/src/core/agents/perf-consensus.md +0 -280
  372. package/src/core/agents/performance.md +0 -492
  373. package/src/core/agents/product.md +0 -535
  374. package/src/core/agents/qa.md +0 -765
  375. package/src/core/agents/readme-updater.md +0 -579
  376. package/src/core/agents/refactor.md +0 -558
  377. package/src/core/agents/research.md +0 -453
  378. package/src/core/agents/rlm-subcore.md +0 -207
  379. package/src/core/agents/schema-validator.md +0 -454
  380. package/src/core/agents/security-analyzer-api.md +0 -199
  381. package/src/core/agents/security-analyzer-auth.md +0 -160
  382. package/src/core/agents/security-analyzer-authz.md +0 -168
  383. package/src/core/agents/security-analyzer-deps.md +0 -147
  384. package/src/core/agents/security-analyzer-infra.md +0 -176
  385. package/src/core/agents/security-analyzer-injection.md +0 -148
  386. package/src/core/agents/security-analyzer-input.md +0 -191
  387. package/src/core/agents/security-analyzer-secrets.md +0 -175
  388. package/src/core/agents/security-consensus.md +0 -276
  389. package/src/core/agents/security.md +0 -486
  390. package/src/core/agents/seo-analyzer-content.md +0 -167
  391. package/src/core/agents/seo-analyzer-images.md +0 -187
  392. package/src/core/agents/seo-analyzer-performance.md +0 -206
  393. package/src/core/agents/seo-analyzer-schema.md +0 -176
  394. package/src/core/agents/seo-analyzer-sitemap.md +0 -172
  395. package/src/core/agents/seo-analyzer-technical.md +0 -144
  396. package/src/core/agents/seo-consensus.md +0 -289
  397. package/src/core/agents/team-coordinator.md +0 -333
  398. package/src/core/agents/team-lead.md +0 -171
  399. package/src/core/agents/test-analyzer-assertions.md +0 -181
  400. package/src/core/agents/test-analyzer-coverage.md +0 -183
  401. package/src/core/agents/test-analyzer-fragility.md +0 -185
  402. package/src/core/agents/test-analyzer-integration.md +0 -155
  403. package/src/core/agents/test-analyzer-maintenance.md +0 -173
  404. package/src/core/agents/test-analyzer-mocking.md +0 -178
  405. package/src/core/agents/test-analyzer-patterns.md +0 -189
  406. package/src/core/agents/test-analyzer-structure.md +0 -177
  407. package/src/core/agents/test-consensus.md +0 -294
  408. package/src/core/agents/testing.md +0 -527
  409. package/src/core/agents/ui-validator.md +0 -331
  410. package/src/core/agents/ui.md +0 -1227
  411. package/src/core/commands/adr/list.md +0 -191
  412. package/src/core/commands/adr/update.md +0 -258
  413. package/src/core/commands/adr/view.md +0 -274
  414. package/src/core/commands/adr.md +0 -394
  415. package/src/core/commands/ads/audit.md +0 -453
  416. package/src/core/commands/ads/budget.md +0 -97
  417. package/src/core/commands/ads/competitor.md +0 -112
  418. package/src/core/commands/ads/creative.md +0 -85
  419. package/src/core/commands/ads/generate.md +0 -238
  420. package/src/core/commands/ads/google.md +0 -112
  421. package/src/core/commands/ads/health.md +0 -327
  422. package/src/core/commands/ads/landing.md +0 -119
  423. package/src/core/commands/ads/linkedin.md +0 -112
  424. package/src/core/commands/ads/meta.md +0 -91
  425. package/src/core/commands/ads/microsoft.md +0 -115
  426. package/src/core/commands/ads/plan.md +0 -321
  427. package/src/core/commands/ads/test-plan.md +0 -317
  428. package/src/core/commands/ads/tiktok.md +0 -129
  429. package/src/core/commands/ads/track.md +0 -288
  430. package/src/core/commands/ads/youtube.md +0 -124
  431. package/src/core/commands/ads.md +0 -140
  432. package/src/core/commands/agent.md +0 -256
  433. package/src/core/commands/api.md +0 -267
  434. package/src/core/commands/assign.md +0 -369
  435. package/src/core/commands/audit.md +0 -531
  436. package/src/core/commands/auto.md +0 -556
  437. package/src/core/commands/automate.md +0 -415
  438. package/src/core/commands/babysit.md +0 -643
  439. package/src/core/commands/baseline.md +0 -743
  440. package/src/core/commands/batch.md +0 -551
  441. package/src/core/commands/blockers.md +0 -602
  442. package/src/core/commands/board.md +0 -509
  443. package/src/core/commands/browser-qa.md +0 -240
  444. package/src/core/commands/changelog.md +0 -582
  445. package/src/core/commands/choose.md +0 -430
  446. package/src/core/commands/ci.md +0 -330
  447. package/src/core/commands/code/accessibility.md +0 -363
  448. package/src/core/commands/code/api.md +0 -313
  449. package/src/core/commands/code/architecture.md +0 -313
  450. package/src/core/commands/code/completeness.md +0 -519
  451. package/src/core/commands/code/legal.md +0 -509
  452. package/src/core/commands/code/logic.md +0 -432
  453. package/src/core/commands/code/performance.md +0 -506
  454. package/src/core/commands/code/security.md +0 -509
  455. package/src/core/commands/code/test.md +0 -505
  456. package/src/core/commands/compress.md +0 -408
  457. package/src/core/commands/configure.md +0 -1159
  458. package/src/core/commands/context/export.md +0 -296
  459. package/src/core/commands/context/full.md +0 -353
  460. package/src/core/commands/context/note.md +0 -380
  461. package/src/core/commands/council.md +0 -592
  462. package/src/core/commands/debt.md +0 -491
  463. package/src/core/commands/deploy.md +0 -864
  464. package/src/core/commands/deps.md +0 -728
  465. package/src/core/commands/diagnose.md +0 -404
  466. package/src/core/commands/docs.md +0 -469
  467. package/src/core/commands/epic/edit.md +0 -213
  468. package/src/core/commands/epic/list.md +0 -190
  469. package/src/core/commands/epic/view.md +0 -267
  470. package/src/core/commands/epic.md +0 -477
  471. package/src/core/commands/export.md +0 -238
  472. package/src/core/commands/feedback.md +0 -603
  473. package/src/core/commands/handoff.md +0 -386
  474. package/src/core/commands/help.md +0 -194
  475. package/src/core/commands/ideate/brief.md +0 -363
  476. package/src/core/commands/ideate/discover.md +0 -399
  477. package/src/core/commands/ideate/features.md +0 -497
  478. package/src/core/commands/ideate/history.md +0 -403
  479. package/src/core/commands/ideate/new.md +0 -900
  480. package/src/core/commands/impact.md +0 -407
  481. package/src/core/commands/install.md +0 -529
  482. package/src/core/commands/learn/explain.md +0 -118
  483. package/src/core/commands/learn/glossary.md +0 -135
  484. package/src/core/commands/learn/patterns.md +0 -138
  485. package/src/core/commands/learn/tour.md +0 -126
  486. package/src/core/commands/maintain.md +0 -558
  487. package/src/core/commands/metrics.md +0 -844
  488. package/src/core/commands/migrate/codemods.md +0 -151
  489. package/src/core/commands/migrate/plan.md +0 -131
  490. package/src/core/commands/migrate/scan.md +0 -114
  491. package/src/core/commands/migrate/validate.md +0 -119
  492. package/src/core/commands/multi-expert.md +0 -447
  493. package/src/core/commands/packages.md +0 -535
  494. package/src/core/commands/pr.md +0 -337
  495. package/src/core/commands/readme-sync.md +0 -329
  496. package/src/core/commands/research/analyze.md +0 -798
  497. package/src/core/commands/research/ask.md +0 -864
  498. package/src/core/commands/research/import.md +0 -1025
  499. package/src/core/commands/research/list.md +0 -273
  500. package/src/core/commands/research/synthesize.md +0 -928
  501. package/src/core/commands/research/view.md +0 -323
  502. package/src/core/commands/retro.md +0 -795
  503. package/src/core/commands/review.md +0 -694
  504. package/src/core/commands/rlm.md +0 -446
  505. package/src/core/commands/roadmap/analyze.md +0 -400
  506. package/src/core/commands/rpi.md +0 -633
  507. package/src/core/commands/seo/audit.md +0 -444
  508. package/src/core/commands/seo/competitor.md +0 -174
  509. package/src/core/commands/seo/content.md +0 -107
  510. package/src/core/commands/seo/geo.md +0 -229
  511. package/src/core/commands/seo/hreflang.md +0 -140
  512. package/src/core/commands/seo/images.md +0 -96
  513. package/src/core/commands/seo/page.md +0 -198
  514. package/src/core/commands/seo/plan.md +0 -163
  515. package/src/core/commands/seo/programmatic.md +0 -131
  516. package/src/core/commands/seo/references/cwv-thresholds.md +0 -64
  517. package/src/core/commands/seo/references/eeat-framework.md +0 -110
  518. package/src/core/commands/seo/references/quality-gates.md +0 -91
  519. package/src/core/commands/seo/references/schema-types.md +0 -102
  520. package/src/core/commands/seo/schema.md +0 -183
  521. package/src/core/commands/seo/sitemap.md +0 -97
  522. package/src/core/commands/seo/technical.md +0 -100
  523. package/src/core/commands/seo.md +0 -107
  524. package/src/core/commands/session/cleanup.md +0 -452
  525. package/src/core/commands/session/end.md +0 -865
  526. package/src/core/commands/session/history.md +0 -293
  527. package/src/core/commands/session/init.md +0 -210
  528. package/src/core/commands/session/new.md +0 -827
  529. package/src/core/commands/session/resume.md +0 -291
  530. package/src/core/commands/session/spawn.md +0 -205
  531. package/src/core/commands/session/status.md +0 -274
  532. package/src/core/commands/skill/list.md +0 -139
  533. package/src/core/commands/skill/recommend.md +0 -216
  534. package/src/core/commands/sprint.md +0 -714
  535. package/src/core/commands/status/undo.md +0 -191
  536. package/src/core/commands/status.md +0 -423
  537. package/src/core/commands/story/edit.md +0 -204
  538. package/src/core/commands/story/list.md +0 -199
  539. package/src/core/commands/story/view.md +0 -312
  540. package/src/core/commands/story-validate.md +0 -491
  541. package/src/core/commands/story.md +0 -465
  542. package/src/core/commands/tdd-next.md +0 -238
  543. package/src/core/commands/tdd.md +0 -211
  544. package/src/core/commands/team/guide.md +0 -688
  545. package/src/core/commands/team/list.md +0 -59
  546. package/src/core/commands/team/start.md +0 -130
  547. package/src/core/commands/team/status.md +0 -66
  548. package/src/core/commands/team/stop.md +0 -78
  549. package/src/core/commands/template.md +0 -644
  550. package/src/core/commands/tests.md +0 -731
  551. package/src/core/commands/update.md +0 -591
  552. package/src/core/commands/validate-expertise.md +0 -305
  553. package/src/core/commands/velocity.md +0 -630
  554. package/src/core/commands/verify.md +0 -534
  555. package/src/core/commands/whats-new.md +0 -201
  556. package/src/core/commands/workflow.md +0 -449
  557. package/src/core/council/sessions/.gitkeep +0 -0
  558. package/src/core/council/shared_reasoning.template.md +0 -106
  559. package/src/core/experts/README.md +0 -236
  560. package/src/core/experts/_core-expertise.yaml +0 -105
  561. package/src/core/experts/accessibility/expertise.yaml +0 -115
  562. package/src/core/experts/accessibility/question.md +0 -41
  563. package/src/core/experts/accessibility/self-improve.md +0 -45
  564. package/src/core/experts/accessibility/workflow.md +0 -59
  565. package/src/core/experts/adr-writer/expertise.yaml +0 -138
  566. package/src/core/experts/adr-writer/question.md +0 -56
  567. package/src/core/experts/adr-writer/self-improve.md +0 -106
  568. package/src/core/experts/adr-writer/workflow.md +0 -184
  569. package/src/core/experts/analytics/expertise.yaml +0 -119
  570. package/src/core/experts/analytics/question.md +0 -74
  571. package/src/core/experts/analytics/self-improve.md +0 -163
  572. package/src/core/experts/analytics/workflow.md +0 -272
  573. package/src/core/experts/api/expertise.yaml +0 -124
  574. package/src/core/experts/api/question.md +0 -74
  575. package/src/core/experts/api/self-improve.md +0 -122
  576. package/src/core/experts/api/workflow.md +0 -248
  577. package/src/core/experts/ci/expertise.yaml +0 -106
  578. package/src/core/experts/ci/question.md +0 -69
  579. package/src/core/experts/ci/self-improve.md +0 -100
  580. package/src/core/experts/ci/workflow.md +0 -145
  581. package/src/core/experts/codebase-query/expertise.yaml +0 -121
  582. package/src/core/experts/codebase-query/question.md +0 -73
  583. package/src/core/experts/codebase-query/self-improve.md +0 -105
  584. package/src/core/experts/compliance/expertise.yaml +0 -101
  585. package/src/core/experts/compliance/question.md +0 -56
  586. package/src/core/experts/compliance/self-improve.md +0 -106
  587. package/src/core/experts/compliance/workflow.md +0 -184
  588. package/src/core/experts/database/expertise.yaml +0 -109
  589. package/src/core/experts/database/question.md +0 -74
  590. package/src/core/experts/database/self-improve.md +0 -121
  591. package/src/core/experts/database/workflow.md +0 -234
  592. package/src/core/experts/datamigration/expertise.yaml +0 -141
  593. package/src/core/experts/datamigration/question.md +0 -56
  594. package/src/core/experts/datamigration/self-improve.md +0 -106
  595. package/src/core/experts/datamigration/workflow.md +0 -184
  596. package/src/core/experts/design/expertise.yaml +0 -116
  597. package/src/core/experts/design/question.md +0 -56
  598. package/src/core/experts/design/self-improve.md +0 -106
  599. package/src/core/experts/design/workflow.md +0 -184
  600. package/src/core/experts/devops/expertise.yaml +0 -116
  601. package/src/core/experts/devops/question.md +0 -68
  602. package/src/core/experts/devops/self-improve.md +0 -102
  603. package/src/core/experts/devops/workflow.md +0 -142
  604. package/src/core/experts/documentation/expertise.yaml +0 -126
  605. package/src/core/experts/documentation/question.md +0 -41
  606. package/src/core/experts/documentation/self-improve.md +0 -45
  607. package/src/core/experts/documentation/workflow.md +0 -55
  608. package/src/core/experts/epic-planner/expertise.yaml +0 -144
  609. package/src/core/experts/epic-planner/question.md +0 -56
  610. package/src/core/experts/epic-planner/self-improve.md +0 -106
  611. package/src/core/experts/epic-planner/workflow.md +0 -184
  612. package/src/core/experts/integrations/expertise.yaml +0 -113
  613. package/src/core/experts/integrations/question.md +0 -74
  614. package/src/core/experts/integrations/self-improve.md +0 -151
  615. package/src/core/experts/integrations/workflow.md +0 -246
  616. package/src/core/experts/mentor/expertise.yaml +0 -125
  617. package/src/core/experts/mentor/question.md +0 -56
  618. package/src/core/experts/mentor/self-improve.md +0 -106
  619. package/src/core/experts/mentor/workflow.md +0 -184
  620. package/src/core/experts/mobile/expertise.yaml +0 -136
  621. package/src/core/experts/mobile/question.md +0 -72
  622. package/src/core/experts/mobile/self-improve.md +0 -140
  623. package/src/core/experts/mobile/workflow.md +0 -240
  624. package/src/core/experts/monitoring/expertise.yaml +0 -132
  625. package/src/core/experts/monitoring/question.md +0 -76
  626. package/src/core/experts/monitoring/self-improve.md +0 -150
  627. package/src/core/experts/monitoring/workflow.md +0 -264
  628. package/src/core/experts/performance/expertise.yaml +0 -68
  629. package/src/core/experts/performance/question.md +0 -41
  630. package/src/core/experts/performance/self-improve.md +0 -45
  631. package/src/core/experts/performance/workflow.md +0 -61
  632. package/src/core/experts/product/expertise.yaml +0 -143
  633. package/src/core/experts/product/question.md +0 -56
  634. package/src/core/experts/product/self-improve.md +0 -106
  635. package/src/core/experts/product/workflow.md +0 -184
  636. package/src/core/experts/qa/expertise.yaml +0 -110
  637. package/src/core/experts/qa/question.md +0 -56
  638. package/src/core/experts/qa/self-improve.md +0 -106
  639. package/src/core/experts/qa/workflow.md +0 -184
  640. package/src/core/experts/readme-updater/expertise.yaml +0 -141
  641. package/src/core/experts/readme-updater/question.md +0 -56
  642. package/src/core/experts/readme-updater/self-improve.md +0 -106
  643. package/src/core/experts/readme-updater/workflow.md +0 -184
  644. package/src/core/experts/refactor/expertise.yaml +0 -135
  645. package/src/core/experts/refactor/question.md +0 -41
  646. package/src/core/experts/refactor/self-improve.md +0 -45
  647. package/src/core/experts/refactor/workflow.md +0 -57
  648. package/src/core/experts/research/expertise.yaml +0 -143
  649. package/src/core/experts/research/question.md +0 -56
  650. package/src/core/experts/research/self-improve.md +0 -106
  651. package/src/core/experts/research/workflow.md +0 -184
  652. package/src/core/experts/security/expertise.yaml +0 -117
  653. package/src/core/experts/security/question.md +0 -77
  654. package/src/core/experts/security/self-improve.md +0 -102
  655. package/src/core/experts/security/workflow.md +0 -152
  656. package/src/core/experts/templates/expertise-template.yaml +0 -67
  657. package/src/core/experts/templates/question-template.md +0 -56
  658. package/src/core/experts/templates/self-improve-template.md +0 -106
  659. package/src/core/experts/templates/workflow-template.md +0 -184
  660. package/src/core/experts/testing/expertise.yaml +0 -112
  661. package/src/core/experts/testing/question.md +0 -68
  662. package/src/core/experts/testing/self-improve.md +0 -102
  663. package/src/core/experts/testing/workflow.md +0 -143
  664. package/src/core/experts/ui/expertise.yaml +0 -133
  665. package/src/core/experts/ui/question.md +0 -74
  666. package/src/core/experts/ui/self-improve.md +0 -122
  667. package/src/core/experts/ui/workflow.md +0 -262
  668. package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +0 -424
  669. package/src/core/knowledge/ads/ad-optimization-logic.md +0 -590
  670. package/src/core/knowledge/ads/ad-technical-specifications.md +0 -385
  671. package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +0 -506
  672. package/src/core/knowledge/ads/paid-advertising-research-2026.md +0 -445
  673. package/src/core/profiles/COMPARISON.md +0 -170
  674. package/src/core/profiles/README.md +0 -178
  675. package/src/core/profiles/claude-code.yaml +0 -111
  676. package/src/core/profiles/codex.yaml +0 -103
  677. package/src/core/profiles/cursor.yaml +0 -134
  678. package/src/core/profiles/examples.js +0 -250
  679. package/src/core/profiles/loader.js +0 -235
  680. package/src/core/profiles/windsurf.yaml +0 -159
  681. package/src/core/skills/_learnings/README.md +0 -91
  682. package/src/core/skills/_learnings/_template.yaml +0 -106
  683. package/src/core/skills/_learnings/code-review.yaml +0 -118
  684. package/src/core/skills/_learnings/commit.yaml +0 -69
  685. package/src/core/skills/_learnings/story-writer.yaml +0 -71
  686. package/src/core/teams/backend.json +0 -41
  687. package/src/core/teams/builder-validator.json +0 -51
  688. package/src/core/teams/code-review.json +0 -41
  689. package/src/core/teams/frontend.json +0 -41
  690. package/src/core/teams/fullstack.json +0 -41
  691. package/src/core/teams/logic-audit.json +0 -53
  692. package/src/core/teams/perf-audit.json +0 -71
  693. package/src/core/teams/qa.json +0 -41
  694. package/src/core/teams/security-audit.json +0 -71
  695. package/src/core/teams/solo.json +0 -35
  696. package/src/core/teams/test-audit.json +0 -71
  697. package/src/core/templates/CONTEXT.md.example +0 -49
  698. package/src/core/templates/README-template.md +0 -16
  699. package/src/core/templates/adr-template.md +0 -28
  700. package/src/core/templates/agent-coordination-pattern.md +0 -38
  701. package/src/core/templates/agent-profile-template.md +0 -51
  702. package/src/core/templates/agileflow-metadata.json +0 -150
  703. package/src/core/templates/browser-qa-spec.yaml +0 -94
  704. package/src/core/templates/ci-workflow.yml +0 -74
  705. package/src/core/templates/claude-settings.advanced.example.json +0 -75
  706. package/src/core/templates/claude-settings.example.json +0 -26
  707. package/src/core/templates/command-documentation.md +0 -187
  708. package/src/core/templates/command-prerequisites.yaml +0 -169
  709. package/src/core/templates/comms-note-template.md +0 -24
  710. package/src/core/templates/damage-control-patterns.yaml +0 -243
  711. package/src/core/templates/environment.json +0 -18
  712. package/src/core/templates/epic-template.md +0 -27
  713. package/src/core/templates/plan-template.md +0 -125
  714. package/src/core/templates/preserve-rules-common.md +0 -107
  715. package/src/core/templates/preserve-rules.json +0 -42
  716. package/src/core/templates/proactive-action-spec.md +0 -29
  717. package/src/core/templates/product-brief.md +0 -136
  718. package/src/core/templates/quality-gate-priorities.md +0 -34
  719. package/src/core/templates/research-template.md +0 -44
  720. package/src/core/templates/session-harness-protocol.md +0 -128
  721. package/src/core/templates/session-state.json +0 -56
  722. package/src/core/templates/story-lifecycle.md +0 -213
  723. package/src/core/templates/story-template.md +0 -92
  724. package/src/core/templates/tdd-test-template.js +0 -241
  725. package/src/core/templates/worktrees-guide.md +0 -231
  726. package/tools/agileflow-npx.js +0 -52
  727. package/tools/cli/agileflow-cli.js +0 -72
  728. package/tools/cli/commands/config.js +0 -285
  729. package/tools/cli/commands/doctor.js +0 -496
  730. package/tools/cli/commands/list.js +0 -385
  731. package/tools/cli/commands/session.js +0 -1176
  732. package/tools/cli/commands/setup.js +0 -255
  733. package/tools/cli/commands/status.js +0 -101
  734. package/tools/cli/commands/tui.js +0 -56
  735. package/tools/cli/commands/uninstall.js +0 -155
  736. package/tools/cli/commands/update.js +0 -299
  737. package/tools/cli/installers/core/installer.js +0 -892
  738. package/tools/cli/installers/ide/_base-ide.js +0 -518
  739. package/tools/cli/installers/ide/_interface.js +0 -238
  740. package/tools/cli/installers/ide/claude-code.js +0 -432
  741. package/tools/cli/installers/ide/codex.js +0 -426
  742. package/tools/cli/installers/ide/cursor.js +0 -217
  743. package/tools/cli/installers/ide/manager.js +0 -222
  744. package/tools/cli/installers/ide/windsurf.js +0 -282
  745. package/tools/cli/lib/command-context.js +0 -382
  746. package/tools/cli/lib/config-manager.js +0 -446
  747. package/tools/cli/lib/content-injector.js +0 -969
  748. package/tools/cli/lib/content-transformer.js +0 -496
  749. package/tools/cli/lib/docs-setup.js +0 -464
  750. package/tools/cli/lib/error-handler.js +0 -165
  751. package/tools/cli/lib/ide-error-factory.js +0 -421
  752. package/tools/cli/lib/ide-errors.js +0 -367
  753. package/tools/cli/lib/ide-generator.js +0 -357
  754. package/tools/cli/lib/ide-health-monitor.js +0 -364
  755. package/tools/cli/lib/ide-registry.js +0 -297
  756. package/tools/cli/lib/npm-utils.js +0 -103
  757. package/tools/cli/lib/self-update.js +0 -148
  758. package/tools/cli/lib/ui.js +0 -211
  759. package/tools/cli/lib/utils.js +0 -87
  760. package/tools/cli/lib/validation-middleware.js +0 -491
  761. package/tools/cli/lib/version-checker.js +0 -95
  762. package/tools/postinstall.js +0 -190
@@ -1,1927 +0,0 @@
1
- /**
2
- * configure-features.js - Feature enable/disable handlers for agileflow-configure
3
- *
4
- * Extracted from agileflow-configure.js (US-0094)
5
- */
6
-
7
- const fs = require('fs');
8
- const path = require('path');
9
- const crypto = require('crypto');
10
- const os = require('os');
11
- const {
12
- c,
13
- log,
14
- success,
15
- warn,
16
- error,
17
- info,
18
- header,
19
- ensureDir,
20
- readJSON,
21
- writeJSON,
22
- updateGitignore,
23
- } = require('./configure-utils');
24
-
25
- // ============================================================================
26
- // CONFIGURATION CONSTANTS
27
- // ============================================================================
28
-
29
- const FEATURES = {
30
- sessionstart: { hook: 'SessionStart', script: 'agileflow-welcome.js', type: 'node' },
31
- precompact: { hook: 'PreCompact', script: 'precompact-context.sh', type: 'bash' },
32
- ralphloop: { hook: 'Stop', script: 'ralph-loop.js', type: 'node' },
33
- selfimprove: { hook: 'Stop', script: 'auto-self-improve.js', type: 'node' },
34
- archival: { script: 'archive-completed-stories.sh', requiresHook: 'sessionstart' },
35
- statusline: { script: 'agileflow-statusline.sh' },
36
- autoupdate: { metadataOnly: true },
37
- damagecontrol: {
38
- preToolUseHooks: true,
39
- scripts: ['damage-control-bash.js', 'damage-control-edit.js', 'damage-control-write.js'],
40
- patternsFile: 'damage-control-patterns.yaml',
41
- },
42
- askuserquestion: { metadataOnly: true },
43
- tmuxautospawn: { metadataOnly: true },
44
- shellaliases: {
45
- metadataOnly: false,
46
- description: 'Shell aliases (af/agileflow) for tmux-wrapped Claude',
47
- },
48
- claudemdreinforcement: {
49
- metadataOnly: false,
50
- description: 'Add /babysit rules to CLAUDE.md for context preservation',
51
- },
52
- processcleanup: {
53
- metadataOnly: true,
54
- description: 'Auto-kill duplicate Claude processes in same directory to prevent freezing',
55
- },
56
- claudeflags: {
57
- metadataOnly: false,
58
- description:
59
- 'Default flags for Claude CLI (sets permissions.defaultMode in .claude/settings.json)',
60
- },
61
- agentteams: {
62
- metadataOnly: false,
63
- description: 'Enable Claude Code native Agent Teams (sets env var in .claude/settings.json)',
64
- },
65
- noaiattribution: {
66
- preToolUseHook: true,
67
- script: 'strip-ai-attribution.js',
68
- description: 'Block git commits containing AI attribution (Co-Authored-By, etc.)',
69
- },
70
- browserqa: {
71
- metadataOnly: false,
72
- description:
73
- 'Agentic browser testing with Playwright (Bowser four-layer pattern). Screenshot evidence, 80% pass rate threshold.',
74
- },
75
- contextverbosity: {
76
- metadataOnly: true,
77
- description: 'Control how much context is loaded per command (full/lite/minimal)',
78
- },
79
- };
80
-
81
- const PROFILES = {
82
- full: {
83
- description: 'All features enabled (including experimental Stop hooks)',
84
- enable: [
85
- 'sessionstart',
86
- 'precompact',
87
- 'archival',
88
- 'statusline',
89
- 'ralphloop',
90
- 'selfimprove',
91
- 'askuserquestion',
92
- 'tmuxautospawn',
93
- 'noaiattribution',
94
- ],
95
- archivalDays: 30,
96
- },
97
- basic: {
98
- description: 'Essential hooks + archival (SessionStart + PreCompact + Archival)',
99
- enable: [
100
- 'sessionstart',
101
- 'precompact',
102
- 'archival',
103
- 'askuserquestion',
104
- 'tmuxautospawn',
105
- 'noaiattribution',
106
- ],
107
- disable: ['statusline', 'ralphloop', 'selfimprove'],
108
- archivalDays: 30,
109
- contextVerbosity: 'lite',
110
- },
111
- minimal: {
112
- description: 'SessionStart + archival only',
113
- enable: ['sessionstart', 'archival'],
114
- disable: [
115
- 'precompact',
116
- 'statusline',
117
- 'ralphloop',
118
- 'selfimprove',
119
- 'askuserquestion',
120
- 'tmuxautospawn',
121
- ],
122
- archivalDays: 30,
123
- contextVerbosity: 'lite',
124
- },
125
- none: {
126
- description: 'Disable all AgileFlow features',
127
- disable: [
128
- 'sessionstart',
129
- 'precompact',
130
- 'archival',
131
- 'statusline',
132
- 'ralphloop',
133
- 'selfimprove',
134
- 'askuserquestion',
135
- 'tmuxautospawn',
136
- 'noaiattribution',
137
- ],
138
- },
139
- experimental: {
140
- description:
141
- '⚠️ CONTEXT HEAVY: Full command file injection during compact (uses more tokens but may be more reliable)',
142
- enable: [
143
- 'sessionstart',
144
- 'precompact',
145
- 'archival',
146
- 'statusline',
147
- 'ralphloop',
148
- 'selfimprove',
149
- 'askuserquestion',
150
- 'tmuxautospawn',
151
- 'noaiattribution',
152
- ],
153
- archivalDays: 30,
154
- experimental: {
155
- fullFileInjection: true,
156
- description:
157
- 'Instead of compact summaries, injects entire command files during context compaction',
158
- },
159
- },
160
- };
161
-
162
- const STATUSLINE_COMPONENTS = [
163
- 'agileflow',
164
- 'model',
165
- 'story',
166
- 'epic',
167
- 'wip',
168
- 'context',
169
- 'cost',
170
- 'git',
171
- ];
172
-
173
- // Scripts directory
174
- const SCRIPTS_DIR = path.join(process.cwd(), '.agileflow', 'scripts');
175
-
176
- // ============================================================================
177
- // HELPER FUNCTIONS
178
- // ============================================================================
179
-
180
- const scriptExists = scriptName => fs.existsSync(path.join(SCRIPTS_DIR, scriptName));
181
- const getScriptPath = scriptName => `.agileflow/scripts/${scriptName}`;
182
-
183
- /**
184
- * Hash a file's content using SHA-256 (first 16 hex chars)
185
- * @param {string} filePath - Path to the file
186
- * @returns {string|null} 16-char hex hash, or null if file can't be read
187
- */
188
- function hashFile(filePath) {
189
- try {
190
- const content = fs.readFileSync(filePath, 'utf8');
191
- return crypto.createHash('sha256').update(content).digest('hex').slice(0, 16);
192
- } catch {
193
- return null;
194
- }
195
- }
196
-
197
- // ============================================================================
198
- // METADATA MANAGEMENT
199
- // ============================================================================
200
-
201
- /**
202
- * Update metadata file with provided updates
203
- * @param {object} updates - Updates to apply (archival, features, updates)
204
- * @param {string} version - Current version string
205
- */
206
- function updateMetadata(updates, version) {
207
- const metaPath = 'docs/00-meta/agileflow-metadata.json';
208
-
209
- if (!fs.existsSync(metaPath)) {
210
- ensureDir('docs/00-meta');
211
- writeJSON(metaPath, { version, created: new Date().toISOString() });
212
- }
213
-
214
- const meta = readJSON(metaPath) || {};
215
-
216
- // Deep merge
217
- if (updates.archival) {
218
- meta.archival = { ...meta.archival, ...updates.archival };
219
- }
220
- if (updates.features) {
221
- meta.features = meta.features || {};
222
- Object.entries(updates.features).forEach(([key, value]) => {
223
- meta.features[key] = { ...meta.features[key], ...value };
224
- });
225
- }
226
- if (updates.updates) {
227
- meta.updates = { ...meta.updates, ...updates.updates };
228
- }
229
-
230
- meta.version = version;
231
- meta.updated = new Date().toISOString();
232
-
233
- writeJSON(metaPath, meta);
234
- }
235
-
236
- // ============================================================================
237
- // ENABLE FEATURE
238
- // ============================================================================
239
-
240
- /**
241
- * Enable a feature
242
- * @param {string} feature - Feature name
243
- * @param {object} options - Options (archivalDays, mode, protectionLevel, isUpgrade)
244
- * @param {string} version - Current version string
245
- * @returns {boolean} Success
246
- */
247
- function enableFeature(feature, options = {}, version) {
248
- const config = FEATURES[feature];
249
- if (!config) {
250
- error(`Unknown feature: ${feature}`);
251
- return false;
252
- }
253
-
254
- ensureDir('.claude');
255
-
256
- const settings = readJSON('.claude/settings.json') || {};
257
- settings.hooks = settings.hooks || {};
258
- settings.permissions = settings.permissions || { allow: [], deny: [], ask: [] };
259
-
260
- // Handle hook-based features
261
- if (config.hook) {
262
- if (!enableHookFeature(feature, config, settings, version)) {
263
- return false;
264
- }
265
- }
266
-
267
- // Handle archival
268
- if (feature === 'archival') {
269
- if (!enableArchival(settings, options, version)) {
270
- return false;
271
- }
272
- }
273
-
274
- // Handle statusLine
275
- if (feature === 'statusline') {
276
- if (!enableStatusLine(settings, version)) {
277
- return false;
278
- }
279
- }
280
-
281
- // Handle autoupdate (metadata only)
282
- if (feature === 'autoupdate') {
283
- updateMetadata({ updates: { autoUpdate: true, showChangelog: true } }, version);
284
- success('Auto-update enabled');
285
- info('AgileFlow will check for updates every session and update automatically');
286
- return true;
287
- }
288
-
289
- // Handle askuserquestion (metadata only)
290
- if (feature === 'askuserquestion') {
291
- const mode = options.mode || 'all';
292
- updateMetadata(
293
- {
294
- features: {
295
- askUserQuestion: {
296
- enabled: true,
297
- mode,
298
- version,
299
- at: new Date().toISOString(),
300
- },
301
- },
302
- },
303
- version
304
- );
305
- success(`AskUserQuestion enabled (mode: ${mode})`);
306
- info('All commands will end with AskUserQuestion tool for guided interaction');
307
- return true;
308
- }
309
-
310
- // Handle tmuxautospawn (metadata only)
311
- if (feature === 'tmuxautospawn') {
312
- updateMetadata(
313
- {
314
- features: {
315
- tmuxAutoSpawn: {
316
- enabled: true,
317
- version,
318
- at: new Date().toISOString(),
319
- },
320
- },
321
- },
322
- version
323
- );
324
- success('Tmux auto-spawn enabled');
325
- info('Running "af" or "agileflow" will auto-start Claude in tmux session');
326
- return true;
327
- }
328
-
329
- // Handle processcleanup (metadata only)
330
- if (feature === 'processcleanup') {
331
- updateMetadata(
332
- {
333
- features: {
334
- processCleanup: {
335
- enabled: true,
336
- autoKill: false,
337
- version,
338
- at: new Date().toISOString(),
339
- },
340
- },
341
- },
342
- version
343
- );
344
- success('Process cleanup enabled');
345
- info('Duplicate Claude processes will be detected and reported on session start');
346
- info('Auto-kill is disabled by default for safety');
347
- info(' Only affects processes in the SAME working directory (worktrees are safe)');
348
- info(' Set AGILEFLOW_PROCESS_CLEANUP_AUTOKILL=1 to opt in to auto-kill at runtime');
349
- return true;
350
- }
351
-
352
- // Handle claude flags (e.g., --dangerously-skip-permissions)
353
- // Also sets permissions.defaultMode in .claude/settings.json
354
- if (feature === 'claudeflags') {
355
- const defaultFlags = options.flags || '--dangerously-skip-permissions';
356
-
357
- // Map CLI flags to settings.json defaultMode values
358
- const flagToMode = {
359
- '--dangerously-skip-permissions': 'bypassPermissions',
360
- '--permission-mode acceptEdits': 'acceptEdits',
361
- };
362
- const defaultMode = flagToMode[defaultFlags];
363
-
364
- if (defaultMode) {
365
- settings.permissions = settings.permissions || {};
366
- settings.permissions.defaultMode = defaultMode;
367
- writeJSON('.claude/settings.json', settings);
368
- info(`Set permissions.defaultMode = "${defaultMode}" in .claude/settings.json`);
369
- }
370
-
371
- updateMetadata(
372
- {
373
- features: {
374
- claudeFlags: {
375
- enabled: true,
376
- defaultFlags,
377
- version,
378
- at: new Date().toISOString(),
379
- },
380
- },
381
- },
382
- version
383
- );
384
- success(`Default Claude flags configured: ${defaultFlags}`);
385
- info('These flags will be passed to Claude when launched via "af" or "agileflow"');
386
- if (defaultMode) {
387
- info('Restart Claude Code for the new default mode to take effect');
388
- }
389
- return true;
390
- }
391
-
392
- // Handle agent teams - set env var in .claude/settings.json
393
- if (feature === 'agentteams') {
394
- settings.env = settings.env || {};
395
- settings.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';
396
-
397
- // Register PostToolUse hooks for native team observability
398
- if (!settings.hooks) settings.hooks = {};
399
- if (!settings.hooks.PostToolUse) settings.hooks.PostToolUse = [];
400
- const observerCmd = 'node $CLAUDE_PROJECT_DIR/.agileflow/scripts/native-team-observer.js';
401
- for (const matcher of ['TeamCreate', 'SendMessage', 'ListTeams']) {
402
- const exists = settings.hooks.PostToolUse.some(
403
- h =>
404
- h.matcher === matcher &&
405
- h.hooks?.some(hk => hk.command && hk.command.includes('native-team-observer'))
406
- );
407
- if (!exists) {
408
- settings.hooks.PostToolUse.push({
409
- matcher,
410
- hooks: [{ type: 'command', command: observerCmd, timeout: 5000 }],
411
- });
412
- }
413
- }
414
-
415
- writeJSON('.claude/settings.json', settings);
416
- updateMetadata(
417
- {
418
- features: {
419
- agentTeams: {
420
- enabled: true,
421
- version,
422
- at: new Date().toISOString(),
423
- },
424
- },
425
- },
426
- version
427
- );
428
- success('Native Agent Teams enabled');
429
- info('Set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 in .claude/settings.json');
430
- info('Registered PostToolUse hooks for native team observability');
431
- info('Claude Code will use native TeamCreate/SendMessage tools');
432
- info('Fallback: subagent mode (Task/TaskOutput) when native is unavailable');
433
- return true;
434
- }
435
-
436
- // Handle shell aliases
437
- if (feature === 'shellaliases') {
438
- const result = enableShellAliases();
439
- if (
440
- result.configured.length > 0 ||
441
- result.skipped.some(s => s.includes('already configured'))
442
- ) {
443
- updateMetadata(
444
- {
445
- features: {
446
- shellAliases: {
447
- enabled: true,
448
- version,
449
- at: new Date().toISOString(),
450
- shells: result.configured,
451
- },
452
- },
453
- },
454
- version
455
- );
456
- if (result.configured.length > 0) {
457
- success(`Shell aliases added to: ${result.configured.join(', ')}`);
458
- info('Reload shell: source ~/.bashrc or source ~/.zshrc');
459
- info('Then use "af" or "agileflow" to start Claude in tmux');
460
- } else {
461
- info('Shell aliases already configured');
462
- }
463
- return true;
464
- }
465
- if (result.skipped.length > 0) {
466
- warn(`Shell aliases skipped: ${result.skipped.join(', ')}`);
467
- }
468
- return false;
469
- }
470
-
471
- // Handle CLAUDE.md reinforcement
472
- if (feature === 'claudemdreinforcement') {
473
- const result = enableClaudeMdReinforcement();
474
- if (result.success) {
475
- updateMetadata(
476
- {
477
- features: {
478
- claudeMdReinforcement: {
479
- enabled: true,
480
- version,
481
- at: new Date().toISOString(),
482
- },
483
- },
484
- },
485
- version
486
- );
487
- if (result.added) {
488
- success('Added /babysit rules to CLAUDE.md');
489
- } else {
490
- info('CLAUDE.md already has /babysit rules');
491
- }
492
- return true;
493
- }
494
- error(`Failed to update CLAUDE.md: ${result.error}`);
495
- return false;
496
- }
497
-
498
- // Handle damage control
499
- if (feature === 'damagecontrol') {
500
- return enableDamageControl(settings, options, version);
501
- }
502
-
503
- // Handle no AI attribution
504
- if (feature === 'noaiattribution') {
505
- return enableNoAiAttribution(settings, version);
506
- }
507
-
508
- // Handle browser QA (agentic browser testing)
509
- if (feature === 'browserqa') {
510
- return enableBrowserQa(version);
511
- }
512
-
513
- // Handle context verbosity (metadata only)
514
- if (feature === 'contextverbosity') {
515
- const mode = options.mode || 'lite';
516
- const validModes = ['full', 'lite', 'minimal'];
517
- if (!validModes.includes(mode)) {
518
- error(`Invalid verbosity mode: ${mode}. Valid: ${validModes.join(', ')}`);
519
- return false;
520
- }
521
- updateMetadata(
522
- {
523
- features: {
524
- contextVerbosity: {
525
- enabled: true,
526
- mode,
527
- version,
528
- at: new Date().toISOString(),
529
- },
530
- },
531
- },
532
- version
533
- );
534
- success(`Context verbosity set to: ${mode}`);
535
- if (mode === 'lite') {
536
- info('Lite: summary table + git status + active stories + smart recommendations');
537
- info('Skips: full file dumps, feature catalog, research content, ideation');
538
- } else if (mode === 'minimal') {
539
- info('Minimal: summary table only with story counts');
540
- info('Skips: everything except compact summary');
541
- }
542
- return true;
543
- }
544
-
545
- const featureConfig = FEATURES[feature];
546
- const contentHash = featureConfig?.script
547
- ? hashFile(path.join(SCRIPTS_DIR, featureConfig.script))
548
- : null;
549
- writeJSON('.claude/settings.json', settings);
550
- updateMetadata(
551
- {
552
- features: {
553
- [feature]: {
554
- enabled: true,
555
- version,
556
- ...(contentHash ? { contentHash } : {}),
557
- at: new Date().toISOString(),
558
- },
559
- },
560
- },
561
- version
562
- );
563
- updateGitignore();
564
-
565
- return true;
566
- }
567
-
568
- /**
569
- * Enable a hook-based feature
570
- */
571
- function enableHookFeature(feature, config, settings, version) {
572
- const scriptPath = getScriptPath(config.script);
573
-
574
- if (!scriptExists(config.script)) {
575
- error(`Script not found: ${scriptPath}`);
576
- info('Run "npx agileflow update" to reinstall scripts');
577
- return false;
578
- }
579
-
580
- const absoluteScriptPath = path.join(process.cwd(), scriptPath);
581
- const isStopHook = config.hook === 'Stop';
582
- const command =
583
- config.type === 'node'
584
- ? `node ${absoluteScriptPath}${isStopHook ? ' 2>/dev/null || true' : ''}`
585
- : `bash ${absoluteScriptPath}${isStopHook ? ' 2>/dev/null || true' : ''}`;
586
-
587
- if (isStopHook) {
588
- // Stop hooks stack - add to existing
589
- if (!settings.hooks.Stop) {
590
- settings.hooks.Stop = [{ matcher: '', hooks: [] }];
591
- } else if (!Array.isArray(settings.hooks.Stop) || settings.hooks.Stop.length === 0) {
592
- settings.hooks.Stop = [{ matcher: '', hooks: [] }];
593
- } else if (!settings.hooks.Stop[0].hooks) {
594
- settings.hooks.Stop[0].hooks = [];
595
- }
596
-
597
- const hasHook = settings.hooks.Stop[0].hooks.some(h => h.command?.includes(config.script));
598
- if (!hasHook) {
599
- settings.hooks.Stop[0].hooks.push({ type: 'command', command });
600
- success(`Stop hook added (${config.script})`);
601
- } else {
602
- info(`${feature} already enabled`);
603
- }
604
- } else {
605
- // Other hooks replace entirely
606
- settings.hooks[config.hook] = [{ matcher: '', hooks: [{ type: 'command', command }] }];
607
- success(`${config.hook} hook enabled (${config.script})`);
608
- }
609
-
610
- return true;
611
- }
612
-
613
- /**
614
- * Enable archival feature
615
- */
616
- function enableArchival(settings, options, version) {
617
- const days = options.archivalDays || 30;
618
- const scriptPath = getScriptPath('archive-completed-stories.sh');
619
-
620
- if (!scriptExists('archive-completed-stories.sh')) {
621
- error(`Script not found: ${scriptPath}`);
622
- info('Run "npx agileflow update" to reinstall scripts');
623
- return false;
624
- }
625
-
626
- const absoluteScriptPath = path.join(process.cwd(), scriptPath);
627
- if (settings.hooks.SessionStart?.[0]?.hooks) {
628
- const hasArchival = settings.hooks.SessionStart[0].hooks.some(h =>
629
- h.command?.includes('archive-completed-stories')
630
- );
631
- if (!hasArchival) {
632
- settings.hooks.SessionStart[0].hooks.push({
633
- type: 'command',
634
- command: `bash ${absoluteScriptPath} --quiet`,
635
- });
636
- }
637
- }
638
-
639
- updateMetadata({ archival: { enabled: true, threshold_days: days } }, version);
640
- success(`Archival enabled (${days} days)`);
641
- return true;
642
- }
643
-
644
- /**
645
- * Enable status line feature
646
- */
647
- function enableStatusLine(settings, version) {
648
- const scriptPath = getScriptPath('agileflow-statusline.sh');
649
-
650
- if (!scriptExists('agileflow-statusline.sh')) {
651
- error(`Script not found: ${scriptPath}`);
652
- info('Run "npx agileflow update" to reinstall scripts');
653
- return false;
654
- }
655
-
656
- const absoluteScriptPath = path.join(process.cwd(), scriptPath);
657
- settings.statusLine = {
658
- type: 'command',
659
- command: `bash ${absoluteScriptPath}`,
660
- padding: 0,
661
- };
662
- success('Status line enabled');
663
- return true;
664
- }
665
-
666
- /**
667
- * Enable damage control feature
668
- */
669
- function enableDamageControl(settings, options, version) {
670
- const level = options.protectionLevel || 'standard';
671
-
672
- // Verify all required scripts exist
673
- const requiredScripts = [
674
- 'damage-control-bash.js',
675
- 'damage-control-edit.js',
676
- 'damage-control-write.js',
677
- ];
678
- for (const script of requiredScripts) {
679
- if (!scriptExists(script)) {
680
- error(`Script not found: ${getScriptPath(script)}`);
681
- info('Run "npx agileflow update" to reinstall scripts');
682
- return false;
683
- }
684
- }
685
-
686
- // Deploy patterns file if not exists
687
- const patternsDir = path.join(process.cwd(), '.agileflow', 'config');
688
- const patternsDest = path.join(patternsDir, 'damage-control-patterns.yaml');
689
- if (!fs.existsSync(patternsDest)) {
690
- ensureDir(patternsDir);
691
- const templatePath = path.join(
692
- process.cwd(),
693
- '.agileflow',
694
- 'templates',
695
- 'damage-control-patterns.yaml'
696
- );
697
- if (fs.existsSync(templatePath)) {
698
- fs.copyFileSync(templatePath, patternsDest);
699
- success('Deployed damage control patterns');
700
- } else {
701
- warn('No patterns template found - hooks will use defaults');
702
- }
703
- }
704
-
705
- // Initialize PreToolUse array
706
- if (!settings.hooks.PreToolUse) {
707
- settings.hooks.PreToolUse = [];
708
- }
709
-
710
- const addPreToolUseHook = (matcher, scriptName) => {
711
- const scriptFullPath = path.join(process.cwd(), '.agileflow', 'scripts', scriptName);
712
- settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(h => h.matcher !== matcher);
713
- settings.hooks.PreToolUse.push({
714
- matcher,
715
- hooks: [{ type: 'command', command: `node ${scriptFullPath}`, timeout: 5 }],
716
- });
717
- };
718
-
719
- addPreToolUseHook('Bash', 'damage-control-bash.js');
720
- addPreToolUseHook('Edit', 'damage-control-edit.js');
721
- addPreToolUseHook('Write', 'damage-control-write.js');
722
-
723
- success('Damage control PreToolUse hooks enabled');
724
-
725
- const primaryHash = hashFile(path.join(SCRIPTS_DIR, 'damage-control-bash.js'));
726
- updateMetadata(
727
- {
728
- features: {
729
- damagecontrol: {
730
- enabled: true,
731
- protectionLevel: level,
732
- version,
733
- ...(primaryHash ? { contentHash: primaryHash } : {}),
734
- at: new Date().toISOString(),
735
- },
736
- },
737
- },
738
- version
739
- );
740
-
741
- writeJSON('.claude/settings.json', settings);
742
- updateGitignore();
743
-
744
- return true;
745
- }
746
-
747
- /**
748
- * Enable no AI attribution feature
749
- */
750
- function enableNoAiAttribution(settings, version) {
751
- const scriptName = 'strip-ai-attribution.js';
752
-
753
- if (!scriptExists(scriptName)) {
754
- error(`Script not found: ${getScriptPath(scriptName)}`);
755
- info('Run "npx agileflow update" to reinstall scripts');
756
- return false;
757
- }
758
-
759
- // Initialize PreToolUse array
760
- if (!settings.hooks.PreToolUse) {
761
- settings.hooks.PreToolUse = [];
762
- }
763
-
764
- const scriptFullPath = path.join(process.cwd(), '.agileflow', 'scripts', scriptName);
765
-
766
- // Remove existing hook if any
767
- for (const entry of settings.hooks.PreToolUse) {
768
- if (entry.matcher === 'Bash' && Array.isArray(entry.hooks)) {
769
- entry.hooks = entry.hooks.filter(h => !h.command?.includes('strip-ai-attribution'));
770
- }
771
- }
772
- // Clean up empty entries
773
- settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
774
- h => Array.isArray(h.hooks) && h.hooks.length > 0
775
- );
776
-
777
- // Add to existing Bash matcher or create new one
778
- const bashEntry = settings.hooks.PreToolUse.find(h => h.matcher === 'Bash');
779
- if (bashEntry) {
780
- bashEntry.hooks.push({ type: 'command', command: `node ${scriptFullPath}`, timeout: 5 });
781
- } else {
782
- settings.hooks.PreToolUse.push({
783
- matcher: 'Bash',
784
- hooks: [{ type: 'command', command: `node ${scriptFullPath}`, timeout: 5 }],
785
- });
786
- }
787
-
788
- const contentHash = hashFile(path.join(SCRIPTS_DIR, scriptName));
789
- updateMetadata(
790
- {
791
- features: {
792
- noaiattribution: {
793
- enabled: true,
794
- version,
795
- ...(contentHash ? { contentHash } : {}),
796
- at: new Date().toISOString(),
797
- },
798
- },
799
- },
800
- version
801
- );
802
-
803
- writeJSON('.claude/settings.json', settings);
804
- updateGitignore();
805
-
806
- success('AI attribution blocking enabled');
807
- info('Git commits with AI footers (Co-Authored-By, etc.) will be blocked');
808
- return true;
809
- }
810
-
811
- // ============================================================================
812
- // DISABLE FEATURE
813
- // ============================================================================
814
-
815
- /**
816
- * Disable a feature
817
- * @param {string} feature - Feature name
818
- * @param {string} version - Current version string
819
- * @returns {boolean} Success
820
- */
821
- function disableFeature(feature, version) {
822
- const config = FEATURES[feature];
823
- if (!config) {
824
- error(`Unknown feature: ${feature}`);
825
- return false;
826
- }
827
-
828
- if (!fs.existsSync('.claude/settings.json')) {
829
- info(`${feature} already disabled (no settings file)`);
830
- return true;
831
- }
832
-
833
- const settings = readJSON('.claude/settings.json');
834
- if (!settings) return false;
835
-
836
- // Disable hook
837
- if (config.hook && settings.hooks?.[config.hook]) {
838
- if (config.hook === 'Stop') {
839
- // Stop hooks stack - remove only this script
840
- if (settings.hooks.Stop?.[0]?.hooks) {
841
- const before = settings.hooks.Stop[0].hooks.length;
842
- settings.hooks.Stop[0].hooks = settings.hooks.Stop[0].hooks.filter(
843
- h => !h.command?.includes(config.script)
844
- );
845
- const after = settings.hooks.Stop[0].hooks.length;
846
-
847
- if (before > after) {
848
- success(`Stop hook removed (${config.script})`);
849
- }
850
-
851
- if (settings.hooks.Stop[0].hooks.length === 0) {
852
- delete settings.hooks.Stop;
853
- }
854
- }
855
- } else {
856
- delete settings.hooks[config.hook];
857
- success(`${config.hook} hook disabled`);
858
- }
859
- }
860
-
861
- // Disable archival
862
- if (feature === 'archival') {
863
- if (settings.hooks?.SessionStart?.[0]?.hooks) {
864
- settings.hooks.SessionStart[0].hooks = settings.hooks.SessionStart[0].hooks.filter(
865
- h => !h.command?.includes('archive-completed-stories')
866
- );
867
- }
868
- updateMetadata({ archival: { enabled: false } }, version);
869
- success('Archival disabled');
870
- }
871
-
872
- // Disable statusLine
873
- if (feature === 'statusline' && settings.statusLine) {
874
- delete settings.statusLine;
875
- success('Status line disabled');
876
- }
877
-
878
- // Disable autoupdate
879
- if (feature === 'autoupdate') {
880
- updateMetadata({ updates: { autoUpdate: false } }, version);
881
- success('Auto-update disabled');
882
- return true;
883
- }
884
-
885
- // Disable askuserquestion
886
- if (feature === 'askuserquestion') {
887
- updateMetadata(
888
- {
889
- features: {
890
- askUserQuestion: {
891
- enabled: false,
892
- version,
893
- at: new Date().toISOString(),
894
- },
895
- },
896
- },
897
- version
898
- );
899
- success('AskUserQuestion disabled');
900
- info('Commands will end with natural text questions instead of AskUserQuestion tool');
901
- return true;
902
- }
903
-
904
- // Disable tmuxautospawn
905
- if (feature === 'tmuxautospawn') {
906
- updateMetadata(
907
- {
908
- features: {
909
- tmuxAutoSpawn: {
910
- enabled: false,
911
- version,
912
- at: new Date().toISOString(),
913
- },
914
- },
915
- },
916
- version
917
- );
918
- success('Tmux auto-spawn disabled');
919
- info('Running "af" or "agileflow" will start Claude directly without tmux');
920
- return true;
921
- }
922
-
923
- // Disable processcleanup
924
- if (feature === 'processcleanup') {
925
- updateMetadata(
926
- {
927
- features: {
928
- processCleanup: {
929
- enabled: false,
930
- autoKill: false,
931
- version,
932
- at: new Date().toISOString(),
933
- },
934
- },
935
- },
936
- version
937
- );
938
- success('Process cleanup disabled');
939
- info('Duplicate Claude processes will only trigger a warning (no auto-kill)');
940
- return true;
941
- }
942
-
943
- // Disable claude flags - also reset permissions.defaultMode in settings.json
944
- if (feature === 'claudeflags') {
945
- if (settings.permissions?.defaultMode) {
946
- delete settings.permissions.defaultMode;
947
- writeJSON('.claude/settings.json', settings);
948
- info('Removed permissions.defaultMode from .claude/settings.json');
949
- }
950
- updateMetadata(
951
- {
952
- features: {
953
- claudeFlags: {
954
- enabled: false,
955
- defaultFlags: '',
956
- version,
957
- at: new Date().toISOString(),
958
- },
959
- },
960
- },
961
- version
962
- );
963
- success('Default Claude flags disabled');
964
- info('Claude will launch with default permissions (prompts for each action)');
965
- info('Restart Claude Code for the change to take effect');
966
- return true;
967
- }
968
-
969
- // Disable agent teams - remove env var from .claude/settings.json
970
- if (feature === 'agentteams') {
971
- if (settings.env) {
972
- delete settings.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
973
- if (Object.keys(settings.env).length === 0) {
974
- delete settings.env;
975
- }
976
- }
977
-
978
- // Remove PostToolUse hooks for native team observer
979
- if (settings.hooks?.PostToolUse) {
980
- settings.hooks.PostToolUse = settings.hooks.PostToolUse.filter(
981
- h => !h.hooks?.some(hk => hk.command && hk.command.includes('native-team-observer'))
982
- );
983
- if (settings.hooks.PostToolUse.length === 0) {
984
- delete settings.hooks.PostToolUse;
985
- }
986
- if (Object.keys(settings.hooks).length === 0) {
987
- delete settings.hooks;
988
- }
989
- }
990
-
991
- writeJSON('.claude/settings.json', settings);
992
- updateMetadata(
993
- {
994
- features: {
995
- agentTeams: {
996
- enabled: false,
997
- version,
998
- at: new Date().toISOString(),
999
- },
1000
- },
1001
- },
1002
- version
1003
- );
1004
- success('Native Agent Teams disabled');
1005
- info('Removed CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS from .claude/settings.json');
1006
- info('Removed PostToolUse hooks for native team observer');
1007
- info('AgileFlow will use subagent mode (Task/TaskOutput) for multi-agent orchestration');
1008
- return true;
1009
- }
1010
-
1011
- // Disable shell aliases
1012
- if (feature === 'shellaliases') {
1013
- const result = disableShellAliases();
1014
- updateMetadata(
1015
- {
1016
- features: {
1017
- shellAliases: {
1018
- enabled: false,
1019
- version,
1020
- at: new Date().toISOString(),
1021
- },
1022
- },
1023
- },
1024
- version
1025
- );
1026
- if (result.removed.length > 0) {
1027
- success(`Shell aliases removed from: ${result.removed.join(', ')}`);
1028
- info('Reload shell: source ~/.bashrc or source ~/.zshrc');
1029
- } else {
1030
- info('No shell aliases found to remove');
1031
- }
1032
- return true;
1033
- }
1034
-
1035
- // Disable CLAUDE.md reinforcement
1036
- if (feature === 'claudemdreinforcement') {
1037
- const result = disableClaudeMdReinforcement();
1038
- updateMetadata(
1039
- {
1040
- features: {
1041
- claudeMdReinforcement: {
1042
- enabled: false,
1043
- version,
1044
- at: new Date().toISOString(),
1045
- },
1046
- },
1047
- },
1048
- version
1049
- );
1050
- if (result.removed) {
1051
- success('Removed /babysit rules from CLAUDE.md');
1052
- } else {
1053
- info('CLAUDE.md did not have /babysit rules');
1054
- }
1055
- return true;
1056
- }
1057
-
1058
- // Disable damage control
1059
- if (feature === 'damagecontrol') {
1060
- if (settings.hooks?.PreToolUse && Array.isArray(settings.hooks.PreToolUse)) {
1061
- const before = settings.hooks.PreToolUse.length;
1062
- settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(h => {
1063
- const isDamageControlHook = h.hooks?.some(hk => hk.command?.includes('damage-control'));
1064
- return !isDamageControlHook;
1065
- });
1066
- const after = settings.hooks.PreToolUse.length;
1067
-
1068
- if (before > after) {
1069
- success(`Removed ${before - after} damage control PreToolUse hook(s)`);
1070
- }
1071
-
1072
- if (settings.hooks.PreToolUse.length === 0) {
1073
- delete settings.hooks.PreToolUse;
1074
- }
1075
- }
1076
-
1077
- updateMetadata(
1078
- {
1079
- features: {
1080
- damagecontrol: {
1081
- enabled: false,
1082
- version,
1083
- at: new Date().toISOString(),
1084
- },
1085
- },
1086
- },
1087
- version
1088
- );
1089
-
1090
- writeJSON('.claude/settings.json', settings);
1091
- success('Damage control disabled');
1092
- return true;
1093
- }
1094
-
1095
- // Disable browser QA
1096
- if (feature === 'browserqa') {
1097
- updateMetadata(
1098
- {
1099
- features: {
1100
- browserqa: {
1101
- enabled: false,
1102
- version,
1103
- at: new Date().toISOString(),
1104
- },
1105
- },
1106
- },
1107
- version
1108
- );
1109
- success('Browser QA disabled');
1110
- info('Agentic browser testing deactivated');
1111
- return true;
1112
- }
1113
-
1114
- // Disable context verbosity (reset to full)
1115
- if (feature === 'contextverbosity') {
1116
- updateMetadata(
1117
- {
1118
- features: {
1119
- contextVerbosity: {
1120
- enabled: false,
1121
- mode: 'full',
1122
- version,
1123
- at: new Date().toISOString(),
1124
- },
1125
- },
1126
- },
1127
- version
1128
- );
1129
- success('Context verbosity reset to full');
1130
- return true;
1131
- }
1132
-
1133
- // Disable no AI attribution
1134
- if (feature === 'noaiattribution') {
1135
- if (settings.hooks?.PreToolUse && Array.isArray(settings.hooks.PreToolUse)) {
1136
- for (const entry of settings.hooks.PreToolUse) {
1137
- if (entry.matcher === 'Bash' && Array.isArray(entry.hooks)) {
1138
- entry.hooks = entry.hooks.filter(h => !h.command?.includes('strip-ai-attribution'));
1139
- }
1140
- }
1141
- // Clean up empty entries
1142
- settings.hooks.PreToolUse = settings.hooks.PreToolUse.filter(
1143
- h => Array.isArray(h.hooks) && h.hooks.length > 0
1144
- );
1145
- if (settings.hooks.PreToolUse.length === 0) {
1146
- delete settings.hooks.PreToolUse;
1147
- }
1148
- }
1149
-
1150
- updateMetadata(
1151
- {
1152
- features: {
1153
- noaiattribution: {
1154
- enabled: false,
1155
- version,
1156
- at: new Date().toISOString(),
1157
- },
1158
- },
1159
- },
1160
- version
1161
- );
1162
-
1163
- writeJSON('.claude/settings.json', settings);
1164
- success('AI attribution blocking disabled');
1165
- return true;
1166
- }
1167
-
1168
- writeJSON('.claude/settings.json', settings);
1169
- updateMetadata(
1170
- { features: { [feature]: { enabled: false, version, at: new Date().toISOString() } } },
1171
- version
1172
- );
1173
-
1174
- return true;
1175
- }
1176
-
1177
- // ============================================================================
1178
- // PROFILES
1179
- // ============================================================================
1180
-
1181
- /**
1182
- * Apply a preset profile
1183
- * @param {string} profileName - Profile name
1184
- * @param {object} options - Options
1185
- * @param {string} version - Current version string
1186
- * @returns {boolean} Success
1187
- */
1188
- function applyProfile(profileName, options = {}, version) {
1189
- const profile = PROFILES[profileName];
1190
- if (!profile) {
1191
- error(`Unknown profile: ${profileName}`);
1192
- log('Available: ' + Object.keys(PROFILES).join(', '));
1193
- return false;
1194
- }
1195
-
1196
- header(`Applying "${profileName}" profile`);
1197
- log(profile.description, c.dim);
1198
-
1199
- if (profile.enable) {
1200
- profile.enable.forEach(f =>
1201
- enableFeature(f, { archivalDays: profile.archivalDays || options.archivalDays }, version)
1202
- );
1203
- }
1204
-
1205
- if (profile.disable) {
1206
- profile.disable.forEach(f => disableFeature(f, version));
1207
- }
1208
-
1209
- // Apply context verbosity if specified in profile
1210
- if (profile.contextVerbosity) {
1211
- enableFeature('contextverbosity', { mode: profile.contextVerbosity }, version);
1212
- }
1213
-
1214
- // Handle experimental profile settings
1215
- if (profile.experimental) {
1216
- updateMetadata(
1217
- {
1218
- features: {
1219
- experimental: {
1220
- enabled: true,
1221
- fullFileInjection: profile.experimental.fullFileInjection || false,
1222
- version,
1223
- at: new Date().toISOString(),
1224
- },
1225
- },
1226
- },
1227
- version
1228
- );
1229
- if (profile.experimental.fullFileInjection) {
1230
- warn('⚠️ EXPERIMENTAL: Full file injection enabled');
1231
- info(' PreCompact will inject entire command files instead of compact summaries');
1232
- info(' This uses more context tokens but may provide better instruction adherence');
1233
- }
1234
- } else {
1235
- // Disable experimental mode if switching to non-experimental profile
1236
- updateMetadata(
1237
- {
1238
- features: {
1239
- experimental: {
1240
- enabled: false,
1241
- fullFileInjection: false,
1242
- version,
1243
- at: new Date().toISOString(),
1244
- },
1245
- },
1246
- },
1247
- version
1248
- );
1249
- }
1250
-
1251
- return true;
1252
- }
1253
-
1254
- // ============================================================================
1255
- // STATUSLINE COMPONENTS
1256
- // ============================================================================
1257
-
1258
- /**
1259
- * Set statusline component visibility
1260
- * @param {string[]} enableComponents - Components to enable
1261
- * @param {string[]} disableComponents - Components to disable
1262
- * @returns {boolean} Success
1263
- */
1264
- function setStatuslineComponents(enableComponents = [], disableComponents = []) {
1265
- const metaPath = 'docs/00-meta/agileflow-metadata.json';
1266
-
1267
- if (!fs.existsSync(metaPath)) {
1268
- warn('No metadata file found - run with --enable=statusline first');
1269
- return false;
1270
- }
1271
-
1272
- const meta = readJSON(metaPath);
1273
- if (!meta) {
1274
- error('Cannot parse metadata file');
1275
- return false;
1276
- }
1277
-
1278
- meta.features = meta.features || {};
1279
- meta.features.statusline = meta.features.statusline || {};
1280
- meta.features.statusline.components = meta.features.statusline.components || {};
1281
-
1282
- // Set defaults
1283
- STATUSLINE_COMPONENTS.forEach(comp => {
1284
- if (meta.features.statusline.components[comp] === undefined) {
1285
- meta.features.statusline.components[comp] = true;
1286
- }
1287
- });
1288
-
1289
- // Enable specified
1290
- enableComponents.forEach(comp => {
1291
- if (STATUSLINE_COMPONENTS.includes(comp)) {
1292
- meta.features.statusline.components[comp] = true;
1293
- success(`Statusline component enabled: ${comp}`);
1294
- } else {
1295
- warn(`Unknown component: ${comp} (available: ${STATUSLINE_COMPONENTS.join(', ')})`);
1296
- }
1297
- });
1298
-
1299
- // Disable specified
1300
- disableComponents.forEach(comp => {
1301
- if (STATUSLINE_COMPONENTS.includes(comp)) {
1302
- meta.features.statusline.components[comp] = false;
1303
- success(`Statusline component disabled: ${comp}`);
1304
- } else {
1305
- warn(`Unknown component: ${comp} (available: ${STATUSLINE_COMPONENTS.join(', ')})`);
1306
- }
1307
- });
1308
-
1309
- meta.updated = new Date().toISOString();
1310
- writeJSON(metaPath, meta);
1311
-
1312
- return true;
1313
- }
1314
-
1315
- /**
1316
- * List statusline components
1317
- */
1318
- function listStatuslineComponents() {
1319
- const metaPath = 'docs/00-meta/agileflow-metadata.json';
1320
-
1321
- header('Statusline Components');
1322
-
1323
- if (!fs.existsSync(metaPath)) {
1324
- log(' No configuration found (defaults: all enabled)', c.dim);
1325
- STATUSLINE_COMPONENTS.forEach(comp => {
1326
- log(` ${comp}: enabled (default)`, c.green);
1327
- });
1328
- return;
1329
- }
1330
-
1331
- const meta = readJSON(metaPath);
1332
- const components = meta?.features?.statusline?.components || {};
1333
-
1334
- STATUSLINE_COMPONENTS.forEach(comp => {
1335
- const enabled = components[comp] !== false;
1336
- const icon = enabled ? '' : '';
1337
- const color = enabled ? c.green : c.dim;
1338
- log(` ${icon} ${comp}: ${enabled ? 'enabled' : 'disabled'}`, color);
1339
- });
1340
-
1341
- log('\nTo toggle: --show=<component> or --hide=<component>', c.dim);
1342
- log(`Components: ${STATUSLINE_COMPONENTS.join(', ')}`, c.dim);
1343
- }
1344
-
1345
- // ============================================================================
1346
- // MIGRATION
1347
- // ============================================================================
1348
-
1349
- /**
1350
- * Migrate settings to new format
1351
- * @returns {boolean} Whether migration occurred
1352
- */
1353
- function migrateSettings() {
1354
- header('Migrating Settings...');
1355
-
1356
- if (!fs.existsSync('.claude/settings.json')) {
1357
- warn('No settings.json to migrate');
1358
- return false;
1359
- }
1360
-
1361
- const settings = readJSON('.claude/settings.json');
1362
- if (!settings) {
1363
- error('Cannot parse settings.json');
1364
- return false;
1365
- }
1366
-
1367
- let migrated = false;
1368
-
1369
- // Migrate hooks to new format
1370
- if (settings.hooks) {
1371
- ['SessionStart', 'PreCompact', 'UserPromptSubmit', 'Stop'].forEach(hookName => {
1372
- const hook = settings.hooks[hookName];
1373
- if (!hook) return;
1374
-
1375
- if (typeof hook === 'string') {
1376
- const isNode = hook.includes('node ') || hook.endsWith('.js');
1377
- settings.hooks[hookName] = [
1378
- { matcher: '', hooks: [{ type: 'command', command: isNode ? hook : `bash ${hook}` }] },
1379
- ];
1380
- success(`Migrated ${hookName} from string format`);
1381
- migrated = true;
1382
- } else if (Array.isArray(hook) && hook.length > 0) {
1383
- const first = hook[0];
1384
- if (first.enabled !== undefined || first.command !== undefined) {
1385
- if (first.command) {
1386
- settings.hooks[hookName] = [
1387
- { matcher: '', hooks: [{ type: 'command', command: first.command }] },
1388
- ];
1389
- success(`Migrated ${hookName} from old object format`);
1390
- migrated = true;
1391
- }
1392
- } else if (first.matcher === undefined) {
1393
- settings.hooks[hookName] = [
1394
- { matcher: '', hooks: first.hooks || [{ type: 'command', command: 'echo "hook"' }] },
1395
- ];
1396
- success(`Migrated ${hookName} - added matcher`);
1397
- migrated = true;
1398
- }
1399
- }
1400
- });
1401
- }
1402
-
1403
- // Migrate statusLine
1404
- if (settings.statusLine) {
1405
- if (typeof settings.statusLine === 'string') {
1406
- settings.statusLine = { type: 'command', command: settings.statusLine, padding: 0 };
1407
- success('Migrated statusLine from string format');
1408
- migrated = true;
1409
- } else if (!settings.statusLine.type) {
1410
- settings.statusLine.type = 'command';
1411
- if (settings.statusLine.refreshInterval) {
1412
- delete settings.statusLine.refreshInterval;
1413
- settings.statusLine.padding = 0;
1414
- }
1415
- success('Migrated statusLine - added type:command');
1416
- migrated = true;
1417
- }
1418
- }
1419
-
1420
- if (migrated) {
1421
- fs.copyFileSync('.claude/settings.json', '.claude/settings.json.backup');
1422
- info('Backed up to .claude/settings.json.backup');
1423
- writeJSON('.claude/settings.json', settings);
1424
- success('Settings migrated successfully!');
1425
- } else {
1426
- info('No migration needed - formats are correct');
1427
- }
1428
-
1429
- return migrated;
1430
- }
1431
-
1432
- /**
1433
- * Upgrade outdated features to latest version
1434
- * @param {object} status - Status object from detectConfig
1435
- * @param {string} version - Current version
1436
- * @returns {boolean} Whether any features were upgraded
1437
- */
1438
- function upgradeFeatures(status, version) {
1439
- header('Upgrading Outdated Features...');
1440
-
1441
- let upgraded = 0;
1442
-
1443
- Object.entries(status.features).forEach(([feature, data]) => {
1444
- if (data.enabled && data.outdated) {
1445
- log(`\nUpgrading ${feature}...`, c.cyan);
1446
- if (
1447
- enableFeature(feature, { archivalDays: data.threshold || 30, isUpgrade: true }, version)
1448
- ) {
1449
- upgraded++;
1450
- }
1451
- }
1452
- });
1453
-
1454
- if (upgraded === 0) {
1455
- info('No features needed upgrading');
1456
- } else {
1457
- success(`Upgraded ${upgraded} feature(s) to v${version}`);
1458
- }
1459
-
1460
- return upgraded > 0;
1461
- }
1462
-
1463
- // ============================================================================
1464
- // STARTUP MODE (atomic command)
1465
- // ============================================================================
1466
-
1467
- /**
1468
- * Valid startup modes and their mappings
1469
- */
1470
- const STARTUP_MODES = {
1471
- 'skip-permissions': {
1472
- flags: '--dangerously-skip-permissions',
1473
- defaultMode: 'bypassPermissions',
1474
- description: 'Skip all permission prompts (trusted mode)',
1475
- },
1476
- 'accept-edits': {
1477
- flags: '--permission-mode acceptEdits',
1478
- defaultMode: 'acceptEdits',
1479
- description: 'Auto-accept file edits, prompt for other actions',
1480
- },
1481
- normal: {
1482
- flags: null,
1483
- defaultMode: null,
1484
- description: 'Standard Claude with permission prompts',
1485
- },
1486
- 'no-claude': {
1487
- flags: null,
1488
- defaultMode: null,
1489
- description: 'Create worktree only, start Claude manually',
1490
- },
1491
- };
1492
-
1493
- /**
1494
- * Set startup mode atomically - updates BOTH metadata AND .claude/settings.json
1495
- * This replaces the fragile two-step process of updating metadata + running --enable=claudeflags
1496
- *
1497
- * @param {string} mode - One of: skip-permissions, accept-edits, normal, no-claude
1498
- * @param {string} version - Current version string
1499
- * @returns {boolean} Success
1500
- */
1501
- function enableStartupMode(mode, version) {
1502
- const modeConfig = STARTUP_MODES[mode];
1503
- if (!modeConfig) {
1504
- error(`Unknown startup mode: ${mode}`);
1505
- log(` Valid modes: ${Object.keys(STARTUP_MODES).join(', ')}`, c.dim);
1506
- return false;
1507
- }
1508
-
1509
- ensureDir('.claude');
1510
- const settings = readJSON('.claude/settings.json') || {};
1511
- settings.permissions = settings.permissions || { allow: [], deny: [], ask: [] };
1512
-
1513
- if (mode === 'normal' || mode === 'no-claude') {
1514
- // Remove defaultMode from settings
1515
- if (settings.permissions.defaultMode) {
1516
- delete settings.permissions.defaultMode;
1517
- }
1518
- writeJSON('.claude/settings.json', settings);
1519
-
1520
- // Disable claudeflags + set defaultStartupMode in metadata (single write)
1521
- updateMetadata(
1522
- {
1523
- features: {
1524
- claudeFlags: {
1525
- enabled: false,
1526
- defaultFlags: '',
1527
- version,
1528
- at: new Date().toISOString(),
1529
- },
1530
- },
1531
- },
1532
- version
1533
- );
1534
- } else {
1535
- // Set defaultMode in settings.json
1536
- settings.permissions.defaultMode = modeConfig.defaultMode;
1537
- writeJSON('.claude/settings.json', settings);
1538
-
1539
- // Enable claudeflags + set defaultStartupMode in metadata (single write)
1540
- updateMetadata(
1541
- {
1542
- features: {
1543
- claudeFlags: {
1544
- enabled: true,
1545
- defaultFlags: modeConfig.flags,
1546
- version,
1547
- at: new Date().toISOString(),
1548
- },
1549
- },
1550
- },
1551
- version
1552
- );
1553
- }
1554
-
1555
- // Set defaultStartupMode in metadata (updateMetadata already created file if missing)
1556
- const metaPath = 'docs/00-meta/agileflow-metadata.json';
1557
- const meta = readJSON(metaPath) || {};
1558
- meta.defaultStartupMode = mode;
1559
- meta.updated = new Date().toISOString();
1560
- writeJSON(metaPath, meta);
1561
-
1562
- success(`Default startup mode set to: ${mode}`);
1563
- if (modeConfig.defaultMode) {
1564
- info(`Set permissions.defaultMode = "${modeConfig.defaultMode}" in .claude/settings.json`);
1565
- } else {
1566
- info('Removed permissions.defaultMode from .claude/settings.json');
1567
- }
1568
- info(`Metadata: defaultStartupMode = "${mode}"`);
1569
- if (mode !== 'normal') {
1570
- info('Restart Claude Code for the new mode to take effect');
1571
- }
1572
-
1573
- return true;
1574
- }
1575
-
1576
- // ============================================================================
1577
- // SHELL ALIASES
1578
- // ============================================================================
1579
-
1580
- const SHELL_ALIAS_MARKER = '# AgileFlow tmux wrapper';
1581
- const SHELL_ALIAS_BLOCK = `
1582
- ${SHELL_ALIAS_MARKER}
1583
- # Use 'af' or 'agileflow' for tmux, 'claude' stays normal
1584
- alias af="bash .agileflow/scripts/af"
1585
- alias agileflow="bash .agileflow/scripts/af"
1586
- `;
1587
-
1588
- /**
1589
- * Enable shell aliases by adding them to ~/.bashrc and ~/.zshrc
1590
- * @returns {object} Result with configured and skipped shells
1591
- */
1592
- function enableShellAliases() {
1593
- const result = {
1594
- configured: [],
1595
- skipped: [],
1596
- error: null,
1597
- };
1598
-
1599
- // Only set up aliases on Unix-like systems
1600
- if (process.platform === 'win32') {
1601
- result.skipped.push('Windows (not supported)');
1602
- return result;
1603
- }
1604
-
1605
- const homeDir = os.homedir();
1606
- const rcFiles = [
1607
- { name: 'bash', path: path.join(homeDir, '.bashrc') },
1608
- { name: 'zsh', path: path.join(homeDir, '.zshrc') },
1609
- ];
1610
-
1611
- // Lines that belong to AgileFlow alias blocks (old and new markers)
1612
- const ALIAS_BLOCK_LINES = [
1613
- '# AgileFlow tmux wrapper',
1614
- '# AgileFlow tmux shortcuts (claude stays normal)',
1615
- "# Use 'af' or 'agileflow' for tmux, 'claude' stays normal",
1616
- 'alias af="bash .agileflow/scripts/af"',
1617
- 'alias agileflow="bash .agileflow/scripts/af"',
1618
- ];
1619
-
1620
- for (const rc of rcFiles) {
1621
- try {
1622
- // Check if RC file exists
1623
- if (!fs.existsSync(rc.path)) {
1624
- result.skipped.push(`${rc.name} (no ${path.basename(rc.path)})`);
1625
- continue;
1626
- }
1627
-
1628
- const content = fs.readFileSync(rc.path, 'utf8');
1629
-
1630
- // Check for ANY existing af alias (covers old and new markers)
1631
- if (content.includes('alias af="bash .agileflow/scripts/af"')) {
1632
- // Clean up: remove ALL existing alias block lines, then re-add one clean copy
1633
- const lines = content.split('\n');
1634
- const cleaned = lines.filter(line => {
1635
- const trimmed = line.trim();
1636
- return !ALIAS_BLOCK_LINES.includes(trimmed);
1637
- });
1638
- // Remove trailing empty lines from cleanup
1639
- while (cleaned.length > 0 && cleaned[cleaned.length - 1].trim() === '') {
1640
- cleaned.pop();
1641
- }
1642
- fs.writeFileSync(rc.path, cleaned.join('\n') + SHELL_ALIAS_BLOCK);
1643
- result.configured.push(rc.name);
1644
- continue;
1645
- }
1646
-
1647
- // First time: just append
1648
- fs.appendFileSync(rc.path, SHELL_ALIAS_BLOCK);
1649
- result.configured.push(rc.name);
1650
- } catch (err) {
1651
- result.skipped.push(`${rc.name} (error: ${err.message})`);
1652
- }
1653
- }
1654
-
1655
- return result;
1656
- }
1657
-
1658
- /**
1659
- * Disable shell aliases by removing them from ~/.bashrc and ~/.zshrc
1660
- * @returns {object} Result with removed shells
1661
- */
1662
- function disableShellAliases() {
1663
- const result = {
1664
- removed: [],
1665
- skipped: [],
1666
- };
1667
-
1668
- if (process.platform === 'win32') {
1669
- return result;
1670
- }
1671
-
1672
- const homeDir = os.homedir();
1673
- const rcFiles = [
1674
- { name: 'bash', path: path.join(homeDir, '.bashrc') },
1675
- { name: 'zsh', path: path.join(homeDir, '.zshrc') },
1676
- ];
1677
-
1678
- // Lines that belong to AgileFlow alias blocks (old and new markers)
1679
- const ALIAS_BLOCK_LINES = [
1680
- '# AgileFlow tmux wrapper',
1681
- '# AgileFlow tmux shortcuts (claude stays normal)',
1682
- "# Use 'af' or 'agileflow' for tmux, 'claude' stays normal",
1683
- 'alias af="bash .agileflow/scripts/af"',
1684
- 'alias agileflow="bash .agileflow/scripts/af"',
1685
- ];
1686
-
1687
- for (const rc of rcFiles) {
1688
- try {
1689
- if (!fs.existsSync(rc.path)) {
1690
- continue;
1691
- }
1692
-
1693
- const content = fs.readFileSync(rc.path, 'utf8');
1694
-
1695
- // Check for any AgileFlow alias (covers old and new markers)
1696
- if (
1697
- !content.includes('alias af="bash .agileflow/scripts/af"') &&
1698
- !content.includes(SHELL_ALIAS_MARKER)
1699
- ) {
1700
- continue;
1701
- }
1702
-
1703
- // Remove all alias block lines
1704
- const lines = content.split('\n');
1705
- const filteredLines = lines.filter(line => {
1706
- const trimmed = line.trim();
1707
- return !ALIAS_BLOCK_LINES.includes(trimmed);
1708
- });
1709
-
1710
- // Remove trailing empty lines from cleanup
1711
- while (filteredLines.length > 0 && filteredLines[filteredLines.length - 1].trim() === '') {
1712
- filteredLines.pop();
1713
- }
1714
-
1715
- fs.writeFileSync(rc.path, filteredLines.join('\n') + '\n', 'utf8');
1716
- result.removed.push(rc.name);
1717
- } catch (err) {
1718
- result.skipped.push(`${rc.name} (error: ${err.message})`);
1719
- }
1720
- }
1721
-
1722
- return result;
1723
- }
1724
-
1725
- // ============================================================================
1726
- // CLAUDE.MD REINFORCEMENT
1727
- // ============================================================================
1728
-
1729
- // ============================================================================
1730
- // BROWSER QA
1731
- // ============================================================================
1732
-
1733
- /**
1734
- * Enable browser QA (agentic browser testing)
1735
- * Creates evidence directory structure, deploys spec template, updates metadata
1736
- */
1737
- function enableBrowserQa(version) {
1738
- // Create evidence directory structure + screenshots dir for visual verification
1739
- const dirs = [
1740
- '.agileflow/ui-review',
1741
- '.agileflow/ui-review/runs',
1742
- '.agileflow/ui-review/specs',
1743
- '.agileflow/ui-review/baselines',
1744
- 'screenshots',
1745
- ];
1746
- for (const dir of dirs) {
1747
- ensureDir(dir);
1748
- }
1749
-
1750
- // Deploy spec template if not exists
1751
- const templateDest = path.join(
1752
- process.cwd(),
1753
- '.agileflow',
1754
- 'ui-review',
1755
- 'specs',
1756
- '_template.yaml'
1757
- );
1758
- if (!fs.existsSync(templateDest)) {
1759
- const templateSrc = path.join(process.cwd(), '.agileflow', 'templates', 'browser-qa-spec.yaml');
1760
- if (fs.existsSync(templateSrc)) {
1761
- fs.copyFileSync(templateSrc, templateDest);
1762
- success('Deployed browser-qa spec template');
1763
- } else {
1764
- info('No spec template found - create YAML specs manually in .agileflow/ui-review/specs/');
1765
- }
1766
- }
1767
-
1768
- // Check for Playwright
1769
- let playwrightAvailable = false;
1770
- try {
1771
- require.resolve('playwright');
1772
- playwrightAvailable = true;
1773
- } catch {
1774
- // Not installed
1775
- }
1776
-
1777
- if (!playwrightAvailable) {
1778
- warn('Playwright not found - install for browser automation:');
1779
- info(' npm install --save-optional playwright');
1780
- info(' npx playwright install chromium');
1781
- }
1782
-
1783
- // Update gitignore - evidence runs should not be committed
1784
- updateGitignore();
1785
-
1786
- updateMetadata(
1787
- {
1788
- features: {
1789
- browserqa: {
1790
- enabled: true,
1791
- version,
1792
- at: new Date().toISOString(),
1793
- playwright_detected: playwrightAvailable,
1794
- },
1795
- },
1796
- },
1797
- version
1798
- );
1799
-
1800
- success('UI Testing enabled (agentic browser testing + visual verification)');
1801
- info('Evidence directory: .agileflow/ui-review/');
1802
- info('Screenshots directory: screenshots/ (for visual verification with VISUAL=true)');
1803
- info('Spec template: .agileflow/ui-review/specs/_template.yaml');
1804
- info('Agentic testing: /agileflow:browser-qa SCENARIO=<spec.yaml>');
1805
- info('Visual verification: /agileflow:babysit EPIC=EP-XXXX MODE=loop VISUAL=true');
1806
- if (playwrightAvailable) {
1807
- info('Playwright: detected');
1808
- }
1809
-
1810
- return true;
1811
- }
1812
-
1813
- const CLAUDE_MD_MARKER = '<!-- AGILEFLOW_BABYSIT_RULES -->';
1814
- const CLAUDE_MD_CONTENT = `
1815
-
1816
- ${CLAUDE_MD_MARKER}
1817
- ## AgileFlow /babysit Context Preservation Rules
1818
-
1819
- When \`/agileflow:babysit\` is active (check session-state.json), these rules are MANDATORY:
1820
-
1821
- 1. **ALWAYS end responses with the AskUserQuestion tool** - Not text like "What next?" but the ACTUAL TOOL CALL
1822
- 2. **Use Plan Mode for non-trivial tasks** - Call \`EnterPlanMode\` before complex implementations
1823
- 3. **Delegate complex work to domain experts** - Use \`Task\` tool with appropriate \`subagent_type\`
1824
- 4. **Track progress with TaskCreate/TaskUpdate** - For any task with 3+ steps
1825
-
1826
- These rules persist across conversation compaction. Check \`docs/09-agents/session-state.json\` for active commands.
1827
- ${CLAUDE_MD_MARKER}
1828
- `;
1829
-
1830
- /**
1831
- * Enable CLAUDE.md reinforcement by adding babysit rules
1832
- * @returns {object} Result with success, added, and error
1833
- */
1834
- function enableClaudeMdReinforcement() {
1835
- const claudeMdPath = path.join(process.cwd(), 'CLAUDE.md');
1836
-
1837
- try {
1838
- let existingContent = '';
1839
- if (fs.existsSync(claudeMdPath)) {
1840
- existingContent = fs.readFileSync(claudeMdPath, 'utf8');
1841
- }
1842
-
1843
- // Only append if marker doesn't exist
1844
- if (existingContent.includes(CLAUDE_MD_MARKER)) {
1845
- return { success: true, added: false };
1846
- }
1847
-
1848
- fs.appendFileSync(claudeMdPath, CLAUDE_MD_CONTENT);
1849
- return { success: true, added: true };
1850
- } catch (err) {
1851
- return { success: false, error: err.message };
1852
- }
1853
- }
1854
-
1855
- /**
1856
- * Disable CLAUDE.md reinforcement by removing babysit rules
1857
- * @returns {object} Result with removed flag
1858
- */
1859
- function disableClaudeMdReinforcement() {
1860
- const claudeMdPath = path.join(process.cwd(), 'CLAUDE.md');
1861
-
1862
- if (!fs.existsSync(claudeMdPath)) {
1863
- return { removed: false };
1864
- }
1865
-
1866
- try {
1867
- const content = fs.readFileSync(claudeMdPath, 'utf8');
1868
-
1869
- if (!content.includes(CLAUDE_MD_MARKER)) {
1870
- return { removed: false };
1871
- }
1872
-
1873
- // Remove the section between markers (inclusive)
1874
- const startIdx = content.indexOf(CLAUDE_MD_MARKER);
1875
- const endMarkerIdx = content.indexOf(CLAUDE_MD_MARKER, startIdx + CLAUDE_MD_MARKER.length);
1876
-
1877
- if (startIdx === -1 || endMarkerIdx === -1) {
1878
- return { removed: false };
1879
- }
1880
-
1881
- // Find the start of the line containing the first marker
1882
- let lineStart = content.lastIndexOf('\n', startIdx);
1883
- if (lineStart === -1) lineStart = 0;
1884
-
1885
- // Find the end of the line containing the second marker
1886
- let lineEnd = content.indexOf('\n', endMarkerIdx + CLAUDE_MD_MARKER.length);
1887
- if (lineEnd === -1) lineEnd = content.length;
1888
-
1889
- const newContent = content.slice(0, lineStart) + content.slice(lineEnd);
1890
-
1891
- // Clean up any trailing newlines
1892
- fs.writeFileSync(claudeMdPath, newContent.trimEnd() + '\n', 'utf8');
1893
- return { removed: true };
1894
- } catch (err) {
1895
- return { removed: false, error: err.message };
1896
- }
1897
- }
1898
-
1899
- module.exports = {
1900
- // Constants
1901
- FEATURES,
1902
- PROFILES,
1903
- STATUSLINE_COMPONENTS,
1904
- // Feature management
1905
- enableFeature,
1906
- disableFeature,
1907
- applyProfile,
1908
- updateMetadata,
1909
- // Statusline components
1910
- setStatuslineComponents,
1911
- listStatuslineComponents,
1912
- // Migration
1913
- migrateSettings,
1914
- upgradeFeatures,
1915
- // Helpers
1916
- scriptExists,
1917
- getScriptPath,
1918
- // Startup mode
1919
- enableStartupMode,
1920
- STARTUP_MODES,
1921
- // Shell aliases
1922
- enableShellAliases,
1923
- disableShellAliases,
1924
- // CLAUDE.md reinforcement
1925
- enableClaudeMdReinforcement,
1926
- disableClaudeMdReinforcement,
1927
- };