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,877 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* spawn-audit-sessions.js - Spawn ULTRADEEP audit analyzer sessions in tmux
|
|
5
|
-
*
|
|
6
|
-
* Spawns each analyzer as a separate Claude Code session in tmux,
|
|
7
|
-
* with sentinel files for coordination and tab grouping for visual organization.
|
|
8
|
-
*
|
|
9
|
-
* Key differences from spawn-parallel.js:
|
|
10
|
-
* - No worktrees: audits are read-only, all sessions share the same repo
|
|
11
|
-
* - Piped prompts: each session gets analyzer-specific prompt via echo | claude
|
|
12
|
-
* - Sentinel files: each writes findings to docs/09-agents/ultradeep/{trace_id}/
|
|
13
|
-
* - Tab grouping: applies colors from tmux-group-colors.js
|
|
14
|
-
*
|
|
15
|
-
* Usage:
|
|
16
|
-
* node scripts/spawn-audit-sessions.js --audit=security --target=src/ --focus=all --trace-id=abc123
|
|
17
|
-
* node scripts/spawn-audit-sessions.js --audit=logic --target=. --depth=ultradeep
|
|
18
|
-
*
|
|
19
|
-
* Options:
|
|
20
|
-
* --audit=TYPE Audit type: logic|security|performance|test|completeness|legal
|
|
21
|
-
* --target=PATH Target file or directory to analyze
|
|
22
|
-
* --focus=AREAS Comma-separated focus areas, or 'all'
|
|
23
|
-
* --trace-id=ID Unique trace ID (auto-generated if not provided)
|
|
24
|
-
* --timeout=MINUTES Completion timeout (default: 30)
|
|
25
|
-
* --dry-run Show what would be spawned without executing
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
const { execFileSync } = require('child_process');
|
|
29
|
-
const fs = require('fs');
|
|
30
|
-
const path = require('path');
|
|
31
|
-
const crypto = require('crypto');
|
|
32
|
-
|
|
33
|
-
const { getAuditType, getAnalyzersForAudit } = require('./lib/audit-registry');
|
|
34
|
-
const { getColorForAudit } = require('./lib/tmux-group-colors');
|
|
35
|
-
const { resolveModel, estimateCost } = require('./lib/model-profiles');
|
|
36
|
-
|
|
37
|
-
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Read ultradeep config from agileflow-metadata.json.
|
|
41
|
-
* @returns {{ stagger_seconds: number, max_concurrent: number }}
|
|
42
|
-
*/
|
|
43
|
-
function getUltradeepConfig() {
|
|
44
|
-
const defaults = { stagger_seconds: 3, max_concurrent: 0 };
|
|
45
|
-
try {
|
|
46
|
-
const metaPath = path.join(process.cwd(), 'docs', '00-meta', 'agileflow-metadata.json');
|
|
47
|
-
if (fs.existsSync(metaPath)) {
|
|
48
|
-
const meta = JSON.parse(fs.readFileSync(metaPath, 'utf8'));
|
|
49
|
-
const ud = meta.ultradeep || {};
|
|
50
|
-
if (typeof ud.stagger_seconds === 'number') defaults.stagger_seconds = ud.stagger_seconds;
|
|
51
|
-
if (typeof ud.max_concurrent === 'number') defaults.max_concurrent = ud.max_concurrent;
|
|
52
|
-
}
|
|
53
|
-
} catch (_) {
|
|
54
|
-
/* use defaults */
|
|
55
|
-
}
|
|
56
|
-
return defaults;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Parse CLI arguments.
|
|
61
|
-
* @returns {object} Parsed options
|
|
62
|
-
*/
|
|
63
|
-
function parseArgs() {
|
|
64
|
-
const args = process.argv.slice(2);
|
|
65
|
-
const options = {
|
|
66
|
-
audit: null,
|
|
67
|
-
target: '.',
|
|
68
|
-
focus: ['all'],
|
|
69
|
-
model: null,
|
|
70
|
-
traceId: null,
|
|
71
|
-
timeout: 30,
|
|
72
|
-
dryRun: false,
|
|
73
|
-
json: false,
|
|
74
|
-
stagger: null,
|
|
75
|
-
concurrency: null,
|
|
76
|
-
depth: null,
|
|
77
|
-
partitions: null,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
for (const arg of args) {
|
|
81
|
-
if (arg.startsWith('--audit=')) options.audit = arg.split('=')[1];
|
|
82
|
-
else if (arg.startsWith('--target=')) options.target = arg.split('=')[1];
|
|
83
|
-
else if (arg.startsWith('--focus=')) options.focus = arg.split('=')[1].split(',');
|
|
84
|
-
else if (arg.startsWith('--model=')) options.model = arg.split('=')[1];
|
|
85
|
-
else if (arg.startsWith('--trace-id=')) options.traceId = arg.split('=')[1];
|
|
86
|
-
else if (arg.startsWith('--timeout=')) {
|
|
87
|
-
const parsed = parseInt(arg.split('=')[1], 10);
|
|
88
|
-
options.timeout = isNaN(parsed) ? 30 : parsed;
|
|
89
|
-
} else if (arg.startsWith('--stagger=')) {
|
|
90
|
-
const parsed = parseFloat(arg.split('=')[1]);
|
|
91
|
-
options.stagger = isNaN(parsed) ? null : parsed;
|
|
92
|
-
} else if (arg.startsWith('--concurrency=')) {
|
|
93
|
-
const parsed = parseInt(arg.split('=')[1], 10);
|
|
94
|
-
options.concurrency = isNaN(parsed) ? null : parsed;
|
|
95
|
-
} else if (arg.startsWith('--depth=')) options.depth = arg.split('=')[1];
|
|
96
|
-
else if (arg.startsWith('--partitions='))
|
|
97
|
-
options.partitions = arg.split('=')[1].split(',').filter(Boolean);
|
|
98
|
-
else if (arg === '--dry-run') options.dryRun = true;
|
|
99
|
-
else if (arg === '--json') options.json = true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!options.traceId) {
|
|
103
|
-
options.traceId = crypto.randomBytes(6).toString('hex');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return options;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Check if tmux is available and we're in a tmux session.
|
|
111
|
-
* @returns {{ available: boolean, inSession: boolean }}
|
|
112
|
-
*/
|
|
113
|
-
function checkTmux() {
|
|
114
|
-
try {
|
|
115
|
-
execFileSync('which', ['tmux'], { stdio: 'pipe' });
|
|
116
|
-
const inSession = !!process.env.TMUX;
|
|
117
|
-
return { available: true, inSession };
|
|
118
|
-
} catch (_) {
|
|
119
|
-
return { available: false, inSession: false };
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Create the sentinel directory for a trace.
|
|
125
|
-
* @param {string} rootDir - Project root
|
|
126
|
-
* @param {string} traceId - Unique trace ID
|
|
127
|
-
* @returns {string} Path to sentinel directory
|
|
128
|
-
*/
|
|
129
|
-
function createSentinelDir(rootDir, traceId) {
|
|
130
|
-
const sentinelDir = path.join(rootDir, 'docs', '09-agents', 'ultradeep', traceId);
|
|
131
|
-
fs.mkdirSync(sentinelDir, { recursive: true });
|
|
132
|
-
return sentinelDir;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Write initial status file for the trace.
|
|
137
|
-
* @param {string} sentinelDir - Sentinel directory path
|
|
138
|
-
* @param {string} auditType - Audit type key
|
|
139
|
-
* @param {Array} analyzers - Array of analyzer configs
|
|
140
|
-
* @param {number} [staggerMs] - Stagger delay in milliseconds
|
|
141
|
-
* @param {number} [maxConcurrent] - Max concurrent sessions (0 = unlimited)
|
|
142
|
-
*/
|
|
143
|
-
function writeStatusFile(sentinelDir, auditType, analyzers, staggerMs, maxConcurrent, extra) {
|
|
144
|
-
const status = {
|
|
145
|
-
started_at: new Date().toISOString(),
|
|
146
|
-
audit_type: auditType,
|
|
147
|
-
analyzers: analyzers.map(a => a.key),
|
|
148
|
-
completed: [],
|
|
149
|
-
failed: [],
|
|
150
|
-
stagger_ms: staggerMs != null ? staggerMs : null,
|
|
151
|
-
max_concurrent: maxConcurrent || null,
|
|
152
|
-
};
|
|
153
|
-
// Store extra fields for retry support
|
|
154
|
-
if (extra) {
|
|
155
|
-
if (extra.target != null) status.target = extra.target;
|
|
156
|
-
if (extra.model != null) status.model = extra.model;
|
|
157
|
-
if (extra.timeout_minutes != null) status.timeout_minutes = extra.timeout_minutes;
|
|
158
|
-
}
|
|
159
|
-
fs.writeFileSync(path.join(sentinelDir, '_status.json'), JSON.stringify(status, null, 2) + '\n');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Build the prompt for an individual analyzer session.
|
|
164
|
-
* @param {object} analyzer - Analyzer config { key, subagent_type, label }
|
|
165
|
-
* @param {string} target - Target path to analyze
|
|
166
|
-
* @param {string} traceId - Trace ID
|
|
167
|
-
* @param {string} sentinelDir - Sentinel directory for output
|
|
168
|
-
* @param {string} auditType - Audit type key
|
|
169
|
-
* @param {string} [model] - Resolved model name for sub-agent
|
|
170
|
-
* @returns {string} Prompt text
|
|
171
|
-
*/
|
|
172
|
-
function buildAnalyzerPrompt(analyzer, target, traceId, sentinelDir, auditType, model) {
|
|
173
|
-
const findingsFile = path.join(sentinelDir, `${analyzer.key}.findings.json`);
|
|
174
|
-
|
|
175
|
-
// Sanitize fields that get interpolated into double-quoted prompt sections
|
|
176
|
-
const safeLabel = String(analyzer.label || '').replace(/["\\]/g, '');
|
|
177
|
-
const safeTarget = String(target || '').replace(/["\\]/g, '');
|
|
178
|
-
const safeSubagentType = String(analyzer.subagent_type || '').replace(/["\\]/g, '');
|
|
179
|
-
|
|
180
|
-
return `You are an ULTRADEEP audit session coordinator.
|
|
181
|
-
|
|
182
|
-
## Task
|
|
183
|
-
|
|
184
|
-
1. Use the Agent tool to spawn a sub-agent for analysis
|
|
185
|
-
2. After the sub-agent completes, parse its output and write findings as JSON to the sentinel file
|
|
186
|
-
|
|
187
|
-
## Agent Configuration
|
|
188
|
-
|
|
189
|
-
Use the Agent tool with these parameters:
|
|
190
|
-
- subagent_type: "${safeSubagentType}"
|
|
191
|
-
- description: "${safeLabel} analysis of ${safeTarget}"${model ? `\n- model: "${model}"` : ''}
|
|
192
|
-
- prompt: |
|
|
193
|
-
Analyze the target path ${safeTarget} thoroughly for ${safeLabel}-related issues.
|
|
194
|
-
Search all relevant files recursively. Be thorough.
|
|
195
|
-
Return a JSON object with this structure:
|
|
196
|
-
{"findings": [{"id": "${analyzer.key}-NNN", "severity": "P0|P1|P2|P3", "title": "Short description", "file": "path/to/file.js", "line": 42, "description": "Detailed explanation", "evidence": "Code snippet or reasoning", "recommendation": "How to fix"}], "summary": {"files_scanned": 0, "total_findings": 0, "by_severity": {"P0": 0, "P1": 0, "P2": 0, "P3": 0}}}
|
|
197
|
-
TRACE_ID: ${traceId}
|
|
198
|
-
ANALYZER: ${analyzer.key}
|
|
199
|
-
|
|
200
|
-
## Output
|
|
201
|
-
|
|
202
|
-
After the Agent tool returns its analysis, write a JSON file to: ${findingsFile}
|
|
203
|
-
|
|
204
|
-
Use this structure:
|
|
205
|
-
{
|
|
206
|
-
"analyzer": "${analyzer.key}",
|
|
207
|
-
"audit_type": "${auditType}",
|
|
208
|
-
"trace_id": "${traceId}",
|
|
209
|
-
"target": "${safeTarget}",
|
|
210
|
-
"completed_at": "<ISO timestamp>",
|
|
211
|
-
"findings": [
|
|
212
|
-
{
|
|
213
|
-
"id": "${analyzer.key}-001",
|
|
214
|
-
"severity": "P0|P1|P2|P3",
|
|
215
|
-
"title": "Short description",
|
|
216
|
-
"file": "path/to/file.js",
|
|
217
|
-
"line": 42,
|
|
218
|
-
"description": "Detailed explanation",
|
|
219
|
-
"evidence": "Code snippet or reasoning",
|
|
220
|
-
"recommendation": "How to fix"
|
|
221
|
-
}
|
|
222
|
-
],
|
|
223
|
-
"summary": {
|
|
224
|
-
"files_scanned": 0,
|
|
225
|
-
"total_findings": 0,
|
|
226
|
-
"by_severity": { "P0": 0, "P1": 0, "P2": 0, "P3": 0 }
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
IMPORTANT: You MUST write the findings JSON file when complete. This is how the orchestrator knows you're done.
|
|
231
|
-
If the Agent tool is unavailable or returns an error, perform the analysis directly using Read, Glob, and Grep tools.
|
|
232
|
-
Start by spawning the Agent now.`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Create a slug from a partition path for use in window names and filenames.
|
|
237
|
-
* Only allows alphanumeric, hyphens, and underscores — safe for tmux window
|
|
238
|
-
* names, shell interpolation, and filesystem paths.
|
|
239
|
-
* @param {string} partition - Partition path (e.g. 'src/auth')
|
|
240
|
-
* @returns {string} Slug (e.g. 'src-auth')
|
|
241
|
-
*/
|
|
242
|
-
function partitionSlug(partition) {
|
|
243
|
-
return (
|
|
244
|
-
partition
|
|
245
|
-
.replace(/^\.?\/?/, '')
|
|
246
|
-
.replace(/\/+$/g, '')
|
|
247
|
-
.replace(/[/\\]/g, '-')
|
|
248
|
-
.replace(/[^a-zA-Z0-9_-]/g, '_') || 'root'
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Build the prompt for an extreme-mode partition coordinator session.
|
|
254
|
-
* This coordinator runs ALL analyzers on a single partition using the Agent tool.
|
|
255
|
-
* @param {string} partition - Partition path to analyze
|
|
256
|
-
* @param {Array<{ key: string, subagent_type: string, label: string }>} analyzers - All analyzers to run
|
|
257
|
-
* @param {string} traceId - Trace ID
|
|
258
|
-
* @param {string} sentinelDir - Sentinel directory for output
|
|
259
|
-
* @param {string} auditType - Audit type key
|
|
260
|
-
* @param {string} [model] - Resolved model name for sub-agents
|
|
261
|
-
* @returns {string} Prompt text
|
|
262
|
-
*/
|
|
263
|
-
function buildExtremePrompt(partition, analyzers, traceId, sentinelDir, auditType, model) {
|
|
264
|
-
const slug = partitionSlug(partition);
|
|
265
|
-
const findingsFile = path.join(sentinelDir, `${slug}.findings.json`);
|
|
266
|
-
|
|
267
|
-
const safePartition = String(partition || '').replace(/["\\]/g, '');
|
|
268
|
-
|
|
269
|
-
const analyzerList = analyzers
|
|
270
|
-
.map((a, i) => `${i + 1}. subagent_type: "${a.subagent_type}" — ${a.label} (key: ${a.key})`)
|
|
271
|
-
.join('\n');
|
|
272
|
-
|
|
273
|
-
const modelLine = model ? `\n- model: "${model}"` : '';
|
|
274
|
-
|
|
275
|
-
return `You are an EXTREME audit session coordinator for partition: ${safePartition}
|
|
276
|
-
|
|
277
|
-
## Task
|
|
278
|
-
|
|
279
|
-
Run ALL of the following analyzers on your partition using the Agent tool.
|
|
280
|
-
Deploy them in parallel (multiple Agent calls in one message) where possible.
|
|
281
|
-
|
|
282
|
-
## Analyzers to Run
|
|
283
|
-
${analyzerList}
|
|
284
|
-
|
|
285
|
-
## Agent Configuration for Each Analyzer
|
|
286
|
-
|
|
287
|
-
Use the Agent tool with these parameters for each analyzer:
|
|
288
|
-
- subagent_type: (from the list above)
|
|
289
|
-
- description: "[Analyzer label] analysis of ${safePartition}"${modelLine}
|
|
290
|
-
- prompt: |
|
|
291
|
-
Analyze the target path ${safePartition} thoroughly for issues relevant to your analyzer domain.
|
|
292
|
-
Search all relevant files recursively. Be thorough.
|
|
293
|
-
Use the analyzer key from your subagent_type as the ID prefix (e.g., for "security-analyzer-injection" use "injection").
|
|
294
|
-
Return a JSON object with this structure:
|
|
295
|
-
{"findings": [{"id": "<analyzer-key>-NNN", "severity": "P0|P1|P2|P3", "title": "Short description", "file": "path/to/file.js", "line": 42, "description": "Detailed explanation", "evidence": "Code snippet or reasoning", "recommendation": "How to fix"}], "summary": {"files_scanned": 0, "total_findings": 0, "by_severity": {"P0": 0, "P1": 0, "P2": 0, "P3": 0}}}
|
|
296
|
-
TRACE_ID: ${traceId}
|
|
297
|
-
|
|
298
|
-
## After All Analyzers Complete
|
|
299
|
-
|
|
300
|
-
Combine ALL findings from ALL analyzers into a single JSON file: ${findingsFile}
|
|
301
|
-
|
|
302
|
-
Use this structure:
|
|
303
|
-
{
|
|
304
|
-
"partition": "${safePartition}",
|
|
305
|
-
"audit_type": "${auditType}",
|
|
306
|
-
"trace_id": "${traceId}",
|
|
307
|
-
"completed_at": "<ISO timestamp>",
|
|
308
|
-
"analyzer_count": ${analyzers.length},
|
|
309
|
-
"analyzers_run": [${analyzers.map(a => `"${a.key}"`).join(', ')}],
|
|
310
|
-
"findings": [
|
|
311
|
-
{
|
|
312
|
-
"id": "<analyzer_key>-001",
|
|
313
|
-
"analyzer": "<analyzer_key>",
|
|
314
|
-
"severity": "P0|P1|P2|P3",
|
|
315
|
-
"title": "Short description",
|
|
316
|
-
"file": "path/to/file.js",
|
|
317
|
-
"line": 42,
|
|
318
|
-
"description": "Detailed explanation",
|
|
319
|
-
"evidence": "Code snippet or reasoning",
|
|
320
|
-
"recommendation": "How to fix"
|
|
321
|
-
}
|
|
322
|
-
],
|
|
323
|
-
"summary": {
|
|
324
|
-
"files_scanned": 0,
|
|
325
|
-
"total_findings": 0,
|
|
326
|
-
"by_severity": { "P0": 0, "P1": 0, "P2": 0, "P3": 0 }
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
IMPORTANT: You MUST write the findings JSON file when complete. This is how the orchestrator knows you're done.
|
|
331
|
-
Start by spawning ALL ${analyzers.length} analyzers now, in parallel.`;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Spawn a single analyzer session in tmux.
|
|
336
|
-
* @param {object} params - Session parameters
|
|
337
|
-
* @returns {string|null} Window name if successful, null on failure
|
|
338
|
-
*/
|
|
339
|
-
function spawnOneSession({
|
|
340
|
-
analyzer,
|
|
341
|
-
index,
|
|
342
|
-
sessionName,
|
|
343
|
-
rootDir,
|
|
344
|
-
options,
|
|
345
|
-
sentinelDir,
|
|
346
|
-
auditType,
|
|
347
|
-
groupColor,
|
|
348
|
-
}) {
|
|
349
|
-
const windowName = `${auditType.prefix}:${analyzer.key}`;
|
|
350
|
-
const model = resolveModel(options.model, 'haiku');
|
|
351
|
-
const prompt = buildAnalyzerPrompt(
|
|
352
|
-
analyzer,
|
|
353
|
-
options.target,
|
|
354
|
-
options.traceId,
|
|
355
|
-
sentinelDir,
|
|
356
|
-
options.audit,
|
|
357
|
-
model
|
|
358
|
-
);
|
|
359
|
-
const escapedPrompt = prompt.replace(/'/g, "'\\''");
|
|
360
|
-
|
|
361
|
-
try {
|
|
362
|
-
if (index === 0) {
|
|
363
|
-
execFileSync(
|
|
364
|
-
'tmux',
|
|
365
|
-
['new-session', '-d', '-s', sessionName, '-n', windowName, '-c', rootDir],
|
|
366
|
-
{ stdio: 'pipe' }
|
|
367
|
-
);
|
|
368
|
-
} else {
|
|
369
|
-
execFileSync('tmux', ['new-window', '-t', sessionName, '-n', windowName, '-c', rootDir], {
|
|
370
|
-
stdio: 'pipe',
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
execFileSync(
|
|
375
|
-
'tmux',
|
|
376
|
-
['set-option', '-w', '-t', `${sessionName}:${windowName}`, '@group_color', groupColor],
|
|
377
|
-
{ stdio: 'pipe' }
|
|
378
|
-
);
|
|
379
|
-
|
|
380
|
-
const claudeCmd = `echo '${escapedPrompt}' | claude --model ${model} --allowedTools 'Read Glob Grep Write Agent' 2>&1; echo "AUDIT_COMPLETE: ${analyzer.key}"`;
|
|
381
|
-
execFileSync('tmux', ['send-keys', '-t', `${sessionName}:${windowName}`, claudeCmd, 'Enter'], {
|
|
382
|
-
stdio: 'pipe',
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
return windowName;
|
|
386
|
-
} catch (err) {
|
|
387
|
-
console.error(`Failed to spawn ${windowName}: ${err.message}`);
|
|
388
|
-
return null;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Poll sentinel directory for wave completion.
|
|
394
|
-
* @param {string} sentinelDir - Sentinel directory path
|
|
395
|
-
* @param {string[]} keys - Analyzer keys to wait for
|
|
396
|
-
* @param {number} timeoutMinutes - Timeout in minutes
|
|
397
|
-
* @returns {Promise<boolean>} true if all completed, false on timeout
|
|
398
|
-
*/
|
|
399
|
-
async function pollWaveCompletion(sentinelDir, keys, timeoutMinutes) {
|
|
400
|
-
const timeoutMs = (timeoutMinutes || 30) * 60 * 1000;
|
|
401
|
-
const startTime = Date.now();
|
|
402
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
403
|
-
const allDone = keys.every(key =>
|
|
404
|
-
fs.existsSync(path.join(sentinelDir, `${key}.findings.json`))
|
|
405
|
-
);
|
|
406
|
-
if (allDone) return true;
|
|
407
|
-
await sleep(3000);
|
|
408
|
-
}
|
|
409
|
-
return false;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
/**
|
|
413
|
-
* Spawn audit analyzer sessions in tmux with staggered launching.
|
|
414
|
-
* @param {object} options - Parsed CLI options
|
|
415
|
-
* @returns {Promise<{ ok: boolean, traceId: string, sentinelDir: string, sessions: string[] }>}
|
|
416
|
-
*/
|
|
417
|
-
async function spawnAuditInTmux(options) {
|
|
418
|
-
const rootDir = process.cwd();
|
|
419
|
-
const auditType = getAuditType(options.audit);
|
|
420
|
-
|
|
421
|
-
if (!auditType) {
|
|
422
|
-
console.error(`Unknown audit type: ${options.audit}`);
|
|
423
|
-
console.error(`Valid types: logic, security, performance, test, completeness, legal, seo, ads`);
|
|
424
|
-
process.exit(1);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
const isExtreme = options.depth === 'extreme';
|
|
428
|
-
const depthForRegistry = isExtreme ? 'extreme' : 'ultradeep';
|
|
429
|
-
const result = getAnalyzersForAudit(options.audit, depthForRegistry, options.focus);
|
|
430
|
-
if (!result || result.analyzers.length === 0) {
|
|
431
|
-
console.error(`No analyzers found for ${options.audit} with focus: ${options.focus.join(',')}`);
|
|
432
|
-
process.exit(1);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
const sentinelDir = createSentinelDir(rootDir, options.traceId);
|
|
436
|
-
|
|
437
|
-
// Use stderr for human output when --json mode is active
|
|
438
|
-
const log = options.json ? console.error : console.log;
|
|
439
|
-
|
|
440
|
-
// --- EXTREME MODE: partition-based multi-agent ---
|
|
441
|
-
if (isExtreme) {
|
|
442
|
-
if (!options.partitions || options.partitions.length === 0) {
|
|
443
|
-
console.error('EXTREME mode requires --partitions=dir1,dir2,...');
|
|
444
|
-
process.exit(1);
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const partitions = options.partitions;
|
|
448
|
-
const partitionSlugs = partitions.map(p => partitionSlug(p));
|
|
449
|
-
|
|
450
|
-
// Write status file with partition info
|
|
451
|
-
const statusData = {
|
|
452
|
-
started_at: new Date().toISOString(),
|
|
453
|
-
audit_type: options.audit,
|
|
454
|
-
mode: 'extreme',
|
|
455
|
-
partitions: partitions,
|
|
456
|
-
analyzers: partitionSlugs,
|
|
457
|
-
analyzers_per_partition: result.analyzers.map(a => a.key),
|
|
458
|
-
completed: [],
|
|
459
|
-
failed: [],
|
|
460
|
-
target: options.target,
|
|
461
|
-
model: options.model,
|
|
462
|
-
timeout_minutes: options.timeout,
|
|
463
|
-
};
|
|
464
|
-
fs.writeFileSync(
|
|
465
|
-
path.join(sentinelDir, '_status.json'),
|
|
466
|
-
JSON.stringify(statusData, null, 2) + '\n'
|
|
467
|
-
);
|
|
468
|
-
|
|
469
|
-
const groupColor = getColorForAudit(options.audit);
|
|
470
|
-
const totalSessions = partitions.length * result.analyzers.length;
|
|
471
|
-
|
|
472
|
-
if (options.dryRun) {
|
|
473
|
-
log(`\nDry run - EXTREME mode would spawn ${partitions.length} partition coordinators:`);
|
|
474
|
-
log(` Partitions: ${partitions.join(', ')}`);
|
|
475
|
-
log(` Analyzers per partition: ${result.analyzers.length}`);
|
|
476
|
-
log(` Total agent sessions: ${totalSessions}`);
|
|
477
|
-
const model = resolveModel(options.model, 'haiku');
|
|
478
|
-
for (const p of partitions) {
|
|
479
|
-
const slug = partitionSlug(p);
|
|
480
|
-
log(
|
|
481
|
-
` ${auditType.prefix}:${slug} (${model}) → ALL ${result.analyzers.length} analyzers on ${p}`
|
|
482
|
-
);
|
|
483
|
-
}
|
|
484
|
-
log(`\nSentinel dir: ${sentinelDir}`);
|
|
485
|
-
log(`Group color: ${groupColor}`);
|
|
486
|
-
return {
|
|
487
|
-
ok: true,
|
|
488
|
-
traceId: options.traceId,
|
|
489
|
-
sentinelDir,
|
|
490
|
-
sessions: [],
|
|
491
|
-
dryRun: true,
|
|
492
|
-
mode: 'extreme',
|
|
493
|
-
partitions,
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
const tmux = checkTmux();
|
|
498
|
-
if (!tmux.available) {
|
|
499
|
-
console.error('tmux is not available. EXTREME mode requires tmux.');
|
|
500
|
-
console.error('Falling back to DEPTH=deep mode.');
|
|
501
|
-
return { ok: false, traceId: options.traceId, sentinelDir, sessions: [], fallback: 'deep' };
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const sessionName = `audit-${options.audit}-${options.traceId.slice(0, 8)}`;
|
|
505
|
-
const sessions = [];
|
|
506
|
-
const config = getUltradeepConfig();
|
|
507
|
-
const staggerMs =
|
|
508
|
-
((options.stagger != null ? options.stagger : config.stagger_seconds) || 0) * 1000;
|
|
509
|
-
|
|
510
|
-
for (let i = 0; i < partitions.length; i++) {
|
|
511
|
-
if (i > 0 && staggerMs > 0) await sleep(staggerMs);
|
|
512
|
-
|
|
513
|
-
const partition = partitions[i];
|
|
514
|
-
const slug = partitionSlug(partition);
|
|
515
|
-
const windowName = `${auditType.prefix}:${slug}`;
|
|
516
|
-
const model = resolveModel(options.model, 'haiku');
|
|
517
|
-
const prompt = buildExtremePrompt(
|
|
518
|
-
partition,
|
|
519
|
-
result.analyzers,
|
|
520
|
-
options.traceId,
|
|
521
|
-
sentinelDir,
|
|
522
|
-
options.audit,
|
|
523
|
-
model
|
|
524
|
-
);
|
|
525
|
-
const escapedPrompt = prompt.replace(/'/g, "'\\''");
|
|
526
|
-
|
|
527
|
-
try {
|
|
528
|
-
if (i === 0) {
|
|
529
|
-
execFileSync(
|
|
530
|
-
'tmux',
|
|
531
|
-
['new-session', '-d', '-s', sessionName, '-n', windowName, '-c', rootDir],
|
|
532
|
-
{ stdio: 'pipe' }
|
|
533
|
-
);
|
|
534
|
-
} else {
|
|
535
|
-
execFileSync('tmux', ['new-window', '-t', sessionName, '-n', windowName, '-c', rootDir], {
|
|
536
|
-
stdio: 'pipe',
|
|
537
|
-
});
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
execFileSync(
|
|
541
|
-
'tmux',
|
|
542
|
-
['set-option', '-w', '-t', `${sessionName}:${windowName}`, '@group_color', groupColor],
|
|
543
|
-
{ stdio: 'pipe' }
|
|
544
|
-
);
|
|
545
|
-
|
|
546
|
-
const claudeCmd = `echo '${escapedPrompt}' | claude --model ${model} --allowedTools 'Read Glob Grep Write Agent' 2>&1; echo "AUDIT_COMPLETE: ${slug}"`;
|
|
547
|
-
execFileSync(
|
|
548
|
-
'tmux',
|
|
549
|
-
['send-keys', '-t', `${sessionName}:${windowName}`, claudeCmd, 'Enter'],
|
|
550
|
-
{
|
|
551
|
-
stdio: 'pipe',
|
|
552
|
-
}
|
|
553
|
-
);
|
|
554
|
-
|
|
555
|
-
sessions.push(windowName);
|
|
556
|
-
} catch (err) {
|
|
557
|
-
console.error(`Failed to spawn ${windowName}: ${err.message}`);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Apply status bar theme
|
|
562
|
-
try {
|
|
563
|
-
const tmuxScript = path.join(__dirname, 'claude-tmux.sh');
|
|
564
|
-
execFileSync(tmuxScript, [`--configure-session=${sessionName}`], { stdio: 'pipe' });
|
|
565
|
-
} catch (_) {
|
|
566
|
-
// Non-critical
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
log(`\nSpawned ${sessions.length} partition coordinators in tmux session: ${sessionName}`);
|
|
570
|
-
log(` Partitions: ${partitions.join(', ')}`);
|
|
571
|
-
log(` Analyzers per partition: ${result.analyzers.length}`);
|
|
572
|
-
log(` Total agent sessions: ${totalSessions}`);
|
|
573
|
-
log(`Sentinel dir: ${sentinelDir}`);
|
|
574
|
-
log(`Attach with: tmux attach -t ${sessionName}`);
|
|
575
|
-
|
|
576
|
-
return {
|
|
577
|
-
ok: true,
|
|
578
|
-
traceId: options.traceId,
|
|
579
|
-
sentinelDir,
|
|
580
|
-
sessions,
|
|
581
|
-
sessionName,
|
|
582
|
-
mode: 'extreme',
|
|
583
|
-
partitions,
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// --- ULTRADEEP MODE (existing behavior) ---
|
|
588
|
-
|
|
589
|
-
// Enforce session limit
|
|
590
|
-
if (result.analyzers.length > 20) {
|
|
591
|
-
console.error(`Too many analyzers (${result.analyzers.length}). Maximum is 20.`);
|
|
592
|
-
process.exit(1);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Resolve stagger and concurrency from CLI flags or config
|
|
596
|
-
const config = getUltradeepConfig();
|
|
597
|
-
const staggerMs =
|
|
598
|
-
((options.stagger != null ? options.stagger : config.stagger_seconds) || 0) * 1000;
|
|
599
|
-
const maxConcurrent = options.concurrency != null ? options.concurrency : config.max_concurrent;
|
|
600
|
-
|
|
601
|
-
writeStatusFile(sentinelDir, options.audit, result.analyzers, staggerMs, maxConcurrent, {
|
|
602
|
-
target: options.target,
|
|
603
|
-
model: options.model,
|
|
604
|
-
timeout_minutes: options.timeout,
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
const groupColor = getColorForAudit(options.audit);
|
|
608
|
-
const sessions = [];
|
|
609
|
-
|
|
610
|
-
if (options.dryRun) {
|
|
611
|
-
log(`\nDry run - would spawn ${result.analyzers.length} sessions:`);
|
|
612
|
-
log(` Stagger: ${staggerMs / 1000}s between launches`);
|
|
613
|
-
if (maxConcurrent > 0) {
|
|
614
|
-
const waveCount = Math.ceil(result.analyzers.length / maxConcurrent);
|
|
615
|
-
log(` Concurrency: ${maxConcurrent}/wave (${waveCount} waves)`);
|
|
616
|
-
}
|
|
617
|
-
for (const analyzer of result.analyzers) {
|
|
618
|
-
const model = resolveModel(options.model, 'haiku');
|
|
619
|
-
log(` ${auditType.prefix}:${analyzer.key} (${model}) → ${analyzer.label}`);
|
|
620
|
-
}
|
|
621
|
-
log(`\nSentinel dir: ${sentinelDir}`);
|
|
622
|
-
log(`Group color: ${groupColor}`);
|
|
623
|
-
return { ok: true, traceId: options.traceId, sentinelDir, sessions: [], dryRun: true };
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
const tmux = checkTmux();
|
|
627
|
-
if (!tmux.available) {
|
|
628
|
-
console.error('tmux is not available. ULTRADEEP mode requires tmux.');
|
|
629
|
-
console.error('Falling back to DEPTH=deep mode.');
|
|
630
|
-
return { ok: false, traceId: options.traceId, sentinelDir, sessions: [], fallback: 'deep' };
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Create dedicated tmux session for this audit
|
|
634
|
-
const sessionName = `audit-${options.audit}-${options.traceId.slice(0, 8)}`;
|
|
635
|
-
let sessionIndex = 0;
|
|
636
|
-
|
|
637
|
-
if (maxConcurrent > 0 && result.analyzers.length > maxConcurrent) {
|
|
638
|
-
// Wave-based spawning
|
|
639
|
-
const waves = [];
|
|
640
|
-
for (let i = 0; i < result.analyzers.length; i += maxConcurrent) {
|
|
641
|
-
waves.push(result.analyzers.slice(i, i + maxConcurrent));
|
|
642
|
-
}
|
|
643
|
-
for (let w = 0; w < waves.length; w++) {
|
|
644
|
-
if (w > 0) {
|
|
645
|
-
const prevKeys = waves[w - 1].map(a => a.key);
|
|
646
|
-
await pollWaveCompletion(sentinelDir, prevKeys, options.timeout);
|
|
647
|
-
}
|
|
648
|
-
for (let i = 0; i < waves[w].length; i++) {
|
|
649
|
-
if (sessionIndex > 0 && staggerMs > 0) await sleep(staggerMs);
|
|
650
|
-
const name = spawnOneSession({
|
|
651
|
-
analyzer: waves[w][i],
|
|
652
|
-
index: sessionIndex,
|
|
653
|
-
sessionName,
|
|
654
|
-
rootDir,
|
|
655
|
-
options,
|
|
656
|
-
sentinelDir,
|
|
657
|
-
auditType,
|
|
658
|
-
groupColor,
|
|
659
|
-
});
|
|
660
|
-
if (name) sessions.push(name);
|
|
661
|
-
sessionIndex++;
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
} else {
|
|
665
|
-
// Simple staggered spawning (no wave limit)
|
|
666
|
-
for (let i = 0; i < result.analyzers.length; i++) {
|
|
667
|
-
if (i > 0 && staggerMs > 0) await sleep(staggerMs);
|
|
668
|
-
const name = spawnOneSession({
|
|
669
|
-
analyzer: result.analyzers[i],
|
|
670
|
-
index: i,
|
|
671
|
-
sessionName,
|
|
672
|
-
rootDir,
|
|
673
|
-
options,
|
|
674
|
-
sentinelDir,
|
|
675
|
-
auditType,
|
|
676
|
-
groupColor,
|
|
677
|
-
});
|
|
678
|
-
if (name) sessions.push(name);
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
// Apply the same status bar theme as normal Claude sessions
|
|
683
|
-
try {
|
|
684
|
-
const tmuxScript = path.join(__dirname, 'claude-tmux.sh');
|
|
685
|
-
execFileSync(tmuxScript, [`--configure-session=${sessionName}`], { stdio: 'pipe' });
|
|
686
|
-
} catch (_) {
|
|
687
|
-
// Non-critical styling failure — audit session still works with default theme
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
log(`\nSpawned ${sessions.length} analyzer sessions in tmux session: ${sessionName}`);
|
|
691
|
-
log(`Sentinel dir: ${sentinelDir}`);
|
|
692
|
-
log(`Attach with: tmux attach -t ${sessionName}`);
|
|
693
|
-
|
|
694
|
-
return { ok: true, traceId: options.traceId, sentinelDir, sessions, sessionName };
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
/**
|
|
698
|
-
* Poll sentinel directory for completion.
|
|
699
|
-
* @param {string} sentinelDir - Sentinel directory path
|
|
700
|
-
* @param {string[]} expected - Expected analyzer keys
|
|
701
|
-
* @param {number} timeoutMinutes - Timeout in minutes
|
|
702
|
-
* @returns {Promise<{ complete: boolean, results: object[], missing: string[] }>}
|
|
703
|
-
*/
|
|
704
|
-
async function pollForCompletion(sentinelDir, expected, timeoutMinutes) {
|
|
705
|
-
const timeoutMs = timeoutMinutes * 60 * 1000;
|
|
706
|
-
const startTime = Date.now();
|
|
707
|
-
const pollIntervalMs = 5000;
|
|
708
|
-
|
|
709
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
710
|
-
const completed = [];
|
|
711
|
-
const missing = [];
|
|
712
|
-
|
|
713
|
-
for (const key of expected) {
|
|
714
|
-
const findingsFile = path.join(sentinelDir, `${key}.findings.json`);
|
|
715
|
-
if (fs.existsSync(findingsFile)) {
|
|
716
|
-
completed.push(key);
|
|
717
|
-
} else {
|
|
718
|
-
missing.push(key);
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// Update status file
|
|
723
|
-
try {
|
|
724
|
-
const statusPath = path.join(sentinelDir, '_status.json');
|
|
725
|
-
const status = JSON.parse(fs.readFileSync(statusPath, 'utf8'));
|
|
726
|
-
status.completed = completed;
|
|
727
|
-
status.last_checked = new Date().toISOString();
|
|
728
|
-
fs.writeFileSync(statusPath, JSON.stringify(status, null, 2) + '\n');
|
|
729
|
-
} catch (_) {
|
|
730
|
-
// Non-critical
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (missing.length === 0) {
|
|
734
|
-
return { complete: true, results: collectResults(sentinelDir, expected), missing: [] };
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// Timeout
|
|
741
|
-
const results = collectResults(sentinelDir, expected);
|
|
742
|
-
const completedKeys = results.map(r => r.analyzer);
|
|
743
|
-
const missing = expected.filter(k => !completedKeys.includes(k));
|
|
744
|
-
return { complete: false, results, missing };
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
/**
|
|
748
|
-
* Collect all findings from sentinel directory.
|
|
749
|
-
* @param {string} sentinelDir - Sentinel directory path
|
|
750
|
-
* @param {string[]} expected - Expected keys. In ultradeep mode these are analyzer keys
|
|
751
|
-
* (e.g. 'injection', 'auth'). In extreme mode these are partition slugs
|
|
752
|
-
* (e.g. 'src-auth', 'src-api') — matches the `analyzers` array in `_status.json`.
|
|
753
|
-
* @returns {object[]} Array of parsed findings
|
|
754
|
-
*/
|
|
755
|
-
function collectResults(sentinelDir, expected) {
|
|
756
|
-
const results = [];
|
|
757
|
-
|
|
758
|
-
for (const key of expected) {
|
|
759
|
-
const findingsFile = path.join(sentinelDir, `${key}.findings.json`);
|
|
760
|
-
try {
|
|
761
|
-
if (fs.existsSync(findingsFile)) {
|
|
762
|
-
const data = JSON.parse(fs.readFileSync(findingsFile, 'utf8'));
|
|
763
|
-
results.push(data);
|
|
764
|
-
}
|
|
765
|
-
} catch (err) {
|
|
766
|
-
results.push({
|
|
767
|
-
analyzer: key,
|
|
768
|
-
error: `Failed to parse findings: ${err.message}`,
|
|
769
|
-
findings: [],
|
|
770
|
-
});
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return results;
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
/**
|
|
778
|
-
* Show cost estimation before launching.
|
|
779
|
-
* @param {string} auditType - Audit type key
|
|
780
|
-
* @param {number} analyzerCount - Number of analyzers to spawn
|
|
781
|
-
* @param {string} [model] - Explicit model override
|
|
782
|
-
* @param {object} [opts] - Options
|
|
783
|
-
* @param {boolean} [opts.json] - If true, route output to stderr to keep stdout clean for JSON
|
|
784
|
-
* @param {number} [opts.partitions] - Number of partitions (extreme mode)
|
|
785
|
-
*/
|
|
786
|
-
function showCostEstimate(auditType, analyzerCount, model, opts) {
|
|
787
|
-
const resolved = resolveModel(model, 'haiku');
|
|
788
|
-
const partCount =
|
|
789
|
-
opts && typeof opts.partitions === 'number' && opts.partitions > 1 ? opts.partitions : 1;
|
|
790
|
-
const estimate = estimateCost(resolved, analyzerCount, partCount);
|
|
791
|
-
const log = opts && opts.json ? console.error : console.log;
|
|
792
|
-
|
|
793
|
-
if (partCount > 1) {
|
|
794
|
-
log(`\nCost estimate for EXTREME ${auditType} audit:`);
|
|
795
|
-
log(` Model: ${estimate.model}`);
|
|
796
|
-
log(` Partitions: ${partCount}`);
|
|
797
|
-
log(` Analyzers per partition: ${analyzerCount}`);
|
|
798
|
-
log(` Total agent sessions: ${estimate.totalSessions}`);
|
|
799
|
-
log(` Per-agent estimate: ${estimate.perAnalyzerCost}`);
|
|
800
|
-
log(` Total estimate: ${estimate.totalEstimate}`);
|
|
801
|
-
} else {
|
|
802
|
-
log(`\nCost estimate for ULTRADEEP ${auditType} audit:`);
|
|
803
|
-
log(` Model: ${estimate.model}`);
|
|
804
|
-
log(` Analyzers: ${analyzerCount}`);
|
|
805
|
-
log(` Cost multiplier vs haiku: ${estimate.multiplier}x`);
|
|
806
|
-
log(` Per-analyzer estimate: ${estimate.perAnalyzerCost}`);
|
|
807
|
-
log(` Total estimate: ${estimate.totalEstimate}`);
|
|
808
|
-
log(` Each analyzer runs as a full Claude Code session`);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// Main
|
|
813
|
-
if (require.main === module) {
|
|
814
|
-
(async () => {
|
|
815
|
-
const options = parseArgs();
|
|
816
|
-
|
|
817
|
-
if (!options.audit) {
|
|
818
|
-
console.error(
|
|
819
|
-
'Usage: node spawn-audit-sessions.js --audit=TYPE --target=PATH [--focus=AREAS] [--model=MODEL] [--trace-id=ID] [--stagger=SECONDS] [--concurrency=N]'
|
|
820
|
-
);
|
|
821
|
-
console.error('Types: logic, security, performance, test, completeness, legal');
|
|
822
|
-
process.exit(1);
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
const isExtreme = options.depth === 'extreme';
|
|
826
|
-
const depthForCost = isExtreme ? 'extreme' : 'ultradeep';
|
|
827
|
-
const result = getAnalyzersForAudit(options.audit, depthForCost, options.focus);
|
|
828
|
-
if (result) {
|
|
829
|
-
showCostEstimate(options.audit, result.analyzers.length, options.model, {
|
|
830
|
-
json: options.json,
|
|
831
|
-
partitions: isExtreme && options.partitions ? options.partitions.length : 1,
|
|
832
|
-
});
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
const spawnResult = await spawnAuditInTmux(options);
|
|
836
|
-
|
|
837
|
-
if (options.json) {
|
|
838
|
-
const jsonOut = {
|
|
839
|
-
ok: spawnResult.ok,
|
|
840
|
-
traceId: spawnResult.traceId,
|
|
841
|
-
sentinelDir: spawnResult.sentinelDir,
|
|
842
|
-
sessionName: spawnResult.sessionName || null,
|
|
843
|
-
sessions: spawnResult.sessions,
|
|
844
|
-
dryRun: spawnResult.dryRun || false,
|
|
845
|
-
fallback: spawnResult.fallback || null,
|
|
846
|
-
mode: spawnResult.mode || 'ultradeep',
|
|
847
|
-
partitions: spawnResult.partitions || null,
|
|
848
|
-
};
|
|
849
|
-
console.log(JSON.stringify(jsonOut));
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
if (!spawnResult.ok && spawnResult.fallback) {
|
|
853
|
-
process.exit(2); // Signal fallback to caller
|
|
854
|
-
}
|
|
855
|
-
})().catch(err => {
|
|
856
|
-
console.error(err.message);
|
|
857
|
-
process.exit(1);
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
module.exports = {
|
|
862
|
-
parseArgs,
|
|
863
|
-
checkTmux,
|
|
864
|
-
createSentinelDir,
|
|
865
|
-
writeStatusFile,
|
|
866
|
-
buildAnalyzerPrompt,
|
|
867
|
-
buildExtremePrompt,
|
|
868
|
-
partitionSlug,
|
|
869
|
-
spawnOneSession,
|
|
870
|
-
spawnAuditInTmux,
|
|
871
|
-
pollForCompletion,
|
|
872
|
-
pollWaveCompletion,
|
|
873
|
-
collectResults,
|
|
874
|
-
showCostEstimate,
|
|
875
|
-
getUltradeepConfig,
|
|
876
|
-
sleep,
|
|
877
|
-
};
|