memory-journal-mcp 6.1.2 → 6.2.1
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/README.md +44 -28
- package/dist/{chunk-X4SWFATC.js → chunk-BI4ZNSKA.js} +38 -24
- package/dist/{chunk-HCEWINSB.js → chunk-N6EBIDN7.js} +99 -102
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/tools-WPRY5MJ6.js +2 -0
- package/package.json +10 -1
- package/skills/github-commander/SKILL.md +151 -0
- package/skills/github-commander/config/project-config.example.md +125 -0
- package/skills/github-commander/workflows/code-quality-audit.md +80 -0
- package/skills/github-commander/workflows/full-audit.md +134 -0
- package/skills/github-commander/workflows/issue-triage.md +239 -0
- package/skills/github-commander/workflows/milestone-sprint.md +81 -0
- package/skills/github-commander/workflows/perf-audit.md +142 -0
- package/skills/github-commander/workflows/pr-review.md +123 -0
- package/skills/github-commander/workflows/security-audit.md +170 -0
- package/skills/github-commander/workflows/update-deps.md +109 -0
- package/.dockerignore +0 -139
- package/.gitattributes +0 -20
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -95
- package/.github/ISSUE_TEMPLATE/config.yml +0 -11
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -110
- package/.github/ISSUE_TEMPLATE/question.md +0 -78
- package/.github/aw/actions-lock.json +0 -14
- package/.github/copilot-instructions.md +0 -122
- package/.github/dependabot.yml +0 -93
- package/.github/pull_request_template.md +0 -135
- package/.github/workflows/README.md +0 -133
- package/.github/workflows/agentics-maintenance.yml +0 -141
- package/.github/workflows/auto-release.yml +0 -68
- package/.github/workflows/ci-health-monitor.lock.yml +0 -1121
- package/.github/workflows/ci-health-monitor.md +0 -87
- package/.github/workflows/codeql.yml +0 -41
- package/.github/workflows/dependabot-auto-merge.yml +0 -42
- package/.github/workflows/dependency-maintenance.lock.yml +0 -1182
- package/.github/workflows/dependency-maintenance.md +0 -147
- package/.github/workflows/docker-publish.yml +0 -254
- package/.github/workflows/docs-drift-detector.lock.yml +0 -1142
- package/.github/workflows/docs-drift-detector.md +0 -115
- package/.github/workflows/lint-and-test.yml +0 -60
- package/.github/workflows/publish-npm.yml +0 -85
- package/.github/workflows/secrets-scanning.yml +0 -32
- package/.github/workflows/security-update.yml +0 -127
- package/.gitleaks.toml +0 -9
- package/.prettierignore +0 -21
- package/.prettierrc +0 -33
- package/.scout-ignore +0 -12
- package/.trivyignore +0 -21
- package/CHANGELOG.md +0 -1814
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -263
- package/DOCKER_README.md +0 -331
- package/Dockerfile +0 -128
- package/SECURITY.md +0 -227
- package/UNRELEASED.md +0 -1
- package/dist/tools-T4U5A3X4.js +0 -2
- package/docker-compose.yml +0 -71
- package/docs/README.md +0 -18
- package/docs/agentic-journal-synergy.md +0 -175
- package/docs/copilot-setup.md +0 -72
- package/eslint.config.js +0 -110
- package/mcp-config-example.json +0 -21
- package/playwright.config.ts +0 -35
- package/releases/v2.1.0.md +0 -220
- package/releases/v2.2.0.md +0 -168
- package/releases/v3.0.0.md +0 -237
- package/releases/v3.1.0.md +0 -104
- package/releases/v3.1.1.md +0 -42
- package/releases/v3.1.2.md +0 -40
- package/releases/v3.1.3.md +0 -64
- package/releases/v3.1.4.md +0 -32
- package/releases/v3.1.5.md +0 -44
- package/releases/v4.0.0.md +0 -71
- package/releases/v4.1.0.md +0 -88
- package/releases/v4.2.0.md +0 -90
- package/releases/v4.3.0.md +0 -92
- package/releases/v4.3.1.md +0 -69
- package/releases/v4.4.0.md +0 -120
- package/releases/v4.4.1.md +0 -33
- package/releases/v4.4.2.md +0 -31
- package/releases/v4.5.0.md +0 -116
- package/releases/v5.0.0.md +0 -105
- package/releases/v5.0.1.md +0 -25
- package/releases/v5.1.0.md +0 -83
- package/releases/v5.1.1.md +0 -10
- package/releases/v6.0.0.md +0 -48
- package/releases/v6.0.1.md +0 -36
- package/releases/v6.1.0.md +0 -68
- package/releases/v6.1.1.md +0 -30
- package/releases/v6.1.2.md +0 -23
- package/scripts/generate-server-instructions.ts +0 -306
- package/scripts/server-instructions-function-body.ts +0 -107
- package/scripts/server-instructions-gotchas.ts +0 -45
- package/server.json +0 -42
- package/social-preview.png +0 -0
- package/src/auth/auth-context.ts +0 -78
- package/src/auth/authorization-server-discovery.ts +0 -263
- package/src/auth/errors.ts +0 -215
- package/src/auth/index.ts +0 -58
- package/src/auth/middleware.ts +0 -392
- package/src/auth/oauth-resource-server.ts +0 -170
- package/src/auth/scope-map.ts +0 -46
- package/src/auth/scopes.ts +0 -256
- package/src/auth/token-validator.ts +0 -293
- package/src/auth/transport-agnostic.ts +0 -164
- package/src/auth/types.ts +0 -372
- package/src/cli.ts +0 -279
- package/src/codemode/api-constants.ts +0 -263
- package/src/codemode/api.ts +0 -302
- package/src/codemode/auto-return.ts +0 -65
- package/src/codemode/index.ts +0 -47
- package/src/codemode/sandbox-factory.ts +0 -144
- package/src/codemode/sandbox.ts +0 -220
- package/src/codemode/security.ts +0 -155
- package/src/codemode/types.ts +0 -228
- package/src/codemode/worker-sandbox.ts +0 -277
- package/src/codemode/worker-script.ts +0 -239
- package/src/constants/icons.ts +0 -183
- package/src/constants/server-instructions.md +0 -166
- package/src/constants/server-instructions.ts +0 -514
- package/src/database/adapter-factory.ts +0 -16
- package/src/database/core/entry-columns.ts +0 -10
- package/src/database/core/interfaces.ts +0 -188
- package/src/database/core/schema.ts +0 -152
- package/src/database/sqlite-adapter/backup.ts +0 -167
- package/src/database/sqlite-adapter/entries/crud.ts +0 -233
- package/src/database/sqlite-adapter/entries/importance.ts +0 -76
- package/src/database/sqlite-adapter/entries/index.ts +0 -142
- package/src/database/sqlite-adapter/entries/search.ts +0 -294
- package/src/database/sqlite-adapter/entries/shared.ts +0 -102
- package/src/database/sqlite-adapter/entries/statistics.ts +0 -162
- package/src/database/sqlite-adapter/index.ts +0 -265
- package/src/database/sqlite-adapter/native-connection.ts +0 -301
- package/src/database/sqlite-adapter/relationships.ts +0 -70
- package/src/database/sqlite-adapter/tags.ts +0 -182
- package/src/filtering/tool-filter.ts +0 -312
- package/src/github/github-integration/client.ts +0 -114
- package/src/github/github-integration/index.ts +0 -297
- package/src/github/github-integration/insights.ts +0 -155
- package/src/github/github-integration/issues.ts +0 -213
- package/src/github/github-integration/milestones.ts +0 -262
- package/src/github/github-integration/projects.ts +0 -414
- package/src/github/github-integration/pull-requests.ts +0 -235
- package/src/github/github-integration/repository.ts +0 -110
- package/src/github/github-integration/types.ts +0 -43
- package/src/handlers/prompts/github.ts +0 -210
- package/src/handlers/prompts/index.ts +0 -97
- package/src/handlers/prompts/workflow.ts +0 -361
- package/src/handlers/resources/core/briefing/context-section.ts +0 -182
- package/src/handlers/resources/core/briefing/github-section.ts +0 -354
- package/src/handlers/resources/core/briefing/index.ts +0 -106
- package/src/handlers/resources/core/briefing/user-message.ts +0 -114
- package/src/handlers/resources/core/health.ts +0 -75
- package/src/handlers/resources/core/index.ts +0 -31
- package/src/handlers/resources/core/instructions.ts +0 -45
- package/src/handlers/resources/core/utilities.ts +0 -310
- package/src/handlers/resources/github.ts +0 -340
- package/src/handlers/resources/graph.ts +0 -218
- package/src/handlers/resources/help.ts +0 -410
- package/src/handlers/resources/index.ts +0 -143
- package/src/handlers/resources/shared.ts +0 -219
- package/src/handlers/resources/team.ts +0 -134
- package/src/handlers/resources/templates.ts +0 -334
- package/src/handlers/tools/admin.ts +0 -351
- package/src/handlers/tools/analytics.ts +0 -346
- package/src/handlers/tools/backup.ts +0 -272
- package/src/handlers/tools/codemode.ts +0 -188
- package/src/handlers/tools/core.ts +0 -359
- package/src/handlers/tools/error-fields-mixin.ts +0 -10
- package/src/handlers/tools/export.ts +0 -150
- package/src/handlers/tools/github/copilot-tools.ts +0 -72
- package/src/handlers/tools/github/helpers.ts +0 -125
- package/src/handlers/tools/github/insights-tools.ts +0 -112
- package/src/handlers/tools/github/issue-tools.ts +0 -442
- package/src/handlers/tools/github/kanban-tools.ts +0 -153
- package/src/handlers/tools/github/milestone-tools.ts +0 -371
- package/src/handlers/tools/github/mutation-tools.ts +0 -17
- package/src/handlers/tools/github/read-tools.ts +0 -302
- package/src/handlers/tools/github/schemas.ts +0 -435
- package/src/handlers/tools/github.ts +0 -39
- package/src/handlers/tools/index.ts +0 -255
- package/src/handlers/tools/relationships.ts +0 -390
- package/src/handlers/tools/schemas.ts +0 -165
- package/src/handlers/tools/search.ts +0 -448
- package/src/handlers/tools/team/admin-tools.ts +0 -164
- package/src/handlers/tools/team/analytics-tools.ts +0 -233
- package/src/handlers/tools/team/backup-tools.ts +0 -83
- package/src/handlers/tools/team/core-tools.ts +0 -197
- package/src/handlers/tools/team/export-tools.ts +0 -130
- package/src/handlers/tools/team/helpers.ts +0 -66
- package/src/handlers/tools/team/index.ts +0 -45
- package/src/handlers/tools/team/relationship-tools.ts +0 -219
- package/src/handlers/tools/team/schemas.ts +0 -558
- package/src/handlers/tools/team/search-tools.ts +0 -145
- package/src/handlers/tools/team/vector-tools.ts +0 -261
- package/src/index.ts +0 -57
- package/src/server/mcp-server.ts +0 -446
- package/src/server/registration.ts +0 -141
- package/src/server/scheduler.ts +0 -283
- package/src/transports/http/handlers.ts +0 -78
- package/src/transports/http/index.ts +0 -8
- package/src/transports/http/security.ts +0 -147
- package/src/transports/http/server/index.ts +0 -397
- package/src/transports/http/server/legacy-sse.ts +0 -87
- package/src/transports/http/server/stateful.ts +0 -222
- package/src/transports/http/server/stateless.ts +0 -42
- package/src/transports/http/types.ts +0 -132
- package/src/types/entities.ts +0 -145
- package/src/types/error-types.ts +0 -92
- package/src/types/errors.ts +0 -200
- package/src/types/filtering.ts +0 -55
- package/src/types/github.ts +0 -216
- package/src/types/index.ts +0 -348
- package/src/utils/error-helpers.ts +0 -78
- package/src/utils/errors/error-response-fields.ts +0 -29
- package/src/utils/errors/suggestions.ts +0 -94
- package/src/utils/github-helpers.ts +0 -33
- package/src/utils/logger.ts +0 -107
- package/src/utils/mcp-logger.ts +0 -155
- package/src/utils/progress-utils.ts +0 -100
- package/src/utils/query-helpers.ts +0 -78
- package/src/utils/resource-annotations.ts +0 -75
- package/src/utils/security-utils.ts +0 -198
- package/src/utils/vector-index-helpers.ts +0 -24
- package/src/vector/vector-search-manager.ts +0 -409
- package/src/version.ts +0 -15
- package/test-server/README.md +0 -193
- package/test-server/code-map.md +0 -399
- package/test-server/test-agent-experience.md +0 -213
- package/test-server/test-filter-instructions.mjs +0 -295
- package/test-server/test-instruction-levels.mjs +0 -102
- package/test-server/test-preflight.md +0 -55
- package/test-server/test-prompts.mjs +0 -185
- package/test-server/test-scheduler.mjs +0 -174
- package/test-server/test-tool-annotations.mjs +0 -115
- package/test-server/test-tools-codemode.md +0 -632
- package/test-server/test-tools-codemode2.md +0 -1218
- package/test-server/test-tools-team.md +0 -215
- package/test-server/test-tools.md +0 -429
- package/test-server/test-tools2.md +0 -361
- package/test-server/test-tools3.md +0 -396
- package/test-server/tool-reference.md +0 -231
- package/tests/README.md +0 -54
- package/tests/auth/auth-context.test.ts +0 -162
- package/tests/auth/authorization-server-discovery.test.ts +0 -265
- package/tests/auth/errors.test.ts +0 -170
- package/tests/auth/middleware.test.ts +0 -585
- package/tests/auth/oauth-resource-server.test.ts +0 -173
- package/tests/auth/scope-map.test.ts +0 -66
- package/tests/auth/scopes.test.ts +0 -347
- package/tests/auth/token-validator.test.ts +0 -271
- package/tests/codemode/api.test.ts +0 -396
- package/tests/codemode/auto-return.test.ts +0 -167
- package/tests/codemode/codemode-tool-handlers.test.ts +0 -197
- package/tests/codemode/sandbox-factory.test.ts +0 -152
- package/tests/codemode/sandbox.test.ts +0 -190
- package/tests/codemode/security.test.ts +0 -242
- package/tests/codemode/worker-sandbox.test.ts +0 -106
- package/tests/constants/icons.test.ts +0 -101
- package/tests/constants/server-instructions.test.ts +0 -514
- package/tests/database/crud-workflow-branches.test.ts +0 -418
- package/tests/database/database-branches.test.ts +0 -132
- package/tests/database/entries-auth-branches.test.ts +0 -390
- package/tests/database/native-connection.test.ts +0 -249
- package/tests/database/shared-helpers.test.ts +0 -103
- package/tests/database/sqlite-adapter.bench.ts +0 -63
- package/tests/database/sqlite-adapter.test.ts +0 -690
- package/tests/database/tags.test.ts +0 -134
- package/tests/e2e/README.md +0 -39
- package/tests/e2e/auth.spec.ts +0 -106
- package/tests/e2e/codemode-abuse.spec.ts +0 -75
- package/tests/e2e/health.spec.ts +0 -63
- package/tests/e2e/helpers.ts +0 -139
- package/tests/e2e/oauth-discovery.spec.ts +0 -102
- package/tests/e2e/oauth-scopes.spec.ts +0 -222
- package/tests/e2e/payloads-admin.spec.ts +0 -76
- package/tests/e2e/payloads-analytics.spec.ts +0 -37
- package/tests/e2e/payloads-backup-restore.spec.ts +0 -102
- package/tests/e2e/payloads-backup.spec.ts +0 -44
- package/tests/e2e/payloads-codemode-api.spec.ts +0 -131
- package/tests/e2e/payloads-codemode-readonly.spec.ts +0 -116
- package/tests/e2e/payloads-codemode.spec.ts +0 -116
- package/tests/e2e/payloads-core.spec.ts +0 -82
- package/tests/e2e/payloads-error-contracts.spec.ts +0 -159
- package/tests/e2e/payloads-export.spec.ts +0 -46
- package/tests/e2e/payloads-github-degradation.spec.ts +0 -73
- package/tests/e2e/payloads-github.spec.ts +0 -176
- package/tests/e2e/payloads-relationships.spec.ts +0 -56
- package/tests/e2e/payloads-search.spec.ts +0 -64
- package/tests/e2e/payloads-team-happy.spec.ts +0 -231
- package/tests/e2e/payloads-team.spec.ts +0 -174
- package/tests/e2e/prompts-expanded.spec.ts +0 -137
- package/tests/e2e/prompts.spec.ts +0 -62
- package/tests/e2e/protocols.spec.ts +0 -134
- package/tests/e2e/rate-limiting.spec.ts +0 -291
- package/tests/e2e/resources-briefing-env.spec.ts +0 -106
- package/tests/e2e/resources-complete.spec.ts +0 -180
- package/tests/e2e/resources-expanded.spec.ts +0 -83
- package/tests/e2e/resources-instructions-levels.spec.ts +0 -145
- package/tests/e2e/resources-templates.spec.ts +0 -123
- package/tests/e2e/resources.spec.ts +0 -103
- package/tests/e2e/scheduler.spec.ts +0 -79
- package/tests/e2e/security.spec.ts +0 -112
- package/tests/e2e/session-advanced.spec.ts +0 -152
- package/tests/e2e/sessions.spec.ts +0 -95
- package/tests/e2e/stateless.spec.ts +0 -79
- package/tests/e2e/streaming.spec.ts +0 -176
- package/tests/e2e/tool-filtering-presets.spec.ts +0 -192
- package/tests/e2e/tool-filtering.spec.ts +0 -77
- package/tests/e2e/tools.spec.ts +0 -111
- package/tests/filtering/tool-filter.test.ts +0 -314
- package/tests/github/client-issues-errors.test.ts +0 -433
- package/tests/github/github-integration-branches.test.ts +0 -490
- package/tests/github/github-integration.test.ts +0 -1015
- package/tests/github/github-managers-branches.test.ts +0 -907
- package/tests/github/pull-requests.test.ts +0 -334
- package/tests/handlers/analytics-branches.test.ts +0 -222
- package/tests/handlers/backup-branches.test.ts +0 -270
- package/tests/handlers/briefing-context-section.test.ts +0 -388
- package/tests/handlers/briefing-github-section.test.ts +0 -392
- package/tests/handlers/briefing-user-message.test.ts +0 -405
- package/tests/handlers/codemode-tools.test.ts +0 -85
- package/tests/handlers/copilot-tools.test.ts +0 -126
- package/tests/handlers/error-path-coverage.test.ts +0 -324
- package/tests/handlers/export-tools.test.ts +0 -203
- package/tests/handlers/github-resource-handlers.test.ts +0 -929
- package/tests/handlers/github-tool-handlers.test.ts +0 -1452
- package/tests/handlers/handler-error-branches.test.ts +0 -346
- package/tests/handlers/help-resource.test.ts +0 -92
- package/tests/handlers/prompt-handler-coverage.test.ts +0 -108
- package/tests/handlers/prompt-handlers.test.ts +0 -131
- package/tests/handlers/resource-handler-coverage.test.ts +0 -281
- package/tests/handlers/resource-handlers.test.ts +0 -357
- package/tests/handlers/resource-prompt-branches.test.ts +0 -495
- package/tests/handlers/search-tool-handlers.test.ts +0 -379
- package/tests/handlers/targeted-gap-closure.test.ts +0 -387
- package/tests/handlers/team-admin.test.ts +0 -291
- package/tests/handlers/team-analytics.test.ts +0 -220
- package/tests/handlers/team-core.test.ts +0 -148
- package/tests/handlers/team-data.test.ts +0 -198
- package/tests/handlers/team-relationships.test.ts +0 -271
- package/tests/handlers/team-resource-handlers.test.ts +0 -161
- package/tests/handlers/team-search.test.ts +0 -134
- package/tests/handlers/team-tool-handlers.test.ts +0 -301
- package/tests/handlers/team-vector.test.ts +0 -213
- package/tests/handlers/template-github-branches.test.ts +0 -676
- package/tests/handlers/tool-annotations.test.ts +0 -90
- package/tests/handlers/tool-handler-coverage.test.ts +0 -514
- package/tests/handlers/tool-handlers.test.ts +0 -510
- package/tests/handlers/tool-output-schemas.test.ts +0 -116
- package/tests/handlers/vector-tool-handlers.test.ts +0 -238
- package/tests/security/sql-injection.test.ts +0 -284
- package/tests/server/mcp-server.bench.ts +0 -55
- package/tests/server/mcp-server.test.ts +0 -1326
- package/tests/server/scheduler.test.ts +0 -400
- package/tests/transports/http-legacy-sse.test.ts +0 -275
- package/tests/transports/http-security.test.ts +0 -322
- package/tests/transports/http-stateful.test.ts +0 -487
- package/tests/transports/http-transport-server.test.ts +0 -301
- package/tests/transports/http-transport.test.ts +0 -771
- package/tests/utils/github-helpers.test.ts +0 -58
- package/tests/utils/logger.test.ts +0 -180
- package/tests/utils/mcp-logger.test.ts +0 -211
- package/tests/utils/progress-utils.test.ts +0 -156
- package/tests/utils/query-helpers.test.ts +0 -80
- package/tests/utils/security-utils.test.ts +0 -82
- package/tests/vector/vector-search-branches.test.ts +0 -111
- package/tests/vector/vector-search-manager.test.ts +0 -375
- package/tests/vector/vector-search.bench.ts +0 -48
- package/tsconfig.json +0 -42
- package/tsup.config.ts +0 -19
- package/vitest.config.ts +0 -25
|
@@ -1,1218 +0,0 @@
|
|
|
1
|
-
# Test memory-journal-mcp — Pass 4: Code Mode Advanced
|
|
2
|
-
|
|
3
|
-
Test multi-step workflows, cross-group orchestration, and the remaining tool groups (relationships, GitHub, admin/backup/export, team) through Code Mode.
|
|
4
|
-
|
|
5
|
-
**Scope:** ~55 test scenarios across 6 phases (Phases 22-27) covering multi-step pipelines, cross-group orchestration, relationships, GitHub (16 tools), admin/backup/export, and team tools — all via Code Mode.
|
|
6
|
-
|
|
7
|
-
**Prerequisites:**
|
|
8
|
-
|
|
9
|
-
- Pass 3 (`test-tools-codemode.md`) must pass first — sandbox, security, core CRUD, and search verified.
|
|
10
|
-
- Pass 1 seed data (S1-S17) must exist — S13–S14 are personal journal entries with `project_number: 5`, S15–S17 are team DB entries with `project_number: 5`, all required for `get_cross_project_insights` / `team_get_cross_project_insights` to return non-empty results.
|
|
11
|
-
- Confirm MCP server instructions were auto-received before starting.
|
|
12
|
-
- Use the MCP server directly for all tests — not the terminal or scripts.
|
|
13
|
-
- Use https://github.com/users/neverinfamous/projects/5 for project/Kanban testing.
|
|
14
|
-
|
|
15
|
-
**Workflow after testing:**
|
|
16
|
-
|
|
17
|
-
1. Create a plan to fix any issues found or potential improvement opportunities, including changes to `server-instructions.md`/`server-instructions.ts` or this file (`test-server/test-tools-codemode2.md`).
|
|
18
|
-
2. Use `code-map.md` as a source of truth and ensure fixes comply with `C:\Users\chris\Desktop\adamic\skills\mcp-builder`.
|
|
19
|
-
3. After implementation, update `UNRELEASED.md` and commit without pushing. Then, stop so the user can verify with `npm run lint && npm run typecheck`, `npm run test`, and `npm run test:e2e`.
|
|
20
|
-
4. After user completes verification, re-test fixes with direct MCP calls.
|
|
21
|
-
5. Provide a very brief final summary.
|
|
22
|
-
|
|
23
|
-
> [!IMPORTANT]
|
|
24
|
-
> **Test Session Prerequisites**
|
|
25
|
-
|
|
26
|
-
1. The server instructions are auto-injected by the MCP protocol. Confirm receipt (no need to read `memory://instructions` separately).
|
|
27
|
-
2. Read `memory://briefing` to confirm context loaded (the briefing table confirms receipt).
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Phase 22: Multi-Step Workflows
|
|
32
|
-
|
|
33
|
-
### 22.1 Read-Only Pipelines
|
|
34
|
-
|
|
35
|
-
| Test | Code | Expected Result |
|
|
36
|
-
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- |
|
|
37
|
-
| Stats + recent summary | `const stats = await mj.analytics.getStatistics({}); const recent = await mj.core.getRecentEntries({limit: 3}); return { total: stats.totalEntries, recentCount: recent.entries.length };` | Both fields populated |
|
|
38
|
-
| Search + count | `const results = await mj.search.searchEntries({query: "test", limit: 5}); return { matchCount: results.entries.length, query: "test" };` | `matchCount` ≥ 0, `query: "test"` |
|
|
39
|
-
| Recent + tag extraction | `const r = await mj.core.getRecentEntries({limit: 10}); const tags = r.entries.flatMap(e => e.tags \|\| []); const counts = {}; for (const t of tags) { counts[t] = (counts[t] \|\| 0) + 1; } return { uniqueTags: Object.keys(counts).length, topTags: Object.entries(counts).sort(([,a],[,b]) => b - a).slice(0, 5) };` | `uniqueTags` ≥ 0, `topTags` array |
|
|
40
|
-
|
|
41
|
-
### 22.2 Conditional Branching
|
|
42
|
-
|
|
43
|
-
| Test | Code | Expected Result |
|
|
44
|
-
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
|
|
45
|
-
| Conditional on stats | `const s = await mj.analytics.getStatistics({}); if (s.totalEntries > 0) { return { status: "has entries", count: s.totalEntries }; } else { return { status: "empty journal" }; }` | Returns either branch based on data |
|
|
46
|
-
| Loop over entries | `const r = await mj.core.getRecentEntries({limit: 5}); const summaries = r.entries.map(e => ({ id: e.id, type: e.entryType, len: e.content?.length ?? 0 })); return summaries;` | Array of summary objects |
|
|
47
|
-
|
|
48
|
-
### 22.3 Create + Read Round-Trip (via Code Mode)
|
|
49
|
-
|
|
50
|
-
| Test | Code | Expected Result |
|
|
51
|
-
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
|
52
|
-
| Create + read back | `const created = await mj.core.createEntryMinimal({content: "Code Mode round-trip test"}); const fetched = await mj.core.getEntryById({entry_id: created.entry.id}); return { createdId: created.entry.id, fetchedContent: fetched.entry.content };` | `fetchedContent` matches "Code Mode round-trip test" |
|
|
53
|
-
| Create + search | `const created = await mj.core.createEntry({content: "CodeMode search marker XYZ789", tags: ["codemode-test"]}); const found = await mj.search.searchEntries({query: "CodeMode search marker XYZ789", limit: 1}); return { found: found.entries.length > 0, createdId: created.entry.id };` | `found: true` |
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## Phase 23: Cross-Group Orchestration
|
|
58
|
-
|
|
59
|
-
> [!TIP]
|
|
60
|
-
> These tests simulate real agent workflows that span multiple API groups in a single Code Mode execution — the primary use case for token savings.
|
|
61
|
-
|
|
62
|
-
### 23.1 Journal Health Dashboard
|
|
63
|
-
|
|
64
|
-
```javascript
|
|
65
|
-
// Test code:
|
|
66
|
-
const stats = await mj.analytics.getStatistics({})
|
|
67
|
-
const recent = await mj.core.getRecentEntries({ limit: 5 })
|
|
68
|
-
const tags = await mj.core.listTags({})
|
|
69
|
-
return {
|
|
70
|
-
totalEntries: stats.totalEntries,
|
|
71
|
-
recentTitles: recent.entries.map((e) => e.title || e.content?.substring(0, 50)),
|
|
72
|
-
tagCount: tags.tags?.length ?? 0,
|
|
73
|
-
healthStatus: stats.totalEntries > 0 ? 'healthy' : 'empty',
|
|
74
|
-
}
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
| Check | Expected |
|
|
78
|
-
| -------------- | ---------------- |
|
|
79
|
-
| `totalEntries` | Number > 0 |
|
|
80
|
-
| `recentTitles` | Array of strings |
|
|
81
|
-
| `tagCount` | Number ≥ 0 |
|
|
82
|
-
| `healthStatus` | `"healthy"` |
|
|
83
|
-
|
|
84
|
-
### 23.2 GitHub-Journal Coverage Report
|
|
85
|
-
|
|
86
|
-
```javascript
|
|
87
|
-
// Test code:
|
|
88
|
-
const issues = await mj.github.getGithubIssues({ limit: 3 })
|
|
89
|
-
const results = []
|
|
90
|
-
for (const issue of (issues.issues || []).slice(0, 2)) {
|
|
91
|
-
const entries = await mj.search.searchEntries({
|
|
92
|
-
query: `#${issue.number}`,
|
|
93
|
-
limit: 3,
|
|
94
|
-
})
|
|
95
|
-
results.push({
|
|
96
|
-
issue: `#${issue.number}: ${issue.title}`,
|
|
97
|
-
linkedEntries: entries.entries.length,
|
|
98
|
-
})
|
|
99
|
-
}
|
|
100
|
-
return { issueCount: issues.issues?.length ?? 0, coverage: results }
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
| Check | Expected |
|
|
104
|
-
| ------------ | ----------------------------------------------- |
|
|
105
|
-
| `issueCount` | Number ≥ 0 |
|
|
106
|
-
| `coverage` | Array with `issue` and `linkedEntries` per item |
|
|
107
|
-
|
|
108
|
-
### 23.3 Tag Analysis Pipeline
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
// Test code:
|
|
112
|
-
const tagList = await mj.core.listTags({})
|
|
113
|
-
const topTags = (tagList.tags || []).sort((a, b) => b.count - a.count).slice(0, 3)
|
|
114
|
-
const report = []
|
|
115
|
-
for (const tag of topTags) {
|
|
116
|
-
const entries = await mj.search.searchEntries({ query: tag.name, limit: 2 })
|
|
117
|
-
report.push({ tag: tag.name, count: tag.count, sampleEntries: entries.entries.length })
|
|
118
|
-
}
|
|
119
|
-
return { analyzedTags: report.length, report }
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
| Check | Expected |
|
|
123
|
-
| -------------- | --------------------------------------------------- |
|
|
124
|
-
| `analyzedTags` | Number ≥ 0 |
|
|
125
|
-
| `report` | Array with `tag`, `count`, `sampleEntries` per item |
|
|
126
|
-
|
|
127
|
-
### 23.4 Relationship Graph Summary
|
|
128
|
-
|
|
129
|
-
```javascript
|
|
130
|
-
// Test code:
|
|
131
|
-
const recent = await mj.core.getRecentEntries({ limit: 5 })
|
|
132
|
-
const withRelationships = []
|
|
133
|
-
for (const entry of recent.entries.slice(0, 3)) {
|
|
134
|
-
const detail = await mj.core.getEntryById({ entry_id: entry.id })
|
|
135
|
-
const relCount = detail.entry?.relationships?.length ?? 0
|
|
136
|
-
if (relCount > 0) {
|
|
137
|
-
withRelationships.push({ id: entry.id, relationships: relCount })
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return { checked: Math.min(recent.entries.length, 3), withRelationships }
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
| Check | Expected |
|
|
144
|
-
| ------------------- | ---------------------------------------------- |
|
|
145
|
-
| `checked` | Number (1-3) |
|
|
146
|
-
| `withRelationships` | Array (may be empty if no relationships exist) |
|
|
147
|
-
|
|
148
|
-
### 23.5 Full Pipeline: Create → Index → Search
|
|
149
|
-
|
|
150
|
-
> [!CAUTION]
|
|
151
|
-
> This test creates a real entry and modifies the vector index.
|
|
152
|
-
|
|
153
|
-
```javascript
|
|
154
|
-
// Test code:
|
|
155
|
-
const entry = await mj.core.createEntry({
|
|
156
|
-
content: 'Code Mode pipeline test: semantic indexing verification ZQJKM',
|
|
157
|
-
tags: ['codemode-pipeline-test'],
|
|
158
|
-
entry_type: 'technical_note',
|
|
159
|
-
})
|
|
160
|
-
await mj.admin.addToVectorIndex({ entry_id: entry.entry.id })
|
|
161
|
-
const found = await mj.search.semanticSearch({
|
|
162
|
-
query: 'semantic indexing verification',
|
|
163
|
-
limit: 5,
|
|
164
|
-
})
|
|
165
|
-
const match = found.entries?.some((e) => e.id === entry.entry.id)
|
|
166
|
-
return {
|
|
167
|
-
createdId: entry.entry.id,
|
|
168
|
-
indexed: true,
|
|
169
|
-
foundInSemantic: match,
|
|
170
|
-
totalResults: found.entries?.length ?? 0,
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
| Check | Expected |
|
|
175
|
-
| ----------------- | ----------------------------------------------------------------------------------------------------- |
|
|
176
|
-
| `createdId` | Number |
|
|
177
|
-
| `foundInSemantic` | `true` or `false` — may be `false` due to vector indexing latency within a single Code Mode execution |
|
|
178
|
-
| `totalResults` | ≥ 1 |
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## Phase 24: Relationships & Visualization via Code Mode
|
|
183
|
-
|
|
184
|
-
### 24.1 Link Entries — All Relationship Types
|
|
185
|
-
|
|
186
|
-
```javascript
|
|
187
|
-
// Test code:
|
|
188
|
-
const r = await mj.core.getRecentEntries({ limit: 4 })
|
|
189
|
-
const ids = r.entries.map((e) => e.id)
|
|
190
|
-
if (ids.length < 4) return { error: 'Need at least 4 entries' }
|
|
191
|
-
|
|
192
|
-
const ref = await mj.relationships.linkEntries({
|
|
193
|
-
from_entry_id: ids[0],
|
|
194
|
-
to_entry_id: ids[1],
|
|
195
|
-
relationship_type: 'references',
|
|
196
|
-
})
|
|
197
|
-
const impl = await mj.relationships.linkEntries({
|
|
198
|
-
from_entry_id: ids[0],
|
|
199
|
-
to_entry_id: ids[2],
|
|
200
|
-
relationship_type: 'implements',
|
|
201
|
-
description: 'Implements the spec',
|
|
202
|
-
})
|
|
203
|
-
const blocked = await mj.relationships.linkEntries({
|
|
204
|
-
from_entry_id: ids[0],
|
|
205
|
-
to_entry_id: ids[3],
|
|
206
|
-
relationship_type: 'blocked_by',
|
|
207
|
-
})
|
|
208
|
-
const resolved = await mj.relationships.linkEntries({
|
|
209
|
-
from_entry_id: ids[1],
|
|
210
|
-
to_entry_id: ids[2],
|
|
211
|
-
relationship_type: 'resolved',
|
|
212
|
-
})
|
|
213
|
-
const caused = await mj.relationships.linkEntries({
|
|
214
|
-
from_entry_id: ids[2],
|
|
215
|
-
to_entry_id: ids[3],
|
|
216
|
-
relationship_type: 'caused',
|
|
217
|
-
})
|
|
218
|
-
return {
|
|
219
|
-
refSuccess: ref.success,
|
|
220
|
-
implSuccess: impl.success,
|
|
221
|
-
implHasDesc: !!impl.relationship?.description,
|
|
222
|
-
blockedSuccess: blocked.success,
|
|
223
|
-
resolvedSuccess: resolved.success,
|
|
224
|
-
causedSuccess: caused.success,
|
|
225
|
-
entryIds: ids,
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
| Check | Expected |
|
|
230
|
-
| -------------- | -------- |
|
|
231
|
-
| All `*Success` | `true` |
|
|
232
|
-
| `implHasDesc` | `true` |
|
|
233
|
-
|
|
234
|
-
### 24.2 Link Entries — Duplicate & Error Paths
|
|
235
|
-
|
|
236
|
-
```javascript
|
|
237
|
-
// Test code (run after 24.1):
|
|
238
|
-
const r = await mj.core.getRecentEntries({ limit: 2 })
|
|
239
|
-
const [a, b] = r.entries.map((e) => e.id)
|
|
240
|
-
|
|
241
|
-
const dup = await mj.relationships.linkEntries({
|
|
242
|
-
from_entry_id: a,
|
|
243
|
-
to_entry_id: b,
|
|
244
|
-
relationship_type: 'references',
|
|
245
|
-
})
|
|
246
|
-
const reverse = await mj.relationships.linkEntries({
|
|
247
|
-
from_entry_id: b,
|
|
248
|
-
to_entry_id: a,
|
|
249
|
-
relationship_type: 'references',
|
|
250
|
-
})
|
|
251
|
-
const badSource = await mj.relationships.linkEntries({
|
|
252
|
-
from_entry_id: 999999,
|
|
253
|
-
to_entry_id: b,
|
|
254
|
-
relationship_type: 'references',
|
|
255
|
-
})
|
|
256
|
-
const badTarget = await mj.relationships.linkEntries({
|
|
257
|
-
from_entry_id: a,
|
|
258
|
-
to_entry_id: 999999,
|
|
259
|
-
relationship_type: 'references',
|
|
260
|
-
})
|
|
261
|
-
return {
|
|
262
|
-
dupDetected: dup.duplicate === true,
|
|
263
|
-
dupHasMessage: !!dup.message,
|
|
264
|
-
reverseSuccess: reverse.success,
|
|
265
|
-
badSourceFailed: badSource.success === false,
|
|
266
|
-
badTargetFailed: badTarget.success === false,
|
|
267
|
-
}
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
| Check | Expected |
|
|
271
|
-
| ----------------- | ---------------------------------- |
|
|
272
|
-
| `dupDetected` | `true` |
|
|
273
|
-
| `reverseSuccess` | `true` (reverse direction allowed) |
|
|
274
|
-
| `badSourceFailed` | `true` |
|
|
275
|
-
| `badTargetFailed` | `true` |
|
|
276
|
-
|
|
277
|
-
### 24.3 Visualize Relationships
|
|
278
|
-
|
|
279
|
-
```javascript
|
|
280
|
-
// Test code:
|
|
281
|
-
const r = await mj.core.getRecentEntries({ limit: 1 })
|
|
282
|
-
const id = r.entries[0].id
|
|
283
|
-
|
|
284
|
-
const viz = await mj.relationships.visualizeRelationships({ entry_id: id })
|
|
285
|
-
const vizTags = await mj.relationships.visualizeRelationships({ tags: ['architecture'] })
|
|
286
|
-
const vizDeep = await mj.relationships.visualizeRelationships({ entry_id: id, depth: 3 })
|
|
287
|
-
const vizLimit = await mj.relationships.visualizeRelationships({ entry_id: id, limit: 5 })
|
|
288
|
-
const vizBad = await mj.relationships.visualizeRelationships({ entry_id: 999999 })
|
|
289
|
-
return {
|
|
290
|
-
hasMermaid: typeof viz.mermaid === 'string' && viz.mermaid.length > 0,
|
|
291
|
-
hasLegend: !!viz.legend,
|
|
292
|
-
entryCount: viz.entry_count,
|
|
293
|
-
relCount: viz.relationship_count,
|
|
294
|
-
tagVizHasMermaid: typeof vizTags.mermaid === 'string',
|
|
295
|
-
deepEntryCount: vizDeep.entry_count,
|
|
296
|
-
limitEntryCount: vizLimit.entry_count,
|
|
297
|
-
badNotFound: !!vizBad.message && vizBad.message.includes('not found'),
|
|
298
|
-
}
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
| Check | Expected |
|
|
302
|
-
| ------------- | -------- |
|
|
303
|
-
| `hasMermaid` | `true` |
|
|
304
|
-
| `hasLegend` | `true` |
|
|
305
|
-
| `entryCount` | ≥ 1 |
|
|
306
|
-
| `badNotFound` | `true` |
|
|
307
|
-
|
|
308
|
-
---
|
|
309
|
-
|
|
310
|
-
## Phase 25: GitHub Tools via Code Mode (16 tools)
|
|
311
|
-
|
|
312
|
-
> [!CAUTION]
|
|
313
|
-
> Phase 25.3–25.4 create and modify **real GitHub issues and milestones**. Clean up after testing.
|
|
314
|
-
|
|
315
|
-
### 25.1 Read-Only GitHub Tools
|
|
316
|
-
|
|
317
|
-
```javascript
|
|
318
|
-
// Test code:
|
|
319
|
-
const ctx = await mj.github.getGithubContext({})
|
|
320
|
-
const issues = await mj.github.getGithubIssues({ limit: 3 })
|
|
321
|
-
const closedIssues = await mj.github.getGithubIssues({ state: 'closed', limit: 2 })
|
|
322
|
-
const prs = await mj.github.getGithubPrs({ limit: 3 })
|
|
323
|
-
const closedPrs = await mj.github.getGithubPrs({ state: 'closed', limit: 2 })
|
|
324
|
-
const milestones = await mj.github.getGithubMilestones({})
|
|
325
|
-
|
|
326
|
-
// Single-item lookups (use known numbers from context)
|
|
327
|
-
const issueNum = issues.issues?.[0]?.number
|
|
328
|
-
const prNum = prs.pullRequests?.[0]?.number ?? closedPrs.pullRequests?.[0]?.number
|
|
329
|
-
const singleIssue = issueNum ? await mj.github.getGithubIssue({ issue_number: issueNum }) : null
|
|
330
|
-
const singlePr = prNum ? await mj.github.getGithubPr({ pr_number: prNum }) : null
|
|
331
|
-
|
|
332
|
-
return {
|
|
333
|
-
contextHasRepo: !!ctx.repoName,
|
|
334
|
-
contextHasBranch: !!ctx.branch,
|
|
335
|
-
issueCount: issues.count,
|
|
336
|
-
issueMilestoneField: typeof issues.issues?.[0]?.milestone,
|
|
337
|
-
closedIssueCount: closedIssues.count,
|
|
338
|
-
prCount: prs.count,
|
|
339
|
-
closedPrCount: closedPrs.count,
|
|
340
|
-
milestoneCount: milestones.count,
|
|
341
|
-
singleIssueHasBody: !!singleIssue?.issue?.body !== undefined,
|
|
342
|
-
singlePrHasDraft: singlePr?.pullRequest?.draft !== undefined,
|
|
343
|
-
}
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
| Check | Expected |
|
|
347
|
-
| ------------------ | -------- |
|
|
348
|
-
| `contextHasRepo` | `true` |
|
|
349
|
-
| `contextHasBranch` | `true` |
|
|
350
|
-
| `issueCount` | ≥ 0 |
|
|
351
|
-
| `milestoneCount` | ≥ 0 |
|
|
352
|
-
|
|
353
|
-
### 25.2 GitHub Error Paths
|
|
354
|
-
|
|
355
|
-
| Test | Code | Expected Result |
|
|
356
|
-
| --------------------- | -------------------------------------------------------------------------- | ------------------------------------------ |
|
|
357
|
-
| Nonexistent issue | `return await mj.github.getGithubIssue({ issue_number: 999999 });` | `{ error: "Issue #999999 not found" }` |
|
|
358
|
-
| Nonexistent PR | `return await mj.github.getGithubPr({ pr_number: 999999 });` | `{ error: "PR #999999 not found" }` |
|
|
359
|
-
| Nonexistent milestone | `return await mj.github.getGithubMilestone({ milestone_number: 999999 });` | `{ error: "Milestone #999999 not found" }` |
|
|
360
|
-
| Nonexistent Kanban | `return await mj.github.getKanbanBoard({ project_number: 99999 });` | Structured error with project not found |
|
|
361
|
-
|
|
362
|
-
### 25.3 Kanban Tools
|
|
363
|
-
|
|
364
|
-
```javascript
|
|
365
|
-
// Test code:
|
|
366
|
-
const board = await mj.github.getKanbanBoard({ project_number: 5 })
|
|
367
|
-
const hasItems = board.columns?.some((c) => c.items?.length > 0)
|
|
368
|
-
const itemId = board.columns?.flatMap((c) => c.items ?? []).find((i) => i)?.id
|
|
369
|
-
|
|
370
|
-
let moveResult = null
|
|
371
|
-
if (itemId) {
|
|
372
|
-
moveResult = await mj.github.moveKanbanItem({
|
|
373
|
-
project_number: 5,
|
|
374
|
-
item_id: itemId,
|
|
375
|
-
target_status: 'In progress',
|
|
376
|
-
})
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
const badMove = await mj.github.moveKanbanItem({
|
|
380
|
-
project_number: 5,
|
|
381
|
-
item_id: itemId || 'fake-id',
|
|
382
|
-
target_status: 'Nonexistent Status',
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
return {
|
|
386
|
-
boardHasColumns: Array.isArray(board.columns),
|
|
387
|
-
statusOptions: board.statusOptions,
|
|
388
|
-
hasItems,
|
|
389
|
-
moveSuccess: moveResult?.success,
|
|
390
|
-
badMoveError: badMove.success === false,
|
|
391
|
-
badMoveHasStatuses: Array.isArray(badMove.availableStatuses),
|
|
392
|
-
}
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
| Check | Expected |
|
|
396
|
-
| -------------------- | ----------------------- |
|
|
397
|
-
| `boardHasColumns` | `true` |
|
|
398
|
-
| `statusOptions` | Array of valid statuses |
|
|
399
|
-
| `moveSuccess` | `true` (if items exist) |
|
|
400
|
-
| `badMoveError` | `true` |
|
|
401
|
-
| `badMoveHasStatuses` | `true` |
|
|
402
|
-
|
|
403
|
-
### 25.4 Issue Lifecycle & Milestone CRUD
|
|
404
|
-
|
|
405
|
-
> [!CAUTION]
|
|
406
|
-
> Creates and closes real GitHub issues and milestones. Clean up in Phase 25.6.
|
|
407
|
-
|
|
408
|
-
```javascript
|
|
409
|
-
// Test code — Issue Lifecycle:
|
|
410
|
-
const created = await mj.github.createGithubIssueWithEntry({
|
|
411
|
-
title: 'CM4 Test: Code Mode Issue',
|
|
412
|
-
body: 'Created via Code Mode test',
|
|
413
|
-
labels: ['test'],
|
|
414
|
-
project_number: 5,
|
|
415
|
-
tags: ['codemode4-test'],
|
|
416
|
-
})
|
|
417
|
-
const issueNum = created.issue?.number
|
|
418
|
-
|
|
419
|
-
const closed = await mj.github.closeGithubIssueWithEntry({
|
|
420
|
-
issue_number: issueNum,
|
|
421
|
-
resolution_notes: 'CM4 test complete',
|
|
422
|
-
comment: 'Closing via Code Mode',
|
|
423
|
-
move_to_done: true,
|
|
424
|
-
project_number: 5,
|
|
425
|
-
})
|
|
426
|
-
|
|
427
|
-
const alreadyClosed = await mj.github.closeGithubIssueWithEntry({
|
|
428
|
-
issue_number: issueNum,
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
return {
|
|
432
|
-
createSuccess: created.success,
|
|
433
|
-
issueNumber: issueNum,
|
|
434
|
-
hasJournal: !!created.journalEntry,
|
|
435
|
-
hasProject: !!created.project,
|
|
436
|
-
closeSuccess: closed.success,
|
|
437
|
-
closeHasKanban: !!closed.kanban,
|
|
438
|
-
kanbanMoved: closed.kanban?.moved,
|
|
439
|
-
alreadyClosedError: alreadyClosed.success === false,
|
|
440
|
-
alreadyClosedMsg: alreadyClosed.error,
|
|
441
|
-
}
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
| Check | Expected |
|
|
445
|
-
| -------------------- | -------- |
|
|
446
|
-
| `createSuccess` | `true` |
|
|
447
|
-
| `hasJournal` | `true` |
|
|
448
|
-
| `closeSuccess` | `true` |
|
|
449
|
-
| `kanbanMoved` | `true` |
|
|
450
|
-
| `alreadyClosedError` | `true` |
|
|
451
|
-
|
|
452
|
-
```javascript
|
|
453
|
-
// Test code — Milestone CRUD:
|
|
454
|
-
const ms = await mj.github.createGithubMilestone({
|
|
455
|
-
title: 'CM4 Test Milestone',
|
|
456
|
-
description: 'Created via Code Mode',
|
|
457
|
-
due_on: '2026-12-31',
|
|
458
|
-
})
|
|
459
|
-
const msNum = ms.milestone?.number
|
|
460
|
-
|
|
461
|
-
const updated = await mj.github.updateGithubMilestone({
|
|
462
|
-
milestone_number: msNum,
|
|
463
|
-
description: 'Updated via Code Mode',
|
|
464
|
-
})
|
|
465
|
-
|
|
466
|
-
const closed = await mj.github.updateGithubMilestone({
|
|
467
|
-
milestone_number: msNum,
|
|
468
|
-
state: 'closed',
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
const detail = await mj.github.getGithubMilestone({
|
|
472
|
-
milestone_number: msNum,
|
|
473
|
-
})
|
|
474
|
-
|
|
475
|
-
const deleted = await mj.github.deleteGithubMilestone({
|
|
476
|
-
milestone_number: msNum,
|
|
477
|
-
confirm: true,
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
return {
|
|
481
|
-
createSuccess: ms.success,
|
|
482
|
-
msNumber: msNum,
|
|
483
|
-
updateSuccess: updated.success,
|
|
484
|
-
closeSuccess: closed.success,
|
|
485
|
-
detailState: detail.milestone?.state,
|
|
486
|
-
deleteSuccess: deleted.success,
|
|
487
|
-
}
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
| Check | Expected |
|
|
491
|
-
| --------------- | ---------- |
|
|
492
|
-
| `createSuccess` | `true` |
|
|
493
|
-
| `updateSuccess` | `true` |
|
|
494
|
-
| `detailState` | `"closed"` |
|
|
495
|
-
| `deleteSuccess` | `true` |
|
|
496
|
-
|
|
497
|
-
### 25.5 Repo Insights & Copilot Reviews
|
|
498
|
-
|
|
499
|
-
```javascript
|
|
500
|
-
// Test code:
|
|
501
|
-
const stars = await mj.github.getRepoInsights({})
|
|
502
|
-
const traffic = await mj.github.getRepoInsights({ sections: 'traffic' })
|
|
503
|
-
const all = await mj.github.getRepoInsights({ sections: 'all' })
|
|
504
|
-
|
|
505
|
-
// Copilot reviews (use a known PR number)
|
|
506
|
-
const reviewed = await mj.github.getCopilotReviews({ pr_number: 1 })
|
|
507
|
-
|
|
508
|
-
return {
|
|
509
|
-
hasStars: typeof stars.stars === 'number',
|
|
510
|
-
hasForks: typeof stars.forks === 'number',
|
|
511
|
-
trafficHasClones: traffic.traffic?.clones !== undefined || traffic.error !== undefined,
|
|
512
|
-
allSections: !!all,
|
|
513
|
-
reviewState: reviewed.state,
|
|
514
|
-
reviewComments: reviewed.commentCount,
|
|
515
|
-
}
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
| Check | Expected |
|
|
519
|
-
| ------------- | ------------------------------------- |
|
|
520
|
-
| `hasStars` | `true` |
|
|
521
|
-
| `hasForks` | `true` |
|
|
522
|
-
| `reviewState` | String (`"none"`, `"approved"`, etc.) |
|
|
523
|
-
|
|
524
|
-
### 25.6 GitHub Cleanup
|
|
525
|
-
|
|
526
|
-
> [!IMPORTANT]
|
|
527
|
-
> Run after all Phase 25 tests. Check for any unclosed test issues or milestones.
|
|
528
|
-
|
|
529
|
-
| Cleanup Step | Code |
|
|
530
|
-
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
531
|
-
| Verify no orphans | `const b = await mj.github.getKanbanBoard({ project_number: 5 }); const testItems = b.columns?.flatMap(c => c.items ?? []).filter(i => i.title?.includes("CM4")); return { orphans: testItems?.length ?? 0 };` |
|
|
532
|
-
|
|
533
|
-
---
|
|
534
|
-
|
|
535
|
-
## Phase 26: Admin, Backup & Export via Code Mode
|
|
536
|
-
|
|
537
|
-
### 26.1 Tag Management
|
|
538
|
-
|
|
539
|
-
```javascript
|
|
540
|
-
// Test code:
|
|
541
|
-
const tags = await mj.core.listTags({})
|
|
542
|
-
const hasEntries = tags.tags?.length > 0
|
|
543
|
-
|
|
544
|
-
// Create source tag for merge
|
|
545
|
-
await mj.core.createEntry({ content: 'CM4 merge test entry', tags: ['cm4-old-tag'] })
|
|
546
|
-
const merged = await mj.admin.mergeTags({
|
|
547
|
-
source_tag: 'cm4-old-tag',
|
|
548
|
-
target_tag: 'cm4-new-tag',
|
|
549
|
-
})
|
|
550
|
-
const afterMerge = await mj.core.listTags({})
|
|
551
|
-
const oldGone = !afterMerge.tags?.some((t) => t.name === 'cm4-old-tag')
|
|
552
|
-
const newExists = afterMerge.tags?.some((t) => t.name === 'cm4-new-tag')
|
|
553
|
-
|
|
554
|
-
// Error paths
|
|
555
|
-
const sameMerge = await mj.admin.mergeTags({
|
|
556
|
-
source_tag: 'cm4-new-tag',
|
|
557
|
-
target_tag: 'cm4-new-tag',
|
|
558
|
-
})
|
|
559
|
-
const nonexistentMerge = await mj.admin.mergeTags({
|
|
560
|
-
source_tag: 'nonexistent-xyz-cm4',
|
|
561
|
-
target_tag: 'test',
|
|
562
|
-
})
|
|
563
|
-
|
|
564
|
-
return {
|
|
565
|
-
tagCount: tags.tags?.length ?? 0,
|
|
566
|
-
mergeSuccess: merged.success,
|
|
567
|
-
entriesUpdated: merged.entriesUpdated,
|
|
568
|
-
oldTagGone: oldGone,
|
|
569
|
-
newTagExists: newExists,
|
|
570
|
-
sameTagError: sameMerge.success === false,
|
|
571
|
-
nonexistentError: nonexistentMerge.success === false,
|
|
572
|
-
}
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
| Check | Expected |
|
|
576
|
-
| ------------------ | -------- |
|
|
577
|
-
| `mergeSuccess` | `true` |
|
|
578
|
-
| `oldTagGone` | `true` |
|
|
579
|
-
| `newTagExists` | `true` |
|
|
580
|
-
| `sameTagError` | `true` |
|
|
581
|
-
| `nonexistentError` | `true` |
|
|
582
|
-
|
|
583
|
-
### 26.2 Export
|
|
584
|
-
|
|
585
|
-
```javascript
|
|
586
|
-
// Test code:
|
|
587
|
-
const jsonExport = await mj.export.exportEntries({ format: 'json', limit: 5 })
|
|
588
|
-
const mdExport = await mj.export.exportEntries({ format: 'markdown', limit: 5 })
|
|
589
|
-
const tagExport = await mj.export.exportEntries({
|
|
590
|
-
format: 'json',
|
|
591
|
-
tags: ['architecture'],
|
|
592
|
-
limit: 10,
|
|
593
|
-
})
|
|
594
|
-
const dateExport = await mj.export.exportEntries({
|
|
595
|
-
format: 'json',
|
|
596
|
-
start_date: '2026-01-01',
|
|
597
|
-
end_date: '2026-03-01',
|
|
598
|
-
})
|
|
599
|
-
const typeExport = await mj.export.exportEntries({
|
|
600
|
-
format: 'json',
|
|
601
|
-
entry_types: ['planning'],
|
|
602
|
-
limit: 10,
|
|
603
|
-
})
|
|
604
|
-
return {
|
|
605
|
-
jsonHasEntries: Array.isArray(jsonExport.entries),
|
|
606
|
-
jsonCount: jsonExport.entries?.length ?? 0,
|
|
607
|
-
mdHasContent: typeof mdExport.content === 'string',
|
|
608
|
-
tagFiltered:
|
|
609
|
-
tagExport.entries?.every(
|
|
610
|
-
(e) => e.tags?.includes('architecture') || e.tags?.some((t) => t === 'architecture')
|
|
611
|
-
) ?? false,
|
|
612
|
-
dateFiltered: dateExport.entries?.length >= 0,
|
|
613
|
-
typeFiltered: typeExport.entries?.every((e) => e.entryType === 'planning') ?? true,
|
|
614
|
-
}
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
| Check | Expected |
|
|
618
|
-
| ---------------- | --------------------------------------------- |
|
|
619
|
-
| `jsonHasEntries` | `true` |
|
|
620
|
-
| `mdHasContent` | `true` |
|
|
621
|
-
| `tagFiltered` | `true` (only entries with "architecture" tag) |
|
|
622
|
-
| `typeFiltered` | `true` (only "planning" type) |
|
|
623
|
-
|
|
624
|
-
### 26.3 Backup & Restore
|
|
625
|
-
|
|
626
|
-
```javascript
|
|
627
|
-
// Test code:
|
|
628
|
-
const named = await mj.backup.backupJournal({ name: 'cm4-test-backup' })
|
|
629
|
-
const auto = await mj.backup.backupJournal({})
|
|
630
|
-
const list = await mj.backup.listBackups({})
|
|
631
|
-
|
|
632
|
-
// Path traversal
|
|
633
|
-
const traversal = await mj.backup.backupJournal({ name: '../../etc/passwd' })
|
|
634
|
-
|
|
635
|
-
// Restore
|
|
636
|
-
const restored = await mj.backup.restoreBackup({
|
|
637
|
-
filename: named.filename,
|
|
638
|
-
confirm: true,
|
|
639
|
-
})
|
|
640
|
-
|
|
641
|
-
// Restore nonexistent
|
|
642
|
-
const badRestore = await mj.backup.restoreBackup({
|
|
643
|
-
filename: 'nonexistent-cm4.db',
|
|
644
|
-
confirm: true,
|
|
645
|
-
})
|
|
646
|
-
|
|
647
|
-
// Cleanup
|
|
648
|
-
const cleanup = await mj.backup.cleanupBackups({ keep_count: 5 })
|
|
649
|
-
|
|
650
|
-
return {
|
|
651
|
-
namedSuccess: named.success,
|
|
652
|
-
namedFilename: named.filename,
|
|
653
|
-
namedHasPath: !!named.path,
|
|
654
|
-
namedHasSize: typeof named.sizeBytes === 'number',
|
|
655
|
-
autoSuccess: auto.success,
|
|
656
|
-
listTotal: list.total,
|
|
657
|
-
traversalBlocked: traversal.success === false,
|
|
658
|
-
restoreSuccess: restored.success,
|
|
659
|
-
restoreHasReverted: !!restored.revertedChanges,
|
|
660
|
-
badRestoreError: badRestore.success === false,
|
|
661
|
-
cleanupSuccess: cleanup.success,
|
|
662
|
-
}
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
| Check | Expected |
|
|
666
|
-
| ------------------ | -------- |
|
|
667
|
-
| `namedSuccess` | `true` |
|
|
668
|
-
| `namedHasPath` | `true` |
|
|
669
|
-
| `namedHasSize` | `true` |
|
|
670
|
-
| `autoSuccess` | `true` |
|
|
671
|
-
| `traversalBlocked` | `true` |
|
|
672
|
-
| `restoreSuccess` | `true` |
|
|
673
|
-
| `badRestoreError` | `true` |
|
|
674
|
-
| `cleanupSuccess` | `true` |
|
|
675
|
-
|
|
676
|
-
---
|
|
677
|
-
|
|
678
|
-
## Phase 27: Team Tools & Error Paths via Code Mode
|
|
679
|
-
|
|
680
|
-
> [!NOTE]
|
|
681
|
-
> Requires `TEAM_DB_PATH` to be configured. If not configured, all team tools should return structured `{ success: false, error: "Team database not configured..." }`.
|
|
682
|
-
>
|
|
683
|
-
> **`team_delete_entry` is soft-delete only** — no `permanent` flag.
|
|
684
|
-
|
|
685
|
-
### 27.1 Team CRUD
|
|
686
|
-
|
|
687
|
-
```javascript
|
|
688
|
-
// Test code:
|
|
689
|
-
const created = await mj.team.teamCreateEntry({
|
|
690
|
-
content: 'CM4 team entry test',
|
|
691
|
-
tags: ['codemode4-team-test'],
|
|
692
|
-
entry_type: 'standup',
|
|
693
|
-
})
|
|
694
|
-
const withAuthor = await mj.team.teamCreateEntry({
|
|
695
|
-
content: 'CM4 team explicit author',
|
|
696
|
-
author: 'CM4Bot',
|
|
697
|
-
})
|
|
698
|
-
const recent = await mj.team.teamGetRecent({ limit: 5 })
|
|
699
|
-
const search = await mj.team.teamSearch({ query: 'CM4 team entry test' })
|
|
700
|
-
const tagSearch = await mj.team.teamSearch({ tags: ['codemode4-team-test'] })
|
|
701
|
-
const combined = await mj.team.teamSearch({
|
|
702
|
-
query: 'team',
|
|
703
|
-
tags: ['codemode4-team-test'],
|
|
704
|
-
})
|
|
705
|
-
const noArgs = await mj.team.teamSearch({})
|
|
706
|
-
|
|
707
|
-
// New: get by ID, list tags
|
|
708
|
-
const detail = await mj.team.teamGetEntryById({ entry_id: created.entry.id })
|
|
709
|
-
const detailNoRels = await mj.team.teamGetEntryById({
|
|
710
|
-
entry_id: created.entry.id,
|
|
711
|
-
include_relationships: false,
|
|
712
|
-
})
|
|
713
|
-
const tags = await mj.team.teamListTags({})
|
|
714
|
-
|
|
715
|
-
return {
|
|
716
|
-
createSuccess: created.success,
|
|
717
|
-
createAuthor: created.entry?.author,
|
|
718
|
-
explicitAuthor: withAuthor.entry?.author,
|
|
719
|
-
recentCount: recent.entries?.length ?? 0,
|
|
720
|
-
recentHasAuthor: !!recent.entries?.[0]?.author,
|
|
721
|
-
searchCount: search.entries?.length ?? 0,
|
|
722
|
-
tagSearchCount: tagSearch.entries?.length ?? 0,
|
|
723
|
-
combinedCount: combined.entries?.length ?? 0,
|
|
724
|
-
noArgsCount: noArgs.entries?.length ?? 0,
|
|
725
|
-
detailHasEntry: !!detail.entry,
|
|
726
|
-
detailHasImportance: !!detail.importance,
|
|
727
|
-
detailNoRelsEmpty: !detailNoRels.relationships?.length,
|
|
728
|
-
tagCount: tags.tags?.length ?? 0,
|
|
729
|
-
}
|
|
730
|
-
```
|
|
731
|
-
|
|
732
|
-
| Check | Expected |
|
|
733
|
-
| ----------------- | --------------------------------- |
|
|
734
|
-
| `createSuccess` | `true` |
|
|
735
|
-
| `createAuthor` | Non-empty string (auto-populated) |
|
|
736
|
-
| `explicitAuthor` | `"CM4Bot"` |
|
|
737
|
-
| `recentHasAuthor` | `true` |
|
|
738
|
-
| `searchCount` | ≥ 1 |
|
|
739
|
-
| `tagSearchCount` | ≥ 1 |
|
|
740
|
-
| `detailHasEntry` | `true` |
|
|
741
|
-
| `tagCount` | ≥ 1 |
|
|
742
|
-
|
|
743
|
-
### 27.2 Team Error Paths
|
|
744
|
-
|
|
745
|
-
| Test | Code | Expected Result |
|
|
746
|
-
| ------------------ | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
|
747
|
-
| Invalid entry_type | `return await mj.team.teamCreateEntry({ content: "test", entry_type: "invalid" });` | `{ success: false, error: "..." }` |
|
|
748
|
-
| Nonexistent get | `return await mj.team.teamGetEntryById({ entry_id: 999999 });` | `{ success: false, error: "..." }` |
|
|
749
|
-
| Nonexistent update | `return await mj.team.teamUpdateEntry({ entry_id: 999999, content: "x" });` | `{ success: false, error: "..." }` |
|
|
750
|
-
| Nonexistent delete | `return await mj.team.teamDeleteEntry({ entry_id: 999999 });` | `{ success: false, error: "..." }` |
|
|
751
|
-
| Invalid date range | `return await mj.team.teamSearchByDateRange({ start_date: "Jan 1", end_date: "Jan 31" });` | `{ success: false, error: "..." }` |
|
|
752
|
-
| Merge same tag | `return await mj.team.teamMergeTags({ source_tag: "x", target_tag: "x" });` | `{ success: false, error: "..." }` |
|
|
753
|
-
| Link nonexistent | `return await mj.team.teamLinkEntries({ from_entry_id: 999999, to_entry_id: 1, relationship_type: "references" });` | `{ success: false, error: "..." }` |
|
|
754
|
-
|
|
755
|
-
### 27.3 Team Date Range Search
|
|
756
|
-
|
|
757
|
-
```javascript
|
|
758
|
-
// Test code:
|
|
759
|
-
const results = await mj.team.teamSearchByDateRange({
|
|
760
|
-
start_date: '2026-01-01',
|
|
761
|
-
end_date: '2026-12-31',
|
|
762
|
-
})
|
|
763
|
-
const typed = await mj.team.teamSearchByDateRange({
|
|
764
|
-
start_date: '2026-01-01',
|
|
765
|
-
end_date: '2026-12-31',
|
|
766
|
-
entry_type: 'standup',
|
|
767
|
-
})
|
|
768
|
-
const tagged = await mj.team.teamSearchByDateRange({
|
|
769
|
-
start_date: '2026-01-01',
|
|
770
|
-
end_date: '2026-12-31',
|
|
771
|
-
tags: ['codemode4-team-test'],
|
|
772
|
-
})
|
|
773
|
-
return {
|
|
774
|
-
hasEntries: Array.isArray(results.entries),
|
|
775
|
-
count: results.count ?? 0,
|
|
776
|
-
typedFiltered: typed.entries?.every((e) => e.entryType === 'standup') ?? true,
|
|
777
|
-
taggedCount: tagged.entries?.length ?? 0,
|
|
778
|
-
}
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
| Check | Expected |
|
|
782
|
-
| --------------- | -------- |
|
|
783
|
-
| `hasEntries` | `true` |
|
|
784
|
-
| `typedFiltered` | `true` |
|
|
785
|
-
|
|
786
|
-
### 27.4 Team Admin
|
|
787
|
-
|
|
788
|
-
```javascript
|
|
789
|
-
// Test code:
|
|
790
|
-
const r = await mj.team.teamGetRecent({ limit: 1 })
|
|
791
|
-
const id = r.entries[0].id
|
|
792
|
-
|
|
793
|
-
const updated = await mj.team.teamUpdateEntry({
|
|
794
|
-
entry_id: id,
|
|
795
|
-
content: 'CM4 updated team content',
|
|
796
|
-
tags: ['cm4-updated-team'],
|
|
797
|
-
})
|
|
798
|
-
const verify = await mj.team.teamGetEntryById({ entry_id: id })
|
|
799
|
-
|
|
800
|
-
// Merge tags
|
|
801
|
-
await mj.team.teamCreateEntry({ content: 'CM4 merge source', tags: ['cm4-team-old'] })
|
|
802
|
-
const merged = await mj.team.teamMergeTags({
|
|
803
|
-
source_tag: 'cm4-team-old',
|
|
804
|
-
target_tag: 'cm4-team-new',
|
|
805
|
-
})
|
|
806
|
-
const afterTags = await mj.team.teamListTags({})
|
|
807
|
-
const oldGone = !afterTags.tags?.some((t) => t.name === 'cm4-team-old')
|
|
808
|
-
const newExists = afterTags.tags?.some((t) => t.name === 'cm4-team-new')
|
|
809
|
-
|
|
810
|
-
// Soft delete
|
|
811
|
-
const toDelete = await mj.team.teamCreateEntry({ content: 'CM4 delete me' })
|
|
812
|
-
const deleted = await mj.team.teamDeleteEntry({ entry_id: toDelete.entry.id })
|
|
813
|
-
|
|
814
|
-
return {
|
|
815
|
-
updateSuccess: updated.success,
|
|
816
|
-
contentUpdated: verify.entry?.content === 'CM4 updated team content',
|
|
817
|
-
mergeSuccess: merged.success,
|
|
818
|
-
oldTagGone: oldGone,
|
|
819
|
-
newTagExists: newExists,
|
|
820
|
-
deleteSuccess: deleted.success,
|
|
821
|
-
}
|
|
822
|
-
```
|
|
823
|
-
|
|
824
|
-
| Check | Expected |
|
|
825
|
-
| ---------------- | -------- |
|
|
826
|
-
| `updateSuccess` | `true` |
|
|
827
|
-
| `contentUpdated` | `true` |
|
|
828
|
-
| `mergeSuccess` | `true` |
|
|
829
|
-
| `oldTagGone` | `true` |
|
|
830
|
-
| `newTagExists` | `true` |
|
|
831
|
-
| `deleteSuccess` | `true` |
|
|
832
|
-
|
|
833
|
-
### 27.5 Team Analytics
|
|
834
|
-
|
|
835
|
-
```javascript
|
|
836
|
-
// Test code:
|
|
837
|
-
const stats = await mj.team.teamGetStatistics({})
|
|
838
|
-
const monthly = await mj.team.teamGetStatistics({ group_by: 'month' })
|
|
839
|
-
return {
|
|
840
|
-
hasTotalEntries: typeof stats.totalEntries === 'number',
|
|
841
|
-
hasEntriesByType: !!stats.entriesByType,
|
|
842
|
-
hasAuthors: Array.isArray(stats.authors),
|
|
843
|
-
monthlyHasPeriods: Array.isArray(monthly.entriesByPeriod),
|
|
844
|
-
}
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
| Check | Expected |
|
|
848
|
-
| ------------------- | -------- |
|
|
849
|
-
| `hasTotalEntries` | `true` |
|
|
850
|
-
| `hasEntriesByType` | `true` |
|
|
851
|
-
| `hasAuthors` | `true` |
|
|
852
|
-
| `monthlyHasPeriods` | `true` |
|
|
853
|
-
|
|
854
|
-
### 27.6 Team Relationships
|
|
855
|
-
|
|
856
|
-
```javascript
|
|
857
|
-
// Test code:
|
|
858
|
-
const r = await mj.team.teamGetRecent({ limit: 2 })
|
|
859
|
-
const [a, b] = r.entries.map((e) => e.id)
|
|
860
|
-
|
|
861
|
-
const linked = await mj.team.teamLinkEntries({
|
|
862
|
-
from_entry_id: a,
|
|
863
|
-
to_entry_id: b,
|
|
864
|
-
relationship_type: 'references',
|
|
865
|
-
description: 'CM4 team link test',
|
|
866
|
-
})
|
|
867
|
-
const dup = await mj.team.teamLinkEntries({
|
|
868
|
-
from_entry_id: a,
|
|
869
|
-
to_entry_id: b,
|
|
870
|
-
relationship_type: 'references',
|
|
871
|
-
})
|
|
872
|
-
const viz = await mj.team.teamVisualizeRelationships({ entry_id: a })
|
|
873
|
-
const vizTag = await mj.team.teamVisualizeRelationships({ tag: 'codemode4-team-test' })
|
|
874
|
-
|
|
875
|
-
return {
|
|
876
|
-
linkSuccess: linked.success,
|
|
877
|
-
hasDescription: !!linked.relationship?.description,
|
|
878
|
-
dupDetected: dup.duplicate === true,
|
|
879
|
-
hasMermaid: typeof viz.mermaid === 'string' && viz.mermaid.length > 0,
|
|
880
|
-
nodeCount: viz.nodeCount,
|
|
881
|
-
tagVizHasMermaid: typeof vizTag.mermaid === 'string',
|
|
882
|
-
}
|
|
883
|
-
```
|
|
884
|
-
|
|
885
|
-
| Check | Expected |
|
|
886
|
-
| ---------------- | -------- |
|
|
887
|
-
| `linkSuccess` | `true` |
|
|
888
|
-
| `hasDescription` | `true` |
|
|
889
|
-
| `dupDetected` | `true` |
|
|
890
|
-
| `hasMermaid` | `true` |
|
|
891
|
-
|
|
892
|
-
### 27.7 Team Export
|
|
893
|
-
|
|
894
|
-
```javascript
|
|
895
|
-
// Test code:
|
|
896
|
-
const jsonExport = await mj.team.teamExportEntries({ format: 'json', limit: 5 })
|
|
897
|
-
const mdExport = await mj.team.teamExportEntries({ format: 'markdown', limit: 5 })
|
|
898
|
-
const tagExport = await mj.team.teamExportEntries({
|
|
899
|
-
format: 'json',
|
|
900
|
-
tags: ['codemode4-team-test'],
|
|
901
|
-
limit: 10,
|
|
902
|
-
})
|
|
903
|
-
return {
|
|
904
|
-
jsonHasData: typeof jsonExport.data === 'string',
|
|
905
|
-
jsonCount: jsonExport.count ?? 0,
|
|
906
|
-
mdHasData: typeof mdExport.data === 'string',
|
|
907
|
-
tagFilteredCount: tagExport.count ?? 0,
|
|
908
|
-
}
|
|
909
|
-
```
|
|
910
|
-
|
|
911
|
-
| Check | Expected |
|
|
912
|
-
| ------------- | -------- |
|
|
913
|
-
| `jsonHasData` | `true` |
|
|
914
|
-
| `mdHasData` | `true` |
|
|
915
|
-
| `jsonCount` | ≥ 1 |
|
|
916
|
-
|
|
917
|
-
### 27.8 Team Backup
|
|
918
|
-
|
|
919
|
-
```javascript
|
|
920
|
-
// Test code:
|
|
921
|
-
const named = await mj.team.teamBackup({ name: 'cm4-team-backup' })
|
|
922
|
-
const auto = await mj.team.teamBackup({})
|
|
923
|
-
const list = await mj.team.teamListBackups({})
|
|
924
|
-
return {
|
|
925
|
-
namedSuccess: named.success,
|
|
926
|
-
namedFilename: named.filename,
|
|
927
|
-
namedHasPath: !!named.path,
|
|
928
|
-
namedHasSize: typeof named.sizeBytes === 'number',
|
|
929
|
-
autoSuccess: auto.success,
|
|
930
|
-
listTotal: list.total,
|
|
931
|
-
listHasBackups: Array.isArray(list.backups),
|
|
932
|
-
}
|
|
933
|
-
```
|
|
934
|
-
|
|
935
|
-
| Check | Expected |
|
|
936
|
-
| ---------------- | -------- |
|
|
937
|
-
| `namedSuccess` | `true` |
|
|
938
|
-
| `namedHasPath` | `true` |
|
|
939
|
-
| `namedHasSize` | `true` |
|
|
940
|
-
| `autoSuccess` | `true` |
|
|
941
|
-
| `listHasBackups` | `true` |
|
|
942
|
-
|
|
943
|
-
### 27.9 Team Vector & Cross-Project Insights
|
|
944
|
-
|
|
945
|
-
```javascript
|
|
946
|
-
// Test code:
|
|
947
|
-
const rebuild = await mj.team.teamRebuildVectorIndex({})
|
|
948
|
-
const stats = await mj.team.teamGetVectorIndexStats({})
|
|
949
|
-
|
|
950
|
-
const search = await mj.team.teamSemanticSearch({ query: 'standup' })
|
|
951
|
-
const strict = await mj.team.teamSemanticSearch({
|
|
952
|
-
query: 'standup',
|
|
953
|
-
similarity_threshold: 0.5,
|
|
954
|
-
})
|
|
955
|
-
|
|
956
|
-
const recent = await mj.team.teamGetRecent({ limit: 1 })
|
|
957
|
-
const addResult = await mj.team.teamAddToVectorIndex({
|
|
958
|
-
entry_id: recent.entries[0].id,
|
|
959
|
-
})
|
|
960
|
-
const addBad = await mj.team.teamAddToVectorIndex({ entry_id: 999999 })
|
|
961
|
-
|
|
962
|
-
const insights = await mj.team.teamGetCrossProjectInsights({})
|
|
963
|
-
const insightsFiltered = await mj.team.teamGetCrossProjectInsights({
|
|
964
|
-
start_date: '2026-01-01',
|
|
965
|
-
end_date: '2026-03-01',
|
|
966
|
-
min_entries: 1,
|
|
967
|
-
})
|
|
968
|
-
|
|
969
|
-
return {
|
|
970
|
-
rebuildSuccess: rebuild.success,
|
|
971
|
-
entriesIndexed: rebuild.entriesIndexed,
|
|
972
|
-
vectorAvailable: stats.available,
|
|
973
|
-
vectorItemCount: stats.itemCount,
|
|
974
|
-
searchCount: search.entries?.length ?? 0,
|
|
975
|
-
strictFewer: (strict.entries?.length ?? 0) <= (search.entries?.length ?? 0),
|
|
976
|
-
addSuccess: addResult.success,
|
|
977
|
-
addBadError: addBad.success === false,
|
|
978
|
-
insightsProjectCount: insights.project_count,
|
|
979
|
-
insightsHasProjects: Array.isArray(insights.projects),
|
|
980
|
-
filteredInsights: insightsFiltered.project_count >= 0,
|
|
981
|
-
}
|
|
982
|
-
```
|
|
983
|
-
|
|
984
|
-
| Check | Expected |
|
|
985
|
-
| ---------------------- | ------------------------------------------------------------------------- |
|
|
986
|
-
| `rebuildSuccess` | `true` |
|
|
987
|
-
| `entriesIndexed` | Number > 0 |
|
|
988
|
-
| `vectorAvailable` | `true` |
|
|
989
|
-
| `searchCount` | ≥ 1 |
|
|
990
|
-
| `strictFewer` | `true` |
|
|
991
|
-
| `addSuccess` | `true` |
|
|
992
|
-
| `addBadError` | `true` |
|
|
993
|
-
| `insightsHasProjects` | `true` |
|
|
994
|
-
| `insightsProjectCount` | ≥ 1 (project 5 visible with seed entries S15–S17; 0 if team seed missing) |
|
|
995
|
-
| `filteredInsights` | `project_count ≥ 0` (≥ 1 if S15–S17 fall within date range) |
|
|
996
|
-
|
|
997
|
-
### 27.10 Cross-Tool Error Path Verification (via Code Mode)
|
|
998
|
-
|
|
999
|
-
> [!IMPORTANT]
|
|
1000
|
-
> Verify that tool errors propagate as structured handler errors through the Code Mode API bridge — not as raw MCP errors or unhandled exceptions.
|
|
1001
|
-
|
|
1002
|
-
```javascript
|
|
1003
|
-
// Test code — batch error path testing:
|
|
1004
|
-
const errors = {}
|
|
1005
|
-
|
|
1006
|
-
// Core errors
|
|
1007
|
-
errors.createEmpty = await mj.core.createEntry({ content: '' })
|
|
1008
|
-
errors.getNotFound = await mj.core.getEntryById({ entry_id: 999999 })
|
|
1009
|
-
errors.updateNotFound = await mj.admin.updateEntry({ entry_id: 999999, content: 'x' })
|
|
1010
|
-
errors.deleteNotFound = await mj.admin.deleteEntry({ entry_id: 999999 })
|
|
1011
|
-
|
|
1012
|
-
// Relationship errors
|
|
1013
|
-
errors.linkBadSource = await mj.relationships.linkEntries({
|
|
1014
|
-
from_entry_id: 999999,
|
|
1015
|
-
to_entry_id: 1,
|
|
1016
|
-
relationship_type: 'references',
|
|
1017
|
-
})
|
|
1018
|
-
errors.vizNotFound = await mj.relationships.visualizeRelationships({ entry_id: 999999 })
|
|
1019
|
-
|
|
1020
|
-
// GitHub errors
|
|
1021
|
-
errors.issueNotFound = await mj.github.getGithubIssue({ issue_number: 999999 })
|
|
1022
|
-
errors.prNotFound = await mj.github.getGithubPr({ pr_number: 999999 })
|
|
1023
|
-
errors.msNotFound = await mj.github.getGithubMilestone({ milestone_number: 999999 })
|
|
1024
|
-
|
|
1025
|
-
// Backup errors
|
|
1026
|
-
errors.restoreNotFound = await mj.backup.restoreBackup({
|
|
1027
|
-
filename: 'nonexistent.db',
|
|
1028
|
-
confirm: true,
|
|
1029
|
-
})
|
|
1030
|
-
errors.backupTraversal = await mj.backup.backupJournal({ name: '../../../etc/passwd' })
|
|
1031
|
-
|
|
1032
|
-
// Admin errors
|
|
1033
|
-
errors.mergeNonexistent = await mj.admin.mergeTags({
|
|
1034
|
-
source_tag: 'nonexistent-xyz-abc',
|
|
1035
|
-
target_tag: 'test',
|
|
1036
|
-
})
|
|
1037
|
-
errors.addVectorBad = await mj.admin.addToVectorIndex({ entry_id: 999999 })
|
|
1038
|
-
|
|
1039
|
-
// Team errors
|
|
1040
|
-
errors.teamGetNotFound = await mj.team.teamGetEntryById({ entry_id: 999999 })
|
|
1041
|
-
errors.teamUpdateNotFound = await mj.team.teamUpdateEntry({ entry_id: 999999, content: 'x' })
|
|
1042
|
-
errors.teamDeleteNotFound = await mj.team.teamDeleteEntry({ entry_id: 999999 })
|
|
1043
|
-
errors.teamLinkBad = await mj.team.teamLinkEntries({
|
|
1044
|
-
from_entry_id: 999999,
|
|
1045
|
-
to_entry_id: 1,
|
|
1046
|
-
relationship_type: 'references',
|
|
1047
|
-
})
|
|
1048
|
-
|
|
1049
|
-
// Team vector errors (only true error paths)
|
|
1050
|
-
errors.teamAddVectorBad = await mj.team.teamAddToVectorIndex({ entry_id: 999999 })
|
|
1051
|
-
|
|
1052
|
-
// Verify all errors are structured (not raw throws)
|
|
1053
|
-
const allStructured = Object.entries(errors).every(([key, val]) => {
|
|
1054
|
-
return (
|
|
1055
|
-
val &&
|
|
1056
|
-
typeof val === 'object' &&
|
|
1057
|
-
(val.success === false || val.error !== undefined || val.message?.includes('not found'))
|
|
1058
|
-
)
|
|
1059
|
-
})
|
|
1060
|
-
|
|
1061
|
-
return {
|
|
1062
|
-
testedCount: Object.keys(errors).length,
|
|
1063
|
-
allStructured,
|
|
1064
|
-
details: Object.fromEntries(
|
|
1065
|
-
Object.entries(errors).map(([k, v]) => [
|
|
1066
|
-
k,
|
|
1067
|
-
{
|
|
1068
|
-
success: v.success,
|
|
1069
|
-
hasError: !!v.error || !!v.message,
|
|
1070
|
-
errorSnippet: (v.error || v.message || '')?.substring(0, 60),
|
|
1071
|
-
},
|
|
1072
|
-
])
|
|
1073
|
-
),
|
|
1074
|
-
}
|
|
1075
|
-
```
|
|
1076
|
-
|
|
1077
|
-
| Check | Expected |
|
|
1078
|
-
| --------------- | --------------------------------------------------- |
|
|
1079
|
-
| `testedCount` | 18 |
|
|
1080
|
-
| `allStructured` | `true` — no raw exceptions through Code Mode bridge |
|
|
1081
|
-
|
|
1082
|
-
---
|
|
1083
|
-
|
|
1084
|
-
## Cleanup
|
|
1085
|
-
|
|
1086
|
-
After testing, remove all entries and backups created during Phases 22-27:
|
|
1087
|
-
|
|
1088
|
-
```javascript
|
|
1089
|
-
// Cleanup code:
|
|
1090
|
-
const entries = await mj.search.searchEntries({ query: 'CM4', limit: 50 })
|
|
1091
|
-
const cm4Entries = entries.entries.filter(
|
|
1092
|
-
(e) => e.content?.includes('CM4') || e.tags?.some((t) => t.startsWith('codemode4'))
|
|
1093
|
-
)
|
|
1094
|
-
const results = []
|
|
1095
|
-
for (const e of cm4Entries) {
|
|
1096
|
-
const del = await mj.admin.deleteEntry({ entry_id: e.id, permanent: true })
|
|
1097
|
-
results.push({ id: e.id, deleted: del.success })
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
// Also clean up Code Mode (Phase 22-23) entries
|
|
1101
|
-
const cmEntries = await mj.search.searchEntries({ query: 'CodeMode', limit: 50 })
|
|
1102
|
-
for (const e of cmEntries.entries) {
|
|
1103
|
-
if (
|
|
1104
|
-
e.content?.includes('Code Mode') &&
|
|
1105
|
-
(e.tags?.includes('codemode-test') || e.tags?.includes('codemode-pipeline-test'))
|
|
1106
|
-
) {
|
|
1107
|
-
const del = await mj.admin.deleteEntry({ entry_id: e.id, permanent: true })
|
|
1108
|
-
results.push({ id: e.id, deleted: del.success })
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
// Clean up team entries created during Phase 27
|
|
1113
|
-
const teamEntries = await mj.team.teamSearch({ query: 'CM4', limit: 50 })
|
|
1114
|
-
for (const e of teamEntries.entries ?? []) {
|
|
1115
|
-
if (e.content?.includes('CM4')) {
|
|
1116
|
-
const del = await mj.team.teamDeleteEntry({ entry_id: e.id })
|
|
1117
|
-
results.push({ id: e.id, source: 'team', deleted: del.success })
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
return { cleaned: results.length, details: results }
|
|
1122
|
-
```
|
|
1123
|
-
|
|
1124
|
-
---
|
|
1125
|
-
|
|
1126
|
-
## Test Execution Order
|
|
1127
|
-
|
|
1128
|
-
1. **Phase 22**: Multi-Step Workflows (read-only pipelines, conditional branching, create+read round-trip)
|
|
1129
|
-
2. **Phase 23**: Cross-Group Orchestration (health dashboard, GitHub-journal coverage, tag analysis, full pipeline)
|
|
1130
|
-
3. **Phase 24**: Relationships & Visualization (all types, duplicates, visualization variants, error paths)
|
|
1131
|
-
4. **Phase 25**: GitHub (16 tools — context, issues, PRs, Kanban, milestones, insights, copilot + cleanup)
|
|
1132
|
-
5. **Phase 26**: Admin, Backup & Export (tags, merge, export filters, backup lifecycle)
|
|
1133
|
-
6. **Phase 27**: Team + Error Paths (20 team tools CRUD, admin, analytics, vector, insights, relationships, export, backup, cross-tool error propagation)
|
|
1134
|
-
|
|
1135
|
-
---
|
|
1136
|
-
|
|
1137
|
-
## Success Criteria
|
|
1138
|
-
|
|
1139
|
-
### Multi-Step Workflows (Phase 22)
|
|
1140
|
-
|
|
1141
|
-
- [ ] Chaining 2+ API calls in single execution works
|
|
1142
|
-
- [ ] Data transformation (map, flatMap, sort, reduce) works on results
|
|
1143
|
-
- [ ] Conditional branching based on query results works
|
|
1144
|
-
- [ ] Create + read round-trip produces matching data
|
|
1145
|
-
- [ ] Create + search finds the created entry
|
|
1146
|
-
|
|
1147
|
-
### Cross-Group Orchestration (Phase 23)
|
|
1148
|
-
|
|
1149
|
-
- [ ] Journal health dashboard aggregates stats + recent + tags correctly
|
|
1150
|
-
- [ ] GitHub-journal coverage report iterates issues and searches entries
|
|
1151
|
-
- [ ] Tag analysis pipeline processes multiple tags with search per tag
|
|
1152
|
-
- [ ] Relationship graph summary checks entries for relationship counts
|
|
1153
|
-
- [ ] Full pipeline (create → index → semantic search) completes end-to-end
|
|
1154
|
-
|
|
1155
|
-
### Relationships (Phase 24)
|
|
1156
|
-
|
|
1157
|
-
- [ ] All relationship types (`references`, `implements`, `blocked_by`, `resolved`, `caused`) create via Code Mode
|
|
1158
|
-
- [ ] `link_entries` with `description` persists the description
|
|
1159
|
-
- [ ] Duplicate detection returns `duplicate: true`
|
|
1160
|
-
- [ ] Nonexistent IDs return `success: false` with descriptive message
|
|
1161
|
-
- [ ] `visualize_relationships` returns Mermaid with legend, supports tags/depth/limit filters
|
|
1162
|
-
- [ ] Nonexistent entry ID returns "not found" message
|
|
1163
|
-
|
|
1164
|
-
### GitHub (Phase 25)
|
|
1165
|
-
|
|
1166
|
-
- [ ] All 16 GitHub tools callable via `mj.github.*`
|
|
1167
|
-
- [ ] `get_github_context` returns repo and branch info
|
|
1168
|
-
- [ ] `get_github_issues` and `get_github_prs` support `state` filter (open/closed/all)
|
|
1169
|
-
- [ ] Single issue/PR lookups return expected fields
|
|
1170
|
-
- [ ] Nonexistent issue/PR/milestone return structured errors
|
|
1171
|
-
- [ ] Kanban board returns columns with statusOptions
|
|
1172
|
-
- [ ] `move_kanban_item` with invalid status returns error with `availableStatuses`
|
|
1173
|
-
- [ ] Issue lifecycle (create → close) works end-to-end via Code Mode
|
|
1174
|
-
- [ ] `close_github_issue_with_entry` returns error for already-closed issues
|
|
1175
|
-
- [ ] Milestone CRUD lifecycle (create → update → close → delete) works via Code Mode
|
|
1176
|
-
- [ ] `get_repo_insights` returns star/fork data
|
|
1177
|
-
- [ ] `get_copilot_reviews` returns review state
|
|
1178
|
-
- [ ] All test artifacts cleaned up
|
|
1179
|
-
|
|
1180
|
-
### Admin, Backup & Export (Phase 26)
|
|
1181
|
-
|
|
1182
|
-
- [ ] `list_tags` returns tag list via Code Mode
|
|
1183
|
-
- [ ] `merge_tags` consolidates tags correctly — source removed, target exists
|
|
1184
|
-
- [ ] `merge_tags` returns structured errors for same-tag and nonexistent source
|
|
1185
|
-
- [ ] `export_entries` JSON and markdown formats work
|
|
1186
|
-
- [ ] `export_entries` filters (`tags`, `start_date/end_date`, `entry_types`) produce filtered results
|
|
1187
|
-
- [ ] `backup_journal` named and auto-named both succeed
|
|
1188
|
-
- [ ] `backup_journal` path traversal blocked with structured error
|
|
1189
|
-
- [ ] `list_backups` returns backup metadata
|
|
1190
|
-
- [ ] `restore_backup` succeeds with `revertedChanges` field
|
|
1191
|
-
- [ ] `restore_backup` nonexistent file returns structured error
|
|
1192
|
-
- [ ] `cleanup_backups` deletes old backups
|
|
1193
|
-
|
|
1194
|
-
### Team & Error Paths (Phase 27)
|
|
1195
|
-
|
|
1196
|
-
- [ ] `team_create_entry` with auto-detected and explicit `author` works
|
|
1197
|
-
- [ ] `team_get_recent` returns entries with `author` field
|
|
1198
|
-
- [ ] `team_search` filters by text, tags, and combined
|
|
1199
|
-
- [ ] `team_get_entry_by_id` returns entry detail with `importance` and optional `relationships`
|
|
1200
|
-
- [ ] `team_list_tags` returns tag list from team database
|
|
1201
|
-
- [ ] `team_search_by_date_range` filters by date range, entry_type, and tags
|
|
1202
|
-
- [ ] `team_update_entry` updates content, tags, and entry_type
|
|
1203
|
-
- [ ] `team_delete_entry` soft-deletes team entries
|
|
1204
|
-
- [ ] `team_merge_tags` consolidates tags — source removed, entries re-tagged
|
|
1205
|
-
- [ ] `team_get_statistics` returns `totalEntries`, `entriesByType`, `authors`
|
|
1206
|
-
- [ ] `team_link_entries` creates relationships with duplicate detection
|
|
1207
|
-
- [ ] `team_visualize_relationships` returns Mermaid diagram with node/edge counts
|
|
1208
|
-
- [ ] `team_export_entries` exports JSON and markdown with filters
|
|
1209
|
-
- [ ] `team_backup` creates named and auto-named backups
|
|
1210
|
-
- [ ] `team_list_backups` returns backup metadata
|
|
1211
|
-
- [ ] `team_rebuild_vector_index` indexes team entries via Code Mode
|
|
1212
|
-
- [ ] `team_get_vector_index_stats` returns vector stats via Code Mode
|
|
1213
|
-
- [ ] `team_semantic_search` with threshold filtering works via Code Mode
|
|
1214
|
-
- [ ] `team_add_to_vector_index` succeeds for existing, errors for nonexistent via Code Mode
|
|
1215
|
-
- [ ] `team_get_cross_project_insights` returns schema-compliant response via Code Mode
|
|
1216
|
-
- [ ] Invalid `entry_type` on team create returns structured error
|
|
1217
|
-
- [ ] All 18 cross-tool error paths return structured handler errors (not raw throws) through Code Mode
|
|
1218
|
-
- [ ] All test entries cleaned up after Phase 27
|