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,1158 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* context-formatter.js
|
|
4
|
-
*
|
|
5
|
-
* Output formatting module for obtain-context.js (US-0148)
|
|
6
|
-
*
|
|
7
|
-
* Responsibilities:
|
|
8
|
-
* - Summary table generation (compact overview)
|
|
9
|
-
* - Full content generation (detailed context)
|
|
10
|
-
* - Context budget warning display
|
|
11
|
-
* - String padding and truncation utilities
|
|
12
|
-
* - Box drawing and color formatting
|
|
13
|
-
*
|
|
14
|
-
* Note: Uses pre-fetched data from context-loader.js for all formatting
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const fs = require('fs');
|
|
18
|
-
const path = require('path');
|
|
19
|
-
|
|
20
|
-
// Import colors and helpers
|
|
21
|
-
let C, box;
|
|
22
|
-
try {
|
|
23
|
-
const colors = require('../../lib/colors');
|
|
24
|
-
C = colors.c;
|
|
25
|
-
box = colors.box;
|
|
26
|
-
} catch {
|
|
27
|
-
// Fallback if colors not available
|
|
28
|
-
C = {
|
|
29
|
-
dim: '',
|
|
30
|
-
reset: '',
|
|
31
|
-
bold: '',
|
|
32
|
-
brand: '',
|
|
33
|
-
coral: '',
|
|
34
|
-
amber: '',
|
|
35
|
-
skyBlue: '',
|
|
36
|
-
mintGreen: '',
|
|
37
|
-
peach: '',
|
|
38
|
-
lavender: '',
|
|
39
|
-
teal: '',
|
|
40
|
-
cyan: '',
|
|
41
|
-
blue: '',
|
|
42
|
-
green: '',
|
|
43
|
-
lightGreen: '',
|
|
44
|
-
lightYellow: '',
|
|
45
|
-
};
|
|
46
|
-
box = {};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Import loader for fallback sync reads
|
|
50
|
-
const {
|
|
51
|
-
safeRead,
|
|
52
|
-
safeReadJSON,
|
|
53
|
-
safeLs,
|
|
54
|
-
safeExec,
|
|
55
|
-
getContextPercentage,
|
|
56
|
-
} = require('./context-loader');
|
|
57
|
-
|
|
58
|
-
// Import ideation index for filtering suggestions
|
|
59
|
-
let ideationIndex;
|
|
60
|
-
try {
|
|
61
|
-
ideationIndex = require('./ideation-index');
|
|
62
|
-
} catch {
|
|
63
|
-
// Ideation index not available
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// =============================================================================
|
|
67
|
-
// String Utilities
|
|
68
|
-
// =============================================================================
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Pad string to length, accounting for ANSI escape codes.
|
|
72
|
-
* @param {string} str - String to pad
|
|
73
|
-
* @param {number} len - Target length
|
|
74
|
-
* @returns {string} Padded string
|
|
75
|
-
*/
|
|
76
|
-
function pad(str, len) {
|
|
77
|
-
const stripped = str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
78
|
-
const diff = len - stripped.length;
|
|
79
|
-
if (diff <= 0) return str;
|
|
80
|
-
return str + ' '.repeat(diff);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Truncate string to max length, respecting ANSI codes.
|
|
85
|
-
* @param {string} str - String to truncate
|
|
86
|
-
* @param {number} maxLen - Maximum length
|
|
87
|
-
* @param {string} suffix - Suffix for truncated strings
|
|
88
|
-
* @returns {string} Truncated string
|
|
89
|
-
*/
|
|
90
|
-
function truncate(str, maxLen, suffix = '..') {
|
|
91
|
-
const stripped = str.replace(/\x1b\[[0-9;]*m/g, '');
|
|
92
|
-
if (stripped.length <= maxLen) return str;
|
|
93
|
-
|
|
94
|
-
const targetLen = maxLen - suffix.length;
|
|
95
|
-
let visibleCount = 0;
|
|
96
|
-
let cutIndex = 0;
|
|
97
|
-
let inEscape = false;
|
|
98
|
-
|
|
99
|
-
for (let i = 0; i < str.length; i++) {
|
|
100
|
-
if (str[i] === '\x1b') {
|
|
101
|
-
inEscape = true;
|
|
102
|
-
} else if (inEscape && str[i] === 'm') {
|
|
103
|
-
inEscape = false;
|
|
104
|
-
} else if (!inEscape) {
|
|
105
|
-
visibleCount++;
|
|
106
|
-
if (visibleCount >= targetLen) {
|
|
107
|
-
cutIndex = i + 1;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return str.substring(0, cutIndex) + suffix;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// =============================================================================
|
|
116
|
-
// Context Budget Warning (GSD Integration)
|
|
117
|
-
// =============================================================================
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Generate context budget warning box if usage exceeds threshold.
|
|
121
|
-
* Based on GSD research: 50% is where quality starts degrading.
|
|
122
|
-
*
|
|
123
|
-
* @param {number} percent - Context usage percentage
|
|
124
|
-
* @returns {string} Warning box or empty string
|
|
125
|
-
*/
|
|
126
|
-
function generateContextWarning(percent) {
|
|
127
|
-
if (percent < 50) {
|
|
128
|
-
return '';
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const width = 60;
|
|
132
|
-
const topLine = `┏${'━'.repeat(width - 2)}┓`;
|
|
133
|
-
const bottomLine = `┗${'━'.repeat(width - 2)}┛`;
|
|
134
|
-
|
|
135
|
-
let color, icon, message, suggestion;
|
|
136
|
-
|
|
137
|
-
if (percent >= 70) {
|
|
138
|
-
color = C.coral;
|
|
139
|
-
icon = '🔴';
|
|
140
|
-
message = `Context usage: ${percent}% (in degradation zone)`;
|
|
141
|
-
suggestion = 'Strongly recommend: compact conversation or delegate to sub-agent';
|
|
142
|
-
} else {
|
|
143
|
-
color = C.amber;
|
|
144
|
-
icon = '⚠️';
|
|
145
|
-
message = `Context usage: ${percent}% (approaching 50% threshold)`;
|
|
146
|
-
suggestion = 'Consider: delegate to sub-agent or compact conversation';
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const msgPadded = ` ${icon} ${message}`.padEnd(width - 3) + '┃';
|
|
150
|
-
const sugPadded = ` → ${suggestion}`.padEnd(width - 3) + '┃';
|
|
151
|
-
|
|
152
|
-
return [
|
|
153
|
-
`${color}${C.bold}${topLine}${C.reset}`,
|
|
154
|
-
`${color}${C.bold}┃${msgPadded}${C.reset}`,
|
|
155
|
-
`${color}${C.bold}┃${sugPadded}${C.reset}`,
|
|
156
|
-
`${color}${C.bold}${bottomLine}${C.reset}`,
|
|
157
|
-
'',
|
|
158
|
-
].join('\n');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// =============================================================================
|
|
162
|
-
// Summary Generation
|
|
163
|
-
// =============================================================================
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Generate summary content using pre-fetched data.
|
|
167
|
-
*
|
|
168
|
-
* @param {Object} prefetched - Pre-fetched data from prefetchAllData()
|
|
169
|
-
* @param {Object} options - Additional options
|
|
170
|
-
* @param {string} options.commandName - Active command name
|
|
171
|
-
* @param {string[]} options.activeSections - Active progressive disclosure sections
|
|
172
|
-
* @returns {string} Summary content
|
|
173
|
-
*/
|
|
174
|
-
function generateSummary(prefetched = null, options = {}) {
|
|
175
|
-
const { commandName = null, activeSections = [] } = options;
|
|
176
|
-
|
|
177
|
-
// Box drawing characters
|
|
178
|
-
const boxChars = {
|
|
179
|
-
tl: '╭',
|
|
180
|
-
tr: '╮',
|
|
181
|
-
bl: '╰',
|
|
182
|
-
br: '╯',
|
|
183
|
-
h: '─',
|
|
184
|
-
v: '│',
|
|
185
|
-
lT: '├',
|
|
186
|
-
rT: '┤',
|
|
187
|
-
tT: '┬',
|
|
188
|
-
bT: '┴',
|
|
189
|
-
cross: '┼',
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
const W = 58; // Total inner width
|
|
193
|
-
const L = 20; // Left column width
|
|
194
|
-
const R = W - 24; // Right column width (34 chars)
|
|
195
|
-
|
|
196
|
-
// Create a row with auto-truncation
|
|
197
|
-
function row(left, right, leftColor = '', rightColor = '') {
|
|
198
|
-
const leftStr = `${leftColor}${left}${leftColor ? C.reset : ''}`;
|
|
199
|
-
const rightTrunc = truncate(right, R);
|
|
200
|
-
const rightStr = `${rightColor}${rightTrunc}${rightColor ? C.reset : ''}`;
|
|
201
|
-
return `${C.dim}${boxChars.v}${C.reset} ${pad(leftStr, L)} ${C.dim}${boxChars.v}${C.reset} ${pad(rightStr, R)} ${C.dim}${boxChars.v}${C.reset}\n`;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const divider = () =>
|
|
205
|
-
`${C.dim}${boxChars.lT}${boxChars.h.repeat(L + 2)}${boxChars.cross}${boxChars.h.repeat(W - L - 2)}${boxChars.rT}${C.reset}\n`;
|
|
206
|
-
const headerTopBorder = `${C.dim}${boxChars.tl}${boxChars.h.repeat(L + 2)}${boxChars.tT}${boxChars.h.repeat(W - L - 2)}${boxChars.tr}${C.reset}\n`;
|
|
207
|
-
const headerDivider = `${C.dim}${boxChars.lT}${boxChars.h.repeat(L + 2)}${boxChars.tT}${boxChars.h.repeat(W - L - 2)}${boxChars.rT}${C.reset}\n`;
|
|
208
|
-
const bottomBorder = `${C.dim}${boxChars.bl}${boxChars.h.repeat(L + 2)}${boxChars.bT}${boxChars.h.repeat(W - L - 2)}${boxChars.br}${C.reset}\n`;
|
|
209
|
-
|
|
210
|
-
// Gather data - use prefetched when available, fallback to sync reads
|
|
211
|
-
const branch = prefetched?.git?.branch ?? safeExec('git branch --show-current') ?? 'unknown';
|
|
212
|
-
const lastCommitShort =
|
|
213
|
-
prefetched?.git?.commitShort ?? safeExec('git log -1 --format="%h"') ?? '?';
|
|
214
|
-
const lastCommitMsg =
|
|
215
|
-
prefetched?.git?.commitMsg ?? safeExec('git log -1 --format="%s"') ?? 'no commits';
|
|
216
|
-
const statusLines = (prefetched?.git?.status ?? safeExec('git status --short') ?? '')
|
|
217
|
-
.split('\n')
|
|
218
|
-
.filter(Boolean);
|
|
219
|
-
const statusJson = prefetched?.json?.statusJson ?? safeReadJSON('docs/09-agents/status.json');
|
|
220
|
-
const sessionState =
|
|
221
|
-
prefetched?.json?.sessionState ?? safeReadJSON('docs/09-agents/session-state.json');
|
|
222
|
-
const researchFiles =
|
|
223
|
-
prefetched?.researchFiles ??
|
|
224
|
-
safeLs('docs/10-research')
|
|
225
|
-
.filter(f => f.endsWith('.md') && f !== 'README.md')
|
|
226
|
-
.sort()
|
|
227
|
-
.reverse();
|
|
228
|
-
const epicFiles =
|
|
229
|
-
prefetched?.dirs?.epics?.filter(f => f.endsWith('.md') && f !== 'README.md') ??
|
|
230
|
-
safeLs('docs/05-epics').filter(f => f.endsWith('.md') && f !== 'README.md');
|
|
231
|
-
|
|
232
|
-
// Count stories by status
|
|
233
|
-
const byStatus = {};
|
|
234
|
-
const readyStories = [];
|
|
235
|
-
if (statusJson && statusJson.stories) {
|
|
236
|
-
Object.entries(statusJson.stories).forEach(([id, story]) => {
|
|
237
|
-
const s = story.status || 'unknown';
|
|
238
|
-
byStatus[s] = (byStatus[s] || 0) + 1;
|
|
239
|
-
if (s === 'ready') readyStories.push(id);
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Session info
|
|
244
|
-
let sessionDuration = null;
|
|
245
|
-
let currentStory = null;
|
|
246
|
-
if (sessionState && sessionState.current_session && sessionState.current_session.started_at) {
|
|
247
|
-
const started = new Date(sessionState.current_session.started_at);
|
|
248
|
-
sessionDuration = Math.round((Date.now() - started.getTime()) / 60000);
|
|
249
|
-
currentStory = sessionState.current_session.current_story;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Build table
|
|
253
|
-
let summary = '\n';
|
|
254
|
-
summary += headerTopBorder;
|
|
255
|
-
|
|
256
|
-
// Header row
|
|
257
|
-
const title = commandName ? `Context [${commandName}]` : 'Context Summary';
|
|
258
|
-
const branchColor =
|
|
259
|
-
branch === 'main' ? C.mintGreen : branch.startsWith('fix') ? C.coral : C.skyBlue;
|
|
260
|
-
const maxBranchLen = 20;
|
|
261
|
-
const branchDisplay =
|
|
262
|
-
branch.length > maxBranchLen ? branch.substring(0, maxBranchLen - 2) + '..' : branch;
|
|
263
|
-
const header = `${C.brand}${C.bold}${title}${C.reset} ${branchColor}${branchDisplay}${C.reset} ${C.dim}(${lastCommitShort})${C.reset}`;
|
|
264
|
-
summary += `${C.dim}${boxChars.v}${C.reset} ${pad(header, W - 1)} ${C.dim}${boxChars.v}${C.reset}\n`;
|
|
265
|
-
|
|
266
|
-
summary += headerDivider;
|
|
267
|
-
|
|
268
|
-
// Story counts
|
|
269
|
-
summary += row(
|
|
270
|
-
'In Progress',
|
|
271
|
-
byStatus['in-progress'] ? `${byStatus['in-progress']}` : '0',
|
|
272
|
-
C.peach,
|
|
273
|
-
byStatus['in-progress'] ? C.peach : C.dim
|
|
274
|
-
);
|
|
275
|
-
summary += row(
|
|
276
|
-
'Blocked',
|
|
277
|
-
byStatus['blocked'] ? `${byStatus['blocked']}` : '0',
|
|
278
|
-
C.coral,
|
|
279
|
-
byStatus['blocked'] ? C.coral : C.dim
|
|
280
|
-
);
|
|
281
|
-
summary += row(
|
|
282
|
-
'Ready',
|
|
283
|
-
byStatus['ready'] ? `${byStatus['ready']}` : '0',
|
|
284
|
-
C.skyBlue,
|
|
285
|
-
byStatus['ready'] ? C.skyBlue : C.dim
|
|
286
|
-
);
|
|
287
|
-
const completedColor = `${C.bold}${C.mintGreen}`;
|
|
288
|
-
summary += row(
|
|
289
|
-
'Completed',
|
|
290
|
-
byStatus['done'] ? `${byStatus['done']}` : '0',
|
|
291
|
-
completedColor,
|
|
292
|
-
byStatus['done'] ? completedColor : C.dim
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
summary += divider();
|
|
296
|
-
|
|
297
|
-
// Git status
|
|
298
|
-
const uncommittedStatus =
|
|
299
|
-
statusLines.length > 0 ? `${statusLines.length} uncommitted` : '✓ clean';
|
|
300
|
-
summary += row('Git', uncommittedStatus, C.blue, statusLines.length > 0 ? C.peach : C.mintGreen);
|
|
301
|
-
|
|
302
|
-
// Session
|
|
303
|
-
const sessionText = sessionDuration !== null ? `${sessionDuration} min active` : 'no session';
|
|
304
|
-
summary += row('Session', sessionText, C.blue, sessionDuration !== null ? C.lightGreen : C.dim);
|
|
305
|
-
|
|
306
|
-
// Current story
|
|
307
|
-
const storyText = currentStory ? currentStory : 'none';
|
|
308
|
-
summary += row('Working on', storyText, C.blue, currentStory ? C.lightYellow : C.dim);
|
|
309
|
-
|
|
310
|
-
// Ready stories
|
|
311
|
-
if (readyStories.length > 0) {
|
|
312
|
-
summary += row('⭐ Up Next', readyStories.slice(0, 3).join(', '), C.skyBlue, C.skyBlue);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Progressive disclosure: Show active sections
|
|
316
|
-
if (activeSections.length > 0) {
|
|
317
|
-
summary += divider();
|
|
318
|
-
const sectionList = activeSections.join(', ');
|
|
319
|
-
summary += row('📖 Sections', sectionList, C.cyan, C.mintGreen);
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
summary += divider();
|
|
323
|
-
|
|
324
|
-
// Scale indicator (EP-0033)
|
|
325
|
-
let scaleDetectorSummary;
|
|
326
|
-
try {
|
|
327
|
-
scaleDetectorSummary = require('./scale-detector');
|
|
328
|
-
} catch {
|
|
329
|
-
/* not available */
|
|
330
|
-
}
|
|
331
|
-
if (scaleDetectorSummary) {
|
|
332
|
-
try {
|
|
333
|
-
const scaleResult = scaleDetectorSummary.detectScale({
|
|
334
|
-
rootDir: process.cwd(),
|
|
335
|
-
statusJson: prefetched?.json?.statusJson,
|
|
336
|
-
sessionState: prefetched?.json?.sessionState,
|
|
337
|
-
});
|
|
338
|
-
const label = scaleDetectorSummary.getScaleLabel(scaleResult.scale);
|
|
339
|
-
summary += row('Scale', label, C.lavender, C.cyan);
|
|
340
|
-
} catch {
|
|
341
|
-
// Silently ignore
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// Command prerequisites
|
|
346
|
-
if (options.prereqResult && !options.prereqResult.allMet) {
|
|
347
|
-
const n = options.prereqResult.unmet.length;
|
|
348
|
-
const crit = options.prereqResult.criticalUnmet;
|
|
349
|
-
const prereqText = crit > 0 ? `${crit} critical missing` : `${n} unmet`;
|
|
350
|
-
summary += row('Prereqs', prereqText, C.coral, C.coral);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Key files
|
|
354
|
-
const keyFileChecks = [
|
|
355
|
-
{ path: 'CLAUDE.md', label: 'CLAUDE' },
|
|
356
|
-
{ path: 'README.md', label: 'README' },
|
|
357
|
-
{ path: 'docs/04-architecture/README.md', label: 'arch' },
|
|
358
|
-
{ path: 'docs/02-practices/README.md', label: 'practices' },
|
|
359
|
-
];
|
|
360
|
-
const keyFileStatus = keyFileChecks
|
|
361
|
-
.map(f => {
|
|
362
|
-
const exists = fs.existsSync(f.path);
|
|
363
|
-
return exists ? `${C.mintGreen}✓${C.reset}${f.label}` : `${C.dim}○${f.label}${C.reset}`;
|
|
364
|
-
})
|
|
365
|
-
.join(' ');
|
|
366
|
-
summary += row('Key files', keyFileStatus, C.lavender, '');
|
|
367
|
-
|
|
368
|
-
// Research
|
|
369
|
-
const researchText = researchFiles.length > 0 ? `${researchFiles.length} notes` : 'none';
|
|
370
|
-
summary += row(
|
|
371
|
-
'Research',
|
|
372
|
-
researchText,
|
|
373
|
-
C.lavender,
|
|
374
|
-
researchFiles.length > 0 ? C.skyBlue : C.dim
|
|
375
|
-
);
|
|
376
|
-
|
|
377
|
-
// Epics
|
|
378
|
-
const epicText = epicFiles.length > 0 ? `${epicFiles.length} epics` : 'none';
|
|
379
|
-
summary += row('Epics', epicText, C.lavender, epicFiles.length > 0 ? C.skyBlue : C.dim);
|
|
380
|
-
|
|
381
|
-
summary += divider();
|
|
382
|
-
|
|
383
|
-
// Last commit
|
|
384
|
-
summary += row(
|
|
385
|
-
'Last commit',
|
|
386
|
-
`${C.peach}${lastCommitShort}${C.reset} ${lastCommitMsg}`,
|
|
387
|
-
C.dim,
|
|
388
|
-
''
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
summary += bottomBorder;
|
|
392
|
-
|
|
393
|
-
return summary;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// =============================================================================
|
|
397
|
-
// Full Content Generation
|
|
398
|
-
// =============================================================================
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Generate full content using pre-fetched data.
|
|
402
|
-
*
|
|
403
|
-
* @param {Object} prefetched - Pre-fetched data from prefetchAllData()
|
|
404
|
-
* @param {Object} options - Additional options
|
|
405
|
-
* @param {string} options.commandName - Active command name
|
|
406
|
-
* @param {string[]} options.activeSections - Active progressive disclosure sections
|
|
407
|
-
* @returns {string} Full content
|
|
408
|
-
*/
|
|
409
|
-
function generateFullContent(prefetched = null, options = {}) {
|
|
410
|
-
const {
|
|
411
|
-
commandName = null,
|
|
412
|
-
activeSections = [],
|
|
413
|
-
smartDetectResults = null,
|
|
414
|
-
verbosityMode = 'full',
|
|
415
|
-
} = options;
|
|
416
|
-
|
|
417
|
-
// MINIMAL MODE: Return compact output only
|
|
418
|
-
if (verbosityMode === 'minimal') {
|
|
419
|
-
return generateMinimalContent(prefetched, options);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
let content = '';
|
|
423
|
-
|
|
424
|
-
const modeLabel = verbosityMode !== 'full' ? ` [${verbosityMode}]` : '';
|
|
425
|
-
const title = commandName
|
|
426
|
-
? `AgileFlow Context [${commandName}]${modeLabel}`
|
|
427
|
-
: `AgileFlow Context${modeLabel}`;
|
|
428
|
-
content += `${C.lavender}${C.bold}${title}${C.reset}\n`;
|
|
429
|
-
content += `${C.dim}Generated: ${new Date().toISOString()}${C.reset}\n`;
|
|
430
|
-
|
|
431
|
-
// SESSION CONTEXT BANNER - skip in lite mode
|
|
432
|
-
if (verbosityMode === 'full') {
|
|
433
|
-
const sessionManagerPath = path.join(__dirname, '..', 'session-manager.js');
|
|
434
|
-
const altSessionManagerPath = '.agileflow/scripts/session-manager.js';
|
|
435
|
-
|
|
436
|
-
if (fs.existsSync(sessionManagerPath) || fs.existsSync(altSessionManagerPath)) {
|
|
437
|
-
const managerPath = fs.existsSync(sessionManagerPath)
|
|
438
|
-
? sessionManagerPath
|
|
439
|
-
: altSessionManagerPath;
|
|
440
|
-
const sessionStatus = safeExec(`node "${managerPath}" status`);
|
|
441
|
-
|
|
442
|
-
if (sessionStatus) {
|
|
443
|
-
try {
|
|
444
|
-
const statusData = JSON.parse(sessionStatus);
|
|
445
|
-
if (statusData.current) {
|
|
446
|
-
const session = statusData.current;
|
|
447
|
-
const isMain = session.is_main === true;
|
|
448
|
-
const sessionName = session.nickname
|
|
449
|
-
? `Session ${session.id} "${session.nickname}"`
|
|
450
|
-
: `Session ${session.id}`;
|
|
451
|
-
|
|
452
|
-
content += `\n${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`;
|
|
453
|
-
content += `${C.teal}${C.bold}📍 SESSION CONTEXT${C.reset}\n`;
|
|
454
|
-
content += `${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n`;
|
|
455
|
-
|
|
456
|
-
if (isMain) {
|
|
457
|
-
content += `${C.mintGreen}${C.bold}${sessionName}${C.reset} ${C.dim}(main project)${C.reset}\n`;
|
|
458
|
-
} else {
|
|
459
|
-
content += `${C.peach}${C.bold}🔀 ${sessionName}${C.reset} ${C.dim}(worktree)${C.reset}\n`;
|
|
460
|
-
content += `Branch: ${C.skyBlue}${session.branch || 'unknown'}${C.reset}\n`;
|
|
461
|
-
content += `${C.dim}Path: ${session.path || process.cwd()}${C.reset}\n`;
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (statusData.otherActive > 0) {
|
|
465
|
-
content += `${C.amber}⚠️ ${statusData.otherActive} other active session(s)${C.reset} - check story claims below\n`;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
content += `${C.teal}${C.bold}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${C.reset}\n\n`;
|
|
469
|
-
}
|
|
470
|
-
} catch {
|
|
471
|
-
// Silently ignore session parse errors
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
} // end verbosityMode === 'full' (session context banner)
|
|
476
|
-
|
|
477
|
-
// INTERACTION MODE (AskUserQuestion)
|
|
478
|
-
const earlyMetadata =
|
|
479
|
-
prefetched?.json?.metadata ?? safeReadJSON('docs/00-meta/agileflow-metadata.json');
|
|
480
|
-
const askUserQuestionConfig = earlyMetadata?.features?.askUserQuestion;
|
|
481
|
-
|
|
482
|
-
if (askUserQuestionConfig?.enabled) {
|
|
483
|
-
content += `${C.coral}${C.bold}┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓${C.reset}\n`;
|
|
484
|
-
content += `${C.coral}${C.bold}┃ 🔔 SMART AskUserQuestion After EVERY Response ┃${C.reset}\n`;
|
|
485
|
-
content += `${C.coral}${C.bold}┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛${C.reset}\n`;
|
|
486
|
-
content += `${C.bold}After completing ANY task${C.reset} (implementation, fix, etc.):\n`;
|
|
487
|
-
content += `${C.mintGreen}→ ALWAYS${C.reset} call ${C.skyBlue}AskUserQuestion${C.reset} tool with ${C.bold}SMART, contextual${C.reset} options\n`;
|
|
488
|
-
content += `${C.coral}→ NEVER${C.reset} generic options like "Continue" or "What next?"\n\n`;
|
|
489
|
-
content += `${C.bold}Smart Suggestion Principles:${C.reset}\n`;
|
|
490
|
-
content += `${C.mintGreen}→${C.reset} Always mark one option ${C.bold}"(Recommended)"${C.reset} based on logical next step\n`;
|
|
491
|
-
content += `${C.mintGreen}→${C.reset} Be specific: ${C.dim}"Run npm test for auth changes"${C.reset} not ${C.dim}"Run tests"${C.reset}\n`;
|
|
492
|
-
content += `${C.mintGreen}→${C.reset} Include context: ${C.dim}"3 files changed"${C.reset}, story IDs, test results\n`;
|
|
493
|
-
content += `${C.mintGreen}→${C.reset} Suggest workflow progression: plan → implement → test → commit\n`;
|
|
494
|
-
content += `${C.mintGreen}→${C.reset} After errors: suggest specific alternative, not ${C.dim}"fix it"${C.reset}\n\n`;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// CONTEXT BUDGET WARNING
|
|
498
|
-
const contextUsage = getContextPercentage();
|
|
499
|
-
if (contextUsage && contextUsage.percent >= 50) {
|
|
500
|
-
content += generateContextWarning(contextUsage.percent);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// COMMAND PREREQUISITES WARNING
|
|
504
|
-
if (
|
|
505
|
-
options.prereqResult &&
|
|
506
|
-
!options.prereqResult.allMet &&
|
|
507
|
-
options.prereqResult.unmet.length > 0
|
|
508
|
-
) {
|
|
509
|
-
try {
|
|
510
|
-
const { formatPrereqWarnings } = require('./command-prereqs');
|
|
511
|
-
content += formatPrereqWarnings(options.prereqResult);
|
|
512
|
-
} catch {
|
|
513
|
-
// Fail open
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// PROGRESSIVE DISCLOSURE - skip in lite mode
|
|
518
|
-
if (activeSections.length > 0 && verbosityMode === 'full') {
|
|
519
|
-
content += `\n${C.cyan}${C.bold}═══ 📖 Progressive Disclosure: Active Sections ═══${C.reset}\n`;
|
|
520
|
-
content += `${C.dim}The following sections are activated based on command parameters.${C.reset}\n`;
|
|
521
|
-
content += `${C.dim}Look for <!-- SECTION: name --> markers in the command file.${C.reset}\n\n`;
|
|
522
|
-
|
|
523
|
-
activeSections.forEach(section => {
|
|
524
|
-
content += ` ${C.mintGreen}✓${C.reset} ${C.bold}${section}${C.reset}\n`;
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
const sectionDescriptions = {
|
|
528
|
-
'loop-mode': 'Autonomous epic execution (MODE=loop)',
|
|
529
|
-
'multi-session': 'Multi-session coordination detected',
|
|
530
|
-
'visual-e2e': 'Visual screenshot verification (VISUAL=true)',
|
|
531
|
-
delegation: 'Expert spawning patterns (load when spawning)',
|
|
532
|
-
stuck: 'Research prompt guidance (load after 2 failures)',
|
|
533
|
-
'plan-mode': 'Planning workflow details (load when entering plan mode)',
|
|
534
|
-
tools: 'Tool usage guidance (load when needed)',
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
content += `\n${C.dim}Section meanings:${C.reset}\n`;
|
|
538
|
-
activeSections.forEach(section => {
|
|
539
|
-
const desc = sectionDescriptions[section] || 'Conditional content';
|
|
540
|
-
content += ` ${C.dim}• ${section}: ${desc}${C.reset}\n`;
|
|
541
|
-
});
|
|
542
|
-
content += '\n';
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// SCALE DETECTION (EP-0033) - skip in lite mode
|
|
546
|
-
if (verbosityMode === 'full') {
|
|
547
|
-
let scaleDetector;
|
|
548
|
-
try {
|
|
549
|
-
scaleDetector = require('./scale-detector');
|
|
550
|
-
} catch {
|
|
551
|
-
/* not available */
|
|
552
|
-
}
|
|
553
|
-
if (scaleDetector) {
|
|
554
|
-
try {
|
|
555
|
-
const scaleResult = scaleDetector.detectScale({
|
|
556
|
-
rootDir: process.cwd(),
|
|
557
|
-
statusJson: prefetched?.json?.statusJson,
|
|
558
|
-
sessionState: prefetched?.json?.sessionState,
|
|
559
|
-
});
|
|
560
|
-
const recs = scaleDetector.getScaleRecommendations(scaleResult.scale);
|
|
561
|
-
const label = scaleDetector.getScaleLabel(scaleResult.scale);
|
|
562
|
-
content += `\n${C.cyan}${C.bold}═══ Project Scale: ${label} ═══${C.reset}\n`;
|
|
563
|
-
content += `${C.dim}Detected: ${scaleResult.metrics.files} files, ${scaleResult.metrics.stories} stories, ${scaleResult.metrics.commits} commits (6mo)${C.reset}\n`;
|
|
564
|
-
content += `Planning depth: ${C.mintGreen}${recs.planningDepth}${C.reset} | Experts: ${C.mintGreen}${recs.expertCount}${C.reset}\n`;
|
|
565
|
-
content += `${C.dim}${recs.description}${C.reset}\n`;
|
|
566
|
-
} catch {
|
|
567
|
-
// Silently ignore scale detection errors
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
} // end verbosityMode === 'full' (scale detection)
|
|
571
|
-
|
|
572
|
-
// GIT STATUS
|
|
573
|
-
content += `\n${C.skyBlue}${C.bold}═══ Git Status ═══${C.reset}\n`;
|
|
574
|
-
const branch = prefetched?.git?.branch ?? safeExec('git branch --show-current') ?? 'unknown';
|
|
575
|
-
const status = prefetched?.git?.status ?? safeExec('git status --short') ?? '';
|
|
576
|
-
const statusLines = status.split('\n').filter(Boolean);
|
|
577
|
-
const lastCommit =
|
|
578
|
-
prefetched?.git?.commitFull ?? safeExec('git log -1 --format="%h %s"') ?? 'no commits';
|
|
579
|
-
|
|
580
|
-
content += `Branch: ${C.mintGreen}${branch}${C.reset}\n`;
|
|
581
|
-
content += `Last commit: ${C.dim}${lastCommit}${C.reset}\n`;
|
|
582
|
-
if (statusLines.length > 0) {
|
|
583
|
-
content += `Uncommitted: ${C.peach}${statusLines.length} file(s)${C.reset}\n`;
|
|
584
|
-
statusLines.slice(0, 10).forEach(line => (content += ` ${C.dim}${line}${C.reset}\n`));
|
|
585
|
-
if (statusLines.length > 10)
|
|
586
|
-
content += ` ${C.dim}... and ${statusLines.length - 10} more${C.reset}\n`;
|
|
587
|
-
} else {
|
|
588
|
-
content += `Uncommitted: ${C.mintGreen}clean${C.reset}\n`;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// STATUS.JSON
|
|
592
|
-
const statusJson = prefetched?.json?.statusJson ?? safeReadJSON('docs/09-agents/status.json');
|
|
593
|
-
|
|
594
|
-
if (verbosityMode === 'lite') {
|
|
595
|
-
// Lite mode: show counts and active stories only
|
|
596
|
-
content += `\n${C.skyBlue}${C.bold}═══ Status.json (Active Stories) ═══${C.reset}\n`;
|
|
597
|
-
if (statusJson?.stories) {
|
|
598
|
-
const active = Object.entries(statusJson.stories)
|
|
599
|
-
.filter(([, s]) => s.status === 'in-progress' || s.status === 'ready')
|
|
600
|
-
.slice(0, 10);
|
|
601
|
-
if (active.length > 0) {
|
|
602
|
-
content += `Active stories (${active.length}):\n`;
|
|
603
|
-
active.forEach(([id, s]) => {
|
|
604
|
-
content += ` ${C.lavender}${id}${C.reset}: ${s.title || 'untitled'} ${C.dim}[${s.status}]${C.reset}\n`;
|
|
605
|
-
});
|
|
606
|
-
} else {
|
|
607
|
-
content += `${C.dim}No active stories${C.reset}\n`;
|
|
608
|
-
}
|
|
609
|
-
} else {
|
|
610
|
-
content += `${C.dim}No status.json found${C.reset}\n`;
|
|
611
|
-
}
|
|
612
|
-
} else {
|
|
613
|
-
// Full mode: dump entire JSON
|
|
614
|
-
content += `\n${C.skyBlue}${C.bold}═══ Status.json (Full Content) ═══${C.reset}\n`;
|
|
615
|
-
if (statusJson) {
|
|
616
|
-
content += `${C.dim}${'─'.repeat(50)}${C.reset}\n`;
|
|
617
|
-
content +=
|
|
618
|
-
JSON.stringify(statusJson, null, 2)
|
|
619
|
-
.split('\n')
|
|
620
|
-
.map(l => ` ${l}`)
|
|
621
|
-
.join('\n') + '\n';
|
|
622
|
-
content += `${C.dim}${'─'.repeat(50)}${C.reset}\n`;
|
|
623
|
-
} else {
|
|
624
|
-
content += `${C.dim}No status.json found${C.reset}\n`;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
// SESSION STATE
|
|
629
|
-
const sessionState =
|
|
630
|
-
prefetched?.json?.sessionState ?? safeReadJSON('docs/09-agents/session-state.json');
|
|
631
|
-
|
|
632
|
-
if (verbosityMode === 'lite') {
|
|
633
|
-
// Brief session state in lite mode
|
|
634
|
-
content += `\n${C.skyBlue}${C.bold}═══ Session State ═══${C.reset}\n`;
|
|
635
|
-
if (sessionState?.current_session?.started_at) {
|
|
636
|
-
const started = new Date(sessionState.current_session.started_at);
|
|
637
|
-
const duration = Math.round((Date.now() - started.getTime()) / 60000);
|
|
638
|
-
content += `Session: ${C.lightGreen}${duration} min${C.reset}`;
|
|
639
|
-
if (sessionState.current_session.current_story) {
|
|
640
|
-
content += ` | Working on: ${C.lightYellow}${sessionState.current_session.current_story}${C.reset}`;
|
|
641
|
-
}
|
|
642
|
-
content += '\n';
|
|
643
|
-
if (Array.isArray(sessionState.active_commands) && sessionState.active_commands.length > 0) {
|
|
644
|
-
const cmdNames = sessionState.active_commands.map(c => c.name).join(', ');
|
|
645
|
-
content += `Active commands: ${C.skyBlue}${cmdNames}${C.reset}\n`;
|
|
646
|
-
}
|
|
647
|
-
} else {
|
|
648
|
-
content += `${C.dim}No active session${C.reset}\n`;
|
|
649
|
-
}
|
|
650
|
-
} else {
|
|
651
|
-
// Full session state
|
|
652
|
-
content += `\n${C.skyBlue}${C.bold}═══ Session State ═══${C.reset}\n`;
|
|
653
|
-
if (sessionState) {
|
|
654
|
-
const current = sessionState.current_session;
|
|
655
|
-
if (current && current.started_at) {
|
|
656
|
-
const started = new Date(current.started_at);
|
|
657
|
-
const duration = Math.round((Date.now() - started.getTime()) / 60000);
|
|
658
|
-
content += `Active session: ${C.lightGreen}${duration} min${C.reset}\n`;
|
|
659
|
-
if (current.current_story) {
|
|
660
|
-
content += `Working on: ${C.lightYellow}${current.current_story}${C.reset}\n`;
|
|
661
|
-
}
|
|
662
|
-
} else {
|
|
663
|
-
content += `${C.dim}No active session${C.reset}\n`;
|
|
664
|
-
}
|
|
665
|
-
if (Array.isArray(sessionState.active_commands) && sessionState.active_commands.length > 0) {
|
|
666
|
-
const cmdNames = sessionState.active_commands.map(c => c.name).join(', ');
|
|
667
|
-
content += `Active commands: ${C.skyBlue}${cmdNames}${C.reset}\n`;
|
|
668
|
-
} else if (sessionState.active_command && sessionState.active_command.name) {
|
|
669
|
-
content += `Active command: ${C.skyBlue}${sessionState.active_command.name}${C.reset}\n`;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
const batchLoop = sessionState.batch_loop;
|
|
673
|
-
if (batchLoop && batchLoop.enabled) {
|
|
674
|
-
content += `\n${C.skyBlue}${C.bold}── Batch Loop Active ──${C.reset}\n`;
|
|
675
|
-
content += `Pattern: ${C.cyan}${batchLoop.pattern}${C.reset}\n`;
|
|
676
|
-
content += `Action: ${C.cyan}${batchLoop.action}${C.reset}\n`;
|
|
677
|
-
content += `Current: ${C.lightYellow}${batchLoop.current_item || 'none'}${C.reset}\n`;
|
|
678
|
-
const summary = batchLoop.summary || {};
|
|
679
|
-
content += `Progress: ${C.lightGreen}${summary.completed || 0}${C.reset}/${summary.total || 0} `;
|
|
680
|
-
content += `(${C.lightYellow}${summary.in_progress || 0}${C.reset} in progress)\n`;
|
|
681
|
-
content += `Iteration: ${batchLoop.iteration || 0}/${batchLoop.max_iterations || 50}\n`;
|
|
682
|
-
}
|
|
683
|
-
} else {
|
|
684
|
-
content += `${C.dim}No session-state.json found${C.reset}\n`;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// Remaining content would continue here...
|
|
689
|
-
// For brevity, returning the core content
|
|
690
|
-
// The full implementation would include all remaining sections
|
|
691
|
-
|
|
692
|
-
// Add remaining sections (pass verbosityMode through options)
|
|
693
|
-
content += generateRemainingContent(prefetched, { ...options, verbosityMode });
|
|
694
|
-
|
|
695
|
-
return content;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
/**
|
|
699
|
-
* Generate remaining content sections (internal helper).
|
|
700
|
-
* @param {Object} prefetched - Pre-fetched data
|
|
701
|
-
* @param {Object} options - Options
|
|
702
|
-
* @returns {string} Remaining content
|
|
703
|
-
*/
|
|
704
|
-
function generateRemainingContent(prefetched, options = {}) {
|
|
705
|
-
const { verbosityMode = 'full' } = options;
|
|
706
|
-
let content = '';
|
|
707
|
-
|
|
708
|
-
// STORY CLAIMS - skip in lite mode
|
|
709
|
-
const shouldLoadClaims = prefetched?.sectionsToLoad?.sessionClaims !== false;
|
|
710
|
-
if (shouldLoadClaims && verbosityMode === 'full') {
|
|
711
|
-
const storyClaimingPath = path.join(__dirname, 'story-claiming.js');
|
|
712
|
-
const altStoryClaimingPath = '.agileflow/scripts/lib/story-claiming.js';
|
|
713
|
-
|
|
714
|
-
if (fs.existsSync(storyClaimingPath) || fs.existsSync(altStoryClaimingPath)) {
|
|
715
|
-
try {
|
|
716
|
-
const claimPath = fs.existsSync(storyClaimingPath)
|
|
717
|
-
? storyClaimingPath
|
|
718
|
-
: altStoryClaimingPath;
|
|
719
|
-
const storyClaiming = require(claimPath);
|
|
720
|
-
|
|
721
|
-
const othersResult = storyClaiming.getStoriesClaimedByOthers();
|
|
722
|
-
if (othersResult.ok && othersResult.stories && othersResult.stories.length > 0) {
|
|
723
|
-
content += `\n${C.amber}${C.bold}═══ 🔒 Claimed Stories ═══${C.reset}\n`;
|
|
724
|
-
content += `${C.dim}Stories locked by other sessions - pick a different one${C.reset}\n`;
|
|
725
|
-
othersResult.stories.forEach(story => {
|
|
726
|
-
const sessionDir = story.claimedBy?.path
|
|
727
|
-
? path.basename(story.claimedBy.path)
|
|
728
|
-
: 'unknown';
|
|
729
|
-
content += ` ${C.coral}🔒${C.reset} ${C.lavender}${story.id ?? '?'}${C.reset} "${story.title ?? 'untitled'}" ${C.dim}→ Session ${story.claimedBy?.session_id ?? '?'} (${sessionDir})${C.reset}\n`;
|
|
730
|
-
});
|
|
731
|
-
content += '\n';
|
|
732
|
-
}
|
|
733
|
-
|
|
734
|
-
const myResult = storyClaiming.getClaimedStoriesForSession();
|
|
735
|
-
if (myResult.ok && myResult.stories && myResult.stories.length > 0) {
|
|
736
|
-
content += `\n${C.mintGreen}${C.bold}═══ ✓ Your Claimed Stories ═══${C.reset}\n`;
|
|
737
|
-
myResult.stories.forEach(story => {
|
|
738
|
-
content += ` ${C.mintGreen}✓${C.reset} ${C.lavender}${story.id ?? '?'}${C.reset} "${story.title ?? 'untitled'}"\n`;
|
|
739
|
-
});
|
|
740
|
-
content += '\n';
|
|
741
|
-
}
|
|
742
|
-
} catch {
|
|
743
|
-
// Story claiming not available
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// UI TESTING STATUS (unified Visual E2E + Browser QA) - skip in lite mode
|
|
749
|
-
if (verbosityMode === 'full') {
|
|
750
|
-
const metadata =
|
|
751
|
-
prefetched?.json?.metadata ?? safeReadJSON('docs/00-meta/agileflow-metadata.json');
|
|
752
|
-
const browserQaConfig = metadata?.features?.browserqa;
|
|
753
|
-
const playwrightExists =
|
|
754
|
-
fs.existsSync('playwright.config.ts') || fs.existsSync('playwright.config.js');
|
|
755
|
-
const screenshotsExists = fs.existsSync('screenshots');
|
|
756
|
-
const browserQaSpecsExist = fs.existsSync('.agileflow/ui-review/specs');
|
|
757
|
-
|
|
758
|
-
const uiTestingEnabled =
|
|
759
|
-
playwrightExists || screenshotsExists || browserQaConfig?.enabled || browserQaSpecsExist;
|
|
760
|
-
|
|
761
|
-
if (uiTestingEnabled) {
|
|
762
|
-
const browserQaRunsExist = fs.existsSync('.agileflow/ui-review/runs');
|
|
763
|
-
content += `\n${C.brand}${C.bold}═══ UI Testing (Bowser): ENABLED ═══${C.reset}\n`;
|
|
764
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
|
|
765
|
-
content += `${C.mintGreen}✓ Playwright:${C.reset} ${playwrightExists ? 'configured' : 'not found'}\n`;
|
|
766
|
-
content += `${C.mintGreen}✓ Screenshots:${C.reset} ${screenshotsExists ? 'screenshots/ (for visual verification)' : 'not found'}\n`;
|
|
767
|
-
content += `${C.mintGreen}✓ Browser QA Specs:${C.reset} ${browserQaSpecsExist ? '.agileflow/ui-review/specs/' : 'not found'}\n`;
|
|
768
|
-
content += `${C.mintGreen}✓ Evidence Runs:${C.reset} ${browserQaRunsExist ? '.agileflow/ui-review/runs/' : 'not found'}\n\n`;
|
|
769
|
-
content += `${C.bold}AGENTIC TESTING:${C.reset} ${C.skyBlue}/agileflow:browser-qa SCENARIO=<spec.yaml>${C.reset}\n`;
|
|
770
|
-
content += `${C.dim} Pass rate: 80% threshold | Results are informational (not merge-blocking)${C.reset}\n`;
|
|
771
|
-
content += `${C.bold}VISUAL VERIFICATION:${C.reset} ${C.skyBlue}VISUAL=true${C.reset} flag with babysit\n`;
|
|
772
|
-
content += `${C.dim} /agileflow:babysit EPIC=EP-XXXX MODE=loop VISUAL=true${C.reset}\n\n`;
|
|
773
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n\n`;
|
|
774
|
-
}
|
|
775
|
-
} // end verbosityMode === 'full' (UI testing status)
|
|
776
|
-
|
|
777
|
-
// DOCS STRUCTURE - skip in lite mode
|
|
778
|
-
if (verbosityMode === 'full') {
|
|
779
|
-
content += `\n${C.skyBlue}${C.bold}═══ Documentation ═══${C.reset}\n`;
|
|
780
|
-
const docsDir = 'docs';
|
|
781
|
-
const docFolders = (prefetched?.dirs?.docs ?? safeLs(docsDir)).filter(f => {
|
|
782
|
-
try {
|
|
783
|
-
return fs.statSync(path.join(docsDir, f)).isDirectory();
|
|
784
|
-
} catch {
|
|
785
|
-
return false;
|
|
786
|
-
}
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
if (docFolders.length > 0) {
|
|
790
|
-
docFolders.forEach(folder => {
|
|
791
|
-
const folderPath = path.join(docsDir, folder);
|
|
792
|
-
const files = safeLs(folderPath);
|
|
793
|
-
const mdFiles = files.filter(f => f.endsWith('.md'));
|
|
794
|
-
const jsonFiles = files.filter(f => f.endsWith('.json') || f.endsWith('.jsonl'));
|
|
795
|
-
const info = [];
|
|
796
|
-
if (mdFiles.length > 0) info.push(`${mdFiles.length} md`);
|
|
797
|
-
if (jsonFiles.length > 0) info.push(`${jsonFiles.length} json`);
|
|
798
|
-
content += ` ${C.dim}${folder}/${C.reset} ${info.length > 0 ? `(${info.join(', ')})` : ''}\n`;
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
} // end verbosityMode === 'full' (docs structure)
|
|
802
|
-
|
|
803
|
-
// RESEARCH NOTES - lite shows list only, minimal skips entirely
|
|
804
|
-
if (verbosityMode === 'full' || verbosityMode === 'lite') {
|
|
805
|
-
const shouldLoadResearch = prefetched?.sectionsToLoad?.researchContent !== false;
|
|
806
|
-
content += `\n${C.skyBlue}${C.bold}═══ Research Notes ═══${C.reset}\n`;
|
|
807
|
-
const researchDir = 'docs/10-research';
|
|
808
|
-
const researchFiles =
|
|
809
|
-
prefetched?.researchFiles ??
|
|
810
|
-
safeLs(researchDir)
|
|
811
|
-
.filter(f => f.endsWith('.md') && f !== 'README.md')
|
|
812
|
-
.sort()
|
|
813
|
-
.reverse();
|
|
814
|
-
if (researchFiles.length > 0) {
|
|
815
|
-
content += `${C.dim}───${C.reset} Available Research Notes\n`;
|
|
816
|
-
researchFiles.forEach(file => (content += ` ${C.dim}${file}${C.reset}\n`));
|
|
817
|
-
|
|
818
|
-
// In lite mode, only show the list - no content dump
|
|
819
|
-
if (verbosityMode === 'full') {
|
|
820
|
-
const mostRecentFile = researchFiles[0];
|
|
821
|
-
const mostRecentPath = path.join(researchDir, mostRecentFile);
|
|
822
|
-
const mostRecentContent =
|
|
823
|
-
prefetched?.mostRecentResearch ?? (shouldLoadResearch ? safeRead(mostRecentPath) : null);
|
|
824
|
-
|
|
825
|
-
if (mostRecentContent) {
|
|
826
|
-
content += `\n${C.mintGreen}📄 Most Recent: ${mostRecentFile}${C.reset}\n`;
|
|
827
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
|
|
828
|
-
content += mostRecentContent + '\n';
|
|
829
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
|
|
830
|
-
} else if (!shouldLoadResearch) {
|
|
831
|
-
content += `\n${C.dim}📄 Content deferred (lazy loading). Use /agileflow:research to access.${C.reset}\n`;
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
} else {
|
|
835
|
-
content += `${C.dim}No research notes${C.reset}\n`;
|
|
836
|
-
}
|
|
837
|
-
} // end research notes (full/lite)
|
|
838
|
-
|
|
839
|
-
// BUS MESSAGES - skip in lite mode
|
|
840
|
-
if (verbosityMode === 'full') {
|
|
841
|
-
content += `\n${C.skyBlue}${C.bold}═══ Recent Agent Messages ═══${C.reset}\n`;
|
|
842
|
-
const busPath = 'docs/09-agents/bus/log.jsonl';
|
|
843
|
-
const busContent = prefetched?.text?.busLog ?? safeRead(busPath);
|
|
844
|
-
if (busContent) {
|
|
845
|
-
const lines = busContent.trim().split('\n').filter(Boolean);
|
|
846
|
-
const recent = lines.slice(-5);
|
|
847
|
-
if (recent.length > 0) {
|
|
848
|
-
recent.forEach(line => {
|
|
849
|
-
try {
|
|
850
|
-
const msg = JSON.parse(line);
|
|
851
|
-
const time = msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : '?';
|
|
852
|
-
content += ` ${C.dim}[${time}]${C.reset} ${msg.from || '?'}: ${msg.type || msg.message || '?'}\n`;
|
|
853
|
-
} catch {
|
|
854
|
-
content += ` ${C.dim}${line.substring(0, 80)}...${C.reset}\n`;
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
} else {
|
|
858
|
-
content += `${C.dim}No messages${C.reset}\n`;
|
|
859
|
-
}
|
|
860
|
-
} else {
|
|
861
|
-
content += `${C.dim}No bus log found${C.reset}\n`;
|
|
862
|
-
}
|
|
863
|
-
} // end verbosityMode === 'full' (bus messages)
|
|
864
|
-
|
|
865
|
-
// KEY FILES - full dumps in full mode, existence check in lite
|
|
866
|
-
if (verbosityMode === 'full') {
|
|
867
|
-
content += `\n${C.cyan}${C.bold}═══ Key Context Files (Full Content) ═══${C.reset}\n`;
|
|
868
|
-
|
|
869
|
-
const prefetchedKeyMap = {
|
|
870
|
-
'CLAUDE.md': 'claudeMd',
|
|
871
|
-
'README.md': 'readmeMd',
|
|
872
|
-
'docs/04-architecture/README.md': 'archReadme',
|
|
873
|
-
'docs/02-practices/README.md': 'practicesReadme',
|
|
874
|
-
'docs/08-project/roadmap.md': 'roadmap',
|
|
875
|
-
};
|
|
876
|
-
|
|
877
|
-
const keyFilesToRead = [
|
|
878
|
-
{ path: 'CLAUDE.md', label: 'CLAUDE.md (Project Instructions)' },
|
|
879
|
-
{ path: 'README.md', label: 'README.md (Project Overview)' },
|
|
880
|
-
{ path: 'docs/04-architecture/README.md', label: 'Architecture Index' },
|
|
881
|
-
{ path: 'docs/02-practices/README.md', label: 'Practices Index' },
|
|
882
|
-
{ path: 'docs/08-project/roadmap.md', label: 'Roadmap' },
|
|
883
|
-
];
|
|
884
|
-
|
|
885
|
-
keyFilesToRead.forEach(({ path: filePath, label }) => {
|
|
886
|
-
const prefetchKey = prefetchedKeyMap[filePath];
|
|
887
|
-
const fileContent = prefetched?.text?.[prefetchKey] ?? safeRead(filePath);
|
|
888
|
-
if (fileContent) {
|
|
889
|
-
content += `\n${C.green}✓ ${label}${C.reset} ${C.dim}(${filePath})${C.reset}\n`;
|
|
890
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
|
|
891
|
-
content += fileContent + '\n';
|
|
892
|
-
content += `${C.dim}${'─'.repeat(60)}${C.reset}\n`;
|
|
893
|
-
} else {
|
|
894
|
-
content += `${C.dim}○ ${label} (not found)${C.reset}\n`;
|
|
895
|
-
}
|
|
896
|
-
});
|
|
897
|
-
|
|
898
|
-
const settingsExists = fs.existsSync('.claude/settings.json');
|
|
899
|
-
content += `\n ${settingsExists ? `${C.green}✓${C.reset}` : `${C.dim}○${C.reset}`} .claude/settings.json\n`;
|
|
900
|
-
} // end verbosityMode === 'full' (key files)
|
|
901
|
-
|
|
902
|
-
// EPICS FOLDER - count only in lite mode
|
|
903
|
-
content += `\n${C.cyan}${C.bold}═══ Epic Files ═══${C.reset}\n`;
|
|
904
|
-
const epicFiles =
|
|
905
|
-
prefetched?.dirs?.epics?.filter(f => f.endsWith('.md') && f !== 'README.md') ??
|
|
906
|
-
safeLs('docs/05-epics').filter(f => f.endsWith('.md') && f !== 'README.md');
|
|
907
|
-
if (epicFiles.length > 0) {
|
|
908
|
-
if (verbosityMode === 'lite') {
|
|
909
|
-
content += `${C.dim}${epicFiles.length} epic file(s)${C.reset}\n`;
|
|
910
|
-
} else {
|
|
911
|
-
epicFiles.forEach(file => (content += ` ${C.dim}${file}${C.reset}\n`));
|
|
912
|
-
}
|
|
913
|
-
} else {
|
|
914
|
-
content += `${C.dim}No epic files${C.reset}\n`;
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
// IDEATION SUGGESTIONS (filtered to exclude implemented) - skip in lite mode
|
|
918
|
-
if (ideationIndex && verbosityMode === 'full') {
|
|
919
|
-
try {
|
|
920
|
-
const rootDir = process.cwd();
|
|
921
|
-
const indexResult = ideationIndex.loadIdeationIndex(rootDir);
|
|
922
|
-
|
|
923
|
-
if (indexResult.ok && indexResult.data) {
|
|
924
|
-
const index = indexResult.data;
|
|
925
|
-
const summary = ideationIndex.getIndexSummary(index);
|
|
926
|
-
|
|
927
|
-
// Only show if there are ideas
|
|
928
|
-
if (summary.totalIdeas > 0) {
|
|
929
|
-
content += `\n${C.cyan}${C.bold}═══ 💡 Ideation Summary ═══${C.reset}\n`;
|
|
930
|
-
|
|
931
|
-
// Show status breakdown
|
|
932
|
-
content += `${C.dim}Total ideas: ${summary.totalIdeas} | `;
|
|
933
|
-
content += `Pending: ${summary.byStatus.pending || 0} | `;
|
|
934
|
-
content += `Implemented: ${summary.byStatus.implemented || 0}${C.reset}\n`;
|
|
935
|
-
|
|
936
|
-
// Get recurring ideas that are NOT implemented
|
|
937
|
-
const recurringIdeas = ideationIndex.getRecurringIdeas(index, {
|
|
938
|
-
excludeImplemented: true,
|
|
939
|
-
});
|
|
940
|
-
|
|
941
|
-
if (recurringIdeas.length > 0) {
|
|
942
|
-
content += `\n${C.amber}🔥 Top Recurring Ideas (Not Yet Implemented)${C.reset}\n`;
|
|
943
|
-
content += `${C.dim}These ideas appeared 2+ times across ideation reports - consider prioritizing them${C.reset}\n\n`;
|
|
944
|
-
|
|
945
|
-
recurringIdeas.slice(0, 5).forEach((item, i) => {
|
|
946
|
-
const { idea, occurrenceCount } = item;
|
|
947
|
-
content += ` ${i + 1}. ${C.lavender}[${idea.id}]${C.reset} ${idea.title}\n`;
|
|
948
|
-
content += ` ${C.dim}Category: ${idea.category} | Occurrences: ${occurrenceCount}x | Status: ${idea.status}${C.reset}\n`;
|
|
949
|
-
});
|
|
950
|
-
|
|
951
|
-
if (recurringIdeas.length > 5) {
|
|
952
|
-
content += `\n ${C.dim}... and ${recurringIdeas.length - 5} more recurring ideas${C.reset}\n`;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
content += `\n${C.dim}Run /agileflow:ideate:history STATUS=recurring to see all${C.reset}\n`;
|
|
956
|
-
} else if (summary.byStatus.pending > 0) {
|
|
957
|
-
// Has pending ideas but none recurring
|
|
958
|
-
content += `\n${C.dim}No recurring ideas found. ${summary.byStatus.pending} pending ideas available.${C.reset}\n`;
|
|
959
|
-
content += `${C.dim}Run /agileflow:ideate:history STATUS=pending to see them.${C.reset}\n`;
|
|
960
|
-
} else {
|
|
961
|
-
// All ideas implemented!
|
|
962
|
-
content += `\n${C.mintGreen}✓ All ideation items have been implemented!${C.reset}\n`;
|
|
963
|
-
content += `${C.dim}Run /agileflow:ideate:new to generate fresh improvement ideas.${C.reset}\n`;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
} catch {
|
|
968
|
-
// Silently ignore ideation errors
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
// SMART RECOMMENDATIONS (Contextual Feature Router) - immediate only in lite mode
|
|
973
|
-
const smartDetectResults = options.smartDetectResults;
|
|
974
|
-
if (smartDetectResults && !smartDetectResults.disabled) {
|
|
975
|
-
const { immediate, available, auto_enabled } = smartDetectResults.recommendations;
|
|
976
|
-
const hasRecommendations =
|
|
977
|
-
immediate.length > 0 || (verbosityMode === 'full' && available.length > 0);
|
|
978
|
-
|
|
979
|
-
if (hasRecommendations) {
|
|
980
|
-
content += `\n${C.brand}${C.bold}═══ Smart Recommendations ═══${C.reset}\n`;
|
|
981
|
-
content += `${C.dim}Phase: ${smartDetectResults.lifecycle_phase} (${smartDetectResults.phase_reason})${C.reset}\n`;
|
|
982
|
-
|
|
983
|
-
if (immediate.length > 0) {
|
|
984
|
-
content += `\n${C.coral}${C.bold}Immediate:${C.reset}\n`;
|
|
985
|
-
immediate.forEach(r => {
|
|
986
|
-
content += ` ${C.coral}!${C.reset} ${C.bold}${r.feature}${C.reset}: ${r.trigger} ${C.dim}(${r.command})${C.reset}\n`;
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
// Available recommendations - full mode only
|
|
991
|
-
if (verbosityMode === 'full' && available.length > 0) {
|
|
992
|
-
content += `\n${C.skyBlue}Available:${C.reset}\n`;
|
|
993
|
-
available.slice(0, 5).forEach(r => {
|
|
994
|
-
content += ` ${C.skyBlue}>${C.reset} ${r.feature}: ${r.trigger} ${C.dim}(${r.command})${C.reset}\n`;
|
|
995
|
-
});
|
|
996
|
-
if (available.length > 5) {
|
|
997
|
-
content += ` ${C.dim}... and ${available.length - 5} more${C.reset}\n`;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
// Show auto-enabled modes
|
|
1003
|
-
const modes = auto_enabled || {};
|
|
1004
|
-
const enabledModes = Object.entries(modes)
|
|
1005
|
-
.filter(([, v]) => v)
|
|
1006
|
-
.map(([k]) => k.replace('_', ' '));
|
|
1007
|
-
if (enabledModes.length > 0) {
|
|
1008
|
-
content += `\n${C.mintGreen}Auto-enabled:${C.reset} ${enabledModes.join(', ')}\n`;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
// Feature catalog - show all major features with status (full mode only)
|
|
1012
|
-
const catalog = smartDetectResults.feature_catalog;
|
|
1013
|
-
if (catalog && catalog.length > 0 && verbosityMode === 'full') {
|
|
1014
|
-
const categoryLabels = {
|
|
1015
|
-
modes: 'Modes',
|
|
1016
|
-
collaboration: 'Collaboration',
|
|
1017
|
-
workflow: 'Workflow',
|
|
1018
|
-
analysis: 'Analysis',
|
|
1019
|
-
testing: 'Testing',
|
|
1020
|
-
automation: 'Automation',
|
|
1021
|
-
};
|
|
1022
|
-
const statusIcons = {
|
|
1023
|
-
triggered: `${C.mintGreen}*${C.reset}`,
|
|
1024
|
-
available: `${C.skyBlue}>${C.reset}`,
|
|
1025
|
-
unavailable: `${C.dim}-${C.reset}`,
|
|
1026
|
-
};
|
|
1027
|
-
|
|
1028
|
-
// Group by category, skip disabled
|
|
1029
|
-
const grouped = {};
|
|
1030
|
-
for (const entry of catalog) {
|
|
1031
|
-
if (entry.status === 'disabled') continue;
|
|
1032
|
-
if (!grouped[entry.category]) grouped[entry.category] = [];
|
|
1033
|
-
grouped[entry.category].push(entry);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
const categoryOrder = [
|
|
1037
|
-
'modes',
|
|
1038
|
-
'collaboration',
|
|
1039
|
-
'workflow',
|
|
1040
|
-
'analysis',
|
|
1041
|
-
'testing',
|
|
1042
|
-
'automation',
|
|
1043
|
-
];
|
|
1044
|
-
const hasEntries = Object.keys(grouped).length > 0;
|
|
1045
|
-
|
|
1046
|
-
if (hasEntries) {
|
|
1047
|
-
content += `\n${C.brand}${C.bold}═══ Feature Catalog ═══${C.reset}\n`;
|
|
1048
|
-
|
|
1049
|
-
for (const cat of categoryOrder) {
|
|
1050
|
-
const entries = grouped[cat];
|
|
1051
|
-
if (!entries || entries.length === 0) continue;
|
|
1052
|
-
content += `\n${C.bold}${categoryLabels[cat] || cat}:${C.reset}\n`;
|
|
1053
|
-
for (const entry of entries) {
|
|
1054
|
-
const icon = statusIcons[entry.status] || `${C.dim}?${C.reset}`;
|
|
1055
|
-
content += ` ${icon} ${C.bold}${entry.name}${C.reset} - ${entry.description} ${C.dim}(${entry.how_to_use})${C.reset}\n`;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
// FOOTER
|
|
1063
|
-
content += `\n${C.dim}─────────────────────────────────────────${C.reset}\n`;
|
|
1064
|
-
content += `${C.dim}Context gathered in single execution. Claude has full context.${C.reset}\n`;
|
|
1065
|
-
|
|
1066
|
-
return content;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
/**
|
|
1070
|
-
* Generate minimal content - compact summary only.
|
|
1071
|
-
* Used when verbosityMode is 'minimal' to save ~80% of context tokens.
|
|
1072
|
-
*
|
|
1073
|
-
* @param {Object} prefetched - Pre-fetched data from prefetchAllData()
|
|
1074
|
-
* @param {Object} options - Additional options
|
|
1075
|
-
* @returns {string} Minimal content
|
|
1076
|
-
*/
|
|
1077
|
-
function generateMinimalContent(prefetched, options = {}) {
|
|
1078
|
-
const { commandName = null } = options;
|
|
1079
|
-
let content = '';
|
|
1080
|
-
|
|
1081
|
-
// Title
|
|
1082
|
-
const title = commandName
|
|
1083
|
-
? `AgileFlow Context [${commandName}] [minimal]`
|
|
1084
|
-
: 'AgileFlow Context [minimal]';
|
|
1085
|
-
content += `${C.lavender}${C.bold}${title}${C.reset}\n`;
|
|
1086
|
-
|
|
1087
|
-
// Git (compact)
|
|
1088
|
-
const branch = prefetched?.git?.branch ?? safeExec('git branch --show-current') ?? 'unknown';
|
|
1089
|
-
const statusStr = prefetched?.git?.status ?? safeExec('git status --short') ?? '';
|
|
1090
|
-
const uncommitted = statusStr.split('\n').filter(Boolean).length;
|
|
1091
|
-
const lastCommit =
|
|
1092
|
-
prefetched?.git?.commitFull ?? safeExec('git log -1 --format="%h %s"') ?? 'no commits';
|
|
1093
|
-
content += `Git: ${C.mintGreen}${branch}${C.reset} | ${uncommitted > 0 ? `${C.peach}${uncommitted} uncommitted${C.reset}` : `${C.mintGreen}clean${C.reset}`} | ${C.dim}${lastCommit}${C.reset}\n`;
|
|
1094
|
-
|
|
1095
|
-
// Story counts
|
|
1096
|
-
const statusJson = prefetched?.json?.statusJson ?? safeReadJSON('docs/09-agents/status.json');
|
|
1097
|
-
if (statusJson?.stories) {
|
|
1098
|
-
const counts = {};
|
|
1099
|
-
Object.values(statusJson.stories).forEach(s => {
|
|
1100
|
-
const st = s.status || 'unknown';
|
|
1101
|
-
counts[st] = (counts[st] || 0) + 1;
|
|
1102
|
-
});
|
|
1103
|
-
content += `Stories: ${C.skyBlue}${counts.ready || 0} ready${C.reset}, ${C.peach}${counts['in-progress'] || 0} in-progress${C.reset}, ${C.mintGreen}${counts.done || 0} done${C.reset}`;
|
|
1104
|
-
if (counts.blocked) content += `, ${C.coral}${counts.blocked} blocked${C.reset}`;
|
|
1105
|
-
content += '\n';
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
// Active session (one-liner)
|
|
1109
|
-
const sessionState =
|
|
1110
|
-
prefetched?.json?.sessionState ?? safeReadJSON('docs/09-agents/session-state.json');
|
|
1111
|
-
if (sessionState?.current_session?.started_at) {
|
|
1112
|
-
const started = new Date(sessionState.current_session.started_at);
|
|
1113
|
-
const duration = Math.round((Date.now() - started.getTime()) / 60000);
|
|
1114
|
-
content += `Session: ${C.lightGreen}${duration} min${C.reset}`;
|
|
1115
|
-
if (sessionState.current_session.current_story) {
|
|
1116
|
-
content += ` | Working on: ${C.lightYellow}${sessionState.current_session.current_story}${C.reset}`;
|
|
1117
|
-
}
|
|
1118
|
-
content += '\n';
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
// Active commands
|
|
1122
|
-
if (Array.isArray(sessionState?.active_commands) && sessionState.active_commands.length > 0) {
|
|
1123
|
-
const cmdNames = sessionState.active_commands.map(c => c.name).join(', ');
|
|
1124
|
-
content += `Active commands: ${C.skyBlue}${cmdNames}${C.reset}\n`;
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
// Context budget warning (always show)
|
|
1128
|
-
const contextUsage = getContextPercentage();
|
|
1129
|
-
if (contextUsage && contextUsage.percent >= 50) {
|
|
1130
|
-
content += generateContextWarning(contextUsage.percent);
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
// AskUserQuestion banner (keep in minimal - it's an instruction, not data)
|
|
1134
|
-
const earlyMetadata =
|
|
1135
|
-
prefetched?.json?.metadata ?? safeReadJSON('docs/00-meta/agileflow-metadata.json');
|
|
1136
|
-
if (earlyMetadata?.features?.askUserQuestion?.enabled) {
|
|
1137
|
-
content += `\n${C.coral}${C.bold}🔔 SMART AskUserQuestion After EVERY Response${C.reset}\n`;
|
|
1138
|
-
content += `${C.mintGreen}→ ALWAYS${C.reset} call AskUserQuestion with contextual options. ${C.coral}→ NEVER${C.reset} generic.\n`;
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
content += `\n${C.dim}[minimal mode - run /agileflow:configure to change context verbosity]${C.reset}\n`;
|
|
1142
|
-
|
|
1143
|
-
return content;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
module.exports = {
|
|
1147
|
-
// String utilities
|
|
1148
|
-
pad,
|
|
1149
|
-
truncate,
|
|
1150
|
-
|
|
1151
|
-
// Warning generation
|
|
1152
|
-
generateContextWarning,
|
|
1153
|
-
|
|
1154
|
-
// Main generators
|
|
1155
|
-
generateSummary,
|
|
1156
|
-
generateFullContent,
|
|
1157
|
-
generateMinimalContent,
|
|
1158
|
-
};
|