specweave 0.24.11 → 0.26.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/CLAUDE.md +742 -26
- package/bin/specweave.js +14 -0
- package/dist/plugins/specweave-github/lib/CodeValidator.js +2 -2
- package/dist/plugins/specweave-github/lib/CodeValidator.js.map +1 -1
- package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.js +1 -1
- package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +28 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +64 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-issue-updater.js +1 -1
- package/dist/plugins/specweave-github/lib/github-issue-updater.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-increment-changes.js +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-increment-changes.js.map +1 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +7 -6
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js +1 -1
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js.map +1 -1
- package/dist/src/adapters/adapter-base.js +1 -1
- package/dist/src/adapters/adapter-base.js.map +1 -1
- package/dist/src/adapters/adapter-loader.js +1 -1
- package/dist/src/adapters/adapter-loader.js.map +1 -1
- package/dist/src/adapters/agents-md-generator.js +1 -1
- package/dist/src/adapters/agents-md-generator.js.map +1 -1
- package/dist/src/adapters/claude/adapter.js +1 -1
- package/dist/src/adapters/claude/adapter.js.map +1 -1
- package/dist/src/adapters/claude-md-generator.js +1 -1
- package/dist/src/adapters/claude-md-generator.js.map +1 -1
- package/dist/src/adapters/codex/adapter.js +1 -1
- package/dist/src/adapters/codex/adapter.js.map +1 -1
- package/dist/src/adapters/cursor/adapter.js +1 -1
- package/dist/src/adapters/cursor/adapter.js.map +1 -1
- package/dist/src/adapters/doc-generator.js +1 -1
- package/dist/src/adapters/doc-generator.js.map +1 -1
- package/dist/src/adapters/gemini/adapter.js +1 -1
- package/dist/src/adapters/gemini/adapter.js.map +1 -1
- package/dist/src/adapters/generic/adapter.js +1 -1
- package/dist/src/adapters/generic/adapter.js.map +1 -1
- package/dist/src/cli/commands/cicd-monitor.js +1 -1
- package/dist/src/cli/commands/cicd-monitor.js.map +1 -1
- package/dist/src/cli/commands/delete-feature.d.ts +14 -0
- package/dist/src/cli/commands/delete-feature.d.ts.map +1 -0
- package/dist/src/cli/commands/delete-feature.js +87 -0
- package/dist/src/cli/commands/delete-feature.js.map +1 -0
- package/dist/src/cli/commands/detect-specs.js +1 -1
- package/dist/src/cli/commands/detect-specs.js.map +1 -1
- package/dist/src/cli/commands/import-external.js +1 -1
- package/dist/src/cli/commands/import-external.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +45 -47
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/install.js +1 -1
- package/dist/src/cli/commands/install.js.map +1 -1
- package/dist/src/cli/commands/list.js +1 -1
- package/dist/src/cli/commands/list.js.map +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.js +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
- package/dist/src/cli/commands/migrate-to-profiles.js +1 -1
- package/dist/src/cli/commands/migrate-to-profiles.js.map +1 -1
- package/dist/src/cli/commands/plan/agent-invoker.js +1 -1
- package/dist/src/cli/commands/repair-status-desync.js +1 -1
- package/dist/src/cli/commands/repair-status-desync.js.map +1 -1
- package/dist/src/cli/commands/revert-wip-limit.js +1 -1
- package/dist/src/cli/commands/revert-wip-limit.js.map +1 -1
- package/dist/src/cli/commands/sync-specs.js +1 -1
- package/dist/src/cli/commands/sync-specs.js.map +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js +1 -1
- package/dist/src/cli/helpers/init/initial-increment-generator.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +15 -36
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +12 -31
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.d.ts +6 -1
- package/dist/src/cli/helpers/issue-tracker/types.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/types.js.map +1 -1
- package/dist/src/config/import-config.js +1 -1
- package/dist/src/config/import-config.js.map +1 -1
- package/dist/src/config/types.d.ts +203 -1208
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/ac-test-validator-cli.js +1 -1
- package/dist/src/core/ac-test-validator-cli.js.map +1 -1
- package/dist/src/core/ac-test-validator.js +1 -1
- package/dist/src/core/ac-test-validator.js.map +1 -1
- package/dist/src/core/brownfield/analyzer.js +1 -1
- package/dist/src/core/brownfield/analyzer.js.map +1 -1
- package/dist/src/core/brownfield/importer.js +1 -1
- package/dist/src/core/brownfield/importer.js.map +1 -1
- package/dist/src/core/cicd/config-loader.js +1 -1
- package/dist/src/core/cicd/config-loader.js.map +1 -1
- package/dist/src/core/cicd/notifier.js +1 -1
- package/dist/src/core/cicd/notifier.js.map +1 -1
- package/dist/src/core/cicd/parent-repo-validator.js +1 -1
- package/dist/src/core/cicd/parent-repo-validator.js.map +1 -1
- package/dist/src/core/cicd/state-manager.js +1 -1
- package/dist/src/core/cicd/state-manager.js.map +1 -1
- package/dist/src/core/config/types.d.ts +46 -12
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js +0 -5
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/config-manager.js +1 -1
- package/dist/src/core/config-manager.js.map +1 -1
- package/dist/src/core/cost-tracker.js +1 -1
- package/dist/src/core/cost-tracker.js.map +1 -1
- package/dist/src/core/deduplication/command-deduplicator.js +1 -1
- package/dist/src/core/deduplication/command-deduplicator.js.map +1 -1
- package/dist/src/core/feature-deleter/audit-logger.d.ts +30 -0
- package/dist/src/core/feature-deleter/audit-logger.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/audit-logger.js +77 -0
- package/dist/src/core/feature-deleter/audit-logger.js.map +1 -0
- package/dist/src/core/feature-deleter/confirmation-manager.d.ts +39 -0
- package/dist/src/core/feature-deleter/confirmation-manager.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/confirmation-manager.js +89 -0
- package/dist/src/core/feature-deleter/confirmation-manager.js.map +1 -0
- package/dist/src/core/feature-deleter/deletion-transaction.d.ts +51 -0
- package/dist/src/core/feature-deleter/deletion-transaction.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/deletion-transaction.js +185 -0
- package/dist/src/core/feature-deleter/deletion-transaction.js.map +1 -0
- package/dist/src/core/feature-deleter/git-service.d.ts +43 -0
- package/dist/src/core/feature-deleter/git-service.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/git-service.js +127 -0
- package/dist/src/core/feature-deleter/git-service.js.map +1 -0
- package/dist/src/core/feature-deleter/github-service.d.ts +36 -0
- package/dist/src/core/feature-deleter/github-service.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/github-service.js +102 -0
- package/dist/src/core/feature-deleter/github-service.js.map +1 -0
- package/dist/src/core/feature-deleter/index.d.ts +35 -0
- package/dist/src/core/feature-deleter/index.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/index.js +199 -0
- package/dist/src/core/feature-deleter/index.js.map +1 -0
- package/dist/src/core/feature-deleter/types.d.ts +179 -0
- package/dist/src/core/feature-deleter/types.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/types.js +7 -0
- package/dist/src/core/feature-deleter/types.js.map +1 -0
- package/dist/src/core/feature-deleter/validator.d.ts +46 -0
- package/dist/src/core/feature-deleter/validator.d.ts.map +1 -0
- package/dist/src/core/feature-deleter/validator.js +231 -0
- package/dist/src/core/feature-deleter/validator.js.map +1 -0
- package/dist/src/core/hooks/HealthReporter.js +1 -1
- package/dist/src/core/hooks/HealthReporter.js.map +1 -1
- package/dist/src/core/hooks/HookAutoFixer.js +1 -1
- package/dist/src/core/hooks/HookAutoFixer.js.map +1 -1
- package/dist/src/core/hooks/HookScanner.js +1 -1
- package/dist/src/core/hooks/HookScanner.js.map +1 -1
- package/dist/src/core/i18n/language-manager.js +1 -1
- package/dist/src/core/i18n/language-manager.js.map +1 -1
- package/dist/src/core/i18n/locale-manager.js +1 -1
- package/dist/src/core/i18n/locale-manager.js.map +1 -1
- package/dist/src/core/i18n/system-prompt-injector.js +1 -1
- package/dist/src/core/i18n/system-prompt-injector.js.map +1 -1
- package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
- package/dist/src/core/increment/ac-status-manager.js +18 -4
- package/dist/src/core/increment/ac-status-manager.js.map +1 -1
- package/dist/src/core/increment/active-increment-manager.js +1 -1
- package/dist/src/core/increment/active-increment-manager.js.map +1 -1
- package/dist/src/core/increment/completion-validator.js +1 -1
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/core/increment/conflict-resolver.js +1 -1
- package/dist/src/core/increment/conflict-resolver.js.map +1 -1
- package/dist/src/core/increment/desync-detector.js +1 -1
- package/dist/src/core/increment/desync-detector.js.map +1 -1
- package/dist/src/core/increment/discipline-checker.js +1 -1
- package/dist/src/core/increment/discipline-checker.js.map +1 -1
- package/dist/src/core/increment/duplicate-detector.js +1 -1
- package/dist/src/core/increment/duplicate-detector.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +1 -1
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/increment-reopener.js +1 -1
- package/dist/src/core/increment/increment-reopener.js.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +1 -1
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/metadata-validator.js +1 -1
- package/dist/src/core/increment/metadata-validator.js.map +1 -1
- package/dist/src/core/increment/recent-work-scanner.js +1 -1
- package/dist/src/core/increment/recent-work-scanner.js.map +1 -1
- package/dist/src/core/increment/spec-frontmatter-updater.js +1 -1
- package/dist/src/core/increment/spec-frontmatter-updater.js.map +1 -1
- package/dist/src/core/increment/status-auto-transition.js +1 -1
- package/dist/src/core/increment/status-auto-transition.js.map +1 -1
- package/dist/src/core/increment-status.js +1 -1
- package/dist/src/core/increment-status.js.map +1 -1
- package/dist/src/core/living-docs/content-distributor.js +1 -1
- package/dist/src/core/living-docs/content-distributor.js.map +1 -1
- package/dist/src/core/living-docs/cross-linker.js +1 -1
- package/dist/src/core/living-docs/cross-linker.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +1 -1
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +72 -13
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/living-docs/project-detector.js +1 -1
- package/dist/src/core/living-docs/project-detector.js.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.js +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -1
- package/dist/src/core/logging/prompt-logger.js +1 -1
- package/dist/src/core/logging/prompt-logger.js.map +1 -1
- package/dist/src/core/plugin-loader.js +1 -1
- package/dist/src/core/plugin-loader.js.map +1 -1
- package/dist/src/core/project-manager.js +1 -1
- package/dist/src/core/project-manager.js.map +1 -1
- package/dist/src/core/qa/qa-runner.js +1 -1
- package/dist/src/core/qa/qa-runner.js.map +1 -1
- package/dist/src/core/repo-structure/folder-detector.js +1 -1
- package/dist/src/core/repo-structure/folder-detector.js.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-bulk-discovery.js +20 -5
- package/dist/src/core/repo-structure/repo-bulk-discovery.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +29 -14
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/repo-structure/setup-state-manager.js +1 -1
- package/dist/src/core/repo-structure/setup-state-manager.js.map +1 -1
- package/dist/src/core/spec-detector.js +1 -1
- package/dist/src/core/spec-detector.js.map +1 -1
- package/dist/src/core/specs/spec-metadata-manager.js +1 -1
- package/dist/src/core/specs/spec-metadata-manager.js.map +1 -1
- package/dist/src/core/status-line/status-line-updater.js +1 -1
- package/dist/src/core/status-line/status-line-updater.js.map +1 -1
- package/dist/src/core/status-line-validator.js +1 -1
- package/dist/src/core/status-line-validator.js.map +1 -1
- package/dist/src/core/sync/bidirectional-engine.js +1 -1
- package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
- package/dist/src/core/sync/profile-manager.js +1 -1
- package/dist/src/core/sync/profile-manager.js.map +1 -1
- package/dist/src/core/sync/project-context.js +1 -1
- package/dist/src/core/sync/project-context.js.map +1 -1
- package/dist/src/core/sync/sync-event-logger.js +1 -1
- package/dist/src/core/sync/sync-event-logger.js.map +1 -1
- package/dist/src/core/types/config.js +1 -1
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/core/us-completion-detector.d.ts +124 -0
- package/dist/src/core/us-completion-detector.d.ts.map +1 -0
- package/dist/src/core/us-completion-detector.js +270 -0
- package/dist/src/core/us-completion-detector.js.map +1 -0
- package/dist/src/core/utils/permission-checker.js +1 -1
- package/dist/src/core/utils/permission-checker.js.map +1 -1
- package/dist/src/core/workflow/autonomous-executor.js +1 -1
- package/dist/src/core/workflow/autonomous-executor.js.map +1 -1
- package/dist/src/core/workflow/backlog-scanner.js +1 -1
- package/dist/src/core/workflow/backlog-scanner.js.map +1 -1
- package/dist/src/core/workflow/cost-estimator.js +1 -1
- package/dist/src/core/workflow/cost-estimator.js.map +1 -1
- package/dist/src/core/workflow/state-manager.js +1 -1
- package/dist/src/core/workflow/state-manager.js.map +1 -1
- package/dist/src/importers/duplicate-detector.js +1 -1
- package/dist/src/importers/duplicate-detector.js.map +1 -1
- package/dist/src/importers/item-converter.js +1 -1
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +33 -140
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +30 -27
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +11 -34
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +15 -82
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +38 -93
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +4 -42
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.d.ts +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.js +3 -3
- package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +1 -1
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/living-docs/id-registry.js +1 -1
- package/dist/src/living-docs/id-registry.js.map +1 -1
- package/dist/src/sync/external-item-sync-service.js +1 -1
- package/dist/src/sync/external-item-sync-service.js.map +1 -1
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -1
- package/dist/src/sync/format-preservation-sync.js +23 -5
- package/dist/src/sync/format-preservation-sync.js.map +1 -1
- package/dist/src/sync/frontmatter-updater.d.ts +57 -0
- package/dist/src/sync/frontmatter-updater.d.ts.map +1 -0
- package/dist/src/sync/frontmatter-updater.js +147 -0
- package/dist/src/sync/frontmatter-updater.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +22 -1
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
- package/dist/src/sync/sync-coordinator.js +268 -21
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/sync/sync-metadata.js +1 -1
- package/dist/src/sync/sync-metadata.js.map +1 -1
- package/dist/src/types/living-docs-us-file.d.ts +18 -0
- package/dist/src/types/living-docs-us-file.d.ts.map +1 -1
- package/dist/src/types/living-docs-us-file.js.map +1 -1
- package/dist/src/utils/agents-md-compiler.js +1 -1
- package/dist/src/utils/agents-md-compiler.js.map +1 -1
- package/dist/src/utils/auto-install.js +1 -1
- package/dist/src/utils/auto-install.js.map +1 -1
- package/dist/src/utils/cost-reporter.js +1 -1
- package/dist/src/utils/cost-reporter.js.map +1 -1
- package/dist/src/utils/docs-preview/config-generator.js +1 -1
- package/dist/src/utils/docs-preview/config-generator.js.map +1 -1
- package/dist/src/utils/docs-preview/docusaurus-setup.js +1 -1
- package/dist/src/utils/docs-preview/docusaurus-setup.js.map +1 -1
- package/dist/src/utils/docs-preview/package-installer.js +1 -1
- package/dist/src/utils/docs-preview/package-installer.js.map +1 -1
- package/dist/src/utils/docs-preview/sidebar-builder.js +1 -1
- package/dist/src/utils/docs-preview/sidebar-builder.js.map +1 -1
- package/dist/src/utils/env-file-generator.js +1 -1
- package/dist/src/utils/env-file-generator.js.map +1 -1
- package/dist/src/utils/external-resource-validator.js +1 -1
- package/dist/src/utils/external-resource-validator.js.map +1 -1
- package/dist/src/utils/fs-native.d.ts +51 -5
- package/dist/src/utils/fs-native.d.ts.map +1 -1
- package/dist/src/utils/fs-native.js +100 -5
- package/dist/src/utils/fs-native.js.map +1 -1
- package/dist/src/utils/plugin-validator.js +1 -1
- package/dist/src/utils/plugin-validator.js.map +1 -1
- package/dist/src/utils/project-detection.js +1 -1
- package/dist/src/utils/project-detection.js.map +1 -1
- package/dist/src/utils/project-validator.js +1 -1
- package/dist/src/utils/project-validator.js.map +1 -1
- package/dist/src/utils/spec-parser.js +1 -1
- package/dist/src/utils/spec-parser.js.map +1 -1
- package/dist/src/utils/spec-splitter.js +1 -1
- package/dist/src/utils/spec-splitter.js.map +1 -1
- package/dist/src/validators/ac-coverage-validator.js +1 -1
- package/dist/src/validators/ac-coverage-validator.js.map +1 -1
- package/package.json +5 -6
- package/plugins/specweave/.claude-plugin/plugin.json +17 -11
- package/plugins/specweave/agents/architect/AGENT.md +115 -45
- package/plugins/specweave/agents/code-standards-detective/AGENT.md +47 -0
- package/plugins/specweave/agents/docs-writer/AGENT.md +134 -1
- package/plugins/specweave/agents/increment-quality-judge-v2/AGENT.md +1 -0
- package/plugins/specweave/agents/infrastructure/AGENT.md +48 -1
- package/plugins/specweave/agents/performance/AGENT.md +46 -0
- package/plugins/specweave/agents/pm/AGENT.md +115 -3
- package/plugins/specweave/agents/qa-lead/AGENT.md +40 -1
- package/plugins/specweave/agents/reflective-reviewer/AGENT.md +5 -0
- package/plugins/specweave/agents/security/AGENT.md +45 -0
- package/plugins/specweave/agents/tdd-orchestrator/AGENT.md +128 -1
- package/plugins/specweave/agents/tech-lead/AGENT.md +138 -1
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +76 -6
- package/plugins/specweave/agents/translator/AGENT.md +132 -0
- package/plugins/specweave/commands/specweave-sync-progress.md +616 -0
- package/plugins/specweave/hooks/hooks.json +0 -9
- package/plugins/specweave/hooks/lib/update-status-line.sh +19 -0
- package/plugins/specweave/hooks/post-edit-write-consolidated.sh +335 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +133 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +58 -19
- package/plugins/specweave/hooks/post-task-completion.sh +100 -9
- package/plugins/specweave/hooks/pre-edit-spec.sh +0 -11
- package/plugins/specweave/hooks/pre-edit-write-consolidated.sh +225 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +11 -0
- package/plugins/specweave/hooks/pre-write-spec.sh +0 -11
- package/plugins/specweave/hooks/shared/bulk-operation-detector.sh +167 -0
- package/plugins/specweave/lib/hooks/consolidated-sync.js +78 -3
- package/plugins/specweave/lib/hooks/us-completion-orchestrator.js +135 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +18 -4
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -1
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +1 -1
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -1
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +1 -1
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +1 -1
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -1
- package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
- package/plugins/specweave/skills/progress-sync/SKILL.md +405 -0
- package/plugins/specweave-ado/lib/ado-project-detector.js +1 -1
- package/plugins/specweave-ado/lib/ado-project-detector.ts +1 -1
- package/plugins/specweave-ado/lib/conflict-resolver.js +1 -1
- package/plugins/specweave-ado/lib/conflict-resolver.ts +1 -1
- package/plugins/specweave-backend/agents/database-optimizer/AGENT.md +1 -1
- package/plugins/specweave-frontend/agents/frontend-architect/AGENT.md +5 -0
- package/plugins/specweave-github/.claude-plugin/plugin.json +1 -15
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +480 -0
- package/plugins/specweave-github/hooks/README.md +34 -25
- package/plugins/specweave-github/lib/CodeValidator.js +1 -1
- package/plugins/specweave-github/lib/CodeValidator.ts +2 -2
- package/plugins/specweave-github/lib/ThreeLayerSyncManager.js +1 -1
- package/plugins/specweave-github/lib/ThreeLayerSyncManager.ts +1 -1
- package/plugins/specweave-github/lib/github-client-v2.js +59 -1
- package/plugins/specweave-github/lib/github-client-v2.ts +82 -1
- package/plugins/specweave-github/lib/github-issue-updater.js +1 -1
- package/plugins/specweave-github/lib/github-issue-updater.ts +1 -1
- package/plugins/specweave-github/lib/github-sync-bidirectional.js +1 -1
- package/plugins/specweave-github/lib/github-sync-bidirectional.ts +1 -1
- package/plugins/specweave-github/lib/github-sync-increment-changes.js +1 -1
- package/plugins/specweave-github/lib/github-sync-increment-changes.ts +1 -1
- package/plugins/specweave-github/lib/user-story-issue-builder.js +4 -4
- package/plugins/specweave-github/lib/user-story-issue-builder.ts +7 -6
- package/plugins/specweave-infrastructure/agents/devops/AGENT.md +48 -1
- package/plugins/specweave-infrastructure/agents/network-engineer/AGENT.md +6 -1
- package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +6 -1
- package/plugins/specweave-infrastructure/agents/performance-engineer/AGENT.md +6 -1
- package/plugins/specweave-infrastructure/agents/sre/AGENT.md +5 -0
- package/plugins/specweave-jira/lib/jira-epic-sync.js +1 -1
- package/plugins/specweave-jira/lib/jira-epic-sync.ts +1 -1
- package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +5 -0
- package/plugins/specweave-kubernetes/agents/kubernetes-architect/AGENT.md +47 -2
- package/plugins/specweave-ml/agents/data-scientist/AGENT.md +1 -1
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +5 -0
- package/plugins/specweave-ml/agents/mlops-engineer/AGENT.md +6 -1
- package/plugins/specweave-payments/agents/payment-integration/AGENT.md +1 -1
- package/plugins/specweave-release/commands/specweave-release-npm.md +130 -2
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +198 -0
- package/plugins/specweave-ado/hooks/hooks.json +0 -15
- package/plugins/specweave-github/hooks/hooks.json +0 -15
- package/plugins/specweave-jira/hooks/hooks.json +0 -15
- package/plugins/specweave-release/hooks/hooks.json +0 -15
|
@@ -36,10 +36,13 @@
|
|
|
36
36
|
|
|
37
37
|
set +e # NEVER use set -e in hooks - it causes crashes
|
|
38
38
|
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
# ============================================================================
|
|
40
|
+
# PROJECT ROOT DETECTION (MUST BE FIRST - v0.26.1 FIX)
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# CRITICAL FIX: PROJECT_ROOT must be defined BEFORE recursion guard creation
|
|
43
|
+
# BUG (v0.26.0): Used $PROJECT_ROOT on line 71 but defined it on line 112
|
|
44
|
+
# RESULT: Guard file created at wrong path (/.specweave/...) → recursion not prevented
|
|
45
|
+
# See: Incident 2025-11-24 (3x PreToolUse hook fires, Claude Code crash)
|
|
43
46
|
|
|
44
47
|
# Find project root by searching upward for .specweave/ directory
|
|
45
48
|
# Works regardless of where hook is installed (source or .claude/hooks/)
|
|
@@ -63,6 +66,60 @@ find_project_root() {
|
|
|
63
66
|
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
64
67
|
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
65
68
|
|
|
69
|
+
# ============================================================================
|
|
70
|
+
# RECURSION PREVENTION (CRITICAL - v0.26.0 - FILE-BASED GUARD)
|
|
71
|
+
# ============================================================================
|
|
72
|
+
# PROBLEM: Hooks that write files trigger other hooks, causing infinite loops.
|
|
73
|
+
# OLD SOLUTION (v0.25.1): Environment variable SPECWEAVE_IN_HOOK=1
|
|
74
|
+
# WHY IT FAILED: Background processes (&) create NEW shells that don't inherit env vars!
|
|
75
|
+
#
|
|
76
|
+
# NEW SOLUTION (v0.26.0): File-based recursion guard
|
|
77
|
+
# - Guard file exists = already inside hook chain
|
|
78
|
+
# - Works across ALL processes (not just current shell)
|
|
79
|
+
# - Atomic operation (mkdir -p ensures thread safety)
|
|
80
|
+
# - Cleanup guaranteed by trap EXIT
|
|
81
|
+
#
|
|
82
|
+
# Example infinite loop (BEFORE fix):
|
|
83
|
+
# TodoWrite → post-task-completion.sh (sets SPECWEAVE_IN_HOOK=1)
|
|
84
|
+
# → spawns background process (&)
|
|
85
|
+
# → consolidated-sync.js (SPECWEAVE_IN_HOOK=0! lost!)
|
|
86
|
+
# → fs.writeFile(tasks.md)
|
|
87
|
+
# → post-edit-write-consolidated.sh (guard fails!)
|
|
88
|
+
# → INFINITE RECURSION → 27 duplicate GitHub comments!
|
|
89
|
+
#
|
|
90
|
+
# With file-based guard (AFTER fix):
|
|
91
|
+
# TodoWrite → post-task-completion.sh (creates .hook-recursion-guard file)
|
|
92
|
+
# → spawns background process (&)
|
|
93
|
+
# → consolidated-sync.js (inherits guard file!)
|
|
94
|
+
# → fs.writeFile(tasks.md)
|
|
95
|
+
# → post-edit-write-consolidated.sh (checks file, exits)
|
|
96
|
+
# → NO RECURSION ✅
|
|
97
|
+
#
|
|
98
|
+
# See: .specweave/increments/0051-*/reports/GITHUB-COMMENT-RECURSION-ROOT-CAUSE-2025-11-24.md
|
|
99
|
+
# See: ADR-0073 (Hook Recursion Prevention Strategy)
|
|
100
|
+
|
|
101
|
+
RECURSION_GUARD_FILE="$PROJECT_ROOT/.specweave/state/.hook-recursion-guard"
|
|
102
|
+
|
|
103
|
+
if [[ -f "$RECURSION_GUARD_FILE" ]]; then
|
|
104
|
+
# Silent exit - we're already inside a hook chain
|
|
105
|
+
echo "[$(date)] ⏭️ Recursion guard detected - skipping (already in hook)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
106
|
+
exit 0
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
# Create guard file (atomic operation)
|
|
110
|
+
mkdir -p "$PROJECT_ROOT/.specweave/state" 2>/dev/null || true
|
|
111
|
+
touch "$RECURSION_GUARD_FILE"
|
|
112
|
+
|
|
113
|
+
# Ensure guard file is ALWAYS removed when script exits (even on error)
|
|
114
|
+
trap 'rm -f "$RECURSION_GUARD_FILE" 2>/dev/null || true' EXIT SIGINT SIGTERM
|
|
115
|
+
|
|
116
|
+
echo "[$(date)] 🔒 Recursion guard created" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
117
|
+
|
|
118
|
+
# EMERGENCY KILL SWITCH (after recursion guard)
|
|
119
|
+
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
120
|
+
exit 0
|
|
121
|
+
fi
|
|
122
|
+
|
|
66
123
|
# ============================================================================
|
|
67
124
|
# EMERGENCY SAFETY CHECKS
|
|
68
125
|
# ============================================================================
|
|
@@ -349,13 +406,25 @@ fi
|
|
|
349
406
|
# ============================================================================
|
|
350
407
|
# CONSOLIDATED SYNC (v0.24.4 - PERFORMANCE OPTIMIZATION)
|
|
351
408
|
# ============================================================================
|
|
352
|
-
#
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
#
|
|
356
|
-
#
|
|
409
|
+
# EMERGENCY FIX (v0.26.0-hotfix): DISABLED TO PREVENT CLAUDE CODE CRASHES
|
|
410
|
+
#
|
|
411
|
+
# ROOT CAUSE: consolidated-sync.js makes 5+ Edit/Write operations, each triggering
|
|
412
|
+
# 3 hooks (PreToolUse, PostToolUse×2), resulting in 15+ hook invocations per task.
|
|
413
|
+
# This causes process exhaustion and Claude Code crashes.
|
|
414
|
+
#
|
|
415
|
+
# NEW STRATEGY: Run consolidated sync ONLY at:
|
|
416
|
+
# 1. Session end (all tasks done + 120s inactivity)
|
|
417
|
+
# 2. Manual sync (/specweave:sync-docs command)
|
|
418
|
+
# 3. Increment closure (/specweave:done validation)
|
|
419
|
+
#
|
|
420
|
+
# See: .specweave/increments/0051-*/reports/CLAUDE-CODE-CRASH-ROOT-CAUSE-2025-11-23.md
|
|
421
|
+
# See: ADR-0072 (Post-Task Hook Simplification)
|
|
357
422
|
# ============================================================================
|
|
358
423
|
|
|
424
|
+
# RE-ENABLED: Automatic sync on each TodoWrite (ACCEPTING CRASH RISK)
|
|
425
|
+
# WARNING: This can cause Claude Code crashes if too many TodoWrite events fire rapidly
|
|
426
|
+
# User explicitly requested re-enabling despite crash risk
|
|
427
|
+
|
|
359
428
|
echo "[$(date)] 🚀 Running consolidated sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
360
429
|
|
|
361
430
|
# Find consolidated sync script
|
|
@@ -371,6 +440,28 @@ fi
|
|
|
371
440
|
fi
|
|
372
441
|
|
|
373
442
|
if [ -n "$CONSOLIDATED_SCRIPT" ]; then
|
|
443
|
+
# Load GITHUB_TOKEN from .env for gh CLI authentication
|
|
444
|
+
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|
445
|
+
# Extract GITHUB_TOKEN from .env (handles various formats)
|
|
446
|
+
GITHUB_TOKEN_FROM_ENV=$(grep -E '^GITHUB_TOKEN=' "$PROJECT_ROOT/.env" 2>/dev/null | head -1 | cut -d'=' -f2- | sed 's/^["'\'']//' | sed 's/["'\'']$//')
|
|
447
|
+
if [ -n "$GITHUB_TOKEN_FROM_ENV" ]; then
|
|
448
|
+
export GITHUB_TOKEN="$GITHUB_TOKEN_FROM_ENV"
|
|
449
|
+
echo "[$(date)] ✅ GitHub token loaded from .env" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
450
|
+
fi
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
# FIX (v0.26.0): Skip GitHub sync in post-task-completion hook
|
|
454
|
+
# GitHub sync should ONLY run on increment COMPLETION, not task completion
|
|
455
|
+
# This prevents 27 duplicate comments (see root cause analysis)
|
|
456
|
+
export SKIP_GITHUB_SYNC=true
|
|
457
|
+
|
|
458
|
+
# EMERGENCY FIX (v0.25.1): Skip US sync in post-task-completion hook
|
|
459
|
+
# CRITICAL: US sync triggers livingDocsSync.syncIncrement() which calls
|
|
460
|
+
# syncToExternalTools() without respecting SKIP_GITHUB_SYNC, causing
|
|
461
|
+
# Edit/Write operations that trigger new hook chains → infinite recursion → crash
|
|
462
|
+
# See: ROOT-CAUSE-ANALYSIS-TODOWRITE-CRASH-2025-11-24.md
|
|
463
|
+
export SKIP_US_SYNC=true
|
|
464
|
+
|
|
374
465
|
# Run consolidated sync (single Node.js process handles ALL operations)
|
|
375
466
|
if (cd "$PROJECT_ROOT" && node "$CONSOLIDATED_SCRIPT" "$CURRENT_INCREMENT") >> "$DEBUG_LOG" 2>&1; then
|
|
376
467
|
echo "[$(date)] ✅ Consolidated sync completed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
@@ -101,17 +101,6 @@ else
|
|
|
101
101
|
exit 0 # Let PostToolUse handle it with mtime fallback
|
|
102
102
|
fi
|
|
103
103
|
|
|
104
|
-
# ============================================================================
|
|
105
|
-
# EARLY EXIT: Only process .specweave/ files (v0.24.4 Performance Fix)
|
|
106
|
-
# ============================================================================
|
|
107
|
-
# 90% of Edit operations are on non-SpecWeave files (src/, tests/, node_modules/)
|
|
108
|
-
# Exit immediately for non-.specweave/ files to reduce hook overhead by 90%
|
|
109
|
-
|
|
110
|
-
if [[ "$FILE_PATH" != *"/.specweave/"* ]]; then
|
|
111
|
-
echo "[$(date)] pre-edit-spec: Not a .specweave/ file, skipping (performance optimization)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
112
|
-
exit 0
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
104
|
# Check if this is a spec.md or tasks.md file in increments folder
|
|
116
105
|
IS_SPEC_FILE=false
|
|
117
106
|
if [[ "$FILE_PATH" == *"/spec.md" ]] || [[ "$FILE_PATH" == *"/tasks.md" ]]; then
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Pre-Edit/Write Consolidated Hook: Capture File Path BEFORE Edit/Write Executes
|
|
4
|
+
#
|
|
5
|
+
# Purpose: Unified hook for both Edit and Write tools
|
|
6
|
+
# Strategy: Hierarchical early exit for maximum performance
|
|
7
|
+
#
|
|
8
|
+
# CONSOLIDATION (v0.25.0):
|
|
9
|
+
# - Replaces pre-edit-spec.sh and pre-write-spec.sh (identical code)
|
|
10
|
+
# - Reduces hook overhead by 50% (2 pre-hooks → 1)
|
|
11
|
+
# - Single point of maintenance
|
|
12
|
+
#
|
|
13
|
+
# HIERARCHICAL EARLY EXIT (v0.26.1):
|
|
14
|
+
# - Tier 0: TOOL_USE_ARGS check (< 1ms) - Exit if empty (Claude Code bug)
|
|
15
|
+
# - Tier 1: .specweave/ path check (< 5ms) - Exit if not SpecWeave file
|
|
16
|
+
# - Tier 2: Active increment check (< 10ms) - Exit if archived/completed
|
|
17
|
+
# - Tier 3: Full processing - AC sync, status line, living docs
|
|
18
|
+
#
|
|
19
|
+
# GRACEFUL DEGRADATION:
|
|
20
|
+
# - PreToolUse works if TOOL_USE_ARGS is available (fast filtering)
|
|
21
|
+
# - PostToolUse fallback uses mtime if PreToolUse disabled (slower but works)
|
|
22
|
+
# - Self-tuning: Disables PreToolUse if consistently useless
|
|
23
|
+
#
|
|
24
|
+
# Architecture:
|
|
25
|
+
# PreToolUse:Edit/Write → pre-edit-write-consolidated.sh (this file)
|
|
26
|
+
# ↓ writes to
|
|
27
|
+
# .specweave/state/.pending-status-update
|
|
28
|
+
# ↓ read by
|
|
29
|
+
# PostToolUse:Edit/Write → post-edit-write-consolidated.sh
|
|
30
|
+
#
|
|
31
|
+
# Version: v0.26.1 (HIERARCHICAL EARLY EXIT)
|
|
32
|
+
# Date: 2025-11-24
|
|
33
|
+
#
|
|
34
|
+
# EMERGENCY FIXES (v0.24.3):
|
|
35
|
+
# - Kill switch: Set SPECWEAVE_DISABLE_HOOKS=1 to disable ALL hooks
|
|
36
|
+
# - Circuit breaker: Auto-disable after 3 consecutive failures
|
|
37
|
+
# - File locking: Prevent concurrent executions
|
|
38
|
+
# - Complete error isolation: Never let errors reach Claude Code
|
|
39
|
+
|
|
40
|
+
# EMERGENCY FIX: Remove set -e - it causes Claude Code crashes!
|
|
41
|
+
set +e
|
|
42
|
+
|
|
43
|
+
# ============================================================================
|
|
44
|
+
# TIER 0: ULTRA-FAST REJECTION (< 1ms) - v0.26.1 CRITICAL FIX
|
|
45
|
+
# ============================================================================
|
|
46
|
+
# Problem: Claude Code doesn't pass TOOL_USE_ARGS to PreToolUse hooks (bug)
|
|
47
|
+
# Result: PreToolUse hooks are "blind" - can't filter files, fire for everything
|
|
48
|
+
# Impact: Massive overhead (1 pre-hook per Edit/Write on ANY file)
|
|
49
|
+
#
|
|
50
|
+
# Solution: Exit immediately if TOOL_USE_ARGS is empty
|
|
51
|
+
# - No find_project_root, no file path extraction, no processing
|
|
52
|
+
# - Eliminates 33% of hook overhead (1 of 3 hooks per operation)
|
|
53
|
+
# - Falls back to PostToolUse mtime detection (slower but works)
|
|
54
|
+
#
|
|
55
|
+
# See: ADR-0128 (Hierarchical Hook Early Exit Strategy)
|
|
56
|
+
|
|
57
|
+
if [[ -z "${TOOL_USE_ARGS:-}" ]]; then
|
|
58
|
+
# Telemetry: Track PreToolUse disabled events (lightweight counter)
|
|
59
|
+
# This helps us understand if Claude Code ever fixes the TOOL_USE_ARGS bug
|
|
60
|
+
TELEMETRY_DIR="${HOME}/.claude/.specweave-telemetry"
|
|
61
|
+
mkdir -p "$TELEMETRY_DIR" 2>/dev/null || true
|
|
62
|
+
echo "$(date -u +%s)" >> "$TELEMETRY_DIR/pretooluse-disabled.log" 2>/dev/null || true
|
|
63
|
+
|
|
64
|
+
# Silent exit - PreToolUse is useless without TOOL_USE_ARGS
|
|
65
|
+
# PostToolUse will handle via mtime fallback
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Telemetry: Track PreToolUse enabled events (TOOL_USE_ARGS available)
|
|
70
|
+
TELEMETRY_DIR="${HOME}/.claude/.specweave-telemetry"
|
|
71
|
+
mkdir -p "$TELEMETRY_DIR" 2>/dev/null || true
|
|
72
|
+
echo "$(date -u +%s)" >> "$TELEMETRY_DIR/pretooluse-enabled.log" 2>/dev/null || true
|
|
73
|
+
|
|
74
|
+
# Find project root (must be BEFORE recursion guard to get PROJECT_ROOT)
|
|
75
|
+
find_project_root() {
|
|
76
|
+
local dir="$PWD"
|
|
77
|
+
while [[ "$dir" != "/" ]]; do
|
|
78
|
+
if [[ -d "$dir/.specweave" ]]; then
|
|
79
|
+
echo "$dir"
|
|
80
|
+
return 0
|
|
81
|
+
fi
|
|
82
|
+
dir=$(dirname "$dir")
|
|
83
|
+
done
|
|
84
|
+
echo "$PWD"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
PROJECT_ROOT=$(find_project_root)
|
|
88
|
+
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
89
|
+
LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
|
|
90
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
91
|
+
PENDING_FILE="$STATE_DIR/.pending-status-update"
|
|
92
|
+
METRICS_FILE="$STATE_DIR/hook-metrics.jsonl"
|
|
93
|
+
|
|
94
|
+
# ============================================================================
|
|
95
|
+
# RECURSION PREVENTION (CRITICAL - v0.26.0 - FILE-BASED GUARD)
|
|
96
|
+
# ============================================================================
|
|
97
|
+
# NEW SOLUTION (v0.26.0): File-based recursion guard
|
|
98
|
+
# - Guard file exists = already inside hook chain
|
|
99
|
+
# - Works across ALL processes (not just current shell)
|
|
100
|
+
#
|
|
101
|
+
# See: ADR-0073 (Hook Recursion Prevention Strategy)
|
|
102
|
+
|
|
103
|
+
RECURSION_GUARD_FILE="$PROJECT_ROOT/.specweave/state/.hook-recursion-guard"
|
|
104
|
+
|
|
105
|
+
if [[ -f "$RECURSION_GUARD_FILE" ]]; then
|
|
106
|
+
# Silent exit - we're already inside a hook chain
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# EMERGENCY KILL SWITCH: Disable all hooks if env variable set
|
|
111
|
+
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Ensure directories exist
|
|
116
|
+
mkdir -p "$STATE_DIR" "$LOGS_DIR" 2>/dev/null || true
|
|
117
|
+
|
|
118
|
+
# ============================================================================
|
|
119
|
+
# TIER 2: Extract File Path from Tool Arguments
|
|
120
|
+
# ============================================================================
|
|
121
|
+
# PreToolUse should have access to tool arguments BEFORE execution
|
|
122
|
+
# Try multiple methods to extract file_path
|
|
123
|
+
|
|
124
|
+
FILE_PATH=""
|
|
125
|
+
|
|
126
|
+
# Method 1: TOOL_USE_ARGS environment variable (primary for PreToolUse)
|
|
127
|
+
if [[ -n "${TOOL_USE_ARGS:-}" ]]; then
|
|
128
|
+
# Try to parse JSON with jq if available
|
|
129
|
+
if command -v jq &> /dev/null; then
|
|
130
|
+
FILE_PATH=$(echo "$TOOL_USE_ARGS" | jq -r '.file_path // empty' 2>/dev/null || echo "")
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Fallback: Regex extraction if jq not available or failed
|
|
134
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
135
|
+
FILE_PATH=$(echo "$TOOL_USE_ARGS" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)".*/\1/' || echo "")
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
# Method 2: TOOL_USE_CONTENT (fallback)
|
|
140
|
+
if [[ -z "$FILE_PATH" ]] && [[ -n "${TOOL_USE_CONTENT:-}" ]]; then
|
|
141
|
+
FILE_PATH="$TOOL_USE_CONTENT"
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# Method 3: Parse from stdin (last resort - experimental)
|
|
145
|
+
if [[ -z "$FILE_PATH" ]] && [[ ! -t 0 ]]; then
|
|
146
|
+
# Read stdin and try to extract file_path
|
|
147
|
+
STDIN_DATA=$(cat 2>/dev/null || echo "")
|
|
148
|
+
if [[ -n "$STDIN_DATA" ]] && command -v jq &> /dev/null; then
|
|
149
|
+
FILE_PATH=$(echo "$STDIN_DATA" | jq -r '.file_path // empty' 2>/dev/null || echo "")
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# ============================================================================
|
|
154
|
+
# TIER 2: Signal Detection and Validation
|
|
155
|
+
# ============================================================================
|
|
156
|
+
|
|
157
|
+
# Log what we detected (for debugging PreToolUse effectiveness)
|
|
158
|
+
if [[ -n "$FILE_PATH" ]]; then
|
|
159
|
+
echo "[$(date)] pre-edit-write: Detected file_path: $FILE_PATH" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
160
|
+
else
|
|
161
|
+
echo "[$(date)] pre-edit-write: No file_path detected (will fall back to Tier 1)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
162
|
+
exit 0 # Let PostToolUse handle it with mtime fallback
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# ============================================================================
|
|
166
|
+
# EARLY EXIT: Only process .specweave/ files (v0.24.4 Performance Fix)
|
|
167
|
+
# ============================================================================
|
|
168
|
+
# 90% of Edit/Write operations are on non-SpecWeave files (src/, tests/, node_modules/)
|
|
169
|
+
# Exit immediately for non-.specweave/ files to reduce hook overhead by 90%
|
|
170
|
+
|
|
171
|
+
# Handle both absolute and relative paths: /.specweave/ or .specweave/
|
|
172
|
+
if [[ "$FILE_PATH" != *"/.specweave/"* ]] && [[ "$FILE_PATH" != ".specweave/"* ]]; then
|
|
173
|
+
echo "[$(date)] pre-edit-write: Not a .specweave/ file, skipping (performance optimization)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
174
|
+
exit 0
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# Check if this is a spec.md or tasks.md file in increments folder
|
|
178
|
+
IS_SPEC_FILE=false
|
|
179
|
+
if [[ "$FILE_PATH" == *"/spec.md" ]] || [[ "$FILE_PATH" == *"/tasks.md" ]]; then
|
|
180
|
+
# Handle both absolute (/.specweave/increments/) and relative (.specweave/increments/) paths
|
|
181
|
+
if [[ "$FILE_PATH" == *"/.specweave/increments/"* ]] || [[ "$FILE_PATH" == ".specweave/increments/"* ]]; then
|
|
182
|
+
# Exclude archived increments
|
|
183
|
+
if [[ "$FILE_PATH" != *"/_archive/"* ]]; then
|
|
184
|
+
IS_SPEC_FILE=true
|
|
185
|
+
fi
|
|
186
|
+
fi
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# If not a spec/tasks file, exit silently (no signal to PostToolUse)
|
|
190
|
+
if [[ "$IS_SPEC_FILE" != "true" ]]; then
|
|
191
|
+
echo "[$(date)] pre-edit-write: Not a spec/tasks file - no signal" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
192
|
+
exit 0
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# ============================================================================
|
|
196
|
+
# TIER 2: Write Signal for PostToolUse Hook
|
|
197
|
+
# ============================================================================
|
|
198
|
+
|
|
199
|
+
# Write file path to pending file for PostToolUse to consume
|
|
200
|
+
echo "$FILE_PATH" > "$PENDING_FILE" 2>/dev/null || true
|
|
201
|
+
|
|
202
|
+
echo "[$(date)] pre-edit-write: Signaled PostToolUse for: $FILE_PATH" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
203
|
+
|
|
204
|
+
# ============================================================================
|
|
205
|
+
# TIER 2: Metrics Collection
|
|
206
|
+
# ============================================================================
|
|
207
|
+
|
|
208
|
+
# Record metrics (JSONL format - one JSON object per line)
|
|
209
|
+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
210
|
+
METRIC_ENTRY="{\"timestamp\":\"$TIMESTAMP\",\"hook\":\"pre-edit-write\",\"event\":\"file_detected\",\"file_path\":\"$FILE_PATH\",\"method\":\"TOOL_USE_ARGS\"}"
|
|
211
|
+
|
|
212
|
+
# Append to metrics file (JSONL)
|
|
213
|
+
echo "$METRIC_ENTRY" >> "$METRICS_FILE" 2>/dev/null || true
|
|
214
|
+
|
|
215
|
+
# Log rotation for metrics (keep last 1000 entries)
|
|
216
|
+
if [[ -f "$METRICS_FILE" ]]; then
|
|
217
|
+
LINE_COUNT=$(wc -l < "$METRICS_FILE" 2>/dev/null || echo 0)
|
|
218
|
+
if (( LINE_COUNT > 1000 )); then
|
|
219
|
+
tail -1000 "$METRICS_FILE" > "$METRICS_FILE.tmp" 2>/dev/null || true
|
|
220
|
+
mv "$METRICS_FILE.tmp" "$METRICS_FILE" 2>/dev/null || true
|
|
221
|
+
fi
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
225
|
+
exit 0
|
|
@@ -22,6 +22,17 @@
|
|
|
22
22
|
|
|
23
23
|
set +e # EMERGENCY FIX: Prevents Claude Code crashes
|
|
24
24
|
|
|
25
|
+
# ============================================================================
|
|
26
|
+
# RECURSION PREVENTION (CRITICAL - v0.25.1)
|
|
27
|
+
# ============================================================================
|
|
28
|
+
# Skip if we're already inside a hook to prevent infinite recursion
|
|
29
|
+
if [[ "${SPECWEAVE_IN_HOOK:-0}" == "1" ]]; then
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Mark that we're now inside a hook
|
|
34
|
+
export SPECWEAVE_IN_HOOK=1
|
|
35
|
+
|
|
25
36
|
# EMERGENCY KILL SWITCH
|
|
26
37
|
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
27
38
|
exit 0
|
|
@@ -101,17 +101,6 @@ else
|
|
|
101
101
|
exit 0 # Let PostToolUse handle it with mtime fallback
|
|
102
102
|
fi
|
|
103
103
|
|
|
104
|
-
# ============================================================================
|
|
105
|
-
# EARLY EXIT: Only process .specweave/ files (v0.24.4 Performance Fix)
|
|
106
|
-
# ============================================================================
|
|
107
|
-
# 90% of Write operations are on non-SpecWeave files (src/, tests/, node_modules/)
|
|
108
|
-
# Exit immediately for non-.specweave/ files to reduce hook overhead by 90%
|
|
109
|
-
|
|
110
|
-
if [[ "$FILE_PATH" != *"/.specweave/"* ]]; then
|
|
111
|
-
echo "[$(date)] pre-write-spec: Not a .specweave/ file, skipping (performance optimization)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
112
|
-
exit 0
|
|
113
|
-
fi
|
|
114
|
-
|
|
115
104
|
# Check if this is a spec.md or tasks.md file in increments folder
|
|
116
105
|
IS_SPEC_FILE=false
|
|
117
106
|
if [[ "$FILE_PATH" == *"/spec.md" ]] || [[ "$FILE_PATH" == *"/tasks.md" ]]; then
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Bulk Operation Detector (v0.26.0)
|
|
3
|
+
#
|
|
4
|
+
# Detects bulk edit operations (5+ edits in 10 seconds) and triggers batch mode.
|
|
5
|
+
# Part of ADR-0130: Hook Bulk Operation Detection and Batching
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# source bulk-operation-detector.sh
|
|
9
|
+
# BULK_STATUS=$(detect_bulk_operation "$INCREMENT_ID")
|
|
10
|
+
#
|
|
11
|
+
# if [ "$BULK_STATUS" = "BULK_MODE_DETECTED" ]; then
|
|
12
|
+
# # Skip individual hook, batch job will run later
|
|
13
|
+
# exit 0
|
|
14
|
+
# fi
|
|
15
|
+
|
|
16
|
+
# Configuration
|
|
17
|
+
BULK_THRESHOLD=${SPECWEAVE_BULK_THRESHOLD:-5} # 5+ operations = bulk mode
|
|
18
|
+
BULK_WINDOW=${SPECWEAVE_BULK_WINDOW:-10} # seconds
|
|
19
|
+
IDLE_DELAY=${SPECWEAVE_IDLE_DELAY:-5} # seconds before batch execution
|
|
20
|
+
|
|
21
|
+
# State files
|
|
22
|
+
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
23
|
+
OPERATION_COUNTER="$STATE_DIR/.hook-operation-counter"
|
|
24
|
+
OPERATION_TIMESTAMP="$STATE_DIR/.hook-operation-timestamp"
|
|
25
|
+
|
|
26
|
+
# Ensure state directory exists
|
|
27
|
+
mkdir -p "$STATE_DIR"
|
|
28
|
+
|
|
29
|
+
##
|
|
30
|
+
# Detect bulk operation
|
|
31
|
+
#
|
|
32
|
+
# Uses sliding window counter to detect operation bursts:
|
|
33
|
+
# - Counts operations within BULK_WINDOW (10 seconds)
|
|
34
|
+
# - If count >= BULK_THRESHOLD (5 operations) → bulk mode
|
|
35
|
+
# - Resets counter after idle period
|
|
36
|
+
#
|
|
37
|
+
# Args:
|
|
38
|
+
# $1 - INCREMENT_ID (optional, for logging)
|
|
39
|
+
#
|
|
40
|
+
# Returns:
|
|
41
|
+
# BULK_MODE_DETECTED - Bulk operation detected, skip individual hook
|
|
42
|
+
# SINGLE_OPERATION - Single operation, run hook normally
|
|
43
|
+
##
|
|
44
|
+
detect_bulk_operation() {
|
|
45
|
+
local INCREMENT_ID="${1:-unknown}"
|
|
46
|
+
local CURRENT_TIME=$(date +%s)
|
|
47
|
+
|
|
48
|
+
# Read existing counter and timestamp
|
|
49
|
+
local RECENT_OPS=0
|
|
50
|
+
local LAST_OP_TIME=0
|
|
51
|
+
|
|
52
|
+
if [ -f "$OPERATION_COUNTER" ]; then
|
|
53
|
+
RECENT_OPS=$(cat "$OPERATION_COUNTER" 2>/dev/null || echo 0)
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ -f "$OPERATION_TIMESTAMP" ]; then
|
|
57
|
+
LAST_OP_TIME=$(cat "$OPERATION_TIMESTAMP" 2>/dev/null || echo 0)
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Reset counter if outside window (idle period detected)
|
|
61
|
+
local TIME_SINCE_LAST_OP=$((CURRENT_TIME - LAST_OP_TIME))
|
|
62
|
+
if (( TIME_SINCE_LAST_OP > BULK_WINDOW )); then
|
|
63
|
+
RECENT_OPS=0
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Increment operation counter
|
|
67
|
+
RECENT_OPS=$((RECENT_OPS + 1))
|
|
68
|
+
|
|
69
|
+
# Write atomically (use temp file + rename for atomicity)
|
|
70
|
+
echo "$RECENT_OPS" > "${OPERATION_COUNTER}.tmp"
|
|
71
|
+
mv "${OPERATION_COUNTER}.tmp" "$OPERATION_COUNTER"
|
|
72
|
+
|
|
73
|
+
echo "$CURRENT_TIME" > "${OPERATION_TIMESTAMP}.tmp"
|
|
74
|
+
mv "${OPERATION_TIMESTAMP}.tmp" "$OPERATION_TIMESTAMP"
|
|
75
|
+
|
|
76
|
+
# Bulk operation detected?
|
|
77
|
+
if (( RECENT_OPS >= BULK_THRESHOLD )); then
|
|
78
|
+
# Log bulk mode activation
|
|
79
|
+
local DEBUG_LOG="$PROJECT_ROOT/.specweave/logs/hook-debug.log"
|
|
80
|
+
echo "[$(date)] [BULK] Detected bulk operation for $INCREMENT_ID (op #$RECENT_OPS)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
81
|
+
|
|
82
|
+
# Schedule batch job (if not already scheduled)
|
|
83
|
+
schedule_batch_job "$INCREMENT_ID"
|
|
84
|
+
|
|
85
|
+
echo "BULK_MODE_DETECTED"
|
|
86
|
+
return 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Single operation
|
|
90
|
+
echo "SINGLE_OPERATION"
|
|
91
|
+
return 0
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
##
|
|
95
|
+
# Schedule batch job
|
|
96
|
+
#
|
|
97
|
+
# Schedules a batch job to run after idle period (IDLE_DELAY seconds).
|
|
98
|
+
# If a batch job is already scheduled, it gets canceled and rescheduled.
|
|
99
|
+
#
|
|
100
|
+
# Args:
|
|
101
|
+
# $1 - INCREMENT_ID
|
|
102
|
+
##
|
|
103
|
+
schedule_batch_job() {
|
|
104
|
+
local INCREMENT_ID="$1"
|
|
105
|
+
local BATCH_LOCK="$STATE_DIR/.batch-job-${INCREMENT_ID}.lock"
|
|
106
|
+
local DEBUG_LOG="$PROJECT_ROOT/.specweave/logs/hook-debug.log"
|
|
107
|
+
|
|
108
|
+
# Cancel existing batch job (if any)
|
|
109
|
+
if [ -f "$BATCH_LOCK" ]; then
|
|
110
|
+
local OLD_PID=$(cat "$BATCH_LOCK" 2>/dev/null || echo "")
|
|
111
|
+
if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
|
|
112
|
+
kill "$OLD_PID" 2>/dev/null || true
|
|
113
|
+
echo "[$(date)] [BATCH] Canceled previous batch job (PID: $OLD_PID)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
114
|
+
fi
|
|
115
|
+
rm -f "$BATCH_LOCK"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Schedule new batch job (background process)
|
|
119
|
+
(
|
|
120
|
+
# Wait for idle period
|
|
121
|
+
sleep "$IDLE_DELAY"
|
|
122
|
+
|
|
123
|
+
# If operation counter still exists → run batched hook
|
|
124
|
+
if [ -f "$OPERATION_COUNTER" ]; then
|
|
125
|
+
local OPERATION_COUNT=$(cat "$OPERATION_COUNTER" 2>/dev/null || echo 0)
|
|
126
|
+
|
|
127
|
+
echo "[$(date)] [BATCH] Idle period detected, running batch job for $INCREMENT_ID ($OPERATION_COUNT ops)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
128
|
+
|
|
129
|
+
# Clear operation counter (batch job starting)
|
|
130
|
+
rm -f "$OPERATION_COUNTER" "$OPERATION_TIMESTAMP"
|
|
131
|
+
|
|
132
|
+
# Run consolidated hook in batch mode
|
|
133
|
+
bash "$PROJECT_ROOT/plugins/specweave/hooks/post-task-completion.sh" \
|
|
134
|
+
--batch-mode \
|
|
135
|
+
--increment "$INCREMENT_ID" \
|
|
136
|
+
>> "$PROJECT_ROOT/.specweave/logs/batch-jobs.log" 2>&1
|
|
137
|
+
|
|
138
|
+
echo "[$(date)] [BATCH] ✅ Batch job completed for $INCREMENT_ID" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
139
|
+
else
|
|
140
|
+
echo "[$(date)] [BATCH] Operation counter cleared before batch job ran (duplicate batch?)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Cleanup batch lock
|
|
144
|
+
rm -f "$BATCH_LOCK"
|
|
145
|
+
) &
|
|
146
|
+
|
|
147
|
+
# Save PID for cancellation
|
|
148
|
+
local BATCH_PID=$!
|
|
149
|
+
echo "$BATCH_PID" > "$BATCH_LOCK"
|
|
150
|
+
|
|
151
|
+
echo "[$(date)] [BATCH] Scheduled batch job for $INCREMENT_ID (PID: $BATCH_PID, delay: ${IDLE_DELAY}s)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
##
|
|
155
|
+
# Reset bulk operation counter
|
|
156
|
+
#
|
|
157
|
+
# Manually resets the operation counter (useful for testing or troubleshooting).
|
|
158
|
+
##
|
|
159
|
+
reset_bulk_counter() {
|
|
160
|
+
rm -f "$OPERATION_COUNTER" "$OPERATION_TIMESTAMP"
|
|
161
|
+
echo "[$(date)] [BULK] Operation counter reset" >> "$PROJECT_ROOT/.specweave/logs/hook-debug.log" 2>/dev/null || true
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Export functions for use in hooks
|
|
165
|
+
export -f detect_bulk_operation
|
|
166
|
+
export -f schedule_batch_job
|
|
167
|
+
export -f reset_bulk_counter
|