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
|
@@ -1,969 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Content Injector - Dynamic content injection for AgileFlow files
|
|
3
|
-
*
|
|
4
|
-
* Supports template variables that get replaced at install time:
|
|
5
|
-
*
|
|
6
|
-
* COUNTS:
|
|
7
|
-
* {{COMMAND_COUNT}} - Total number of commands
|
|
8
|
-
* {{AGENT_COUNT}} - Total number of agents
|
|
9
|
-
* {{SKILL_COUNT}} - Total number of skills
|
|
10
|
-
*
|
|
11
|
-
* LISTS:
|
|
12
|
-
* <!-- {{AGENT_LIST}} --> - Full formatted agent list
|
|
13
|
-
* <!-- {{COMMAND_LIST}} --> - Full formatted command list
|
|
14
|
-
*
|
|
15
|
-
* TEMPLATES:
|
|
16
|
-
* <!-- {{SESSION_HARNESS}} --> - Session harness protocol (generic)
|
|
17
|
-
* <!-- {{SESSION_HARNESS:AG-API}} --> - Session harness protocol (with agent ID)
|
|
18
|
-
* <!-- {{QUALITY_GATE_PRIORITIES}} --> - Quality gate priorities (CRITICAL/HIGH/MEDIUM)
|
|
19
|
-
*
|
|
20
|
-
* METADATA:
|
|
21
|
-
* {{VERSION}} - AgileFlow version from package.json
|
|
22
|
-
* {{INSTALL_DATE}} - Date of installation (YYYY-MM-DD)
|
|
23
|
-
*
|
|
24
|
-
* FOLDER REFERENCES:
|
|
25
|
-
* {agileflow_folder} - Name of the agileflow folder (e.g., .agileflow)
|
|
26
|
-
* {docs_folder} - Name of the docs folder (e.g., docs, agileflow-docs)
|
|
27
|
-
* {project-root} - Project root reference
|
|
28
|
-
*
|
|
29
|
-
* PATH INJECTION:
|
|
30
|
-
* When docsFolder is not 'docs', all path references like `docs/` are replaced
|
|
31
|
-
* with the actual folder name (e.g., `agileflow-docs/`).
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
const fs = require('fs');
|
|
35
|
-
const path = require('path');
|
|
36
|
-
|
|
37
|
-
// Use shared modules
|
|
38
|
-
const { parseFrontmatter, normalizeTools } = require('../../../scripts/lib/frontmatter-parser');
|
|
39
|
-
const { validatePath } = require('../../../lib/validate');
|
|
40
|
-
const {
|
|
41
|
-
countCommands,
|
|
42
|
-
countAgents,
|
|
43
|
-
countSkills,
|
|
44
|
-
getCounts,
|
|
45
|
-
} = require('../../../scripts/lib/counter');
|
|
46
|
-
const {
|
|
47
|
-
sanitize,
|
|
48
|
-
sanitizeAgentData,
|
|
49
|
-
sanitizeCommandData,
|
|
50
|
-
validatePlaceholderValue,
|
|
51
|
-
detectInjectionAttempt,
|
|
52
|
-
} = require('../../../lib/content-sanitizer');
|
|
53
|
-
|
|
54
|
-
// =============================================================================
|
|
55
|
-
// List Generation Functions
|
|
56
|
-
// =============================================================================
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Validate that a file path is within the expected directory.
|
|
60
|
-
* Prevents reading files outside the expected scope.
|
|
61
|
-
* Security: Symlinks are NOT allowed to prevent escape attacks.
|
|
62
|
-
* @param {string} filePath - File path to validate
|
|
63
|
-
* @param {string} baseDir - Expected base directory
|
|
64
|
-
* @returns {boolean} True if path is safe
|
|
65
|
-
*/
|
|
66
|
-
function isPathSafe(filePath, baseDir) {
|
|
67
|
-
// Security hardening (US-0104): Symlinks disabled to prevent escape attacks
|
|
68
|
-
const result = validatePath(filePath, baseDir, { allowSymlinks: false });
|
|
69
|
-
return result.ok;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Derive agent category from name for compact grouping.
|
|
74
|
-
* @param {string} name - Agent name
|
|
75
|
-
* @returns {string} Category name
|
|
76
|
-
*/
|
|
77
|
-
function categorizeAgent(name) {
|
|
78
|
-
// Audit analyzer families
|
|
79
|
-
const analyzerMatch = name.match(/^(logic|security|perf|test|completeness|legal)-analyzer-/);
|
|
80
|
-
if (analyzerMatch) {
|
|
81
|
-
const familyNames = {
|
|
82
|
-
logic: 'Logic',
|
|
83
|
-
security: 'Security',
|
|
84
|
-
perf: 'Performance',
|
|
85
|
-
test: 'Tests',
|
|
86
|
-
completeness: 'Completeness',
|
|
87
|
-
legal: 'Legal',
|
|
88
|
-
};
|
|
89
|
-
return `Audit - ${familyNames[analyzerMatch[1]] || analyzerMatch[1]}`;
|
|
90
|
-
}
|
|
91
|
-
// Consensus coordinators for audit families
|
|
92
|
-
const consensusMatch = name.match(/^(logic|security|perf|test|completeness|legal)-consensus$/);
|
|
93
|
-
if (consensusMatch) {
|
|
94
|
-
const familyNames = {
|
|
95
|
-
logic: 'Logic',
|
|
96
|
-
security: 'Security',
|
|
97
|
-
perf: 'Performance',
|
|
98
|
-
test: 'Tests',
|
|
99
|
-
completeness: 'Completeness',
|
|
100
|
-
legal: 'Legal',
|
|
101
|
-
};
|
|
102
|
-
return `Audit - ${familyNames[consensusMatch[1]] || consensusMatch[1]}`;
|
|
103
|
-
}
|
|
104
|
-
if (name.startsWith('council-')) return 'Council';
|
|
105
|
-
if (name.endsWith('-validator')) return 'Validation';
|
|
106
|
-
return 'Domain';
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Scan agents directory and generate compact category-grouped agent list
|
|
111
|
-
* @param {string} agentsDir - Path to agents directory
|
|
112
|
-
* @returns {string} Formatted agent list grouped by category
|
|
113
|
-
*/
|
|
114
|
-
function generateAgentList(agentsDir) {
|
|
115
|
-
if (!fs.existsSync(agentsDir)) return '';
|
|
116
|
-
|
|
117
|
-
const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
118
|
-
const agents = [];
|
|
119
|
-
|
|
120
|
-
for (const file of files) {
|
|
121
|
-
const filePath = path.join(agentsDir, file);
|
|
122
|
-
|
|
123
|
-
// Validate path before reading to prevent traversal via symlinks or malicious names
|
|
124
|
-
if (!isPathSafe(filePath, agentsDir)) {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
129
|
-
const frontmatter = parseFrontmatter(content);
|
|
130
|
-
|
|
131
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Sanitize agent data to prevent injection attacks
|
|
136
|
-
const rawAgent = {
|
|
137
|
-
name: frontmatter.name || path.basename(file, '.md'),
|
|
138
|
-
description: frontmatter.description || '',
|
|
139
|
-
tools: normalizeTools(frontmatter.tools),
|
|
140
|
-
model: frontmatter.model || 'haiku',
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const sanitizedAgent = sanitizeAgentData(rawAgent);
|
|
144
|
-
|
|
145
|
-
// Skip if sanitization produced invalid data
|
|
146
|
-
if (!sanitizedAgent.name || sanitizedAgent.name === 'unknown') {
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
agents.push(sanitizedAgent);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
agents.sort((a, b) => a.name.localeCompare(b.name));
|
|
154
|
-
|
|
155
|
-
// Sanitize the count value
|
|
156
|
-
const safeCount = sanitize.count(agents.length);
|
|
157
|
-
|
|
158
|
-
// Group by category for compact output
|
|
159
|
-
const categories = {};
|
|
160
|
-
for (const agent of agents) {
|
|
161
|
-
const cat = categorizeAgent(agent.name);
|
|
162
|
-
if (!categories[cat]) categories[cat] = [];
|
|
163
|
-
categories[cat].push(agent.name);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
let output = `**AVAILABLE AGENTS (${safeCount} total)**:\n\n`;
|
|
167
|
-
|
|
168
|
-
for (const [category, names] of Object.entries(categories)) {
|
|
169
|
-
output += `**${category}**: ${names.join(', ')}\n`;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return output;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Scan commands directory and generate formatted command list
|
|
177
|
-
* @param {string} commandsDir - Path to commands directory
|
|
178
|
-
* @returns {string} Formatted command list
|
|
179
|
-
*/
|
|
180
|
-
function generateCommandList(commandsDir) {
|
|
181
|
-
if (!fs.existsSync(commandsDir)) return '';
|
|
182
|
-
|
|
183
|
-
const commands = [];
|
|
184
|
-
|
|
185
|
-
// Scan main commands
|
|
186
|
-
const mainFiles = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
|
|
187
|
-
for (const file of mainFiles) {
|
|
188
|
-
const filePath = path.join(commandsDir, file);
|
|
189
|
-
|
|
190
|
-
// Validate path before reading
|
|
191
|
-
if (!isPathSafe(filePath, commandsDir)) {
|
|
192
|
-
continue;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
196
|
-
const frontmatter = parseFrontmatter(content);
|
|
197
|
-
const cmdName = path.basename(file, '.md');
|
|
198
|
-
|
|
199
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) {
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Sanitize command data to prevent injection attacks
|
|
204
|
-
const rawCommand = {
|
|
205
|
-
name: cmdName,
|
|
206
|
-
description: frontmatter.description || '',
|
|
207
|
-
argumentHint: frontmatter['argument-hint'] || '',
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const sanitizedCommand = sanitizeCommandData(rawCommand);
|
|
211
|
-
if (!sanitizedCommand.name || sanitizedCommand.name === 'unknown') {
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
commands.push(sanitizedCommand);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Scan subdirectories (e.g., session/)
|
|
219
|
-
const entries = fs.readdirSync(commandsDir, { withFileTypes: true });
|
|
220
|
-
for (const entry of entries) {
|
|
221
|
-
if (entry.isDirectory()) {
|
|
222
|
-
const subDir = path.join(commandsDir, entry.name);
|
|
223
|
-
|
|
224
|
-
// Validate subdirectory path
|
|
225
|
-
if (!isPathSafe(subDir, commandsDir)) {
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const subFiles = fs.readdirSync(subDir).filter(f => f.endsWith('.md'));
|
|
230
|
-
|
|
231
|
-
for (const file of subFiles) {
|
|
232
|
-
const filePath = path.join(subDir, file);
|
|
233
|
-
|
|
234
|
-
// Validate file path within subdirectory
|
|
235
|
-
if (!isPathSafe(filePath, commandsDir)) {
|
|
236
|
-
continue;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
240
|
-
const frontmatter = parseFrontmatter(content);
|
|
241
|
-
const cmdName = `${entry.name}:${path.basename(file, '.md')}`;
|
|
242
|
-
|
|
243
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) {
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Sanitize command data
|
|
248
|
-
const rawCommand = {
|
|
249
|
-
name: cmdName,
|
|
250
|
-
description: frontmatter.description || '',
|
|
251
|
-
argumentHint: frontmatter['argument-hint'] || '',
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const sanitizedCommand = sanitizeCommandData(rawCommand);
|
|
255
|
-
if (!sanitizedCommand.name || sanitizedCommand.name === 'unknown') {
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
commands.push(sanitizedCommand);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
265
|
-
|
|
266
|
-
// Sanitize the count value
|
|
267
|
-
const safeCount = sanitize.count(commands.length);
|
|
268
|
-
let output = `Available commands (${safeCount} total):\n`;
|
|
269
|
-
|
|
270
|
-
commands.forEach(cmd => {
|
|
271
|
-
// All values are already sanitized by sanitizeCommandData
|
|
272
|
-
const argHint = cmd.argumentHint ? ` ${cmd.argumentHint}` : '';
|
|
273
|
-
output += `- \`/agileflow:${cmd.name}${argHint}\` - ${cmd.description}\n`;
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
return output;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Generate a compact category summary for agents (no individual names).
|
|
281
|
-
* Used by minimal mode and generators that want a discovery-oriented summary.
|
|
282
|
-
* @param {string} agentsDir - Path to agents directory
|
|
283
|
-
* @returns {string} Compact category summary with counts
|
|
284
|
-
*/
|
|
285
|
-
function generateAgentSummary(agentsDir) {
|
|
286
|
-
if (!fs.existsSync(agentsDir)) return '';
|
|
287
|
-
|
|
288
|
-
const files = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
289
|
-
const agents = [];
|
|
290
|
-
|
|
291
|
-
for (const file of files) {
|
|
292
|
-
const filePath = path.join(agentsDir, file);
|
|
293
|
-
if (!isPathSafe(filePath, agentsDir)) continue;
|
|
294
|
-
|
|
295
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
296
|
-
const frontmatter = parseFrontmatter(content);
|
|
297
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
|
|
298
|
-
|
|
299
|
-
const name = frontmatter.name || path.basename(file, '.md');
|
|
300
|
-
agents.push(name);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Group by category, count per category
|
|
304
|
-
const categories = {};
|
|
305
|
-
for (const name of agents) {
|
|
306
|
-
const cat = categorizeAgent(name);
|
|
307
|
-
if (!categories[cat]) categories[cat] = 0;
|
|
308
|
-
categories[cat]++;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const safeCount = sanitize.count(agents.length);
|
|
312
|
-
let output = `**${safeCount} agents** across ${Object.keys(categories).length} categories:\n`;
|
|
313
|
-
for (const [category, count] of Object.entries(categories)) {
|
|
314
|
-
output += `- **${category}**: ${count} agents\n`;
|
|
315
|
-
}
|
|
316
|
-
output += `\nRun \`/agileflow:help agents\` or browse \`.agileflow/agents/\` for the full list.`;
|
|
317
|
-
return output;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Generate a compact category summary for commands (no individual names).
|
|
322
|
-
* Used by minimal mode and generators that want a discovery-oriented summary.
|
|
323
|
-
* @param {string} commandsDir - Path to commands directory
|
|
324
|
-
* @returns {string} Compact category summary with counts
|
|
325
|
-
*/
|
|
326
|
-
function generateCommandSummary(commandsDir) {
|
|
327
|
-
if (!fs.existsSync(commandsDir)) return '';
|
|
328
|
-
|
|
329
|
-
const commands = [];
|
|
330
|
-
|
|
331
|
-
// Count main command files
|
|
332
|
-
const mainFiles = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
|
|
333
|
-
for (const file of mainFiles) {
|
|
334
|
-
const filePath = path.join(commandsDir, file);
|
|
335
|
-
if (!isPathSafe(filePath, commandsDir)) continue;
|
|
336
|
-
|
|
337
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
338
|
-
const frontmatter = parseFrontmatter(content);
|
|
339
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
|
|
340
|
-
commands.push(path.basename(file, '.md'));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Count subdirectory command files
|
|
344
|
-
const entries = fs.readdirSync(commandsDir, { withFileTypes: true });
|
|
345
|
-
for (const entry of entries) {
|
|
346
|
-
if (entry.isDirectory()) {
|
|
347
|
-
const subDir = path.join(commandsDir, entry.name);
|
|
348
|
-
if (!isPathSafe(subDir, commandsDir)) continue;
|
|
349
|
-
|
|
350
|
-
const subFiles = fs.readdirSync(subDir).filter(f => f.endsWith('.md'));
|
|
351
|
-
for (const file of subFiles) {
|
|
352
|
-
const filePath = path.join(subDir, file);
|
|
353
|
-
if (!isPathSafe(filePath, commandsDir)) continue;
|
|
354
|
-
|
|
355
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
356
|
-
const frontmatter = parseFrontmatter(content);
|
|
357
|
-
if (!frontmatter || Object.keys(frontmatter).length === 0) continue;
|
|
358
|
-
commands.push(`${entry.name}:${path.basename(file, '.md')}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const safeCount = sanitize.count(commands.length);
|
|
364
|
-
return `**${safeCount} commands** available. Run \`/agileflow:help\` for the full list with descriptions.`;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// =============================================================================
|
|
368
|
-
// Template Generation Functions
|
|
369
|
-
// =============================================================================
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Session harness template cache
|
|
373
|
-
* @type {string|null}
|
|
374
|
-
*/
|
|
375
|
-
let sessionHarnessTemplateCache = null;
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Quality gate priorities template cache
|
|
379
|
-
* @type {string|null}
|
|
380
|
-
*/
|
|
381
|
-
let qualityGatePrioritiesCache = null;
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Load session harness template from templates directory
|
|
385
|
-
* @param {string} coreDir - Path to core directory
|
|
386
|
-
* @returns {string} Template content or empty string if not found
|
|
387
|
-
*/
|
|
388
|
-
function loadSessionHarnessTemplate(coreDir) {
|
|
389
|
-
// Return cached template if available
|
|
390
|
-
if (sessionHarnessTemplateCache !== null) {
|
|
391
|
-
return sessionHarnessTemplateCache;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
const templatePath = path.join(coreDir, 'templates', 'session-harness-protocol.md');
|
|
395
|
-
|
|
396
|
-
if (!fs.existsSync(templatePath)) {
|
|
397
|
-
// Template not found, return empty string
|
|
398
|
-
sessionHarnessTemplateCache = '';
|
|
399
|
-
return sessionHarnessTemplateCache;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Validate path is within core directory (security)
|
|
403
|
-
if (!isPathSafe(templatePath, coreDir)) {
|
|
404
|
-
sessionHarnessTemplateCache = '';
|
|
405
|
-
return sessionHarnessTemplateCache;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
try {
|
|
409
|
-
sessionHarnessTemplateCache = fs.readFileSync(templatePath, 'utf8');
|
|
410
|
-
return sessionHarnessTemplateCache;
|
|
411
|
-
} catch (err) {
|
|
412
|
-
sessionHarnessTemplateCache = '';
|
|
413
|
-
return sessionHarnessTemplateCache;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* Generate session harness protocol content for a specific agent
|
|
419
|
-
* @param {string} coreDir - Path to core directory
|
|
420
|
-
* @param {string} agentId - Agent ID (e.g., "AG-API", "AG-UI")
|
|
421
|
-
* @returns {string} Session harness content with agent ID substituted
|
|
422
|
-
*/
|
|
423
|
-
function generateSessionHarnessContent(coreDir, agentId = 'AGENT') {
|
|
424
|
-
const template = loadSessionHarnessTemplate(coreDir);
|
|
425
|
-
|
|
426
|
-
if (!template) {
|
|
427
|
-
return '';
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Substitute agent ID in the template
|
|
431
|
-
// The template uses {AGENT_ID} as placeholder
|
|
432
|
-
return template.replace(/\{AGENT_ID\}/g, agentId);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Clear the session harness template cache
|
|
437
|
-
* Useful for testing or when template file changes
|
|
438
|
-
*/
|
|
439
|
-
function clearSessionHarnessCache() {
|
|
440
|
-
sessionHarnessTemplateCache = null;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* Load quality gate priorities template from templates directory
|
|
445
|
-
* @param {string} coreDir - Path to core directory
|
|
446
|
-
* @returns {string} Template content or empty string if not found
|
|
447
|
-
*/
|
|
448
|
-
function loadQualityGatePrioritiesTemplate(coreDir) {
|
|
449
|
-
// Return cached template if available
|
|
450
|
-
if (qualityGatePrioritiesCache !== null) {
|
|
451
|
-
return qualityGatePrioritiesCache;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
const templatePath = path.join(coreDir, 'templates', 'quality-gate-priorities.md');
|
|
455
|
-
|
|
456
|
-
if (!fs.existsSync(templatePath)) {
|
|
457
|
-
qualityGatePrioritiesCache = '';
|
|
458
|
-
return qualityGatePrioritiesCache;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Validate path is within core directory (security)
|
|
462
|
-
if (!isPathSafe(templatePath, coreDir)) {
|
|
463
|
-
qualityGatePrioritiesCache = '';
|
|
464
|
-
return qualityGatePrioritiesCache;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
try {
|
|
468
|
-
qualityGatePrioritiesCache = fs.readFileSync(templatePath, 'utf8');
|
|
469
|
-
return qualityGatePrioritiesCache;
|
|
470
|
-
} catch (err) {
|
|
471
|
-
qualityGatePrioritiesCache = '';
|
|
472
|
-
return qualityGatePrioritiesCache;
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Generate quality gate priorities content for a specific agent
|
|
478
|
-
* @param {string} coreDir - Path to core directory
|
|
479
|
-
* @param {string} agentId - Agent ID (e.g., "AG-API", "AG-UI")
|
|
480
|
-
* @returns {string} Quality gate priorities content with agent ID substituted
|
|
481
|
-
*/
|
|
482
|
-
function generateQualityGatePrioritiesContent(coreDir, agentId = 'AGENT') {
|
|
483
|
-
const template = loadQualityGatePrioritiesTemplate(coreDir);
|
|
484
|
-
|
|
485
|
-
if (!template) {
|
|
486
|
-
return '';
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
// Substitute placeholders in the template
|
|
490
|
-
return template
|
|
491
|
-
.replace(/\{AGENT_ID\}/g, agentId)
|
|
492
|
-
.replace(/\{TIMESTAMP\}/g, new Date().toISOString())
|
|
493
|
-
.replace(/\{STORY_ID\}/g, 'US-XXXX');
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Clear the quality gate priorities template cache
|
|
498
|
-
* Useful for testing or when template file changes
|
|
499
|
-
*/
|
|
500
|
-
function clearQualityGatePrioritiesCache() {
|
|
501
|
-
qualityGatePrioritiesCache = null;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
// =============================================================================
|
|
505
|
-
// Preserve Rules Expansion Functions
|
|
506
|
-
// =============================================================================
|
|
507
|
-
|
|
508
|
-
/**
|
|
509
|
-
* Preserve rules template cache
|
|
510
|
-
* @type {Object|null}
|
|
511
|
-
*/
|
|
512
|
-
let preserveRulesCache = null;
|
|
513
|
-
|
|
514
|
-
/**
|
|
515
|
-
* Load preserve rules definitions from templates directory
|
|
516
|
-
* @param {string} coreDir - Path to core directory
|
|
517
|
-
* @returns {Object} Rules object with category keys and rule arrays
|
|
518
|
-
*/
|
|
519
|
-
function loadPreserveRules(coreDir) {
|
|
520
|
-
// Return cached rules if available
|
|
521
|
-
if (preserveRulesCache !== null) {
|
|
522
|
-
return preserveRulesCache;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
const rulesPath = path.join(coreDir, 'templates', 'preserve-rules.json');
|
|
526
|
-
|
|
527
|
-
if (!fs.existsSync(rulesPath)) {
|
|
528
|
-
preserveRulesCache = {};
|
|
529
|
-
return preserveRulesCache;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// Validate path is within core directory (security)
|
|
533
|
-
if (!isPathSafe(rulesPath, coreDir)) {
|
|
534
|
-
preserveRulesCache = {};
|
|
535
|
-
return preserveRulesCache;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
try {
|
|
539
|
-
const content = fs.readFileSync(rulesPath, 'utf8');
|
|
540
|
-
preserveRulesCache = JSON.parse(content);
|
|
541
|
-
return preserveRulesCache;
|
|
542
|
-
} catch (err) {
|
|
543
|
-
preserveRulesCache = {};
|
|
544
|
-
return preserveRulesCache;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
* Expand preserve rules placeholders in content
|
|
550
|
-
* Replaces "{{RULES:category}}" with actual rule strings from the template
|
|
551
|
-
*
|
|
552
|
-
* @param {string} content - Content with preserve rules placeholders
|
|
553
|
-
* @param {string} coreDir - Path to core directory
|
|
554
|
-
* @returns {string} Content with rules expanded
|
|
555
|
-
*/
|
|
556
|
-
function expandPreserveRules(content, coreDir) {
|
|
557
|
-
const rules = loadPreserveRules(coreDir);
|
|
558
|
-
|
|
559
|
-
if (!rules || Object.keys(rules).length === 0) {
|
|
560
|
-
return content;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
// Pattern matches: - "{{RULES:category}}" in YAML preserve_rules arrays
|
|
564
|
-
// We need to handle the YAML list context carefully
|
|
565
|
-
const pattern = /- "\{\{RULES:(\w+)\}\}"/g;
|
|
566
|
-
|
|
567
|
-
return content.replace(pattern, (match, category) => {
|
|
568
|
-
const ruleList = rules[category];
|
|
569
|
-
|
|
570
|
-
if (!ruleList || !Array.isArray(ruleList) || ruleList.length === 0) {
|
|
571
|
-
// Unknown category or empty, keep original placeholder as warning
|
|
572
|
-
return match;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Sanitize rules before injecting
|
|
576
|
-
const sanitizedRules = ruleList.map(rule => {
|
|
577
|
-
// Escape double quotes in rule text
|
|
578
|
-
const escaped = String(rule).replace(/"/g, '\\"');
|
|
579
|
-
// Validate it's a reasonable rule string
|
|
580
|
-
if (escaped.length > 500) {
|
|
581
|
-
return escaped.substring(0, 500);
|
|
582
|
-
}
|
|
583
|
-
return escaped;
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
// Return expanded rules as YAML list items with proper indentation
|
|
587
|
-
// Each rule becomes: - "rule text"
|
|
588
|
-
return sanitizedRules.map(rule => `- "${rule}"`).join('\n ');
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
/**
|
|
593
|
-
* Clear the preserve rules template cache
|
|
594
|
-
* Useful for testing or when template file changes
|
|
595
|
-
*/
|
|
596
|
-
function clearPreserveRulesCache() {
|
|
597
|
-
preserveRulesCache = null;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// =============================================================================
|
|
601
|
-
// Main Injection Function
|
|
602
|
-
// =============================================================================
|
|
603
|
-
|
|
604
|
-
/**
|
|
605
|
-
* Inject all template variables into content
|
|
606
|
-
* @param {string} content - Template content with placeholders
|
|
607
|
-
* @param {Object} context - Context for replacements
|
|
608
|
-
* @param {string} context.coreDir - Path to core directory (commands/, agents/, skills/)
|
|
609
|
-
* @param {string} context.agileflowFolder - AgileFlow folder name
|
|
610
|
-
* @param {string} context.docsFolder - Docs folder name (default: 'docs')
|
|
611
|
-
* @param {string} context.version - AgileFlow version
|
|
612
|
-
* @param {boolean} context.minimal - When true, skip AGENT_LIST and COMMAND_LIST injection
|
|
613
|
-
* (replaces with discovery pointers). Keeps session harness, quality gates, preserve_rules.
|
|
614
|
-
* @returns {string} Content with all placeholders replaced
|
|
615
|
-
*/
|
|
616
|
-
function injectContent(content, context = {}) {
|
|
617
|
-
const {
|
|
618
|
-
coreDir,
|
|
619
|
-
agileflowFolder = '.agileflow',
|
|
620
|
-
docsFolder = 'docs',
|
|
621
|
-
version = 'unknown',
|
|
622
|
-
minimal = false,
|
|
623
|
-
} = context;
|
|
624
|
-
|
|
625
|
-
let result = content;
|
|
626
|
-
|
|
627
|
-
// Multi-line list placeholders can corrupt YAML if injected into frontmatter.
|
|
628
|
-
// Keep frontmatter untouched for these placeholders and inject only in body.
|
|
629
|
-
const replaceInBodyOnly = (input, replacer) => {
|
|
630
|
-
const frontmatterMatch = input.match(/^(---\n[\s\S]*?\n---\n?)([\s\S]*)$/);
|
|
631
|
-
if (!frontmatterMatch) {
|
|
632
|
-
return replacer(input);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const frontmatter = frontmatterMatch[1];
|
|
636
|
-
const body = frontmatterMatch[2];
|
|
637
|
-
return `${frontmatter}${replacer(body)}`;
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
// Expand preserve rules placeholders first (YAML frontmatter processing)
|
|
641
|
-
if (coreDir && fs.existsSync(coreDir) && result.includes('{{RULES:')) {
|
|
642
|
-
result = expandPreserveRules(result, coreDir);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// Get counts if core directory is available
|
|
646
|
-
let counts = { commands: 0, agents: 0, skills: 0 };
|
|
647
|
-
if (coreDir && fs.existsSync(coreDir)) {
|
|
648
|
-
counts = getCounts(coreDir);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Validate and sanitize all placeholder values before injection
|
|
652
|
-
const safeCommandCount = validatePlaceholderValue('COMMAND_COUNT', counts.commands).sanitized;
|
|
653
|
-
const safeAgentCount = validatePlaceholderValue('AGENT_COUNT', counts.agents).sanitized;
|
|
654
|
-
const safeSkillCount = validatePlaceholderValue('SKILL_COUNT', counts.skills).sanitized;
|
|
655
|
-
const safeVersion = validatePlaceholderValue('VERSION', version).sanitized;
|
|
656
|
-
const safeDate = validatePlaceholderValue('INSTALL_DATE', new Date()).sanitized;
|
|
657
|
-
const safeAgileflowFolder = validatePlaceholderValue(
|
|
658
|
-
'agileflow_folder',
|
|
659
|
-
agileflowFolder
|
|
660
|
-
).sanitized;
|
|
661
|
-
const safeDocsFolder = validatePlaceholderValue('docs_folder', docsFolder).sanitized;
|
|
662
|
-
|
|
663
|
-
// Replace count placeholders (both formats: {{X}} and <!-- {{X}} -->)
|
|
664
|
-
result = result.replace(/\{\{COMMAND_COUNT\}\}/g, String(safeCommandCount));
|
|
665
|
-
result = result.replace(/\{\{AGENT_COUNT\}\}/g, String(safeAgentCount));
|
|
666
|
-
result = result.replace(/\{\{SKILL_COUNT\}\}/g, String(safeSkillCount));
|
|
667
|
-
|
|
668
|
-
// Replace metadata placeholders
|
|
669
|
-
result = result.replace(/\{\{VERSION\}\}/g, safeVersion);
|
|
670
|
-
result = result.replace(/\{\{INSTALL_DATE\}\}/g, safeDate);
|
|
671
|
-
|
|
672
|
-
// Replace list placeholders (only if core directory available)
|
|
673
|
-
// List generation already includes sanitization via sanitizeAgentData/sanitizeCommandData
|
|
674
|
-
if (coreDir && fs.existsSync(coreDir)) {
|
|
675
|
-
if (result.includes('{{AGENT_LIST}}')) {
|
|
676
|
-
let agentList;
|
|
677
|
-
if (minimal) {
|
|
678
|
-
// Minimal mode: replace with compact discovery pointer
|
|
679
|
-
agentList = `**Agents**: ${safeAgentCount} available. Run \`/agileflow:help agents\` or \`ls .agileflow/agents/\` to browse.`;
|
|
680
|
-
} else {
|
|
681
|
-
agentList = generateAgentList(path.join(coreDir, 'agents'));
|
|
682
|
-
}
|
|
683
|
-
result = replaceInBodyOnly(result, body => {
|
|
684
|
-
let updated = body.replace(/<!-- \{\{AGENT_LIST\}\} -->/g, agentList);
|
|
685
|
-
updated = updated.replace(/\{\{AGENT_LIST\}\}/g, agentList);
|
|
686
|
-
return updated;
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (result.includes('{{COMMAND_LIST}}')) {
|
|
691
|
-
let commandList;
|
|
692
|
-
if (minimal) {
|
|
693
|
-
// Minimal mode: replace with compact discovery pointer
|
|
694
|
-
commandList = `**Commands**: ${safeCommandCount} available. Run \`/agileflow:help\` or \`ls .agileflow/commands/\` to browse.`;
|
|
695
|
-
} else {
|
|
696
|
-
commandList = generateCommandList(path.join(coreDir, 'commands'));
|
|
697
|
-
}
|
|
698
|
-
result = replaceInBodyOnly(result, body => {
|
|
699
|
-
let updated = body.replace(/<!-- \{\{COMMAND_LIST\}\} -->/g, commandList);
|
|
700
|
-
updated = updated.replace(/\{\{COMMAND_LIST\}\}/g, commandList);
|
|
701
|
-
return updated;
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Replace session harness template placeholder
|
|
706
|
-
// Supports two formats:
|
|
707
|
-
// <!-- {{SESSION_HARNESS}} --> - Uses default agent ID
|
|
708
|
-
// <!-- {{SESSION_HARNESS:AG-API}} --> - Uses specified agent ID
|
|
709
|
-
if (result.includes('SESSION_HARNESS')) {
|
|
710
|
-
// First, handle agent-specific format: <!-- {{SESSION_HARNESS:AG-XXX}} -->
|
|
711
|
-
const agentSpecificPattern = /<!-- \{\{SESSION_HARNESS:(AG-[A-Z]+)\}\} -->/g;
|
|
712
|
-
result = result.replace(agentSpecificPattern, (match, agentId) => {
|
|
713
|
-
return generateSessionHarnessContent(coreDir, agentId);
|
|
714
|
-
});
|
|
715
|
-
|
|
716
|
-
// Then, handle generic format: <!-- {{SESSION_HARNESS}} -->
|
|
717
|
-
// Try to extract agent ID from frontmatter name field if available
|
|
718
|
-
const genericPattern = /<!-- \{\{SESSION_HARNESS\}\} -->/g;
|
|
719
|
-
result = result.replace(genericPattern, () => {
|
|
720
|
-
// Try to get agent ID from frontmatter 'name' field
|
|
721
|
-
// Look for "name: agileflow-xxx" pattern in the content
|
|
722
|
-
const frontmatterMatch = result.match(/^---[\s\S]*?name:\s*(agileflow-)?(\w+)[\s\S]*?---/m);
|
|
723
|
-
let agentId = 'AGENT';
|
|
724
|
-
if (frontmatterMatch && frontmatterMatch[2]) {
|
|
725
|
-
// Convert agent name to uppercase agent ID format
|
|
726
|
-
// e.g., "api" -> "AG-API", "ui" -> "AG-UI"
|
|
727
|
-
agentId = `AG-${frontmatterMatch[2].toUpperCase()}`;
|
|
728
|
-
}
|
|
729
|
-
return generateSessionHarnessContent(coreDir, agentId);
|
|
730
|
-
});
|
|
731
|
-
|
|
732
|
-
// Also handle non-comment format: {{SESSION_HARNESS}}
|
|
733
|
-
result = result.replace(/\{\{SESSION_HARNESS\}\}/g, () => {
|
|
734
|
-
const frontmatterMatch = result.match(/^---[\s\S]*?name:\s*(agileflow-)?(\w+)[\s\S]*?---/m);
|
|
735
|
-
let agentId = 'AGENT';
|
|
736
|
-
if (frontmatterMatch && frontmatterMatch[2]) {
|
|
737
|
-
agentId = `AG-${frontmatterMatch[2].toUpperCase()}`;
|
|
738
|
-
}
|
|
739
|
-
return generateSessionHarnessContent(coreDir, agentId);
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
// Replace quality gate priorities template placeholder
|
|
744
|
-
// Supports: <!-- {{QUALITY_GATE_PRIORITIES}} -->
|
|
745
|
-
if (result.includes('QUALITY_GATE_PRIORITIES')) {
|
|
746
|
-
// Handle comment format: <!-- {{QUALITY_GATE_PRIORITIES}} -->
|
|
747
|
-
const qualityGatePattern = /<!-- \{\{QUALITY_GATE_PRIORITIES\}\} -->/g;
|
|
748
|
-
result = result.replace(qualityGatePattern, () => {
|
|
749
|
-
const frontmatterMatch = result.match(/^---[\s\S]*?name:\s*(agileflow-)?(\w+)[\s\S]*?---/m);
|
|
750
|
-
let agentId = 'AGENT';
|
|
751
|
-
if (frontmatterMatch && frontmatterMatch[2]) {
|
|
752
|
-
agentId = `AG-${frontmatterMatch[2].toUpperCase()}`;
|
|
753
|
-
}
|
|
754
|
-
return generateQualityGatePrioritiesContent(coreDir, agentId);
|
|
755
|
-
});
|
|
756
|
-
|
|
757
|
-
// Also handle non-comment format: {{QUALITY_GATE_PRIORITIES}}
|
|
758
|
-
result = result.replace(/\{\{QUALITY_GATE_PRIORITIES\}\}/g, () => {
|
|
759
|
-
const frontmatterMatch = result.match(/^---[\s\S]*?name:\s*(agileflow-)?(\w+)[\s\S]*?---/m);
|
|
760
|
-
let agentId = 'AGENT';
|
|
761
|
-
if (frontmatterMatch && frontmatterMatch[2]) {
|
|
762
|
-
agentId = `AG-${frontmatterMatch[2].toUpperCase()}`;
|
|
763
|
-
}
|
|
764
|
-
return generateQualityGatePrioritiesContent(coreDir, agentId);
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// Replace folder placeholders with sanitized values
|
|
770
|
-
result = result.replace(/\{agileflow_folder\}/g, safeAgileflowFolder);
|
|
771
|
-
result = result.replace(/\{docs_folder\}/g, safeDocsFolder);
|
|
772
|
-
result = result.replace(/\{project-root\}/g, '{project-root}'); // Keep as-is for runtime
|
|
773
|
-
|
|
774
|
-
// Replace docs/ path references with actual folder if different from default
|
|
775
|
-
// This ensures all path references point to the correct folder
|
|
776
|
-
// Pattern matches: `docs/`, "docs/", 'docs/' but NOT word boundaries like "documents/"
|
|
777
|
-
if (safeDocsFolder !== 'docs') {
|
|
778
|
-
// Replace in code/path contexts: `docs/xxx`, "docs/xxx", 'docs/xxx'
|
|
779
|
-
result = result.replace(/`docs\//g, `\`${safeDocsFolder}/`);
|
|
780
|
-
result = result.replace(/"docs\//g, `"${safeDocsFolder}/`);
|
|
781
|
-
result = result.replace(/'docs\//g, `'${safeDocsFolder}/`);
|
|
782
|
-
// Replace standalone path references like: docs/00-meta, docs/09-agents
|
|
783
|
-
// Must be followed by a path component (letter, number, or dash)
|
|
784
|
-
result = result.replace(/\bdocs\/([0-9a-zA-Z_-])/g, `${safeDocsFolder}/$1`);
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
return result;
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
// =============================================================================
|
|
791
|
-
// Section Processing Functions (Progressive Disclosure)
|
|
792
|
-
// =============================================================================
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
* Extract section names from content
|
|
796
|
-
* @param {string} content - Content with section markers
|
|
797
|
-
* @returns {string[]} Array of section names
|
|
798
|
-
*/
|
|
799
|
-
function extractSectionNames(content) {
|
|
800
|
-
const sectionPattern = /<!-- SECTION: (\w+[-\w]*) -->/g;
|
|
801
|
-
const sections = [];
|
|
802
|
-
let match;
|
|
803
|
-
while ((match = sectionPattern.exec(content)) !== null) {
|
|
804
|
-
sections.push(match[1]);
|
|
805
|
-
}
|
|
806
|
-
return sections;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
/**
|
|
810
|
-
* Filter content to only include specified sections
|
|
811
|
-
* Sections are marked with: <!-- SECTION: name --> ... <!-- END_SECTION -->
|
|
812
|
-
*
|
|
813
|
-
* @param {string} content - Content with section markers
|
|
814
|
-
* @param {string[]} activeSections - Sections to include (empty = include all)
|
|
815
|
-
* @returns {string} Content with only active sections
|
|
816
|
-
*/
|
|
817
|
-
function filterSections(content, activeSections = []) {
|
|
818
|
-
// If no active sections specified, include all content
|
|
819
|
-
if (!activeSections || activeSections.length === 0) {
|
|
820
|
-
return content;
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
// Pattern matches: <!-- SECTION: name --> content <!-- END_SECTION -->
|
|
824
|
-
const sectionPattern = /<!-- SECTION: (\w+[-\w]*) -->([\s\S]*?)<!-- END_SECTION -->/g;
|
|
825
|
-
|
|
826
|
-
return content.replace(sectionPattern, (match, sectionName, sectionContent) => {
|
|
827
|
-
if (activeSections.includes(sectionName)) {
|
|
828
|
-
// Keep the section content, remove the markers
|
|
829
|
-
return sectionContent;
|
|
830
|
-
}
|
|
831
|
-
// Remove the entire section
|
|
832
|
-
return '';
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
/**
|
|
837
|
-
* Remove all section markers but keep content
|
|
838
|
-
* Used when no filtering is needed but markers should be cleaned
|
|
839
|
-
*
|
|
840
|
-
* @param {string} content - Content with section markers
|
|
841
|
-
* @returns {string} Content without section markers
|
|
842
|
-
*/
|
|
843
|
-
function stripSectionMarkers(content) {
|
|
844
|
-
// Remove section start markers
|
|
845
|
-
let result = content.replace(/<!-- SECTION: \w+[-\w]* -->\n?/g, '');
|
|
846
|
-
// Remove section end markers
|
|
847
|
-
result = result.replace(/<!-- END_SECTION -->\n?/g, '');
|
|
848
|
-
return result;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
/**
|
|
852
|
-
* Check if content has section markers
|
|
853
|
-
* @param {string} content - Content to check
|
|
854
|
-
* @returns {boolean} True if content has sections
|
|
855
|
-
*/
|
|
856
|
-
function hasSections(content) {
|
|
857
|
-
return /<!-- SECTION: \w+[-\w]* -->/.test(content);
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// =============================================================================
|
|
861
|
-
// Utility Functions
|
|
862
|
-
// =============================================================================
|
|
863
|
-
|
|
864
|
-
/**
|
|
865
|
-
* Check if content has any template variables
|
|
866
|
-
* @param {string} content - Content to check
|
|
867
|
-
* @returns {boolean} True if content has placeholders
|
|
868
|
-
*/
|
|
869
|
-
function hasPlaceholders(content) {
|
|
870
|
-
const patterns = [
|
|
871
|
-
/\{\{COMMAND_COUNT\}\}/,
|
|
872
|
-
/\{\{AGENT_COUNT\}\}/,
|
|
873
|
-
/\{\{SKILL_COUNT\}\}/,
|
|
874
|
-
/\{\{VERSION\}\}/,
|
|
875
|
-
/\{\{INSTALL_DATE\}\}/,
|
|
876
|
-
/\{\{AGENT_LIST\}\}/,
|
|
877
|
-
/\{\{COMMAND_LIST\}\}/,
|
|
878
|
-
/\{\{SESSION_HARNESS\}\}/,
|
|
879
|
-
/\{\{QUALITY_GATE_PRIORITIES\}\}/,
|
|
880
|
-
/\{\{RULES:\w+\}\}/,
|
|
881
|
-
/\{agileflow_folder\}/,
|
|
882
|
-
/\{docs_folder\}/,
|
|
883
|
-
];
|
|
884
|
-
|
|
885
|
-
return patterns.some(pattern => pattern.test(content));
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
* List all supported placeholders
|
|
890
|
-
* @returns {Object} Placeholder documentation
|
|
891
|
-
*/
|
|
892
|
-
function getPlaceholderDocs() {
|
|
893
|
-
return {
|
|
894
|
-
counts: {
|
|
895
|
-
'{{COMMAND_COUNT}}': 'Total number of slash commands',
|
|
896
|
-
'{{AGENT_COUNT}}': 'Total number of specialized agents',
|
|
897
|
-
'{{SKILL_COUNT}}': 'Total number of skills',
|
|
898
|
-
},
|
|
899
|
-
lists: {
|
|
900
|
-
'<!-- {{AGENT_LIST}} -->': 'Full formatted agent list with details',
|
|
901
|
-
'<!-- {{COMMAND_LIST}} -->': 'Full formatted command list',
|
|
902
|
-
},
|
|
903
|
-
templates: {
|
|
904
|
-
'<!-- {{SESSION_HARNESS}} -->':
|
|
905
|
-
'Session harness protocol (auto-detects agent ID from frontmatter)',
|
|
906
|
-
'<!-- {{SESSION_HARNESS:AG-API}} -->': 'Session harness protocol with explicit agent ID',
|
|
907
|
-
'<!-- {{QUALITY_GATE_PRIORITIES}} -->':
|
|
908
|
-
'Quality gate priorities with CRITICAL/HIGH/MEDIUM levels',
|
|
909
|
-
},
|
|
910
|
-
preserve_rules: {
|
|
911
|
-
'{{RULES:json_operations}}': 'Rules for safe JSON file modifications',
|
|
912
|
-
'{{RULES:file_preview}}': 'Rules for showing previews before writing',
|
|
913
|
-
'{{RULES:user_confirmation}}': 'Rules for using AskUserQuestion tool',
|
|
914
|
-
'{{RULES:task_tracking}}': 'Rules for using TaskCreate/TaskUpdate tool',
|
|
915
|
-
'{{RULES:bus_messaging}}': 'Rules for bus message logging',
|
|
916
|
-
'{{RULES:plan_mode}}': 'Rules for using EnterPlanMode',
|
|
917
|
-
'{{RULES:commit_approval}}': 'Rules about git commits',
|
|
918
|
-
'{{RULES:delegation}}': 'Rules for expert delegation',
|
|
919
|
-
'{{RULES:research_first}}': 'Rules for checking research before starting',
|
|
920
|
-
'{{RULES:status_updates}}': 'Rules for updating status.json',
|
|
921
|
-
},
|
|
922
|
-
metadata: {
|
|
923
|
-
'{{VERSION}}': 'AgileFlow version from package.json',
|
|
924
|
-
'{{INSTALL_DATE}}': 'Installation date (YYYY-MM-DD)',
|
|
925
|
-
},
|
|
926
|
-
folders: {
|
|
927
|
-
'{agileflow_folder}': 'Name of the AgileFlow folder',
|
|
928
|
-
'{docs_folder}': 'Name of the docs folder (docs/ paths auto-replaced when different)',
|
|
929
|
-
'{project-root}': 'Project root reference (kept as-is)',
|
|
930
|
-
},
|
|
931
|
-
};
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
module.exports = {
|
|
935
|
-
// Count functions
|
|
936
|
-
countCommands,
|
|
937
|
-
countAgents,
|
|
938
|
-
countSkills,
|
|
939
|
-
getCounts,
|
|
940
|
-
|
|
941
|
-
// List generation
|
|
942
|
-
generateAgentList,
|
|
943
|
-
generateCommandList,
|
|
944
|
-
|
|
945
|
-
// Summary generation (compact, for minimal mode)
|
|
946
|
-
generateAgentSummary,
|
|
947
|
-
generateCommandSummary,
|
|
948
|
-
|
|
949
|
-
// Template generation
|
|
950
|
-
generateSessionHarnessContent,
|
|
951
|
-
clearSessionHarnessCache,
|
|
952
|
-
generateQualityGatePrioritiesContent,
|
|
953
|
-
clearQualityGatePrioritiesCache,
|
|
954
|
-
|
|
955
|
-
// Preserve rules expansion
|
|
956
|
-
expandPreserveRules,
|
|
957
|
-
clearPreserveRulesCache,
|
|
958
|
-
|
|
959
|
-
// Main injection
|
|
960
|
-
injectContent,
|
|
961
|
-
hasPlaceholders,
|
|
962
|
-
getPlaceholderDocs,
|
|
963
|
-
|
|
964
|
-
// Section processing (progressive disclosure)
|
|
965
|
-
extractSectionNames,
|
|
966
|
-
filterSections,
|
|
967
|
-
stripSectionMarkers,
|
|
968
|
-
hasSections,
|
|
969
|
-
};
|