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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified config loader for AgileFlow v4.
|
|
3
|
+
*
|
|
4
|
+
* Reads `agileflow.config.json` from a project root, validates against the
|
|
5
|
+
* JSON Schema, merges with defaults, and returns a frozen config object.
|
|
6
|
+
*
|
|
7
|
+
* Missing file → returns defaults (not an error — first-run case).
|
|
8
|
+
* Invalid JSON → throws with the file path.
|
|
9
|
+
* Schema violation → throws with a JSON Pointer to the offending field.
|
|
10
|
+
*/
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
const path = require("path");
|
|
13
|
+
const Ajv = require("ajv");
|
|
14
|
+
|
|
15
|
+
const schema = require("./schema.json");
|
|
16
|
+
const { defaultConfig } = require("./defaults.js");
|
|
17
|
+
|
|
18
|
+
const CONFIG_FILENAME = "agileflow.config.json";
|
|
19
|
+
|
|
20
|
+
const ajv = new Ajv({ allErrors: true, useDefaults: false, strict: false });
|
|
21
|
+
const validate = ajv.compile(schema);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Shallow-merge user config on top of defaults. `plugins`, `hooks`, and
|
|
25
|
+
* `personalization` sub-objects are deep-merged at one level so that
|
|
26
|
+
* partial user configs don't wipe defaults.
|
|
27
|
+
*
|
|
28
|
+
* @param {import('./defaults.js').AgileflowConfig} defaults
|
|
29
|
+
* @param {Partial<import('./defaults.js').AgileflowConfig>} user
|
|
30
|
+
* @returns {import('./defaults.js').AgileflowConfig}
|
|
31
|
+
*/
|
|
32
|
+
function mergeConfig(defaults, user) {
|
|
33
|
+
return {
|
|
34
|
+
version: user.version ?? defaults.version,
|
|
35
|
+
plugins: { ...defaults.plugins, ...(user.plugins || {}) },
|
|
36
|
+
hooks: { ...defaults.hooks, ...(user.hooks || {}) },
|
|
37
|
+
behaviors: { ...defaults.behaviors, ...(user.behaviors || {}) },
|
|
38
|
+
personalization: {
|
|
39
|
+
...defaults.personalization,
|
|
40
|
+
...(user.personalization || {}),
|
|
41
|
+
},
|
|
42
|
+
ide: { ...defaults.ide, ...(user.ide || {}) },
|
|
43
|
+
language: user.language ?? defaults.language,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Format Ajv errors as a single human-readable message with JSON Pointers.
|
|
49
|
+
* @param {import('ajv').ErrorObject[]} errors
|
|
50
|
+
* @returns {string}
|
|
51
|
+
*/
|
|
52
|
+
function formatSchemaErrors(errors) {
|
|
53
|
+
return errors
|
|
54
|
+
.map((e) => ` • ${e.instancePath || "/"} ${e.message}`)
|
|
55
|
+
.join("\n");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Load config from the given project root.
|
|
60
|
+
*
|
|
61
|
+
* @param {string} cwd - project root directory
|
|
62
|
+
* @returns {Promise<{
|
|
63
|
+
* config: import('./defaults.js').AgileflowConfig,
|
|
64
|
+
* path: string | null,
|
|
65
|
+
* source: 'file' | 'defaults'
|
|
66
|
+
* }>}
|
|
67
|
+
*/
|
|
68
|
+
async function loadConfig(cwd) {
|
|
69
|
+
const configPath = path.join(cwd, CONFIG_FILENAME);
|
|
70
|
+
|
|
71
|
+
// Read directly and treat ENOENT as "no config → use defaults". This
|
|
72
|
+
// eliminates the existsSync-then-readFileSync TOCTOU window; between
|
|
73
|
+
// the two calls another process could delete the file and the user
|
|
74
|
+
// would get a misleading "Failed to read" error instead of defaults.
|
|
75
|
+
let raw;
|
|
76
|
+
try {
|
|
77
|
+
raw = fs.readFileSync(configPath, "utf8");
|
|
78
|
+
} catch (err) {
|
|
79
|
+
if (err.code === "ENOENT") {
|
|
80
|
+
return Object.freeze({
|
|
81
|
+
config: Object.freeze(defaultConfig()),
|
|
82
|
+
path: null,
|
|
83
|
+
source: "defaults",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Failed to read ${configPath}: ${err.message}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let parsed;
|
|
90
|
+
try {
|
|
91
|
+
parsed = JSON.parse(raw);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
throw new Error(`Invalid JSON in ${configPath}: ${err.message}`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!validate(parsed)) {
|
|
97
|
+
const details = formatSchemaErrors(validate.errors || []);
|
|
98
|
+
throw new Error(`Config validation failed for ${configPath}:\n${details}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const merged = mergeConfig(defaultConfig(), parsed);
|
|
102
|
+
// Core plugin cannot be disabled — enforce at load time.
|
|
103
|
+
merged.plugins.core = { ...merged.plugins.core, enabled: true };
|
|
104
|
+
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
config: Object.freeze(merged),
|
|
107
|
+
path: configPath,
|
|
108
|
+
source: "file",
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = {
|
|
113
|
+
CONFIG_FILENAME,
|
|
114
|
+
loadConfig,
|
|
115
|
+
mergeConfig,
|
|
116
|
+
formatSchemaErrors,
|
|
117
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://github.com/projectquestorg/AgileFlow/apps/cli/config.schema.json",
|
|
4
|
+
"title": "AgileFlow v4 user config",
|
|
5
|
+
"description": "User-facing configuration for AgileFlow v4. Lives at agileflow.config.json in project root.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["version"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"$schema": { "type": "string" },
|
|
11
|
+
"version": {
|
|
12
|
+
"type": "integer",
|
|
13
|
+
"const": 1,
|
|
14
|
+
"description": "Config schema version. Bumped on breaking changes."
|
|
15
|
+
},
|
|
16
|
+
"plugins": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"description": "Map of plugin-id -> { enabled: bool, settings?: object }. core is always enabled.",
|
|
19
|
+
"additionalProperties": {
|
|
20
|
+
"type": "object",
|
|
21
|
+
"additionalProperties": false,
|
|
22
|
+
"properties": {
|
|
23
|
+
"enabled": { "type": "boolean" },
|
|
24
|
+
"settings": { "type": "object", "additionalProperties": true }
|
|
25
|
+
},
|
|
26
|
+
"required": ["enabled"]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"hooks": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"description": "Per-hook-id user overrides applied on top of plugin-supplied defaults.",
|
|
32
|
+
"additionalProperties": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"additionalProperties": false,
|
|
35
|
+
"properties": {
|
|
36
|
+
"enabled": { "type": "boolean" },
|
|
37
|
+
"timeout": { "type": "integer", "minimum": 0, "maximum": 60000 },
|
|
38
|
+
"skipOnError": { "type": "boolean" }
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"behaviors": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"description": "Curated behavior presets. Each maps to one or more hooks the installer wires up. Disabling a behavior excludes its hooks from the generated hook-manifest.yaml.",
|
|
45
|
+
"additionalProperties": false,
|
|
46
|
+
"properties": {
|
|
47
|
+
"loadContext": {
|
|
48
|
+
"type": "boolean",
|
|
49
|
+
"description": "SessionStart: print project context (stories, dirty files, recent commits) for Claude to consume."
|
|
50
|
+
},
|
|
51
|
+
"babysitDefault": {
|
|
52
|
+
"type": "boolean",
|
|
53
|
+
"description": "SessionStart: inject the babysit-mentor pattern so Claude defaults to mentor mode without explicit invocation."
|
|
54
|
+
},
|
|
55
|
+
"damageControl": {
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
"description": "PreToolUse: block dangerous Bash commands and risky Edit/Write paths via the patterns library."
|
|
58
|
+
},
|
|
59
|
+
"preCompactState": {
|
|
60
|
+
"type": "boolean",
|
|
61
|
+
"description": "PreCompact: capture story IDs, active command, and dirty git state so they survive Claude's compaction summary."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"personalization": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"additionalProperties": false,
|
|
68
|
+
"properties": {
|
|
69
|
+
"tone": {
|
|
70
|
+
"type": "string",
|
|
71
|
+
"enum": ["concise", "detailed", "teaching"]
|
|
72
|
+
},
|
|
73
|
+
"ask_level": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": ["none", "decision_points", "always"]
|
|
76
|
+
},
|
|
77
|
+
"verbosity": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"enum": ["low", "medium", "high"]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"ide": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"properties": {
|
|
87
|
+
"primary": {
|
|
88
|
+
"type": "string",
|
|
89
|
+
"enum": ["claude-code", "cursor", "windsurf", "codex"]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"language": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "IETF BCP 47 language tag (e.g. 'en', 'es', 'pt-BR').",
|
|
96
|
+
"pattern": "^[a-z]{2}(-[A-Z][a-zA-Z0-9]+)?$"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config writer — writes `agileflow.config.json` to a project root atomically.
|
|
3
|
+
*
|
|
4
|
+
* Write strategy: render to a temp file (`.agileflow.config.json.tmp-<pid>`)
|
|
5
|
+
* in the same directory, then `fs.rename()` into place. Same-directory
|
|
6
|
+
* rename is atomic on POSIX and on Windows for files on the same volume,
|
|
7
|
+
* so readers always see either the old content or the new content — never
|
|
8
|
+
* a truncated half-write.
|
|
9
|
+
*
|
|
10
|
+
* Serializes only the user-facing fields (drops internal loader metadata
|
|
11
|
+
* like `source`/`path`). Adds `$schema` pointer for editor validation.
|
|
12
|
+
*/
|
|
13
|
+
const fs = require("fs");
|
|
14
|
+
const path = require("path");
|
|
15
|
+
|
|
16
|
+
const { CONFIG_FILENAME } = require("./loader.js");
|
|
17
|
+
|
|
18
|
+
const SCHEMA_REF = "./node_modules/agileflow/src/runtime/config/schema.json";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {string} cwd - project root
|
|
22
|
+
* @param {import('./defaults.js').AgileflowConfig} config
|
|
23
|
+
* @returns {Promise<string>} absolute path of the written config file
|
|
24
|
+
*/
|
|
25
|
+
async function writeConfig(cwd, config) {
|
|
26
|
+
const file = path.join(cwd, CONFIG_FILENAME);
|
|
27
|
+
const tmp = path.join(cwd, `.${CONFIG_FILENAME}.tmp-${process.pid}`);
|
|
28
|
+
const payload = {
|
|
29
|
+
$schema: SCHEMA_REF,
|
|
30
|
+
version: 1,
|
|
31
|
+
plugins: config.plugins,
|
|
32
|
+
hooks: config.hooks,
|
|
33
|
+
behaviors: config.behaviors,
|
|
34
|
+
personalization: config.personalization,
|
|
35
|
+
ide: config.ide,
|
|
36
|
+
language: config.language,
|
|
37
|
+
};
|
|
38
|
+
const content = JSON.stringify(payload, null, 2) + "\n";
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
await fs.promises.writeFile(tmp, content, "utf8");
|
|
42
|
+
await fs.promises.rename(tmp, file);
|
|
43
|
+
} catch (err) {
|
|
44
|
+
// Best-effort cleanup of the temp file on failure. Ignore cleanup errors.
|
|
45
|
+
try {
|
|
46
|
+
await fs.promises.unlink(tmp);
|
|
47
|
+
} catch {
|
|
48
|
+
/* swallow */
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
return file;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = { writeConfig, SCHEMA_REF };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook manifest aggregator.
|
|
3
|
+
*
|
|
4
|
+
* At install time, walks every enabled plugin's `provides.hooks` array
|
|
5
|
+
* and produces a single `.agileflow/hook-manifest.yaml` that the
|
|
6
|
+
* orchestrator (and the 6 dispatchers) read at runtime.
|
|
7
|
+
*
|
|
8
|
+
* Plugin manifests declare hooks with paths relative to the plugin's
|
|
9
|
+
* source directory:
|
|
10
|
+
*
|
|
11
|
+
* provides:
|
|
12
|
+
* hooks:
|
|
13
|
+
* - id: babysit-clear-restore
|
|
14
|
+
* event: SessionStart
|
|
15
|
+
* script: hooks/babysit-clear-restore.js
|
|
16
|
+
* timeout: 5000
|
|
17
|
+
* skipOnError: true
|
|
18
|
+
*
|
|
19
|
+
* The aggregator rewrites the script path to be relative to the
|
|
20
|
+
* project root (so the orchestrator can find it after install):
|
|
21
|
+
*
|
|
22
|
+
* - script: .agileflow/plugins/core/hooks/babysit-clear-restore.js
|
|
23
|
+
*
|
|
24
|
+
* Aggregation is content-only — the loader's strict validator runs
|
|
25
|
+
* afterwards when the orchestrator reads the file, so any malformed
|
|
26
|
+
* plugin contribution surfaces with a clear error rather than silently
|
|
27
|
+
* misbehaving.
|
|
28
|
+
*/
|
|
29
|
+
const fs = require("fs");
|
|
30
|
+
const path = require("path");
|
|
31
|
+
const yaml = require("js-yaml");
|
|
32
|
+
|
|
33
|
+
const HEADER_COMMENT =
|
|
34
|
+
"# Auto-generated by `agileflow setup` / `agileflow update`.\n" +
|
|
35
|
+
"# Do not edit by hand — your changes will be overwritten on the next install.\n" +
|
|
36
|
+
"# To override per-hook settings (timeout, skipOnError, enabled),\n" +
|
|
37
|
+
"# use the `hooks:` map in agileflow.config.json instead.\n" +
|
|
38
|
+
"#\n";
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @typedef {import('../plugins/registry.js').PluginManifest} PluginManifest
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build a single normalized hook-manifest object from the ordered set
|
|
46
|
+
* of enabled plugins. Pure: no I/O.
|
|
47
|
+
*
|
|
48
|
+
* Behavior gating: a plugin hook entry may declare `behavior: <key>`
|
|
49
|
+
* (e.g. `behavior: damageControl`). When `behaviors` is supplied and
|
|
50
|
+
* the corresponding key is `false`, the hook is excluded from the
|
|
51
|
+
* generated manifest — its script never runs at runtime. Hooks
|
|
52
|
+
* without a `behavior` field are always included (they're not part
|
|
53
|
+
* of the curated preset surface).
|
|
54
|
+
*
|
|
55
|
+
* @param {PluginManifest[]} orderedPlugins
|
|
56
|
+
* @param {Record<string, boolean>} [behaviors] - user's behavior toggles
|
|
57
|
+
* @returns {{ version: 1, hooks: Array<object> }}
|
|
58
|
+
*/
|
|
59
|
+
function buildHookManifest(orderedPlugins, behaviors) {
|
|
60
|
+
/** @type {Array<object>} */
|
|
61
|
+
const hooks = [];
|
|
62
|
+
for (const plugin of orderedPlugins) {
|
|
63
|
+
const provided =
|
|
64
|
+
plugin.provides && Array.isArray(plugin.provides.hooks)
|
|
65
|
+
? plugin.provides.hooks
|
|
66
|
+
: [];
|
|
67
|
+
for (const entry of provided) {
|
|
68
|
+
if (!entry || typeof entry !== "object") continue;
|
|
69
|
+
if (typeof entry.id !== "string" || typeof entry.script !== "string")
|
|
70
|
+
continue;
|
|
71
|
+
// Behavior-gated hooks are skipped when the user disabled the
|
|
72
|
+
// preset. A missing `behavior` field means "always include".
|
|
73
|
+
if (
|
|
74
|
+
typeof entry.behavior === "string" &&
|
|
75
|
+
behaviors &&
|
|
76
|
+
behaviors[entry.behavior] === false
|
|
77
|
+
) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const out = {
|
|
81
|
+
id: entry.id,
|
|
82
|
+
event: entry.event,
|
|
83
|
+
script: `.agileflow/plugins/${plugin.id}/${entry.script}`,
|
|
84
|
+
};
|
|
85
|
+
if (entry.matcher != null) out.matcher = entry.matcher;
|
|
86
|
+
if (Array.isArray(entry.runAfter)) out.runAfter = entry.runAfter;
|
|
87
|
+
if (typeof entry.timeout === "number") out.timeout = entry.timeout;
|
|
88
|
+
if (typeof entry.skipOnError === "boolean")
|
|
89
|
+
out.skipOnError = entry.skipOnError;
|
|
90
|
+
if (typeof entry.enabled === "boolean") out.enabled = entry.enabled;
|
|
91
|
+
hooks.push(out);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { version: 1, hooks };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Aggregate + atomically write the hook manifest to disk. Call only
|
|
99
|
+
* when the target IDE supports hooks (i.e. claude-code today).
|
|
100
|
+
*
|
|
101
|
+
* @param {PluginManifest[]} orderedPlugins
|
|
102
|
+
* @param {string} agileflowDir - absolute path to .agileflow/
|
|
103
|
+
* @param {Record<string, boolean>} [behaviors] - user's behavior toggles
|
|
104
|
+
* @returns {Promise<string>} absolute path of the written manifest
|
|
105
|
+
*/
|
|
106
|
+
async function writeAggregatedManifest(
|
|
107
|
+
orderedPlugins,
|
|
108
|
+
agileflowDir,
|
|
109
|
+
behaviors,
|
|
110
|
+
) {
|
|
111
|
+
const manifest = buildHookManifest(orderedPlugins, behaviors);
|
|
112
|
+
const dest = path.join(agileflowDir, "hook-manifest.yaml");
|
|
113
|
+
const yamlText = HEADER_COMMENT + yaml.dump(manifest, { noRefs: true });
|
|
114
|
+
|
|
115
|
+
await fs.promises.mkdir(agileflowDir, { recursive: true });
|
|
116
|
+
const tmp = path.join(
|
|
117
|
+
agileflowDir,
|
|
118
|
+
`.hook-manifest.yaml.tmp-${process.pid}-${Math.random().toString(36).slice(2, 10)}`,
|
|
119
|
+
);
|
|
120
|
+
try {
|
|
121
|
+
await fs.promises.writeFile(tmp, yamlText, "utf8");
|
|
122
|
+
await fs.promises.rename(tmp, dest);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
try {
|
|
125
|
+
await fs.promises.unlink(tmp);
|
|
126
|
+
} catch {
|
|
127
|
+
/* swallow */
|
|
128
|
+
}
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
return dest;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Remove the hook manifest if it exists. Used when switching to a
|
|
136
|
+
* non-claude-code IDE so a stale claude-code manifest doesn't linger.
|
|
137
|
+
*
|
|
138
|
+
* @param {string} agileflowDir
|
|
139
|
+
* @returns {Promise<boolean>} true if a file was removed
|
|
140
|
+
*/
|
|
141
|
+
async function removeAggregatedManifest(agileflowDir) {
|
|
142
|
+
const dest = path.join(agileflowDir, "hook-manifest.yaml");
|
|
143
|
+
try {
|
|
144
|
+
await fs.promises.unlink(dest);
|
|
145
|
+
return true;
|
|
146
|
+
} catch (err) {
|
|
147
|
+
if (err.code === "ENOENT") return false;
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
module.exports = {
|
|
153
|
+
buildHookManifest,
|
|
154
|
+
writeAggregatedManifest,
|
|
155
|
+
removeAggregatedManifest,
|
|
156
|
+
HEADER_COMMENT,
|
|
157
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook chain ordering.
|
|
3
|
+
*
|
|
4
|
+
* Given a list of `HookEntry` for a single event, returns the topological
|
|
5
|
+
* order in which they must be executed (dependencies before dependents)
|
|
6
|
+
* and detects cycles with a clear error message that names the cycle path.
|
|
7
|
+
*
|
|
8
|
+
* Filtering by event happens upstream — `orderChain` accepts whatever
|
|
9
|
+
* the caller gives it.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const COLOR_WHITE = 0;
|
|
13
|
+
const COLOR_GRAY = 1;
|
|
14
|
+
const COLOR_BLACK = 2;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {import('./manifest-loader.js').HookEntry} HookEntry
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Validate that every `runAfter` entry resolves to a hook id in this set.
|
|
22
|
+
* @param {HookEntry[]} hooks
|
|
23
|
+
* @param {Map<string, HookEntry>} byId
|
|
24
|
+
*/
|
|
25
|
+
function assertRunAfterExists(hooks, byId) {
|
|
26
|
+
for (const h of hooks) {
|
|
27
|
+
for (const dep of h.runAfter) {
|
|
28
|
+
if (!byId.has(dep)) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Hook "${h.id}" runAfter references unknown hook "${dep}" (in same event chain)`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Topologically sort the chain. Hooks with `runAfter: [a, b]` come AFTER
|
|
39
|
+
* a and b. Within a layer, ordering is stable on the original input order
|
|
40
|
+
* so two ready-to-run hooks keep their declaration order.
|
|
41
|
+
*
|
|
42
|
+
* @param {HookEntry[]} hooks
|
|
43
|
+
* @returns {HookEntry[]}
|
|
44
|
+
* @throws {Error} on cycles or unresolved runAfter targets
|
|
45
|
+
*/
|
|
46
|
+
function orderChain(hooks) {
|
|
47
|
+
const byId = new Map(hooks.map((h) => [h.id, h]));
|
|
48
|
+
if (byId.size !== hooks.length) {
|
|
49
|
+
// Caller should have rejected duplicates upstream; defensive check.
|
|
50
|
+
const seen = new Set();
|
|
51
|
+
for (const h of hooks) {
|
|
52
|
+
if (seen.has(h.id)) throw new Error(`duplicate hook id in chain: ${h.id}`);
|
|
53
|
+
seen.add(h.id);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
assertRunAfterExists(hooks, byId);
|
|
57
|
+
|
|
58
|
+
/** @type {Map<string, number>} */
|
|
59
|
+
const color = new Map();
|
|
60
|
+
/** @type {HookEntry[]} */
|
|
61
|
+
const order = [];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {string} id
|
|
65
|
+
* @param {string[]} stack
|
|
66
|
+
*/
|
|
67
|
+
function visit(id, stack) {
|
|
68
|
+
const c = color.get(id) ?? COLOR_WHITE;
|
|
69
|
+
if (c === COLOR_BLACK) return;
|
|
70
|
+
if (c === COLOR_GRAY) {
|
|
71
|
+
const start = stack.indexOf(id);
|
|
72
|
+
const cycle = [...stack.slice(start), id].join(' -> ');
|
|
73
|
+
throw new Error(`Hook chain cycle detected: ${cycle}`);
|
|
74
|
+
}
|
|
75
|
+
color.set(id, COLOR_GRAY);
|
|
76
|
+
const h = byId.get(id);
|
|
77
|
+
const next = [...stack, id];
|
|
78
|
+
for (const dep of h.runAfter) {
|
|
79
|
+
visit(dep, next);
|
|
80
|
+
}
|
|
81
|
+
color.set(id, COLOR_BLACK);
|
|
82
|
+
order.push(h);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Visit in declaration order so within a topological "layer" the
|
|
86
|
+
// original order is preserved.
|
|
87
|
+
for (const h of hooks) {
|
|
88
|
+
visit(h.id, []);
|
|
89
|
+
}
|
|
90
|
+
return order;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { orderChain };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook execution logger.
|
|
3
|
+
*
|
|
4
|
+
* Appends one JSON object per line to `.agileflow/logs/hook-execution.jsonl`.
|
|
5
|
+
* The orchestrator writes one entry per hook invocation, capturing
|
|
6
|
+
* timing, exit code, and truncated stdout/stderr.
|
|
7
|
+
*
|
|
8
|
+
* Log file is created on first write; missing parent directories are
|
|
9
|
+
* created automatically. Append-only — log rotation is a future concern.
|
|
10
|
+
*/
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const MAX_OUTPUT_BYTES = 4 * 1024; // 4 KB cap per stream
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} HookLogEntry
|
|
18
|
+
* @property {string} timestamp - ISO 8601
|
|
19
|
+
* @property {string} event
|
|
20
|
+
* @property {string} hookId
|
|
21
|
+
* @property {'ok'|'error'|'timeout'|'skipped'} status
|
|
22
|
+
* @property {number|null} exitCode
|
|
23
|
+
* @property {number} durationMs
|
|
24
|
+
* @property {string} [stdout]
|
|
25
|
+
* @property {string} [stderr]
|
|
26
|
+
* @property {boolean} [skippedByOnError] - true when status='error' was tolerated due to skipOnError
|
|
27
|
+
* @property {string} [reason] - free-form note (e.g. why skipped)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Truncate a string buffer to `MAX_OUTPUT_BYTES` to keep the log line
|
|
32
|
+
* bounded. Cuts on byte length, not code units, so trailing multi-byte
|
|
33
|
+
* sequences are stripped cleanly.
|
|
34
|
+
* @param {string|Buffer|undefined} value
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
function truncate(value) {
|
|
38
|
+
if (value == null || value === '') return '';
|
|
39
|
+
const buf = Buffer.isBuffer(value) ? value : Buffer.from(String(value), 'utf8');
|
|
40
|
+
if (buf.length <= MAX_OUTPUT_BYTES) return buf.toString('utf8');
|
|
41
|
+
return buf.subarray(0, MAX_OUTPUT_BYTES).toString('utf8') + '\n…[truncated]';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Append one entry to the JSONL log.
|
|
46
|
+
*
|
|
47
|
+
* Throws on filesystem failures so the orchestrator can surface them in
|
|
48
|
+
* structured exit codes — but in practice the orchestrator wraps this
|
|
49
|
+
* in a try/catch and never fails because of a logging error.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} logPath - absolute path to hook-execution.jsonl
|
|
52
|
+
* @param {HookLogEntry} entry
|
|
53
|
+
*/
|
|
54
|
+
async function appendHookLog(logPath, entry) {
|
|
55
|
+
await fs.promises.mkdir(path.dirname(logPath), { recursive: true });
|
|
56
|
+
const normalized = {
|
|
57
|
+
...entry,
|
|
58
|
+
stdout: entry.stdout == null ? undefined : truncate(entry.stdout),
|
|
59
|
+
stderr: entry.stderr == null ? undefined : truncate(entry.stderr),
|
|
60
|
+
};
|
|
61
|
+
// Drop undefined keys so the JSONL line is compact.
|
|
62
|
+
for (const k of Object.keys(normalized)) {
|
|
63
|
+
if (normalized[k] === undefined) delete normalized[k];
|
|
64
|
+
}
|
|
65
|
+
await fs.promises.appendFile(logPath, JSON.stringify(normalized) + '\n', 'utf8');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { appendHookLog, truncate, MAX_OUTPUT_BYTES };
|