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.
- package/CHANGELOG.md +238 -473
- package/README.md +22 -114
- package/bin/agileflow.js +15 -0
- package/bin/hooks/pre-bash.js +35 -0
- package/bin/hooks/pre-compact.js +34 -0
- package/bin/hooks/pre-edit.js +32 -0
- package/bin/hooks/pre-write.js +32 -0
- package/bin/hooks/session-start.js +42 -0
- package/bin/hooks/stop.js +34 -0
- package/content/plugins/ads/plugin.yaml +14 -0
- package/content/plugins/audit/plugin.yaml +14 -0
- package/content/plugins/core/hooks/babysit-mentor-injector.js +55 -0
- package/content/plugins/core/hooks/context-loader.js +169 -0
- package/content/plugins/core/hooks/damage-control-bash.js +78 -0
- package/content/plugins/core/hooks/damage-control-edit.js +76 -0
- package/content/plugins/core/hooks/damage-control-patterns.yaml +100 -0
- package/content/plugins/core/hooks/damage-control-write.js +72 -0
- package/content/plugins/core/hooks/pre-compact-state.js +90 -0
- package/content/plugins/core/hooks/session-welcome.js +19 -0
- package/content/plugins/core/plugin.yaml +82 -0
- package/content/plugins/core/skills/agileflow-adr/SKILL.md +179 -0
- package/content/plugins/core/skills/agileflow-babysit-mentor/SKILL.md +144 -0
- package/content/plugins/core/skills/agileflow-epic-planner/SKILL.md +179 -0
- package/content/plugins/core/skills/agileflow-status-updater/SKILL.md +132 -0
- package/content/plugins/core/skills/agileflow-story-writer/SKILL.md +200 -0
- package/content/plugins/council/plugin.yaml +14 -0
- package/content/plugins/seo/plugin.yaml +14 -0
- package/package.json +29 -49
- package/src/cli/commands/doctor.js +159 -0
- package/src/cli/commands/hook.js +80 -0
- package/src/cli/commands/setup.js +292 -0
- package/src/cli/commands/status.js +47 -0
- package/src/cli/commands/update.js +83 -0
- package/src/cli/index.js +73 -0
- package/src/cli/wizard/behaviors-picker.js +108 -0
- package/src/cli/wizard/ide-picker.js +57 -0
- package/src/cli/wizard/personalization.js +64 -0
- package/src/cli/wizard/plugin-picker.js +106 -0
- package/src/lib/hash.js +41 -0
- package/src/runtime/config/defaults.js +61 -0
- package/src/runtime/config/loader.js +117 -0
- package/src/runtime/config/schema.json +99 -0
- package/src/runtime/config/writer.js +55 -0
- package/src/runtime/hooks/aggregator.js +157 -0
- package/src/runtime/hooks/chain.js +93 -0
- package/src/runtime/hooks/logger.js +68 -0
- package/src/runtime/hooks/manifest-loader.js +228 -0
- package/src/runtime/hooks/orchestrator.js +322 -0
- package/src/runtime/ide/capabilities.js +111 -0
- package/src/runtime/ide/claude-code-settings.js +234 -0
- package/src/runtime/ide/claude-code-skills.js +202 -0
- package/src/runtime/installer/file-index.js +112 -0
- package/src/runtime/installer/install.js +329 -0
- package/src/runtime/installer/stash.js +61 -0
- package/src/runtime/installer/sync-engine.js +205 -0
- package/src/runtime/plugins/registry.js +132 -0
- package/src/runtime/plugins/resolver.js +138 -0
- package/src/runtime/plugins/validator.js +196 -0
- package/src/runtime/skills/validator.js +335 -0
- package/lib/README.md +0 -178
- package/lib/api-routes.js +0 -625
- package/lib/api-server.js +0 -278
- package/lib/cache-provider.js +0 -155
- package/lib/codebase-indexer.js +0 -819
- package/lib/colors.generated.js +0 -117
- package/lib/colors.js +0 -341
- package/lib/consent.js +0 -232
- package/lib/content-sanitizer.js +0 -464
- package/lib/correlation.js +0 -277
- package/lib/drivers/claude-driver.ts +0 -312
- package/lib/drivers/codex-driver.ts +0 -464
- package/lib/drivers/driver-manager.ts +0 -159
- package/lib/drivers/gemini-driver.ts +0 -498
- package/lib/drivers/index.ts +0 -17
- package/lib/error-codes.js +0 -590
- package/lib/errors.js +0 -670
- package/lib/feature-flags.js +0 -171
- package/lib/feedback.js +0 -595
- package/lib/file-cache.js +0 -541
- package/lib/flag-detection.js +0 -344
- package/lib/format-error.js +0 -156
- package/lib/gate-runner.js +0 -282
- package/lib/generator-factory.js +0 -333
- package/lib/git-operations.js +0 -266
- package/lib/lazy-require.js +0 -59
- package/lib/lock-file.js +0 -144
- package/lib/logger.js +0 -106
- package/lib/merge-operations.js +0 -1006
- package/lib/path-resolver.js +0 -544
- package/lib/path-utils.js +0 -49
- package/lib/paths.js +0 -291
- package/lib/placeholder-registry.js +0 -822
- package/lib/process-executor.js +0 -214
- package/lib/progress.js +0 -334
- package/lib/protocol/driver.ts +0 -354
- package/lib/protocol/index.ts +0 -12
- package/lib/protocol/ir.ts +0 -271
- package/lib/registry-cache.js +0 -80
- package/lib/registry-di.js +0 -358
- package/lib/result-schema.js +0 -363
- package/lib/result.js +0 -210
- package/lib/session-display.js +0 -331
- package/lib/session-operations.js +0 -611
- package/lib/session-registry.js +0 -484
- package/lib/session-state-machine.js +0 -465
- package/lib/session-switching.js +0 -191
- package/lib/skill-loader.js +0 -213
- package/lib/smart-json-file.js +0 -682
- package/lib/state-machine.js +0 -286
- package/lib/table-formatter.js +0 -519
- package/lib/template-loader.js +0 -143
- package/lib/transient-status.js +0 -374
- package/lib/ui-manager.js +0 -612
- package/lib/validate-args.js +0 -213
- package/lib/validate-commands.js +0 -308
- package/lib/validate-names.js +0 -143
- package/lib/validate-paths.js +0 -434
- package/lib/validate.js +0 -134
- package/lib/worktree-operations.js +0 -201
- package/lib/yaml-utils.js +0 -164
- package/scripts/README.md +0 -267
- package/scripts/af +0 -34
- package/scripts/agent-loop.js +0 -879
- package/scripts/agileflow-configure.js +0 -368
- package/scripts/agileflow-statusline.sh +0 -857
- package/scripts/agileflow-welcome.js +0 -2246
- package/scripts/api-server-runner.js +0 -177
- package/scripts/archive-completed-stories.sh +0 -308
- package/scripts/auto-self-improve.js +0 -326
- package/scripts/automation-run-due.js +0 -128
- package/scripts/babysit-clear-restore.js +0 -154
- package/scripts/babysit-context-restore.js +0 -89
- package/scripts/backfill-ideation-status.js +0 -128
- package/scripts/batch-pmap-loop.js +0 -551
- package/scripts/check-sessions.js +0 -116
- package/scripts/check-update.js +0 -282
- package/scripts/ci-summary.js +0 -294
- package/scripts/claude-smart.sh +0 -85
- package/scripts/claude-tmux.sh +0 -737
- package/scripts/claude-watchdog.sh +0 -225
- package/scripts/clear-active-command.js +0 -48
- package/scripts/compress-status.sh +0 -116
- package/scripts/context-loader.js +0 -310
- package/scripts/damage-control/bash-tool-damage-control.js +0 -22
- package/scripts/damage-control/edit-tool-damage-control.js +0 -19
- package/scripts/damage-control/patterns.yaml +0 -227
- package/scripts/damage-control/write-tool-damage-control.js +0 -19
- package/scripts/damage-control-bash.js +0 -51
- package/scripts/damage-control-edit.js +0 -48
- package/scripts/damage-control-multi-agent.js +0 -231
- package/scripts/damage-control-write.js +0 -48
- package/scripts/dependency-check.js +0 -311
- package/scripts/document-repl.js +0 -793
- package/scripts/expertise-metrics.sh +0 -264
- package/scripts/generate-all.sh +0 -77
- package/scripts/generate-colors.js +0 -314
- package/scripts/generators/agent-registry.js +0 -183
- package/scripts/generators/command-registry.js +0 -166
- package/scripts/generators/index.js +0 -85
- package/scripts/generators/inject-babysit.js +0 -191
- package/scripts/generators/inject-help.js +0 -125
- package/scripts/generators/inject-readme.js +0 -166
- package/scripts/generators/skill-registry.js +0 -188
- package/scripts/get-env.js +0 -225
- package/scripts/init.sh +0 -76
- package/scripts/lib/README-portable-tasks.md +0 -424
- package/scripts/lib/ac-test-matcher.js +0 -452
- package/scripts/lib/audit-cleanup.js +0 -250
- package/scripts/lib/audit-registry.js +0 -340
- package/scripts/lib/automation-registry.js +0 -544
- package/scripts/lib/automation-runner.js +0 -476
- package/scripts/lib/browser-qa-evidence.js +0 -409
- package/scripts/lib/browser-qa-status.js +0 -192
- package/scripts/lib/bus-utils.js +0 -473
- package/scripts/lib/colors.generated.sh +0 -82
- package/scripts/lib/colors.sh +0 -46
- package/scripts/lib/command-prereqs.js +0 -280
- package/scripts/lib/concurrency-limiter.js +0 -511
- package/scripts/lib/configure-detect.js +0 -596
- package/scripts/lib/configure-features.js +0 -1927
- package/scripts/lib/configure-repair.js +0 -327
- package/scripts/lib/configure-utils.js +0 -114
- package/scripts/lib/context-formatter.js +0 -1158
- package/scripts/lib/context-loader.js +0 -840
- package/scripts/lib/counter.js +0 -103
- package/scripts/lib/damage-control-utils.js +0 -619
- package/scripts/lib/feature-catalog.js +0 -332
- package/scripts/lib/file-lock.js +0 -392
- package/scripts/lib/file-tracking.js +0 -735
- package/scripts/lib/frontmatter-parser.js +0 -133
- package/scripts/lib/gate-enforcer.js +0 -295
- package/scripts/lib/hook-metrics.js +0 -324
- package/scripts/lib/ideation-index.js +0 -1205
- package/scripts/lib/json-utils.sh +0 -162
- package/scripts/lib/lifecycle-detector.js +0 -125
- package/scripts/lib/model-profiles.js +0 -118
- package/scripts/lib/portable-tasks-cli.js +0 -274
- package/scripts/lib/portable-tasks.js +0 -479
- package/scripts/lib/process-cleanup.js +0 -527
- package/scripts/lib/quality-gates.js +0 -788
- package/scripts/lib/scale-detector.js +0 -396
- package/scripts/lib/sessionRegistry.js +0 -678
- package/scripts/lib/signal-detectors.js +0 -867
- package/scripts/lib/skill-catalog.js +0 -557
- package/scripts/lib/skill-recommender.js +0 -311
- package/scripts/lib/state-migrator.js +0 -353
- package/scripts/lib/status-task-bridge.js +0 -522
- package/scripts/lib/status-writer.js +0 -255
- package/scripts/lib/story-claiming.js +0 -704
- package/scripts/lib/story-state-machine.js +0 -437
- package/scripts/lib/sync-ideation-status.js +0 -291
- package/scripts/lib/task-registry-cache.js +0 -490
- package/scripts/lib/task-registry.js +0 -1191
- package/scripts/lib/task-sync.js +0 -230
- package/scripts/lib/tdd-phase-manager.js +0 -455
- package/scripts/lib/team-events.js +0 -510
- package/scripts/lib/tmux-audit-monitor.js +0 -612
- package/scripts/lib/tmux-group-colors.js +0 -113
- package/scripts/lib/tool-registry.yaml +0 -241
- package/scripts/lib/tool-shed.js +0 -441
- package/scripts/lib/validation-registry.js +0 -177
- package/scripts/messaging-bridge.js +0 -561
- package/scripts/migrate-ideation-index.js +0 -553
- package/scripts/native-team-observer.js +0 -219
- package/scripts/obtain-context.js +0 -272
- package/scripts/pre-push-check.sh +0 -46
- package/scripts/precompact-context.sh +0 -306
- package/scripts/query-codebase.js +0 -543
- package/scripts/ralph-loop.js +0 -1278
- package/scripts/resume-session.sh +0 -121
- package/scripts/screenshot-verifier.js +0 -215
- package/scripts/session-boundary.js +0 -138
- package/scripts/session-coordinator.sh +0 -232
- package/scripts/session-manager.js +0 -546
- package/scripts/smart-detect.js +0 -449
- package/scripts/spawn-audit-sessions.js +0 -877
- package/scripts/spawn-parallel.js +0 -751
- package/scripts/strip-ai-attribution.js +0 -63
- package/scripts/task-completed-gate.js +0 -237
- package/scripts/team-manager.js +0 -596
- package/scripts/team-status-display.js +0 -200
- package/scripts/teammate-idle-gate.js +0 -237
- package/scripts/test-session-boundary.js +0 -80
- package/scripts/tmux-close-windows.sh +0 -180
- package/scripts/tmux-restore-window.sh +0 -67
- package/scripts/tmux-save-closed-window.sh +0 -35
- package/scripts/tui/App.js +0 -151
- package/scripts/tui/Dashboard.js +0 -277
- package/scripts/tui/blessed/data/watcher.js +0 -180
- package/scripts/tui/blessed/index.js +0 -244
- package/scripts/tui/blessed/panels/output.js +0 -101
- package/scripts/tui/blessed/panels/sessions.js +0 -150
- package/scripts/tui/blessed/panels/trace.js +0 -97
- package/scripts/tui/blessed/ui/help.js +0 -77
- package/scripts/tui/blessed/ui/screen.js +0 -52
- package/scripts/tui/blessed/ui/statusbar.js +0 -47
- package/scripts/tui/blessed/ui/tabbar.js +0 -99
- package/scripts/tui/index.js +0 -70
- package/scripts/tui/lib/crashRecovery.js +0 -304
- package/scripts/tui/lib/eventStream.js +0 -309
- package/scripts/tui/lib/keyboard.js +0 -261
- package/scripts/tui/lib/loopControl.js +0 -371
- package/scripts/tui/panels/OutputPanel.js +0 -240
- package/scripts/tui/panels/SessionPanel.js +0 -170
- package/scripts/tui/panels/TracePanel.js +0 -298
- package/scripts/tui/simple-tui.js +0 -510
- package/scripts/validate-expertise.sh +0 -263
- package/scripts/validate-tokens.sh +0 -73
- package/scripts/validators/README.md +0 -143
- package/scripts/validators/component-validator.js +0 -239
- package/scripts/validators/json-schema-validator.js +0 -186
- package/scripts/validators/markdown-validator.js +0 -152
- package/scripts/validators/migration-validator.js +0 -129
- package/scripts/validators/security-validator.js +0 -380
- package/scripts/validators/story-format-validator.js +0 -197
- package/scripts/validators/test-result-validator.js +0 -114
- package/scripts/validators/workflow-validator.js +0 -247
- package/scripts/welcome-deferred.js +0 -437
- package/scripts/worktree-create.sh +0 -111
- package/src/core/agents/a11y-analyzer-aria.md +0 -155
- package/src/core/agents/a11y-analyzer-forms.md +0 -162
- package/src/core/agents/a11y-analyzer-keyboard.md +0 -175
- package/src/core/agents/a11y-analyzer-semantic.md +0 -153
- package/src/core/agents/a11y-analyzer-visual.md +0 -158
- package/src/core/agents/a11y-consensus.md +0 -248
- package/src/core/agents/accessibility.md +0 -515
- package/src/core/agents/adr-writer.md +0 -463
- package/src/core/agents/ads-audit-budget.md +0 -181
- package/src/core/agents/ads-audit-compliance.md +0 -169
- package/src/core/agents/ads-audit-creative.md +0 -164
- package/src/core/agents/ads-audit-google.md +0 -226
- package/src/core/agents/ads-audit-meta.md +0 -183
- package/src/core/agents/ads-audit-tracking.md +0 -197
- package/src/core/agents/ads-consensus.md +0 -396
- package/src/core/agents/ads-generate.md +0 -145
- package/src/core/agents/ads-performance-tracker.md +0 -197
- package/src/core/agents/analytics.md +0 -617
- package/src/core/agents/api-quality-analyzer-conventions.md +0 -148
- package/src/core/agents/api-quality-analyzer-docs.md +0 -176
- package/src/core/agents/api-quality-analyzer-errors.md +0 -183
- package/src/core/agents/api-quality-analyzer-pagination.md +0 -171
- package/src/core/agents/api-quality-analyzer-versioning.md +0 -143
- package/src/core/agents/api-quality-consensus.md +0 -214
- package/src/core/agents/api-validator.md +0 -183
- package/src/core/agents/api.md +0 -665
- package/src/core/agents/arch-analyzer-circular.md +0 -148
- package/src/core/agents/arch-analyzer-complexity.md +0 -171
- package/src/core/agents/arch-analyzer-coupling.md +0 -146
- package/src/core/agents/arch-analyzer-layering.md +0 -151
- package/src/core/agents/arch-analyzer-patterns.md +0 -162
- package/src/core/agents/arch-consensus.md +0 -227
- package/src/core/agents/brainstorm-analyzer-features.md +0 -169
- package/src/core/agents/brainstorm-analyzer-growth.md +0 -161
- package/src/core/agents/brainstorm-analyzer-integration.md +0 -172
- package/src/core/agents/brainstorm-analyzer-market.md +0 -147
- package/src/core/agents/brainstorm-analyzer-ux.md +0 -167
- package/src/core/agents/brainstorm-consensus.md +0 -237
- package/src/core/agents/browser-qa.md +0 -328
- package/src/core/agents/ci.md +0 -511
- package/src/core/agents/code-reviewer.md +0 -288
- package/src/core/agents/codebase-query.md +0 -266
- package/src/core/agents/completeness-analyzer-api.md +0 -190
- package/src/core/agents/completeness-analyzer-conditional.md +0 -201
- package/src/core/agents/completeness-analyzer-handlers.md +0 -159
- package/src/core/agents/completeness-analyzer-imports.md +0 -159
- package/src/core/agents/completeness-analyzer-routes.md +0 -182
- package/src/core/agents/completeness-analyzer-state.md +0 -188
- package/src/core/agents/completeness-analyzer-stubs.md +0 -198
- package/src/core/agents/completeness-consensus.md +0 -286
- package/src/core/agents/compliance.md +0 -509
- package/src/core/agents/council-advocate.md +0 -206
- package/src/core/agents/council-analyst.md +0 -252
- package/src/core/agents/council-optimist.md +0 -170
- package/src/core/agents/database.md +0 -601
- package/src/core/agents/datamigration.md +0 -699
- package/src/core/agents/design.md +0 -525
- package/src/core/agents/devops.md +0 -720
- package/src/core/agents/documentation.md +0 -504
- package/src/core/agents/epic-planner.md +0 -480
- package/src/core/agents/error-analyzer.md +0 -201
- package/src/core/agents/integrations.md +0 -603
- package/src/core/agents/legal-analyzer-a11y.md +0 -110
- package/src/core/agents/legal-analyzer-ai.md +0 -117
- package/src/core/agents/legal-analyzer-consumer.md +0 -108
- package/src/core/agents/legal-analyzer-content.md +0 -113
- package/src/core/agents/legal-analyzer-international.md +0 -115
- package/src/core/agents/legal-analyzer-licensing.md +0 -115
- package/src/core/agents/legal-analyzer-privacy.md +0 -108
- package/src/core/agents/legal-analyzer-security.md +0 -112
- package/src/core/agents/legal-analyzer-terms.md +0 -111
- package/src/core/agents/legal-consensus.md +0 -242
- package/src/core/agents/logic-analyzer-edge.md +0 -170
- package/src/core/agents/logic-analyzer-flow.md +0 -253
- package/src/core/agents/logic-analyzer-invariant.md +0 -206
- package/src/core/agents/logic-analyzer-race.md +0 -266
- package/src/core/agents/logic-analyzer-type.md +0 -217
- package/src/core/agents/logic-consensus.md +0 -253
- package/src/core/agents/mentor.md +0 -654
- package/src/core/agents/mobile.md +0 -501
- package/src/core/agents/monitoring.md +0 -537
- package/src/core/agents/multi-expert.md +0 -311
- package/src/core/agents/orchestrator.md +0 -749
- package/src/core/agents/perf-analyzer-assets.md +0 -174
- package/src/core/agents/perf-analyzer-bundle.md +0 -165
- package/src/core/agents/perf-analyzer-caching.md +0 -160
- package/src/core/agents/perf-analyzer-compute.md +0 -165
- package/src/core/agents/perf-analyzer-memory.md +0 -182
- package/src/core/agents/perf-analyzer-network.md +0 -157
- package/src/core/agents/perf-analyzer-queries.md +0 -155
- package/src/core/agents/perf-analyzer-rendering.md +0 -156
- package/src/core/agents/perf-consensus.md +0 -280
- package/src/core/agents/performance.md +0 -492
- package/src/core/agents/product.md +0 -535
- package/src/core/agents/qa.md +0 -765
- package/src/core/agents/readme-updater.md +0 -579
- package/src/core/agents/refactor.md +0 -558
- package/src/core/agents/research.md +0 -453
- package/src/core/agents/rlm-subcore.md +0 -207
- package/src/core/agents/schema-validator.md +0 -454
- package/src/core/agents/security-analyzer-api.md +0 -199
- package/src/core/agents/security-analyzer-auth.md +0 -160
- package/src/core/agents/security-analyzer-authz.md +0 -168
- package/src/core/agents/security-analyzer-deps.md +0 -147
- package/src/core/agents/security-analyzer-infra.md +0 -176
- package/src/core/agents/security-analyzer-injection.md +0 -148
- package/src/core/agents/security-analyzer-input.md +0 -191
- package/src/core/agents/security-analyzer-secrets.md +0 -175
- package/src/core/agents/security-consensus.md +0 -276
- package/src/core/agents/security.md +0 -486
- package/src/core/agents/seo-analyzer-content.md +0 -167
- package/src/core/agents/seo-analyzer-images.md +0 -187
- package/src/core/agents/seo-analyzer-performance.md +0 -206
- package/src/core/agents/seo-analyzer-schema.md +0 -176
- package/src/core/agents/seo-analyzer-sitemap.md +0 -172
- package/src/core/agents/seo-analyzer-technical.md +0 -144
- package/src/core/agents/seo-consensus.md +0 -289
- package/src/core/agents/team-coordinator.md +0 -333
- package/src/core/agents/team-lead.md +0 -171
- package/src/core/agents/test-analyzer-assertions.md +0 -181
- package/src/core/agents/test-analyzer-coverage.md +0 -183
- package/src/core/agents/test-analyzer-fragility.md +0 -185
- package/src/core/agents/test-analyzer-integration.md +0 -155
- package/src/core/agents/test-analyzer-maintenance.md +0 -173
- package/src/core/agents/test-analyzer-mocking.md +0 -178
- package/src/core/agents/test-analyzer-patterns.md +0 -189
- package/src/core/agents/test-analyzer-structure.md +0 -177
- package/src/core/agents/test-consensus.md +0 -294
- package/src/core/agents/testing.md +0 -527
- package/src/core/agents/ui-validator.md +0 -331
- package/src/core/agents/ui.md +0 -1227
- package/src/core/commands/adr/list.md +0 -191
- package/src/core/commands/adr/update.md +0 -258
- package/src/core/commands/adr/view.md +0 -274
- package/src/core/commands/adr.md +0 -394
- package/src/core/commands/ads/audit.md +0 -453
- package/src/core/commands/ads/budget.md +0 -97
- package/src/core/commands/ads/competitor.md +0 -112
- package/src/core/commands/ads/creative.md +0 -85
- package/src/core/commands/ads/generate.md +0 -238
- package/src/core/commands/ads/google.md +0 -112
- package/src/core/commands/ads/health.md +0 -327
- package/src/core/commands/ads/landing.md +0 -119
- package/src/core/commands/ads/linkedin.md +0 -112
- package/src/core/commands/ads/meta.md +0 -91
- package/src/core/commands/ads/microsoft.md +0 -115
- package/src/core/commands/ads/plan.md +0 -321
- package/src/core/commands/ads/test-plan.md +0 -317
- package/src/core/commands/ads/tiktok.md +0 -129
- package/src/core/commands/ads/track.md +0 -288
- package/src/core/commands/ads/youtube.md +0 -124
- package/src/core/commands/ads.md +0 -140
- package/src/core/commands/agent.md +0 -256
- package/src/core/commands/api.md +0 -267
- package/src/core/commands/assign.md +0 -369
- package/src/core/commands/audit.md +0 -531
- package/src/core/commands/auto.md +0 -556
- package/src/core/commands/automate.md +0 -415
- package/src/core/commands/babysit.md +0 -643
- package/src/core/commands/baseline.md +0 -743
- package/src/core/commands/batch.md +0 -551
- package/src/core/commands/blockers.md +0 -602
- package/src/core/commands/board.md +0 -509
- package/src/core/commands/browser-qa.md +0 -240
- package/src/core/commands/changelog.md +0 -582
- package/src/core/commands/choose.md +0 -430
- package/src/core/commands/ci.md +0 -330
- package/src/core/commands/code/accessibility.md +0 -363
- package/src/core/commands/code/api.md +0 -313
- package/src/core/commands/code/architecture.md +0 -313
- package/src/core/commands/code/completeness.md +0 -519
- package/src/core/commands/code/legal.md +0 -509
- package/src/core/commands/code/logic.md +0 -432
- package/src/core/commands/code/performance.md +0 -506
- package/src/core/commands/code/security.md +0 -509
- package/src/core/commands/code/test.md +0 -505
- package/src/core/commands/compress.md +0 -408
- package/src/core/commands/configure.md +0 -1159
- package/src/core/commands/context/export.md +0 -296
- package/src/core/commands/context/full.md +0 -353
- package/src/core/commands/context/note.md +0 -380
- package/src/core/commands/council.md +0 -592
- package/src/core/commands/debt.md +0 -491
- package/src/core/commands/deploy.md +0 -864
- package/src/core/commands/deps.md +0 -728
- package/src/core/commands/diagnose.md +0 -404
- package/src/core/commands/docs.md +0 -469
- package/src/core/commands/epic/edit.md +0 -213
- package/src/core/commands/epic/list.md +0 -190
- package/src/core/commands/epic/view.md +0 -267
- package/src/core/commands/epic.md +0 -477
- package/src/core/commands/export.md +0 -238
- package/src/core/commands/feedback.md +0 -603
- package/src/core/commands/handoff.md +0 -386
- package/src/core/commands/help.md +0 -194
- package/src/core/commands/ideate/brief.md +0 -363
- package/src/core/commands/ideate/discover.md +0 -399
- package/src/core/commands/ideate/features.md +0 -497
- package/src/core/commands/ideate/history.md +0 -403
- package/src/core/commands/ideate/new.md +0 -900
- package/src/core/commands/impact.md +0 -407
- package/src/core/commands/install.md +0 -529
- package/src/core/commands/learn/explain.md +0 -118
- package/src/core/commands/learn/glossary.md +0 -135
- package/src/core/commands/learn/patterns.md +0 -138
- package/src/core/commands/learn/tour.md +0 -126
- package/src/core/commands/maintain.md +0 -558
- package/src/core/commands/metrics.md +0 -844
- package/src/core/commands/migrate/codemods.md +0 -151
- package/src/core/commands/migrate/plan.md +0 -131
- package/src/core/commands/migrate/scan.md +0 -114
- package/src/core/commands/migrate/validate.md +0 -119
- package/src/core/commands/multi-expert.md +0 -447
- package/src/core/commands/packages.md +0 -535
- package/src/core/commands/pr.md +0 -337
- package/src/core/commands/readme-sync.md +0 -329
- package/src/core/commands/research/analyze.md +0 -798
- package/src/core/commands/research/ask.md +0 -864
- package/src/core/commands/research/import.md +0 -1025
- package/src/core/commands/research/list.md +0 -273
- package/src/core/commands/research/synthesize.md +0 -928
- package/src/core/commands/research/view.md +0 -323
- package/src/core/commands/retro.md +0 -795
- package/src/core/commands/review.md +0 -694
- package/src/core/commands/rlm.md +0 -446
- package/src/core/commands/roadmap/analyze.md +0 -400
- package/src/core/commands/rpi.md +0 -633
- package/src/core/commands/seo/audit.md +0 -444
- package/src/core/commands/seo/competitor.md +0 -174
- package/src/core/commands/seo/content.md +0 -107
- package/src/core/commands/seo/geo.md +0 -229
- package/src/core/commands/seo/hreflang.md +0 -140
- package/src/core/commands/seo/images.md +0 -96
- package/src/core/commands/seo/page.md +0 -198
- package/src/core/commands/seo/plan.md +0 -163
- package/src/core/commands/seo/programmatic.md +0 -131
- package/src/core/commands/seo/references/cwv-thresholds.md +0 -64
- package/src/core/commands/seo/references/eeat-framework.md +0 -110
- package/src/core/commands/seo/references/quality-gates.md +0 -91
- package/src/core/commands/seo/references/schema-types.md +0 -102
- package/src/core/commands/seo/schema.md +0 -183
- package/src/core/commands/seo/sitemap.md +0 -97
- package/src/core/commands/seo/technical.md +0 -100
- package/src/core/commands/seo.md +0 -107
- package/src/core/commands/session/cleanup.md +0 -452
- package/src/core/commands/session/end.md +0 -865
- package/src/core/commands/session/history.md +0 -293
- package/src/core/commands/session/init.md +0 -210
- package/src/core/commands/session/new.md +0 -827
- package/src/core/commands/session/resume.md +0 -291
- package/src/core/commands/session/spawn.md +0 -205
- package/src/core/commands/session/status.md +0 -274
- package/src/core/commands/skill/list.md +0 -139
- package/src/core/commands/skill/recommend.md +0 -216
- package/src/core/commands/sprint.md +0 -714
- package/src/core/commands/status/undo.md +0 -191
- package/src/core/commands/status.md +0 -423
- package/src/core/commands/story/edit.md +0 -204
- package/src/core/commands/story/list.md +0 -199
- package/src/core/commands/story/view.md +0 -312
- package/src/core/commands/story-validate.md +0 -491
- package/src/core/commands/story.md +0 -465
- package/src/core/commands/tdd-next.md +0 -238
- package/src/core/commands/tdd.md +0 -211
- package/src/core/commands/team/guide.md +0 -688
- package/src/core/commands/team/list.md +0 -59
- package/src/core/commands/team/start.md +0 -130
- package/src/core/commands/team/status.md +0 -66
- package/src/core/commands/team/stop.md +0 -78
- package/src/core/commands/template.md +0 -644
- package/src/core/commands/tests.md +0 -731
- package/src/core/commands/update.md +0 -591
- package/src/core/commands/validate-expertise.md +0 -305
- package/src/core/commands/velocity.md +0 -630
- package/src/core/commands/verify.md +0 -534
- package/src/core/commands/whats-new.md +0 -201
- package/src/core/commands/workflow.md +0 -449
- package/src/core/council/sessions/.gitkeep +0 -0
- package/src/core/council/shared_reasoning.template.md +0 -106
- package/src/core/experts/README.md +0 -236
- package/src/core/experts/_core-expertise.yaml +0 -105
- package/src/core/experts/accessibility/expertise.yaml +0 -115
- package/src/core/experts/accessibility/question.md +0 -41
- package/src/core/experts/accessibility/self-improve.md +0 -45
- package/src/core/experts/accessibility/workflow.md +0 -59
- package/src/core/experts/adr-writer/expertise.yaml +0 -138
- package/src/core/experts/adr-writer/question.md +0 -56
- package/src/core/experts/adr-writer/self-improve.md +0 -106
- package/src/core/experts/adr-writer/workflow.md +0 -184
- package/src/core/experts/analytics/expertise.yaml +0 -119
- package/src/core/experts/analytics/question.md +0 -74
- package/src/core/experts/analytics/self-improve.md +0 -163
- package/src/core/experts/analytics/workflow.md +0 -272
- package/src/core/experts/api/expertise.yaml +0 -124
- package/src/core/experts/api/question.md +0 -74
- package/src/core/experts/api/self-improve.md +0 -122
- package/src/core/experts/api/workflow.md +0 -248
- package/src/core/experts/ci/expertise.yaml +0 -106
- package/src/core/experts/ci/question.md +0 -69
- package/src/core/experts/ci/self-improve.md +0 -100
- package/src/core/experts/ci/workflow.md +0 -145
- package/src/core/experts/codebase-query/expertise.yaml +0 -121
- package/src/core/experts/codebase-query/question.md +0 -73
- package/src/core/experts/codebase-query/self-improve.md +0 -105
- package/src/core/experts/compliance/expertise.yaml +0 -101
- package/src/core/experts/compliance/question.md +0 -56
- package/src/core/experts/compliance/self-improve.md +0 -106
- package/src/core/experts/compliance/workflow.md +0 -184
- package/src/core/experts/database/expertise.yaml +0 -109
- package/src/core/experts/database/question.md +0 -74
- package/src/core/experts/database/self-improve.md +0 -121
- package/src/core/experts/database/workflow.md +0 -234
- package/src/core/experts/datamigration/expertise.yaml +0 -141
- package/src/core/experts/datamigration/question.md +0 -56
- package/src/core/experts/datamigration/self-improve.md +0 -106
- package/src/core/experts/datamigration/workflow.md +0 -184
- package/src/core/experts/design/expertise.yaml +0 -116
- package/src/core/experts/design/question.md +0 -56
- package/src/core/experts/design/self-improve.md +0 -106
- package/src/core/experts/design/workflow.md +0 -184
- package/src/core/experts/devops/expertise.yaml +0 -116
- package/src/core/experts/devops/question.md +0 -68
- package/src/core/experts/devops/self-improve.md +0 -102
- package/src/core/experts/devops/workflow.md +0 -142
- package/src/core/experts/documentation/expertise.yaml +0 -126
- package/src/core/experts/documentation/question.md +0 -41
- package/src/core/experts/documentation/self-improve.md +0 -45
- package/src/core/experts/documentation/workflow.md +0 -55
- package/src/core/experts/epic-planner/expertise.yaml +0 -144
- package/src/core/experts/epic-planner/question.md +0 -56
- package/src/core/experts/epic-planner/self-improve.md +0 -106
- package/src/core/experts/epic-planner/workflow.md +0 -184
- package/src/core/experts/integrations/expertise.yaml +0 -113
- package/src/core/experts/integrations/question.md +0 -74
- package/src/core/experts/integrations/self-improve.md +0 -151
- package/src/core/experts/integrations/workflow.md +0 -246
- package/src/core/experts/mentor/expertise.yaml +0 -125
- package/src/core/experts/mentor/question.md +0 -56
- package/src/core/experts/mentor/self-improve.md +0 -106
- package/src/core/experts/mentor/workflow.md +0 -184
- package/src/core/experts/mobile/expertise.yaml +0 -136
- package/src/core/experts/mobile/question.md +0 -72
- package/src/core/experts/mobile/self-improve.md +0 -140
- package/src/core/experts/mobile/workflow.md +0 -240
- package/src/core/experts/monitoring/expertise.yaml +0 -132
- package/src/core/experts/monitoring/question.md +0 -76
- package/src/core/experts/monitoring/self-improve.md +0 -150
- package/src/core/experts/monitoring/workflow.md +0 -264
- package/src/core/experts/performance/expertise.yaml +0 -68
- package/src/core/experts/performance/question.md +0 -41
- package/src/core/experts/performance/self-improve.md +0 -45
- package/src/core/experts/performance/workflow.md +0 -61
- package/src/core/experts/product/expertise.yaml +0 -143
- package/src/core/experts/product/question.md +0 -56
- package/src/core/experts/product/self-improve.md +0 -106
- package/src/core/experts/product/workflow.md +0 -184
- package/src/core/experts/qa/expertise.yaml +0 -110
- package/src/core/experts/qa/question.md +0 -56
- package/src/core/experts/qa/self-improve.md +0 -106
- package/src/core/experts/qa/workflow.md +0 -184
- package/src/core/experts/readme-updater/expertise.yaml +0 -141
- package/src/core/experts/readme-updater/question.md +0 -56
- package/src/core/experts/readme-updater/self-improve.md +0 -106
- package/src/core/experts/readme-updater/workflow.md +0 -184
- package/src/core/experts/refactor/expertise.yaml +0 -135
- package/src/core/experts/refactor/question.md +0 -41
- package/src/core/experts/refactor/self-improve.md +0 -45
- package/src/core/experts/refactor/workflow.md +0 -57
- package/src/core/experts/research/expertise.yaml +0 -143
- package/src/core/experts/research/question.md +0 -56
- package/src/core/experts/research/self-improve.md +0 -106
- package/src/core/experts/research/workflow.md +0 -184
- package/src/core/experts/security/expertise.yaml +0 -117
- package/src/core/experts/security/question.md +0 -77
- package/src/core/experts/security/self-improve.md +0 -102
- package/src/core/experts/security/workflow.md +0 -152
- package/src/core/experts/templates/expertise-template.yaml +0 -67
- package/src/core/experts/templates/question-template.md +0 -56
- package/src/core/experts/templates/self-improve-template.md +0 -106
- package/src/core/experts/templates/workflow-template.md +0 -184
- package/src/core/experts/testing/expertise.yaml +0 -112
- package/src/core/experts/testing/question.md +0 -68
- package/src/core/experts/testing/self-improve.md +0 -102
- package/src/core/experts/testing/workflow.md +0 -143
- package/src/core/experts/ui/expertise.yaml +0 -133
- package/src/core/experts/ui/question.md +0 -74
- package/src/core/experts/ui/self-improve.md +0 -122
- package/src/core/experts/ui/workflow.md +0 -262
- package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +0 -424
- package/src/core/knowledge/ads/ad-optimization-logic.md +0 -590
- package/src/core/knowledge/ads/ad-technical-specifications.md +0 -385
- package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +0 -506
- package/src/core/knowledge/ads/paid-advertising-research-2026.md +0 -445
- package/src/core/profiles/COMPARISON.md +0 -170
- package/src/core/profiles/README.md +0 -178
- package/src/core/profiles/claude-code.yaml +0 -111
- package/src/core/profiles/codex.yaml +0 -103
- package/src/core/profiles/cursor.yaml +0 -134
- package/src/core/profiles/examples.js +0 -250
- package/src/core/profiles/loader.js +0 -235
- package/src/core/profiles/windsurf.yaml +0 -159
- package/src/core/skills/_learnings/README.md +0 -91
- package/src/core/skills/_learnings/_template.yaml +0 -106
- package/src/core/skills/_learnings/code-review.yaml +0 -118
- package/src/core/skills/_learnings/commit.yaml +0 -69
- package/src/core/skills/_learnings/story-writer.yaml +0 -71
- package/src/core/teams/backend.json +0 -41
- package/src/core/teams/builder-validator.json +0 -51
- package/src/core/teams/code-review.json +0 -41
- package/src/core/teams/frontend.json +0 -41
- package/src/core/teams/fullstack.json +0 -41
- package/src/core/teams/logic-audit.json +0 -53
- package/src/core/teams/perf-audit.json +0 -71
- package/src/core/teams/qa.json +0 -41
- package/src/core/teams/security-audit.json +0 -71
- package/src/core/teams/solo.json +0 -35
- package/src/core/teams/test-audit.json +0 -71
- package/src/core/templates/CONTEXT.md.example +0 -49
- package/src/core/templates/README-template.md +0 -16
- package/src/core/templates/adr-template.md +0 -28
- package/src/core/templates/agent-coordination-pattern.md +0 -38
- package/src/core/templates/agent-profile-template.md +0 -51
- package/src/core/templates/agileflow-metadata.json +0 -150
- package/src/core/templates/browser-qa-spec.yaml +0 -94
- package/src/core/templates/ci-workflow.yml +0 -74
- package/src/core/templates/claude-settings.advanced.example.json +0 -75
- package/src/core/templates/claude-settings.example.json +0 -26
- package/src/core/templates/command-documentation.md +0 -187
- package/src/core/templates/command-prerequisites.yaml +0 -169
- package/src/core/templates/comms-note-template.md +0 -24
- package/src/core/templates/damage-control-patterns.yaml +0 -243
- package/src/core/templates/environment.json +0 -18
- package/src/core/templates/epic-template.md +0 -27
- package/src/core/templates/plan-template.md +0 -125
- package/src/core/templates/preserve-rules-common.md +0 -107
- package/src/core/templates/preserve-rules.json +0 -42
- package/src/core/templates/proactive-action-spec.md +0 -29
- package/src/core/templates/product-brief.md +0 -136
- package/src/core/templates/quality-gate-priorities.md +0 -34
- package/src/core/templates/research-template.md +0 -44
- package/src/core/templates/session-harness-protocol.md +0 -128
- package/src/core/templates/session-state.json +0 -56
- package/src/core/templates/story-lifecycle.md +0 -213
- package/src/core/templates/story-template.md +0 -92
- package/src/core/templates/tdd-test-template.js +0 -241
- package/src/core/templates/worktrees-guide.md +0 -231
- package/tools/agileflow-npx.js +0 -52
- package/tools/cli/agileflow-cli.js +0 -72
- package/tools/cli/commands/config.js +0 -285
- package/tools/cli/commands/doctor.js +0 -496
- package/tools/cli/commands/list.js +0 -385
- package/tools/cli/commands/session.js +0 -1176
- package/tools/cli/commands/setup.js +0 -255
- package/tools/cli/commands/status.js +0 -101
- package/tools/cli/commands/tui.js +0 -56
- package/tools/cli/commands/uninstall.js +0 -155
- package/tools/cli/commands/update.js +0 -299
- package/tools/cli/installers/core/installer.js +0 -892
- package/tools/cli/installers/ide/_base-ide.js +0 -518
- package/tools/cli/installers/ide/_interface.js +0 -238
- package/tools/cli/installers/ide/claude-code.js +0 -432
- package/tools/cli/installers/ide/codex.js +0 -426
- package/tools/cli/installers/ide/cursor.js +0 -217
- package/tools/cli/installers/ide/manager.js +0 -222
- package/tools/cli/installers/ide/windsurf.js +0 -282
- package/tools/cli/lib/command-context.js +0 -382
- package/tools/cli/lib/config-manager.js +0 -446
- package/tools/cli/lib/content-injector.js +0 -969
- package/tools/cli/lib/content-transformer.js +0 -496
- package/tools/cli/lib/docs-setup.js +0 -464
- package/tools/cli/lib/error-handler.js +0 -165
- package/tools/cli/lib/ide-error-factory.js +0 -421
- package/tools/cli/lib/ide-errors.js +0 -367
- package/tools/cli/lib/ide-generator.js +0 -357
- package/tools/cli/lib/ide-health-monitor.js +0 -364
- package/tools/cli/lib/ide-registry.js +0 -297
- package/tools/cli/lib/npm-utils.js +0 -103
- package/tools/cli/lib/self-update.js +0 -148
- package/tools/cli/lib/ui.js +0 -211
- package/tools/cli/lib/utils.js +0 -87
- package/tools/cli/lib/validation-middleware.js +0 -491
- package/tools/cli/lib/version-checker.js +0 -95
- package/tools/postinstall.js +0 -190
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code settings.json writer.
|
|
3
|
+
*
|
|
4
|
+
* When the target IDE is `claude-code`, the installer registers our 6
|
|
5
|
+
* hook entry points in `.claude/settings.json` so Claude Code actually
|
|
6
|
+
* invokes them at runtime. We use the unified `npx --no-install
|
|
7
|
+
* agileflow hook <event> [--matcher <m>]` command so the path resolves
|
|
8
|
+
* regardless of how the package is installed.
|
|
9
|
+
*
|
|
10
|
+
* The writer is **non-destructive**: it merges with any existing
|
|
11
|
+
* settings.json. Only AgileFlow-owned hook entries (identified by the
|
|
12
|
+
* `agileflow hook` substring in their command) are replaced; the
|
|
13
|
+
* user's other hook registrations and non-hook fields (permissions,
|
|
14
|
+
* env, etc.) are preserved.
|
|
15
|
+
*
|
|
16
|
+
* On a non-claude-code switch, `removeManagedHooks` strips our entries
|
|
17
|
+
* but leaves the rest of the file alone.
|
|
18
|
+
*/
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
const HOOK_COMMAND_MARKER = 'agileflow hook';
|
|
23
|
+
const HOOK_TIMEOUT_SECONDS = 30;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The 6 hook registrations we own. Each is `{ event, matcher?, command }`.
|
|
27
|
+
* The `command` is what gets baked into settings.json.
|
|
28
|
+
*/
|
|
29
|
+
const MANAGED_HOOKS = [
|
|
30
|
+
{ event: 'SessionStart', matcher: null, command: 'npx --no-install agileflow hook SessionStart' },
|
|
31
|
+
{ event: 'PreToolUse', matcher: 'Bash', command: 'npx --no-install agileflow hook PreToolUse --matcher Bash' },
|
|
32
|
+
{ event: 'PreToolUse', matcher: 'Edit', command: 'npx --no-install agileflow hook PreToolUse --matcher Edit' },
|
|
33
|
+
{ event: 'PreToolUse', matcher: 'Write', command: 'npx --no-install agileflow hook PreToolUse --matcher Write' },
|
|
34
|
+
{ event: 'PreCompact', matcher: null, command: 'npx --no-install agileflow hook PreCompact' },
|
|
35
|
+
{ event: 'Stop', matcher: null, command: 'npx --no-install agileflow hook Stop' },
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const MANAGED_EVENTS = new Set(MANAGED_HOOKS.map((h) => h.event));
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Detect whether a settings.json hook entry belongs to AgileFlow.
|
|
42
|
+
* @param {*} entry
|
|
43
|
+
*/
|
|
44
|
+
function isAgileflowEntry(entry) {
|
|
45
|
+
if (!entry || typeof entry !== 'object' || !Array.isArray(entry.hooks)) return false;
|
|
46
|
+
return entry.hooks.some(
|
|
47
|
+
(h) =>
|
|
48
|
+
h &&
|
|
49
|
+
typeof h === 'object' &&
|
|
50
|
+
h.type === 'command' &&
|
|
51
|
+
typeof h.command === 'string' &&
|
|
52
|
+
h.command.includes(HOOK_COMMAND_MARKER),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build a fresh entry for one MANAGED_HOOKS row.
|
|
58
|
+
* @param {{ matcher: string|null, command: string }} hook
|
|
59
|
+
*/
|
|
60
|
+
function buildEntry({ matcher, command }) {
|
|
61
|
+
/** @type {{ matcher?: string, hooks: object[] }} */
|
|
62
|
+
const out = {
|
|
63
|
+
hooks: [
|
|
64
|
+
{ type: 'command', command, timeout: HOOK_TIMEOUT_SECONDS },
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
if (matcher) out.matcher = matcher;
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Read existing settings.json (or {} if absent / malformed).
|
|
73
|
+
* @param {string} settingsPath
|
|
74
|
+
* @returns {Promise<object>}
|
|
75
|
+
*/
|
|
76
|
+
async function readExisting(settingsPath) {
|
|
77
|
+
try {
|
|
78
|
+
const raw = await fs.promises.readFile(settingsPath, 'utf8');
|
|
79
|
+
const parsed = JSON.parse(raw);
|
|
80
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return {};
|
|
81
|
+
return parsed;
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err.code === 'ENOENT') return {};
|
|
84
|
+
if (err instanceof SyntaxError) return {};
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Atomically write the merged settings.
|
|
91
|
+
* @param {string} settingsPath
|
|
92
|
+
* @param {object} settings
|
|
93
|
+
*/
|
|
94
|
+
async function writeMerged(settingsPath, settings) {
|
|
95
|
+
await fs.promises.mkdir(path.dirname(settingsPath), { recursive: true });
|
|
96
|
+
const tmp = path.join(
|
|
97
|
+
path.dirname(settingsPath),
|
|
98
|
+
`.${path.basename(settingsPath)}.tmp-${process.pid}-${Math.random().toString(36).slice(2, 10)}`,
|
|
99
|
+
);
|
|
100
|
+
const text = JSON.stringify(settings, null, 2) + '\n';
|
|
101
|
+
try {
|
|
102
|
+
await fs.promises.writeFile(tmp, text, 'utf8');
|
|
103
|
+
await fs.promises.rename(tmp, settingsPath);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
try {
|
|
106
|
+
await fs.promises.unlink(tmp);
|
|
107
|
+
} catch {
|
|
108
|
+
/* swallow */
|
|
109
|
+
}
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Compute the merged settings: drop any existing AgileFlow entries from
|
|
116
|
+
* the events we manage, append our fresh ones in the canonical order,
|
|
117
|
+
* leave everything else alone.
|
|
118
|
+
*
|
|
119
|
+
* @param {object} existing
|
|
120
|
+
* @returns {object}
|
|
121
|
+
*/
|
|
122
|
+
function mergeManagedHooks(existing) {
|
|
123
|
+
const next = { ...existing };
|
|
124
|
+
// Reject array-shaped `hooks`: spreading an array into a plain object
|
|
125
|
+
// produces numeric-keyed garbage. Treat it as missing instead.
|
|
126
|
+
const baseHooks =
|
|
127
|
+
existing.hooks &&
|
|
128
|
+
typeof existing.hooks === 'object' &&
|
|
129
|
+
!Array.isArray(existing.hooks)
|
|
130
|
+
? existing.hooks
|
|
131
|
+
: {};
|
|
132
|
+
const hooks = { ...baseHooks };
|
|
133
|
+
|
|
134
|
+
for (const event of MANAGED_EVENTS) {
|
|
135
|
+
const prior = Array.isArray(hooks[event]) ? hooks[event] : [];
|
|
136
|
+
// Strip our previous registrations, keep user's other entries.
|
|
137
|
+
const userEntries = prior.filter((e) => !isAgileflowEntry(e));
|
|
138
|
+
const ours = MANAGED_HOOKS.filter((h) => h.event === event).map(buildEntry);
|
|
139
|
+
hooks[event] = [...ours, ...userEntries];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
next.hooks = hooks;
|
|
143
|
+
return next;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Compute the unmanaged settings: strip AgileFlow entries from every
|
|
148
|
+
* event we manage. Used when switching to a non-claude-code IDE.
|
|
149
|
+
*
|
|
150
|
+
* @param {object} existing
|
|
151
|
+
* @returns {object}
|
|
152
|
+
*/
|
|
153
|
+
function unmanageHooks(existing) {
|
|
154
|
+
const next = { ...existing };
|
|
155
|
+
if (
|
|
156
|
+
!existing.hooks ||
|
|
157
|
+
typeof existing.hooks !== 'object' ||
|
|
158
|
+
Array.isArray(existing.hooks)
|
|
159
|
+
) {
|
|
160
|
+
return next;
|
|
161
|
+
}
|
|
162
|
+
const hooks = { ...existing.hooks };
|
|
163
|
+
for (const event of MANAGED_EVENTS) {
|
|
164
|
+
if (!Array.isArray(hooks[event])) continue;
|
|
165
|
+
const userEntries = hooks[event].filter((e) => !isAgileflowEntry(e));
|
|
166
|
+
if (userEntries.length === 0) {
|
|
167
|
+
delete hooks[event];
|
|
168
|
+
} else {
|
|
169
|
+
hooks[event] = userEntries;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// If hooks ended up with no keys, drop the field entirely.
|
|
173
|
+
if (Object.keys(hooks).length === 0) {
|
|
174
|
+
delete next.hooks;
|
|
175
|
+
} else {
|
|
176
|
+
next.hooks = hooks;
|
|
177
|
+
}
|
|
178
|
+
return next;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Register the 6 AgileFlow hooks in `<projectRoot>/.claude/settings.json`.
|
|
183
|
+
*
|
|
184
|
+
* @param {string} projectRoot
|
|
185
|
+
* @returns {Promise<string>} absolute path of the written settings file
|
|
186
|
+
*/
|
|
187
|
+
async function writeClaudeCodeSettings(projectRoot) {
|
|
188
|
+
const settingsPath = path.join(projectRoot, '.claude', 'settings.json');
|
|
189
|
+
const existing = await readExisting(settingsPath);
|
|
190
|
+
const merged = mergeManagedHooks(existing);
|
|
191
|
+
await writeMerged(settingsPath, merged);
|
|
192
|
+
return settingsPath;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Strip AgileFlow hook registrations from settings.json. If the file
|
|
197
|
+
* ends up empty (no hooks AND no other fields), it's removed; if it
|
|
198
|
+
* still has content, the cleaned version is written back.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} projectRoot
|
|
201
|
+
* @returns {Promise<{ removed: boolean, settingsPath: string|null }>}
|
|
202
|
+
*/
|
|
203
|
+
async function removeClaudeCodeSettings(projectRoot) {
|
|
204
|
+
const settingsPath = path.join(projectRoot, '.claude', 'settings.json');
|
|
205
|
+
// readExisting already converts ENOENT and SyntaxError to {} — any
|
|
206
|
+
// exception here means a real filesystem problem (EACCES / EIO).
|
|
207
|
+
// Do NOT swallow: a silent success would lie about successfully
|
|
208
|
+
// removing entries that are still in an unreadable file.
|
|
209
|
+
const existing = await readExisting(settingsPath);
|
|
210
|
+
const next = unmanageHooks(existing);
|
|
211
|
+
if (Object.keys(next).length === 0) {
|
|
212
|
+
try {
|
|
213
|
+
await fs.promises.unlink(settingsPath);
|
|
214
|
+
return { removed: true, settingsPath };
|
|
215
|
+
} catch (err) {
|
|
216
|
+
if (err.code === 'ENOENT') return { removed: false, settingsPath: null };
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
await writeMerged(settingsPath, next);
|
|
221
|
+
return { removed: false, settingsPath };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
module.exports = {
|
|
225
|
+
writeClaudeCodeSettings,
|
|
226
|
+
removeClaudeCodeSettings,
|
|
227
|
+
mergeManagedHooks,
|
|
228
|
+
unmanageHooks,
|
|
229
|
+
isAgileflowEntry,
|
|
230
|
+
MANAGED_HOOKS,
|
|
231
|
+
MANAGED_EVENTS,
|
|
232
|
+
HOOK_COMMAND_MARKER,
|
|
233
|
+
HOOK_TIMEOUT_SECONDS,
|
|
234
|
+
};
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code skill mirror.
|
|
3
|
+
*
|
|
4
|
+
* Plugin skills are sourced under `apps/cli/content/plugins/<id>/skills/<skill-id>/`
|
|
5
|
+
* and copied into `.agileflow/plugins/<id>/skills/<skill-id>/` by the
|
|
6
|
+
* sync engine. But Claude Code discovers skills from `.claude/skills/<skill-id>/`,
|
|
7
|
+
* so this module mirrors enabled plugin skills to that canonical
|
|
8
|
+
* location and prunes orphaned skills when plugins are disabled.
|
|
9
|
+
*
|
|
10
|
+
* We use copy (not symlink) for portability — Windows symlink behavior
|
|
11
|
+
* is inconsistent and Claude Code itself runs there. The duplication
|
|
12
|
+
* cost is negligible at v4-alpha skill counts.
|
|
13
|
+
*/
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {import('../plugins/registry.js').PluginManifest} PluginManifest
|
|
19
|
+
*
|
|
20
|
+
* @typedef {Object} MirrorResult
|
|
21
|
+
* @property {string[]} mirrored - skill ids written to .claude/skills/
|
|
22
|
+
* @property {string[]} pruned - skill ids removed from .claude/skills/ (orphans)
|
|
23
|
+
* @property {Array<{ skillId: string, error: string }>} skipped - skills whose source was missing
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Recursively copy a directory tree.
|
|
28
|
+
* @param {string} src
|
|
29
|
+
* @param {string} dest
|
|
30
|
+
*/
|
|
31
|
+
async function copyDir(src, dest) {
|
|
32
|
+
// Read the source listing FIRST. If src is missing (ENOENT), the
|
|
33
|
+
// error propagates BEFORE we create dest, so a missing source can't
|
|
34
|
+
// leave behind an empty destination dir for the caller to mistake
|
|
35
|
+
// for a successful copy.
|
|
36
|
+
const entries = await fs.promises.readdir(src, { withFileTypes: true });
|
|
37
|
+
await fs.promises.mkdir(dest, { recursive: true });
|
|
38
|
+
for (const e of entries) {
|
|
39
|
+
const s = path.join(src, e.name);
|
|
40
|
+
const d = path.join(dest, e.name);
|
|
41
|
+
if (e.isDirectory()) {
|
|
42
|
+
await copyDir(s, d);
|
|
43
|
+
} else if (e.isFile()) {
|
|
44
|
+
await fs.promises.copyFile(s, d);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Recursively remove a directory tree (no-op when missing).
|
|
51
|
+
* @param {string} dir
|
|
52
|
+
*/
|
|
53
|
+
async function rmDir(dir) {
|
|
54
|
+
await fs.promises.rm(dir, { recursive: true, force: true });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Collect every skill declared by an enabled plugin manifest. Returns
|
|
59
|
+
* a list of `{ skillId, sourceDir }` where sourceDir is absolute.
|
|
60
|
+
*
|
|
61
|
+
* @param {PluginManifest[]} orderedPlugins
|
|
62
|
+
* @returns {Array<{ skillId: string, sourceDir: string }>}
|
|
63
|
+
*/
|
|
64
|
+
function collectPluginSkills(orderedPlugins) {
|
|
65
|
+
/** @type {Array<{ skillId: string, sourceDir: string }>} */
|
|
66
|
+
const out = [];
|
|
67
|
+
for (const plugin of orderedPlugins) {
|
|
68
|
+
const skills =
|
|
69
|
+
plugin.provides && Array.isArray(plugin.provides.skills)
|
|
70
|
+
? plugin.provides.skills
|
|
71
|
+
: [];
|
|
72
|
+
for (const s of skills) {
|
|
73
|
+
// Reject missing-or-empty id/dir. An empty `dir: ""` would
|
|
74
|
+
// pass `typeof === 'string'` but path.join silently treats it as
|
|
75
|
+
// the plugin root, which is never what the author intended.
|
|
76
|
+
if (
|
|
77
|
+
!s ||
|
|
78
|
+
typeof s.id !== 'string' ||
|
|
79
|
+
!s.id ||
|
|
80
|
+
typeof s.dir !== 'string' ||
|
|
81
|
+
!s.dir
|
|
82
|
+
) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
out.push({
|
|
86
|
+
skillId: s.id,
|
|
87
|
+
sourceDir: path.join(plugin.dir, s.dir),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Mirror enabled plugin skills into `<projectRoot>/.claude/skills/<skill-id>/`
|
|
96
|
+
* and remove any `.claude/skills/<id>/` whose id is not in the current
|
|
97
|
+
* enabled set.
|
|
98
|
+
*
|
|
99
|
+
* Only AgileFlow-tracked skills are pruned: a skill is "tracked" iff
|
|
100
|
+
* its dir contains a `SKILL.md` whose first line is `---` AND its name
|
|
101
|
+
* appears in any plugin's `provides.skills` (i.e., we recognize it).
|
|
102
|
+
* To stay safe, we limit pruning to skills we've seen previously by
|
|
103
|
+
* recording the install set in the file index — but for v4-alpha
|
|
104
|
+
* simplicity, we prune every dir under `.claude/skills/` whose name
|
|
105
|
+
* matches an `agileflow-*` convention OR is in the previously-mirrored
|
|
106
|
+
* set on disk. Unknown user-placed skill dirs without that prefix are
|
|
107
|
+
* left alone.
|
|
108
|
+
*
|
|
109
|
+
* @param {PluginManifest[]} orderedPlugins
|
|
110
|
+
* @param {string} projectRoot
|
|
111
|
+
* @returns {Promise<MirrorResult>}
|
|
112
|
+
*/
|
|
113
|
+
async function mirrorClaudeCodeSkills(orderedPlugins, projectRoot) {
|
|
114
|
+
const claudeSkills = path.join(projectRoot, '.claude', 'skills');
|
|
115
|
+
await fs.promises.mkdir(claudeSkills, { recursive: true });
|
|
116
|
+
|
|
117
|
+
const want = collectPluginSkills(orderedPlugins);
|
|
118
|
+
const wantIds = new Set(want.map((w) => w.skillId));
|
|
119
|
+
|
|
120
|
+
/** @type {string[]} */
|
|
121
|
+
const mirrored = [];
|
|
122
|
+
/** @type {Array<{ skillId: string, error: string }>} */
|
|
123
|
+
const skipped = [];
|
|
124
|
+
for (const { skillId, sourceDir } of want) {
|
|
125
|
+
const dest = path.join(claudeSkills, skillId);
|
|
126
|
+
try {
|
|
127
|
+
// Replace the destination wholesale so removed files in source
|
|
128
|
+
// don't linger in the user's .claude/skills/.
|
|
129
|
+
await rmDir(dest);
|
|
130
|
+
await copyDir(sourceDir, dest);
|
|
131
|
+
mirrored.push(skillId);
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// A missing source dir (ENOENT) shouldn't crash the entire
|
|
134
|
+
// install — log and continue so other skills still mirror. A
|
|
135
|
+
// permission error or unrelated failure still propagates.
|
|
136
|
+
if (err && err.code === 'ENOENT') {
|
|
137
|
+
skipped.push({
|
|
138
|
+
skillId,
|
|
139
|
+
error: `source not found: ${sourceDir}`,
|
|
140
|
+
});
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
throw err;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** @type {string[]} */
|
|
148
|
+
const pruned = [];
|
|
149
|
+
let entries;
|
|
150
|
+
try {
|
|
151
|
+
entries = await fs.promises.readdir(claudeSkills, { withFileTypes: true });
|
|
152
|
+
} catch (err) {
|
|
153
|
+
if (err.code === 'ENOENT') return { mirrored, pruned };
|
|
154
|
+
throw err;
|
|
155
|
+
}
|
|
156
|
+
for (const e of entries) {
|
|
157
|
+
if (!e.isDirectory()) continue;
|
|
158
|
+
if (wantIds.has(e.name)) continue;
|
|
159
|
+
// Only prune skills that LOOK like ours: agileflow-* prefix. This
|
|
160
|
+
// avoids blasting a user-placed third-party skill whose id we
|
|
161
|
+
// don't manage. A dedicated prune-from-index approach can replace
|
|
162
|
+
// this heuristic in a later phase.
|
|
163
|
+
if (!e.name.startsWith('agileflow-')) continue;
|
|
164
|
+
await rmDir(path.join(claudeSkills, e.name));
|
|
165
|
+
pruned.push(e.name);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return { mirrored, pruned, skipped };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove all AgileFlow-mirrored skills from `.claude/skills/`. Used
|
|
173
|
+
* when switching to a non-skill IDE.
|
|
174
|
+
*
|
|
175
|
+
* @param {string} projectRoot
|
|
176
|
+
* @returns {Promise<string[]>} ids that were removed
|
|
177
|
+
*/
|
|
178
|
+
async function unmirrorClaudeCodeSkills(projectRoot) {
|
|
179
|
+
const claudeSkills = path.join(projectRoot, '.claude', 'skills');
|
|
180
|
+
/** @type {string[]} */
|
|
181
|
+
const removed = [];
|
|
182
|
+
let entries;
|
|
183
|
+
try {
|
|
184
|
+
entries = await fs.promises.readdir(claudeSkills, { withFileTypes: true });
|
|
185
|
+
} catch (err) {
|
|
186
|
+
if (err.code === 'ENOENT') return removed;
|
|
187
|
+
throw err;
|
|
188
|
+
}
|
|
189
|
+
for (const e of entries) {
|
|
190
|
+
if (!e.isDirectory()) continue;
|
|
191
|
+
if (!e.name.startsWith('agileflow-')) continue;
|
|
192
|
+
await rmDir(path.join(claudeSkills, e.name));
|
|
193
|
+
removed.push(e.name);
|
|
194
|
+
}
|
|
195
|
+
return removed;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = {
|
|
199
|
+
mirrorClaudeCodeSkills,
|
|
200
|
+
unmirrorClaudeCodeSkills,
|
|
201
|
+
collectPluginSkills,
|
|
202
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File index read/write for the sync engine.
|
|
3
|
+
*
|
|
4
|
+
* The file index (`_cfg/files.json`) records the SHA256 hash of every
|
|
5
|
+
* file the installer has written into the user's project and whether
|
|
6
|
+
* the user has since diverged from that baseline. The sync engine uses
|
|
7
|
+
* the index to decide whether a destination file is safe to overwrite,
|
|
8
|
+
* should be preserved, or should trigger a stash.
|
|
9
|
+
*
|
|
10
|
+
* Schema (version 1):
|
|
11
|
+
* {
|
|
12
|
+
* schema: 1,
|
|
13
|
+
* generated_at: <ISO string>,
|
|
14
|
+
* version: <CLI version that wrote this index>,
|
|
15
|
+
* files: {
|
|
16
|
+
* "<posix-relative-path>": {
|
|
17
|
+
* sha256: "<hex>",
|
|
18
|
+
* protected: <bool>
|
|
19
|
+
* },
|
|
20
|
+
* ...
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
|
|
27
|
+
const SCHEMA_VERSION = 1;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {{ sha256: string, protected: boolean }} FileRecord
|
|
31
|
+
* @typedef {{ schema: 1, generated_at: string, version: string, files: Record<string, FileRecord> }} FileIndex
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build an empty index. Caller fills `files` as sync proceeds.
|
|
36
|
+
* @param {string} cliVersion
|
|
37
|
+
* @returns {FileIndex}
|
|
38
|
+
*/
|
|
39
|
+
function emptyIndex(cliVersion) {
|
|
40
|
+
return {
|
|
41
|
+
schema: SCHEMA_VERSION,
|
|
42
|
+
generated_at: new Date().toISOString(),
|
|
43
|
+
version: cliVersion,
|
|
44
|
+
files: {},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Read an index file. Returns null on missing file, malformed JSON, or
|
|
50
|
+
* schema mismatch — the caller should treat any of those as "first
|
|
51
|
+
* install / no baseline" and start fresh.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} indexPath
|
|
54
|
+
* @returns {Promise<FileIndex|null>}
|
|
55
|
+
*/
|
|
56
|
+
async function readFileIndex(indexPath) {
|
|
57
|
+
let raw;
|
|
58
|
+
try {
|
|
59
|
+
raw = await fs.promises.readFile(indexPath, 'utf8');
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (err.code === 'ENOENT') return null;
|
|
62
|
+
throw err;
|
|
63
|
+
}
|
|
64
|
+
let parsed;
|
|
65
|
+
try {
|
|
66
|
+
parsed = JSON.parse(raw);
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
|
|
71
|
+
if (parsed.schema !== SCHEMA_VERSION) return null;
|
|
72
|
+
if (!parsed.files || typeof parsed.files !== 'object' || Array.isArray(parsed.files)) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return /** @type {FileIndex} */ (parsed);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Write the index atomically (temp + rename), matching the writer's
|
|
80
|
+
* pattern for the user config. Callers should pass the final index they
|
|
81
|
+
* produced — nothing about `files` is validated here.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} indexPath
|
|
84
|
+
* @param {FileIndex} index
|
|
85
|
+
* @returns {Promise<void>}
|
|
86
|
+
*/
|
|
87
|
+
async function writeFileIndex(indexPath, index) {
|
|
88
|
+
const dir = path.dirname(indexPath);
|
|
89
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
90
|
+
const tmp = path.join(
|
|
91
|
+
dir,
|
|
92
|
+
`${path.basename(indexPath)}.tmp-${process.pid}-${Math.random().toString(36).slice(2, 10)}`,
|
|
93
|
+
);
|
|
94
|
+
const payload = {
|
|
95
|
+
...index,
|
|
96
|
+
generated_at: new Date().toISOString(),
|
|
97
|
+
};
|
|
98
|
+
const content = JSON.stringify(payload, null, 2) + '\n';
|
|
99
|
+
try {
|
|
100
|
+
await fs.promises.writeFile(tmp, content, 'utf8');
|
|
101
|
+
await fs.promises.rename(tmp, indexPath);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
try {
|
|
104
|
+
await fs.promises.unlink(tmp);
|
|
105
|
+
} catch {
|
|
106
|
+
/* swallow */
|
|
107
|
+
}
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = { SCHEMA_VERSION, emptyIndex, readFileIndex, writeFileIndex };
|