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,469 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* State Storage Task History Tests
|
|
3
|
-
*
|
|
4
|
-
* Tests for task history functionality in StateStorage:
|
|
5
|
-
* - Task history push on completion
|
|
6
|
-
* - FIFO eviction (max 20 entries)
|
|
7
|
-
* - Backward compatibility (undefined taskHistory)
|
|
8
|
-
* - Accessor methods (getTaskHistory, getMostRecentTask, getTaskHistoryByType)
|
|
9
|
-
* - Context injection (markdown generation with filtering)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { afterEach, beforeEach, describe, expect, it } from 'bun:test'
|
|
13
|
-
import fs from 'node:fs/promises'
|
|
14
|
-
import os from 'node:os'
|
|
15
|
-
import path from 'node:path'
|
|
16
|
-
import pathManager from '../../infrastructure/path-manager'
|
|
17
|
-
import type { CurrentTask, StateJson } from '../../schemas/state'
|
|
18
|
-
import { prjctDb } from '../../storage/database'
|
|
19
|
-
import { stateStorage } from '../../storage/state-storage'
|
|
20
|
-
|
|
21
|
-
// =============================================================================
|
|
22
|
-
// Test Setup
|
|
23
|
-
// =============================================================================
|
|
24
|
-
|
|
25
|
-
let tmpRoot: string | null = null
|
|
26
|
-
let testProjectId: string
|
|
27
|
-
|
|
28
|
-
// Mock pathManager to use temp directory
|
|
29
|
-
const originalGetGlobalProjectPath = pathManager.getGlobalProjectPath.bind(pathManager)
|
|
30
|
-
const originalGetStoragePath = pathManager.getStoragePath.bind(pathManager)
|
|
31
|
-
const originalGetFilePath = pathManager.getFilePath.bind(pathManager)
|
|
32
|
-
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
// Create temp directory for test isolation
|
|
35
|
-
tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'prjct-history-test-'))
|
|
36
|
-
testProjectId = `test-history-${Date.now()}`
|
|
37
|
-
|
|
38
|
-
// Mock pathManager to use temp directory
|
|
39
|
-
pathManager.getGlobalProjectPath = (projectId: string) => {
|
|
40
|
-
return path.join(tmpRoot!, projectId)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
pathManager.getStoragePath = (projectId: string, filename: string) => {
|
|
44
|
-
return path.join(tmpRoot!, projectId, 'storage', filename)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
pathManager.getFilePath = (projectId: string, layer: string, filename: string) => {
|
|
48
|
-
return path.join(tmpRoot!, projectId, layer, filename)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Create storage and sync directories
|
|
52
|
-
const storagePath = pathManager.getStoragePath(testProjectId, '')
|
|
53
|
-
await fs.mkdir(storagePath, { recursive: true })
|
|
54
|
-
|
|
55
|
-
const syncPath = path.join(tmpRoot!, testProjectId, 'sync')
|
|
56
|
-
await fs.mkdir(syncPath, { recursive: true })
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
afterEach(async () => {
|
|
60
|
-
// Close SQLite connections before cleanup
|
|
61
|
-
prjctDb.close()
|
|
62
|
-
|
|
63
|
-
// Restore original pathManager methods
|
|
64
|
-
pathManager.getGlobalProjectPath = originalGetGlobalProjectPath
|
|
65
|
-
pathManager.getStoragePath = originalGetStoragePath
|
|
66
|
-
pathManager.getFilePath = originalGetFilePath
|
|
67
|
-
|
|
68
|
-
// Clean up temp directory
|
|
69
|
-
if (tmpRoot) {
|
|
70
|
-
await fs.rm(tmpRoot, { recursive: true, force: true })
|
|
71
|
-
tmpRoot = null
|
|
72
|
-
}
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
// =============================================================================
|
|
76
|
-
// Helper Functions
|
|
77
|
-
// =============================================================================
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Create a mock task for testing
|
|
81
|
-
*/
|
|
82
|
-
function createMockTask(
|
|
83
|
-
overrides: Partial<CurrentTask> & Record<string, unknown> = {}
|
|
84
|
-
): CurrentTask {
|
|
85
|
-
return {
|
|
86
|
-
id: `task-${Date.now()}`,
|
|
87
|
-
description: 'Test task',
|
|
88
|
-
startedAt: new Date().toISOString(),
|
|
89
|
-
sessionId: `session-${Date.now()}`,
|
|
90
|
-
...overrides,
|
|
91
|
-
} as CurrentTask
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Complete a task and return the state
|
|
96
|
-
*/
|
|
97
|
-
async function completeTaskAndGetState(projectId: string, task: CurrentTask): Promise<StateJson> {
|
|
98
|
-
// Start the task
|
|
99
|
-
await stateStorage.startTask(projectId, task)
|
|
100
|
-
|
|
101
|
-
// Complete the task
|
|
102
|
-
await stateStorage.completeTask(projectId)
|
|
103
|
-
|
|
104
|
-
// Return the state
|
|
105
|
-
return await stateStorage.read(projectId)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// =============================================================================
|
|
109
|
-
// Tests: Task History Push on Completion
|
|
110
|
-
// =============================================================================
|
|
111
|
-
|
|
112
|
-
describe('Task History - Push on Completion', () => {
|
|
113
|
-
it('should add completed task to taskHistory array', async () => {
|
|
114
|
-
const task = createMockTask({
|
|
115
|
-
description: 'Test task 1',
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
const state = await completeTaskAndGetState(testProjectId, task)
|
|
119
|
-
|
|
120
|
-
expect(state.taskHistory).toBeDefined()
|
|
121
|
-
expect(state.taskHistory?.length).toBe(1)
|
|
122
|
-
expect(state.taskHistory![0].title).toBe('Test task 1')
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
it('should include all required metadata in history entry', async () => {
|
|
126
|
-
const task = createMockTask({
|
|
127
|
-
description: 'Test task with metadata',
|
|
128
|
-
linearId: 'PRJ-123',
|
|
129
|
-
linearUuid: 'uuid-123',
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
const state = await completeTaskAndGetState(testProjectId, task)
|
|
133
|
-
|
|
134
|
-
const entry = state.taskHistory![0]
|
|
135
|
-
expect(entry.taskId).toBe(task.id)
|
|
136
|
-
expect(entry.title).toBe('Test task with metadata')
|
|
137
|
-
expect(entry.startedAt).toBeDefined() // startedAt is set by startTask()
|
|
138
|
-
expect(entry.completedAt).toBeDefined()
|
|
139
|
-
expect(entry.subtaskCount).toBe(0)
|
|
140
|
-
expect(entry.subtaskSummaries).toEqual([])
|
|
141
|
-
expect(entry.outcome).toBe('Task completed')
|
|
142
|
-
expect(entry.linearId).toBe('PRJ-123')
|
|
143
|
-
expect(entry.linearUuid).toBe('uuid-123')
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
it('should extract subtask summaries from completed task', async () => {
|
|
147
|
-
const task = createMockTask({
|
|
148
|
-
description: 'Task with subtasks',
|
|
149
|
-
subtasks: [
|
|
150
|
-
{
|
|
151
|
-
id: 'subtask-1',
|
|
152
|
-
description: 'First subtask',
|
|
153
|
-
domain: 'backend',
|
|
154
|
-
agent: 'backend.md',
|
|
155
|
-
status: 'completed',
|
|
156
|
-
dependsOn: [],
|
|
157
|
-
summary: {
|
|
158
|
-
title: 'Subtask 1 Complete',
|
|
159
|
-
description: 'Did some work',
|
|
160
|
-
filesChanged: [{ path: 'file1.ts', action: 'modified' }],
|
|
161
|
-
whatWasDone: ['Made changes'],
|
|
162
|
-
outputForNextAgent: 'Ready for next step',
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
id: 'subtask-2',
|
|
167
|
-
description: 'Second subtask',
|
|
168
|
-
domain: 'backend',
|
|
169
|
-
agent: 'backend.md',
|
|
170
|
-
status: 'pending',
|
|
171
|
-
dependsOn: [],
|
|
172
|
-
},
|
|
173
|
-
],
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
const state = await completeTaskAndGetState(testProjectId, task)
|
|
177
|
-
|
|
178
|
-
const entry = state.taskHistory![0]
|
|
179
|
-
expect(entry.subtaskCount).toBe(2)
|
|
180
|
-
expect(entry.subtaskSummaries.length).toBe(1) // Only completed with summary
|
|
181
|
-
expect(entry.subtaskSummaries[0].title).toBe('Subtask 1 Complete')
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
it('should preserve order - newest entries first', async () => {
|
|
185
|
-
// Complete 3 tasks
|
|
186
|
-
for (let i = 1; i <= 3; i++) {
|
|
187
|
-
const task = createMockTask({
|
|
188
|
-
description: `Task ${i}`,
|
|
189
|
-
})
|
|
190
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const state = await stateStorage.read(testProjectId)
|
|
194
|
-
|
|
195
|
-
expect(state.taskHistory?.length).toBe(3)
|
|
196
|
-
expect(state.taskHistory![0].title).toBe('Task 3') // Newest first
|
|
197
|
-
expect(state.taskHistory![1].title).toBe('Task 2')
|
|
198
|
-
expect(state.taskHistory![2].title).toBe('Task 1') // Oldest last
|
|
199
|
-
})
|
|
200
|
-
})
|
|
201
|
-
|
|
202
|
-
// =============================================================================
|
|
203
|
-
// Tests: FIFO Eviction
|
|
204
|
-
// =============================================================================
|
|
205
|
-
|
|
206
|
-
describe('Task History - FIFO Eviction', () => {
|
|
207
|
-
it('should enforce max 20 entries', async () => {
|
|
208
|
-
// Complete 25 tasks
|
|
209
|
-
for (let i = 1; i <= 25; i++) {
|
|
210
|
-
const task = createMockTask({
|
|
211
|
-
description: `Task ${i}`,
|
|
212
|
-
})
|
|
213
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const state = await stateStorage.read(testProjectId)
|
|
217
|
-
|
|
218
|
-
expect(state.taskHistory?.length).toBe(20) // Max 20
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('should drop oldest entries when exceeding limit', async () => {
|
|
222
|
-
// Complete 22 tasks
|
|
223
|
-
for (let i = 1; i <= 22; i++) {
|
|
224
|
-
const task = createMockTask({
|
|
225
|
-
description: `Task ${i}`,
|
|
226
|
-
})
|
|
227
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const state = await stateStorage.read(testProjectId)
|
|
231
|
-
|
|
232
|
-
expect(state.taskHistory?.length).toBe(20)
|
|
233
|
-
expect(state.taskHistory![0].title).toBe('Task 22') // Newest
|
|
234
|
-
expect(state.taskHistory![19].title).toBe('Task 3') // Oldest kept
|
|
235
|
-
// Task 1 and Task 2 should be dropped
|
|
236
|
-
})
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
// =============================================================================
|
|
240
|
-
// Tests: Backward Compatibility
|
|
241
|
-
// =============================================================================
|
|
242
|
-
|
|
243
|
-
describe('Task History - Backward Compatibility', () => {
|
|
244
|
-
it('should initialize taskHistory as empty array when undefined', async () => {
|
|
245
|
-
// Read state before any tasks (should use default)
|
|
246
|
-
const state = await stateStorage.read(testProjectId)
|
|
247
|
-
|
|
248
|
-
expect(state.taskHistory).toBeDefined()
|
|
249
|
-
expect(Array.isArray(state.taskHistory)).toBe(true)
|
|
250
|
-
expect(state.taskHistory?.length).toBe(0)
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
it('should handle missing taskHistory field in existing state', async () => {
|
|
254
|
-
// Manually write state without taskHistory field
|
|
255
|
-
const stateFile = pathManager.getStoragePath(testProjectId, 'state.json')
|
|
256
|
-
|
|
257
|
-
await fs.writeFile(
|
|
258
|
-
stateFile,
|
|
259
|
-
JSON.stringify({
|
|
260
|
-
currentTask: null,
|
|
261
|
-
pausedTasks: [],
|
|
262
|
-
lastUpdated: new Date().toISOString(),
|
|
263
|
-
// No taskHistory field
|
|
264
|
-
})
|
|
265
|
-
)
|
|
266
|
-
|
|
267
|
-
// Complete a task - should work without error
|
|
268
|
-
const task = createMockTask({ description: 'New task' })
|
|
269
|
-
const state = await completeTaskAndGetState(testProjectId, task)
|
|
270
|
-
|
|
271
|
-
expect(state.taskHistory).toBeDefined()
|
|
272
|
-
expect(state.taskHistory?.length).toBe(1)
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
// =============================================================================
|
|
277
|
-
// Tests: Accessor Methods
|
|
278
|
-
// =============================================================================
|
|
279
|
-
|
|
280
|
-
describe('Task History - Accessor Methods', () => {
|
|
281
|
-
beforeEach(async () => {
|
|
282
|
-
// Setup: Complete 3 tasks with different classifications
|
|
283
|
-
const tasks = [
|
|
284
|
-
{ description: 'Feature task 1', type: 'feature' },
|
|
285
|
-
{ description: 'Bug fix', type: 'bug' },
|
|
286
|
-
{ description: 'Feature task 2', type: 'feature' },
|
|
287
|
-
]
|
|
288
|
-
|
|
289
|
-
for (const taskData of tasks) {
|
|
290
|
-
const task = createMockTask(taskData)
|
|
291
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
292
|
-
}
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
it('getTaskHistory() should return full history', async () => {
|
|
296
|
-
const history = await stateStorage.getTaskHistory(testProjectId)
|
|
297
|
-
|
|
298
|
-
expect(history.length).toBe(3)
|
|
299
|
-
expect(history[0].title).toBe('Feature task 2') // Newest first
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
it('getMostRecentTask() should return latest entry', async () => {
|
|
303
|
-
const recent = await stateStorage.getMostRecentTask(testProjectId)
|
|
304
|
-
|
|
305
|
-
expect(recent).not.toBeNull()
|
|
306
|
-
expect(recent!.title).toBe('Feature task 2')
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
it('getMostRecentTask() should return null when no history', async () => {
|
|
310
|
-
const emptyProjectId = `empty-${Date.now()}`
|
|
311
|
-
|
|
312
|
-
// Create storage directory for empty project
|
|
313
|
-
const storagePath = pathManager.getStoragePath(emptyProjectId, '')
|
|
314
|
-
await fs.mkdir(storagePath, { recursive: true })
|
|
315
|
-
|
|
316
|
-
const recent = await stateStorage.getMostRecentTask(emptyProjectId)
|
|
317
|
-
|
|
318
|
-
expect(recent).toBeNull()
|
|
319
|
-
})
|
|
320
|
-
|
|
321
|
-
it('getTaskHistoryByType() should filter by classification', async () => {
|
|
322
|
-
const featureHistory = await stateStorage.getTaskHistoryByType(testProjectId, 'feature')
|
|
323
|
-
|
|
324
|
-
expect(featureHistory.length).toBe(2)
|
|
325
|
-
expect(featureHistory.every((h) => h.classification === 'feature')).toBe(true)
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
it('getTaskHistoryByType() should return empty array for no matches', async () => {
|
|
329
|
-
const choreHistory = await stateStorage.getTaskHistoryByType(testProjectId, 'chore')
|
|
330
|
-
|
|
331
|
-
expect(choreHistory.length).toBe(0)
|
|
332
|
-
})
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
// =============================================================================
|
|
336
|
-
// Tests: Context Injection (Markdown Generation)
|
|
337
|
-
// =============================================================================
|
|
338
|
-
|
|
339
|
-
describe('Task History - Context Injection', () => {
|
|
340
|
-
it('should include task history section in markdown when history exists', async () => {
|
|
341
|
-
// Complete a task
|
|
342
|
-
const task = createMockTask({ description: 'Completed task' })
|
|
343
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
344
|
-
|
|
345
|
-
// Generate markdown
|
|
346
|
-
const state = await stateStorage.read(testProjectId)
|
|
347
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
348
|
-
|
|
349
|
-
expect(markdown).toContain('Recent tasks')
|
|
350
|
-
expect(markdown).toContain('Completed task')
|
|
351
|
-
expect(markdown).toContain('Task history helps identify patterns')
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
it('should filter by current task classification when task is active', async () => {
|
|
355
|
-
// Complete several tasks
|
|
356
|
-
const tasks = [
|
|
357
|
-
{ description: 'Feature 1', type: 'feature' },
|
|
358
|
-
{ description: 'Bug 1', type: 'bug' },
|
|
359
|
-
{ description: 'Feature 2', type: 'feature' },
|
|
360
|
-
]
|
|
361
|
-
|
|
362
|
-
for (const taskData of tasks) {
|
|
363
|
-
const task = createMockTask(taskData)
|
|
364
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Start a new bug task (should filter history to bugs only)
|
|
368
|
-
const currentTask = createMockTask({ description: 'Current bug', type: 'bug' })
|
|
369
|
-
await stateStorage.startTask(testProjectId, currentTask)
|
|
370
|
-
|
|
371
|
-
const state = await stateStorage.read(testProjectId)
|
|
372
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
373
|
-
|
|
374
|
-
expect(markdown).toContain('Recent bug tasks')
|
|
375
|
-
expect(markdown).toContain('Bug 1')
|
|
376
|
-
expect(markdown).not.toContain('Feature 1')
|
|
377
|
-
})
|
|
378
|
-
|
|
379
|
-
it('should show max 5 recent tasks when no current task', async () => {
|
|
380
|
-
// Complete 7 tasks
|
|
381
|
-
for (let i = 1; i <= 7; i++) {
|
|
382
|
-
const task = createMockTask({ description: `Task ${i}` })
|
|
383
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
const state = await stateStorage.read(testProjectId)
|
|
387
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
388
|
-
|
|
389
|
-
expect(markdown).toContain('Recent tasks (5)')
|
|
390
|
-
expect(markdown).toContain('Task 7')
|
|
391
|
-
expect(markdown).toContain('Task 3')
|
|
392
|
-
expect(markdown).not.toContain('Task 2') // Too old
|
|
393
|
-
})
|
|
394
|
-
|
|
395
|
-
it('should show max 3 entries of same type when task is active', async () => {
|
|
396
|
-
// Complete 5 feature tasks
|
|
397
|
-
for (let i = 1; i <= 5; i++) {
|
|
398
|
-
const task = createMockTask({ description: `Feature ${i}`, type: 'feature' })
|
|
399
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// Start a new feature task
|
|
403
|
-
const currentTask = createMockTask({ description: 'Current feature', type: 'feature' })
|
|
404
|
-
await stateStorage.startTask(testProjectId, currentTask)
|
|
405
|
-
|
|
406
|
-
const state = await stateStorage.read(testProjectId)
|
|
407
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
408
|
-
|
|
409
|
-
expect(markdown).toContain('Recent feature tasks (3)')
|
|
410
|
-
expect(markdown).toContain('Feature 5')
|
|
411
|
-
expect(markdown).toContain('Feature 4')
|
|
412
|
-
expect(markdown).toContain('Feature 3')
|
|
413
|
-
expect(markdown).not.toContain('Feature 2') // Too old (beyond 3)
|
|
414
|
-
})
|
|
415
|
-
|
|
416
|
-
it('should not show history section when taskHistory is empty', async () => {
|
|
417
|
-
const state = await stateStorage.read(testProjectId)
|
|
418
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
419
|
-
|
|
420
|
-
expect(markdown).not.toContain('Recent tasks')
|
|
421
|
-
expect(markdown).not.toContain('Task history helps identify patterns')
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
it('should include completion time and subtask count', async () => {
|
|
425
|
-
const task = createMockTask({
|
|
426
|
-
description: 'Task with details',
|
|
427
|
-
subtasks: [
|
|
428
|
-
{
|
|
429
|
-
id: 'st-1',
|
|
430
|
-
description: 'Subtask 1',
|
|
431
|
-
domain: 'backend',
|
|
432
|
-
agent: 'backend.md',
|
|
433
|
-
status: 'completed',
|
|
434
|
-
dependsOn: [],
|
|
435
|
-
},
|
|
436
|
-
{
|
|
437
|
-
id: 'st-2',
|
|
438
|
-
description: 'Subtask 2',
|
|
439
|
-
domain: 'backend',
|
|
440
|
-
agent: 'backend.md',
|
|
441
|
-
status: 'completed',
|
|
442
|
-
dependsOn: [],
|
|
443
|
-
},
|
|
444
|
-
],
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
448
|
-
|
|
449
|
-
const state = await stateStorage.read(testProjectId)
|
|
450
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
451
|
-
|
|
452
|
-
expect(markdown).toContain('2 subtasks')
|
|
453
|
-
expect(markdown).toContain('Completed:')
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('should include Linear ID when present', async () => {
|
|
457
|
-
const task = createMockTask({
|
|
458
|
-
description: 'Task with Linear',
|
|
459
|
-
linearId: 'PRJ-456',
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
await completeTaskAndGetState(testProjectId, task)
|
|
463
|
-
|
|
464
|
-
const state = await stateStorage.read(testProjectId)
|
|
465
|
-
const markdown = (stateStorage as any).toMarkdown(state)
|
|
466
|
-
|
|
467
|
-
expect(markdown).toContain('Linear: PRJ-456')
|
|
468
|
-
})
|
|
469
|
-
})
|