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,641 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analysis Storage Tests (PRJ-263)
|
|
3
|
-
*
|
|
4
|
-
* Tests for sealable analysis lifecycle:
|
|
5
|
-
* - Schema validation (draft/verified/sealed)
|
|
6
|
-
* - Signature computation and verification
|
|
7
|
-
* - Staleness detection
|
|
8
|
-
* - Draft preservation on re-sync
|
|
9
|
-
* - Backward compatibility
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { describe, expect, it } from 'bun:test'
|
|
13
|
-
import {
|
|
14
|
-
AnalysisItemSchema,
|
|
15
|
-
AnalysisStatusSchema,
|
|
16
|
-
parseAnalysis,
|
|
17
|
-
type SemanticCheckResult,
|
|
18
|
-
safeParseAnalysis,
|
|
19
|
-
} from '../../schemas/analysis'
|
|
20
|
-
|
|
21
|
-
// =============================================================================
|
|
22
|
-
// Schema Validation
|
|
23
|
-
// =============================================================================
|
|
24
|
-
|
|
25
|
-
describe('AnalysisStatusSchema', () => {
|
|
26
|
-
it('should accept valid statuses', () => {
|
|
27
|
-
expect(AnalysisStatusSchema.parse('draft')).toBe('draft')
|
|
28
|
-
expect(AnalysisStatusSchema.parse('verified')).toBe('verified')
|
|
29
|
-
expect(AnalysisStatusSchema.parse('sealed')).toBe('sealed')
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('should reject invalid statuses', () => {
|
|
33
|
-
expect(() => AnalysisStatusSchema.parse('pending')).toThrow()
|
|
34
|
-
expect(() => AnalysisStatusSchema.parse('active')).toThrow()
|
|
35
|
-
expect(() => AnalysisStatusSchema.parse('')).toThrow()
|
|
36
|
-
})
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
describe('AnalysisItemSchema', () => {
|
|
40
|
-
const validDraft = {
|
|
41
|
-
projectId: 'test-project-123',
|
|
42
|
-
languages: ['TypeScript'],
|
|
43
|
-
frameworks: ['Hono'],
|
|
44
|
-
configFiles: ['tsconfig.json'],
|
|
45
|
-
fileCount: 295,
|
|
46
|
-
patterns: [{ name: 'Service pattern', description: 'Classes with dependency injection' }],
|
|
47
|
-
antiPatterns: [],
|
|
48
|
-
analyzedAt: '2026-02-08T20:00:00.000Z',
|
|
49
|
-
status: 'draft' as const,
|
|
50
|
-
commitHash: 'abc1234',
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
it('should parse a valid draft analysis', () => {
|
|
54
|
-
const result = AnalysisItemSchema.parse(validDraft)
|
|
55
|
-
expect(result.status).toBe('draft')
|
|
56
|
-
expect(result.commitHash).toBe('abc1234')
|
|
57
|
-
expect(result.projectId).toBe('test-project-123')
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('should default status to draft when not provided', () => {
|
|
61
|
-
const { status, ...withoutStatus } = validDraft
|
|
62
|
-
const result = AnalysisItemSchema.parse(withoutStatus)
|
|
63
|
-
expect(result.status).toBe('draft')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('should parse a sealed analysis with signature', () => {
|
|
67
|
-
const sealed = {
|
|
68
|
-
...validDraft,
|
|
69
|
-
status: 'sealed' as const,
|
|
70
|
-
signature: 'sha256-abc123def456',
|
|
71
|
-
sealedAt: '2026-02-08T21:00:00.000Z',
|
|
72
|
-
}
|
|
73
|
-
const result = AnalysisItemSchema.parse(sealed)
|
|
74
|
-
expect(result.status).toBe('sealed')
|
|
75
|
-
expect(result.signature).toBe('sha256-abc123def456')
|
|
76
|
-
expect(result.sealedAt).toBe('2026-02-08T21:00:00.000Z')
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('should accept optional fields as undefined', () => {
|
|
80
|
-
const minimal = {
|
|
81
|
-
projectId: 'test',
|
|
82
|
-
languages: [],
|
|
83
|
-
frameworks: [],
|
|
84
|
-
configFiles: [],
|
|
85
|
-
fileCount: 0,
|
|
86
|
-
patterns: [],
|
|
87
|
-
antiPatterns: [],
|
|
88
|
-
analyzedAt: '2026-02-08T20:00:00.000Z',
|
|
89
|
-
}
|
|
90
|
-
const result = AnalysisItemSchema.parse(minimal)
|
|
91
|
-
expect(result.status).toBe('draft')
|
|
92
|
-
expect(result.commitHash).toBeUndefined()
|
|
93
|
-
expect(result.signature).toBeUndefined()
|
|
94
|
-
expect(result.sealedAt).toBeUndefined()
|
|
95
|
-
expect(result.modelMetadata).toBeUndefined()
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('should reject missing required fields', () => {
|
|
99
|
-
expect(() => AnalysisItemSchema.parse({})).toThrow()
|
|
100
|
-
expect(() => AnalysisItemSchema.parse({ projectId: 'test' })).toThrow()
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
describe('parseAnalysis / safeParseAnalysis', () => {
|
|
105
|
-
it('should parse valid data', () => {
|
|
106
|
-
const data = {
|
|
107
|
-
projectId: 'test',
|
|
108
|
-
languages: ['TypeScript'],
|
|
109
|
-
frameworks: [],
|
|
110
|
-
configFiles: [],
|
|
111
|
-
fileCount: 10,
|
|
112
|
-
patterns: [],
|
|
113
|
-
antiPatterns: [],
|
|
114
|
-
analyzedAt: '2026-02-08T20:00:00.000Z',
|
|
115
|
-
}
|
|
116
|
-
const result = parseAnalysis(data)
|
|
117
|
-
expect(result.projectId).toBe('test')
|
|
118
|
-
expect(result.status).toBe('draft')
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('should return success for safeParseAnalysis with valid data', () => {
|
|
122
|
-
const data = {
|
|
123
|
-
projectId: 'test',
|
|
124
|
-
languages: [],
|
|
125
|
-
frameworks: [],
|
|
126
|
-
configFiles: [],
|
|
127
|
-
fileCount: 0,
|
|
128
|
-
patterns: [],
|
|
129
|
-
antiPatterns: [],
|
|
130
|
-
analyzedAt: '2026-02-08T20:00:00.000Z',
|
|
131
|
-
}
|
|
132
|
-
const result = safeParseAnalysis(data)
|
|
133
|
-
expect(result.success).toBe(true)
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
it('should return failure for safeParseAnalysis with invalid data', () => {
|
|
137
|
-
const result = safeParseAnalysis({ invalid: true })
|
|
138
|
-
expect(result.success).toBe(false)
|
|
139
|
-
})
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
// =============================================================================
|
|
143
|
-
// Staleness Detection (pure function tests)
|
|
144
|
-
// =============================================================================
|
|
145
|
-
|
|
146
|
-
describe('staleness detection', () => {
|
|
147
|
-
// Test checkStaleness method from AnalysisStorage
|
|
148
|
-
it('should detect stale analysis when commits differ', () => {
|
|
149
|
-
const { analysisStorage } = require('../../storage/analysis-storage')
|
|
150
|
-
const result = analysisStorage.checkStaleness('abc1234', 'def5678')
|
|
151
|
-
expect(result.isStale).toBe(true)
|
|
152
|
-
expect(result.sealedCommit).toBe('abc1234')
|
|
153
|
-
expect(result.currentCommit).toBe('def5678')
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
it('should detect fresh analysis when commits match', () => {
|
|
157
|
-
const { analysisStorage } = require('../../storage/analysis-storage')
|
|
158
|
-
const result = analysisStorage.checkStaleness('abc1234', 'abc1234')
|
|
159
|
-
expect(result.isStale).toBe(false)
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('should handle null sealed commit', () => {
|
|
163
|
-
const { analysisStorage } = require('../../storage/analysis-storage')
|
|
164
|
-
const result = analysisStorage.checkStaleness(null, 'abc1234')
|
|
165
|
-
expect(result.isStale).toBe(false)
|
|
166
|
-
expect(result.message).toContain('No sealed analysis')
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
it('should handle null current commit', () => {
|
|
170
|
-
const { analysisStorage } = require('../../storage/analysis-storage')
|
|
171
|
-
const result = analysisStorage.checkStaleness('abc1234', null)
|
|
172
|
-
expect(result.isStale).toBe(true)
|
|
173
|
-
expect(result.message).toContain('Cannot determine')
|
|
174
|
-
})
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
// =============================================================================
|
|
178
|
-
// Signature Computation (determinism test)
|
|
179
|
-
// =============================================================================
|
|
180
|
-
|
|
181
|
-
describe('signature computation', () => {
|
|
182
|
-
it('should produce deterministic signatures for same input', () => {
|
|
183
|
-
const { createHash } = require('node:crypto')
|
|
184
|
-
|
|
185
|
-
const analysis = {
|
|
186
|
-
projectId: 'test',
|
|
187
|
-
languages: ['TypeScript'],
|
|
188
|
-
frameworks: ['Hono'],
|
|
189
|
-
configFiles: [],
|
|
190
|
-
fileCount: 100,
|
|
191
|
-
patterns: [],
|
|
192
|
-
antiPatterns: [],
|
|
193
|
-
analyzedAt: '2026-02-08T20:00:00.000Z',
|
|
194
|
-
commitHash: 'abc1234',
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const canonical = {
|
|
198
|
-
projectId: analysis.projectId,
|
|
199
|
-
languages: analysis.languages,
|
|
200
|
-
frameworks: analysis.frameworks,
|
|
201
|
-
packageManager: undefined,
|
|
202
|
-
sourceDir: undefined,
|
|
203
|
-
testDir: undefined,
|
|
204
|
-
configFiles: analysis.configFiles,
|
|
205
|
-
fileCount: analysis.fileCount,
|
|
206
|
-
patterns: analysis.patterns,
|
|
207
|
-
antiPatterns: analysis.antiPatterns,
|
|
208
|
-
analyzedAt: analysis.analyzedAt,
|
|
209
|
-
commitHash: analysis.commitHash,
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const sig1 = createHash('sha256').update(JSON.stringify(canonical)).digest('hex')
|
|
213
|
-
const sig2 = createHash('sha256').update(JSON.stringify(canonical)).digest('hex')
|
|
214
|
-
|
|
215
|
-
expect(sig1).toBe(sig2)
|
|
216
|
-
expect(sig1).toHaveLength(64) // SHA-256 hex = 64 chars
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
it('should produce different signatures for different inputs', () => {
|
|
220
|
-
const { createHash } = require('node:crypto')
|
|
221
|
-
|
|
222
|
-
const data1 = JSON.stringify({ projectId: 'a', fileCount: 1 })
|
|
223
|
-
const data2 = JSON.stringify({ projectId: 'b', fileCount: 2 })
|
|
224
|
-
|
|
225
|
-
const sig1 = createHash('sha256').update(data1).digest('hex')
|
|
226
|
-
const sig2 = createHash('sha256').update(data2).digest('hex')
|
|
227
|
-
|
|
228
|
-
expect(sig1).not.toBe(sig2)
|
|
229
|
-
})
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
// =============================================================================
|
|
233
|
-
// Backward Compatibility
|
|
234
|
-
// =============================================================================
|
|
235
|
-
|
|
236
|
-
describe('backward compatibility', () => {
|
|
237
|
-
it('should parse old analysis.json without seal fields', () => {
|
|
238
|
-
const oldFormat = {
|
|
239
|
-
projectId: 'old-project',
|
|
240
|
-
languages: ['JavaScript'],
|
|
241
|
-
frameworks: ['Express'],
|
|
242
|
-
configFiles: ['package.json'],
|
|
243
|
-
fileCount: 50,
|
|
244
|
-
patterns: [],
|
|
245
|
-
antiPatterns: [],
|
|
246
|
-
analyzedAt: '2025-12-01T00:00:00.000Z',
|
|
247
|
-
// No status, commitHash, signature, sealedAt
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const result = AnalysisItemSchema.parse(oldFormat)
|
|
251
|
-
expect(result.status).toBe('draft') // Default
|
|
252
|
-
expect(result.commitHash).toBeUndefined()
|
|
253
|
-
expect(result.signature).toBeUndefined()
|
|
254
|
-
expect(result.sealedAt).toBeUndefined()
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('should parse old analysis with modelMetadata but no seal fields', () => {
|
|
258
|
-
const oldWithModel = {
|
|
259
|
-
projectId: 'old-project',
|
|
260
|
-
languages: ['TypeScript'],
|
|
261
|
-
frameworks: [],
|
|
262
|
-
configFiles: [],
|
|
263
|
-
fileCount: 10,
|
|
264
|
-
patterns: [],
|
|
265
|
-
antiPatterns: [],
|
|
266
|
-
analyzedAt: '2026-01-15T00:00:00.000Z',
|
|
267
|
-
modelMetadata: {
|
|
268
|
-
provider: 'claude',
|
|
269
|
-
model: 'sonnet',
|
|
270
|
-
recordedAt: '2026-01-15T00:00:00.000Z',
|
|
271
|
-
},
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const result = AnalysisItemSchema.parse(oldWithModel)
|
|
275
|
-
expect(result.status).toBe('draft')
|
|
276
|
-
expect(result.modelMetadata?.provider).toBe('claude')
|
|
277
|
-
})
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
// =============================================================================
|
|
281
|
-
// Semantic Verification (PRJ-270)
|
|
282
|
-
// =============================================================================
|
|
283
|
-
|
|
284
|
-
describe('semantic verification', () => {
|
|
285
|
-
const { semanticVerify } = require('../../schemas/analysis')
|
|
286
|
-
const fs = require('node:fs/promises')
|
|
287
|
-
const path = require('node:path')
|
|
288
|
-
const os = require('node:os')
|
|
289
|
-
|
|
290
|
-
// Helper to create a temporary test project
|
|
291
|
-
async function createTestProject(options: {
|
|
292
|
-
hasPackageJson?: boolean
|
|
293
|
-
packageJsonDeps?: Record<string, string>
|
|
294
|
-
files?: { path: string; content: string }[]
|
|
295
|
-
fileCount?: number
|
|
296
|
-
}) {
|
|
297
|
-
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'prjct-test-'))
|
|
298
|
-
|
|
299
|
-
// Create package.json if requested
|
|
300
|
-
if (options.hasPackageJson) {
|
|
301
|
-
const pkg = {
|
|
302
|
-
name: 'test-project',
|
|
303
|
-
dependencies: options.packageJsonDeps || {},
|
|
304
|
-
}
|
|
305
|
-
await fs.writeFile(path.join(tmpDir, 'package.json'), JSON.stringify(pkg, null, 2))
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// Create additional files
|
|
309
|
-
if (options.files) {
|
|
310
|
-
for (const file of options.files) {
|
|
311
|
-
const filePath = path.join(tmpDir, file.path)
|
|
312
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
313
|
-
await fs.writeFile(filePath, file.content)
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
return tmpDir
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Helper to cleanup test project
|
|
321
|
-
async function cleanupTestProject(tmpDir: string) {
|
|
322
|
-
try {
|
|
323
|
-
await fs.rm(tmpDir, { recursive: true, force: true })
|
|
324
|
-
} catch {
|
|
325
|
-
// Ignore cleanup errors
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
it('should pass all checks for valid analysis', async () => {
|
|
330
|
-
const projectPath = await createTestProject({
|
|
331
|
-
hasPackageJson: true,
|
|
332
|
-
packageJsonDeps: { hono: '^3.0.0', zod: '^3.0.0' },
|
|
333
|
-
files: [
|
|
334
|
-
{ path: 'src/index.ts', content: 'export const app = {}' },
|
|
335
|
-
{ path: 'src/server.ts', content: 'import { serve } from "bun"' },
|
|
336
|
-
{ path: 'patterns/service.ts', content: 'export class UserService {}' },
|
|
337
|
-
],
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
const analysis = {
|
|
341
|
-
projectId: 'test',
|
|
342
|
-
languages: ['TypeScript'],
|
|
343
|
-
frameworks: ['Hono'],
|
|
344
|
-
configFiles: [],
|
|
345
|
-
fileCount: 4, // package.json + 3 TypeScript files
|
|
346
|
-
patterns: [
|
|
347
|
-
{ name: 'Service pattern', description: 'DI pattern', location: 'patterns/service.ts' },
|
|
348
|
-
],
|
|
349
|
-
antiPatterns: [],
|
|
350
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
351
|
-
status: 'draft' as const,
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
355
|
-
|
|
356
|
-
expect(result.passed).toBe(true)
|
|
357
|
-
expect(result.failedCount).toBe(0)
|
|
358
|
-
expect(result.passedCount).toBeGreaterThan(0)
|
|
359
|
-
expect(result.checks.every((c: SemanticCheckResult) => c.passed)).toBe(true)
|
|
360
|
-
|
|
361
|
-
await cleanupTestProject(projectPath)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it('should fail when frameworks are not in package.json', async () => {
|
|
365
|
-
const projectPath = await createTestProject({
|
|
366
|
-
hasPackageJson: true,
|
|
367
|
-
packageJsonDeps: { express: '^4.0.0' }, // Different framework
|
|
368
|
-
files: [{ path: 'src/index.ts', content: '' }],
|
|
369
|
-
})
|
|
370
|
-
|
|
371
|
-
const analysis = {
|
|
372
|
-
projectId: 'test',
|
|
373
|
-
languages: ['TypeScript'],
|
|
374
|
-
frameworks: ['Hono', 'Zod'], // These are not in dependencies
|
|
375
|
-
configFiles: [],
|
|
376
|
-
fileCount: 1,
|
|
377
|
-
patterns: [],
|
|
378
|
-
antiPatterns: [],
|
|
379
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
380
|
-
status: 'draft' as const,
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
384
|
-
|
|
385
|
-
expect(result.passed).toBe(false)
|
|
386
|
-
expect(result.failedCount).toBeGreaterThan(0)
|
|
387
|
-
|
|
388
|
-
const frameworkCheck = result.checks.find(
|
|
389
|
-
(c: SemanticCheckResult) => c.name === 'Framework verification'
|
|
390
|
-
)
|
|
391
|
-
expect(frameworkCheck?.passed).toBe(false)
|
|
392
|
-
expect(frameworkCheck?.error).toContain('not found in dependencies')
|
|
393
|
-
|
|
394
|
-
await cleanupTestProject(projectPath)
|
|
395
|
-
})
|
|
396
|
-
|
|
397
|
-
it('should fail when package.json is missing', async () => {
|
|
398
|
-
const projectPath = await createTestProject({
|
|
399
|
-
hasPackageJson: false, // No package.json
|
|
400
|
-
files: [{ path: 'src/index.ts', content: '' }],
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
const analysis = {
|
|
404
|
-
projectId: 'test',
|
|
405
|
-
languages: ['TypeScript'],
|
|
406
|
-
frameworks: ['Hono'],
|
|
407
|
-
configFiles: [],
|
|
408
|
-
fileCount: 1,
|
|
409
|
-
patterns: [],
|
|
410
|
-
antiPatterns: [],
|
|
411
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
412
|
-
status: 'draft' as const,
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
416
|
-
|
|
417
|
-
const frameworkCheck = result.checks.find(
|
|
418
|
-
(c: SemanticCheckResult) => c.name === 'Framework verification'
|
|
419
|
-
)
|
|
420
|
-
expect(frameworkCheck?.passed).toBe(false)
|
|
421
|
-
expect(frameworkCheck?.error).toContain('package.json not found')
|
|
422
|
-
|
|
423
|
-
await cleanupTestProject(projectPath)
|
|
424
|
-
})
|
|
425
|
-
|
|
426
|
-
it('should fail when declared languages have no matching files', async () => {
|
|
427
|
-
const projectPath = await createTestProject({
|
|
428
|
-
hasPackageJson: true,
|
|
429
|
-
files: [
|
|
430
|
-
{ path: 'src/index.js', content: '' }, // Only JS files
|
|
431
|
-
],
|
|
432
|
-
})
|
|
433
|
-
|
|
434
|
-
const analysis = {
|
|
435
|
-
projectId: 'test',
|
|
436
|
-
languages: ['TypeScript', 'Go'], // Declared but no .ts or .go files
|
|
437
|
-
frameworks: [],
|
|
438
|
-
configFiles: [],
|
|
439
|
-
fileCount: 1,
|
|
440
|
-
patterns: [],
|
|
441
|
-
antiPatterns: [],
|
|
442
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
443
|
-
status: 'draft' as const,
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
447
|
-
|
|
448
|
-
const languageCheck = result.checks.find(
|
|
449
|
-
(c: SemanticCheckResult) => c.name === 'Language verification'
|
|
450
|
-
)
|
|
451
|
-
expect(languageCheck?.passed).toBe(false)
|
|
452
|
-
expect(languageCheck?.error).toContain('without matching files')
|
|
453
|
-
|
|
454
|
-
await cleanupTestProject(projectPath)
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
it('should fail when pattern locations reference missing files', async () => {
|
|
458
|
-
const projectPath = await createTestProject({
|
|
459
|
-
hasPackageJson: true,
|
|
460
|
-
files: [{ path: 'src/index.ts', content: '' }],
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
const analysis = {
|
|
464
|
-
projectId: 'test',
|
|
465
|
-
languages: ['TypeScript'],
|
|
466
|
-
frameworks: [],
|
|
467
|
-
configFiles: [],
|
|
468
|
-
fileCount: 1,
|
|
469
|
-
patterns: [
|
|
470
|
-
{ name: 'Service pattern', description: 'DI', location: 'src/service.ts' }, // Doesn't exist
|
|
471
|
-
{ name: 'Repository', description: 'Data access', location: 'src/repo.ts' }, // Doesn't exist
|
|
472
|
-
],
|
|
473
|
-
antiPatterns: [],
|
|
474
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
475
|
-
status: 'draft' as const,
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
479
|
-
|
|
480
|
-
const patternCheck = result.checks.find(
|
|
481
|
-
(c: SemanticCheckResult) => c.name === 'Pattern location verification'
|
|
482
|
-
)
|
|
483
|
-
expect(patternCheck?.passed).toBe(false)
|
|
484
|
-
expect(patternCheck?.error).toContain('not found')
|
|
485
|
-
|
|
486
|
-
await cleanupTestProject(projectPath)
|
|
487
|
-
})
|
|
488
|
-
|
|
489
|
-
it('should fail when file count is inaccurate', async () => {
|
|
490
|
-
const projectPath = await createTestProject({
|
|
491
|
-
hasPackageJson: true,
|
|
492
|
-
files: [
|
|
493
|
-
{ path: 'src/a.ts', content: '' },
|
|
494
|
-
{ path: 'src/b.ts', content: '' },
|
|
495
|
-
{ path: 'src/c.ts', content: '' },
|
|
496
|
-
], // 4 files total (package.json + 3 .ts files)
|
|
497
|
-
})
|
|
498
|
-
|
|
499
|
-
const analysis = {
|
|
500
|
-
projectId: 'test',
|
|
501
|
-
languages: ['TypeScript'],
|
|
502
|
-
frameworks: [],
|
|
503
|
-
configFiles: [],
|
|
504
|
-
fileCount: 100, // Way off (actual is ~4)
|
|
505
|
-
patterns: [],
|
|
506
|
-
antiPatterns: [],
|
|
507
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
508
|
-
status: 'draft' as const,
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
512
|
-
|
|
513
|
-
const fileCountCheck = result.checks.find(
|
|
514
|
-
(c: SemanticCheckResult) => c.name === 'File count verification'
|
|
515
|
-
)
|
|
516
|
-
expect(fileCountCheck?.passed).toBe(false)
|
|
517
|
-
expect(fileCountCheck?.error).toContain('mismatch')
|
|
518
|
-
|
|
519
|
-
await cleanupTestProject(projectPath)
|
|
520
|
-
})
|
|
521
|
-
|
|
522
|
-
it('should fail when anti-pattern files are missing', async () => {
|
|
523
|
-
const projectPath = await createTestProject({
|
|
524
|
-
hasPackageJson: true,
|
|
525
|
-
files: [{ path: 'src/index.ts', content: '' }],
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
const analysis = {
|
|
529
|
-
projectId: 'test',
|
|
530
|
-
languages: ['TypeScript'],
|
|
531
|
-
frameworks: [],
|
|
532
|
-
configFiles: [],
|
|
533
|
-
fileCount: 1,
|
|
534
|
-
patterns: [],
|
|
535
|
-
antiPatterns: [
|
|
536
|
-
{ issue: 'Missing types', file: 'src/bad.ts', suggestion: 'Add types' }, // File doesn't exist
|
|
537
|
-
],
|
|
538
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
539
|
-
status: 'draft' as const,
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
543
|
-
|
|
544
|
-
const antiPatternCheck = result.checks.find(
|
|
545
|
-
(c: SemanticCheckResult) => c.name === 'Anti-pattern file verification'
|
|
546
|
-
)
|
|
547
|
-
expect(antiPatternCheck?.passed).toBe(false)
|
|
548
|
-
expect(antiPatternCheck?.error).toContain('not found')
|
|
549
|
-
|
|
550
|
-
await cleanupTestProject(projectPath)
|
|
551
|
-
})
|
|
552
|
-
|
|
553
|
-
it('should skip checks when no data to verify', async () => {
|
|
554
|
-
const projectPath = await createTestProject({
|
|
555
|
-
hasPackageJson: true,
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
const analysis = {
|
|
559
|
-
projectId: 'test',
|
|
560
|
-
languages: [], // No languages declared
|
|
561
|
-
frameworks: [], // No frameworks declared
|
|
562
|
-
configFiles: [],
|
|
563
|
-
fileCount: 1,
|
|
564
|
-
patterns: [], // No patterns with locations
|
|
565
|
-
antiPatterns: [], // No anti-patterns
|
|
566
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
567
|
-
status: 'draft' as const,
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
571
|
-
|
|
572
|
-
expect(result.passed).toBe(true) // All checks skipped, so passes
|
|
573
|
-
expect(
|
|
574
|
-
result.checks.every((c: SemanticCheckResult) => c.output?.includes('skipped') || c.passed)
|
|
575
|
-
).toBe(true)
|
|
576
|
-
|
|
577
|
-
await cleanupTestProject(projectPath)
|
|
578
|
-
})
|
|
579
|
-
|
|
580
|
-
it('should accept file count within tolerance (10%)', async () => {
|
|
581
|
-
const projectPath = await createTestProject({
|
|
582
|
-
hasPackageJson: true,
|
|
583
|
-
files: [
|
|
584
|
-
{ path: 'src/a.ts', content: '' },
|
|
585
|
-
{ path: 'src/b.ts', content: '' },
|
|
586
|
-
{ path: 'src/c.ts', content: '' },
|
|
587
|
-
{ path: 'src/d.ts', content: '' },
|
|
588
|
-
{ path: 'src/e.ts', content: '' },
|
|
589
|
-
], // 6 files total
|
|
590
|
-
})
|
|
591
|
-
|
|
592
|
-
const analysis = {
|
|
593
|
-
projectId: 'test',
|
|
594
|
-
languages: ['TypeScript'],
|
|
595
|
-
frameworks: [],
|
|
596
|
-
configFiles: [],
|
|
597
|
-
fileCount: 6, // Within 10% tolerance
|
|
598
|
-
patterns: [],
|
|
599
|
-
antiPatterns: [],
|
|
600
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
601
|
-
status: 'draft' as const,
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
605
|
-
|
|
606
|
-
const fileCountCheck = result.checks.find(
|
|
607
|
-
(c: SemanticCheckResult) => c.name === 'File count verification'
|
|
608
|
-
)
|
|
609
|
-
expect(fileCountCheck?.passed).toBe(true)
|
|
610
|
-
|
|
611
|
-
await cleanupTestProject(projectPath)
|
|
612
|
-
})
|
|
613
|
-
|
|
614
|
-
it('should handle partial framework matches (case insensitive)', async () => {
|
|
615
|
-
const projectPath = await createTestProject({
|
|
616
|
-
hasPackageJson: true,
|
|
617
|
-
packageJsonDeps: { '@hono/node-server': '^1.0.0' }, // Hono as part of package name
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
const analysis = {
|
|
621
|
-
projectId: 'test',
|
|
622
|
-
languages: [],
|
|
623
|
-
frameworks: ['Hono'], // Should match @hono/node-server
|
|
624
|
-
configFiles: [],
|
|
625
|
-
fileCount: 1,
|
|
626
|
-
patterns: [],
|
|
627
|
-
antiPatterns: [],
|
|
628
|
-
analyzedAt: '2026-02-10T00:00:00.000Z',
|
|
629
|
-
status: 'draft' as const,
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
const result = await semanticVerify(analysis, projectPath)
|
|
633
|
-
|
|
634
|
-
const frameworkCheck = result.checks.find(
|
|
635
|
-
(c: SemanticCheckResult) => c.name === 'Framework verification'
|
|
636
|
-
)
|
|
637
|
-
expect(frameworkCheck?.passed).toBe(true)
|
|
638
|
-
|
|
639
|
-
await cleanupTestProject(projectPath)
|
|
640
|
-
})
|
|
641
|
-
})
|