prjct-cli 1.22.0 → 1.23.0
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 +147 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct.mjs +917 -35845
- package/dist/bin/prjct.mjs.map +7 -0
- package/dist/cli/linear.mjs +16 -0
- package/dist/cli/linear.mjs.map +7 -0
- package/dist/templates.json +1 -0
- package/package.json +4 -5
- package/bin/prjct.ts +0 -342
- package/core/__tests__/agentic/analysis-injection.test.ts +0 -377
- package/core/__tests__/agentic/cache-eviction.test.ts +0 -294
- package/core/__tests__/agentic/command-context.test.ts +0 -281
- package/core/__tests__/agentic/command-executor.test.ts +0 -659
- package/core/__tests__/agentic/domain-classifier.test.ts +0 -330
- package/core/__tests__/agentic/injection-validator.test.ts +0 -255
- package/core/__tests__/agentic/memory-system.test.ts +0 -281
- package/core/__tests__/agentic/plan-mode.test.ts +0 -386
- package/core/__tests__/agentic/prompt-assembly.test.ts +0 -298
- package/core/__tests__/agentic/prompt-builder.test.ts +0 -243
- package/core/__tests__/agentic/response-validator.test.ts +0 -263
- package/core/__tests__/agentic/semantic-matching.test.ts +0 -131
- package/core/__tests__/agentic/smart-context.test.ts +0 -372
- package/core/__tests__/agentic/tech-normalizer.test.ts +0 -136
- package/core/__tests__/agentic/token-budget.test.ts +0 -294
- package/core/__tests__/ai-tools/formatters.test.ts +0 -476
- package/core/__tests__/domain/bm25.test.ts +0 -225
- package/core/__tests__/domain/change-propagator.test.ts +0 -100
- package/core/__tests__/domain/fibonacci.test.ts +0 -113
- package/core/__tests__/domain/file-hasher.test.ts +0 -146
- package/core/__tests__/domain/file-ranker.test.ts +0 -169
- package/core/__tests__/domain/git-cochange.test.ts +0 -121
- package/core/__tests__/domain/import-graph.test.ts +0 -156
- package/core/__tests__/domain/velocity.test.ts +0 -623
- package/core/__tests__/infrastructure/performance-tracker.test.ts +0 -328
- package/core/__tests__/schemas/model.test.ts +0 -272
- package/core/__tests__/services/dependency-validator.test.ts +0 -175
- package/core/__tests__/services/hierarchical-agent-resolver.test.ts +0 -359
- package/core/__tests__/services/nested-context-resolver.test.ts +0 -443
- package/core/__tests__/services/project-index.test.ts +0 -355
- package/core/__tests__/services/staleness-checker.test.ts +0 -204
- package/core/__tests__/storage/analysis-storage.test.ts +0 -641
- package/core/__tests__/storage/archive-storage.test.ts +0 -455
- package/core/__tests__/storage/safe-reader.test.ts +0 -262
- package/core/__tests__/storage/sqlite-migration.test.ts +0 -1016
- package/core/__tests__/storage/state-storage-feedback.test.ts +0 -463
- package/core/__tests__/storage/state-storage-history.test.ts +0 -469
- package/core/__tests__/storage/storage-manager.test.ts +0 -383
- package/core/__tests__/storage/subtask-handoff.test.ts +0 -237
- package/core/__tests__/types/fs.test.ts +0 -125
- package/core/__tests__/utils/date-helper.test.ts +0 -449
- package/core/__tests__/utils/output.test.ts +0 -278
- package/core/__tests__/utils/preserve-sections.test.ts +0 -216
- package/core/__tests__/utils/project-commands.test.ts +0 -71
- package/core/__tests__/utils/retry.test.ts +0 -381
- package/core/__tests__/workflow/state-machine.test.ts +0 -216
- package/core/agentic/agent-router.ts +0 -150
- package/core/agentic/anti-hallucination.ts +0 -141
- package/core/agentic/chain-of-thought.ts +0 -234
- package/core/agentic/command-classifier.ts +0 -141
- package/core/agentic/command-context.ts +0 -168
- package/core/agentic/command-executor.ts +0 -471
- package/core/agentic/context-builder.ts +0 -285
- package/core/agentic/domain-classifier.ts +0 -525
- package/core/agentic/environment-block.ts +0 -102
- package/core/agentic/ground-truth.ts +0 -706
- package/core/agentic/index.ts +0 -193
- package/core/agentic/injection-validator.ts +0 -208
- package/core/agentic/loop-detector.ts +0 -451
- package/core/agentic/memory-system.ts +0 -1547
- package/core/agentic/orchestrator-executor.ts +0 -579
- package/core/agentic/plan-mode.ts +0 -525
- package/core/agentic/prompt-builder.ts +0 -1069
- package/core/agentic/response-validator.ts +0 -98
- package/core/agentic/services.ts +0 -167
- package/core/agentic/skill-loader.ts +0 -106
- package/core/agentic/smart-context.ts +0 -393
- package/core/agentic/tech-normalizer.ts +0 -167
- package/core/agentic/template-executor.ts +0 -272
- package/core/agentic/template-loader.ts +0 -109
- package/core/agentic/token-budget.ts +0 -226
- package/core/agentic/tool-registry.ts +0 -146
- package/core/agents/index.ts +0 -28
- package/core/agents/performance.ts +0 -429
- package/core/ai-tools/formatters.ts +0 -341
- package/core/ai-tools/generator.ts +0 -144
- package/core/ai-tools/index.ts +0 -15
- package/core/ai-tools/registry.ts +0 -201
- package/core/bus/bus.ts +0 -314
- package/core/bus/index.ts +0 -8
- package/core/cli/linear.ts +0 -500
- package/core/cli/lint-meta-commentary.ts +0 -177
- package/core/cli/start.ts +0 -386
- package/core/commands/analysis.ts +0 -1274
- package/core/commands/analytics.ts +0 -342
- package/core/commands/base.ts +0 -118
- package/core/commands/cleanup.ts +0 -157
- package/core/commands/command-data.ts +0 -463
- package/core/commands/commands.ts +0 -306
- package/core/commands/context.ts +0 -238
- package/core/commands/design.ts +0 -77
- package/core/commands/index.ts +0 -19
- package/core/commands/maintenance.ts +0 -77
- package/core/commands/performance.ts +0 -114
- package/core/commands/planning.ts +0 -662
- package/core/commands/register.ts +0 -127
- package/core/commands/registry.ts +0 -444
- package/core/commands/setup.ts +0 -280
- package/core/commands/shipping.ts +0 -267
- package/core/commands/snapshots.ts +0 -297
- package/core/commands/uninstall.ts +0 -542
- package/core/commands/velocity.ts +0 -149
- package/core/commands/workflow.ts +0 -505
- package/core/config/command-context.config.json +0 -66
- package/core/constants/index.ts +0 -379
- package/core/context/generator.ts +0 -368
- package/core/context-tools/files-tool.ts +0 -577
- package/core/context-tools/imports-tool.ts +0 -400
- package/core/context-tools/index.ts +0 -434
- package/core/context-tools/recent-tool.ts +0 -301
- package/core/context-tools/signatures-tool.ts +0 -495
- package/core/context-tools/summary-tool.ts +0 -301
- package/core/context-tools/token-counter.ts +0 -273
- package/core/context-tools/types.ts +0 -253
- package/core/domain/agent-generator.ts +0 -186
- package/core/domain/agent-loader.ts +0 -419
- package/core/domain/analyzer.ts +0 -387
- package/core/domain/architecture-generator.ts +0 -108
- package/core/domain/bm25.ts +0 -525
- package/core/domain/change-propagator.ts +0 -162
- package/core/domain/context-estimator.ts +0 -175
- package/core/domain/fibonacci.ts +0 -128
- package/core/domain/file-hasher.ts +0 -296
- package/core/domain/file-ranker.ts +0 -151
- package/core/domain/git-cochange.ts +0 -250
- package/core/domain/import-graph.ts +0 -315
- package/core/domain/snapshot-manager.ts +0 -415
- package/core/domain/task-stack.ts +0 -578
- package/core/domain/velocity.ts +0 -470
- package/core/errors.ts +0 -335
- package/core/events/events.ts +0 -85
- package/core/events/index.ts +0 -8
- package/core/index.ts +0 -481
- package/core/infrastructure/agent-detector.ts +0 -135
- package/core/infrastructure/ai-provider.ts +0 -578
- package/core/infrastructure/author-detector.ts +0 -133
- package/core/infrastructure/capability-installer.ts +0 -76
- package/core/infrastructure/claude-agent.ts +0 -297
- package/core/infrastructure/command-installer.ts +0 -752
- package/core/infrastructure/config-manager.ts +0 -364
- package/core/infrastructure/editors-config.ts +0 -172
- package/core/infrastructure/path-manager.ts +0 -571
- package/core/infrastructure/performance-tracker.ts +0 -326
- package/core/infrastructure/permission-manager.ts +0 -289
- package/core/infrastructure/setup.ts +0 -1061
- package/core/infrastructure/update-checker.ts +0 -246
- package/core/integrations/issue-tracker/enricher.ts +0 -271
- package/core/integrations/issue-tracker/index.ts +0 -8
- package/core/integrations/issue-tracker/manager.ts +0 -286
- package/core/integrations/issue-tracker/types.ts +0 -310
- package/core/integrations/jira/cache.ts +0 -57
- package/core/integrations/jira/client.ts +0 -688
- package/core/integrations/jira/index.ts +0 -23
- package/core/integrations/jira/service.ts +0 -244
- package/core/integrations/linear/cache.ts +0 -68
- package/core/integrations/linear/client.ts +0 -436
- package/core/integrations/linear/index.ts +0 -20
- package/core/integrations/linear/service.ts +0 -260
- package/core/integrations/linear/sync.ts +0 -314
- package/core/outcomes/analyzer.ts +0 -286
- package/core/outcomes/index.ts +0 -34
- package/core/outcomes/recorder.ts +0 -195
- package/core/plugin/builtin/webhook.ts +0 -148
- package/core/plugin/hooks.ts +0 -315
- package/core/plugin/index.ts +0 -50
- package/core/plugin/loader.ts +0 -354
- package/core/plugin/registry.ts +0 -326
- package/core/schemas/agents.ts +0 -27
- package/core/schemas/analysis.ts +0 -530
- package/core/schemas/classification.ts +0 -91
- package/core/schemas/command-context.ts +0 -29
- package/core/schemas/enriched-task.ts +0 -291
- package/core/schemas/ideas.ts +0 -114
- package/core/schemas/index.ts +0 -53
- package/core/schemas/issues.ts +0 -159
- package/core/schemas/llm-output.ts +0 -170
- package/core/schemas/metrics.ts +0 -143
- package/core/schemas/model.ts +0 -153
- package/core/schemas/outcomes.ts +0 -487
- package/core/schemas/performance.ts +0 -128
- package/core/schemas/permissions.ts +0 -180
- package/core/schemas/prd.ts +0 -450
- package/core/schemas/project.ts +0 -57
- package/core/schemas/roadmap.ts +0 -322
- package/core/schemas/schemas.ts +0 -38
- package/core/schemas/shipped.ts +0 -109
- package/core/schemas/state.ts +0 -284
- package/core/schemas/velocity.ts +0 -103
- package/core/server/index.ts +0 -21
- package/core/server/routes-extended.ts +0 -566
- package/core/server/routes.ts +0 -176
- package/core/server/server.ts +0 -149
- package/core/server/sse.ts +0 -192
- package/core/services/agent-generator.ts +0 -385
- package/core/services/agent-service.ts +0 -168
- package/core/services/breakdown-service.ts +0 -124
- package/core/services/context-generator.ts +0 -445
- package/core/services/context-selector.ts +0 -429
- package/core/services/dependency-validator.ts +0 -318
- package/core/services/diff-generator.ts +0 -313
- package/core/services/doctor-service.ts +0 -423
- package/core/services/file-categorizer.ts +0 -448
- package/core/services/file-scorer.ts +0 -270
- package/core/services/git-analyzer.ts +0 -293
- package/core/services/hierarchical-agent-resolver.ts +0 -236
- package/core/services/hooks-service.ts +0 -685
- package/core/services/index.ts +0 -46
- package/core/services/local-state-generator.ts +0 -158
- package/core/services/memory-service.ts +0 -181
- package/core/services/nested-context-resolver.ts +0 -842
- package/core/services/project-index.ts +0 -911
- package/core/services/project-service.ts +0 -155
- package/core/services/session-tracker.ts +0 -287
- package/core/services/skill-installer.ts +0 -447
- package/core/services/skill-lock.ts +0 -132
- package/core/services/skill-service.ts +0 -306
- package/core/services/stack-detector.ts +0 -229
- package/core/services/staleness-checker.ts +0 -327
- package/core/services/sync-service.ts +0 -1515
- package/core/services/sync-verifier.ts +0 -253
- package/core/services/watch-service.ts +0 -312
- package/core/session/compaction.ts +0 -248
- package/core/session/index.ts +0 -35
- package/core/session/log-migration.ts +0 -88
- package/core/session/metrics.ts +0 -323
- package/core/session/session-log-manager.ts +0 -307
- package/core/session/task-session-manager.ts +0 -404
- package/core/session/utils.ts +0 -51
- package/core/storage/analysis-storage.ts +0 -373
- package/core/storage/archive-storage.ts +0 -205
- package/core/storage/database.ts +0 -575
- package/core/storage/ideas-storage.ts +0 -298
- package/core/storage/index-storage.ts +0 -523
- package/core/storage/index.ts +0 -79
- package/core/storage/metrics-storage.ts +0 -321
- package/core/storage/migrate-json.ts +0 -720
- package/core/storage/queue-storage.ts +0 -336
- package/core/storage/safe-reader.ts +0 -105
- package/core/storage/shipped-storage.ts +0 -253
- package/core/storage/state-storage.ts +0 -1035
- package/core/storage/storage-manager.ts +0 -205
- package/core/storage/storage.ts +0 -177
- package/core/storage/velocity-storage.ts +0 -149
- package/core/sync/auth-config.ts +0 -138
- package/core/sync/index.ts +0 -31
- package/core/sync/oauth-handler.ts +0 -143
- package/core/sync/sync-client.ts +0 -251
- package/core/sync/sync-manager.ts +0 -327
- package/core/tsconfig.json +0 -22
- package/core/types/agentic.ts +0 -760
- package/core/types/agents.ts +0 -150
- package/core/types/bus.ts +0 -193
- package/core/types/citations.ts +0 -22
- package/core/types/commands.ts +0 -399
- package/core/types/config.ts +0 -92
- package/core/types/core.ts +0 -96
- package/core/types/diff.ts +0 -41
- package/core/types/domain.ts +0 -71
- package/core/types/errors.ts +0 -111
- package/core/types/events.ts +0 -42
- package/core/types/fs.ts +0 -72
- package/core/types/index.ts +0 -510
- package/core/types/infrastructure.ts +0 -210
- package/core/types/integrations.ts +0 -31
- package/core/types/jira.ts +0 -51
- package/core/types/logger.ts +0 -17
- package/core/types/memory.ts +0 -313
- package/core/types/outcomes.ts +0 -190
- package/core/types/output.ts +0 -47
- package/core/types/plugin.ts +0 -25
- package/core/types/project-sync.ts +0 -129
- package/core/types/provider.ts +0 -163
- package/core/types/server.ts +0 -71
- package/core/types/services.ts +0 -84
- package/core/types/session.ts +0 -135
- package/core/types/stack.ts +0 -19
- package/core/types/storage.ts +0 -318
- package/core/types/sync-verifier.ts +0 -33
- package/core/types/sync.ts +0 -121
- package/core/types/task.ts +0 -72
- package/core/types/template.ts +0 -24
- package/core/types/utils.ts +0 -92
- package/core/types/workflow.ts +0 -23
- package/core/utils/agent-stream.ts +0 -140
- package/core/utils/animations.ts +0 -251
- package/core/utils/branding.ts +0 -88
- package/core/utils/cache.ts +0 -187
- package/core/utils/citations.ts +0 -39
- package/core/utils/collection-filters.ts +0 -209
- package/core/utils/date-helper.ts +0 -176
- package/core/utils/error-messages.ts +0 -38
- package/core/utils/file-helper.ts +0 -277
- package/core/utils/fs-helpers.ts +0 -14
- package/core/utils/help.ts +0 -314
- package/core/utils/jsonl-helper.ts +0 -290
- package/core/utils/keychain.ts +0 -127
- package/core/utils/logger.ts +0 -77
- package/core/utils/markdown-builder.ts +0 -280
- package/core/utils/next-steps.ts +0 -95
- package/core/utils/output.ts +0 -403
- package/core/utils/preserve-sections.ts +0 -218
- package/core/utils/project-commands.ts +0 -126
- package/core/utils/project-credentials.ts +0 -143
- package/core/utils/provider-cache.ts +0 -49
- package/core/utils/retry.ts +0 -318
- package/core/utils/runtime.ts +0 -108
- package/core/utils/session-helper.ts +0 -278
- package/core/utils/subtask-table.ts +0 -227
- package/core/utils/version.ts +0 -128
- package/core/wizard/index.ts +0 -13
- package/core/wizard/onboarding.ts +0 -633
- package/core/workflow/index.ts +0 -7
- package/core/workflow/state-machine.ts +0 -198
- package/core/workflow/workflow-preferences.ts +0 -294
- package/dist/core/infrastructure/command-installer.js +0 -1141
- package/dist/core/infrastructure/editors-config.js +0 -177
- package/dist/core/infrastructure/setup.js +0 -2244
- package/dist/core/utils/version.js +0 -141
- package/templates/agentic/agent-routing.md +0 -45
- package/templates/agentic/agents/uxui.md +0 -63
- package/templates/agentic/checklist-routing.md +0 -98
- package/templates/agentic/orchestrator.md +0 -68
- package/templates/agentic/task-fragmentation.md +0 -89
- package/templates/agents/AGENTS.md +0 -68
- package/templates/analysis/analyze.md +0 -84
- package/templates/analysis/patterns.md +0 -60
- package/templates/antigravity/SKILL.md +0 -39
- package/templates/architect/discovery.md +0 -67
- package/templates/architect/phases.md +0 -59
- package/templates/checklists/architecture.md +0 -28
- package/templates/checklists/code-quality.md +0 -28
- package/templates/checklists/data.md +0 -33
- package/templates/checklists/documentation.md +0 -33
- package/templates/checklists/infrastructure.md +0 -33
- package/templates/checklists/performance.md +0 -33
- package/templates/checklists/security.md +0 -33
- package/templates/checklists/testing.md +0 -33
- package/templates/checklists/ux-ui.md +0 -37
- package/templates/commands/analyze.md +0 -56
- package/templates/commands/auth.md +0 -234
- package/templates/commands/bug.md +0 -163
- package/templates/commands/cleanup.md +0 -19
- package/templates/commands/dash.md +0 -99
- package/templates/commands/design.md +0 -15
- package/templates/commands/done.md +0 -291
- package/templates/commands/enrich.md +0 -174
- package/templates/commands/git.md +0 -295
- package/templates/commands/history.md +0 -389
- package/templates/commands/idea.md +0 -88
- package/templates/commands/impact.md +0 -864
- package/templates/commands/init.md +0 -54
- package/templates/commands/jira.md +0 -278
- package/templates/commands/linear.md +0 -288
- package/templates/commands/merge.md +0 -206
- package/templates/commands/next.md +0 -80
- package/templates/commands/p.md +0 -67
- package/templates/commands/p.toml +0 -37
- package/templates/commands/pause.md +0 -136
- package/templates/commands/plan.md +0 -696
- package/templates/commands/prd.md +0 -356
- package/templates/commands/resume.md +0 -171
- package/templates/commands/review.md +0 -276
- package/templates/commands/serve.md +0 -118
- package/templates/commands/setup.md +0 -91
- package/templates/commands/ship.md +0 -475
- package/templates/commands/skill.md +0 -259
- package/templates/commands/spec.md +0 -218
- package/templates/commands/status.md +0 -207
- package/templates/commands/sync.md +0 -104
- package/templates/commands/task.md +0 -312
- package/templates/commands/test.md +0 -93
- package/templates/commands/update.md +0 -63
- package/templates/commands/verify.md +0 -204
- package/templates/commands/workflow.md +0 -150
- package/templates/config/skill-mappings.json +0 -82
- package/templates/context/dashboard.md +0 -256
- package/templates/context/roadmap.md +0 -221
- package/templates/cursor/commands/bug.md +0 -8
- package/templates/cursor/commands/done.md +0 -4
- package/templates/cursor/commands/pause.md +0 -6
- package/templates/cursor/commands/resume.md +0 -4
- package/templates/cursor/commands/ship.md +0 -8
- package/templates/cursor/commands/sync.md +0 -4
- package/templates/cursor/commands/task.md +0 -8
- package/templates/cursor/p.md +0 -29
- package/templates/cursor/router.mdc +0 -28
- package/templates/design/api.md +0 -95
- package/templates/design/architecture.md +0 -77
- package/templates/design/component.md +0 -89
- package/templates/design/database.md +0 -78
- package/templates/design/flow.md +0 -94
- package/templates/global/ANTIGRAVITY.md +0 -254
- package/templates/global/CLAUDE.md +0 -497
- package/templates/global/CURSOR.mdc +0 -266
- package/templates/global/GEMINI.md +0 -293
- package/templates/global/STORAGE-SPEC.md +0 -391
- package/templates/global/WINDSURF.md +0 -266
- package/templates/global/modules/CLAUDE-commands.md +0 -70
- package/templates/global/modules/CLAUDE-core.md +0 -105
- package/templates/global/modules/CLAUDE-git.md +0 -50
- package/templates/global/modules/CLAUDE-intelligence.md +0 -92
- package/templates/global/modules/CLAUDE-storage.md +0 -50
- package/templates/global/modules/module-config.json +0 -36
- package/templates/mcp-config.json +0 -19
- package/templates/permissions/default.jsonc +0 -60
- package/templates/permissions/permissive.jsonc +0 -49
- package/templates/permissions/strict.jsonc +0 -58
- package/templates/planning-methodology.md +0 -195
- package/templates/skills/code-review.md +0 -47
- package/templates/skills/debug.md +0 -61
- package/templates/skills/refactor.md +0 -47
- package/templates/subagents/agent-base.md +0 -20
- package/templates/subagents/domain/backend.md +0 -109
- package/templates/subagents/domain/database.md +0 -121
- package/templates/subagents/domain/devops.md +0 -152
- package/templates/subagents/domain/frontend.md +0 -103
- package/templates/subagents/domain/testing.md +0 -169
- package/templates/subagents/pm-expert.md +0 -366
- package/templates/subagents/workflow/chief-architect.md +0 -657
- package/templates/subagents/workflow/prjct-planner.md +0 -159
- package/templates/subagents/workflow/prjct-shipper.md +0 -188
- package/templates/subagents/workflow/prjct-workflow.md +0 -98
- package/templates/tools/bash.txt +0 -22
- package/templates/tools/edit.txt +0 -18
- package/templates/tools/glob.txt +0 -19
- package/templates/tools/grep.txt +0 -21
- package/templates/tools/read.txt +0 -14
- package/templates/tools/task.txt +0 -20
- package/templates/tools/webfetch.txt +0 -16
- package/templates/tools/websearch.txt +0 -18
- package/templates/tools/write.txt +0 -17
- package/templates/windsurf/router.md +0 -28
- package/templates/windsurf/workflows/bug.md +0 -8
- package/templates/windsurf/workflows/done.md +0 -4
- package/templates/windsurf/workflows/pause.md +0 -4
- package/templates/windsurf/workflows/resume.md +0 -4
- package/templates/windsurf/workflows/ship.md +0 -8
- package/templates/windsurf/workflows/sync.md +0 -4
- package/templates/windsurf/workflows/task.md +0 -8
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Outcome Recorder
|
|
3
|
-
*
|
|
4
|
-
* Records execution outcomes for learning and analysis.
|
|
5
|
-
* Appends to JSONL files for efficient streaming.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import path from 'node:path'
|
|
9
|
-
import pathManager from '../infrastructure/path-manager'
|
|
10
|
-
import { generateUUID } from '../schemas'
|
|
11
|
-
import type { Outcome, OutcomeFilter, OutcomeInput } from '../types'
|
|
12
|
-
import * as fileHelper from '../utils/file-helper'
|
|
13
|
-
|
|
14
|
-
const OUTCOMES_DIR = 'outcomes'
|
|
15
|
-
const OUTCOMES_FILE = 'outcomes.jsonl'
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* OutcomeRecorder - Records and retrieves execution outcomes.
|
|
19
|
-
*/
|
|
20
|
-
export class OutcomeRecorder {
|
|
21
|
-
/**
|
|
22
|
-
* Get outcomes directory path for a project.
|
|
23
|
-
*/
|
|
24
|
-
private getOutcomesDir(projectId: string): string {
|
|
25
|
-
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
26
|
-
return path.join(globalPath, OUTCOMES_DIR)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get outcomes file path for a project.
|
|
31
|
-
*/
|
|
32
|
-
private getOutcomesPath(projectId: string): string {
|
|
33
|
-
return path.join(this.getOutcomesDir(projectId), OUTCOMES_FILE)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Record an outcome.
|
|
38
|
-
*/
|
|
39
|
-
async record(projectId: string, input: OutcomeInput): Promise<Outcome> {
|
|
40
|
-
const outcome: Outcome = {
|
|
41
|
-
...input,
|
|
42
|
-
id: generateUUID(),
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const outcomesPath = this.getOutcomesPath(projectId)
|
|
46
|
-
|
|
47
|
-
// Ensure directory exists
|
|
48
|
-
await fileHelper.ensureDir(path.dirname(outcomesPath))
|
|
49
|
-
|
|
50
|
-
// Append to JSONL
|
|
51
|
-
await fileHelper.appendLine(outcomesPath, JSON.stringify(outcome))
|
|
52
|
-
|
|
53
|
-
return outcome
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Get all outcomes for a project.
|
|
58
|
-
*/
|
|
59
|
-
async getAll(projectId: string): Promise<Outcome[]> {
|
|
60
|
-
const outcomesPath = this.getOutcomesPath(projectId)
|
|
61
|
-
|
|
62
|
-
if (!(await fileHelper.fileExists(outcomesPath))) {
|
|
63
|
-
return []
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const content = await fileHelper.readFile(outcomesPath)
|
|
67
|
-
if (!content.trim()) {
|
|
68
|
-
return []
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return content
|
|
72
|
-
.trim()
|
|
73
|
-
.split('\n')
|
|
74
|
-
.filter((line) => line.trim())
|
|
75
|
-
.map((line) => JSON.parse(line) as Outcome)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Get outcomes matching a filter.
|
|
80
|
-
*/
|
|
81
|
-
async filter(projectId: string, filter: OutcomeFilter): Promise<Outcome[]> {
|
|
82
|
-
const all = await this.getAll(projectId)
|
|
83
|
-
|
|
84
|
-
return all.filter((outcome) => {
|
|
85
|
-
if (filter.sessionId && outcome.sessionId !== filter.sessionId) {
|
|
86
|
-
return false
|
|
87
|
-
}
|
|
88
|
-
if (filter.command && outcome.command !== filter.command) {
|
|
89
|
-
return false
|
|
90
|
-
}
|
|
91
|
-
if (filter.agent && outcome.agentUsed !== filter.agent) {
|
|
92
|
-
return false
|
|
93
|
-
}
|
|
94
|
-
if (filter.fromDate && outcome.startedAt < filter.fromDate) {
|
|
95
|
-
return false
|
|
96
|
-
}
|
|
97
|
-
if (filter.toDate && outcome.completedAt > filter.toDate) {
|
|
98
|
-
return false
|
|
99
|
-
}
|
|
100
|
-
if (filter.minQuality && outcome.qualityScore < filter.minQuality) {
|
|
101
|
-
return false
|
|
102
|
-
}
|
|
103
|
-
if (filter.tags && filter.tags.length > 0) {
|
|
104
|
-
const outcomeTags = outcome.tags || []
|
|
105
|
-
if (!filter.tags.some((tag) => outcomeTags.includes(tag))) {
|
|
106
|
-
return false
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return true
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Get recent outcomes (last N).
|
|
115
|
-
*/
|
|
116
|
-
async getRecent(projectId: string, count: number = 10): Promise<Outcome[]> {
|
|
117
|
-
const all = await this.getAll(projectId)
|
|
118
|
-
return all.slice(-count)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Get outcomes for a specific command.
|
|
123
|
-
*/
|
|
124
|
-
async getByCommand(projectId: string, command: string): Promise<Outcome[]> {
|
|
125
|
-
return this.filter(projectId, { command })
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Get outcomes for a specific agent.
|
|
130
|
-
*/
|
|
131
|
-
async getByAgent(projectId: string, agent: string): Promise<Outcome[]> {
|
|
132
|
-
return this.filter(projectId, { agent })
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Calculate estimate accuracy.
|
|
137
|
-
*/
|
|
138
|
-
async getEstimateAccuracy(projectId: string): Promise<number> {
|
|
139
|
-
const outcomes = await this.getAll(projectId)
|
|
140
|
-
|
|
141
|
-
if (outcomes.length === 0) {
|
|
142
|
-
return 0
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Count outcomes where variance was within 20%
|
|
146
|
-
const accurate = outcomes.filter((o) => {
|
|
147
|
-
if (!o.variance) return false
|
|
148
|
-
const variance = this.parseVariance(o.variance)
|
|
149
|
-
const estimated = this.parseDuration(o.estimatedDuration)
|
|
150
|
-
if (estimated === 0) return false
|
|
151
|
-
return Math.abs(variance) / estimated <= 0.2
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
return Math.round((accurate.length / outcomes.length) * 100)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Parse variance string to minutes.
|
|
159
|
-
* "+30m" → 30, "-15m" → -15
|
|
160
|
-
*/
|
|
161
|
-
private parseVariance(variance: string): number {
|
|
162
|
-
const match = variance.match(/^([+-])(\d+)([mh])$/)
|
|
163
|
-
if (!match) return 0
|
|
164
|
-
|
|
165
|
-
const sign = match[1] === '-' ? -1 : 1
|
|
166
|
-
const value = parseInt(match[2], 10)
|
|
167
|
-
const unit = match[3]
|
|
168
|
-
|
|
169
|
-
return sign * (unit === 'h' ? value * 60 : value)
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Parse duration string to minutes.
|
|
174
|
-
* "2h" → 120, "30m" → 30, "1h 30m" → 90
|
|
175
|
-
*/
|
|
176
|
-
private parseDuration(duration: string): number {
|
|
177
|
-
let minutes = 0
|
|
178
|
-
|
|
179
|
-
const hourMatch = duration.match(/(\d+)h/)
|
|
180
|
-
if (hourMatch) {
|
|
181
|
-
minutes += parseInt(hourMatch[1], 10) * 60
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const minMatch = duration.match(/(\d+)m/)
|
|
185
|
-
if (minMatch) {
|
|
186
|
-
minutes += parseInt(minMatch[1], 10)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return minutes
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Singleton instance
|
|
194
|
-
const outcomeRecorder = new OutcomeRecorder()
|
|
195
|
-
export default outcomeRecorder
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Webhook Plugin for prjct-cli
|
|
3
|
-
*
|
|
4
|
-
* Sends HTTP POST requests to configured webhooks on events.
|
|
5
|
-
* Useful for integrating with Slack, Discord, Zapier, etc.
|
|
6
|
-
*
|
|
7
|
-
* @version 1.0.0
|
|
8
|
-
*
|
|
9
|
-
* Configuration in prjct.config.json:
|
|
10
|
-
* {
|
|
11
|
-
* "plugins": ["webhook"],
|
|
12
|
-
* "webhook": {
|
|
13
|
-
* "url": "https://hooks.example.com/...",
|
|
14
|
-
* "events": ["session.completed", "feature.shipped"],
|
|
15
|
-
* "secret": "optional-signing-secret"
|
|
16
|
-
* }
|
|
17
|
-
* }
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import crypto from 'node:crypto'
|
|
21
|
-
import { EventTypes } from '../../bus'
|
|
22
|
-
import type { WebhookConfig, WebhookPayload, WebhookPluginContext } from '../../types'
|
|
23
|
-
import { getErrorMessage } from '../../types/fs'
|
|
24
|
-
import { HookPoints } from '../hooks'
|
|
25
|
-
|
|
26
|
-
const plugin = {
|
|
27
|
-
name: 'webhook',
|
|
28
|
-
version: '1.0.0',
|
|
29
|
-
description: 'Send HTTP webhooks on events',
|
|
30
|
-
|
|
31
|
-
// Plugin state
|
|
32
|
-
config: null as WebhookConfig | null,
|
|
33
|
-
enabled: false,
|
|
34
|
-
enabledEvents: [] as string[],
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Activate plugin
|
|
38
|
-
*/
|
|
39
|
-
async activate({ config }: WebhookPluginContext): Promise<void> {
|
|
40
|
-
plugin.config = config
|
|
41
|
-
|
|
42
|
-
if (!config.url) {
|
|
43
|
-
console.warn('[webhook] No URL configured, plugin disabled')
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
plugin.enabled = true
|
|
48
|
-
plugin.enabledEvents = config.events || [
|
|
49
|
-
EventTypes.SESSION_COMPLETED,
|
|
50
|
-
EventTypes.FEATURE_SHIPPED,
|
|
51
|
-
EventTypes.SNAPSHOT_CREATED,
|
|
52
|
-
]
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Deactivate plugin
|
|
57
|
-
*/
|
|
58
|
-
async deactivate(): Promise<void> {
|
|
59
|
-
plugin.enabled = false
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Event handlers
|
|
64
|
-
*/
|
|
65
|
-
events: {
|
|
66
|
-
[EventTypes.SESSION_COMPLETED]: async (data: unknown): Promise<void> => {
|
|
67
|
-
await plugin.sendWebhook('session.completed', data)
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
[EventTypes.FEATURE_SHIPPED]: async (data: unknown): Promise<void> => {
|
|
71
|
-
await plugin.sendWebhook('feature.shipped', data)
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
[EventTypes.SNAPSHOT_CREATED]: async (data: unknown): Promise<void> => {
|
|
75
|
-
await plugin.sendWebhook('snapshot.created', data)
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
[EventTypes.TASK_COMPLETED]: async (data: unknown): Promise<void> => {
|
|
79
|
-
await plugin.sendWebhook('task.completed', data)
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Hook handlers
|
|
85
|
-
*/
|
|
86
|
-
hooks: {
|
|
87
|
-
[HookPoints.AFTER_FEATURE_SHIP]: async (data: {
|
|
88
|
-
feature: string
|
|
89
|
-
version: string
|
|
90
|
-
timestamp: string
|
|
91
|
-
}): Promise<void> => {
|
|
92
|
-
await plugin.sendWebhook('feature.shipped', {
|
|
93
|
-
feature: data.feature,
|
|
94
|
-
version: data.version,
|
|
95
|
-
timestamp: data.timestamp,
|
|
96
|
-
})
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Send webhook request
|
|
102
|
-
*/
|
|
103
|
-
async sendWebhook(event: string, data: unknown): Promise<void> {
|
|
104
|
-
if (!plugin.enabled || !plugin.config?.url) return
|
|
105
|
-
|
|
106
|
-
// Check if this event should be sent
|
|
107
|
-
if (plugin.config.events && !plugin.config.events.includes(event)) {
|
|
108
|
-
return
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const payload: WebhookPayload = {
|
|
112
|
-
event,
|
|
113
|
-
timestamp: new Date().toISOString(),
|
|
114
|
-
source: 'prjct-cli',
|
|
115
|
-
data,
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
const headers: Record<string, string> = {
|
|
120
|
-
'Content-Type': 'application/json',
|
|
121
|
-
'User-Agent': 'prjct-cli/webhook',
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Add signature if secret is configured
|
|
125
|
-
if (plugin.config.secret) {
|
|
126
|
-
const signature = crypto
|
|
127
|
-
.createHmac('sha256', plugin.config.secret)
|
|
128
|
-
.update(JSON.stringify(payload))
|
|
129
|
-
.digest('hex')
|
|
130
|
-
headers['X-Prjct-Signature'] = `sha256=${signature}`
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const response = await fetch(plugin.config.url, {
|
|
134
|
-
method: 'POST',
|
|
135
|
-
headers,
|
|
136
|
-
body: JSON.stringify(payload),
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
if (!response.ok) {
|
|
140
|
-
console.error(`[webhook] Request failed: ${response.status}`)
|
|
141
|
-
}
|
|
142
|
-
} catch (error) {
|
|
143
|
-
console.error(`[webhook] Error sending webhook:`, getErrorMessage(error))
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export default plugin
|
package/core/plugin/hooks.ts
DELETED
|
@@ -1,315 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HookSystem - Plugin Lifecycle Hooks for prjct-cli
|
|
3
|
-
*
|
|
4
|
-
* Provides hook points for plugins to extend prjct functionality.
|
|
5
|
-
* Hooks can modify data, add side effects, or integrate with external services.
|
|
6
|
-
*
|
|
7
|
-
* @version 1.0.0
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { EventTypes, eventBus } from '../bus'
|
|
11
|
-
import { getErrorMessage } from '../types/fs'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Hook Points - Where plugins can intercept
|
|
15
|
-
*/
|
|
16
|
-
const HookPoints = {
|
|
17
|
-
// Before hooks (can modify data)
|
|
18
|
-
BEFORE_SESSION_START: 'before:session.start',
|
|
19
|
-
BEFORE_SESSION_COMPLETE: 'before:session.complete',
|
|
20
|
-
BEFORE_TASK_CREATE: 'before:task.create',
|
|
21
|
-
BEFORE_FEATURE_SHIP: 'before:feature.ship',
|
|
22
|
-
BEFORE_SNAPSHOT_CREATE: 'before:snapshot.create',
|
|
23
|
-
BEFORE_COMMIT: 'before:git.commit',
|
|
24
|
-
|
|
25
|
-
// After hooks (for side effects)
|
|
26
|
-
AFTER_SESSION_START: 'after:session.start',
|
|
27
|
-
AFTER_SESSION_COMPLETE: 'after:session.complete',
|
|
28
|
-
AFTER_TASK_CREATE: 'after:task.create',
|
|
29
|
-
AFTER_TASK_COMPLETE: 'after:task.complete',
|
|
30
|
-
AFTER_FEATURE_SHIP: 'after:feature.ship',
|
|
31
|
-
AFTER_IDEA_CAPTURE: 'after:idea.capture',
|
|
32
|
-
AFTER_SNAPSHOT_CREATE: 'after:snapshot.create',
|
|
33
|
-
AFTER_SNAPSHOT_RESTORE: 'after:snapshot.restore',
|
|
34
|
-
AFTER_COMMIT: 'after:git.commit',
|
|
35
|
-
AFTER_PUSH: 'after:git.push',
|
|
36
|
-
AFTER_SYNC: 'after:project.sync',
|
|
37
|
-
|
|
38
|
-
// Transform hooks (must return modified data)
|
|
39
|
-
TRANSFORM_COMMIT_MESSAGE: 'transform:commit.message',
|
|
40
|
-
TRANSFORM_TASK_DATA: 'transform:task.data',
|
|
41
|
-
TRANSFORM_METRICS: 'transform:metrics',
|
|
42
|
-
} as const
|
|
43
|
-
|
|
44
|
-
export type HookPoint = (typeof HookPoints)[keyof typeof HookPoints]
|
|
45
|
-
type HookHandler = (data: unknown, context?: unknown) => unknown | Promise<unknown>
|
|
46
|
-
|
|
47
|
-
interface HookEntry {
|
|
48
|
-
handler: HookHandler
|
|
49
|
-
pluginName: string
|
|
50
|
-
priority: number
|
|
51
|
-
id: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface HookRegisterOptions {
|
|
55
|
-
pluginName?: string
|
|
56
|
-
priority?: number
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface PluginHookEntry {
|
|
60
|
-
hookPoint: string
|
|
61
|
-
id: string
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
class HookSystem {
|
|
65
|
-
private hooks: Map<string, HookEntry[]>
|
|
66
|
-
private pluginHooks: Map<string, PluginHookEntry[]>
|
|
67
|
-
|
|
68
|
-
constructor() {
|
|
69
|
-
this.hooks = new Map()
|
|
70
|
-
this.pluginHooks = new Map()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Register a hook handler
|
|
75
|
-
*/
|
|
76
|
-
register(hookPoint: string, handler: HookHandler, options: HookRegisterOptions = {}): () => void {
|
|
77
|
-
const { pluginName = 'anonymous', priority = 10 } = options
|
|
78
|
-
|
|
79
|
-
if (!this.hooks.has(hookPoint)) {
|
|
80
|
-
this.hooks.set(hookPoint, [])
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const hookEntry: HookEntry = {
|
|
84
|
-
handler,
|
|
85
|
-
pluginName,
|
|
86
|
-
priority,
|
|
87
|
-
id: `${pluginName}:${Date.now()}`,
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.hooks.get(hookPoint)!.push(hookEntry)
|
|
91
|
-
|
|
92
|
-
// Sort by priority
|
|
93
|
-
this.hooks.get(hookPoint)!.sort((a, b) => a.priority - b.priority)
|
|
94
|
-
|
|
95
|
-
// Track by plugin
|
|
96
|
-
if (!this.pluginHooks.has(pluginName)) {
|
|
97
|
-
this.pluginHooks.set(pluginName, [])
|
|
98
|
-
}
|
|
99
|
-
this.pluginHooks.get(pluginName)!.push({ hookPoint, id: hookEntry.id })
|
|
100
|
-
|
|
101
|
-
// Return unregister function
|
|
102
|
-
return () => this.unregister(hookPoint, hookEntry.id)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Unregister a hook handler
|
|
107
|
-
*/
|
|
108
|
-
unregister(hookPoint: string, id: string): void {
|
|
109
|
-
const hooks = this.hooks.get(hookPoint)
|
|
110
|
-
if (hooks) {
|
|
111
|
-
const index = hooks.findIndex((h) => h.id === id)
|
|
112
|
-
if (index !== -1) {
|
|
113
|
-
hooks.splice(index, 1)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Unregister all hooks from a plugin
|
|
120
|
-
*/
|
|
121
|
-
unregisterPlugin(pluginName: string): void {
|
|
122
|
-
const pluginEntries = this.pluginHooks.get(pluginName)
|
|
123
|
-
if (pluginEntries) {
|
|
124
|
-
for (const entry of pluginEntries) {
|
|
125
|
-
this.unregister(entry.hookPoint, entry.id)
|
|
126
|
-
}
|
|
127
|
-
this.pluginHooks.delete(pluginName)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Execute a "before" hook (can modify data)
|
|
133
|
-
*/
|
|
134
|
-
async executeBefore(
|
|
135
|
-
hookPoint: string,
|
|
136
|
-
data: Record<string, unknown>
|
|
137
|
-
): Promise<Record<string, unknown>> {
|
|
138
|
-
const hooks = this.hooks.get(hookPoint) || []
|
|
139
|
-
let result = { ...data }
|
|
140
|
-
|
|
141
|
-
for (const hook of hooks) {
|
|
142
|
-
try {
|
|
143
|
-
const modified = await hook.handler(result)
|
|
144
|
-
if (modified !== undefined) {
|
|
145
|
-
result = { ...result, ...(modified as Record<string, unknown>) }
|
|
146
|
-
}
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, getErrorMessage(error))
|
|
149
|
-
// Continue with other hooks
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return result
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Execute an "after" hook (side effects only)
|
|
158
|
-
*/
|
|
159
|
-
async executeAfter(hookPoint: string, data: Record<string, unknown>): Promise<void> {
|
|
160
|
-
const hooks = this.hooks.get(hookPoint) || []
|
|
161
|
-
|
|
162
|
-
// Execute all hooks in parallel for after hooks
|
|
163
|
-
await Promise.allSettled(
|
|
164
|
-
hooks.map(async (hook) => {
|
|
165
|
-
try {
|
|
166
|
-
await hook.handler(data)
|
|
167
|
-
} catch (error) {
|
|
168
|
-
console.error(`Hook error [${hook.pluginName}] at ${hookPoint}:`, getErrorMessage(error))
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
// Emit corresponding event for plugins listening via EventBus
|
|
174
|
-
const eventType = this.hookToEvent(hookPoint)
|
|
175
|
-
if (eventType) {
|
|
176
|
-
await eventBus.emit(eventType, data)
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Execute a "transform" hook (must return modified value)
|
|
182
|
-
*/
|
|
183
|
-
async executeTransform<T>(
|
|
184
|
-
hookPoint: string,
|
|
185
|
-
value: T,
|
|
186
|
-
context: Record<string, unknown> = {}
|
|
187
|
-
): Promise<T> {
|
|
188
|
-
const hooks = this.hooks.get(hookPoint) || []
|
|
189
|
-
let result = value
|
|
190
|
-
|
|
191
|
-
for (const hook of hooks) {
|
|
192
|
-
try {
|
|
193
|
-
const transformed = await hook.handler(result, context)
|
|
194
|
-
if (transformed !== undefined) {
|
|
195
|
-
result = transformed as T
|
|
196
|
-
}
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error(
|
|
199
|
-
`Transform hook error [${hook.pluginName}] at ${hookPoint}:`,
|
|
200
|
-
getErrorMessage(error)
|
|
201
|
-
)
|
|
202
|
-
// Keep previous value on error
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return result
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Map hook point to event type
|
|
211
|
-
*/
|
|
212
|
-
hookToEvent(hookPoint: string): string | null {
|
|
213
|
-
const mapping: Record<string, string> = {
|
|
214
|
-
[HookPoints.AFTER_SESSION_START]: EventTypes.SESSION_STARTED,
|
|
215
|
-
[HookPoints.AFTER_SESSION_COMPLETE]: EventTypes.SESSION_COMPLETED,
|
|
216
|
-
[HookPoints.AFTER_TASK_CREATE]: EventTypes.TASK_CREATED,
|
|
217
|
-
[HookPoints.AFTER_TASK_COMPLETE]: EventTypes.TASK_COMPLETED,
|
|
218
|
-
[HookPoints.AFTER_FEATURE_SHIP]: EventTypes.FEATURE_SHIPPED,
|
|
219
|
-
[HookPoints.AFTER_IDEA_CAPTURE]: EventTypes.IDEA_CAPTURED,
|
|
220
|
-
[HookPoints.AFTER_SNAPSHOT_CREATE]: EventTypes.SNAPSHOT_CREATED,
|
|
221
|
-
[HookPoints.AFTER_SNAPSHOT_RESTORE]: EventTypes.SNAPSHOT_RESTORED,
|
|
222
|
-
[HookPoints.AFTER_COMMIT]: EventTypes.COMMIT_CREATED,
|
|
223
|
-
[HookPoints.AFTER_PUSH]: EventTypes.PUSH_COMPLETED,
|
|
224
|
-
[HookPoints.AFTER_SYNC]: EventTypes.PROJECT_SYNCED,
|
|
225
|
-
}
|
|
226
|
-
return mapping[hookPoint] || null
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Get all registered hooks for a point
|
|
231
|
-
*/
|
|
232
|
-
getHooks(hookPoint: string): Array<{ pluginName: string; priority: number }> {
|
|
233
|
-
return (this.hooks.get(hookPoint) || []).map((h) => ({
|
|
234
|
-
pluginName: h.pluginName,
|
|
235
|
-
priority: h.priority,
|
|
236
|
-
}))
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Get all hooks registered by a plugin
|
|
241
|
-
*/
|
|
242
|
-
getPluginHooks(pluginName: string): string[] {
|
|
243
|
-
const entries = this.pluginHooks.get(pluginName) || []
|
|
244
|
-
return entries.map((e) => e.hookPoint)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Check if a hook point has any handlers
|
|
249
|
-
*/
|
|
250
|
-
hasHooks(hookPoint: string): boolean {
|
|
251
|
-
const hooks = this.hooks.get(hookPoint)
|
|
252
|
-
return hooks !== undefined && hooks.length > 0
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/**
|
|
256
|
-
* Clear all hooks
|
|
257
|
-
*/
|
|
258
|
-
clear(): void {
|
|
259
|
-
this.hooks.clear()
|
|
260
|
-
this.pluginHooks.clear()
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Singleton instance
|
|
265
|
-
const hookSystem = new HookSystem()
|
|
266
|
-
|
|
267
|
-
// Convenience wrapper for common hook patterns
|
|
268
|
-
const hooks = {
|
|
269
|
-
/**
|
|
270
|
-
* Register a before hook
|
|
271
|
-
*/
|
|
272
|
-
before: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
273
|
-
const hookPoint = `before:${point}`
|
|
274
|
-
return hookSystem.register(hookPoint, handler, options)
|
|
275
|
-
},
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
* Register an after hook
|
|
279
|
-
*/
|
|
280
|
-
after: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
281
|
-
const hookPoint = `after:${point}`
|
|
282
|
-
return hookSystem.register(hookPoint, handler, options)
|
|
283
|
-
},
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Register a transform hook
|
|
287
|
-
*/
|
|
288
|
-
transform: (point: string, handler: HookHandler, options?: HookRegisterOptions) => {
|
|
289
|
-
const hookPoint = `transform:${point}`
|
|
290
|
-
return hookSystem.register(hookPoint, handler, options)
|
|
291
|
-
},
|
|
292
|
-
|
|
293
|
-
/**
|
|
294
|
-
* Execute before hooks
|
|
295
|
-
*/
|
|
296
|
-
runBefore: (point: string, data: Record<string, unknown>) => {
|
|
297
|
-
return hookSystem.executeBefore(`before:${point}`, data)
|
|
298
|
-
},
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* Execute after hooks
|
|
302
|
-
*/
|
|
303
|
-
runAfter: (point: string, data: Record<string, unknown>) => {
|
|
304
|
-
return hookSystem.executeAfter(`after:${point}`, data)
|
|
305
|
-
},
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Execute transform hooks
|
|
309
|
-
*/
|
|
310
|
-
runTransform: <T>(point: string, value: T, context?: Record<string, unknown>) => {
|
|
311
|
-
return hookSystem.executeTransform(`transform:${point}`, value, context)
|
|
312
|
-
},
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export { HookSystem, HookPoints, hookSystem, hooks }
|
package/core/plugin/index.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin System - Main Entry Point
|
|
3
|
-
*
|
|
4
|
-
* Exports all plugin-related functionality.
|
|
5
|
-
*
|
|
6
|
-
* @version 1.0.0
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { HookPoints, HookSystem, hookSystem, hooks } from './hooks'
|
|
10
|
-
import { PluginLoader, pluginLoader } from './loader'
|
|
11
|
-
import { PluginRegistry, pluginRegistry } from './registry'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Initialize the complete plugin system
|
|
15
|
-
*/
|
|
16
|
-
async function initializePlugins(
|
|
17
|
-
projectPath: string,
|
|
18
|
-
config: Record<string, unknown> = {}
|
|
19
|
-
): Promise<void> {
|
|
20
|
-
await pluginRegistry.initialize()
|
|
21
|
-
await pluginLoader.initialize(projectPath, config)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Shutdown the plugin system
|
|
26
|
-
*/
|
|
27
|
-
async function shutdownPlugins(): Promise<void> {
|
|
28
|
-
const plugins = pluginLoader.getAllPlugins()
|
|
29
|
-
|
|
30
|
-
for (const plugin of plugins) {
|
|
31
|
-
await pluginLoader.unloadPlugin(plugin.name)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export {
|
|
36
|
-
// Hook system
|
|
37
|
-
HookSystem,
|
|
38
|
-
HookPoints,
|
|
39
|
-
hookSystem,
|
|
40
|
-
hooks,
|
|
41
|
-
// Plugin loader
|
|
42
|
-
PluginLoader,
|
|
43
|
-
pluginLoader,
|
|
44
|
-
// Plugin registry
|
|
45
|
-
PluginRegistry,
|
|
46
|
-
pluginRegistry,
|
|
47
|
-
// Convenience functions
|
|
48
|
-
initializePlugins,
|
|
49
|
-
shutdownPlugins,
|
|
50
|
-
}
|