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,840 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* context-loader.js
|
|
4
|
-
*
|
|
5
|
-
* Data loading module for obtain-context.js (US-0148)
|
|
6
|
-
*
|
|
7
|
-
* Responsibilities:
|
|
8
|
-
* - Synchronous and asynchronous file/JSON/directory reading
|
|
9
|
-
* - Git command execution
|
|
10
|
-
* - Parallel pre-fetching of all required data
|
|
11
|
-
* - Context budget tracking from Claude session files
|
|
12
|
-
* - Lazy loading configuration and section determination
|
|
13
|
-
* - Command argument parsing
|
|
14
|
-
*
|
|
15
|
-
* Performance optimization: Uses Promise.all() for parallel I/O (US-0092)
|
|
16
|
-
* Lazy evaluation: Conditionally loads sections based on command (US-0093)
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const fsPromises = require('fs').promises;
|
|
21
|
-
const path = require('path');
|
|
22
|
-
const os = require('os');
|
|
23
|
-
const { spawnSync, spawn } = require('child_process');
|
|
24
|
-
|
|
25
|
-
// Try to use cached reads if available
|
|
26
|
-
let readJSONCached, readFileCached;
|
|
27
|
-
try {
|
|
28
|
-
const fileCache = require('../../lib/file-cache');
|
|
29
|
-
readJSONCached = fileCache.readJSONCached;
|
|
30
|
-
readFileCached = fileCache.readFileCached;
|
|
31
|
-
} catch {
|
|
32
|
-
// Fallback if file-cache not available
|
|
33
|
-
readJSONCached = null;
|
|
34
|
-
readFileCached = null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// =============================================================================
|
|
38
|
-
// Command Whitelist for safeExec (US-0120)
|
|
39
|
-
// =============================================================================
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Whitelisted git subcommands with allowed arguments (US-0187)
|
|
43
|
-
* Only these specific read-only git operations are permitted.
|
|
44
|
-
*
|
|
45
|
-
* Format: { subcommand: true } allows any args (read-only commands)
|
|
46
|
-
* { subcommand: ['--flag1', '--flag2'] } allows only listed first args
|
|
47
|
-
*/
|
|
48
|
-
const SAFEEXEC_ALLOWED_GIT_SUBCOMMANDS = {
|
|
49
|
-
// Read-only git operations
|
|
50
|
-
branch: ['--show-current', '-a', '--list', '-r', '--all'],
|
|
51
|
-
log: true, // All log flags are read-only
|
|
52
|
-
status: ['--short', '--porcelain', '-s', '--ignored'],
|
|
53
|
-
diff: true, // All diff flags are read-only
|
|
54
|
-
'rev-parse': ['HEAD', '--git-dir', '--show-toplevel', '--abbrev-ref', '--is-inside-work-tree'],
|
|
55
|
-
describe: true, // Read-only
|
|
56
|
-
show: true, // Read-only
|
|
57
|
-
config: ['--get', '--list', '-l', '--get-all'], // Read-only config operations only
|
|
58
|
-
remote: ['-v', '--verbose', 'get-url'],
|
|
59
|
-
tag: ['--list', '-l'],
|
|
60
|
-
'ls-files': true, // Read-only listing
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Dangerous patterns that should never be executed
|
|
65
|
-
*/
|
|
66
|
-
const SAFEEXEC_BLOCKED_PATTERNS = [
|
|
67
|
-
/\|/, // Pipe
|
|
68
|
-
/;/, // Command separator
|
|
69
|
-
/&&/, // AND operator
|
|
70
|
-
/\|\|/, // OR operator
|
|
71
|
-
/`/, // Backticks
|
|
72
|
-
/\$\(/, // Command substitution
|
|
73
|
-
/>/, // Redirect output
|
|
74
|
-
/</, // Redirect input
|
|
75
|
-
/\bsudo\b/, // Sudo
|
|
76
|
-
/\brm\b/, // Remove
|
|
77
|
-
/\bmv\b/, // Move
|
|
78
|
-
/\bcp\b/, // Copy
|
|
79
|
-
/\bchmod\b/, // Change permissions
|
|
80
|
-
/\bchown\b/, // Change owner
|
|
81
|
-
/\bcurl\b/, // curl (network)
|
|
82
|
-
/\bwget\b/, // wget (network)
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Logger for safeExec operations (configurable)
|
|
87
|
-
*/
|
|
88
|
-
let _safeExecLogger = null;
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Configure the safeExec logger
|
|
92
|
-
* @param {Function|null} logger - Logger function or null to disable
|
|
93
|
-
*/
|
|
94
|
-
function configureSafeExecLogger(logger) {
|
|
95
|
-
_safeExecLogger = logger;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Log a safeExec operation
|
|
100
|
-
* @param {string} level - Log level ('debug', 'warn', 'error')
|
|
101
|
-
* @param {string} message - Log message
|
|
102
|
-
* @param {Object} [details] - Additional details
|
|
103
|
-
*/
|
|
104
|
-
function logSafeExec(level, message, details = {}) {
|
|
105
|
-
if (_safeExecLogger) {
|
|
106
|
-
_safeExecLogger(level, message, details);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Parse a git command string into executable and arguments (US-0187)
|
|
112
|
-
* @param {string} cmd - Command string (e.g., "git branch --show-current")
|
|
113
|
-
* @returns {{ ok: boolean, data?: { executable: string, subcommand: string, args: string[], fullArgs: string[] }, error?: string }}
|
|
114
|
-
*/
|
|
115
|
-
function parseGitCommand(cmd) {
|
|
116
|
-
if (!cmd || typeof cmd !== 'string') {
|
|
117
|
-
return { ok: false, error: 'Invalid command' };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const parts = cmd.trim().split(/\s+/);
|
|
121
|
-
if (parts.length < 1 || parts[0] !== 'git') {
|
|
122
|
-
return { ok: false, error: 'Only git commands are supported' };
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Handle bare 'git' command
|
|
126
|
-
if (parts.length < 2) {
|
|
127
|
-
return { ok: false, error: 'Git subcommand required' };
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
ok: true,
|
|
132
|
-
data: {
|
|
133
|
-
executable: 'git',
|
|
134
|
-
subcommand: parts[1],
|
|
135
|
-
args: parts.slice(2),
|
|
136
|
-
fullArgs: parts.slice(1), // ['branch', '--show-current']
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Check if a git subcommand with args is allowed (US-0187)
|
|
143
|
-
* @param {string} subcommand - Git subcommand (e.g., 'branch')
|
|
144
|
-
* @param {string[]} args - Arguments to subcommand
|
|
145
|
-
* @returns {{ allowed: boolean, reason?: string }}
|
|
146
|
-
*/
|
|
147
|
-
function isGitCommandAllowed(subcommand, args) {
|
|
148
|
-
// First check blocked patterns in arguments
|
|
149
|
-
const fullCmd = `git ${subcommand} ${args.join(' ')}`;
|
|
150
|
-
for (const pattern of SAFEEXEC_BLOCKED_PATTERNS) {
|
|
151
|
-
if (pattern.test(fullCmd)) {
|
|
152
|
-
return { allowed: false, reason: `Blocked pattern: ${pattern}` };
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Check against allowed subcommands
|
|
157
|
-
const allowedArgs = SAFEEXEC_ALLOWED_GIT_SUBCOMMANDS[subcommand];
|
|
158
|
-
if (!allowedArgs) {
|
|
159
|
-
return { allowed: false, reason: `Git subcommand '${subcommand}' not in whitelist` };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// If allowedArgs is true, any args are allowed for this subcommand (read-only)
|
|
163
|
-
if (allowedArgs === true) {
|
|
164
|
-
return { allowed: true };
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// If allowedArgs is an array, first arg must match one of the allowed values
|
|
168
|
-
// (or args can be empty for commands like 'git status')
|
|
169
|
-
if (args.length === 0) {
|
|
170
|
-
return { allowed: true };
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (allowedArgs.includes(args[0])) {
|
|
174
|
-
return { allowed: true };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return { allowed: false, reason: `Argument '${args[0]}' not allowed for 'git ${subcommand}'` };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Check if a command is allowed (legacy wrapper for backwards compatibility)
|
|
182
|
-
* @param {string} cmd - Command to check
|
|
183
|
-
* @returns {{allowed: boolean, reason?: string}}
|
|
184
|
-
*/
|
|
185
|
-
function isCommandAllowed(cmd) {
|
|
186
|
-
const parsed = parseGitCommand(cmd);
|
|
187
|
-
if (!parsed.ok) {
|
|
188
|
-
return { allowed: false, reason: parsed.error };
|
|
189
|
-
}
|
|
190
|
-
return isGitCommandAllowed(parsed.data.subcommand, parsed.data.args);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// =============================================================================
|
|
194
|
-
// Synchronous I/O Helpers
|
|
195
|
-
// =============================================================================
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Safely read a file, returning null on error.
|
|
199
|
-
* @param {string} filePath - Path to file
|
|
200
|
-
* @returns {string|null} File contents or null
|
|
201
|
-
*/
|
|
202
|
-
function safeRead(filePath) {
|
|
203
|
-
try {
|
|
204
|
-
return fs.readFileSync(filePath, 'utf8');
|
|
205
|
-
} catch {
|
|
206
|
-
return null;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Safely read and parse JSON file, using cache when available.
|
|
212
|
-
* @param {string} filePath - Path to JSON file
|
|
213
|
-
* @returns {Object|null} Parsed JSON or null
|
|
214
|
-
*/
|
|
215
|
-
function safeReadJSON(filePath) {
|
|
216
|
-
if (readJSONCached) {
|
|
217
|
-
const absPath = path.resolve(filePath);
|
|
218
|
-
return readJSONCached(absPath);
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
222
|
-
return JSON.parse(content);
|
|
223
|
-
} catch {
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Safely list directory contents.
|
|
230
|
-
* @param {string} dirPath - Directory path
|
|
231
|
-
* @returns {string[]} Array of filenames or empty array
|
|
232
|
-
*/
|
|
233
|
-
function safeLs(dirPath) {
|
|
234
|
-
try {
|
|
235
|
-
return fs.readdirSync(dirPath);
|
|
236
|
-
} catch {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Safely execute a git command with whitelist validation (US-0187).
|
|
243
|
-
*
|
|
244
|
-
* Uses spawnSync with shell: false to prevent shell injection.
|
|
245
|
-
* Only whitelisted read-only git commands are allowed.
|
|
246
|
-
* Dangerous patterns (pipes, redirects, etc.) are blocked.
|
|
247
|
-
*
|
|
248
|
-
* @param {string} cmd - Command to execute (must be a git command)
|
|
249
|
-
* @param {Object} [options] - Options
|
|
250
|
-
* @param {boolean} [options.bypassWhitelist=false] - Skip whitelist check (use with caution)
|
|
251
|
-
* @returns {string|null} Command output or null
|
|
252
|
-
*/
|
|
253
|
-
function safeExec(cmd, options = {}) {
|
|
254
|
-
const { bypassWhitelist = false } = options;
|
|
255
|
-
|
|
256
|
-
// Parse command into executable and arguments
|
|
257
|
-
const parsed = parseGitCommand(cmd);
|
|
258
|
-
if (!parsed.ok) {
|
|
259
|
-
logSafeExec('warn', 'Invalid command format', {
|
|
260
|
-
cmd: cmd?.substring(0, 100),
|
|
261
|
-
error: parsed.error,
|
|
262
|
-
});
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Validate command unless bypassed
|
|
267
|
-
if (!bypassWhitelist) {
|
|
268
|
-
const check = isGitCommandAllowed(parsed.data.subcommand, parsed.data.args);
|
|
269
|
-
if (!check.allowed) {
|
|
270
|
-
logSafeExec('warn', 'Command blocked by whitelist', {
|
|
271
|
-
cmd: cmd?.substring(0, 100),
|
|
272
|
-
reason: check.reason,
|
|
273
|
-
});
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
logSafeExec('debug', 'Executing command', {
|
|
279
|
-
cmd: cmd?.substring(0, 100),
|
|
280
|
-
bypassed: bypassWhitelist,
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
try {
|
|
284
|
-
// Use spawnSync with array arguments - NO SHELL INTERPRETATION (US-0187)
|
|
285
|
-
const result = spawnSync(parsed.data.executable, parsed.data.fullArgs, {
|
|
286
|
-
encoding: 'utf8',
|
|
287
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
288
|
-
shell: false, // CRITICAL: Prevents shell injection
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
if (result.error) {
|
|
292
|
-
logSafeExec('error', 'Command spawn failed', {
|
|
293
|
-
cmd: cmd?.substring(0, 50),
|
|
294
|
-
error: result.error.message,
|
|
295
|
-
});
|
|
296
|
-
return null;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (result.status !== 0) {
|
|
300
|
-
logSafeExec('debug', 'Command exited non-zero', {
|
|
301
|
-
cmd: cmd?.substring(0, 50),
|
|
302
|
-
status: result.status,
|
|
303
|
-
stderr: result.stderr?.substring(0, 100),
|
|
304
|
-
});
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const output = (result.stdout || '').trim();
|
|
309
|
-
logSafeExec('debug', 'Command succeeded', {
|
|
310
|
-
cmd: cmd?.substring(0, 50),
|
|
311
|
-
outputLength: output.length,
|
|
312
|
-
});
|
|
313
|
-
return output;
|
|
314
|
-
} catch (error) {
|
|
315
|
-
logSafeExec('error', 'Command execution error', {
|
|
316
|
-
cmd: cmd?.substring(0, 50),
|
|
317
|
-
error: error?.message?.substring(0, 100),
|
|
318
|
-
});
|
|
319
|
-
return null;
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// =============================================================================
|
|
324
|
-
// Asynchronous I/O Helpers
|
|
325
|
-
// =============================================================================
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Asynchronously read a file.
|
|
329
|
-
* @param {string} filePath - Path to file
|
|
330
|
-
* @returns {Promise<string|null>} File contents or null
|
|
331
|
-
*/
|
|
332
|
-
async function safeReadAsync(filePath) {
|
|
333
|
-
try {
|
|
334
|
-
return await fsPromises.readFile(filePath, 'utf8');
|
|
335
|
-
} catch {
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Asynchronously read and parse JSON file.
|
|
342
|
-
* @param {string} filePath - Path to JSON file
|
|
343
|
-
* @returns {Promise<Object|null>} Parsed JSON or null
|
|
344
|
-
*/
|
|
345
|
-
async function safeReadJSONAsync(filePath) {
|
|
346
|
-
try {
|
|
347
|
-
const content = await fsPromises.readFile(filePath, 'utf8');
|
|
348
|
-
return JSON.parse(content);
|
|
349
|
-
} catch {
|
|
350
|
-
return null;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Asynchronously list directory contents.
|
|
356
|
-
* @param {string} dirPath - Directory path
|
|
357
|
-
* @returns {Promise<string[]>} Array of filenames or empty array
|
|
358
|
-
*/
|
|
359
|
-
async function safeLsAsync(dirPath) {
|
|
360
|
-
try {
|
|
361
|
-
return await fsPromises.readdir(dirPath);
|
|
362
|
-
} catch {
|
|
363
|
-
return [];
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Execute a git command asynchronously with whitelist validation (US-0187).
|
|
369
|
-
*
|
|
370
|
-
* Uses spawn with shell: false to prevent shell injection.
|
|
371
|
-
* Only whitelisted read-only git commands are allowed.
|
|
372
|
-
* Dangerous patterns (pipes, redirects, etc.) are blocked.
|
|
373
|
-
*
|
|
374
|
-
* @param {string} cmd - Command to execute (must be a git command)
|
|
375
|
-
* @param {Object} [options] - Options
|
|
376
|
-
* @param {boolean} [options.bypassWhitelist=false] - Skip whitelist check (use with caution)
|
|
377
|
-
* @returns {Promise<string|null>} Command output or null
|
|
378
|
-
*/
|
|
379
|
-
async function safeExecAsync(cmd, options = {}) {
|
|
380
|
-
const { bypassWhitelist = false } = options;
|
|
381
|
-
|
|
382
|
-
// Parse command into executable and arguments
|
|
383
|
-
const parsed = parseGitCommand(cmd);
|
|
384
|
-
if (!parsed.ok) {
|
|
385
|
-
logSafeExec('warn', 'Invalid async command format', {
|
|
386
|
-
cmd: cmd?.substring(0, 100),
|
|
387
|
-
error: parsed.error,
|
|
388
|
-
});
|
|
389
|
-
return null;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// Validate command unless bypassed
|
|
393
|
-
if (!bypassWhitelist) {
|
|
394
|
-
const check = isGitCommandAllowed(parsed.data.subcommand, parsed.data.args);
|
|
395
|
-
if (!check.allowed) {
|
|
396
|
-
logSafeExec('warn', 'Async command blocked by whitelist', {
|
|
397
|
-
cmd: cmd?.substring(0, 100),
|
|
398
|
-
reason: check.reason,
|
|
399
|
-
});
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
logSafeExec('debug', 'Executing async command', {
|
|
405
|
-
cmd: cmd?.substring(0, 100),
|
|
406
|
-
bypassed: bypassWhitelist,
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
return new Promise(resolve => {
|
|
410
|
-
// Use spawn with array arguments - NO SHELL INTERPRETATION (US-0187)
|
|
411
|
-
const proc = spawn(parsed.data.executable, parsed.data.fullArgs, {
|
|
412
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
413
|
-
shell: false, // CRITICAL: Prevents shell injection
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
let stdout = '';
|
|
417
|
-
let stderr = '';
|
|
418
|
-
|
|
419
|
-
proc.stdout.on('data', data => {
|
|
420
|
-
stdout += data;
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
proc.stderr.on('data', data => {
|
|
424
|
-
stderr += data;
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
proc.on('error', error => {
|
|
428
|
-
logSafeExec('error', 'Async spawn error', {
|
|
429
|
-
cmd: cmd?.substring(0, 50),
|
|
430
|
-
error: error.message,
|
|
431
|
-
});
|
|
432
|
-
resolve(null);
|
|
433
|
-
});
|
|
434
|
-
|
|
435
|
-
proc.on('close', code => {
|
|
436
|
-
if (code !== 0) {
|
|
437
|
-
logSafeExec('debug', 'Async command exited non-zero', {
|
|
438
|
-
cmd: cmd?.substring(0, 50),
|
|
439
|
-
code,
|
|
440
|
-
stderr: stderr?.substring(0, 100),
|
|
441
|
-
});
|
|
442
|
-
resolve(null);
|
|
443
|
-
} else {
|
|
444
|
-
const result = stdout.trim();
|
|
445
|
-
logSafeExec('debug', 'Async command succeeded', {
|
|
446
|
-
cmd: cmd?.substring(0, 50),
|
|
447
|
-
outputLength: result.length,
|
|
448
|
-
});
|
|
449
|
-
resolve(result);
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// =============================================================================
|
|
456
|
-
// Context Budget Tracking (GSD Integration)
|
|
457
|
-
// =============================================================================
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Get current context usage percentage from Claude's session files.
|
|
461
|
-
* Reads token counts from the active session JSONL file.
|
|
462
|
-
*
|
|
463
|
-
* @returns {{ percent: number, tokens: number, max: number } | null}
|
|
464
|
-
*/
|
|
465
|
-
function getContextPercentage() {
|
|
466
|
-
try {
|
|
467
|
-
const homeDir = os.homedir();
|
|
468
|
-
const cwd = process.cwd();
|
|
469
|
-
|
|
470
|
-
// Convert current dir to Claude's session file path format
|
|
471
|
-
const projectDir = cwd
|
|
472
|
-
.replace(homeDir, '~')
|
|
473
|
-
.replace('~', homeDir)
|
|
474
|
-
.replace(/\//g, '-')
|
|
475
|
-
.replace(/^-/, '');
|
|
476
|
-
const sessionDir = path.join(homeDir, '.claude', 'projects', `-${projectDir}`);
|
|
477
|
-
|
|
478
|
-
if (!fs.existsSync(sessionDir)) {
|
|
479
|
-
return null;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Find most recent .jsonl session file
|
|
483
|
-
const files = fs
|
|
484
|
-
.readdirSync(sessionDir)
|
|
485
|
-
.filter(f => f.endsWith('.jsonl'))
|
|
486
|
-
.map(f => ({
|
|
487
|
-
name: f,
|
|
488
|
-
mtime: fs.statSync(path.join(sessionDir, f)).mtime.getTime(),
|
|
489
|
-
}))
|
|
490
|
-
.sort((a, b) => b.mtime - a.mtime);
|
|
491
|
-
|
|
492
|
-
if (files.length === 0) {
|
|
493
|
-
return null;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
const sessionFile = path.join(sessionDir, files[0].name);
|
|
497
|
-
const content = fs.readFileSync(sessionFile, 'utf8');
|
|
498
|
-
const lines = content.trim().split('\n').slice(-20); // Last 20 lines
|
|
499
|
-
|
|
500
|
-
// Find latest usage entry
|
|
501
|
-
let latestTokens = 0;
|
|
502
|
-
for (const line of lines.reverse()) {
|
|
503
|
-
try {
|
|
504
|
-
const entry = JSON.parse(line);
|
|
505
|
-
if (entry?.message?.usage) {
|
|
506
|
-
const usage = entry.message.usage;
|
|
507
|
-
latestTokens = (usage.input_tokens || 0) + (usage.cache_read_input_tokens || 0);
|
|
508
|
-
if (latestTokens > 0) break;
|
|
509
|
-
}
|
|
510
|
-
} catch {
|
|
511
|
-
// Skip malformed lines
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
if (latestTokens === 0) {
|
|
516
|
-
return null;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Default to 200K context for modern Claude models
|
|
520
|
-
const maxContext = 200000;
|
|
521
|
-
const percent = Math.min(100, Math.round((latestTokens * 100) / maxContext));
|
|
522
|
-
|
|
523
|
-
return { percent, tokens: latestTokens, max: maxContext };
|
|
524
|
-
} catch {
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// =============================================================================
|
|
530
|
-
// Lazy Evaluation Configuration (US-0093)
|
|
531
|
-
// =============================================================================
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Commands that need full research notes content
|
|
535
|
-
*/
|
|
536
|
-
const RESEARCH_COMMANDS = ['research', 'ideate', 'mentor', 'rpi'];
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Determine which sections need to be loaded based on command and environment.
|
|
540
|
-
*
|
|
541
|
-
* @param {string} cmdName - Command name being executed
|
|
542
|
-
* @param {Object} lazyConfig - Lazy context configuration from metadata
|
|
543
|
-
* @param {boolean} isMultiSession - Whether multiple sessions are detected
|
|
544
|
-
* @returns {Object} Sections to load { researchContent, sessionClaims, fileOverlaps }
|
|
545
|
-
*/
|
|
546
|
-
function determineSectionsToLoad(cmdName, lazyConfig, isMultiSession) {
|
|
547
|
-
// If lazy loading is disabled, load everything
|
|
548
|
-
if (!lazyConfig?.enabled) {
|
|
549
|
-
return {
|
|
550
|
-
researchContent: true,
|
|
551
|
-
sessionClaims: true,
|
|
552
|
-
fileOverlaps: true,
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
// Research notes: load for research-related commands or if 'always'
|
|
557
|
-
const needsResearch =
|
|
558
|
-
lazyConfig.researchNotes === 'always' ||
|
|
559
|
-
(lazyConfig.researchNotes === 'conditional' && RESEARCH_COMMANDS.includes(cmdName));
|
|
560
|
-
|
|
561
|
-
// Session claims: load if multi-session environment or if 'always'
|
|
562
|
-
const needsClaims =
|
|
563
|
-
lazyConfig.sessionClaims === 'always' ||
|
|
564
|
-
(lazyConfig.sessionClaims === 'conditional' && isMultiSession);
|
|
565
|
-
|
|
566
|
-
// File overlaps: load if multi-session environment or if 'always'
|
|
567
|
-
const needsOverlaps =
|
|
568
|
-
lazyConfig.fileOverlaps === 'always' ||
|
|
569
|
-
(lazyConfig.fileOverlaps === 'conditional' && isMultiSession);
|
|
570
|
-
|
|
571
|
-
return {
|
|
572
|
-
researchContent: needsResearch,
|
|
573
|
-
sessionClaims: needsClaims,
|
|
574
|
-
fileOverlaps: needsOverlaps,
|
|
575
|
-
};
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
// =============================================================================
|
|
579
|
-
// Command Argument Parsing
|
|
580
|
-
// =============================================================================
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* Parse command-line arguments and determine which sections to activate.
|
|
584
|
-
*
|
|
585
|
-
* @param {string[]} args - Command-line arguments after command name
|
|
586
|
-
* @returns {Object} { activeSections: string[], params: Object }
|
|
587
|
-
*/
|
|
588
|
-
function parseCommandArgs(args) {
|
|
589
|
-
const activeSections = [];
|
|
590
|
-
const params = {};
|
|
591
|
-
|
|
592
|
-
for (const arg of args) {
|
|
593
|
-
// Parse KEY=VALUE arguments
|
|
594
|
-
const match = arg.match(/^([A-Z_]+)=(.+)$/i);
|
|
595
|
-
if (match) {
|
|
596
|
-
const [, key, value] = match;
|
|
597
|
-
params[key.toUpperCase()] = value;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Activate sections based on parameters
|
|
602
|
-
if (params.MODE === 'loop') {
|
|
603
|
-
activeSections.push('loop-mode');
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
if (params.VISUAL === 'true') {
|
|
607
|
-
activeSections.push('visual-e2e');
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// Query mode: QUERY=<pattern> triggers targeted codebase search (US-0127)
|
|
611
|
-
if (params.QUERY) {
|
|
612
|
-
activeSections.push('query-mode');
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
// Check for multi-session environment
|
|
616
|
-
const registryPath = '.agileflow/sessions/registry.json';
|
|
617
|
-
if (fs.existsSync(registryPath)) {
|
|
618
|
-
try {
|
|
619
|
-
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
620
|
-
const sessionCount = Object.keys(registry.sessions || {}).length;
|
|
621
|
-
if (sessionCount > 1) {
|
|
622
|
-
activeSections.push('multi-session');
|
|
623
|
-
}
|
|
624
|
-
} catch {
|
|
625
|
-
// Silently ignore registry read errors
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
return { activeSections, params };
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Extract command type from frontmatter (output-only vs interactive).
|
|
634
|
-
*
|
|
635
|
-
* @param {string} cmdName - Command name
|
|
636
|
-
* @returns {string} Command type ('interactive', 'output-only', etc.)
|
|
637
|
-
*/
|
|
638
|
-
function getCommandType(cmdName) {
|
|
639
|
-
// Handle nested command paths like "research/ask" -> "research/ask.md"
|
|
640
|
-
const cmdPath = cmdName.includes('/')
|
|
641
|
-
? `${cmdName.substring(0, cmdName.lastIndexOf('/'))}/${cmdName.substring(cmdName.lastIndexOf('/') + 1)}.md`
|
|
642
|
-
: `${cmdName}.md`;
|
|
643
|
-
|
|
644
|
-
const possiblePaths = [
|
|
645
|
-
`packages/cli/src/core/commands/${cmdPath}`,
|
|
646
|
-
`.agileflow/commands/${cmdPath}`,
|
|
647
|
-
`.claude/commands/agileflow/${cmdPath}`,
|
|
648
|
-
`packages/cli/src/core/commands/${cmdName.replace(/\//g, '-')}.md`,
|
|
649
|
-
];
|
|
650
|
-
|
|
651
|
-
for (const searchPath of possiblePaths) {
|
|
652
|
-
if (fs.existsSync(searchPath)) {
|
|
653
|
-
try {
|
|
654
|
-
const content = fs.readFileSync(searchPath, 'utf8');
|
|
655
|
-
const match = content.match(/^---\n[\s\S]*?type:\s*(\S+)/m);
|
|
656
|
-
if (match) {
|
|
657
|
-
return match[1].replace(/['"]/g, '');
|
|
658
|
-
}
|
|
659
|
-
} catch {
|
|
660
|
-
// Continue to next path
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
return 'interactive';
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// =============================================================================
|
|
668
|
-
// Parallel Data Pre-fetching
|
|
669
|
-
// =============================================================================
|
|
670
|
-
|
|
671
|
-
/**
|
|
672
|
-
* Pre-fetch all required data in parallel for optimal performance.
|
|
673
|
-
* This dramatically reduces I/O wait time by overlapping file reads and git commands.
|
|
674
|
-
*
|
|
675
|
-
* @param {Object} options - Options for prefetching
|
|
676
|
-
* @param {Object} options.sectionsToLoad - Which sections need full content
|
|
677
|
-
* @returns {Promise<Object>} Pre-fetched data for content generation
|
|
678
|
-
*/
|
|
679
|
-
async function prefetchAllData(options = {}) {
|
|
680
|
-
const sectionsToLoad = options.sectionsToLoad || {
|
|
681
|
-
researchContent: true,
|
|
682
|
-
sessionClaims: true,
|
|
683
|
-
fileOverlaps: true,
|
|
684
|
-
};
|
|
685
|
-
const verbosityMode = options.verbosityMode || 'full';
|
|
686
|
-
|
|
687
|
-
// Define all files to read
|
|
688
|
-
const jsonFiles = {
|
|
689
|
-
metadata: 'docs/00-meta/agileflow-metadata.json',
|
|
690
|
-
statusJson: 'docs/09-agents/status.json',
|
|
691
|
-
sessionState: 'docs/09-agents/session-state.json',
|
|
692
|
-
};
|
|
693
|
-
|
|
694
|
-
// Text files: skip heavy content in lite/minimal modes
|
|
695
|
-
const textFiles = {};
|
|
696
|
-
if (verbosityMode === 'full') {
|
|
697
|
-
textFiles.busLog = 'docs/09-agents/bus/log.jsonl';
|
|
698
|
-
textFiles.claudeMd = 'CLAUDE.md';
|
|
699
|
-
textFiles.readmeMd = 'README.md';
|
|
700
|
-
textFiles.archReadme = 'docs/04-architecture/README.md';
|
|
701
|
-
textFiles.practicesReadme = 'docs/02-practices/README.md';
|
|
702
|
-
textFiles.roadmap = 'docs/08-project/roadmap.md';
|
|
703
|
-
} else if (verbosityMode === 'lite') {
|
|
704
|
-
textFiles.busLog = 'docs/09-agents/bus/log.jsonl';
|
|
705
|
-
// Skip: claudeMd, readmeMd, archReadme, practicesReadme, roadmap
|
|
706
|
-
}
|
|
707
|
-
// minimal: skip all text files
|
|
708
|
-
|
|
709
|
-
// Directories: skip in minimal mode
|
|
710
|
-
const directories = {};
|
|
711
|
-
if (verbosityMode !== 'minimal') {
|
|
712
|
-
directories.docs = 'docs';
|
|
713
|
-
directories.research = 'docs/10-research';
|
|
714
|
-
directories.epics = 'docs/05-epics';
|
|
715
|
-
} else {
|
|
716
|
-
// minimal still needs epics dir for count
|
|
717
|
-
directories.epics = 'docs/05-epics';
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
// Git commands to run in parallel
|
|
721
|
-
const gitCommands = {
|
|
722
|
-
branch: 'git branch --show-current',
|
|
723
|
-
commitShort: 'git log -1 --format="%h"',
|
|
724
|
-
commitMsg: 'git log -1 --format="%s"',
|
|
725
|
-
commitFull: 'git log -1 --format="%h %s"',
|
|
726
|
-
status: 'git status --short',
|
|
727
|
-
};
|
|
728
|
-
|
|
729
|
-
// Create all promises for parallel execution
|
|
730
|
-
const jsonPromises = Object.entries(jsonFiles).map(async ([key, filePath]) => {
|
|
731
|
-
const data = await safeReadJSONAsync(filePath);
|
|
732
|
-
return [key, data];
|
|
733
|
-
});
|
|
734
|
-
|
|
735
|
-
const textPromises = Object.entries(textFiles).map(async ([key, filePath]) => {
|
|
736
|
-
const data = await safeReadAsync(filePath);
|
|
737
|
-
return [key, data];
|
|
738
|
-
});
|
|
739
|
-
|
|
740
|
-
const dirPromises = Object.entries(directories).map(async ([key, dirPath]) => {
|
|
741
|
-
const files = await safeLsAsync(dirPath);
|
|
742
|
-
return [key, files];
|
|
743
|
-
});
|
|
744
|
-
|
|
745
|
-
const gitPromises = Object.entries(gitCommands).map(async ([key, cmd]) => {
|
|
746
|
-
const data = await safeExecAsync(cmd);
|
|
747
|
-
return [key, data];
|
|
748
|
-
});
|
|
749
|
-
|
|
750
|
-
// Execute all I/O operations in parallel
|
|
751
|
-
const [jsonResults, textResults, dirResults, gitResults] = await Promise.all([
|
|
752
|
-
Promise.all(jsonPromises),
|
|
753
|
-
Promise.all(textPromises),
|
|
754
|
-
Promise.all(dirPromises),
|
|
755
|
-
Promise.all(gitPromises),
|
|
756
|
-
]);
|
|
757
|
-
|
|
758
|
-
// Convert arrays back to objects
|
|
759
|
-
const json = Object.fromEntries(jsonResults);
|
|
760
|
-
const text = Object.fromEntries(textResults);
|
|
761
|
-
const dirs = Object.fromEntries(dirResults);
|
|
762
|
-
const git = Object.fromEntries(gitResults);
|
|
763
|
-
|
|
764
|
-
// Determine most recent research file
|
|
765
|
-
const researchFiles = (dirs.research || [])
|
|
766
|
-
.filter(f => f.endsWith('.md') && f !== 'README.md')
|
|
767
|
-
.sort()
|
|
768
|
-
.reverse();
|
|
769
|
-
|
|
770
|
-
// Lazy loading (US-0093): Only fetch research content if needed
|
|
771
|
-
let mostRecentResearch = null;
|
|
772
|
-
if (sectionsToLoad.researchContent && researchFiles.length > 0) {
|
|
773
|
-
mostRecentResearch = await safeReadAsync(path.join('docs/10-research', researchFiles[0]));
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
return {
|
|
777
|
-
json,
|
|
778
|
-
text,
|
|
779
|
-
dirs,
|
|
780
|
-
git,
|
|
781
|
-
researchFiles,
|
|
782
|
-
mostRecentResearch,
|
|
783
|
-
sectionsToLoad,
|
|
784
|
-
};
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
/**
|
|
788
|
-
* Check if multi-session environment is detected.
|
|
789
|
-
* @returns {boolean} True if multiple sessions exist
|
|
790
|
-
*/
|
|
791
|
-
function isMultiSessionEnvironment() {
|
|
792
|
-
const registryPath = '.agileflow/sessions/registry.json';
|
|
793
|
-
if (fs.existsSync(registryPath)) {
|
|
794
|
-
try {
|
|
795
|
-
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
796
|
-
const sessionCount = Object.keys(registry.sessions || {}).length;
|
|
797
|
-
return sessionCount > 1;
|
|
798
|
-
} catch {
|
|
799
|
-
return false;
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
return false;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
module.exports = {
|
|
806
|
-
// Sync helpers
|
|
807
|
-
safeRead,
|
|
808
|
-
safeReadJSON,
|
|
809
|
-
safeLs,
|
|
810
|
-
safeExec,
|
|
811
|
-
|
|
812
|
-
// Async helpers
|
|
813
|
-
safeReadAsync,
|
|
814
|
-
safeReadJSONAsync,
|
|
815
|
-
safeLsAsync,
|
|
816
|
-
safeExecAsync,
|
|
817
|
-
|
|
818
|
-
// Command whitelist (US-0120, US-0187)
|
|
819
|
-
SAFEEXEC_ALLOWED_GIT_SUBCOMMANDS,
|
|
820
|
-
SAFEEXEC_BLOCKED_PATTERNS,
|
|
821
|
-
configureSafeExecLogger,
|
|
822
|
-
parseGitCommand,
|
|
823
|
-
isGitCommandAllowed,
|
|
824
|
-
isCommandAllowed, // Legacy wrapper for backward compatibility
|
|
825
|
-
|
|
826
|
-
// Context tracking
|
|
827
|
-
getContextPercentage,
|
|
828
|
-
|
|
829
|
-
// Lazy loading
|
|
830
|
-
RESEARCH_COMMANDS,
|
|
831
|
-
determineSectionsToLoad,
|
|
832
|
-
|
|
833
|
-
// Command parsing
|
|
834
|
-
parseCommandArgs,
|
|
835
|
-
getCommandType,
|
|
836
|
-
|
|
837
|
-
// Data prefetching
|
|
838
|
-
prefetchAllData,
|
|
839
|
-
isMultiSessionEnvironment,
|
|
840
|
-
};
|