opentasks 0.0.7 → 0.0.9
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/dist/daemon/entire-linker.d.ts.map +1 -1
- package/dist/daemon/entire-linker.js +42 -48
- package/dist/daemon/entire-linker.js.map +1 -1
- package/dist/daemon/entire-watcher.d.ts +0 -11
- package/dist/daemon/entire-watcher.d.ts.map +1 -1
- package/dist/daemon/entire-watcher.js +1 -32
- package/dist/daemon/entire-watcher.js.map +1 -1
- package/dist/graph/query.js +3 -3
- package/dist/graph/query.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/entire.d.ts +0 -10
- package/dist/providers/entire.d.ts.map +1 -1
- package/dist/providers/entire.js +0 -13
- package/dist/providers/entire.js.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/map-connector.d.ts +87 -0
- package/dist/providers/map-connector.d.ts.map +1 -0
- package/dist/providers/map-connector.js +159 -0
- package/dist/providers/map-connector.js.map +1 -0
- package/dist/storage/interface.d.ts +6 -0
- package/dist/storage/interface.d.ts.map +1 -1
- package/dist/storage/interface.js.map +1 -1
- package/dist/storage/sqlite.d.ts +1 -0
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +11 -0
- package/dist/storage/sqlite.js.map +1 -1
- package/package.json +2 -2
- package/dist/__tests__/cli-tools.test.d.ts +0 -8
- package/dist/__tests__/cli-tools.test.d.ts.map +0 -1
- package/dist/__tests__/cli-tools.test.js +0 -546
- package/dist/__tests__/cli-tools.test.js.map +0 -1
- package/dist/__tests__/cli.test.d.ts +0 -5
- package/dist/__tests__/cli.test.d.ts.map +0 -1
- package/dist/__tests__/cli.test.js +0 -77
- package/dist/__tests__/cli.test.js.map +0 -1
- package/dist/__tests__/p1-p3-gaps.test.d.ts +0 -2
- package/dist/__tests__/p1-p3-gaps.test.d.ts.map +0 -1
- package/dist/__tests__/p1-p3-gaps.test.js +0 -463
- package/dist/__tests__/p1-p3-gaps.test.js.map +0 -1
- package/dist/client/__tests__/client-crud.test.d.ts +0 -7
- package/dist/client/__tests__/client-crud.test.d.ts.map +0 -1
- package/dist/client/__tests__/client-crud.test.js +0 -404
- package/dist/client/__tests__/client-crud.test.js.map +0 -1
- package/dist/client/__tests__/client.test.d.ts +0 -5
- package/dist/client/__tests__/client.test.d.ts.map +0 -1
- package/dist/client/__tests__/client.test.js +0 -518
- package/dist/client/__tests__/client.test.js.map +0 -1
- package/dist/config/__tests__/defaults.test.d.ts +0 -2
- package/dist/config/__tests__/defaults.test.d.ts.map +0 -1
- package/dist/config/__tests__/defaults.test.js +0 -57
- package/dist/config/__tests__/defaults.test.js.map +0 -1
- package/dist/config/__tests__/env.test.d.ts +0 -2
- package/dist/config/__tests__/env.test.d.ts.map +0 -1
- package/dist/config/__tests__/env.test.js +0 -136
- package/dist/config/__tests__/env.test.js.map +0 -1
- package/dist/config/__tests__/index.test.d.ts +0 -2
- package/dist/config/__tests__/index.test.d.ts.map +0 -1
- package/dist/config/__tests__/index.test.js +0 -113
- package/dist/config/__tests__/index.test.js.map +0 -1
- package/dist/config/__tests__/loader.test.d.ts +0 -2
- package/dist/config/__tests__/loader.test.d.ts.map +0 -1
- package/dist/config/__tests__/loader.test.js +0 -128
- package/dist/config/__tests__/loader.test.js.map +0 -1
- package/dist/config/__tests__/merge.test.d.ts +0 -2
- package/dist/config/__tests__/merge.test.d.ts.map +0 -1
- package/dist/config/__tests__/merge.test.js +0 -79
- package/dist/config/__tests__/merge.test.js.map +0 -1
- package/dist/config/__tests__/schema.test.d.ts +0 -2
- package/dist/config/__tests__/schema.test.d.ts.map +0 -1
- package/dist/config/__tests__/schema.test.js +0 -300
- package/dist/config/__tests__/schema.test.js.map +0 -1
- package/dist/core/__tests__/conditional-redirects.test.d.ts +0 -2
- package/dist/core/__tests__/conditional-redirects.test.d.ts.map +0 -1
- package/dist/core/__tests__/conditional-redirects.test.js +0 -83
- package/dist/core/__tests__/conditional-redirects.test.js.map +0 -1
- package/dist/core/__tests__/connections.test.d.ts +0 -2
- package/dist/core/__tests__/connections.test.d.ts.map +0 -1
- package/dist/core/__tests__/connections.test.js +0 -158
- package/dist/core/__tests__/connections.test.js.map +0 -1
- package/dist/core/__tests__/hash.test.d.ts +0 -2
- package/dist/core/__tests__/hash.test.d.ts.map +0 -1
- package/dist/core/__tests__/hash.test.js +0 -139
- package/dist/core/__tests__/hash.test.js.map +0 -1
- package/dist/core/__tests__/id.test.d.ts +0 -2
- package/dist/core/__tests__/id.test.d.ts.map +0 -1
- package/dist/core/__tests__/id.test.js +0 -142
- package/dist/core/__tests__/id.test.js.map +0 -1
- package/dist/core/__tests__/location.test.d.ts +0 -2
- package/dist/core/__tests__/location.test.d.ts.map +0 -1
- package/dist/core/__tests__/location.test.js +0 -77
- package/dist/core/__tests__/location.test.js.map +0 -1
- package/dist/core/__tests__/merge-driver.test.d.ts +0 -2
- package/dist/core/__tests__/merge-driver.test.d.ts.map +0 -1
- package/dist/core/__tests__/merge-driver.test.js +0 -218
- package/dist/core/__tests__/merge-driver.test.js.map +0 -1
- package/dist/core/__tests__/redirects.test.d.ts +0 -2
- package/dist/core/__tests__/redirects.test.d.ts.map +0 -1
- package/dist/core/__tests__/redirects.test.js +0 -123
- package/dist/core/__tests__/redirects.test.js.map +0 -1
- package/dist/core/__tests__/resolve-location-target.test.d.ts +0 -8
- package/dist/core/__tests__/resolve-location-target.test.d.ts.map +0 -1
- package/dist/core/__tests__/resolve-location-target.test.js +0 -303
- package/dist/core/__tests__/resolve-location-target.test.js.map +0 -1
- package/dist/core/__tests__/uri.test.d.ts +0 -2
- package/dist/core/__tests__/uri.test.d.ts.map +0 -1
- package/dist/core/__tests__/uri.test.js +0 -159
- package/dist/core/__tests__/uri.test.js.map +0 -1
- package/dist/core/__tests__/worktree.test.d.ts +0 -2
- package/dist/core/__tests__/worktree.test.d.ts.map +0 -1
- package/dist/core/__tests__/worktree.test.js +0 -120
- package/dist/core/__tests__/worktree.test.js.map +0 -1
- package/dist/daemon/__tests__/flush.test.d.ts +0 -5
- package/dist/daemon/__tests__/flush.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/flush.test.js +0 -213
- package/dist/daemon/__tests__/flush.test.js.map +0 -1
- package/dist/daemon/__tests__/integration.test.d.ts +0 -7
- package/dist/daemon/__tests__/integration.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/integration.test.js +0 -276
- package/dist/daemon/__tests__/integration.test.js.map +0 -1
- package/dist/daemon/__tests__/ipc.test.d.ts +0 -5
- package/dist/daemon/__tests__/ipc.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/ipc.test.js +0 -314
- package/dist/daemon/__tests__/ipc.test.js.map +0 -1
- package/dist/daemon/__tests__/lifecycle.test.d.ts +0 -5
- package/dist/daemon/__tests__/lifecycle.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/lifecycle.test.js +0 -301
- package/dist/daemon/__tests__/lifecycle.test.js.map +0 -1
- package/dist/daemon/__tests__/lock.test.d.ts +0 -5
- package/dist/daemon/__tests__/lock.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/lock.test.js +0 -192
- package/dist/daemon/__tests__/lock.test.js.map +0 -1
- package/dist/daemon/__tests__/methods/graph.test.d.ts +0 -5
- package/dist/daemon/__tests__/methods/graph.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/methods/graph.test.js +0 -309
- package/dist/daemon/__tests__/methods/graph.test.js.map +0 -1
- package/dist/daemon/__tests__/methods/provider.test.d.ts +0 -7
- package/dist/daemon/__tests__/methods/provider.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/methods/provider.test.js +0 -181
- package/dist/daemon/__tests__/methods/provider.test.js.map +0 -1
- package/dist/daemon/__tests__/methods/tools.test.d.ts +0 -5
- package/dist/daemon/__tests__/methods/tools.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/methods/tools.test.js +0 -587
- package/dist/daemon/__tests__/methods/tools.test.js.map +0 -1
- package/dist/daemon/__tests__/multi-location.test.d.ts +0 -8
- package/dist/daemon/__tests__/multi-location.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/multi-location.test.js +0 -669
- package/dist/daemon/__tests__/multi-location.test.js.map +0 -1
- package/dist/daemon/__tests__/registry.test.d.ts +0 -5
- package/dist/daemon/__tests__/registry.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/registry.test.js +0 -208
- package/dist/daemon/__tests__/registry.test.js.map +0 -1
- package/dist/daemon/__tests__/watcher.test.d.ts +0 -5
- package/dist/daemon/__tests__/watcher.test.d.ts.map +0 -1
- package/dist/daemon/__tests__/watcher.test.js +0 -234
- package/dist/daemon/__tests__/watcher.test.js.map +0 -1
- package/dist/daemon/methods/__tests__/graph.test.d.ts +0 -5
- package/dist/daemon/methods/__tests__/graph.test.d.ts.map +0 -1
- package/dist/daemon/methods/__tests__/graph.test.js +0 -274
- package/dist/daemon/methods/__tests__/graph.test.js.map +0 -1
- package/dist/daemon/methods/__tests__/provider.test.d.ts +0 -5
- package/dist/daemon/methods/__tests__/provider.test.d.ts.map +0 -1
- package/dist/daemon/methods/__tests__/provider.test.js +0 -184
- package/dist/daemon/methods/__tests__/provider.test.js.map +0 -1
- package/dist/daemon/methods/__tests__/tools.test.d.ts +0 -5
- package/dist/daemon/methods/__tests__/tools.test.d.ts.map +0 -1
- package/dist/daemon/methods/__tests__/tools.test.js +0 -295
- package/dist/daemon/methods/__tests__/tools.test.js.map +0 -1
- package/dist/entire/agent/agents/claude-code.d.ts +0 -76
- package/dist/entire/agent/agents/claude-code.d.ts.map +0 -1
- package/dist/entire/agent/agents/claude-code.js +0 -759
- package/dist/entire/agent/agents/claude-code.js.map +0 -1
- package/dist/entire/agent/agents/cursor.d.ts +0 -35
- package/dist/entire/agent/agents/cursor.d.ts.map +0 -1
- package/dist/entire/agent/agents/cursor.js +0 -294
- package/dist/entire/agent/agents/cursor.js.map +0 -1
- package/dist/entire/agent/agents/gemini-cli.d.ts +0 -62
- package/dist/entire/agent/agents/gemini-cli.d.ts.map +0 -1
- package/dist/entire/agent/agents/gemini-cli.js +0 -462
- package/dist/entire/agent/agents/gemini-cli.js.map +0 -1
- package/dist/entire/agent/agents/opencode.d.ts +0 -100
- package/dist/entire/agent/agents/opencode.d.ts.map +0 -1
- package/dist/entire/agent/agents/opencode.js +0 -423
- package/dist/entire/agent/agents/opencode.js.map +0 -1
- package/dist/entire/agent/registry.d.ts +0 -54
- package/dist/entire/agent/registry.d.ts.map +0 -1
- package/dist/entire/agent/registry.js +0 -123
- package/dist/entire/agent/registry.js.map +0 -1
- package/dist/entire/agent/session-types.d.ts +0 -45
- package/dist/entire/agent/session-types.d.ts.map +0 -1
- package/dist/entire/agent/session-types.js +0 -50
- package/dist/entire/agent/session-types.js.map +0 -1
- package/dist/entire/agent/types.d.ts +0 -126
- package/dist/entire/agent/types.d.ts.map +0 -1
- package/dist/entire/agent/types.js +0 -39
- package/dist/entire/agent/types.js.map +0 -1
- package/dist/entire/commands/clean.d.ts +0 -30
- package/dist/entire/commands/clean.d.ts.map +0 -1
- package/dist/entire/commands/clean.js +0 -99
- package/dist/entire/commands/clean.js.map +0 -1
- package/dist/entire/commands/disable.d.ts +0 -23
- package/dist/entire/commands/disable.d.ts.map +0 -1
- package/dist/entire/commands/disable.js +0 -57
- package/dist/entire/commands/disable.js.map +0 -1
- package/dist/entire/commands/doctor.d.ts +0 -43
- package/dist/entire/commands/doctor.d.ts.map +0 -1
- package/dist/entire/commands/doctor.js +0 -97
- package/dist/entire/commands/doctor.js.map +0 -1
- package/dist/entire/commands/enable.d.ts +0 -29
- package/dist/entire/commands/enable.d.ts.map +0 -1
- package/dist/entire/commands/enable.js +0 -102
- package/dist/entire/commands/enable.js.map +0 -1
- package/dist/entire/commands/explain.d.ts +0 -68
- package/dist/entire/commands/explain.d.ts.map +0 -1
- package/dist/entire/commands/explain.js +0 -182
- package/dist/entire/commands/explain.js.map +0 -1
- package/dist/entire/commands/reset.d.ts +0 -23
- package/dist/entire/commands/reset.d.ts.map +0 -1
- package/dist/entire/commands/reset.js +0 -68
- package/dist/entire/commands/reset.js.map +0 -1
- package/dist/entire/commands/resume.d.ts +0 -42
- package/dist/entire/commands/resume.d.ts.map +0 -1
- package/dist/entire/commands/resume.js +0 -134
- package/dist/entire/commands/resume.js.map +0 -1
- package/dist/entire/commands/rewind.d.ts +0 -34
- package/dist/entire/commands/rewind.d.ts.map +0 -1
- package/dist/entire/commands/rewind.js +0 -155
- package/dist/entire/commands/rewind.js.map +0 -1
- package/dist/entire/commands/status.d.ts +0 -51
- package/dist/entire/commands/status.d.ts.map +0 -1
- package/dist/entire/commands/status.js +0 -94
- package/dist/entire/commands/status.js.map +0 -1
- package/dist/entire/config.d.ts +0 -40
- package/dist/entire/config.d.ts.map +0 -1
- package/dist/entire/config.js +0 -126
- package/dist/entire/config.js.map +0 -1
- package/dist/entire/git-operations.d.ts +0 -170
- package/dist/entire/git-operations.d.ts.map +0 -1
- package/dist/entire/git-operations.js +0 -395
- package/dist/entire/git-operations.js.map +0 -1
- package/dist/entire/hooks/git-hooks.d.ts +0 -22
- package/dist/entire/hooks/git-hooks.d.ts.map +0 -1
- package/dist/entire/hooks/git-hooks.js +0 -145
- package/dist/entire/hooks/git-hooks.js.map +0 -1
- package/dist/entire/hooks/lifecycle.d.ts +0 -21
- package/dist/entire/hooks/lifecycle.d.ts.map +0 -1
- package/dist/entire/hooks/lifecycle.js +0 -179
- package/dist/entire/hooks/lifecycle.js.map +0 -1
- package/dist/entire/index.d.ts +0 -69
- package/dist/entire/index.d.ts.map +0 -1
- package/dist/entire/index.js +0 -152
- package/dist/entire/index.js.map +0 -1
- package/dist/entire/security/redaction.d.ts +0 -35
- package/dist/entire/security/redaction.d.ts.map +0 -1
- package/dist/entire/security/redaction.js +0 -221
- package/dist/entire/security/redaction.js.map +0 -1
- package/dist/entire/session/state-machine.d.ts +0 -90
- package/dist/entire/session/state-machine.d.ts.map +0 -1
- package/dist/entire/session/state-machine.js +0 -347
- package/dist/entire/session/state-machine.js.map +0 -1
- package/dist/entire/store/checkpoint-store.d.ts +0 -47
- package/dist/entire/store/checkpoint-store.d.ts.map +0 -1
- package/dist/entire/store/checkpoint-store.js +0 -307
- package/dist/entire/store/checkpoint-store.js.map +0 -1
- package/dist/entire/store/native-store.d.ts +0 -14
- package/dist/entire/store/native-store.d.ts.map +0 -1
- package/dist/entire/store/native-store.js +0 -159
- package/dist/entire/store/native-store.js.map +0 -1
- package/dist/entire/store/provider-types.d.ts +0 -78
- package/dist/entire/store/provider-types.d.ts.map +0 -1
- package/dist/entire/store/provider-types.js +0 -12
- package/dist/entire/store/provider-types.js.map +0 -1
- package/dist/entire/store/session-store.d.ts +0 -28
- package/dist/entire/store/session-store.d.ts.map +0 -1
- package/dist/entire/store/session-store.js +0 -187
- package/dist/entire/store/session-store.js.map +0 -1
- package/dist/entire/strategy/attribution.d.ts +0 -39
- package/dist/entire/strategy/attribution.d.ts.map +0 -1
- package/dist/entire/strategy/attribution.js +0 -227
- package/dist/entire/strategy/attribution.js.map +0 -1
- package/dist/entire/strategy/common.d.ts +0 -57
- package/dist/entire/strategy/common.d.ts.map +0 -1
- package/dist/entire/strategy/common.js +0 -156
- package/dist/entire/strategy/common.js.map +0 -1
- package/dist/entire/strategy/content-overlap.d.ts +0 -33
- package/dist/entire/strategy/content-overlap.d.ts.map +0 -1
- package/dist/entire/strategy/content-overlap.js +0 -168
- package/dist/entire/strategy/content-overlap.js.map +0 -1
- package/dist/entire/strategy/manual-commit.d.ts +0 -31
- package/dist/entire/strategy/manual-commit.d.ts.map +0 -1
- package/dist/entire/strategy/manual-commit.js +0 -730
- package/dist/entire/strategy/manual-commit.js.map +0 -1
- package/dist/entire/strategy/types.d.ts +0 -163
- package/dist/entire/strategy/types.d.ts.map +0 -1
- package/dist/entire/strategy/types.js +0 -49
- package/dist/entire/strategy/types.js.map +0 -1
- package/dist/entire/summarize/claude-generator.d.ts +0 -25
- package/dist/entire/summarize/claude-generator.d.ts.map +0 -1
- package/dist/entire/summarize/claude-generator.js +0 -87
- package/dist/entire/summarize/claude-generator.js.map +0 -1
- package/dist/entire/summarize/summarize.d.ts +0 -52
- package/dist/entire/summarize/summarize.d.ts.map +0 -1
- package/dist/entire/summarize/summarize.js +0 -335
- package/dist/entire/summarize/summarize.js.map +0 -1
- package/dist/entire/types.d.ts +0 -288
- package/dist/entire/types.d.ts.map +0 -1
- package/dist/entire/types.js +0 -94
- package/dist/entire/types.js.map +0 -1
- package/dist/entire/utils/chunk-files.d.ts +0 -25
- package/dist/entire/utils/chunk-files.d.ts.map +0 -1
- package/dist/entire/utils/chunk-files.js +0 -47
- package/dist/entire/utils/chunk-files.js.map +0 -1
- package/dist/entire/utils/commit-message.d.ts +0 -11
- package/dist/entire/utils/commit-message.d.ts.map +0 -1
- package/dist/entire/utils/commit-message.js +0 -54
- package/dist/entire/utils/commit-message.js.map +0 -1
- package/dist/entire/utils/detect-agent.d.ts +0 -19
- package/dist/entire/utils/detect-agent.d.ts.map +0 -1
- package/dist/entire/utils/detect-agent.js +0 -34
- package/dist/entire/utils/detect-agent.js.map +0 -1
- package/dist/entire/utils/hook-managers.d.ts +0 -24
- package/dist/entire/utils/hook-managers.d.ts.map +0 -1
- package/dist/entire/utils/hook-managers.js +0 -87
- package/dist/entire/utils/hook-managers.js.map +0 -1
- package/dist/entire/utils/ide-tags.d.ts +0 -12
- package/dist/entire/utils/ide-tags.d.ts.map +0 -1
- package/dist/entire/utils/ide-tags.js +0 -30
- package/dist/entire/utils/ide-tags.js.map +0 -1
- package/dist/entire/utils/paths.d.ts +0 -32
- package/dist/entire/utils/paths.d.ts.map +0 -1
- package/dist/entire/utils/paths.js +0 -55
- package/dist/entire/utils/paths.js.map +0 -1
- package/dist/entire/utils/preview-rewind.d.ts +0 -23
- package/dist/entire/utils/preview-rewind.d.ts.map +0 -1
- package/dist/entire/utils/preview-rewind.js +0 -63
- package/dist/entire/utils/preview-rewind.js.map +0 -1
- package/dist/entire/utils/rewind-conflict.d.ts +0 -52
- package/dist/entire/utils/rewind-conflict.d.ts.map +0 -1
- package/dist/entire/utils/rewind-conflict.js +0 -79
- package/dist/entire/utils/rewind-conflict.js.map +0 -1
- package/dist/entire/utils/shadow-branch.d.ts +0 -44
- package/dist/entire/utils/shadow-branch.d.ts.map +0 -1
- package/dist/entire/utils/shadow-branch.js +0 -93
- package/dist/entire/utils/shadow-branch.js.map +0 -1
- package/dist/entire/utils/string-utils.d.ts +0 -24
- package/dist/entire/utils/string-utils.d.ts.map +0 -1
- package/dist/entire/utils/string-utils.js +0 -47
- package/dist/entire/utils/string-utils.js.map +0 -1
- package/dist/entire/utils/todo-extract.d.ts +0 -52
- package/dist/entire/utils/todo-extract.d.ts.map +0 -1
- package/dist/entire/utils/todo-extract.js +0 -167
- package/dist/entire/utils/todo-extract.js.map +0 -1
- package/dist/entire/utils/trailers.d.ts +0 -36
- package/dist/entire/utils/trailers.d.ts.map +0 -1
- package/dist/entire/utils/trailers.js +0 -149
- package/dist/entire/utils/trailers.js.map +0 -1
- package/dist/entire/utils/transcript-parse.d.ts +0 -57
- package/dist/entire/utils/transcript-parse.d.ts.map +0 -1
- package/dist/entire/utils/transcript-parse.js +0 -126
- package/dist/entire/utils/transcript-parse.js.map +0 -1
- package/dist/entire/utils/transcript-timestamp.d.ts +0 -22
- package/dist/entire/utils/transcript-timestamp.d.ts.map +0 -1
- package/dist/entire/utils/transcript-timestamp.js +0 -56
- package/dist/entire/utils/transcript-timestamp.js.map +0 -1
- package/dist/entire/utils/tree-ops.d.ts +0 -47
- package/dist/entire/utils/tree-ops.d.ts.map +0 -1
- package/dist/entire/utils/tree-ops.js +0 -145
- package/dist/entire/utils/tree-ops.js.map +0 -1
- package/dist/entire/utils/tty.d.ts +0 -25
- package/dist/entire/utils/tty.d.ts.map +0 -1
- package/dist/entire/utils/tty.js +0 -70
- package/dist/entire/utils/tty.js.map +0 -1
- package/dist/entire/utils/validation.d.ts +0 -31
- package/dist/entire/utils/validation.d.ts.map +0 -1
- package/dist/entire/utils/validation.js +0 -59
- package/dist/entire/utils/validation.js.map +0 -1
- package/dist/entire/utils/worktree.d.ts +0 -16
- package/dist/entire/utils/worktree.d.ts.map +0 -1
- package/dist/entire/utils/worktree.js +0 -50
- package/dist/entire/utils/worktree.js.map +0 -1
- package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts +0 -2
- package/dist/graph/__tests__/EdgeTypeRegistry.test.d.ts.map +0 -1
- package/dist/graph/__tests__/EdgeTypeRegistry.test.js +0 -212
- package/dist/graph/__tests__/EdgeTypeRegistry.test.js.map +0 -1
- package/dist/graph/__tests__/FederatedGraph.test.d.ts +0 -2
- package/dist/graph/__tests__/FederatedGraph.test.d.ts.map +0 -1
- package/dist/graph/__tests__/FederatedGraph.test.js +0 -661
- package/dist/graph/__tests__/FederatedGraph.test.js.map +0 -1
- package/dist/graph/__tests__/GraphologyAdapter.test.d.ts +0 -2
- package/dist/graph/__tests__/GraphologyAdapter.test.d.ts.map +0 -1
- package/dist/graph/__tests__/GraphologyAdapter.test.js +0 -326
- package/dist/graph/__tests__/GraphologyAdapter.test.js.map +0 -1
- package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts +0 -2
- package/dist/graph/__tests__/HydratingFederatedGraph.test.d.ts.map +0 -1
- package/dist/graph/__tests__/HydratingFederatedGraph.test.js +0 -587
- package/dist/graph/__tests__/HydratingFederatedGraph.test.js.map +0 -1
- package/dist/graph/__tests__/debounce.test.d.ts +0 -5
- package/dist/graph/__tests__/debounce.test.d.ts.map +0 -1
- package/dist/graph/__tests__/debounce.test.js +0 -195
- package/dist/graph/__tests__/debounce.test.js.map +0 -1
- package/dist/graph/__tests__/edge-cases.test.d.ts +0 -8
- package/dist/graph/__tests__/edge-cases.test.d.ts.map +0 -1
- package/dist/graph/__tests__/edge-cases.test.js +0 -472
- package/dist/graph/__tests__/edge-cases.test.js.map +0 -1
- package/dist/graph/__tests__/expansion.test.d.ts +0 -2
- package/dist/graph/__tests__/expansion.test.d.ts.map +0 -1
- package/dist/graph/__tests__/expansion.test.js +0 -105
- package/dist/graph/__tests__/expansion.test.js.map +0 -1
- package/dist/graph/__tests__/provider-store.test.d.ts +0 -5
- package/dist/graph/__tests__/provider-store.test.d.ts.map +0 -1
- package/dist/graph/__tests__/provider-store.test.js +0 -791
- package/dist/graph/__tests__/provider-store.test.js.map +0 -1
- package/dist/graph/__tests__/query.test.d.ts +0 -5
- package/dist/graph/__tests__/query.test.d.ts.map +0 -1
- package/dist/graph/__tests__/query.test.js +0 -774
- package/dist/graph/__tests__/query.test.js.map +0 -1
- package/dist/graph/__tests__/store.test.d.ts +0 -5
- package/dist/graph/__tests__/store.test.d.ts.map +0 -1
- package/dist/graph/__tests__/store.test.js +0 -489
- package/dist/graph/__tests__/store.test.js.map +0 -1
- package/dist/graph/__tests__/sync.test.d.ts +0 -5
- package/dist/graph/__tests__/sync.test.d.ts.map +0 -1
- package/dist/graph/__tests__/sync.test.js +0 -129
- package/dist/graph/__tests__/sync.test.js.map +0 -1
- package/dist/graph/__tests__/validation.test.d.ts +0 -2
- package/dist/graph/__tests__/validation.test.d.ts.map +0 -1
- package/dist/graph/__tests__/validation.test.js +0 -521
- package/dist/graph/__tests__/validation.test.js.map +0 -1
- package/dist/providers/__tests__/beads.test.d.ts +0 -5
- package/dist/providers/__tests__/beads.test.d.ts.map +0 -1
- package/dist/providers/__tests__/beads.test.js +0 -591
- package/dist/providers/__tests__/beads.test.js.map +0 -1
- package/dist/providers/__tests__/claude-tasks.test.d.ts +0 -5
- package/dist/providers/__tests__/claude-tasks.test.d.ts.map +0 -1
- package/dist/providers/__tests__/claude-tasks.test.js +0 -392
- package/dist/providers/__tests__/claude-tasks.test.js.map +0 -1
- package/dist/providers/__tests__/from-config.test.d.ts +0 -5
- package/dist/providers/__tests__/from-config.test.d.ts.map +0 -1
- package/dist/providers/__tests__/from-config.test.js +0 -152
- package/dist/providers/__tests__/from-config.test.js.map +0 -1
- package/dist/providers/__tests__/materialization.test.d.ts +0 -5
- package/dist/providers/__tests__/materialization.test.d.ts.map +0 -1
- package/dist/providers/__tests__/materialization.test.js +0 -407
- package/dist/providers/__tests__/materialization.test.js.map +0 -1
- package/dist/providers/__tests__/native.test.d.ts +0 -5
- package/dist/providers/__tests__/native.test.d.ts.map +0 -1
- package/dist/providers/__tests__/native.test.js +0 -566
- package/dist/providers/__tests__/native.test.js.map +0 -1
- package/dist/providers/__tests__/registry.test.d.ts +0 -5
- package/dist/providers/__tests__/registry.test.d.ts.map +0 -1
- package/dist/providers/__tests__/registry.test.js +0 -183
- package/dist/providers/__tests__/registry.test.js.map +0 -1
- package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts +0 -2
- package/dist/providers/traits/__tests__/RelationshipQueryable.test.d.ts.map +0 -1
- package/dist/providers/traits/__tests__/RelationshipQueryable.test.js +0 -169
- package/dist/providers/traits/__tests__/RelationshipQueryable.test.js.map +0 -1
- package/dist/providers/traits/__tests__/TaskManageable.test.d.ts +0 -2
- package/dist/providers/traits/__tests__/TaskManageable.test.d.ts.map +0 -1
- package/dist/providers/traits/__tests__/TaskManageable.test.js +0 -172
- package/dist/providers/traits/__tests__/TaskManageable.test.js.map +0 -1
- package/dist/schema/__tests__/validation.test.d.ts +0 -2
- package/dist/schema/__tests__/validation.test.d.ts.map +0 -1
- package/dist/schema/__tests__/validation.test.js +0 -241
- package/dist/schema/__tests__/validation.test.js.map +0 -1
- package/dist/storage/__tests__/atomic-write.test.d.ts +0 -5
- package/dist/storage/__tests__/atomic-write.test.d.ts.map +0 -1
- package/dist/storage/__tests__/atomic-write.test.js +0 -170
- package/dist/storage/__tests__/atomic-write.test.js.map +0 -1
- package/dist/storage/__tests__/file-lock.test.d.ts +0 -2
- package/dist/storage/__tests__/file-lock.test.d.ts.map +0 -1
- package/dist/storage/__tests__/file-lock.test.js +0 -89
- package/dist/storage/__tests__/file-lock.test.js.map +0 -1
- package/dist/storage/__tests__/jsonl.test.d.ts +0 -2
- package/dist/storage/__tests__/jsonl.test.d.ts.map +0 -1
- package/dist/storage/__tests__/jsonl.test.js +0 -228
- package/dist/storage/__tests__/jsonl.test.js.map +0 -1
- package/dist/storage/__tests__/locked-writer.test.d.ts +0 -2
- package/dist/storage/__tests__/locked-writer.test.d.ts.map +0 -1
- package/dist/storage/__tests__/locked-writer.test.js +0 -109
- package/dist/storage/__tests__/locked-writer.test.js.map +0 -1
- package/dist/storage/__tests__/sqlite.test.d.ts +0 -2
- package/dist/storage/__tests__/sqlite.test.d.ts.map +0 -1
- package/dist/storage/__tests__/sqlite.test.js +0 -470
- package/dist/storage/__tests__/sqlite.test.js.map +0 -1
- package/dist/tools/__tests__/annotate.test.d.ts +0 -5
- package/dist/tools/__tests__/annotate.test.d.ts.map +0 -1
- package/dist/tools/__tests__/annotate.test.js +0 -314
- package/dist/tools/__tests__/annotate.test.js.map +0 -1
- package/dist/tools/__tests__/link.test.d.ts +0 -5
- package/dist/tools/__tests__/link.test.d.ts.map +0 -1
- package/dist/tools/__tests__/link.test.js +0 -245
- package/dist/tools/__tests__/link.test.js.map +0 -1
- package/dist/tools/__tests__/query.test.d.ts +0 -5
- package/dist/tools/__tests__/query.test.d.ts.map +0 -1
- package/dist/tools/__tests__/query.test.js +0 -288
- package/dist/tools/__tests__/query.test.js.map +0 -1
- package/dist/tools/__tests__/task.test.d.ts +0 -5
- package/dist/tools/__tests__/task.test.d.ts.map +0 -1
- package/dist/tools/__tests__/task.test.js +0 -178
- package/dist/tools/__tests__/task.test.js.map +0 -1
|
@@ -1,774 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for Query Engine
|
|
3
|
-
*/
|
|
4
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
5
|
-
import { createQueryEngine } from '../query.js';
|
|
6
|
-
// ============================================================================
|
|
7
|
-
// Test Fixtures
|
|
8
|
-
// ============================================================================
|
|
9
|
-
function createMockStorage() {
|
|
10
|
-
return {
|
|
11
|
-
createNode: vi.fn(),
|
|
12
|
-
getNode: vi.fn(),
|
|
13
|
-
updateNode: vi.fn(),
|
|
14
|
-
deleteNode: vi.fn(),
|
|
15
|
-
queryNodes: vi.fn().mockResolvedValue([]),
|
|
16
|
-
createEdge: vi.fn(),
|
|
17
|
-
getEdge: vi.fn(),
|
|
18
|
-
deleteEdge: vi.fn(),
|
|
19
|
-
getEdgesFrom: vi.fn().mockResolvedValue([]),
|
|
20
|
-
getEdgesTo: vi.fn().mockResolvedValue([]),
|
|
21
|
-
addTag: vi.fn(),
|
|
22
|
-
removeTag: vi.fn(),
|
|
23
|
-
getTags: vi.fn().mockResolvedValue([]),
|
|
24
|
-
getTagsForNodes: vi.fn().mockResolvedValue(new Map()),
|
|
25
|
-
getNodesByTag: vi.fn().mockResolvedValue([]),
|
|
26
|
-
getReady: vi.fn().mockResolvedValue([]),
|
|
27
|
-
runInTransaction: vi.fn(),
|
|
28
|
-
markDirty: vi.fn(),
|
|
29
|
-
getDirtyNodes: vi.fn().mockResolvedValue([]),
|
|
30
|
-
clearDirty: vi.fn(),
|
|
31
|
-
close: vi.fn(),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
function createSpec(id, title, overrides = {}) {
|
|
35
|
-
return {
|
|
36
|
-
id,
|
|
37
|
-
uuid: `uuid-${id}`,
|
|
38
|
-
type: 'spec',
|
|
39
|
-
title,
|
|
40
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
41
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
42
|
-
archived: false,
|
|
43
|
-
...overrides,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
function createIssue(id, title, status = 'open', overrides = {}) {
|
|
47
|
-
return {
|
|
48
|
-
id,
|
|
49
|
-
uuid: `uuid-${id}`,
|
|
50
|
-
type: 'issue',
|
|
51
|
-
title,
|
|
52
|
-
status,
|
|
53
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
54
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
55
|
-
archived: false,
|
|
56
|
-
...overrides,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
function createFeedback(id, targetId, overrides = {}) {
|
|
60
|
-
return {
|
|
61
|
-
id,
|
|
62
|
-
uuid: `uuid-${id}`,
|
|
63
|
-
type: 'feedback',
|
|
64
|
-
title: 'Feedback',
|
|
65
|
-
target_id: targetId,
|
|
66
|
-
feedback_type: 'comment',
|
|
67
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
68
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
69
|
-
archived: false,
|
|
70
|
-
resolved: false,
|
|
71
|
-
dismissed: false,
|
|
72
|
-
...overrides,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function createEdge(id, fromId, toId, type) {
|
|
76
|
-
return {
|
|
77
|
-
id,
|
|
78
|
-
uuid: `uuid-${id}`,
|
|
79
|
-
from_id: fromId,
|
|
80
|
-
to_id: toId,
|
|
81
|
-
type,
|
|
82
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
// ============================================================================
|
|
86
|
-
// Test Suites
|
|
87
|
-
// ============================================================================
|
|
88
|
-
describe('QueryEngine', () => {
|
|
89
|
-
let storage;
|
|
90
|
-
let engine;
|
|
91
|
-
beforeEach(() => {
|
|
92
|
-
storage = createMockStorage();
|
|
93
|
-
engine = createQueryEngine(storage);
|
|
94
|
-
});
|
|
95
|
-
describe('nodes()', () => {
|
|
96
|
-
it('should query nodes with filter', async () => {
|
|
97
|
-
const spec = createSpec('s-abc1', 'Test Spec');
|
|
98
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([spec]);
|
|
99
|
-
const result = await engine.nodes({ type: 'spec' });
|
|
100
|
-
expect(storage.queryNodes).toHaveBeenCalledWith({
|
|
101
|
-
type: 'spec',
|
|
102
|
-
status: undefined,
|
|
103
|
-
tags: undefined,
|
|
104
|
-
parent_id: undefined,
|
|
105
|
-
archived: undefined,
|
|
106
|
-
search: undefined,
|
|
107
|
-
limit: undefined,
|
|
108
|
-
offset: undefined,
|
|
109
|
-
});
|
|
110
|
-
expect(result).toHaveLength(1);
|
|
111
|
-
expect(result[0].id).toBe('s-abc1');
|
|
112
|
-
});
|
|
113
|
-
it('should filter out invalid nodes', async () => {
|
|
114
|
-
const validSpec = createSpec('s-abc1', 'Test Spec');
|
|
115
|
-
const invalidNode = { id: 'invalid', type: 'unknown' };
|
|
116
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([validSpec, invalidNode]);
|
|
117
|
-
const result = await engine.nodes({});
|
|
118
|
-
// Only valid spec should be returned
|
|
119
|
-
expect(result).toHaveLength(1);
|
|
120
|
-
expect(result[0].id).toBe('s-abc1');
|
|
121
|
-
});
|
|
122
|
-
it('should handle archived filter', async () => {
|
|
123
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([]);
|
|
124
|
-
await engine.nodes({ archived: false });
|
|
125
|
-
expect(storage.queryNodes).toHaveBeenCalledWith(expect.objectContaining({ archived: false }));
|
|
126
|
-
});
|
|
127
|
-
it('should convert null archived to undefined', async () => {
|
|
128
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([]);
|
|
129
|
-
await engine.nodes({ archived: null });
|
|
130
|
-
expect(storage.queryNodes).toHaveBeenCalledWith(expect.objectContaining({ archived: undefined }));
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
describe('edges()', () => {
|
|
134
|
-
it('should query edges from a node', async () => {
|
|
135
|
-
const edge = createEdge('x-abc1', 's-a', 's-b', 'references');
|
|
136
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([edge]);
|
|
137
|
-
const result = await engine.edges({ from_id: 's-a' });
|
|
138
|
-
expect(storage.getEdgesFrom).toHaveBeenCalledWith('s-a', undefined);
|
|
139
|
-
expect(result).toHaveLength(1);
|
|
140
|
-
expect(result[0].id).toBe('x-abc1');
|
|
141
|
-
});
|
|
142
|
-
it('should query edges to a node', async () => {
|
|
143
|
-
const edge = createEdge('x-abc1', 's-a', 's-b', 'references');
|
|
144
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
145
|
-
const result = await engine.edges({ to_id: 's-b' });
|
|
146
|
-
expect(storage.getEdgesTo).toHaveBeenCalledWith('s-b', undefined);
|
|
147
|
-
expect(result).toHaveLength(1);
|
|
148
|
-
});
|
|
149
|
-
it('should return empty when no filter specified', async () => {
|
|
150
|
-
const result = await engine.edges({});
|
|
151
|
-
expect(result).toHaveLength(0);
|
|
152
|
-
});
|
|
153
|
-
it('should apply pagination', async () => {
|
|
154
|
-
const edges = [
|
|
155
|
-
createEdge('x-1', 's-a', 's-b', 'references'),
|
|
156
|
-
createEdge('x-2', 's-a', 's-c', 'references'),
|
|
157
|
-
createEdge('x-3', 's-a', 's-d', 'references'),
|
|
158
|
-
];
|
|
159
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue(edges);
|
|
160
|
-
const result = await engine.edges({ from_id: 's-a', offset: 1, limit: 1 });
|
|
161
|
-
expect(result).toHaveLength(1);
|
|
162
|
-
expect(result[0].id).toBe('x-2');
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
describe('edgesFrom()', () => {
|
|
166
|
-
it('should get edges from a node', async () => {
|
|
167
|
-
const edge = createEdge('x-abc1', 's-a', 's-b', 'blocks');
|
|
168
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([edge]);
|
|
169
|
-
const result = await engine.edgesFrom('s-a', 'blocks');
|
|
170
|
-
expect(storage.getEdgesFrom).toHaveBeenCalledWith('s-a', 'blocks');
|
|
171
|
-
expect(result).toHaveLength(1);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
describe('edgesTo()', () => {
|
|
175
|
-
it('should get edges to a node', async () => {
|
|
176
|
-
const edge = createEdge('x-abc1', 's-a', 's-b', 'blocks');
|
|
177
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
178
|
-
const result = await engine.edgesTo('s-b', 'blocks');
|
|
179
|
-
expect(storage.getEdgesTo).toHaveBeenCalledWith('s-b', 'blocks');
|
|
180
|
-
expect(result).toHaveLength(1);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
describe('edgesFor()', () => {
|
|
184
|
-
it('should get all edges for a node (both directions)', async () => {
|
|
185
|
-
const fromEdge = createEdge('x-1', 's-a', 's-b', 'blocks');
|
|
186
|
-
const toEdge = createEdge('x-2', 's-c', 's-a', 'references');
|
|
187
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([fromEdge]);
|
|
188
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([toEdge]);
|
|
189
|
-
const result = await engine.edgesFor('s-a');
|
|
190
|
-
expect(result).toHaveLength(2);
|
|
191
|
-
expect(result.map((e) => e.id).sort()).toEqual(['x-1', 'x-2']);
|
|
192
|
-
});
|
|
193
|
-
it('should deduplicate edges', async () => {
|
|
194
|
-
const edge = createEdge('x-1', 's-a', 's-a', 'references'); // self-reference
|
|
195
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([edge]);
|
|
196
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
197
|
-
const result = await engine.edgesFor('s-a');
|
|
198
|
-
expect(result).toHaveLength(1);
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
describe('blockers()', () => {
|
|
202
|
-
it('should get direct blockers', async () => {
|
|
203
|
-
const blocker = createIssue('i-blocker', 'Blocking Issue', 'open');
|
|
204
|
-
const edge = createEdge('x-1', 'i-blocker', 'i-blocked', 'blocks');
|
|
205
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
206
|
-
vi.mocked(storage.getNode).mockResolvedValue(blocker);
|
|
207
|
-
const result = await engine.blockers('i-blocked');
|
|
208
|
-
expect(result).toHaveLength(1);
|
|
209
|
-
expect(result[0].id).toBe('i-blocker');
|
|
210
|
-
});
|
|
211
|
-
it('should filter out inactive blockers by default', async () => {
|
|
212
|
-
const closedBlocker = createIssue('i-blocker', 'Closed Blocker', 'closed');
|
|
213
|
-
const edge = createEdge('x-1', 'i-blocker', 'i-blocked', 'blocks');
|
|
214
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
215
|
-
vi.mocked(storage.getNode).mockResolvedValue(closedBlocker);
|
|
216
|
-
const result = await engine.blockers('i-blocked');
|
|
217
|
-
expect(result).toHaveLength(0);
|
|
218
|
-
});
|
|
219
|
-
it('should include inactive blockers when activeOnly=false', async () => {
|
|
220
|
-
const closedBlocker = createIssue('i-blocker', 'Closed Blocker', 'closed');
|
|
221
|
-
const edge = createEdge('x-1', 'i-blocker', 'i-blocked', 'blocks');
|
|
222
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
223
|
-
vi.mocked(storage.getNode).mockResolvedValue(closedBlocker);
|
|
224
|
-
const result = await engine.blockers('i-blocked', { activeOnly: false });
|
|
225
|
-
expect(result).toHaveLength(1);
|
|
226
|
-
});
|
|
227
|
-
it('should get transitive blockers', async () => {
|
|
228
|
-
const blockerA = createIssue('i-a', 'Blocker A', 'open');
|
|
229
|
-
const blockerB = createIssue('i-b', 'Blocker B', 'open');
|
|
230
|
-
vi.mocked(storage.getEdgesTo)
|
|
231
|
-
.mockResolvedValueOnce([createEdge('x-1', 'i-a', 'i-target', 'blocks')])
|
|
232
|
-
.mockResolvedValueOnce([createEdge('x-2', 'i-b', 'i-a', 'blocks')])
|
|
233
|
-
.mockResolvedValueOnce([]);
|
|
234
|
-
vi.mocked(storage.getNode)
|
|
235
|
-
.mockResolvedValueOnce(blockerA)
|
|
236
|
-
.mockResolvedValueOnce(blockerB);
|
|
237
|
-
const result = await engine.blockers('i-target', { transitive: true });
|
|
238
|
-
expect(result).toHaveLength(2);
|
|
239
|
-
});
|
|
240
|
-
it('should respect maxDepth', async () => {
|
|
241
|
-
// maxDepth=0 allows depth 0 (direct blockers) but no recursion
|
|
242
|
-
// maxDepth=1 would allow depth 0 and depth 1 (blockers of blockers)
|
|
243
|
-
const directBlocker = createIssue('i-direct', 'Direct Blocker', 'open');
|
|
244
|
-
const transitiveBlocker = createIssue('i-transitive', 'Transitive', 'open');
|
|
245
|
-
vi.mocked(storage.getEdgesTo)
|
|
246
|
-
.mockResolvedValueOnce([createEdge('x-1', 'i-direct', 'i-target', 'blocks')])
|
|
247
|
-
.mockResolvedValueOnce([createEdge('x-2', 'i-transitive', 'i-direct', 'blocks')]);
|
|
248
|
-
vi.mocked(storage.getNode)
|
|
249
|
-
.mockResolvedValueOnce(directBlocker)
|
|
250
|
-
.mockResolvedValueOnce(transitiveBlocker);
|
|
251
|
-
// With maxDepth=0 and transitive=true, we get direct blocker but NOT its blockers
|
|
252
|
-
const result = await engine.blockers('i-target', {
|
|
253
|
-
transitive: true,
|
|
254
|
-
maxDepth: 0,
|
|
255
|
-
});
|
|
256
|
-
// Should have 1 result (direct blocker), not 2 (would include transitive)
|
|
257
|
-
expect(result).toHaveLength(1);
|
|
258
|
-
expect(result[0].id).toBe('i-direct');
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
describe('blocking()', () => {
|
|
262
|
-
it('should get nodes this blocks', async () => {
|
|
263
|
-
const blocked = createIssue('i-blocked', 'Blocked Issue', 'open');
|
|
264
|
-
const edge = createEdge('x-1', 'i-blocker', 'i-blocked', 'blocks');
|
|
265
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([edge]);
|
|
266
|
-
vi.mocked(storage.getNode).mockResolvedValue(blocked);
|
|
267
|
-
const result = await engine.blocking('i-blocker');
|
|
268
|
-
expect(result).toHaveLength(1);
|
|
269
|
-
expect(result[0].id).toBe('i-blocked');
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
describe('isBlocking()', () => {
|
|
273
|
-
it('should return true for direct blocking', async () => {
|
|
274
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([
|
|
275
|
-
createEdge('x-1', 'i-a', 'i-b', 'blocks'),
|
|
276
|
-
]);
|
|
277
|
-
const result = await engine.isBlocking('i-a', 'i-b');
|
|
278
|
-
expect(result).toBe(true);
|
|
279
|
-
});
|
|
280
|
-
it('should return true for transitive blocking', async () => {
|
|
281
|
-
vi.mocked(storage.getEdgesFrom)
|
|
282
|
-
.mockResolvedValueOnce([createEdge('x-1', 'i-a', 'i-b', 'blocks')])
|
|
283
|
-
.mockResolvedValueOnce([createEdge('x-2', 'i-b', 'i-c', 'blocks')]);
|
|
284
|
-
const result = await engine.isBlocking('i-a', 'i-c');
|
|
285
|
-
expect(result).toBe(true);
|
|
286
|
-
});
|
|
287
|
-
it('should return false when not blocking', async () => {
|
|
288
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([]);
|
|
289
|
-
const result = await engine.isBlocking('i-a', 'i-b');
|
|
290
|
-
expect(result).toBe(false);
|
|
291
|
-
});
|
|
292
|
-
it('should handle cycles in graph without infinite loop', async () => {
|
|
293
|
-
vi.mocked(storage.getEdgesFrom)
|
|
294
|
-
.mockResolvedValueOnce([createEdge('x-1', 'i-a', 'i-b', 'blocks')])
|
|
295
|
-
.mockResolvedValueOnce([createEdge('x-2', 'i-b', 'i-a', 'blocks')]) // cycle back
|
|
296
|
-
.mockResolvedValue([]);
|
|
297
|
-
// Should terminate without infinite loop
|
|
298
|
-
const result = await engine.isBlocking('i-a', 'i-c');
|
|
299
|
-
expect(result).toBe(false);
|
|
300
|
-
});
|
|
301
|
-
});
|
|
302
|
-
describe('implementers()', () => {
|
|
303
|
-
it('should get issues that implement a spec', async () => {
|
|
304
|
-
const issue = createIssue('i-impl', 'Implementation');
|
|
305
|
-
const edge = createEdge('x-1', 'i-impl', 's-spec', 'implements');
|
|
306
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
307
|
-
vi.mocked(storage.getNode).mockResolvedValue(issue);
|
|
308
|
-
const result = await engine.implementers('s-spec');
|
|
309
|
-
expect(storage.getEdgesTo).toHaveBeenCalledWith('s-spec', 'implements');
|
|
310
|
-
expect(result).toHaveLength(1);
|
|
311
|
-
expect(result[0].id).toBe('i-impl');
|
|
312
|
-
});
|
|
313
|
-
it('should filter out non-issues', async () => {
|
|
314
|
-
const spec = createSpec('s-not-issue', 'Not an issue');
|
|
315
|
-
const edge = createEdge('x-1', 's-not-issue', 's-spec', 'implements');
|
|
316
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([edge]);
|
|
317
|
-
vi.mocked(storage.getNode).mockResolvedValue(spec);
|
|
318
|
-
const result = await engine.implementers('s-spec');
|
|
319
|
-
expect(result).toHaveLength(0);
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
describe('specs()', () => {
|
|
323
|
-
it('should get specs that an issue implements', async () => {
|
|
324
|
-
const spec = createSpec('s-spec', 'Spec');
|
|
325
|
-
const edge = createEdge('x-1', 'i-issue', 's-spec', 'implements');
|
|
326
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([edge]);
|
|
327
|
-
vi.mocked(storage.getNode).mockResolvedValue(spec);
|
|
328
|
-
const result = await engine.specs('i-issue');
|
|
329
|
-
expect(storage.getEdgesFrom).toHaveBeenCalledWith('i-issue', 'implements');
|
|
330
|
-
expect(result).toHaveLength(1);
|
|
331
|
-
expect(result[0].id).toBe('s-spec');
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
describe('children()', () => {
|
|
335
|
-
it('should get child nodes', async () => {
|
|
336
|
-
const child = createSpec('s-child', 'Child', { parent_id: 's-parent' });
|
|
337
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([child]);
|
|
338
|
-
const result = await engine.children('s-parent');
|
|
339
|
-
expect(storage.queryNodes).toHaveBeenCalledWith({ parent_id: 's-parent' });
|
|
340
|
-
expect(result).toHaveLength(1);
|
|
341
|
-
expect(result[0].id).toBe('s-child');
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
describe('parent()', () => {
|
|
345
|
-
it('should get parent node', async () => {
|
|
346
|
-
const child = createSpec('s-child', 'Child', { parent_id: 's-parent' });
|
|
347
|
-
const parent = createSpec('s-parent', 'Parent');
|
|
348
|
-
vi.mocked(storage.getNode)
|
|
349
|
-
.mockResolvedValueOnce(child)
|
|
350
|
-
.mockResolvedValueOnce(parent);
|
|
351
|
-
const result = await engine.parent('s-child');
|
|
352
|
-
expect(result).not.toBeNull();
|
|
353
|
-
expect(result?.id).toBe('s-parent');
|
|
354
|
-
});
|
|
355
|
-
it('should return null when no parent', async () => {
|
|
356
|
-
const node = createSpec('s-root', 'Root');
|
|
357
|
-
vi.mocked(storage.getNode).mockResolvedValue(node);
|
|
358
|
-
const result = await engine.parent('s-root');
|
|
359
|
-
expect(result).toBeNull();
|
|
360
|
-
});
|
|
361
|
-
it('should return null when node not found', async () => {
|
|
362
|
-
vi.mocked(storage.getNode).mockResolvedValue(null);
|
|
363
|
-
const result = await engine.parent('s-missing');
|
|
364
|
-
expect(result).toBeNull();
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
describe('ancestors()', () => {
|
|
368
|
-
it('should get all ancestors', async () => {
|
|
369
|
-
const child = createSpec('s-child', 'Child', { parent_id: 's-mid' });
|
|
370
|
-
const mid = createSpec('s-mid', 'Mid', { parent_id: 's-root' });
|
|
371
|
-
const root = createSpec('s-root', 'Root');
|
|
372
|
-
vi.mocked(storage.getNode)
|
|
373
|
-
.mockResolvedValueOnce(child)
|
|
374
|
-
.mockResolvedValueOnce(mid)
|
|
375
|
-
.mockResolvedValueOnce(mid) // gets mid again for parent_id check
|
|
376
|
-
.mockResolvedValueOnce(root)
|
|
377
|
-
.mockResolvedValueOnce(root); // gets root again for parent_id check
|
|
378
|
-
const result = await engine.ancestors('s-child');
|
|
379
|
-
expect(result.length).toBeGreaterThanOrEqual(1);
|
|
380
|
-
});
|
|
381
|
-
it('should return empty for root node', async () => {
|
|
382
|
-
const root = createSpec('s-root', 'Root');
|
|
383
|
-
vi.mocked(storage.getNode).mockResolvedValue(root);
|
|
384
|
-
const result = await engine.ancestors('s-root');
|
|
385
|
-
expect(result).toHaveLength(0);
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
describe('descendants()', () => {
|
|
389
|
-
it('should get all descendants', async () => {
|
|
390
|
-
const child1 = createSpec('s-c1', 'Child 1', { parent_id: 's-root' });
|
|
391
|
-
const child2 = createSpec('s-c2', 'Child 2', { parent_id: 's-root' });
|
|
392
|
-
const grandchild = createSpec('s-gc', 'Grandchild', { parent_id: 's-c1' });
|
|
393
|
-
vi.mocked(storage.queryNodes)
|
|
394
|
-
.mockResolvedValueOnce([child1, child2]) // children of root
|
|
395
|
-
.mockResolvedValueOnce([grandchild]) // children of c1
|
|
396
|
-
.mockResolvedValueOnce([]) // children of c2
|
|
397
|
-
.mockResolvedValueOnce([]); // children of gc
|
|
398
|
-
const result = await engine.descendants('s-root');
|
|
399
|
-
expect(result).toHaveLength(3);
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
describe('ready()', () => {
|
|
403
|
-
it('should return open issues with no active blockers', async () => {
|
|
404
|
-
const issue = createIssue('i-ready', 'Ready Issue', 'open');
|
|
405
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([issue]);
|
|
406
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]); // no blockers
|
|
407
|
-
const result = await engine.ready();
|
|
408
|
-
expect(storage.queryNodes).toHaveBeenCalledWith({
|
|
409
|
-
type: 'issue',
|
|
410
|
-
status: 'open',
|
|
411
|
-
archived: false,
|
|
412
|
-
});
|
|
413
|
-
expect(result).toHaveLength(1);
|
|
414
|
-
expect(result[0].id).toBe('i-ready');
|
|
415
|
-
});
|
|
416
|
-
it('should exclude issues with active blockers', async () => {
|
|
417
|
-
const issue = createIssue('i-blocked', 'Blocked Issue', 'open');
|
|
418
|
-
const blocker = createIssue('i-blocker', 'Blocker', 'open');
|
|
419
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([issue]);
|
|
420
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
421
|
-
createEdge('x-1', 'i-blocker', 'i-blocked', 'blocks'),
|
|
422
|
-
]);
|
|
423
|
-
vi.mocked(storage.getNode).mockResolvedValue(blocker);
|
|
424
|
-
const result = await engine.ready();
|
|
425
|
-
expect(result).toHaveLength(0);
|
|
426
|
-
});
|
|
427
|
-
it('should include issues whose blockers are closed', async () => {
|
|
428
|
-
const issue = createIssue('i-ready', 'Ready Issue', 'open');
|
|
429
|
-
const closedBlocker = createIssue('i-blocker', 'Closed', 'closed');
|
|
430
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([issue]);
|
|
431
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
432
|
-
createEdge('x-1', 'i-blocker', 'i-ready', 'blocks'),
|
|
433
|
-
]);
|
|
434
|
-
vi.mocked(storage.getNode).mockResolvedValue(closedBlocker);
|
|
435
|
-
const result = await engine.ready();
|
|
436
|
-
expect(result).toHaveLength(1);
|
|
437
|
-
});
|
|
438
|
-
it('should include issues whose blockers are archived', async () => {
|
|
439
|
-
const issue = createIssue('i-ready', 'Ready Issue', 'open');
|
|
440
|
-
const archivedBlocker = createIssue('i-blocker', 'Archived', 'open', {
|
|
441
|
-
archived: true,
|
|
442
|
-
});
|
|
443
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([issue]);
|
|
444
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
445
|
-
createEdge('x-1', 'i-blocker', 'i-ready', 'blocks'),
|
|
446
|
-
]);
|
|
447
|
-
vi.mocked(storage.getNode).mockResolvedValue(archivedBlocker);
|
|
448
|
-
const result = await engine.ready();
|
|
449
|
-
expect(result).toHaveLength(1);
|
|
450
|
-
});
|
|
451
|
-
it('should filter by tags', async () => {
|
|
452
|
-
const issue1 = createIssue('i-1', 'Issue 1', 'open', { tags: ['urgent'] });
|
|
453
|
-
const issue2 = createIssue('i-2', 'Issue 2', 'open', { tags: ['low'] });
|
|
454
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([issue1, issue2]);
|
|
455
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]);
|
|
456
|
-
const result = await engine.ready({ tags: ['urgent'] });
|
|
457
|
-
expect(result).toHaveLength(1);
|
|
458
|
-
expect(result[0].id).toBe('i-1');
|
|
459
|
-
});
|
|
460
|
-
it('should filter by priority', async () => {
|
|
461
|
-
const highPriority = createIssue('i-high', 'High', 'open', { priority: 0 });
|
|
462
|
-
const lowPriority = createIssue('i-low', 'Low', 'open', { priority: 4 });
|
|
463
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([highPriority, lowPriority]);
|
|
464
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]);
|
|
465
|
-
const result = await engine.ready({ priority: 0 });
|
|
466
|
-
expect(result).toHaveLength(1);
|
|
467
|
-
expect(result[0].id).toBe('i-high');
|
|
468
|
-
});
|
|
469
|
-
it('should filter by priority range', async () => {
|
|
470
|
-
const p0 = createIssue('i-0', 'P0', 'open', { priority: 0 });
|
|
471
|
-
const p2 = createIssue('i-2', 'P2', 'open', { priority: 2 });
|
|
472
|
-
const p4 = createIssue('i-4', 'P4', 'open', { priority: 4 });
|
|
473
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([p0, p2, p4]);
|
|
474
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]);
|
|
475
|
-
const result = await engine.ready({ priority: { min: 1, max: 3 } });
|
|
476
|
-
expect(result).toHaveLength(1);
|
|
477
|
-
expect(result[0].id).toBe('i-2');
|
|
478
|
-
});
|
|
479
|
-
it('should filter by assignee', async () => {
|
|
480
|
-
const assigned = createIssue('i-assigned', 'Assigned', 'open', {
|
|
481
|
-
assignee: 'alice',
|
|
482
|
-
});
|
|
483
|
-
const unassigned = createIssue('i-unassigned', 'Unassigned', 'open');
|
|
484
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([assigned, unassigned]);
|
|
485
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]);
|
|
486
|
-
const result = await engine.ready({ assignee: 'alice' });
|
|
487
|
-
expect(result).toHaveLength(1);
|
|
488
|
-
expect(result[0].id).toBe('i-assigned');
|
|
489
|
-
});
|
|
490
|
-
it('should respect limit', async () => {
|
|
491
|
-
const issues = [
|
|
492
|
-
createIssue('i-1', 'Issue 1', 'open'),
|
|
493
|
-
createIssue('i-2', 'Issue 2', 'open'),
|
|
494
|
-
createIssue('i-3', 'Issue 3', 'open'),
|
|
495
|
-
];
|
|
496
|
-
vi.mocked(storage.queryNodes).mockResolvedValue(issues);
|
|
497
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([]);
|
|
498
|
-
const result = await engine.ready({ limit: 2 });
|
|
499
|
-
expect(result).toHaveLength(2);
|
|
500
|
-
});
|
|
501
|
-
});
|
|
502
|
-
describe('feedback()', () => {
|
|
503
|
-
it('should get feedback for a target', async () => {
|
|
504
|
-
const fb = createFeedback('f-1', 's-spec');
|
|
505
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([fb]);
|
|
506
|
-
const result = await engine.feedback('s-spec');
|
|
507
|
-
expect(result).toHaveLength(1);
|
|
508
|
-
expect(result[0].id).toBe('f-1');
|
|
509
|
-
});
|
|
510
|
-
it('should filter by type', async () => {
|
|
511
|
-
const comment = createFeedback('f-1', 's-spec', { feedback_type: 'comment' });
|
|
512
|
-
const suggestion = createFeedback('f-2', 's-spec', {
|
|
513
|
-
feedback_type: 'suggestion',
|
|
514
|
-
});
|
|
515
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([comment, suggestion]);
|
|
516
|
-
const result = await engine.feedback('s-spec', { type: 'comment' });
|
|
517
|
-
expect(result).toHaveLength(1);
|
|
518
|
-
expect(result[0].id).toBe('f-1');
|
|
519
|
-
});
|
|
520
|
-
it('should filter by resolved status', async () => {
|
|
521
|
-
const resolved = createFeedback('f-1', 's-spec', { resolved: true });
|
|
522
|
-
const unresolved = createFeedback('f-2', 's-spec', { resolved: false });
|
|
523
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([resolved, unresolved]);
|
|
524
|
-
const result = await engine.feedback('s-spec', { resolved: true });
|
|
525
|
-
expect(result).toHaveLength(1);
|
|
526
|
-
expect(result[0].id).toBe('f-1');
|
|
527
|
-
});
|
|
528
|
-
it('should exclude dismissed by default', async () => {
|
|
529
|
-
const normal = createFeedback('f-1', 's-spec', { dismissed: false });
|
|
530
|
-
const dismissed = createFeedback('f-2', 's-spec', { dismissed: true });
|
|
531
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([normal, dismissed]);
|
|
532
|
-
const result = await engine.feedback('s-spec');
|
|
533
|
-
expect(result).toHaveLength(1);
|
|
534
|
-
expect(result[0].id).toBe('f-1');
|
|
535
|
-
});
|
|
536
|
-
it('should include dismissed when requested', async () => {
|
|
537
|
-
const normal = createFeedback('f-1', 's-spec', { dismissed: false });
|
|
538
|
-
const dismissed = createFeedback('f-2', 's-spec', { dismissed: true });
|
|
539
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([normal, dismissed]);
|
|
540
|
-
const result = await engine.feedback('s-spec', { includeDismissed: true });
|
|
541
|
-
expect(result).toHaveLength(2);
|
|
542
|
-
});
|
|
543
|
-
});
|
|
544
|
-
describe('unresolvedFeedback()', () => {
|
|
545
|
-
it('should get unresolved feedback', async () => {
|
|
546
|
-
const unresolved = createFeedback('f-1', 's-spec', { resolved: false });
|
|
547
|
-
const resolved = createFeedback('f-2', 's-spec', { resolved: true });
|
|
548
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([unresolved, resolved]);
|
|
549
|
-
const result = await engine.unresolvedFeedback();
|
|
550
|
-
expect(result).toHaveLength(1);
|
|
551
|
-
expect(result[0].id).toBe('f-1');
|
|
552
|
-
});
|
|
553
|
-
it('should exclude dismissed feedback', async () => {
|
|
554
|
-
const unresolved = createFeedback('f-1', 's-spec', {
|
|
555
|
-
resolved: false,
|
|
556
|
-
dismissed: false,
|
|
557
|
-
});
|
|
558
|
-
const dismissed = createFeedback('f-2', 's-spec', {
|
|
559
|
-
resolved: false,
|
|
560
|
-
dismissed: true,
|
|
561
|
-
});
|
|
562
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([unresolved, dismissed]);
|
|
563
|
-
const result = await engine.unresolvedFeedback();
|
|
564
|
-
expect(result).toHaveLength(1);
|
|
565
|
-
expect(result[0].id).toBe('f-1');
|
|
566
|
-
});
|
|
567
|
-
it('should filter by target', async () => {
|
|
568
|
-
const fb1 = createFeedback('f-1', 's-spec1', { resolved: false });
|
|
569
|
-
const fb2 = createFeedback('f-2', 's-spec2', { resolved: false });
|
|
570
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([fb1, fb2]);
|
|
571
|
-
const result = await engine.unresolvedFeedback('s-spec1');
|
|
572
|
-
expect(result).toHaveLength(1);
|
|
573
|
-
expect(result[0].id).toBe('f-1');
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
// ============================================================================
|
|
577
|
-
// Cross-Provider Resolution Tests
|
|
578
|
-
// ============================================================================
|
|
579
|
-
describe('Cross-Provider Resolution', () => {
|
|
580
|
-
describe('with nodeResolver', () => {
|
|
581
|
-
it('blockers() should call resolver for external URIs', async () => {
|
|
582
|
-
const externalNode = {
|
|
583
|
-
id: 'x-ext1',
|
|
584
|
-
uuid: 'ext-uuid-1',
|
|
585
|
-
type: 'external',
|
|
586
|
-
title: 'External Blocker',
|
|
587
|
-
status: 'open',
|
|
588
|
-
uri: 'beads://./bd-blocker',
|
|
589
|
-
source: 'beads',
|
|
590
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
591
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
592
|
-
};
|
|
593
|
-
// Setup mock resolver
|
|
594
|
-
const mockResolver = vi.fn().mockResolvedValue(externalNode);
|
|
595
|
-
// Create engine with resolver
|
|
596
|
-
const engineWithResolver = createQueryEngine({
|
|
597
|
-
storage,
|
|
598
|
-
nodeResolver: mockResolver,
|
|
599
|
-
});
|
|
600
|
-
// Setup storage mocks
|
|
601
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
602
|
-
createEdge('e-1', 'beads://./bd-blocker', 'i-local', 'blocks'),
|
|
603
|
-
]);
|
|
604
|
-
await engineWithResolver.blockers('i-local');
|
|
605
|
-
// Resolver should be called for external URI
|
|
606
|
-
expect(mockResolver).toHaveBeenCalledWith('beads://./bd-blocker');
|
|
607
|
-
// Note: External nodes don't appear in results because they don't
|
|
608
|
-
// parse as valid Node types (spec/issue/feedback). The resolver is
|
|
609
|
-
// still called to support ready() blocking checks.
|
|
610
|
-
});
|
|
611
|
-
it('blockers() should return local issues resolved via resolver', async () => {
|
|
612
|
-
// When resolver returns a valid issue type, it should be in results
|
|
613
|
-
const localBlocker = createIssue('i-blocker', 'Local Blocker');
|
|
614
|
-
const mockResolver = vi.fn().mockResolvedValue(localBlocker);
|
|
615
|
-
const engineWithResolver = createQueryEngine({
|
|
616
|
-
storage,
|
|
617
|
-
nodeResolver: mockResolver,
|
|
618
|
-
});
|
|
619
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
620
|
-
createEdge('e-1', 'beads://./bd-blocker', 'i-local', 'blocks'),
|
|
621
|
-
]);
|
|
622
|
-
const result = await engineWithResolver.blockers('i-local');
|
|
623
|
-
expect(mockResolver).toHaveBeenCalledWith('beads://./bd-blocker');
|
|
624
|
-
expect(result).toHaveLength(1);
|
|
625
|
-
expect(result[0].title).toBe('Local Blocker');
|
|
626
|
-
});
|
|
627
|
-
it('blockers() should use storage for local IDs even with resolver', async () => {
|
|
628
|
-
const localBlocker = createIssue('i-blocker', 'Local Blocker');
|
|
629
|
-
const mockResolver = vi.fn();
|
|
630
|
-
const engineWithResolver = createQueryEngine({
|
|
631
|
-
storage,
|
|
632
|
-
nodeResolver: mockResolver,
|
|
633
|
-
});
|
|
634
|
-
vi.mocked(storage.getNode).mockResolvedValue(localBlocker);
|
|
635
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
636
|
-
createEdge('e-1', 'i-blocker', 'i-local', 'blocks'),
|
|
637
|
-
]);
|
|
638
|
-
await engineWithResolver.blockers('i-local');
|
|
639
|
-
// Resolver should NOT be called for local IDs
|
|
640
|
-
expect(mockResolver).not.toHaveBeenCalled();
|
|
641
|
-
expect(storage.getNode).toHaveBeenCalledWith('i-blocker');
|
|
642
|
-
});
|
|
643
|
-
it('blocking() should call resolver for external URIs', async () => {
|
|
644
|
-
const externalNode = {
|
|
645
|
-
id: 'x-ext1',
|
|
646
|
-
uuid: 'ext-uuid-1',
|
|
647
|
-
type: 'external',
|
|
648
|
-
title: 'External Blocked',
|
|
649
|
-
status: 'open',
|
|
650
|
-
uri: 'beads://./bd-blocked',
|
|
651
|
-
source: 'beads',
|
|
652
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
653
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
654
|
-
};
|
|
655
|
-
const mockResolver = vi.fn().mockResolvedValue(externalNode);
|
|
656
|
-
const engineWithResolver = createQueryEngine({
|
|
657
|
-
storage,
|
|
658
|
-
nodeResolver: mockResolver,
|
|
659
|
-
});
|
|
660
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([
|
|
661
|
-
createEdge('e-1', 'i-blocker', 'beads://./bd-blocked', 'blocks'),
|
|
662
|
-
]);
|
|
663
|
-
await engineWithResolver.blocking('i-blocker');
|
|
664
|
-
// Resolver should be called for external URI
|
|
665
|
-
expect(mockResolver).toHaveBeenCalledWith('beads://./bd-blocked');
|
|
666
|
-
// Note: External nodes don't appear in results because they don't
|
|
667
|
-
// parse as valid Node types (spec/issue/feedback).
|
|
668
|
-
});
|
|
669
|
-
it('blocking() should return local issues resolved via resolver', async () => {
|
|
670
|
-
const localBlocked = createIssue('i-blocked', 'Local Blocked Issue');
|
|
671
|
-
const mockResolver = vi.fn().mockResolvedValue(localBlocked);
|
|
672
|
-
const engineWithResolver = createQueryEngine({
|
|
673
|
-
storage,
|
|
674
|
-
nodeResolver: mockResolver,
|
|
675
|
-
});
|
|
676
|
-
vi.mocked(storage.getEdgesFrom).mockResolvedValue([
|
|
677
|
-
createEdge('e-1', 'i-blocker', 'beads://./bd-blocked', 'blocks'),
|
|
678
|
-
]);
|
|
679
|
-
const result = await engineWithResolver.blocking('i-blocker');
|
|
680
|
-
expect(mockResolver).toHaveBeenCalledWith('beads://./bd-blocked');
|
|
681
|
-
expect(result).toHaveLength(1);
|
|
682
|
-
expect(result[0].title).toBe('Local Blocked Issue');
|
|
683
|
-
});
|
|
684
|
-
it('ready() should consider external blockers when resolver provided', async () => {
|
|
685
|
-
const localIssue = createIssue('i-ready', 'Ready Issue');
|
|
686
|
-
const externalBlocker = {
|
|
687
|
-
id: 'x-ext1',
|
|
688
|
-
uuid: 'ext-uuid-1',
|
|
689
|
-
type: 'external',
|
|
690
|
-
title: 'External Blocker',
|
|
691
|
-
status: 'open', // Active blocker
|
|
692
|
-
uri: 'beads://./bd-blocker',
|
|
693
|
-
source: 'beads',
|
|
694
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
695
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
696
|
-
};
|
|
697
|
-
const mockResolver = vi.fn().mockResolvedValue(externalBlocker);
|
|
698
|
-
const engineWithResolver = createQueryEngine({
|
|
699
|
-
storage,
|
|
700
|
-
nodeResolver: mockResolver,
|
|
701
|
-
});
|
|
702
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([localIssue]);
|
|
703
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
704
|
-
createEdge('e-1', 'beads://./bd-blocker', 'i-ready', 'blocks'),
|
|
705
|
-
]);
|
|
706
|
-
const result = await engineWithResolver.ready();
|
|
707
|
-
// Issue should NOT be ready because external blocker is active
|
|
708
|
-
expect(result).toHaveLength(0);
|
|
709
|
-
});
|
|
710
|
-
it('ready() should include issue when external blocker is closed', async () => {
|
|
711
|
-
const localIssue = createIssue('i-ready', 'Ready Issue');
|
|
712
|
-
const closedBlocker = {
|
|
713
|
-
id: 'x-ext1',
|
|
714
|
-
uuid: 'ext-uuid-1',
|
|
715
|
-
type: 'external',
|
|
716
|
-
title: 'Closed External Blocker',
|
|
717
|
-
status: 'closed', // Closed - not blocking
|
|
718
|
-
uri: 'beads://./bd-blocker',
|
|
719
|
-
source: 'beads',
|
|
720
|
-
created_at: '2024-01-01T00:00:00Z',
|
|
721
|
-
updated_at: '2024-01-01T00:00:00Z',
|
|
722
|
-
};
|
|
723
|
-
const mockResolver = vi.fn().mockResolvedValue(closedBlocker);
|
|
724
|
-
const engineWithResolver = createQueryEngine({
|
|
725
|
-
storage,
|
|
726
|
-
nodeResolver: mockResolver,
|
|
727
|
-
});
|
|
728
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([localIssue]);
|
|
729
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
730
|
-
createEdge('e-1', 'beads://./bd-blocker', 'i-ready', 'blocks'),
|
|
731
|
-
]);
|
|
732
|
-
const result = await engineWithResolver.ready();
|
|
733
|
-
// Issue should be ready because external blocker is closed
|
|
734
|
-
expect(result).toHaveLength(1);
|
|
735
|
-
expect(result[0].id).toBe('i-ready');
|
|
736
|
-
});
|
|
737
|
-
it('resolver returning null should skip the node', async () => {
|
|
738
|
-
const mockResolver = vi.fn().mockResolvedValue(null);
|
|
739
|
-
const engineWithResolver = createQueryEngine({
|
|
740
|
-
storage,
|
|
741
|
-
nodeResolver: mockResolver,
|
|
742
|
-
});
|
|
743
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
744
|
-
createEdge('e-1', 'beads://./bd-missing', 'i-local', 'blocks'),
|
|
745
|
-
]);
|
|
746
|
-
const result = await engineWithResolver.blockers('i-local');
|
|
747
|
-
expect(mockResolver).toHaveBeenCalledWith('beads://./bd-missing');
|
|
748
|
-
expect(result).toHaveLength(0);
|
|
749
|
-
});
|
|
750
|
-
});
|
|
751
|
-
describe('without nodeResolver (backward compatibility)', () => {
|
|
752
|
-
it('blockers() should skip external URIs that storage cannot find', async () => {
|
|
753
|
-
vi.mocked(storage.getNode).mockResolvedValue(null);
|
|
754
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
755
|
-
createEdge('e-1', 'beads://./bd-blocker', 'i-local', 'blocks'),
|
|
756
|
-
]);
|
|
757
|
-
const result = await engine.blockers('i-local');
|
|
758
|
-
expect(result).toHaveLength(0);
|
|
759
|
-
});
|
|
760
|
-
it('ready() should not be blocked by unresolvable external nodes', async () => {
|
|
761
|
-
const localIssue = createIssue('i-ready', 'Ready Issue');
|
|
762
|
-
vi.mocked(storage.queryNodes).mockResolvedValue([localIssue]);
|
|
763
|
-
vi.mocked(storage.getEdgesTo).mockResolvedValue([
|
|
764
|
-
createEdge('e-1', 'beads://./bd-unresolvable', 'i-ready', 'blocks'),
|
|
765
|
-
]);
|
|
766
|
-
vi.mocked(storage.getNode).mockResolvedValue(null);
|
|
767
|
-
const result = await engine.ready();
|
|
768
|
-
// Issue should be ready because blocker cannot be resolved
|
|
769
|
-
expect(result).toHaveLength(1);
|
|
770
|
-
});
|
|
771
|
-
});
|
|
772
|
-
});
|
|
773
|
-
});
|
|
774
|
-
//# sourceMappingURL=query.test.js.map
|