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
package/scripts/lib/counter.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared Counter Module
|
|
3
|
-
*
|
|
4
|
-
* Single source of truth for counting AgileFlow components.
|
|
5
|
-
* Used by: sync-counts.js, content-injector.js, installer.js
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
const path = require('path');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Count command files in a directory (including subdirectories like session/)
|
|
13
|
-
* @param {string} commandsDir - Path to commands directory
|
|
14
|
-
* @returns {number} Total command count
|
|
15
|
-
*/
|
|
16
|
-
function countCommands(commandsDir) {
|
|
17
|
-
if (!fs.existsSync(commandsDir)) return 0;
|
|
18
|
-
|
|
19
|
-
let count = 0;
|
|
20
|
-
const entries = fs.readdirSync(commandsDir, { withFileTypes: true });
|
|
21
|
-
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
24
|
-
count++;
|
|
25
|
-
} else if (entry.isDirectory()) {
|
|
26
|
-
// Count commands in subdirectories (e.g., session/)
|
|
27
|
-
const subDir = path.join(commandsDir, entry.name);
|
|
28
|
-
const subFiles = fs.readdirSync(subDir).filter(f => f.endsWith('.md'));
|
|
29
|
-
count += subFiles.length;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return count;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Count agent files in a directory
|
|
38
|
-
* @param {string} agentsDir - Path to agents directory
|
|
39
|
-
* @returns {number} Total agent count
|
|
40
|
-
*/
|
|
41
|
-
function countAgents(agentsDir) {
|
|
42
|
-
if (!fs.existsSync(agentsDir)) return 0;
|
|
43
|
-
return fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Count skill directories (each skill has a SKILL.md file)
|
|
48
|
-
* @param {string} skillsDir - Path to skills directory
|
|
49
|
-
* @returns {number} Total skill count
|
|
50
|
-
*/
|
|
51
|
-
function countSkills(skillsDir) {
|
|
52
|
-
if (!fs.existsSync(skillsDir)) return 0;
|
|
53
|
-
|
|
54
|
-
let count = 0;
|
|
55
|
-
|
|
56
|
-
function scanDir(dir) {
|
|
57
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
58
|
-
for (const entry of entries) {
|
|
59
|
-
if (entry.isDirectory()) {
|
|
60
|
-
const skillFile = path.join(dir, entry.name, 'SKILL.md');
|
|
61
|
-
if (fs.existsSync(skillFile)) {
|
|
62
|
-
count++;
|
|
63
|
-
}
|
|
64
|
-
// Recurse into subdirectories
|
|
65
|
-
scanDir(path.join(dir, entry.name));
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
scanDir(skillsDir);
|
|
71
|
-
return count;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get all counts at once from a core directory
|
|
76
|
-
* @param {string} coreDir - Path to core directory containing commands/, agents/, skills/
|
|
77
|
-
* @returns {Object} Counts object { commands, agents, skills }
|
|
78
|
-
*/
|
|
79
|
-
function getCounts(coreDir) {
|
|
80
|
-
return {
|
|
81
|
-
commands: countCommands(path.join(coreDir, 'commands')),
|
|
82
|
-
agents: countAgents(path.join(coreDir, 'agents')),
|
|
83
|
-
skills: countSkills(path.join(coreDir, 'skills')),
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Get counts from CLI package source
|
|
89
|
-
* @param {string} cliRoot - Path to packages/cli directory
|
|
90
|
-
* @returns {Object} Counts object { commands, agents, skills }
|
|
91
|
-
*/
|
|
92
|
-
function getSourceCounts(cliRoot) {
|
|
93
|
-
const coreDir = path.join(cliRoot, 'src', 'core');
|
|
94
|
-
return getCounts(coreDir);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
module.exports = {
|
|
98
|
-
countCommands,
|
|
99
|
-
countAgents,
|
|
100
|
-
countSkills,
|
|
101
|
-
getCounts,
|
|
102
|
-
getSourceCounts,
|
|
103
|
-
};
|
|
@@ -1,619 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* damage-control-utils.js - Shared utilities for damage-control hooks
|
|
3
|
-
*
|
|
4
|
-
* EXIT CODE SEMANTICS (Claude Code Hook Protocol):
|
|
5
|
-
* ================================================
|
|
6
|
-
* 0 - Allow operation (or ask via JSON output)
|
|
7
|
-
* 1 - Error (operation proceeds - fail-open)
|
|
8
|
-
* 2 - Block operation (stderr message shown to user)
|
|
9
|
-
*
|
|
10
|
-
* For blocking (exit 2), output reason to stderr:
|
|
11
|
-
* console.error('[BLOCKED] Reason');
|
|
12
|
-
* process.exit(2);
|
|
13
|
-
*
|
|
14
|
-
* For "ask" confirmation (exit 0 with JSON):
|
|
15
|
-
* console.log(JSON.stringify({ result: 'ask', message: 'Confirm?' }));
|
|
16
|
-
* process.exit(0);
|
|
17
|
-
*
|
|
18
|
-
* IMPORTANT: These scripts must FAIL OPEN (exit 0 on error)
|
|
19
|
-
* to avoid blocking users when config is broken.
|
|
20
|
-
*
|
|
21
|
-
* This module is copied to .agileflow/scripts/lib/ at install time
|
|
22
|
-
* and used by damage-control-bash.js, damage-control-edit.js, damage-control-write.js
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const fs = require('fs');
|
|
26
|
-
const path = require('path');
|
|
27
|
-
const os = require('os');
|
|
28
|
-
|
|
29
|
-
// Inline colors (no external dependency - keeps scripts standalone)
|
|
30
|
-
const c = {
|
|
31
|
-
coral: '\x1b[38;5;203m',
|
|
32
|
-
dim: '\x1b[2m',
|
|
33
|
-
reset: '\x1b[0m',
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Pattern cache: avoids re-reading and re-parsing YAML on every hook invocation.
|
|
37
|
-
// Invalidated when the config file's mtime changes.
|
|
38
|
-
const _patternCache = {
|
|
39
|
-
/** @type {string|null} */ filePath: null,
|
|
40
|
-
/** @type {number} */ mtime: 0,
|
|
41
|
-
/** @type {object|null} */ config: null,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// Shared constants
|
|
45
|
-
const CONFIG_PATHS = [
|
|
46
|
-
'.agileflow/config/damage-control-patterns.yaml',
|
|
47
|
-
'.agileflow/config/damage-control-patterns.yml',
|
|
48
|
-
'.agileflow/templates/damage-control-patterns.yaml',
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
const STDIN_TIMEOUT_MS = 4000;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Find project root by looking for .agileflow directory
|
|
55
|
-
* @returns {string} Project root path or current working directory
|
|
56
|
-
*/
|
|
57
|
-
function findProjectRoot() {
|
|
58
|
-
let dir = process.cwd();
|
|
59
|
-
while (dir !== '/') {
|
|
60
|
-
if (fs.existsSync(path.join(dir, '.agileflow'))) {
|
|
61
|
-
return dir;
|
|
62
|
-
}
|
|
63
|
-
dir = path.dirname(dir);
|
|
64
|
-
}
|
|
65
|
-
return process.cwd();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Expand ~ to home directory
|
|
70
|
-
* @param {string} p - Path that may start with ~/
|
|
71
|
-
* @returns {string} Expanded path
|
|
72
|
-
*/
|
|
73
|
-
function expandPath(p) {
|
|
74
|
-
if (p.startsWith('~/')) {
|
|
75
|
-
return path.join(os.homedir(), p.slice(2));
|
|
76
|
-
}
|
|
77
|
-
return p;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Load patterns configuration from YAML file with caching.
|
|
82
|
-
* Returns cached config when the file hasn't changed (mtime check).
|
|
83
|
-
* Returns empty config if not found (fail-open).
|
|
84
|
-
*
|
|
85
|
-
* @param {string} projectRoot - Project root directory
|
|
86
|
-
* @param {function} parseYAML - Function to parse YAML content
|
|
87
|
-
* @param {object} defaultConfig - Default config if no file found
|
|
88
|
-
* @returns {object} Parsed configuration
|
|
89
|
-
*/
|
|
90
|
-
function loadPatterns(projectRoot, parseYAML, defaultConfig = {}) {
|
|
91
|
-
for (const configPath of CONFIG_PATHS) {
|
|
92
|
-
const fullPath = path.join(projectRoot, configPath);
|
|
93
|
-
if (fs.existsSync(fullPath)) {
|
|
94
|
-
try {
|
|
95
|
-
// Check mtime for cache invalidation
|
|
96
|
-
const stat = fs.statSync(fullPath);
|
|
97
|
-
const mtime = stat.mtimeMs;
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
_patternCache.filePath === fullPath &&
|
|
101
|
-
_patternCache.mtime === mtime &&
|
|
102
|
-
_patternCache.config
|
|
103
|
-
) {
|
|
104
|
-
return _patternCache.config;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
108
|
-
const config = parseYAML(content);
|
|
109
|
-
|
|
110
|
-
// Store in cache
|
|
111
|
-
_patternCache.filePath = fullPath;
|
|
112
|
-
_patternCache.mtime = mtime;
|
|
113
|
-
_patternCache.config = config;
|
|
114
|
-
|
|
115
|
-
return config;
|
|
116
|
-
} catch (e) {
|
|
117
|
-
// Continue to next path
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Return empty config if no file found (fail-open)
|
|
123
|
-
return defaultConfig;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Clear the pattern cache (for testing or forced reload).
|
|
128
|
-
*/
|
|
129
|
-
function clearPatternCache() {
|
|
130
|
-
_patternCache.filePath = null;
|
|
131
|
-
_patternCache.mtime = 0;
|
|
132
|
-
_patternCache.config = null;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Check if a file path matches any of the protected patterns
|
|
137
|
-
*
|
|
138
|
-
* @param {string} filePath - File path to check
|
|
139
|
-
* @param {string[]} patterns - Array of patterns to match against
|
|
140
|
-
* @returns {string|null} Matched pattern or null
|
|
141
|
-
*/
|
|
142
|
-
function pathMatches(filePath, patterns) {
|
|
143
|
-
if (!filePath) return null;
|
|
144
|
-
|
|
145
|
-
const normalizedPath = path.resolve(filePath);
|
|
146
|
-
const relativePath = path.relative(process.cwd(), normalizedPath);
|
|
147
|
-
|
|
148
|
-
for (const pattern of patterns) {
|
|
149
|
-
const expandedPattern = expandPath(pattern);
|
|
150
|
-
|
|
151
|
-
// Check if pattern is a directory prefix
|
|
152
|
-
if (pattern.endsWith('/')) {
|
|
153
|
-
const patternDir = expandedPattern.slice(0, -1);
|
|
154
|
-
if (normalizedPath.startsWith(patternDir)) {
|
|
155
|
-
return pattern;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Check exact match
|
|
160
|
-
if (normalizedPath === expandedPattern) {
|
|
161
|
-
return pattern;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Check if normalized path ends with pattern (for filenames like "id_rsa")
|
|
165
|
-
if (normalizedPath.endsWith(pattern) || relativePath.endsWith(pattern)) {
|
|
166
|
-
return pattern;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Check if pattern appears in path (for patterns like "*.pem")
|
|
170
|
-
if (pattern.startsWith('*')) {
|
|
171
|
-
const ext = pattern.slice(1);
|
|
172
|
-
if (normalizedPath.endsWith(ext) || relativePath.endsWith(ext)) {
|
|
173
|
-
return pattern;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Check if path contains pattern (for things like ".env.production")
|
|
178
|
-
const patternBase = path.basename(pattern);
|
|
179
|
-
if (path.basename(normalizedPath) === patternBase) {
|
|
180
|
-
return pattern;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return null;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Output blocked message to stderr
|
|
189
|
-
*
|
|
190
|
-
* @param {string} reason - Main reason for blocking
|
|
191
|
-
* @param {string} [detail] - Additional detail
|
|
192
|
-
* @param {string} [context] - Context info (file path or command)
|
|
193
|
-
*/
|
|
194
|
-
function outputBlocked(reason, detail, context) {
|
|
195
|
-
console.error(`${c.coral}[BLOCKED]${c.reset} ${reason}`);
|
|
196
|
-
if (detail) {
|
|
197
|
-
console.error(`${c.dim}${detail}${c.reset}`);
|
|
198
|
-
}
|
|
199
|
-
if (context) {
|
|
200
|
-
console.error(`${c.dim}${context}${c.reset}`);
|
|
201
|
-
}
|
|
202
|
-
// Help message for AI and user
|
|
203
|
-
console.error('');
|
|
204
|
-
console.error(
|
|
205
|
-
`${c.dim}This is intentional - AgileFlow Damage Control blocked a potentially dangerous operation.${c.reset}`
|
|
206
|
-
);
|
|
207
|
-
console.error(
|
|
208
|
-
`${c.dim}DO NOT retry this command. Ask the user if they want to proceed manually.${c.reset}`
|
|
209
|
-
);
|
|
210
|
-
console.error(`${c.dim}To disable: run /configure → Infrastructure → Damage Control${c.reset}`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Run damage control hook with stdin parsing
|
|
215
|
-
* Handles common error cases and timeout
|
|
216
|
-
*
|
|
217
|
-
* @param {object} options - Hook options
|
|
218
|
-
* @param {function} options.getInputValue - Extract value from parsed input (input) => value
|
|
219
|
-
* @param {function} options.loadConfig - Load configuration () => config
|
|
220
|
-
* @param {function} options.validate - Validate input (value, config) => { action, reason, detail? }
|
|
221
|
-
* @param {function} options.onBlock - Handle blocked result (result, value) => void
|
|
222
|
-
* @param {function} [options.onAsk] - Handle ask result (result, value) => void (optional)
|
|
223
|
-
*/
|
|
224
|
-
function runDamageControlHook(options) {
|
|
225
|
-
const { getInputValue, loadConfig, validate, onBlock, onAsk } = options;
|
|
226
|
-
|
|
227
|
-
let inputData = '';
|
|
228
|
-
|
|
229
|
-
process.stdin.setEncoding('utf8');
|
|
230
|
-
|
|
231
|
-
process.stdin.on('data', chunk => {
|
|
232
|
-
inputData += chunk;
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
process.stdin.on('end', () => {
|
|
236
|
-
try {
|
|
237
|
-
// Parse tool input from Claude Code
|
|
238
|
-
const input = JSON.parse(inputData);
|
|
239
|
-
const value = getInputValue(input);
|
|
240
|
-
|
|
241
|
-
if (!value) {
|
|
242
|
-
// No value to validate - allow
|
|
243
|
-
process.exit(0);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Load patterns and validate
|
|
247
|
-
const config = loadConfig();
|
|
248
|
-
const result = validate(value, config);
|
|
249
|
-
|
|
250
|
-
switch (result.action) {
|
|
251
|
-
case 'block':
|
|
252
|
-
onBlock(result, value);
|
|
253
|
-
process.exit(2);
|
|
254
|
-
break;
|
|
255
|
-
|
|
256
|
-
case 'ask':
|
|
257
|
-
if (onAsk) {
|
|
258
|
-
onAsk(result, value);
|
|
259
|
-
} else {
|
|
260
|
-
// Default ask behavior - output JSON
|
|
261
|
-
console.log(
|
|
262
|
-
JSON.stringify({
|
|
263
|
-
result: 'ask',
|
|
264
|
-
message: result.reason,
|
|
265
|
-
})
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
process.exit(0);
|
|
269
|
-
break;
|
|
270
|
-
|
|
271
|
-
case 'allow':
|
|
272
|
-
default:
|
|
273
|
-
process.exit(0);
|
|
274
|
-
}
|
|
275
|
-
} catch (e) {
|
|
276
|
-
// Parse error or other issue - fail open
|
|
277
|
-
process.exit(0);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// Handle no stdin (direct invocation)
|
|
282
|
-
process.stdin.on('error', () => {
|
|
283
|
-
process.exit(0);
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Set timeout to prevent hanging
|
|
287
|
-
setTimeout(() => {
|
|
288
|
-
process.exit(0);
|
|
289
|
-
}, STDIN_TIMEOUT_MS);
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Parse simplified YAML for damage control patterns
|
|
294
|
-
* Handles both pattern-based sections (with pattern/reason/flags objects)
|
|
295
|
-
* and list-based sections (with simple string arrays)
|
|
296
|
-
*
|
|
297
|
-
* @param {string} content - YAML file content
|
|
298
|
-
* @param {object} sectionConfig - Map of section names to their type ('patterns' or 'list')
|
|
299
|
-
* @returns {object} Parsed configuration
|
|
300
|
-
*
|
|
301
|
-
* @example
|
|
302
|
-
* // For bash patterns (pattern objects):
|
|
303
|
-
* parseSimpleYAML(content, {
|
|
304
|
-
* bashToolPatterns: 'patterns',
|
|
305
|
-
* askPatterns: 'patterns',
|
|
306
|
-
* agileflowProtections: 'patterns',
|
|
307
|
-
* })
|
|
308
|
-
*
|
|
309
|
-
* @example
|
|
310
|
-
* // For path lists (string arrays):
|
|
311
|
-
* parseSimpleYAML(content, {
|
|
312
|
-
* zeroAccessPaths: 'list',
|
|
313
|
-
* readOnlyPaths: 'list',
|
|
314
|
-
* noDeletePaths: 'list',
|
|
315
|
-
* })
|
|
316
|
-
*/
|
|
317
|
-
function parseSimpleYAML(content, sectionConfig) {
|
|
318
|
-
// Initialize result with empty arrays for each section
|
|
319
|
-
const config = {};
|
|
320
|
-
for (const section of Object.keys(sectionConfig)) {
|
|
321
|
-
config[section] = [];
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
let currentSection = null;
|
|
325
|
-
let currentPattern = null;
|
|
326
|
-
|
|
327
|
-
for (const line of content.split('\n')) {
|
|
328
|
-
const trimmed = line.trim();
|
|
329
|
-
|
|
330
|
-
// Skip empty lines and comments
|
|
331
|
-
if (!trimmed || trimmed.startsWith('#')) continue;
|
|
332
|
-
|
|
333
|
-
// Check if this line is a section header we care about
|
|
334
|
-
const sectionMatch = trimmed.match(/^(\w+):$/);
|
|
335
|
-
if (sectionMatch) {
|
|
336
|
-
const sectionName = sectionMatch[1];
|
|
337
|
-
if (sectionConfig[sectionName]) {
|
|
338
|
-
currentSection = sectionName;
|
|
339
|
-
currentPattern = null;
|
|
340
|
-
} else {
|
|
341
|
-
// Section we don't care about
|
|
342
|
-
currentSection = null;
|
|
343
|
-
currentPattern = null;
|
|
344
|
-
}
|
|
345
|
-
continue;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// Skip if we're not in a tracked section
|
|
349
|
-
if (!currentSection) continue;
|
|
350
|
-
|
|
351
|
-
const sectionType = sectionConfig[currentSection];
|
|
352
|
-
|
|
353
|
-
if (sectionType === 'patterns') {
|
|
354
|
-
// Pattern-based section (objects with pattern/reason/flags)
|
|
355
|
-
if (trimmed.startsWith('- pattern:')) {
|
|
356
|
-
const patternValue = trimmed
|
|
357
|
-
.replace('- pattern:', '')
|
|
358
|
-
.trim()
|
|
359
|
-
.replace(/^["']|["']$/g, '');
|
|
360
|
-
currentPattern = { pattern: patternValue };
|
|
361
|
-
config[currentSection].push(currentPattern);
|
|
362
|
-
} else if (trimmed.startsWith('reason:') && currentPattern) {
|
|
363
|
-
currentPattern.reason = trimmed
|
|
364
|
-
.replace('reason:', '')
|
|
365
|
-
.trim()
|
|
366
|
-
.replace(/^["']|["']$/g, '');
|
|
367
|
-
} else if (trimmed.startsWith('flags:') && currentPattern) {
|
|
368
|
-
currentPattern.flags = trimmed
|
|
369
|
-
.replace('flags:', '')
|
|
370
|
-
.trim()
|
|
371
|
-
.replace(/^["']|["']$/g, '');
|
|
372
|
-
} else if (trimmed.startsWith('ask:') && currentPattern) {
|
|
373
|
-
const askValue = trimmed.replace('ask:', '').trim().toLowerCase();
|
|
374
|
-
currentPattern.ask = askValue === 'true';
|
|
375
|
-
}
|
|
376
|
-
} else if (sectionType === 'list') {
|
|
377
|
-
// List-based section (simple string arrays)
|
|
378
|
-
if (trimmed.startsWith('- ')) {
|
|
379
|
-
const value = trimmed.slice(2).replace(/^["']|["']$/g, '');
|
|
380
|
-
config[currentSection].push(value);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return config;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
/**
|
|
389
|
-
* Pre-configured parser for bash tool patterns
|
|
390
|
-
*/
|
|
391
|
-
function parseBashPatterns(content) {
|
|
392
|
-
return parseSimpleYAML(content, {
|
|
393
|
-
bashToolPatterns: 'patterns',
|
|
394
|
-
askPatterns: 'patterns',
|
|
395
|
-
agileflowProtections: 'patterns',
|
|
396
|
-
releaseProtections: 'patterns',
|
|
397
|
-
});
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Pre-configured parser for path patterns (edit/write)
|
|
402
|
-
*/
|
|
403
|
-
function parsePathPatterns(content) {
|
|
404
|
-
return parseSimpleYAML(content, {
|
|
405
|
-
zeroAccessPaths: 'list',
|
|
406
|
-
readOnlyPaths: 'list',
|
|
407
|
-
noDeletePaths: 'list',
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Validate file path against path patterns
|
|
413
|
-
* Used by both edit and write hooks
|
|
414
|
-
*
|
|
415
|
-
* @param {string} filePath - File path to validate
|
|
416
|
-
* @param {object} config - Parsed path patterns config
|
|
417
|
-
* @param {string} operation - Operation type ('edit' or 'write') for error messages
|
|
418
|
-
* @returns {object} Validation result { action, reason?, detail? }
|
|
419
|
-
*/
|
|
420
|
-
function validatePathAgainstPatterns(filePath, config, operation = 'access') {
|
|
421
|
-
// Check zero access paths - completely blocked
|
|
422
|
-
const zeroMatch = pathMatches(filePath, config.zeroAccessPaths || []);
|
|
423
|
-
if (zeroMatch) {
|
|
424
|
-
return {
|
|
425
|
-
action: 'block',
|
|
426
|
-
reason: `Zero-access path: ${zeroMatch}`,
|
|
427
|
-
detail: 'This file is protected and cannot be accessed',
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// Check read-only paths - cannot edit/write
|
|
432
|
-
const readOnlyMatch = pathMatches(filePath, config.readOnlyPaths || []);
|
|
433
|
-
if (readOnlyMatch) {
|
|
434
|
-
return {
|
|
435
|
-
action: 'block',
|
|
436
|
-
reason: `Read-only path: ${readOnlyMatch}`,
|
|
437
|
-
detail: `This file is read-only and cannot be ${operation === 'edit' ? 'edited' : 'written to'}`,
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// Allow by default
|
|
442
|
-
return { action: 'allow' };
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Factory: Create a path-based damage control hook
|
|
447
|
-
*
|
|
448
|
-
* Reduces boilerplate for Edit/Write/Delete hooks that all use path validation.
|
|
449
|
-
*
|
|
450
|
-
* @param {string} operation - Operation type ('edit', 'write', 'delete')
|
|
451
|
-
* @returns {function} Hook runner function
|
|
452
|
-
*
|
|
453
|
-
* @example
|
|
454
|
-
* // In damage-control-edit.js:
|
|
455
|
-
* const { createPathHook } = require('./lib/damage-control-utils');
|
|
456
|
-
* createPathHook('edit')();
|
|
457
|
-
*/
|
|
458
|
-
function createPathHook(operation) {
|
|
459
|
-
return function runHook() {
|
|
460
|
-
const projectRoot = findProjectRoot();
|
|
461
|
-
const defaultConfig = { zeroAccessPaths: [], readOnlyPaths: [], noDeletePaths: [] };
|
|
462
|
-
|
|
463
|
-
runDamageControlHook({
|
|
464
|
-
getInputValue: input => input.file_path || input.tool_input?.file_path,
|
|
465
|
-
loadConfig: () => loadPatterns(projectRoot, parsePathPatterns, defaultConfig),
|
|
466
|
-
validate: (filePath, config) => validatePathAgainstPatterns(filePath, config, operation),
|
|
467
|
-
onBlock: (result, filePath) => {
|
|
468
|
-
outputBlocked(result.reason, result.detail, `File: ${filePath}`);
|
|
469
|
-
},
|
|
470
|
-
});
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Factory: Create the bash damage control hook
|
|
476
|
-
*
|
|
477
|
-
* @returns {function} Hook runner function
|
|
478
|
-
*
|
|
479
|
-
* @example
|
|
480
|
-
* // In damage-control-bash.js:
|
|
481
|
-
* const { createBashHook } = require('./lib/damage-control-utils');
|
|
482
|
-
* createBashHook()();
|
|
483
|
-
*/
|
|
484
|
-
function createBashHook() {
|
|
485
|
-
return function runHook() {
|
|
486
|
-
const projectRoot = findProjectRoot();
|
|
487
|
-
const defaultConfig = {
|
|
488
|
-
bashToolPatterns: [],
|
|
489
|
-
askPatterns: [],
|
|
490
|
-
agileflowProtections: [],
|
|
491
|
-
releaseProtections: [],
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
/**
|
|
495
|
-
* Test command against a single pattern rule
|
|
496
|
-
* Skips patterns that fail ReDoS validation
|
|
497
|
-
*/
|
|
498
|
-
function matchesPattern(command, rule) {
|
|
499
|
-
try {
|
|
500
|
-
// Validate pattern for ReDoS safety before use
|
|
501
|
-
const validation = validatePattern(rule.pattern);
|
|
502
|
-
if (!validation.safe) {
|
|
503
|
-
return false;
|
|
504
|
-
}
|
|
505
|
-
const flags = rule.flags || '';
|
|
506
|
-
const regex = new RegExp(rule.pattern, flags);
|
|
507
|
-
return regex.test(command);
|
|
508
|
-
} catch (e) {
|
|
509
|
-
// Invalid regex - skip this pattern
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* Validate command against all patterns
|
|
516
|
-
*/
|
|
517
|
-
function validateCommand(command, config) {
|
|
518
|
-
// Check bashToolPatterns + agileflowProtections
|
|
519
|
-
// Rules with ask: true trigger confirmation, others block
|
|
520
|
-
const allPatterns = [
|
|
521
|
-
...(config.bashToolPatterns || []),
|
|
522
|
-
...(config.agileflowProtections || []),
|
|
523
|
-
...(config.releaseProtections || []),
|
|
524
|
-
];
|
|
525
|
-
|
|
526
|
-
for (const rule of allPatterns) {
|
|
527
|
-
if (matchesPattern(command, rule)) {
|
|
528
|
-
// Check if this rule wants to ask instead of block
|
|
529
|
-
if (rule.ask === true || rule.ask === 'true') {
|
|
530
|
-
return {
|
|
531
|
-
action: 'ask',
|
|
532
|
-
reason: rule.reason || 'Please confirm this command',
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
|
-
return {
|
|
536
|
-
action: 'block',
|
|
537
|
-
reason: rule.reason || 'Command blocked by damage control',
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// Check askPatterns section (always ask)
|
|
543
|
-
for (const rule of config.askPatterns || []) {
|
|
544
|
-
if (matchesPattern(command, rule)) {
|
|
545
|
-
return {
|
|
546
|
-
action: 'ask',
|
|
547
|
-
reason: rule.reason || 'Please confirm this command',
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
// Allow by default
|
|
553
|
-
return { action: 'allow' };
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
runDamageControlHook({
|
|
557
|
-
getInputValue: input => input.command || input.tool_input?.command,
|
|
558
|
-
loadConfig: () => loadPatterns(projectRoot, parseBashPatterns, defaultConfig),
|
|
559
|
-
validate: validateCommand,
|
|
560
|
-
onBlock: (result, command) => {
|
|
561
|
-
outputBlocked(
|
|
562
|
-
result.reason,
|
|
563
|
-
`Command: ${command.substring(0, 100)}${command.length > 100 ? '...' : ''}`
|
|
564
|
-
);
|
|
565
|
-
},
|
|
566
|
-
});
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
/**
|
|
571
|
-
* Detect ReDoS-vulnerable patterns (nested quantifiers)
|
|
572
|
-
*
|
|
573
|
-
* Checks for patterns like (a+)+ or (a*b?)* that cause
|
|
574
|
-
* catastrophic backtracking on pathological inputs.
|
|
575
|
-
*
|
|
576
|
-
* @param {string} pattern - Regex pattern string to validate
|
|
577
|
-
* @returns {{ safe: boolean, reason?: string }}
|
|
578
|
-
*/
|
|
579
|
-
function validatePattern(pattern) {
|
|
580
|
-
if (!pattern || typeof pattern !== 'string') {
|
|
581
|
-
return { safe: false, reason: 'Empty or invalid pattern' };
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
// Detect nested quantifiers: a group with a quantifier containing inner quantifiers
|
|
585
|
-
// Matches patterns like (x+)*, (x+)+, (x*)+, (x+){2,}, etc.
|
|
586
|
-
const nestedQuantifierRe = /\([^)]*[+*][^)]*\)[+*{]/;
|
|
587
|
-
if (nestedQuantifierRe.test(pattern)) {
|
|
588
|
-
return { safe: false, reason: `Nested quantifier detected in: ${pattern}` };
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// Try to compile the regex to catch syntax errors
|
|
592
|
-
try {
|
|
593
|
-
new RegExp(pattern);
|
|
594
|
-
} catch (e) {
|
|
595
|
-
return { safe: false, reason: `Invalid regex: ${e.message}` };
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
return { safe: true };
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
module.exports = {
|
|
602
|
-
c,
|
|
603
|
-
findProjectRoot,
|
|
604
|
-
expandPath,
|
|
605
|
-
loadPatterns,
|
|
606
|
-
clearPatternCache,
|
|
607
|
-
pathMatches,
|
|
608
|
-
outputBlocked,
|
|
609
|
-
runDamageControlHook,
|
|
610
|
-
parseSimpleYAML,
|
|
611
|
-
parseBashPatterns,
|
|
612
|
-
parsePathPatterns,
|
|
613
|
-
validatePathAgainstPatterns,
|
|
614
|
-
validatePattern,
|
|
615
|
-
createPathHook,
|
|
616
|
-
createBashHook,
|
|
617
|
-
CONFIG_PATHS,
|
|
618
|
-
STDIN_TIMEOUT_MS,
|
|
619
|
-
};
|