prjct-cli 1.22.0 → 1.24.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 +230 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct-core.mjs +1748 -0
- package/dist/bin/prjct.mjs +17 -36672
- package/dist/cli/linear.mjs +14 -0
- package/dist/daemon/entry.mjs +1429 -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,463 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* State Storage Task Feedback Tests (PRJ-272)
|
|
3
|
-
*
|
|
4
|
-
* Tests for the task-to-analysis feedback loop:
|
|
5
|
-
* - Feedback schema validation
|
|
6
|
-
* - Feedback persistence in task history
|
|
7
|
-
* - Feedback aggregation across tasks
|
|
8
|
-
* - Known gotchas promotion (2+ occurrences)
|
|
9
|
-
* - Backward compatibility (tasks without feedback)
|
|
10
|
-
* - Context injection (markdown with feedback)
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
|
|
14
|
-
import fs from 'node:fs/promises'
|
|
15
|
-
import os from 'node:os'
|
|
16
|
-
import path from 'node:path'
|
|
17
|
-
import pathManager from '../../infrastructure/path-manager'
|
|
18
|
-
import type { CurrentTask, StateJson, TaskFeedback } from '../../schemas/state'
|
|
19
|
-
import { TaskFeedbackSchema } from '../../schemas/state'
|
|
20
|
-
import { prjctDb } from '../../storage/database'
|
|
21
|
-
import { stateStorage } from '../../storage/state-storage'
|
|
22
|
-
|
|
23
|
-
// =============================================================================
|
|
24
|
-
// Test Setup
|
|
25
|
-
// =============================================================================
|
|
26
|
-
|
|
27
|
-
let tmpRoot: string | null = null
|
|
28
|
-
let testProjectId: string
|
|
29
|
-
|
|
30
|
-
const originalGetGlobalProjectPath = pathManager.getGlobalProjectPath.bind(pathManager)
|
|
31
|
-
const originalGetStoragePath = pathManager.getStoragePath.bind(pathManager)
|
|
32
|
-
const originalGetFilePath = pathManager.getFilePath.bind(pathManager)
|
|
33
|
-
|
|
34
|
-
beforeEach(async () => {
|
|
35
|
-
tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'prjct-feedback-test-'))
|
|
36
|
-
testProjectId = `test-feedback-${Date.now()}`
|
|
37
|
-
|
|
38
|
-
pathManager.getGlobalProjectPath = (projectId: string) => {
|
|
39
|
-
return path.join(tmpRoot!, projectId)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
pathManager.getStoragePath = (projectId: string, filename: string) => {
|
|
43
|
-
return path.join(tmpRoot!, projectId, 'storage', filename)
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
pathManager.getFilePath = (projectId: string, layer: string, filename: string) => {
|
|
47
|
-
return path.join(tmpRoot!, projectId, layer, filename)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const storagePath = pathManager.getStoragePath(testProjectId, '')
|
|
51
|
-
await fs.mkdir(storagePath, { recursive: true })
|
|
52
|
-
|
|
53
|
-
const syncPath = path.join(tmpRoot!, testProjectId, 'sync')
|
|
54
|
-
await fs.mkdir(syncPath, { recursive: true })
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
afterEach(async () => {
|
|
58
|
-
prjctDb.close()
|
|
59
|
-
|
|
60
|
-
pathManager.getGlobalProjectPath = originalGetGlobalProjectPath
|
|
61
|
-
pathManager.getStoragePath = originalGetStoragePath
|
|
62
|
-
pathManager.getFilePath = originalGetFilePath
|
|
63
|
-
|
|
64
|
-
if (tmpRoot) {
|
|
65
|
-
await fs.rm(tmpRoot, { recursive: true, force: true })
|
|
66
|
-
tmpRoot = null
|
|
67
|
-
}
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
// =============================================================================
|
|
71
|
-
// Helper Functions
|
|
72
|
-
// =============================================================================
|
|
73
|
-
|
|
74
|
-
function createMockTask(
|
|
75
|
-
overrides: Partial<CurrentTask> & Record<string, unknown> = {}
|
|
76
|
-
): CurrentTask {
|
|
77
|
-
return {
|
|
78
|
-
id: `task-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
|
|
79
|
-
description: 'Test task',
|
|
80
|
-
startedAt: new Date().toISOString(),
|
|
81
|
-
sessionId: `session-${Date.now()}`,
|
|
82
|
-
...overrides,
|
|
83
|
-
} as CurrentTask
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async function startAndCompleteWithFeedback(
|
|
87
|
-
projectId: string,
|
|
88
|
-
task: CurrentTask,
|
|
89
|
-
feedback?: TaskFeedback
|
|
90
|
-
): Promise<StateJson> {
|
|
91
|
-
await stateStorage.startTask(projectId, task)
|
|
92
|
-
await stateStorage.completeTask(projectId, feedback)
|
|
93
|
-
return await stateStorage.read(projectId)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// =============================================================================
|
|
97
|
-
// Tests: TaskFeedback Schema Validation
|
|
98
|
-
// =============================================================================
|
|
99
|
-
|
|
100
|
-
describe('TaskFeedback Schema', () => {
|
|
101
|
-
it('should validate a complete feedback object', () => {
|
|
102
|
-
const feedback: TaskFeedback = {
|
|
103
|
-
stackConfirmed: ['React 18', 'TypeScript strict mode'],
|
|
104
|
-
patternsDiscovered: ['API routes follow /api/v1/{resource} pattern'],
|
|
105
|
-
agentAccuracy: [{ agent: 'backend.md', rating: 'helpful', note: 'Good API patterns' }],
|
|
106
|
-
issuesEncountered: ['ESLint conflicts with Prettier'],
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const result = TaskFeedbackSchema.safeParse(feedback)
|
|
110
|
-
expect(result.success).toBe(true)
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
it('should validate an empty feedback object', () => {
|
|
114
|
-
const feedback: TaskFeedback = {}
|
|
115
|
-
|
|
116
|
-
const result = TaskFeedbackSchema.safeParse(feedback)
|
|
117
|
-
expect(result.success).toBe(true)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
it('should validate feedback with only patterns', () => {
|
|
121
|
-
const feedback: TaskFeedback = {
|
|
122
|
-
patternsDiscovered: ['Components use barrel exports'],
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const result = TaskFeedbackSchema.safeParse(feedback)
|
|
126
|
-
expect(result.success).toBe(true)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it('should reject invalid agent accuracy rating', () => {
|
|
130
|
-
const feedback = {
|
|
131
|
-
agentAccuracy: [{ agent: 'backend.md', rating: 'invalid_rating' }],
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const result = TaskFeedbackSchema.safeParse(feedback)
|
|
135
|
-
expect(result.success).toBe(false)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
it('should validate all agent accuracy rating values', () => {
|
|
139
|
-
for (const rating of ['helpful', 'neutral', 'inaccurate'] as const) {
|
|
140
|
-
const feedback: TaskFeedback = {
|
|
141
|
-
agentAccuracy: [{ agent: 'test.md', rating }],
|
|
142
|
-
}
|
|
143
|
-
const result = TaskFeedbackSchema.safeParse(feedback)
|
|
144
|
-
expect(result.success).toBe(true)
|
|
145
|
-
}
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
// =============================================================================
|
|
150
|
-
// Tests: Feedback Persistence in Task History
|
|
151
|
-
// =============================================================================
|
|
152
|
-
|
|
153
|
-
describe('Feedback Persistence', () => {
|
|
154
|
-
it('should store feedback in task history entry', async () => {
|
|
155
|
-
const task = createMockTask({ description: 'Task with feedback' })
|
|
156
|
-
const feedback: TaskFeedback = {
|
|
157
|
-
stackConfirmed: ['TypeScript'],
|
|
158
|
-
patternsDiscovered: ['Uses Hono framework'],
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const state = await startAndCompleteWithFeedback(testProjectId, task, feedback)
|
|
162
|
-
|
|
163
|
-
expect(state.taskHistory).toBeDefined()
|
|
164
|
-
expect(state.taskHistory!.length).toBe(1)
|
|
165
|
-
expect(state.taskHistory![0].feedback).toBeDefined()
|
|
166
|
-
expect(state.taskHistory![0].feedback?.stackConfirmed).toEqual(['TypeScript'])
|
|
167
|
-
expect(state.taskHistory![0].feedback?.patternsDiscovered).toEqual(['Uses Hono framework'])
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('should store task without feedback (backward compatible)', async () => {
|
|
171
|
-
const task = createMockTask({ description: 'Task without feedback' })
|
|
172
|
-
|
|
173
|
-
const state = await startAndCompleteWithFeedback(testProjectId, task)
|
|
174
|
-
|
|
175
|
-
expect(state.taskHistory).toBeDefined()
|
|
176
|
-
expect(state.taskHistory!.length).toBe(1)
|
|
177
|
-
expect(state.taskHistory![0].feedback).toBeUndefined()
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
it('should preserve feedback through FIFO eviction', async () => {
|
|
181
|
-
// Complete first task with feedback
|
|
182
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
183
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
184
|
-
await stateStorage.completeTask(testProjectId, {
|
|
185
|
-
patternsDiscovered: ['Pattern from task 1'],
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
// Complete second task with feedback
|
|
189
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
190
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
191
|
-
await stateStorage.completeTask(testProjectId, {
|
|
192
|
-
patternsDiscovered: ['Pattern from task 2'],
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
const state = await stateStorage.read(testProjectId)
|
|
196
|
-
expect(state.taskHistory!.length).toBe(2)
|
|
197
|
-
// Most recent first (FIFO)
|
|
198
|
-
expect(state.taskHistory![0].feedback?.patternsDiscovered).toEqual(['Pattern from task 2'])
|
|
199
|
-
expect(state.taskHistory![1].feedback?.patternsDiscovered).toEqual(['Pattern from task 1'])
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
it('should store full feedback with all fields', async () => {
|
|
203
|
-
const task = createMockTask({ description: 'Full feedback task' })
|
|
204
|
-
const feedback: TaskFeedback = {
|
|
205
|
-
stackConfirmed: ['React 18', 'TypeScript'],
|
|
206
|
-
patternsDiscovered: ['API routes use /api/v1/{resource}', 'Barrel exports'],
|
|
207
|
-
agentAccuracy: [
|
|
208
|
-
{ agent: 'backend.md', rating: 'helpful', note: 'Good patterns' },
|
|
209
|
-
{ agent: 'frontend.md', rating: 'inaccurate', note: 'Missing Tailwind' },
|
|
210
|
-
],
|
|
211
|
-
issuesEncountered: ['ESLint conflicts with Prettier'],
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
const state = await startAndCompleteWithFeedback(testProjectId, task, feedback)
|
|
215
|
-
|
|
216
|
-
const stored = state.taskHistory![0].feedback!
|
|
217
|
-
expect(stored.stackConfirmed).toEqual(['React 18', 'TypeScript'])
|
|
218
|
-
expect(stored.patternsDiscovered).toEqual([
|
|
219
|
-
'API routes use /api/v1/{resource}',
|
|
220
|
-
'Barrel exports',
|
|
221
|
-
])
|
|
222
|
-
expect(stored.agentAccuracy).toHaveLength(2)
|
|
223
|
-
expect(stored.agentAccuracy![0].rating).toBe('helpful')
|
|
224
|
-
expect(stored.agentAccuracy![1].rating).toBe('inaccurate')
|
|
225
|
-
expect(stored.issuesEncountered).toEqual(['ESLint conflicts with Prettier'])
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
// =============================================================================
|
|
230
|
-
// Tests: Feedback Aggregation
|
|
231
|
-
// =============================================================================
|
|
232
|
-
|
|
233
|
-
describe('Feedback Aggregation', () => {
|
|
234
|
-
it('should aggregate patterns from multiple tasks', async () => {
|
|
235
|
-
// Task 1
|
|
236
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
237
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
238
|
-
await stateStorage.completeTask(testProjectId, {
|
|
239
|
-
patternsDiscovered: ['Pattern A'],
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
// Task 2
|
|
243
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
244
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
245
|
-
await stateStorage.completeTask(testProjectId, {
|
|
246
|
-
patternsDiscovered: ['Pattern B'],
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
250
|
-
expect(aggregated.patternsDiscovered).toContain('Pattern A')
|
|
251
|
-
expect(aggregated.patternsDiscovered).toContain('Pattern B')
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
it('should deduplicate patterns', async () => {
|
|
255
|
-
// Both tasks discover the same pattern
|
|
256
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
257
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
258
|
-
await stateStorage.completeTask(testProjectId, {
|
|
259
|
-
patternsDiscovered: ['Same pattern'],
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
263
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
264
|
-
await stateStorage.completeTask(testProjectId, {
|
|
265
|
-
patternsDiscovered: ['Same pattern'],
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
269
|
-
expect(aggregated.patternsDiscovered).toEqual(['Same pattern'])
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
it('should deduplicate stack confirmations', async () => {
|
|
273
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
274
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
275
|
-
await stateStorage.completeTask(testProjectId, {
|
|
276
|
-
stackConfirmed: ['TypeScript', 'React'],
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
280
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
281
|
-
await stateStorage.completeTask(testProjectId, {
|
|
282
|
-
stackConfirmed: ['TypeScript', 'Next.js'],
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
286
|
-
expect(aggregated.stackConfirmed).toContain('TypeScript')
|
|
287
|
-
expect(aggregated.stackConfirmed).toContain('React')
|
|
288
|
-
expect(aggregated.stackConfirmed).toContain('Next.js')
|
|
289
|
-
// TypeScript should not be duplicated
|
|
290
|
-
expect(aggregated.stackConfirmed.filter((s) => s === 'TypeScript')).toHaveLength(1)
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
it('should promote recurring issues to known gotchas', async () => {
|
|
294
|
-
// Same issue encountered twice
|
|
295
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
296
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
297
|
-
await stateStorage.completeTask(testProjectId, {
|
|
298
|
-
issuesEncountered: ['ESLint conflicts with Prettier'],
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
302
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
303
|
-
await stateStorage.completeTask(testProjectId, {
|
|
304
|
-
issuesEncountered: ['ESLint conflicts with Prettier'],
|
|
305
|
-
})
|
|
306
|
-
|
|
307
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
308
|
-
expect(aggregated.knownGotchas).toContain('ESLint conflicts with Prettier')
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
it('should NOT promote single-occurrence issues to gotchas', async () => {
|
|
312
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
313
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
314
|
-
await stateStorage.completeTask(testProjectId, {
|
|
315
|
-
issuesEncountered: ['One-time issue'],
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
319
|
-
expect(aggregated.issuesEncountered).toContain('One-time issue')
|
|
320
|
-
expect(aggregated.knownGotchas).not.toContain('One-time issue')
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
it('should aggregate agent accuracy across tasks', async () => {
|
|
324
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
325
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
326
|
-
await stateStorage.completeTask(testProjectId, {
|
|
327
|
-
agentAccuracy: [{ agent: 'backend.md', rating: 'helpful' }],
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
331
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
332
|
-
await stateStorage.completeTask(testProjectId, {
|
|
333
|
-
agentAccuracy: [{ agent: 'backend.md', rating: 'inaccurate', note: 'Missing Hono context' }],
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
337
|
-
expect(aggregated.agentAccuracy).toHaveLength(2)
|
|
338
|
-
expect(aggregated.agentAccuracy[0].agent).toBe('backend.md')
|
|
339
|
-
expect(aggregated.agentAccuracy[1].agent).toBe('backend.md')
|
|
340
|
-
})
|
|
341
|
-
|
|
342
|
-
it('should return empty aggregation when no feedback exists', async () => {
|
|
343
|
-
// Complete task without feedback
|
|
344
|
-
const task = createMockTask({ description: 'No feedback' })
|
|
345
|
-
await stateStorage.startTask(testProjectId, task)
|
|
346
|
-
await stateStorage.completeTask(testProjectId)
|
|
347
|
-
|
|
348
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
349
|
-
expect(aggregated.stackConfirmed).toEqual([])
|
|
350
|
-
expect(aggregated.patternsDiscovered).toEqual([])
|
|
351
|
-
expect(aggregated.agentAccuracy).toEqual([])
|
|
352
|
-
expect(aggregated.issuesEncountered).toEqual([])
|
|
353
|
-
expect(aggregated.knownGotchas).toEqual([])
|
|
354
|
-
})
|
|
355
|
-
|
|
356
|
-
it('should return empty aggregation when no tasks exist', async () => {
|
|
357
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
358
|
-
expect(aggregated.stackConfirmed).toEqual([])
|
|
359
|
-
expect(aggregated.patternsDiscovered).toEqual([])
|
|
360
|
-
expect(aggregated.knownGotchas).toEqual([])
|
|
361
|
-
})
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
// =============================================================================
|
|
365
|
-
// Tests: Context Injection (Markdown Generation)
|
|
366
|
-
// =============================================================================
|
|
367
|
-
|
|
368
|
-
describe('Feedback in Markdown Context', () => {
|
|
369
|
-
it('should include patterns in task history markdown', async () => {
|
|
370
|
-
const task = createMockTask({ description: 'Task with patterns' })
|
|
371
|
-
await stateStorage.startTask(testProjectId, task)
|
|
372
|
-
await stateStorage.completeTask(testProjectId, {
|
|
373
|
-
patternsDiscovered: ['Uses barrel exports'],
|
|
374
|
-
})
|
|
375
|
-
|
|
376
|
-
const state = await stateStorage.read(testProjectId)
|
|
377
|
-
// Access the private toMarkdown via the generated context
|
|
378
|
-
const md = (stateStorage as any).toMarkdown(state)
|
|
379
|
-
|
|
380
|
-
expect(md).toContain('Patterns: Uses barrel exports')
|
|
381
|
-
})
|
|
382
|
-
|
|
383
|
-
it('should include gotchas in task history markdown', async () => {
|
|
384
|
-
const task = createMockTask({ description: 'Task with gotchas' })
|
|
385
|
-
await stateStorage.startTask(testProjectId, task)
|
|
386
|
-
await stateStorage.completeTask(testProjectId, {
|
|
387
|
-
issuesEncountered: ['Port 3000 already in use'],
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
const state = await stateStorage.read(testProjectId)
|
|
391
|
-
const md = (stateStorage as any).toMarkdown(state)
|
|
392
|
-
|
|
393
|
-
expect(md).toContain('Gotchas: Port 3000 already in use')
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
it('should NOT show feedback section when feedback is empty', async () => {
|
|
397
|
-
const task = createMockTask({ description: 'Task without feedback' })
|
|
398
|
-
await stateStorage.startTask(testProjectId, task)
|
|
399
|
-
await stateStorage.completeTask(testProjectId)
|
|
400
|
-
|
|
401
|
-
const state = await stateStorage.read(testProjectId)
|
|
402
|
-
const md = (stateStorage as any).toMarkdown(state)
|
|
403
|
-
|
|
404
|
-
expect(md).not.toContain('Patterns:')
|
|
405
|
-
expect(md).not.toContain('Gotchas:')
|
|
406
|
-
})
|
|
407
|
-
})
|
|
408
|
-
|
|
409
|
-
// =============================================================================
|
|
410
|
-
// Tests: Mixed Feedback and Non-Feedback Tasks
|
|
411
|
-
// =============================================================================
|
|
412
|
-
|
|
413
|
-
describe('Mixed Tasks (with and without feedback)', () => {
|
|
414
|
-
it('should handle mix of tasks with and without feedback', async () => {
|
|
415
|
-
// Task 1: with feedback
|
|
416
|
-
const task1 = createMockTask({ description: 'With feedback' })
|
|
417
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
418
|
-
await stateStorage.completeTask(testProjectId, {
|
|
419
|
-
patternsDiscovered: ['Pattern from task 1'],
|
|
420
|
-
})
|
|
421
|
-
|
|
422
|
-
// Task 2: without feedback
|
|
423
|
-
const task2 = createMockTask({ description: 'Without feedback' })
|
|
424
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
425
|
-
await stateStorage.completeTask(testProjectId)
|
|
426
|
-
|
|
427
|
-
// Task 3: with feedback
|
|
428
|
-
const task3 = createMockTask({ description: 'With feedback again' })
|
|
429
|
-
await stateStorage.startTask(testProjectId, task3)
|
|
430
|
-
await stateStorage.completeTask(testProjectId, {
|
|
431
|
-
patternsDiscovered: ['Pattern from task 3'],
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
435
|
-
expect(aggregated.patternsDiscovered).toContain('Pattern from task 1')
|
|
436
|
-
expect(aggregated.patternsDiscovered).toContain('Pattern from task 3')
|
|
437
|
-
expect(aggregated.patternsDiscovered).toHaveLength(2)
|
|
438
|
-
})
|
|
439
|
-
|
|
440
|
-
it('should correctly count occurrences for gotcha promotion with mixed tasks', async () => {
|
|
441
|
-
// Task 1: encounters issue
|
|
442
|
-
const task1 = createMockTask({ description: 'Task 1' })
|
|
443
|
-
await stateStorage.startTask(testProjectId, task1)
|
|
444
|
-
await stateStorage.completeTask(testProjectId, {
|
|
445
|
-
issuesEncountered: ['Build fails on M1'],
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
// Task 2: no feedback
|
|
449
|
-
const task2 = createMockTask({ description: 'Task 2' })
|
|
450
|
-
await stateStorage.startTask(testProjectId, task2)
|
|
451
|
-
await stateStorage.completeTask(testProjectId)
|
|
452
|
-
|
|
453
|
-
// Task 3: encounters same issue
|
|
454
|
-
const task3 = createMockTask({ description: 'Task 3' })
|
|
455
|
-
await stateStorage.startTask(testProjectId, task3)
|
|
456
|
-
await stateStorage.completeTask(testProjectId, {
|
|
457
|
-
issuesEncountered: ['Build fails on M1'],
|
|
458
|
-
})
|
|
459
|
-
|
|
460
|
-
const aggregated = await stateStorage.getAggregatedFeedback(testProjectId)
|
|
461
|
-
expect(aggregated.knownGotchas).toContain('Build fails on M1')
|
|
462
|
-
})
|
|
463
|
-
})
|