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,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dependency Validator Tests
|
|
3
|
-
* Tests for graceful degradation when system dependencies are missing
|
|
4
|
-
*
|
|
5
|
-
* @see PRJ-114
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { beforeEach, describe, expect, it } from 'bun:test'
|
|
9
|
-
import { DependencyError, dependencyValidator, TOOLS } from '../../services/dependency-validator'
|
|
10
|
-
|
|
11
|
-
describe('DependencyValidator', () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
// Clear cache before each test
|
|
14
|
-
dependencyValidator.clearCache()
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
describe('checkTool', () => {
|
|
18
|
-
it('should return available: true for installed tools (git)', () => {
|
|
19
|
-
const result = dependencyValidator.checkTool('git')
|
|
20
|
-
expect(result.available).toBe(true)
|
|
21
|
-
expect(result.version).toBeDefined()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('should return available: true for installed tools (node)', () => {
|
|
25
|
-
const result = dependencyValidator.checkTool('node')
|
|
26
|
-
expect(result.available).toBe(true)
|
|
27
|
-
expect(result.version).toBeDefined()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should return available: false for non-existent tools', () => {
|
|
31
|
-
const result = dependencyValidator.checkTool('definitely-not-a-real-tool-xyz123')
|
|
32
|
-
expect(result.available).toBe(false)
|
|
33
|
-
expect(result.error).toBeDefined()
|
|
34
|
-
expect(result.error?.message).toContain('not installed')
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('should cache results', () => {
|
|
38
|
-
const result1 = dependencyValidator.checkTool('git')
|
|
39
|
-
const result2 = dependencyValidator.checkTool('git')
|
|
40
|
-
// Same object reference means cached
|
|
41
|
-
expect(result1).toBe(result2)
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
describe('isAvailable', () => {
|
|
46
|
-
it('should return true for available tools', () => {
|
|
47
|
-
expect(dependencyValidator.isAvailable('git')).toBe(true)
|
|
48
|
-
expect(dependencyValidator.isAvailable('node')).toBe(true)
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should return false for unavailable tools', () => {
|
|
52
|
-
expect(dependencyValidator.isAvailable('fake-tool-abc')).toBe(false)
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
describe('getVersion', () => {
|
|
57
|
-
it('should return version string for available tools', () => {
|
|
58
|
-
const version = dependencyValidator.getVersion('git')
|
|
59
|
-
expect(version).toBeDefined()
|
|
60
|
-
expect(typeof version).toBe('string')
|
|
61
|
-
// Git version is like "2.39.0" or similar
|
|
62
|
-
expect(version).toMatch(/^\d+\.\d+/)
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('should return undefined for unavailable tools', () => {
|
|
66
|
-
const version = dependencyValidator.getVersion('fake-tool-xyz')
|
|
67
|
-
expect(version).toBeUndefined()
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
describe('ensureTool', () => {
|
|
72
|
-
it('should not throw for available tools', () => {
|
|
73
|
-
expect(() => dependencyValidator.ensureTool('git')).not.toThrow()
|
|
74
|
-
expect(() => dependencyValidator.ensureTool('node')).not.toThrow()
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('should throw DependencyError for unavailable tools', () => {
|
|
78
|
-
expect(() => dependencyValidator.ensureTool('fake-tool-xyz')).toThrow(DependencyError)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('should include helpful hint in error', () => {
|
|
82
|
-
try {
|
|
83
|
-
dependencyValidator.ensureTool('fake-tool-xyz')
|
|
84
|
-
} catch (error) {
|
|
85
|
-
expect(error).toBeInstanceOf(DependencyError)
|
|
86
|
-
expect((error as DependencyError).hint).toBeDefined()
|
|
87
|
-
}
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
describe('ensureTools', () => {
|
|
92
|
-
it('should not throw when all tools are available', () => {
|
|
93
|
-
expect(() => dependencyValidator.ensureTools(['git', 'node'])).not.toThrow()
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('should throw when any tool is unavailable', () => {
|
|
97
|
-
expect(() => dependencyValidator.ensureTools(['git', 'fake-tool-xyz'])).toThrow(
|
|
98
|
-
DependencyError
|
|
99
|
-
)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('should list all missing tools in error', () => {
|
|
103
|
-
try {
|
|
104
|
-
dependencyValidator.ensureTools(['fake-tool-1', 'fake-tool-2'])
|
|
105
|
-
} catch (error) {
|
|
106
|
-
expect(error).toBeInstanceOf(DependencyError)
|
|
107
|
-
expect((error as DependencyError).message).toContain('fake-tool-1')
|
|
108
|
-
expect((error as DependencyError).message).toContain('fake-tool-2')
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
describe('checkAll', () => {
|
|
114
|
-
it('should return status for all default tools', () => {
|
|
115
|
-
const results = dependencyValidator.checkAll()
|
|
116
|
-
expect(results.size).toBeGreaterThan(0)
|
|
117
|
-
expect(results.has('git')).toBe(true)
|
|
118
|
-
expect(results.has('node')).toBe(true)
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('should return status for specified tools', () => {
|
|
122
|
-
const results = dependencyValidator.checkAll(['git', 'node'])
|
|
123
|
-
expect(results.size).toBe(2)
|
|
124
|
-
expect(results.get('git')?.available).toBe(true)
|
|
125
|
-
expect(results.get('node')?.available).toBe(true)
|
|
126
|
-
})
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
describe('clearCache', () => {
|
|
130
|
-
it('should clear cached results', () => {
|
|
131
|
-
const result1 = dependencyValidator.checkTool('git')
|
|
132
|
-
dependencyValidator.clearCache()
|
|
133
|
-
const result2 = dependencyValidator.checkTool('git')
|
|
134
|
-
// Different object reference after cache clear
|
|
135
|
-
expect(result1).not.toBe(result2)
|
|
136
|
-
})
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
describe('TOOLS definitions', () => {
|
|
140
|
-
it('should have required tools marked as required', () => {
|
|
141
|
-
expect(TOOLS.git.required).toBe(true)
|
|
142
|
-
expect(TOOLS.node.required).toBe(true)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
it('should have optional tools marked as not required', () => {
|
|
146
|
-
expect(TOOLS.bun.required).toBe(false)
|
|
147
|
-
expect(TOOLS.gh.required).toBe(false)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it('should have install hints for all tools', () => {
|
|
151
|
-
for (const tool of Object.values(TOOLS)) {
|
|
152
|
-
expect(tool.installHint).toBeDefined()
|
|
153
|
-
expect(tool.installHint.length).toBeGreaterThan(0)
|
|
154
|
-
}
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
describe('DependencyError', () => {
|
|
159
|
-
it('should have correct name', () => {
|
|
160
|
-
const error = new DependencyError({ message: 'test' })
|
|
161
|
-
expect(error.name).toBe('DependencyError')
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('should preserve hint and docs', () => {
|
|
165
|
-
const error = new DependencyError({
|
|
166
|
-
message: 'Tool not found',
|
|
167
|
-
hint: 'Install it',
|
|
168
|
-
docs: 'https://example.com',
|
|
169
|
-
})
|
|
170
|
-
expect(error.message).toBe('Tool not found')
|
|
171
|
-
expect(error.hint).toBe('Install it')
|
|
172
|
-
expect(error.docs).toBe('https://example.com')
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
})
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for HierarchicalAgentResolver
|
|
3
|
-
* PRJ-101: Hierarchical scope system
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { afterEach, beforeEach, describe, expect, test } from 'bun:test'
|
|
7
|
-
import fs from 'node:fs/promises'
|
|
8
|
-
import os from 'node:os'
|
|
9
|
-
import path from 'node:path'
|
|
10
|
-
import HierarchicalAgentResolver from '../../services/hierarchical-agent-resolver'
|
|
11
|
-
|
|
12
|
-
let testDir: string
|
|
13
|
-
let resolver: HierarchicalAgentResolver
|
|
14
|
-
|
|
15
|
-
beforeEach(async () => {
|
|
16
|
-
testDir = path.join(os.tmpdir(), `prjct-har-test-${Date.now()}`)
|
|
17
|
-
await fs.mkdir(testDir, { recursive: true })
|
|
18
|
-
resolver = new HierarchicalAgentResolver(testDir)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(async () => {
|
|
22
|
-
try {
|
|
23
|
-
await fs.rm(testDir, { recursive: true, force: true })
|
|
24
|
-
} catch {
|
|
25
|
-
// Ignore cleanup errors
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
// =============================================================================
|
|
30
|
-
// Basic Resolution Tests
|
|
31
|
-
// =============================================================================
|
|
32
|
-
|
|
33
|
-
describe('HierarchicalAgentResolver - Basic', () => {
|
|
34
|
-
test('resolves agents from root AGENTS.md', async () => {
|
|
35
|
-
await fs.writeFile(
|
|
36
|
-
path.join(testDir, 'AGENTS.md'),
|
|
37
|
-
`## Backend
|
|
38
|
-
|
|
39
|
-
Backend development specialist.
|
|
40
|
-
|
|
41
|
-
### Triggers
|
|
42
|
-
- api
|
|
43
|
-
- endpoint
|
|
44
|
-
- server
|
|
45
|
-
|
|
46
|
-
### Rules
|
|
47
|
-
- Use async/await
|
|
48
|
-
- Validate inputs
|
|
49
|
-
`
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
const result = await resolver.resolveAgentsForPath(testDir)
|
|
53
|
-
|
|
54
|
-
expect(result.agents).toHaveLength(1)
|
|
55
|
-
expect(result.agents[0].name).toBe('Backend')
|
|
56
|
-
expect(result.agents[0].description).toBe('Backend development specialist.')
|
|
57
|
-
expect(result.agents[0].triggers).toContain('api')
|
|
58
|
-
expect(result.agents[0].rules).toContain('Use async/await')
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('returns empty result when no AGENTS.md exists', async () => {
|
|
62
|
-
const result = await resolver.resolveAgentsForPath(testDir)
|
|
63
|
-
|
|
64
|
-
expect(result.agents).toHaveLength(0)
|
|
65
|
-
expect(result.discoveredFiles).toHaveLength(0)
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test('tracks discovered files', async () => {
|
|
69
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Agent\n\nTest.')
|
|
70
|
-
|
|
71
|
-
const result = await resolver.resolveAgentsForPath(testDir)
|
|
72
|
-
|
|
73
|
-
expect(result.discoveredFiles).toHaveLength(1)
|
|
74
|
-
expect(result.discoveredFiles[0]).toBe(path.join(testDir, 'AGENTS.md'))
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test('resolveRootAgents uses root path', async () => {
|
|
78
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Root\n\nRoot agent.')
|
|
79
|
-
|
|
80
|
-
const subDir = path.join(testDir, 'sub')
|
|
81
|
-
await fs.mkdir(subDir)
|
|
82
|
-
await fs.writeFile(path.join(subDir, 'AGENTS.md'), '## Sub\n\nSub agent.')
|
|
83
|
-
|
|
84
|
-
// resolveRootAgents should return root agents
|
|
85
|
-
const result = await resolver.resolveRootAgents()
|
|
86
|
-
|
|
87
|
-
// Root has only 1 agent (no inheritance from children)
|
|
88
|
-
expect(result.agents).toHaveLength(1)
|
|
89
|
-
expect(result.agents[0].name).toBe('Root')
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
// =============================================================================
|
|
94
|
-
// Get Agent By Name Tests
|
|
95
|
-
// =============================================================================
|
|
96
|
-
|
|
97
|
-
describe('HierarchicalAgentResolver - getAgentByName', () => {
|
|
98
|
-
test('finds agent by name', async () => {
|
|
99
|
-
await fs.writeFile(
|
|
100
|
-
path.join(testDir, 'AGENTS.md'),
|
|
101
|
-
`## Frontend
|
|
102
|
-
|
|
103
|
-
Frontend specialist.
|
|
104
|
-
|
|
105
|
-
## Backend
|
|
106
|
-
|
|
107
|
-
Backend specialist.
|
|
108
|
-
`
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
const agent = await resolver.getAgentByName('Backend')
|
|
112
|
-
|
|
113
|
-
expect(agent).not.toBeNull()
|
|
114
|
-
expect(agent?.name).toBe('Backend')
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
test('returns null for non-existent agent', async () => {
|
|
118
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Frontend\n\nFrontend.')
|
|
119
|
-
|
|
120
|
-
const agent = await resolver.getAgentByName('NonExistent')
|
|
121
|
-
|
|
122
|
-
expect(agent).toBeNull()
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
test('case-insensitive search', async () => {
|
|
126
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Backend\n\nBackend.')
|
|
127
|
-
|
|
128
|
-
const agent = await resolver.getAgentByName('BACKEND')
|
|
129
|
-
|
|
130
|
-
expect(agent).not.toBeNull()
|
|
131
|
-
expect(agent?.name).toBe('Backend')
|
|
132
|
-
})
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
// =============================================================================
|
|
136
|
-
// Get All Agent Names Tests
|
|
137
|
-
// =============================================================================
|
|
138
|
-
|
|
139
|
-
describe('HierarchicalAgentResolver - getAllAgentNames', () => {
|
|
140
|
-
test('returns all unique agent names', async () => {
|
|
141
|
-
await fs.writeFile(
|
|
142
|
-
path.join(testDir, 'AGENTS.md'),
|
|
143
|
-
`## Alpha
|
|
144
|
-
|
|
145
|
-
Alpha agent.
|
|
146
|
-
|
|
147
|
-
## Beta
|
|
148
|
-
|
|
149
|
-
Beta agent.
|
|
150
|
-
`
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
const names = await resolver.getAllAgentNames()
|
|
154
|
-
|
|
155
|
-
expect(names).toEqual(['Alpha', 'Beta'])
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
test('includes agents from nested files', async () => {
|
|
159
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Root\n\nRoot.')
|
|
160
|
-
|
|
161
|
-
const subDir = path.join(testDir, 'sub')
|
|
162
|
-
await fs.mkdir(subDir)
|
|
163
|
-
await fs.writeFile(path.join(subDir, 'AGENTS.md'), '## Sub\n\nSub.')
|
|
164
|
-
|
|
165
|
-
const names = await resolver.getAllAgentNames()
|
|
166
|
-
|
|
167
|
-
expect(names.sort()).toEqual(['Root', 'Sub'])
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
test('deduplicates agent names', async () => {
|
|
171
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Shared\n\nRoot shared.')
|
|
172
|
-
|
|
173
|
-
const subDir = path.join(testDir, 'sub')
|
|
174
|
-
await fs.mkdir(subDir)
|
|
175
|
-
await fs.writeFile(path.join(subDir, 'AGENTS.md'), '## Shared\n\nSub shared.')
|
|
176
|
-
|
|
177
|
-
const names = await resolver.getAllAgentNames()
|
|
178
|
-
|
|
179
|
-
expect(names).toEqual(['Shared'])
|
|
180
|
-
})
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
// =============================================================================
|
|
184
|
-
// Agent Existence Check Tests
|
|
185
|
-
// =============================================================================
|
|
186
|
-
|
|
187
|
-
describe('HierarchicalAgentResolver - agentExists', () => {
|
|
188
|
-
test('returns true for existing agent', async () => {
|
|
189
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Frontend\n\nFrontend.')
|
|
190
|
-
|
|
191
|
-
const exists = await resolver.agentExists('Frontend')
|
|
192
|
-
|
|
193
|
-
expect(exists).toBe(true)
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
test('returns false for non-existing agent', async () => {
|
|
197
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Frontend\n\nFrontend.')
|
|
198
|
-
|
|
199
|
-
const exists = await resolver.agentExists('Backend')
|
|
200
|
-
|
|
201
|
-
expect(exists).toBe(false)
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
test('case-insensitive check', async () => {
|
|
205
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Frontend\n\nFrontend.')
|
|
206
|
-
|
|
207
|
-
const exists = await resolver.agentExists('FRONTEND')
|
|
208
|
-
|
|
209
|
-
expect(exists).toBe(true)
|
|
210
|
-
})
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
// =============================================================================
|
|
214
|
-
// Markdown Generation Tests
|
|
215
|
-
// =============================================================================
|
|
216
|
-
|
|
217
|
-
describe('HierarchicalAgentResolver - generateAgentMarkdown', () => {
|
|
218
|
-
test('generates markdown with all sections', async () => {
|
|
219
|
-
await fs.writeFile(
|
|
220
|
-
path.join(testDir, 'AGENTS.md'),
|
|
221
|
-
`## Backend
|
|
222
|
-
|
|
223
|
-
Backend development specialist.
|
|
224
|
-
|
|
225
|
-
### Domain
|
|
226
|
-
backend
|
|
227
|
-
|
|
228
|
-
### Triggers
|
|
229
|
-
- api
|
|
230
|
-
- server
|
|
231
|
-
|
|
232
|
-
### Rules
|
|
233
|
-
- Use TypeScript
|
|
234
|
-
- Log errors
|
|
235
|
-
|
|
236
|
-
### Patterns
|
|
237
|
-
\`\`\`typescript
|
|
238
|
-
export async function handler() {}
|
|
239
|
-
\`\`\`
|
|
240
|
-
`
|
|
241
|
-
)
|
|
242
|
-
|
|
243
|
-
const result = await resolver.resolveAgentsForPath(testDir)
|
|
244
|
-
const md = resolver.generateAgentMarkdown(result.agents[0])
|
|
245
|
-
|
|
246
|
-
expect(md).toContain('# Backend Agent')
|
|
247
|
-
expect(md).toContain('Backend development specialist.')
|
|
248
|
-
expect(md).toContain('## DOMAIN AUTHORITY')
|
|
249
|
-
expect(md).toContain('backend domain')
|
|
250
|
-
expect(md).toContain('## Triggers')
|
|
251
|
-
expect(md).toContain('- api')
|
|
252
|
-
expect(md).toContain('## Rules')
|
|
253
|
-
expect(md).toContain('- Use TypeScript')
|
|
254
|
-
expect(md).toContain('## Patterns')
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
test('includes source attribution', async () => {
|
|
258
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Agent\n\nTest agent.')
|
|
259
|
-
|
|
260
|
-
const result = await resolver.resolveAgentsForPath(testDir)
|
|
261
|
-
const md = resolver.generateAgentMarkdown(result.agents[0])
|
|
262
|
-
|
|
263
|
-
expect(md).toContain('*Resolved from:')
|
|
264
|
-
expect(md).toContain('AGENTS.md')
|
|
265
|
-
})
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
// =============================================================================
|
|
269
|
-
// Hierarchical Resolution Tests
|
|
270
|
-
// =============================================================================
|
|
271
|
-
|
|
272
|
-
describe('HierarchicalAgentResolver - Hierarchy', () => {
|
|
273
|
-
test('merges triggers from parent and child', async () => {
|
|
274
|
-
await fs.writeFile(
|
|
275
|
-
path.join(testDir, 'AGENTS.md'),
|
|
276
|
-
`## Shared
|
|
277
|
-
|
|
278
|
-
Base agent.
|
|
279
|
-
|
|
280
|
-
### Triggers
|
|
281
|
-
- root-trigger
|
|
282
|
-
`
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
const childDir = path.join(testDir, 'child')
|
|
286
|
-
await fs.mkdir(childDir)
|
|
287
|
-
await fs.writeFile(
|
|
288
|
-
path.join(childDir, 'AGENTS.md'),
|
|
289
|
-
`## Shared
|
|
290
|
-
|
|
291
|
-
Extended agent.
|
|
292
|
-
|
|
293
|
-
### Triggers
|
|
294
|
-
- child-trigger
|
|
295
|
-
`
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
const result = await resolver.resolveAgentsForPath(childDir)
|
|
299
|
-
|
|
300
|
-
expect(result.agents[0].triggers).toContain('root-trigger')
|
|
301
|
-
expect(result.agents[0].triggers).toContain('child-trigger')
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
test('tracks overridden agents', async () => {
|
|
305
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Agent\n\nRoot.')
|
|
306
|
-
|
|
307
|
-
const childDir = path.join(testDir, 'child')
|
|
308
|
-
await fs.mkdir(childDir)
|
|
309
|
-
await fs.writeFile(path.join(childDir, 'AGENTS.md'), '## Agent @override\n\nChild override.')
|
|
310
|
-
|
|
311
|
-
const result = await resolver.resolveAgentsForPath(childDir)
|
|
312
|
-
|
|
313
|
-
expect(result.overriddenAgents).toContain('Agent')
|
|
314
|
-
expect(result.agents[0].wasOverridden).toBe(true)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
test('path-specific resolution', async () => {
|
|
318
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Global\n\nGlobal.')
|
|
319
|
-
|
|
320
|
-
const apiDir = path.join(testDir, 'packages', 'api')
|
|
321
|
-
await fs.mkdir(apiDir, { recursive: true })
|
|
322
|
-
await fs.writeFile(path.join(apiDir, 'AGENTS.md'), '## API\n\nAPI specific.')
|
|
323
|
-
|
|
324
|
-
const webDir = path.join(testDir, 'packages', 'web')
|
|
325
|
-
await fs.mkdir(webDir, { recursive: true })
|
|
326
|
-
await fs.writeFile(path.join(webDir, 'AGENTS.md'), '## Web\n\nWeb specific.')
|
|
327
|
-
|
|
328
|
-
// Resolve for API path
|
|
329
|
-
const apiResult = await resolver.resolveAgentsForPath(apiDir)
|
|
330
|
-
expect(apiResult.agents.map((a) => a.name).sort()).toEqual(['API', 'Global'])
|
|
331
|
-
|
|
332
|
-
// Resolve for Web path
|
|
333
|
-
const webResult = await resolver.resolveAgentsForPath(webDir)
|
|
334
|
-
expect(webResult.agents.map((a) => a.name).sort()).toEqual(['Global', 'Web'])
|
|
335
|
-
})
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
// =============================================================================
|
|
339
|
-
// Agent File Tree Tests
|
|
340
|
-
// =============================================================================
|
|
341
|
-
|
|
342
|
-
describe('HierarchicalAgentResolver - getAgentFileTree', () => {
|
|
343
|
-
test('returns hierarchical tree structure', async () => {
|
|
344
|
-
await fs.writeFile(path.join(testDir, 'AGENTS.md'), '## Root\n\nRoot.')
|
|
345
|
-
|
|
346
|
-
const childDir = path.join(testDir, 'child')
|
|
347
|
-
await fs.mkdir(childDir)
|
|
348
|
-
await fs.writeFile(path.join(childDir, 'AGENTS.md'), '## Child\n\nChild.')
|
|
349
|
-
|
|
350
|
-
const tree = await resolver.getAgentFileTree()
|
|
351
|
-
|
|
352
|
-
expect(tree).toHaveLength(2)
|
|
353
|
-
const root = tree.find((n) => n.depth === 0)
|
|
354
|
-
const child = tree.find((n) => n.depth > 0)
|
|
355
|
-
|
|
356
|
-
expect(root?.children).toContain(child)
|
|
357
|
-
expect(child?.parent).toBe(root)
|
|
358
|
-
})
|
|
359
|
-
})
|