sqlew 3.7.3 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +427 -1
- package/README.md +71 -2
- package/assets/kanban-visualizer.png +0 -0
- package/assets/sample-agents/sqlew-scrum-master.md +4 -4
- package/dist/adapters/postgresql-adapter.d.ts +197 -5
- package/dist/adapters/postgresql-adapter.d.ts.map +1 -1
- package/dist/adapters/postgresql-adapter.js +300 -36
- package/dist/adapters/postgresql-adapter.js.map +1 -1
- package/dist/cli/db-export.d.ts +29 -0
- package/dist/cli/db-export.d.ts.map +1 -0
- package/dist/cli/db-export.js +251 -0
- package/dist/cli/db-export.js.map +1 -0
- package/dist/cli/db-import.d.ts +31 -0
- package/dist/cli/db-import.d.ts.map +1 -0
- package/dist/cli/db-import.js +258 -0
- package/dist/cli/db-import.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +32 -73
- package/dist/cli.js.map +1 -1
- package/dist/config/knex/bootstrap/20251025021416_seed_master_data.d.ts.map +1 -1
- package/dist/config/knex/bootstrap/20251025021416_seed_master_data.js +158 -45
- package/dist/config/knex/bootstrap/20251025021416_seed_master_data.js.map +1 -1
- package/dist/config/knex/bootstrap/20251025070349_create_views.d.ts.map +1 -1
- package/dist/config/knex/bootstrap/20251025070349_create_views.js +60 -8
- package/dist/config/knex/bootstrap/20251025070349_create_views.js.map +1 -1
- package/dist/config/knex/enhancements/20251025100000_seed_help_metadata.js +1 -1
- package/dist/config/knex/enhancements/20251025100100_seed_remaining_use_cases.js +5 -5
- package/dist/config/knex/enhancements/20251028000000_simplify_agent_system.d.ts.map +1 -1
- package/dist/config/knex/enhancements/20251028000000_simplify_agent_system.js +9 -1
- package/dist/config/knex/enhancements/20251028000000_simplify_agent_system.js.map +1 -1
- package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.d.ts.map +1 -1
- package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.js +8 -1
- package/dist/config/knex/enhancements/20251105000000_add_token_usage_table.js.map +1 -1
- package/dist/config/knex/enhancements/20251108000000_add_planning_layers_v3_8_0.d.ts +21 -0
- package/dist/config/knex/enhancements/20251108000000_add_planning_layers_v3_8_0.d.ts.map +1 -0
- package/dist/config/knex/enhancements/20251108000000_add_planning_layers_v3_8_0.js +73 -0
- package/dist/config/knex/enhancements/20251108000000_add_planning_layers_v3_8_0.js.map +1 -0
- package/dist/config/knex/enhancements/20251109000000_fix_task_file_links_unique_constraint_v3_8_0.d.ts +19 -0
- package/dist/config/knex/enhancements/20251109000000_fix_task_file_links_unique_constraint_v3_8_0.d.ts.map +1 -0
- package/dist/config/knex/enhancements/20251109000000_fix_task_file_links_unique_constraint_v3_8_0.js +88 -0
- package/dist/config/knex/enhancements/20251109000000_fix_task_file_links_unique_constraint_v3_8_0.js.map +1 -0
- package/dist/config/knex/enhancements/20251109000003_token_usage_cross_db_compat_v3_7_5.d.ts +24 -0
- package/dist/config/knex/enhancements/20251109000003_token_usage_cross_db_compat_v3_7_5.d.ts.map +1 -0
- package/dist/config/knex/enhancements/20251109000003_token_usage_cross_db_compat_v3_7_5.js +79 -0
- package/dist/config/knex/enhancements/20251109000003_token_usage_cross_db_compat_v3_7_5.js.map +1 -0
- package/dist/config/knex/enhancements/20251109010000_tool_cleanup_v3_8_0.d.ts +27 -0
- package/dist/config/knex/enhancements/20251109010000_tool_cleanup_v3_8_0.d.ts.map +1 -0
- package/dist/config/knex/enhancements/20251109010000_tool_cleanup_v3_8_0.js +347 -0
- package/dist/config/knex/enhancements/20251109010000_tool_cleanup_v3_8_0.js.map +1 -0
- package/dist/config/knex/enhancements/20251109020000_fix_missing_help_actions_v3_8_0.d.ts +30 -0
- package/dist/config/knex/enhancements/20251109020000_fix_missing_help_actions_v3_8_0.d.ts.map +1 -0
- package/dist/config/knex/enhancements/20251109020000_fix_missing_help_actions_v3_8_0.js +232 -0
- package/dist/config/knex/enhancements/20251109020000_fix_missing_help_actions_v3_8_0.js.map +1 -0
- package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.d.ts.map +1 -1
- package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.js +9 -0
- package/dist/config/knex/upgrades/20251104000000_add_multi_project_v3_7_0.js.map +1 -1
- package/dist/config/knex/upgrades/20251108000000_hotfix_v_tagged_constraints_project_id.d.ts +14 -0
- package/dist/config/knex/upgrades/20251108000000_hotfix_v_tagged_constraints_project_id.d.ts.map +1 -0
- package/dist/config/knex/upgrades/20251108000000_hotfix_v_tagged_constraints_project_id.js +97 -0
- package/dist/config/knex/upgrades/20251108000000_hotfix_v_tagged_constraints_project_id.js.map +1 -0
- package/dist/config/knex/upgrades/20251109000002_multi_project_cross_db_compat_v3_7_5.d.ts +24 -0
- package/dist/config/knex/upgrades/20251109000002_multi_project_cross_db_compat_v3_7_5.d.ts.map +1 -0
- package/dist/config/knex/upgrades/20251109000002_multi_project_cross_db_compat_v3_7_5.js +303 -0
- package/dist/config/knex/upgrades/20251109000002_multi_project_cross_db_compat_v3_7_5.js.map +1 -0
- package/dist/constants.d.ts +14 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +28 -1
- package/dist/constants.js.map +1 -1
- package/dist/database/config/adapter-factory.d.ts +13 -0
- package/dist/database/config/adapter-factory.d.ts.map +1 -0
- package/dist/database/config/adapter-factory.js +21 -0
- package/dist/database/config/adapter-factory.js.map +1 -0
- package/dist/database/config/config-ops.d.ts +34 -0
- package/dist/database/config/config-ops.d.ts.map +1 -0
- package/dist/database/config/config-ops.js +76 -0
- package/dist/database/config/config-ops.js.map +1 -0
- package/dist/database/index.d.ts +21 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +31 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/initialization/cleanup.d.ts +8 -0
- package/dist/database/initialization/cleanup.d.ts.map +1 -0
- package/dist/database/initialization/cleanup.js +17 -0
- package/dist/database/initialization/cleanup.js.map +1 -0
- package/dist/database/initialization/init.d.ts +21 -0
- package/dist/database/initialization/init.d.ts.map +1 -0
- package/dist/database/initialization/init.js +83 -0
- package/dist/database/initialization/init.js.map +1 -0
- package/dist/database/operations/deletes.d.ts +10 -0
- package/dist/database/operations/deletes.d.ts.map +1 -0
- package/dist/database/operations/deletes.js +14 -0
- package/dist/database/operations/deletes.js.map +1 -0
- package/dist/database/operations/inserts.d.ts +40 -0
- package/dist/database/operations/inserts.d.ts.map +1 -0
- package/dist/database/operations/inserts.js +202 -0
- package/dist/database/operations/inserts.js.map +1 -0
- package/dist/database/operations/queries.d.ts +57 -0
- package/dist/database/operations/queries.d.ts.map +1 -0
- package/dist/database/operations/queries.js +77 -0
- package/dist/database/operations/queries.js.map +1 -0
- package/dist/database/operations/updates.d.ts +10 -0
- package/dist/database/operations/updates.d.ts.map +1 -0
- package/dist/database/operations/updates.js +14 -0
- package/dist/database/operations/updates.js.map +1 -0
- package/dist/database/types.d.ts +5 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +5 -0
- package/dist/database/types.js.map +1 -0
- package/dist/database.d.ts +4 -144
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +5 -461
- package/dist/database.js.map +1 -1
- package/dist/index.js +29 -777
- package/dist/index.js.map +1 -1
- package/dist/server/arg-parser.d.ts +40 -0
- package/dist/server/arg-parser.d.ts.map +1 -0
- package/dist/server/arg-parser.js +137 -0
- package/dist/server/arg-parser.js.map +1 -0
- package/dist/server/setup.d.ts +31 -0
- package/dist/server/setup.d.ts.map +1 -0
- package/dist/server/setup.js +186 -0
- package/dist/server/setup.js.map +1 -0
- package/dist/server/shutdown.d.ts +15 -0
- package/dist/server/shutdown.d.ts.map +1 -0
- package/dist/server/shutdown.js +42 -0
- package/dist/server/shutdown.js.map +1 -0
- package/dist/server/tool-handlers.d.ts +10 -0
- package/dist/server/tool-handlers.d.ts.map +1 -0
- package/dist/server/tool-handlers.js +478 -0
- package/dist/server/tool-handlers.js.map +1 -0
- package/dist/server/tool-registry.d.ts +11 -0
- package/dist/server/tool-registry.d.ts.map +1 -0
- package/dist/server/tool-registry.js +225 -0
- package/dist/server/tool-registry.js.map +1 -0
- package/dist/tests/all-features.test.js +6 -38
- package/dist/tests/all-features.test.js.map +1 -1
- package/dist/tests/batch-validation-comprehensive.test.d.ts +12 -0
- package/dist/tests/batch-validation-comprehensive.test.d.ts.map +1 -0
- package/dist/tests/batch-validation-comprehensive.test.js +472 -0
- package/dist/tests/batch-validation-comprehensive.test.js.map +1 -0
- package/dist/tests/batch-validation-integration.test.d.ts +6 -0
- package/dist/tests/batch-validation-integration.test.d.ts.map +1 -0
- package/dist/tests/batch-validation-integration.test.js +193 -0
- package/dist/tests/batch-validation-integration.test.js.map +1 -0
- package/dist/tests/batch-validation.test.d.ts +6 -0
- package/dist/tests/batch-validation.test.d.ts.map +1 -0
- package/dist/tests/batch-validation.test.js +298 -0
- package/dist/tests/batch-validation.test.js.map +1 -0
- package/dist/tests/context-modular.test.d.ts +7 -0
- package/dist/tests/context-modular.test.d.ts.map +1 -0
- package/dist/tests/context-modular.test.js +271 -0
- package/dist/tests/context-modular.test.js.map +1 -0
- package/dist/tests/decision-batch-validation.test.d.ts +6 -0
- package/dist/tests/decision-batch-validation.test.d.ts.map +1 -0
- package/dist/tests/decision-batch-validation.test.js +253 -0
- package/dist/tests/decision-batch-validation.test.js.map +1 -0
- package/dist/tests/help-system.test.js +1 -1
- package/dist/tests/help-system.test.js.map +1 -1
- package/dist/tests/migrations/test-all-versions-real.js +3 -2
- package/dist/tests/migrations/test-all-versions-real.js.map +1 -1
- package/dist/tests/multi-project.test.js +2 -2
- package/dist/tests/multi-project.test.js.map +1 -1
- package/dist/tests/parameter-validation.test.js +2 -16
- package/dist/tests/parameter-validation.test.js.map +1 -1
- package/dist/tests/tasks.auto-pruning-decision-link.test.js +1 -1
- package/dist/tests/tasks.auto-pruning-decision-link.test.js.map +1 -1
- package/dist/tests/tasks.file-actions-integration.test.d.ts +10 -0
- package/dist/tests/tasks.file-actions-integration.test.d.ts.map +1 -0
- package/dist/tests/tasks.file-actions-integration.test.js +162 -0
- package/dist/tests/tasks.file-actions-integration.test.js.map +1 -0
- package/dist/tests/tasks.file-actions-validation.test.d.ts +6 -0
- package/dist/tests/tasks.file-actions-validation.test.d.ts.map +1 -0
- package/dist/tests/tasks.file-actions-validation.test.js +221 -0
- package/dist/tests/tasks.file-actions-validation.test.js.map +1 -0
- package/dist/tools/constraints/actions/add.d.ts +15 -0
- package/dist/tools/constraints/actions/add.d.ts.map +1 -0
- package/dist/tools/constraints/actions/add.js +101 -0
- package/dist/tools/constraints/actions/add.js.map +1 -0
- package/dist/tools/constraints/actions/deactivate.d.ts +16 -0
- package/dist/tools/constraints/actions/deactivate.d.ts.map +1 -0
- package/dist/tools/constraints/actions/deactivate.js +49 -0
- package/dist/tools/constraints/actions/deactivate.js.map +1 -0
- package/dist/tools/constraints/actions/get.d.ts +16 -0
- package/dist/tools/constraints/actions/get.d.ts.map +1 -0
- package/dist/tools/constraints/actions/get.js +76 -0
- package/dist/tools/constraints/actions/get.js.map +1 -0
- package/dist/tools/constraints/help/example.d.ts +9 -0
- package/dist/tools/constraints/help/example.d.ts.map +1 -0
- package/dist/tools/constraints/help/example.js +144 -0
- package/dist/tools/constraints/help/example.js.map +1 -0
- package/dist/tools/constraints/help/help.d.ts +9 -0
- package/dist/tools/constraints/help/help.d.ts.map +1 -0
- package/dist/tools/constraints/help/help.js +31 -0
- package/dist/tools/constraints/help/help.js.map +1 -0
- package/dist/tools/constraints/index.d.ts +12 -0
- package/dist/tools/constraints/index.d.ts.map +1 -0
- package/dist/tools/constraints/index.js +13 -0
- package/dist/tools/constraints/index.js.map +1 -0
- package/dist/tools/constraints/internal/validation.d.ts +11 -0
- package/dist/tools/constraints/internal/validation.d.ts.map +1 -0
- package/dist/tools/constraints/internal/validation.js +17 -0
- package/dist/tools/constraints/internal/validation.js.map +1 -0
- package/dist/tools/constraints/types.d.ts +6 -0
- package/dist/tools/constraints/types.d.ts.map +1 -0
- package/dist/tools/constraints/types.js +6 -0
- package/dist/tools/constraints/types.js.map +1 -0
- package/dist/tools/context/actions/add-context.d.ts +14 -0
- package/dist/tools/context/actions/add-context.d.ts.map +1 -0
- package/dist/tools/context/actions/add-context.js +62 -0
- package/dist/tools/context/actions/add-context.js.map +1 -0
- package/dist/tools/context/actions/batch-set.d.ts +16 -0
- package/dist/tools/context/actions/batch-set.d.ts.map +1 -0
- package/dist/tools/context/actions/batch-set.js +126 -0
- package/dist/tools/context/actions/batch-set.js.map +1 -0
- package/dist/tools/context/actions/create-template.d.ts +15 -0
- package/dist/tools/context/actions/create-template.d.ts.map +1 -0
- package/dist/tools/context/actions/create-template.js +68 -0
- package/dist/tools/context/actions/create-template.js.map +1 -0
- package/dist/tools/context/actions/get.d.ts +18 -0
- package/dist/tools/context/actions/get.d.ts.map +1 -0
- package/dist/tools/context/actions/get.js +80 -0
- package/dist/tools/context/actions/get.js.map +1 -0
- package/dist/tools/context/actions/hard-delete.d.ts +18 -0
- package/dist/tools/context/actions/hard-delete.d.ts.map +1 -0
- package/dist/tools/context/actions/hard-delete.js +85 -0
- package/dist/tools/context/actions/hard-delete.js.map +1 -0
- package/dist/tools/context/actions/has-updates.d.ts +16 -0
- package/dist/tools/context/actions/has-updates.d.ts.map +1 -0
- package/dist/tools/context/actions/has-updates.js +83 -0
- package/dist/tools/context/actions/has-updates.js.map +1 -0
- package/dist/tools/context/actions/list-contexts.d.ts +14 -0
- package/dist/tools/context/actions/list-contexts.d.ts.map +1 -0
- package/dist/tools/context/actions/list-contexts.js +43 -0
- package/dist/tools/context/actions/list-contexts.js.map +1 -0
- package/dist/tools/context/actions/list-templates.d.ts +15 -0
- package/dist/tools/context/actions/list-templates.d.ts.map +1 -0
- package/dist/tools/context/actions/list-templates.js +47 -0
- package/dist/tools/context/actions/list-templates.js.map +1 -0
- package/dist/tools/context/actions/list.d.ts +16 -0
- package/dist/tools/context/actions/list.d.ts.map +1 -0
- package/dist/tools/context/actions/list.js +100 -0
- package/dist/tools/context/actions/list.js.map +1 -0
- package/dist/tools/context/actions/quick-set.d.ts +21 -0
- package/dist/tools/context/actions/quick-set.d.ts.map +1 -0
- package/dist/tools/context/actions/quick-set.js +104 -0
- package/dist/tools/context/actions/quick-set.js.map +1 -0
- package/dist/tools/context/actions/search-advanced.d.ts +15 -0
- package/dist/tools/context/actions/search-advanced.d.ts.map +1 -0
- package/dist/tools/context/actions/search-advanced.js +140 -0
- package/dist/tools/context/actions/search-advanced.js.map +1 -0
- package/dist/tools/context/actions/search-layer.d.ts +15 -0
- package/dist/tools/context/actions/search-layer.d.ts.map +1 -0
- package/dist/tools/context/actions/search-layer.js +106 -0
- package/dist/tools/context/actions/search-layer.js.map +1 -0
- package/dist/tools/context/actions/search-tags.d.ts +15 -0
- package/dist/tools/context/actions/search-tags.d.ts.map +1 -0
- package/dist/tools/context/actions/search-tags.js +85 -0
- package/dist/tools/context/actions/search-tags.js.map +1 -0
- package/dist/tools/context/actions/set-from-template.d.ts +16 -0
- package/dist/tools/context/actions/set-from-template.d.ts.map +1 -0
- package/dist/tools/context/actions/set-from-template.js +83 -0
- package/dist/tools/context/actions/set-from-template.js.map +1 -0
- package/dist/tools/context/actions/set.d.ts +16 -0
- package/dist/tools/context/actions/set.d.ts.map +1 -0
- package/dist/tools/context/actions/set.js +56 -0
- package/dist/tools/context/actions/set.js.map +1 -0
- package/dist/tools/context/actions/versions.d.ts +15 -0
- package/dist/tools/context/actions/versions.d.ts.map +1 -0
- package/dist/tools/context/actions/versions.js +69 -0
- package/dist/tools/context/actions/versions.js.map +1 -0
- package/dist/tools/context/help/example.d.ts +5 -0
- package/dist/tools/context/help/example.d.ts.map +1 -0
- package/dist/tools/context/help/example.js +96 -0
- package/dist/tools/context/help/example.js.map +1 -0
- package/dist/tools/context/help/help.d.ts +5 -0
- package/dist/tools/context/help/help.d.ts.map +1 -0
- package/dist/tools/context/help/help.js +65 -0
- package/dist/tools/context/help/help.js.map +1 -0
- package/dist/tools/context/index.d.ts +25 -0
- package/dist/tools/context/index.d.ts.map +1 -0
- package/dist/tools/context/index.js +26 -0
- package/dist/tools/context/index.js.map +1 -0
- package/dist/tools/context/internal/queries.d.ts +18 -0
- package/dist/tools/context/internal/queries.d.ts.map +1 -0
- package/dist/tools/context/internal/queries.js +160 -0
- package/dist/tools/context/internal/queries.js.map +1 -0
- package/dist/tools/context/internal/validation.d.ts +39 -0
- package/dist/tools/context/internal/validation.d.ts.map +1 -0
- package/dist/tools/context/internal/validation.js +125 -0
- package/dist/tools/context/internal/validation.js.map +1 -0
- package/dist/tools/context/types.d.ts +6 -0
- package/dist/tools/context/types.d.ts.map +1 -0
- package/dist/tools/context/types.js +6 -0
- package/dist/tools/context/types.js.map +1 -0
- package/dist/tools/example/actions/get.d.ts +14 -0
- package/dist/tools/example/actions/get.d.ts.map +1 -0
- package/dist/tools/example/actions/get.js +40 -0
- package/dist/tools/example/actions/get.js.map +1 -0
- package/dist/tools/example/actions/list-all.d.ts +13 -0
- package/dist/tools/example/actions/list-all.d.ts.map +1 -0
- package/dist/tools/example/actions/list-all.js +39 -0
- package/dist/tools/example/actions/list-all.js.map +1 -0
- package/dist/tools/example/actions/search.d.ts +14 -0
- package/dist/tools/example/actions/search.d.ts.map +1 -0
- package/dist/tools/example/actions/search.js +52 -0
- package/dist/tools/example/actions/search.js.map +1 -0
- package/dist/tools/example/help/example.d.ts +6 -0
- package/dist/tools/example/help/example.d.ts.map +1 -0
- package/dist/tools/example/help/example.js +69 -0
- package/dist/tools/example/help/example.js.map +1 -0
- package/dist/tools/example/help/help.d.ts +6 -0
- package/dist/tools/example/help/help.d.ts.map +1 -0
- package/dist/tools/example/help/help.js +133 -0
- package/dist/tools/example/help/help.js.map +1 -0
- package/dist/tools/example/index.d.ts +11 -0
- package/dist/tools/example/index.d.ts.map +1 -0
- package/dist/tools/example/index.js +12 -0
- package/dist/tools/example/index.js.map +1 -0
- package/dist/tools/example/types.d.ts +59 -0
- package/dist/tools/example/types.d.ts.map +1 -0
- package/dist/tools/example/types.js +6 -0
- package/dist/tools/example/types.js.map +1 -0
- package/dist/tools/files/actions/check-lock.d.ts +16 -0
- package/dist/tools/files/actions/check-lock.d.ts.map +1 -0
- package/dist/tools/files/actions/check-lock.js +70 -0
- package/dist/tools/files/actions/check-lock.js.map +1 -0
- package/dist/tools/files/actions/get.d.ts +16 -0
- package/dist/tools/files/actions/get.d.ts.map +1 -0
- package/dist/tools/files/actions/get.js +113 -0
- package/dist/tools/files/actions/get.js.map +1 -0
- package/dist/tools/files/actions/record-batch.d.ts +18 -0
- package/dist/tools/files/actions/record-batch.d.ts.map +1 -0
- package/dist/tools/files/actions/record-batch.js +114 -0
- package/dist/tools/files/actions/record-batch.js.map +1 -0
- package/dist/tools/files/actions/record.d.ts +16 -0
- package/dist/tools/files/actions/record.d.ts.map +1 -0
- package/dist/tools/files/actions/record.js +37 -0
- package/dist/tools/files/actions/record.js.map +1 -0
- package/dist/tools/files/actions/sqlite-flush.d.ts +27 -0
- package/dist/tools/files/actions/sqlite-flush.d.ts.map +1 -0
- package/dist/tools/files/actions/sqlite-flush.js +66 -0
- package/dist/tools/files/actions/sqlite-flush.js.map +1 -0
- package/dist/tools/files/help/example.d.ts +5 -0
- package/dist/tools/files/help/example.d.ts.map +1 -0
- package/dist/tools/files/help/example.js +98 -0
- package/dist/tools/files/help/example.js.map +1 -0
- package/dist/tools/files/help/help.d.ts +5 -0
- package/dist/tools/files/help/help.d.ts.map +1 -0
- package/dist/tools/files/help/help.js +29 -0
- package/dist/tools/files/help/help.js.map +1 -0
- package/dist/tools/files/index.d.ts +14 -0
- package/dist/tools/files/index.d.ts.map +1 -0
- package/dist/tools/files/index.js +15 -0
- package/dist/tools/files/index.js.map +1 -0
- package/dist/tools/files/internal/queries.d.ts +18 -0
- package/dist/tools/files/internal/queries.d.ts.map +1 -0
- package/dist/tools/files/internal/queries.js +63 -0
- package/dist/tools/files/internal/queries.js.map +1 -0
- package/dist/tools/files/internal/validation.d.ts +18 -0
- package/dist/tools/files/internal/validation.d.ts.map +1 -0
- package/dist/tools/files/internal/validation.js +40 -0
- package/dist/tools/files/internal/validation.js.map +1 -0
- package/dist/tools/files/types.d.ts +6 -0
- package/dist/tools/files/types.d.ts.map +1 -0
- package/dist/tools/files/types.js +6 -0
- package/dist/tools/files/types.js.map +1 -0
- package/dist/tools/help/actions/batch-guide.d.ts +14 -0
- package/dist/tools/help/actions/batch-guide.d.ts.map +1 -0
- package/dist/tools/help/actions/batch-guide.js +59 -0
- package/dist/tools/help/actions/batch-guide.js.map +1 -0
- package/dist/tools/help/actions/error-recovery.d.ts +12 -0
- package/dist/tools/help/actions/error-recovery.d.ts.map +1 -0
- package/dist/tools/help/actions/error-recovery.js +107 -0
- package/dist/tools/help/actions/error-recovery.js.map +1 -0
- package/dist/tools/help/actions/query-action.d.ts +15 -0
- package/dist/tools/help/actions/query-action.d.ts.map +1 -0
- package/dist/tools/help/actions/query-action.js +15 -0
- package/dist/tools/help/actions/query-action.js.map +1 -0
- package/dist/tools/help/actions/query-params.d.ts +15 -0
- package/dist/tools/help/actions/query-params.d.ts.map +1 -0
- package/dist/tools/help/actions/query-params.js +15 -0
- package/dist/tools/help/actions/query-params.js.map +1 -0
- package/dist/tools/help/actions/query-tool.d.ts +15 -0
- package/dist/tools/help/actions/query-tool.d.ts.map +1 -0
- package/dist/tools/help/actions/query-tool.js +15 -0
- package/dist/tools/help/actions/query-tool.js.map +1 -0
- package/dist/tools/help/actions/workflow-hints.d.ts +14 -0
- package/dist/tools/help/actions/workflow-hints.d.ts.map +1 -0
- package/dist/tools/help/actions/workflow-hints.js +15 -0
- package/dist/tools/help/actions/workflow-hints.js.map +1 -0
- package/dist/tools/help/help/example.d.ts +6 -0
- package/dist/tools/help/help/example.d.ts.map +1 -0
- package/dist/tools/help/help/example.js +70 -0
- package/dist/tools/help/help/example.js.map +1 -0
- package/dist/tools/help/help/help.d.ts +6 -0
- package/dist/tools/help/help/help.d.ts.map +1 -0
- package/dist/tools/help/help/help.js +67 -0
- package/dist/tools/help/help/help.js.map +1 -0
- package/dist/tools/help/index.d.ts +14 -0
- package/dist/tools/help/index.d.ts.map +1 -0
- package/dist/tools/help/index.js +15 -0
- package/dist/tools/help/index.js.map +1 -0
- package/dist/tools/help/types.d.ts +92 -0
- package/dist/tools/help/types.d.ts.map +1 -0
- package/dist/tools/help/types.js +6 -0
- package/dist/tools/help/types.js.map +1 -0
- package/dist/tools/help-queries.d.ts.map +1 -1
- package/dist/tools/help-queries.js +1 -0
- package/dist/tools/help-queries.js.map +1 -1
- package/dist/tools/tasks/actions/add-dependency.d.ts +12 -0
- package/dist/tools/tasks/actions/add-dependency.d.ts.map +1 -0
- package/dist/tools/tasks/actions/add-dependency.js +124 -0
- package/dist/tools/tasks/actions/add-dependency.js.map +1 -0
- package/dist/tools/tasks/actions/archive.d.ts +11 -0
- package/dist/tools/tasks/actions/archive.d.ts.map +1 -0
- package/dist/tools/tasks/actions/archive.js +67 -0
- package/dist/tools/tasks/actions/archive.js.map +1 -0
- package/dist/tools/tasks/actions/create-batch.d.ts +19 -0
- package/dist/tools/tasks/actions/create-batch.d.ts.map +1 -0
- package/dist/tools/tasks/actions/create-batch.js +103 -0
- package/dist/tools/tasks/actions/create-batch.js.map +1 -0
- package/dist/tools/tasks/actions/create.d.ts +16 -0
- package/dist/tools/tasks/actions/create.d.ts.map +1 -0
- package/dist/tools/tasks/actions/create.js +180 -0
- package/dist/tools/tasks/actions/create.js.map +1 -0
- package/dist/tools/tasks/actions/get-dependencies.d.ts +12 -0
- package/dist/tools/tasks/actions/get-dependencies.d.ts.map +1 -0
- package/dist/tools/tasks/actions/get-dependencies.js +41 -0
- package/dist/tools/tasks/actions/get-dependencies.js.map +1 -0
- package/dist/tools/tasks/actions/get-pruned-files.d.ts +13 -0
- package/dist/tools/tasks/actions/get-pruned-files.d.ts.map +1 -0
- package/dist/tools/tasks/actions/get-pruned-files.js +45 -0
- package/dist/tools/tasks/actions/get-pruned-files.js.map +1 -0
- package/dist/tools/tasks/actions/get.d.ts +12 -0
- package/dist/tools/tasks/actions/get.d.ts.map +1 -0
- package/dist/tools/tasks/actions/get.js +88 -0
- package/dist/tools/tasks/actions/get.js.map +1 -0
- package/dist/tools/tasks/actions/link-pruned-file.d.ts +13 -0
- package/dist/tools/tasks/actions/link-pruned-file.d.ts.map +1 -0
- package/dist/tools/tasks/actions/link-pruned-file.js +63 -0
- package/dist/tools/tasks/actions/link-pruned-file.js.map +1 -0
- package/dist/tools/tasks/actions/link.d.ts +14 -0
- package/dist/tools/tasks/actions/link.d.ts.map +1 -0
- package/dist/tools/tasks/actions/link.js +118 -0
- package/dist/tools/tasks/actions/link.js.map +1 -0
- package/dist/tools/tasks/actions/list.d.ts +17 -0
- package/dist/tools/tasks/actions/list.d.ts.map +1 -0
- package/dist/tools/tasks/actions/list.js +98 -0
- package/dist/tools/tasks/actions/list.js.map +1 -0
- package/dist/tools/tasks/actions/move.d.ts +12 -0
- package/dist/tools/tasks/actions/move.d.ts.map +1 -0
- package/dist/tools/tasks/actions/move.js +91 -0
- package/dist/tools/tasks/actions/move.js.map +1 -0
- package/dist/tools/tasks/actions/remove-dependency.d.ts +12 -0
- package/dist/tools/tasks/actions/remove-dependency.d.ts.map +1 -0
- package/dist/tools/tasks/actions/remove-dependency.js +36 -0
- package/dist/tools/tasks/actions/remove-dependency.js.map +1 -0
- package/dist/tools/tasks/actions/update.d.ts +10 -0
- package/dist/tools/tasks/actions/update.d.ts.map +1 -0
- package/dist/tools/tasks/actions/update.js +186 -0
- package/dist/tools/tasks/actions/update.js.map +1 -0
- package/dist/tools/tasks/actions/watch-files.d.ts +14 -0
- package/dist/tools/tasks/actions/watch-files.d.ts.map +1 -0
- package/dist/tools/tasks/actions/watch-files.js +127 -0
- package/dist/tools/tasks/actions/watch-files.js.map +1 -0
- package/dist/tools/tasks/help/example.d.ts +8 -0
- package/dist/tools/tasks/help/example.d.ts.map +1 -0
- package/dist/tools/tasks/help/example.js +215 -0
- package/dist/tools/tasks/help/example.js.map +1 -0
- package/dist/tools/tasks/help/help.d.ts +8 -0
- package/dist/tools/tasks/help/help.d.ts.map +1 -0
- package/dist/tools/tasks/help/help.js +293 -0
- package/dist/tools/tasks/help/help.js.map +1 -0
- package/dist/tools/tasks/help/use-case.d.ts +11 -0
- package/dist/tools/tasks/help/use-case.d.ts.map +1 -0
- package/dist/tools/tasks/help/use-case.js +768 -0
- package/dist/tools/tasks/help/use-case.js.map +1 -0
- package/dist/tools/tasks/index.d.ts +28 -0
- package/dist/tools/tasks/index.d.ts.map +1 -0
- package/dist/tools/tasks/index.js +33 -0
- package/dist/tools/tasks/index.js.map +1 -0
- package/dist/tools/tasks/internal/state-machine.d.ts +16 -0
- package/dist/tools/tasks/internal/state-machine.d.ts.map +1 -0
- package/dist/tools/tasks/internal/state-machine.js +36 -0
- package/dist/tools/tasks/internal/state-machine.js.map +1 -0
- package/dist/tools/tasks/internal/task-queries.d.ts +12 -0
- package/dist/tools/tasks/internal/task-queries.d.ts.map +1 -0
- package/dist/tools/tasks/internal/task-queries.js +61 -0
- package/dist/tools/tasks/internal/task-queries.js.map +1 -0
- package/dist/tools/tasks/internal/validation.d.ts +47 -0
- package/dist/tools/tasks/internal/validation.d.ts.map +1 -0
- package/dist/tools/tasks/internal/validation.js +261 -0
- package/dist/tools/tasks/internal/validation.js.map +1 -0
- package/dist/tools/tasks/types.d.ts +68 -0
- package/dist/tools/tasks/types.d.ts.map +1 -0
- package/dist/tools/tasks/types.js +45 -0
- package/dist/tools/tasks/types.js.map +1 -0
- package/dist/tools/tasks/watcher/status.d.ts +9 -0
- package/dist/tools/tasks/watcher/status.d.ts.map +1 -0
- package/dist/tools/tasks/watcher/status.js +126 -0
- package/dist/tools/tasks/watcher/status.js.map +1 -0
- package/dist/tools/tasks.d.ts +12 -148
- package/dist/tools/tasks.d.ts.map +1 -1
- package/dist/tools/tasks.js +12 -2037
- package/dist/tools/tasks.js.map +1 -1
- package/dist/tools/use_case/actions/get.d.ts +14 -0
- package/dist/tools/use_case/actions/get.d.ts.map +1 -0
- package/dist/tools/use_case/actions/get.js +15 -0
- package/dist/tools/use_case/actions/get.js.map +1 -0
- package/dist/tools/use_case/actions/list-all.d.ts +15 -0
- package/dist/tools/use_case/actions/list-all.d.ts.map +1 -0
- package/dist/tools/use_case/actions/list-all.js +20 -0
- package/dist/tools/use_case/actions/list-all.js.map +1 -0
- package/dist/tools/use_case/actions/search.d.ts +14 -0
- package/dist/tools/use_case/actions/search.d.ts.map +1 -0
- package/dist/tools/use_case/actions/search.js +87 -0
- package/dist/tools/use_case/actions/search.js.map +1 -0
- package/dist/tools/use_case/help/example.d.ts +105 -0
- package/dist/tools/use_case/help/example.d.ts.map +1 -0
- package/dist/tools/use_case/help/example.js +138 -0
- package/dist/tools/use_case/help/example.js.map +1 -0
- package/dist/tools/use_case/help/help.d.ts +33 -0
- package/dist/tools/use_case/help/help.d.ts.map +1 -0
- package/dist/tools/use_case/help/help.js +109 -0
- package/dist/tools/use_case/help/help.js.map +1 -0
- package/dist/tools/use_case/index.d.ts +11 -0
- package/dist/tools/use_case/index.d.ts.map +1 -0
- package/dist/tools/use_case/index.js +12 -0
- package/dist/tools/use_case/index.js.map +1 -0
- package/dist/tools/use_case/types.d.ts +58 -0
- package/dist/tools/use_case/types.d.ts.map +1 -0
- package/dist/tools/use_case/types.js +6 -0
- package/dist/tools/use_case/types.js.map +1 -0
- package/dist/types/actions.d.ts +37 -0
- package/dist/types/actions.d.ts.map +1 -0
- package/dist/types/actions.js +6 -0
- package/dist/types/actions.js.map +1 -0
- package/dist/types/constraint/params.d.ts +2 -0
- package/dist/types/constraint/params.d.ts.map +1 -0
- package/dist/types/constraint/params.js +2 -0
- package/dist/types/constraint/params.js.map +1 -0
- package/dist/types/constraint/responses.d.ts +2 -0
- package/dist/types/constraint/responses.d.ts.map +1 -0
- package/dist/types/constraint/responses.js +2 -0
- package/dist/types/constraint/responses.js.map +1 -0
- package/dist/types/decision/batch.d.ts +24 -0
- package/dist/types/decision/batch.d.ts.map +1 -0
- package/dist/types/decision/batch.js +5 -0
- package/dist/types/decision/batch.js.map +1 -0
- package/dist/types/decision/params.d.ts +73 -0
- package/dist/types/decision/params.d.ts.map +1 -0
- package/dist/types/decision/params.js +5 -0
- package/dist/types/decision/params.js.map +1 -0
- package/dist/types/decision/responses.d.ts +79 -0
- package/dist/types/decision/responses.d.ts.map +1 -0
- package/dist/types/decision/responses.js +5 -0
- package/dist/types/decision/responses.js.map +1 -0
- package/dist/types/decision/templates.d.ts +74 -0
- package/dist/types/decision/templates.d.ts.map +1 -0
- package/dist/types/decision/templates.js +5 -0
- package/dist/types/decision/templates.js.map +1 -0
- package/dist/types/enums.d.ts +43 -0
- package/dist/types/enums.d.ts.map +1 -0
- package/dist/types/enums.js +47 -0
- package/dist/types/enums.js.map +1 -0
- package/dist/types/file/params.d.ts +40 -0
- package/dist/types/file/params.d.ts.map +1 -0
- package/dist/types/file/params.js +6 -0
- package/dist/types/file/params.js.map +1 -0
- package/dist/types/file/responses.d.ts +2 -0
- package/dist/types/file/responses.d.ts.map +1 -0
- package/dist/types/file/responses.js +2 -0
- package/dist/types/file/responses.js.map +1 -0
- package/dist/types/import-export.d.ts +126 -0
- package/dist/types/import-export.d.ts.map +1 -0
- package/dist/types/import-export.js +6 -0
- package/dist/types/import-export.js.map +1 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +35 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/master-entities.d.ts +33 -0
- package/dist/types/master-entities.d.ts.map +1 -0
- package/dist/types/master-entities.js +6 -0
- package/dist/types/master-entities.js.map +1 -0
- package/dist/types/task/params.d.ts +172 -0
- package/dist/types/task/params.d.ts.map +1 -0
- package/dist/types/task/params.js +8 -0
- package/dist/types/task/params.js.map +1 -0
- package/dist/types/task/responses.d.ts +334 -0
- package/dist/types/task/responses.d.ts.map +1 -0
- package/dist/types/task/responses.js +8 -0
- package/dist/types/task/responses.js.map +1 -0
- package/dist/types/transaction-entities.d.ts +89 -0
- package/dist/types/transaction-entities.d.ts.map +1 -0
- package/dist/types/transaction-entities.js +5 -0
- package/dist/types/transaction-entities.js.map +1 -0
- package/dist/types/validation.d.ts +44 -0
- package/dist/types/validation.d.ts.map +1 -0
- package/dist/types/validation.js +6 -0
- package/dist/types/validation.js.map +1 -0
- package/dist/types/view-entities.d.ts +61 -0
- package/dist/types/view-entities.d.ts.map +1 -0
- package/dist/types/view-entities.js +5 -0
- package/dist/types/view-entities.js.map +1 -0
- package/dist/types.d.ts +133 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/action-specs/config-specs.d.ts +10 -0
- package/dist/utils/action-specs/config-specs.d.ts.map +1 -0
- package/dist/utils/action-specs/config-specs.js +12 -0
- package/dist/utils/action-specs/config-specs.js.map +1 -0
- package/dist/utils/action-specs/constraint-specs.d.ts +9 -0
- package/dist/utils/action-specs/constraint-specs.d.ts.map +1 -0
- package/dist/utils/action-specs/constraint-specs.js +42 -0
- package/dist/utils/action-specs/constraint-specs.js.map +1 -0
- package/dist/utils/action-specs/decision-specs.d.ts +9 -0
- package/dist/utils/action-specs/decision-specs.d.ts.map +1 -0
- package/dist/utils/action-specs/decision-specs.js +194 -0
- package/dist/utils/action-specs/decision-specs.js.map +1 -0
- package/dist/utils/action-specs/file-specs.d.ts +9 -0
- package/dist/utils/action-specs/file-specs.d.ts.map +1 -0
- package/dist/utils/action-specs/file-specs.js +56 -0
- package/dist/utils/action-specs/file-specs.js.map +1 -0
- package/dist/utils/action-specs/index.d.ts +38 -0
- package/dist/utils/action-specs/index.d.ts.map +1 -0
- package/dist/utils/action-specs/index.js +63 -0
- package/dist/utils/action-specs/index.js.map +1 -0
- package/dist/utils/action-specs/task-specs.d.ts +9 -0
- package/dist/utils/action-specs/task-specs.d.ts.map +1 -0
- package/dist/utils/action-specs/task-specs.js +143 -0
- package/dist/utils/action-specs/task-specs.js.map +1 -0
- package/dist/utils/action-specs/types.d.ts +14 -0
- package/dist/utils/action-specs/types.d.ts.map +1 -0
- package/dist/utils/action-specs/types.js +9 -0
- package/dist/utils/action-specs/types.js.map +1 -0
- package/dist/utils/batch-validation.d.ts +156 -0
- package/dist/utils/batch-validation.d.ts.map +1 -0
- package/dist/utils/batch-validation.example.d.ts +48 -0
- package/dist/utils/batch-validation.example.d.ts.map +1 -0
- package/dist/utils/batch-validation.example.js +180 -0
- package/dist/utils/batch-validation.example.js.map +1 -0
- package/dist/utils/batch-validation.js +345 -0
- package/dist/utils/batch-validation.js.map +1 -0
- package/dist/utils/exporter/export.d.ts +100 -0
- package/dist/utils/exporter/export.d.ts.map +1 -0
- package/dist/utils/exporter/export.js +363 -0
- package/dist/utils/exporter/export.js.map +1 -0
- package/dist/utils/importer/import.d.ts +29 -0
- package/dist/utils/importer/import.d.ts.map +1 -0
- package/dist/utils/importer/import.js +514 -0
- package/dist/utils/importer/import.js.map +1 -0
- package/dist/utils/importer/master-tables.d.ts +18 -0
- package/dist/utils/importer/master-tables.d.ts.map +1 -0
- package/dist/utils/importer/master-tables.js +255 -0
- package/dist/utils/importer/master-tables.js.map +1 -0
- package/dist/utils/importer/topological-sort.d.ts +61 -0
- package/dist/utils/importer/topological-sort.d.ts.map +1 -0
- package/dist/utils/importer/topological-sort.js +143 -0
- package/dist/utils/importer/topological-sort.js.map +1 -0
- package/dist/utils/levenshtein.d.ts +18 -0
- package/dist/utils/levenshtein.d.ts.map +1 -0
- package/dist/utils/levenshtein.js +46 -0
- package/dist/utils/levenshtein.js.map +1 -0
- package/dist/utils/parameter-validator.d.ts +3 -3
- package/dist/utils/parameter-validator.d.ts.map +1 -1
- package/dist/utils/parameter-validator.js +3 -39
- package/dist/utils/parameter-validator.js.map +1 -1
- package/dist/utils/sql-dump/core/dependency-sort.d.ts +16 -0
- package/dist/utils/sql-dump/core/dependency-sort.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/dependency-sort.js +105 -0
- package/dist/utils/sql-dump/core/dependency-sort.js.map +1 -0
- package/dist/utils/sql-dump/core/generate-dump.d.ts +13 -0
- package/dist/utils/sql-dump/core/generate-dump.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/generate-dump.js +181 -0
- package/dist/utils/sql-dump/core/generate-dump.js.map +1 -0
- package/dist/utils/sql-dump/core/index-export.d.ts +9 -0
- package/dist/utils/sql-dump/core/index-export.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/index-export.js +173 -0
- package/dist/utils/sql-dump/core/index-export.js.map +1 -0
- package/dist/utils/sql-dump/core/sequence-reset.d.ts +6 -0
- package/dist/utils/sql-dump/core/sequence-reset.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/sequence-reset.js +28 -0
- package/dist/utils/sql-dump/core/sequence-reset.js.map +1 -0
- package/dist/utils/sql-dump/core/table-export.d.ts +2 -0
- package/dist/utils/sql-dump/core/table-export.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/table-export.js +4 -0
- package/dist/utils/sql-dump/core/table-export.js.map +1 -0
- package/dist/utils/sql-dump/core/view-export.d.ts +2 -0
- package/dist/utils/sql-dump/core/view-export.d.ts.map +1 -0
- package/dist/utils/sql-dump/core/view-export.js +4 -0
- package/dist/utils/sql-dump/core/view-export.js.map +1 -0
- package/dist/utils/sql-dump/formatters/bulk-insert.d.ts +14 -0
- package/dist/utils/sql-dump/formatters/bulk-insert.d.ts.map +1 -0
- package/dist/utils/sql-dump/formatters/bulk-insert.js +177 -0
- package/dist/utils/sql-dump/formatters/bulk-insert.js.map +1 -0
- package/dist/utils/sql-dump/formatters/identifiers.d.ts +6 -0
- package/dist/utils/sql-dump/formatters/identifiers.d.ts.map +1 -0
- package/dist/utils/sql-dump/formatters/identifiers.js +16 -0
- package/dist/utils/sql-dump/formatters/identifiers.js.map +1 -0
- package/dist/utils/sql-dump/formatters/value-formatter.d.ts +14 -0
- package/dist/utils/sql-dump/formatters/value-formatter.d.ts.map +1 -0
- package/dist/utils/sql-dump/formatters/value-formatter.js +281 -0
- package/dist/utils/sql-dump/formatters/value-formatter.js.map +1 -0
- package/dist/utils/sql-dump/generators/controls.d.ts +10 -0
- package/dist/utils/sql-dump/generators/controls.d.ts.map +1 -0
- package/dist/utils/sql-dump/generators/controls.js +36 -0
- package/dist/utils/sql-dump/generators/controls.js.map +1 -0
- package/dist/utils/sql-dump/generators/headers.d.ts +6 -0
- package/dist/utils/sql-dump/generators/headers.d.ts.map +1 -0
- package/dist/utils/sql-dump/generators/headers.js +19 -0
- package/dist/utils/sql-dump/generators/headers.js.map +1 -0
- package/dist/utils/sql-dump/index.d.ts +14 -0
- package/dist/utils/sql-dump/index.d.ts.map +1 -0
- package/dist/utils/sql-dump/index.js +16 -0
- package/dist/utils/sql-dump/index.js.map +1 -0
- package/dist/utils/sql-dump/schema/indexes.d.ts +6 -0
- package/dist/utils/sql-dump/schema/indexes.d.ts.map +1 -0
- package/dist/utils/sql-dump/schema/indexes.js +42 -0
- package/dist/utils/sql-dump/schema/indexes.js.map +1 -0
- package/dist/utils/sql-dump/schema/primary-keys.d.ts +6 -0
- package/dist/utils/sql-dump/schema/primary-keys.d.ts.map +1 -0
- package/dist/utils/sql-dump/schema/primary-keys.js +41 -0
- package/dist/utils/sql-dump/schema/primary-keys.js.map +1 -0
- package/dist/utils/sql-dump/schema/tables.d.ts +12 -0
- package/dist/utils/sql-dump/schema/tables.d.ts.map +1 -0
- package/dist/utils/sql-dump/schema/tables.js +370 -0
- package/dist/utils/sql-dump/schema/tables.js.map +1 -0
- package/dist/utils/sql-dump/schema/views.d.ts +11 -0
- package/dist/utils/sql-dump/schema/views.d.ts.map +1 -0
- package/dist/utils/sql-dump/schema/views.js +110 -0
- package/dist/utils/sql-dump/schema/views.js.map +1 -0
- package/dist/utils/sql-dump/types.d.ts +10 -0
- package/dist/utils/sql-dump/types.d.ts.map +1 -0
- package/dist/utils/sql-dump/types.js +3 -0
- package/dist/utils/sql-dump/types.js.map +1 -0
- package/docs/AI_AGENT_GUIDE.md +2 -2
- package/docs/AUTO_FILE_TRACKING.md +0 -1
- package/docs/BATCH_VALIDATION.md +617 -0
- package/docs/DATABASE_AUTH.md +1 -2
- package/docs/DECISION_TO_TASK_MIGRATION_GUIDE.md +2 -2
- package/docs/SHARED_CONCEPTS.md +2 -2
- package/docs/SPECIALIZED_AGENTS.md +1 -1
- package/docs/TASK_ACTIONS.md +7 -7
- package/docs/TASK_MIGRATION.md +5 -5
- package/docs/TASK_SYSTEM.md +5 -5
- package/docs/TOOL_REFERENCE.md +1 -3
- package/docs/WORKFLOWS.md +1 -1
- package/docs/{DATABASE_MIGRATION.md → cli/DATABASE_MIGRATION.md} +71 -32
- package/docs/cli/DATA_EXPORT_IMPORT.md +400 -0
- package/docs/cli/README.md +227 -0
- package/package.json +7 -4
- package/dist/tools/config.d.ts +0 -58
- package/dist/tools/config.d.ts.map +0 -1
- package/dist/tools/config.js +0 -281
- package/dist/tools/config.js.map +0 -1
- package/dist/tools/constraints.d.ts +0 -49
- package/dist/tools/constraints.d.ts.map +0 -1
- package/dist/tools/constraints.js +0 -378
- package/dist/tools/constraints.js.map +0 -1
- package/dist/tools/context.d.ts +0 -208
- package/dist/tools/context.d.ts.map +0 -1
- package/dist/tools/context.js +0 -1661
- package/dist/tools/context.js.map +0 -1
- package/dist/tools/files.d.ts +0 -54
- package/dist/tools/files.d.ts.map +0 -1
- package/dist/tools/files.js +0 -478
- package/dist/tools/files.js.map +0 -1
- package/dist/tools/messaging.d.ts +0 -71
- package/dist/tools/messaging.d.ts.map +0 -1
- package/dist/tools/messaging.js +0 -483
- package/dist/tools/messaging.js.map +0 -1
- package/dist/tools/utils.d.ts +0 -70
- package/dist/tools/utils.d.ts.map +0 -1
- package/dist/tools/utils.js +0 -483
- package/dist/tools/utils.js.map +0 -1
- package/dist/utils/action-specs.d.ts +0 -46
- package/dist/utils/action-specs.d.ts.map +0 -1
- package/dist/utils/action-specs.js +0 -527
- package/dist/utils/action-specs.js.map +0 -1
- package/docs/BASEADAPTER_IMPLEMENTATION.md +0 -399
- package/docs/HELP_PREVIEW_COMPARISON.md +0 -259
- package/docs/MIGRATION_CHAIN.md +0 -293
- package/docs/MIGRATION_v2.md +0 -538
- package/docs/MIGRATION_v3.3.md +0 -602
- package/docs/MIGRATION_v3.6.0.md +0 -170
- package/docs/MULTI_PROJECT_ARCHITECTURE.md +0 -497
package/dist/tools/context.js
DELETED
|
@@ -1,1661 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Context management tools for MCP Shared Context Server
|
|
3
|
-
* Implements set_decision, get_context, and get_decision tools
|
|
4
|
-
*
|
|
5
|
-
* CONVERTED: Using Knex.js with DatabaseAdapter (async/await)
|
|
6
|
-
*/
|
|
7
|
-
import { getAdapter, getOrCreateAgent, getOrCreateContextKey, getOrCreateTag, getOrCreateScope, getLayerId, addDecisionContext as dbAddDecisionContext, getDecisionWithContext as dbGetDecisionWithContext, listDecisionContexts as dbListDecisionContexts } from '../database.js';
|
|
8
|
-
import { getProjectContext } from '../utils/project-context.js';
|
|
9
|
-
import { STRING_TO_STATUS, DEFAULT_VERSION, DEFAULT_STATUS } from '../constants.js';
|
|
10
|
-
import { validateRequired, validateStatus } from '../utils/validators.js';
|
|
11
|
-
import { logDecisionSet, logDecisionUpdate, recordDecisionHistory } from '../utils/activity-logging.js';
|
|
12
|
-
import { parseStringArray } from '../utils/param-parser.js';
|
|
13
|
-
import { validateActionParams, validateBatchParams } from '../utils/parameter-validator.js';
|
|
14
|
-
import connectionManager from '../utils/connection-manager.js';
|
|
15
|
-
import { debugLog, debugLogFunctionEntry, debugLogFunctionExit, debugLogTransaction, debugLogCriticalError } from '../utils/debug-logger.js';
|
|
16
|
-
/**
|
|
17
|
-
* Internal helper: Set decision without wrapping in transaction
|
|
18
|
-
* Used by setDecision (with transaction) and setDecisionBatch (manages its own transaction)
|
|
19
|
-
*
|
|
20
|
-
* @param params - Decision parameters
|
|
21
|
-
* @param adapter - Database adapter instance
|
|
22
|
-
* @param trx - Optional transaction
|
|
23
|
-
* @returns Response with success status and metadata
|
|
24
|
-
*/
|
|
25
|
-
async function setDecisionInternal(params, adapter, trx) {
|
|
26
|
-
const knex = trx || adapter.getKnex();
|
|
27
|
-
// Validate project context (Constraint #29 - fail-fast before mutations)
|
|
28
|
-
const projectId = getProjectContext().getProjectId();
|
|
29
|
-
// Validate required parameters
|
|
30
|
-
const trimmedKey = validateRequired(params.key, 'key');
|
|
31
|
-
if (params.value === undefined || params.value === null) {
|
|
32
|
-
throw new Error('Parameter "value" is required');
|
|
33
|
-
}
|
|
34
|
-
// Determine if value is numeric
|
|
35
|
-
const isNumeric = typeof params.value === 'number';
|
|
36
|
-
const value = params.value;
|
|
37
|
-
// Set defaults
|
|
38
|
-
const version = params.version || DEFAULT_VERSION;
|
|
39
|
-
const status = params.status ? STRING_TO_STATUS[params.status] : DEFAULT_STATUS;
|
|
40
|
-
const agentName = params.agent || 'system';
|
|
41
|
-
// Validate status
|
|
42
|
-
if (params.status) {
|
|
43
|
-
validateStatus(params.status);
|
|
44
|
-
}
|
|
45
|
-
// Validate layer if provided
|
|
46
|
-
let layerId = null;
|
|
47
|
-
if (params.layer) {
|
|
48
|
-
const validLayers = ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'];
|
|
49
|
-
if (!validLayers.includes(params.layer)) {
|
|
50
|
-
throw new Error(`Invalid layer. Must be one of: ${validLayers.join(', ')}`);
|
|
51
|
-
}
|
|
52
|
-
layerId = await getLayerId(adapter, params.layer, trx);
|
|
53
|
-
if (layerId === null) {
|
|
54
|
-
throw new Error(`Layer not found in database: ${params.layer}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Get or create master records
|
|
58
|
-
const agentId = await getOrCreateAgent(adapter, agentName, trx);
|
|
59
|
-
const keyId = await getOrCreateContextKey(adapter, params.key, trx);
|
|
60
|
-
// Current timestamp
|
|
61
|
-
const ts = Math.floor(Date.now() / 1000);
|
|
62
|
-
// Check if decision already exists for activity logging
|
|
63
|
-
const existingDecision = await knex(isNumeric ? 't_decisions_numeric' : 't_decisions')
|
|
64
|
-
.where({ key_id: keyId, project_id: projectId })
|
|
65
|
-
.first();
|
|
66
|
-
// Insert or update decision based on value type
|
|
67
|
-
const tableName = isNumeric ? 't_decisions_numeric' : 't_decisions';
|
|
68
|
-
const decisionData = {
|
|
69
|
-
key_id: keyId,
|
|
70
|
-
project_id: projectId,
|
|
71
|
-
value: isNumeric ? value : String(value),
|
|
72
|
-
agent_id: agentId,
|
|
73
|
-
layer_id: layerId,
|
|
74
|
-
version: version,
|
|
75
|
-
status: status,
|
|
76
|
-
ts: ts
|
|
77
|
-
};
|
|
78
|
-
// Use transaction-aware upsert instead of adapter.upsert to avoid connection pool timeout
|
|
79
|
-
const conflictColumns = ['key_id', 'project_id'];
|
|
80
|
-
const updateColumns = Object.keys(decisionData).filter(key => !conflictColumns.includes(key));
|
|
81
|
-
const updateData = updateColumns.reduce((acc, col) => {
|
|
82
|
-
acc[col] = decisionData[col];
|
|
83
|
-
return acc;
|
|
84
|
-
}, {});
|
|
85
|
-
await knex(tableName)
|
|
86
|
-
.insert(decisionData)
|
|
87
|
-
.onConflict(conflictColumns)
|
|
88
|
-
.merge(updateData);
|
|
89
|
-
// Activity logging (replaces triggers)
|
|
90
|
-
if (existingDecision) {
|
|
91
|
-
// Update case - log update and record history
|
|
92
|
-
await logDecisionUpdate(knex, {
|
|
93
|
-
key: params.key,
|
|
94
|
-
old_value: String(existingDecision.value),
|
|
95
|
-
new_value: String(value),
|
|
96
|
-
old_version: existingDecision.version,
|
|
97
|
-
new_version: version,
|
|
98
|
-
agent_id: agentId,
|
|
99
|
-
layer_id: layerId || undefined
|
|
100
|
-
});
|
|
101
|
-
await recordDecisionHistory(knex, {
|
|
102
|
-
key_id: keyId,
|
|
103
|
-
version: existingDecision.version,
|
|
104
|
-
value: String(existingDecision.value),
|
|
105
|
-
agent_id: existingDecision.agent_id,
|
|
106
|
-
ts: existingDecision.ts
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
// New decision case - log set
|
|
111
|
-
await logDecisionSet(knex, {
|
|
112
|
-
key: params.key,
|
|
113
|
-
value: String(value),
|
|
114
|
-
version: version,
|
|
115
|
-
status: status,
|
|
116
|
-
agent_id: agentId,
|
|
117
|
-
layer_id: layerId || undefined
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
// Handle m_tags (many-to-many)
|
|
121
|
-
if (params.tags && params.tags.length > 0) {
|
|
122
|
-
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
123
|
-
const tags = parseStringArray(params.tags);
|
|
124
|
-
// Clear existing tags for this project
|
|
125
|
-
await knex('t_decision_tags')
|
|
126
|
-
.where({ decision_key_id: keyId, project_id: projectId })
|
|
127
|
-
.delete();
|
|
128
|
-
// Insert new tags
|
|
129
|
-
for (const tagName of tags) {
|
|
130
|
-
const tagId = await getOrCreateTag(adapter, projectId, tagName, trx); // v3.7.3: pass projectId
|
|
131
|
-
await knex('t_decision_tags').insert({
|
|
132
|
-
decision_key_id: keyId,
|
|
133
|
-
tag_id: tagId,
|
|
134
|
-
project_id: projectId
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// Handle m_scopes (many-to-many)
|
|
139
|
-
if (params.scopes && params.scopes.length > 0) {
|
|
140
|
-
// Parse scopes (handles both arrays and JSON strings from MCP)
|
|
141
|
-
const scopes = parseStringArray(params.scopes);
|
|
142
|
-
// Clear existing scopes for this project
|
|
143
|
-
await knex('t_decision_scopes')
|
|
144
|
-
.where({ decision_key_id: keyId, project_id: projectId })
|
|
145
|
-
.delete();
|
|
146
|
-
// Insert new scopes
|
|
147
|
-
for (const scopeName of scopes) {
|
|
148
|
-
const scopeId = await getOrCreateScope(adapter, projectId, scopeName, trx); // v3.7.3: pass projectId
|
|
149
|
-
await knex('t_decision_scopes').insert({
|
|
150
|
-
decision_key_id: keyId,
|
|
151
|
-
scope_id: scopeId,
|
|
152
|
-
project_id: projectId
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
success: true,
|
|
158
|
-
key: params.key,
|
|
159
|
-
key_id: keyId,
|
|
160
|
-
version: version,
|
|
161
|
-
message: `Decision "${params.key}" set successfully`
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Set or update a decision in the context
|
|
166
|
-
* Auto-detects numeric vs string values and routes to appropriate table
|
|
167
|
-
* Supports tags, layers, scopes, and version tracking
|
|
168
|
-
*
|
|
169
|
-
* @param params - Decision parameters
|
|
170
|
-
* @param adapter - Optional database adapter (for testing)
|
|
171
|
-
* @returns Response with success status and metadata
|
|
172
|
-
*/
|
|
173
|
-
export async function setDecision(params, adapter) {
|
|
174
|
-
debugLogFunctionEntry('setDecision', params);
|
|
175
|
-
// Validate parameters
|
|
176
|
-
try {
|
|
177
|
-
validateActionParams('decision', 'set', params);
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
throw error;
|
|
181
|
-
}
|
|
182
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
183
|
-
try {
|
|
184
|
-
debugLogTransaction('START', 'setDecision');
|
|
185
|
-
// Use transaction for atomicity with connection retry
|
|
186
|
-
const result = await connectionManager.executeWithRetry(async () => {
|
|
187
|
-
return await actualAdapter.transaction(async (trx) => {
|
|
188
|
-
debugLogTransaction('COMMIT', 'setDecision-transaction-begin');
|
|
189
|
-
const internalResult = await setDecisionInternal(params, actualAdapter, trx);
|
|
190
|
-
debugLogTransaction('COMMIT', 'setDecision-transaction-end');
|
|
191
|
-
return internalResult;
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
debugLogFunctionExit('setDecision', true, result);
|
|
195
|
-
return result;
|
|
196
|
-
}
|
|
197
|
-
catch (error) {
|
|
198
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
199
|
-
debugLogCriticalError('setDecision', error, {
|
|
200
|
-
function: 'setDecision',
|
|
201
|
-
params
|
|
202
|
-
});
|
|
203
|
-
debugLogTransaction('ROLLBACK', 'setDecision');
|
|
204
|
-
debugLogFunctionExit('setDecision', false, undefined, error);
|
|
205
|
-
throw new Error(`Failed to set decision: ${message}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Get context t_decisions with advanced filtering
|
|
210
|
-
* Uses v_tagged_decisions view for token efficiency
|
|
211
|
-
* Supports filtering by status, layer, tags, and scope
|
|
212
|
-
*
|
|
213
|
-
* @param params - Filter parameters
|
|
214
|
-
* @param adapter - Optional database adapter (for testing)
|
|
215
|
-
* @returns Array of t_decisions with metadata
|
|
216
|
-
*/
|
|
217
|
-
export async function getContext(params = {}, adapter) {
|
|
218
|
-
// Validate parameters
|
|
219
|
-
try {
|
|
220
|
-
validateActionParams('decision', 'list', params);
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
225
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
226
|
-
const knex = actualAdapter.getKnex();
|
|
227
|
-
// Determine which project to query (current or referenced)
|
|
228
|
-
let projectId;
|
|
229
|
-
if (params._reference_project) {
|
|
230
|
-
// Cross-project query: look up the referenced project
|
|
231
|
-
const refProject = await knex('m_projects')
|
|
232
|
-
.where({ name: params._reference_project })
|
|
233
|
-
.first();
|
|
234
|
-
if (!refProject) {
|
|
235
|
-
throw new Error(`Referenced project "${params._reference_project}" not found`);
|
|
236
|
-
}
|
|
237
|
-
projectId = refProject.id;
|
|
238
|
-
debugLog('INFO', 'Cross-project query', {
|
|
239
|
-
currentProject: getProjectContext().getProjectName(),
|
|
240
|
-
referencedProject: params._reference_project,
|
|
241
|
-
projectId
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// Normal query: use current project
|
|
246
|
-
projectId = getProjectContext().getProjectId();
|
|
247
|
-
}
|
|
248
|
-
try {
|
|
249
|
-
// Build query dynamically based on filters
|
|
250
|
-
// NOTE: v_tagged_decisions view will be updated to include project_id filtering
|
|
251
|
-
let query = knex('v_tagged_decisions').where('project_id', projectId);
|
|
252
|
-
// Filter by status
|
|
253
|
-
if (params.status) {
|
|
254
|
-
if (!STRING_TO_STATUS[params.status]) {
|
|
255
|
-
throw new Error(`Invalid status: ${params.status}`);
|
|
256
|
-
}
|
|
257
|
-
query = query.where('status', params.status);
|
|
258
|
-
}
|
|
259
|
-
// Filter by layer
|
|
260
|
-
if (params.layer) {
|
|
261
|
-
query = query.where('layer', params.layer);
|
|
262
|
-
}
|
|
263
|
-
// Filter by scope
|
|
264
|
-
if (params.scope) {
|
|
265
|
-
// Use LIKE for comma-separated scopes
|
|
266
|
-
query = query.where('scopes', 'like', `%${params.scope}%`);
|
|
267
|
-
}
|
|
268
|
-
// Filter by tags
|
|
269
|
-
if (params.tags && params.tags.length > 0) {
|
|
270
|
-
const tagMatch = params.tag_match || 'OR';
|
|
271
|
-
if (tagMatch === 'AND') {
|
|
272
|
-
// All tags must be present
|
|
273
|
-
for (const tag of params.tags) {
|
|
274
|
-
query = query.where('tags', 'like', `%${tag}%`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
// Any tag must be present (OR)
|
|
279
|
-
query = query.where((builder) => {
|
|
280
|
-
for (const tag of params.tags) {
|
|
281
|
-
builder.orWhere('tags', 'like', `%${tag}%`);
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
// Order by most recent
|
|
287
|
-
query = query.orderBy('updated', 'desc');
|
|
288
|
-
// Execute query
|
|
289
|
-
const rows = await query.select('*');
|
|
290
|
-
return {
|
|
291
|
-
decisions: rows,
|
|
292
|
-
count: rows.length
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
catch (error) {
|
|
296
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
297
|
-
throw new Error(`Failed to get context: ${message}`);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Get a specific decision by key
|
|
302
|
-
* Returns full metadata including tags, layer, scopes, version
|
|
303
|
-
* Optionally includes decision context (v3.2.2)
|
|
304
|
-
*
|
|
305
|
-
* @param params - Decision key and optional include_context flag
|
|
306
|
-
* @param adapter - Optional database adapter (for testing)
|
|
307
|
-
* @returns Decision details or not found
|
|
308
|
-
*/
|
|
309
|
-
export async function getDecision(params, adapter) {
|
|
310
|
-
// Validate parameters
|
|
311
|
-
try {
|
|
312
|
-
validateActionParams('decision', 'get', params);
|
|
313
|
-
}
|
|
314
|
-
catch (error) {
|
|
315
|
-
throw error;
|
|
316
|
-
}
|
|
317
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
318
|
-
const knex = actualAdapter.getKnex();
|
|
319
|
-
// Validate project context
|
|
320
|
-
const projectId = getProjectContext().getProjectId();
|
|
321
|
-
// Validate parameter
|
|
322
|
-
if (!params.key || params.key.trim() === '') {
|
|
323
|
-
throw new Error('Parameter "key" is required and cannot be empty');
|
|
324
|
-
}
|
|
325
|
-
try {
|
|
326
|
-
// If include_context is true, use the context-aware function
|
|
327
|
-
if (params.include_context) {
|
|
328
|
-
// TODO: Update dbGetDecisionWithContext to accept projectId parameter
|
|
329
|
-
const result = await dbGetDecisionWithContext(actualAdapter, params.key);
|
|
330
|
-
if (!result) {
|
|
331
|
-
return {
|
|
332
|
-
found: false
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
return {
|
|
336
|
-
found: true,
|
|
337
|
-
decision: {
|
|
338
|
-
key: result.key,
|
|
339
|
-
value: result.value,
|
|
340
|
-
version: result.version,
|
|
341
|
-
status: result.status,
|
|
342
|
-
layer: result.layer,
|
|
343
|
-
decided_by: result.decided_by,
|
|
344
|
-
updated: result.updated,
|
|
345
|
-
tags: null, // Not included in getDecisionWithContext
|
|
346
|
-
scopes: null // Not included in getDecisionWithContext
|
|
347
|
-
},
|
|
348
|
-
context: result.context.map(ctx => ({
|
|
349
|
-
...ctx,
|
|
350
|
-
// Parse JSON fields
|
|
351
|
-
alternatives_considered: ctx.alternatives_considered ? JSON.parse(ctx.alternatives_considered) : null,
|
|
352
|
-
tradeoffs: ctx.tradeoffs ? JSON.parse(ctx.tradeoffs) : null
|
|
353
|
-
}))
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
// Standard query without context (backward compatible)
|
|
357
|
-
const row = await knex('v_tagged_decisions')
|
|
358
|
-
.where({ key: params.key, project_id: projectId })
|
|
359
|
-
.first();
|
|
360
|
-
if (!row) {
|
|
361
|
-
return {
|
|
362
|
-
found: false
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
return {
|
|
366
|
-
found: true,
|
|
367
|
-
decision: row
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
catch (error) {
|
|
371
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
372
|
-
throw new Error(`Failed to get decision: ${message}`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Search for t_decisions by m_tags with AND/OR logic
|
|
377
|
-
* Provides flexible tag-based filtering with status and layer support
|
|
378
|
-
*
|
|
379
|
-
* @param params - Search parameters (tags, match_mode, status, layer)
|
|
380
|
-
* @param adapter - Optional database adapter (for testing)
|
|
381
|
-
* @returns Array of t_decisions matching tag criteria
|
|
382
|
-
*/
|
|
383
|
-
export async function searchByTags(params, adapter) {
|
|
384
|
-
// Validate parameters
|
|
385
|
-
try {
|
|
386
|
-
validateActionParams('decision', 'search_tags', params);
|
|
387
|
-
}
|
|
388
|
-
catch (error) {
|
|
389
|
-
throw error;
|
|
390
|
-
}
|
|
391
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
392
|
-
const knex = actualAdapter.getKnex();
|
|
393
|
-
// Validate project context
|
|
394
|
-
const projectId = getProjectContext().getProjectId();
|
|
395
|
-
// Validate required parameters
|
|
396
|
-
if (!params.tags || params.tags.length === 0) {
|
|
397
|
-
throw new Error('Parameter "tags" is required and must contain at least one tag');
|
|
398
|
-
}
|
|
399
|
-
try {
|
|
400
|
-
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
401
|
-
const tags = parseStringArray(params.tags);
|
|
402
|
-
const matchMode = params.match_mode || 'OR';
|
|
403
|
-
let query = knex('v_tagged_decisions').where('project_id', projectId);
|
|
404
|
-
// Apply tag filtering based on match mode
|
|
405
|
-
if (matchMode === 'AND') {
|
|
406
|
-
// All tags must be present
|
|
407
|
-
for (const tag of tags) {
|
|
408
|
-
query = query.where('tags', 'like', `%${tag}%`);
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
else if (matchMode === 'OR') {
|
|
412
|
-
// Any tag must be present
|
|
413
|
-
query = query.where((builder) => {
|
|
414
|
-
for (const tag of tags) {
|
|
415
|
-
builder.orWhere('tags', 'like', `%${tag}%`);
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
throw new Error(`Invalid match_mode: ${matchMode}. Must be 'AND' or 'OR'`);
|
|
421
|
-
}
|
|
422
|
-
// Optional status filter
|
|
423
|
-
if (params.status) {
|
|
424
|
-
if (!STRING_TO_STATUS[params.status]) {
|
|
425
|
-
throw new Error(`Invalid status: ${params.status}. Must be 'active', 'deprecated', or 'draft'`);
|
|
426
|
-
}
|
|
427
|
-
query = query.where('status', params.status);
|
|
428
|
-
}
|
|
429
|
-
// Optional layer filter
|
|
430
|
-
if (params.layer) {
|
|
431
|
-
// Validate layer exists
|
|
432
|
-
const layerId = await getLayerId(actualAdapter, params.layer);
|
|
433
|
-
if (layerId === null) {
|
|
434
|
-
throw new Error(`Invalid layer: ${params.layer}. Must be one of: presentation, business, data, infrastructure, cross-cutting`);
|
|
435
|
-
}
|
|
436
|
-
query = query.where('layer', params.layer);
|
|
437
|
-
}
|
|
438
|
-
// Order by most recent
|
|
439
|
-
query = query.orderBy('updated', 'desc');
|
|
440
|
-
// Execute query
|
|
441
|
-
const rows = await query.select('*');
|
|
442
|
-
return {
|
|
443
|
-
decisions: rows,
|
|
444
|
-
count: rows.length
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
catch (error) {
|
|
448
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
449
|
-
throw new Error(`Failed to search by tags: ${message}`);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Get version history for a specific decision key
|
|
454
|
-
* Returns all historical versions ordered by timestamp (newest first)
|
|
455
|
-
*
|
|
456
|
-
* @param params - Decision key to get history for
|
|
457
|
-
* @param adapter - Optional database adapter (for testing)
|
|
458
|
-
* @returns Array of historical versions with metadata
|
|
459
|
-
*/
|
|
460
|
-
export async function getVersions(params, adapter) {
|
|
461
|
-
// Validate parameters
|
|
462
|
-
try {
|
|
463
|
-
validateActionParams('decision', 'versions', params);
|
|
464
|
-
}
|
|
465
|
-
catch (error) {
|
|
466
|
-
throw error;
|
|
467
|
-
}
|
|
468
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
469
|
-
const knex = actualAdapter.getKnex();
|
|
470
|
-
// Validate project context
|
|
471
|
-
const projectId = getProjectContext().getProjectId();
|
|
472
|
-
// Validate required parameter
|
|
473
|
-
if (!params.key || params.key.trim() === '') {
|
|
474
|
-
throw new Error('Parameter "key" is required and cannot be empty');
|
|
475
|
-
}
|
|
476
|
-
try {
|
|
477
|
-
// Get key_id for the decision
|
|
478
|
-
const keyResult = await knex('m_context_keys')
|
|
479
|
-
.where({ key: params.key })
|
|
480
|
-
.first('id');
|
|
481
|
-
if (!keyResult) {
|
|
482
|
-
// Key doesn't exist, return empty history
|
|
483
|
-
return {
|
|
484
|
-
key: params.key,
|
|
485
|
-
history: [],
|
|
486
|
-
count: 0
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
const keyId = keyResult.id;
|
|
490
|
-
// Query t_decision_history with agent join
|
|
491
|
-
const rows = await knex('t_decision_history as dh')
|
|
492
|
-
.leftJoin('m_agents as a', 'dh.agent_id', 'a.id')
|
|
493
|
-
.where({ 'dh.key_id': keyId, 'dh.project_id': projectId })
|
|
494
|
-
.select('dh.version', 'dh.value', 'a.name as agent_name', knex.raw(`datetime(dh.ts, 'unixepoch') as timestamp`))
|
|
495
|
-
.orderBy('dh.ts', 'desc');
|
|
496
|
-
// Transform to response format
|
|
497
|
-
const history = rows.map(row => ({
|
|
498
|
-
version: row.version,
|
|
499
|
-
value: row.value,
|
|
500
|
-
agent: row.agent_name,
|
|
501
|
-
timestamp: row.timestamp
|
|
502
|
-
}));
|
|
503
|
-
return {
|
|
504
|
-
key: params.key,
|
|
505
|
-
history: history,
|
|
506
|
-
count: history.length
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
catch (error) {
|
|
510
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
511
|
-
throw new Error(`Failed to get versions: ${message}`);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Search for t_decisions within a specific architecture layer
|
|
516
|
-
* Supports status filtering and optional tag inclusion
|
|
517
|
-
*
|
|
518
|
-
* @param params - Layer name, optional status and include_tags
|
|
519
|
-
* @param adapter - Optional database adapter (for testing)
|
|
520
|
-
* @returns Array of t_decisions in the specified layer
|
|
521
|
-
*/
|
|
522
|
-
export async function searchByLayer(params, adapter) {
|
|
523
|
-
// Validate parameters
|
|
524
|
-
try {
|
|
525
|
-
validateActionParams('decision', 'search_layer', params);
|
|
526
|
-
}
|
|
527
|
-
catch (error) {
|
|
528
|
-
throw error;
|
|
529
|
-
}
|
|
530
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
531
|
-
const knex = actualAdapter.getKnex();
|
|
532
|
-
// Determine which project to query (current or referenced)
|
|
533
|
-
let projectId;
|
|
534
|
-
if (params._reference_project) {
|
|
535
|
-
// Cross-project query: look up the referenced project
|
|
536
|
-
const refProject = await knex('m_projects')
|
|
537
|
-
.where({ name: params._reference_project })
|
|
538
|
-
.first();
|
|
539
|
-
if (!refProject) {
|
|
540
|
-
throw new Error(`Referenced project "${params._reference_project}" not found`);
|
|
541
|
-
}
|
|
542
|
-
projectId = refProject.id;
|
|
543
|
-
debugLog('INFO', 'Cross-project searchByLayer', {
|
|
544
|
-
currentProject: getProjectContext().getProjectName(),
|
|
545
|
-
referencedProject: params._reference_project,
|
|
546
|
-
projectId
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
// Normal query: use current project
|
|
551
|
-
projectId = getProjectContext().getProjectId();
|
|
552
|
-
}
|
|
553
|
-
// Validate required parameter
|
|
554
|
-
if (!params.layer || params.layer.trim() === '') {
|
|
555
|
-
throw new Error('Parameter "layer" is required and cannot be empty');
|
|
556
|
-
}
|
|
557
|
-
try {
|
|
558
|
-
// Validate layer exists
|
|
559
|
-
const layerId = await getLayerId(actualAdapter, params.layer);
|
|
560
|
-
if (layerId === null) {
|
|
561
|
-
throw new Error(`Invalid layer: ${params.layer}. Must be one of: presentation, business, data, infrastructure, cross-cutting`);
|
|
562
|
-
}
|
|
563
|
-
// Determine which view/table to use
|
|
564
|
-
const includeTagsValue = params.include_tags !== undefined ? params.include_tags : true;
|
|
565
|
-
const statusValue = params.status || 'active';
|
|
566
|
-
// Validate status
|
|
567
|
-
if (!STRING_TO_STATUS[statusValue]) {
|
|
568
|
-
throw new Error(`Invalid status: ${statusValue}. Must be 'active', 'deprecated', or 'draft'`);
|
|
569
|
-
}
|
|
570
|
-
let rows;
|
|
571
|
-
if (includeTagsValue) {
|
|
572
|
-
// Use v_tagged_decisions view for full metadata
|
|
573
|
-
rows = await knex('v_tagged_decisions')
|
|
574
|
-
.where({ layer: params.layer, status: statusValue, project_id: projectId })
|
|
575
|
-
.orderBy('updated', 'desc')
|
|
576
|
-
.select('*');
|
|
577
|
-
}
|
|
578
|
-
else {
|
|
579
|
-
// Use base t_decisions table with minimal joins
|
|
580
|
-
const statusInt = STRING_TO_STATUS[statusValue];
|
|
581
|
-
const stringDecisions = knex('t_decisions as d')
|
|
582
|
-
.innerJoin('m_context_keys as ck', 'd.key_id', 'ck.id')
|
|
583
|
-
.leftJoin('m_layers as l', 'd.layer_id', 'l.id')
|
|
584
|
-
.leftJoin('m_agents as a', 'd.agent_id', 'a.id')
|
|
585
|
-
.where('l.name', params.layer)
|
|
586
|
-
.where('d.status', statusInt)
|
|
587
|
-
.where('d.project_id', projectId)
|
|
588
|
-
.select('ck.key', 'd.value', 'd.version', knex.raw(`CASE d.status WHEN 1 THEN 'active' WHEN 2 THEN 'deprecated' WHEN 3 THEN 'draft' END as status`), 'l.name as layer', knex.raw('NULL as tags'), knex.raw('NULL as scopes'), 'a.name as decided_by', knex.raw(`datetime(d.ts, 'unixepoch') as updated`));
|
|
589
|
-
const numericDecisions = knex('t_decisions_numeric as dn')
|
|
590
|
-
.innerJoin('m_context_keys as ck', 'dn.key_id', 'ck.id')
|
|
591
|
-
.leftJoin('m_layers as l', 'dn.layer_id', 'l.id')
|
|
592
|
-
.leftJoin('m_agents as a', 'dn.agent_id', 'a.id')
|
|
593
|
-
.where('l.name', params.layer)
|
|
594
|
-
.where('dn.status', statusInt)
|
|
595
|
-
.where('dn.project_id', projectId)
|
|
596
|
-
.select('ck.key', knex.raw('CAST(dn.value AS TEXT) as value'), 'dn.version', knex.raw(`CASE dn.status WHEN 1 THEN 'active' WHEN 2 THEN 'deprecated' WHEN 3 THEN 'draft' END as status`), 'l.name as layer', knex.raw('NULL as tags'), knex.raw('NULL as scopes'), 'a.name as decided_by', knex.raw(`datetime(dn.ts, 'unixepoch') as updated`));
|
|
597
|
-
// Union both queries
|
|
598
|
-
rows = await stringDecisions.union([numericDecisions]).orderBy('updated', 'desc');
|
|
599
|
-
}
|
|
600
|
-
return {
|
|
601
|
-
layer: params.layer,
|
|
602
|
-
decisions: rows,
|
|
603
|
-
count: rows.length
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
catch (error) {
|
|
607
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
608
|
-
throw new Error(`Failed to search by layer: ${message}`);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Quick set decision with smart defaults and inference
|
|
613
|
-
* Reduces required parameters from 7 to 2 (key + value only)
|
|
614
|
-
*
|
|
615
|
-
* Inference Rules:
|
|
616
|
-
* - Layer: Inferred from key prefix
|
|
617
|
-
* - api/*, endpoint/*, ui/* → "presentation"
|
|
618
|
-
* - service/*, logic/*, workflow/* → "business"
|
|
619
|
-
* - db/*, model/*, schema/* → "data"
|
|
620
|
-
* - config/*, deploy/* → "infrastructure"
|
|
621
|
-
* - Default → "business"
|
|
622
|
-
*
|
|
623
|
-
* - Tags: Extracted from key hierarchy
|
|
624
|
-
* - Key "api/instruments/synthesis" → tags: ["api", "instruments", "synthesis"]
|
|
625
|
-
*
|
|
626
|
-
* - Scope: Inferred from key hierarchy
|
|
627
|
-
* - Key "api/instruments/synthesis" → scope: "api/instruments"
|
|
628
|
-
*
|
|
629
|
-
* - Auto-defaults:
|
|
630
|
-
* - status: "active"
|
|
631
|
-
* - version: "1.0.0"
|
|
632
|
-
*
|
|
633
|
-
* All inferred fields can be overridden via optional parameters.
|
|
634
|
-
*
|
|
635
|
-
* @param params - Quick set parameters (key and value required)
|
|
636
|
-
* @param adapter - Optional database adapter (for testing)
|
|
637
|
-
* @returns Response with success status and inferred metadata
|
|
638
|
-
*/
|
|
639
|
-
export async function quickSetDecision(params, adapter) {
|
|
640
|
-
// Validate parameters
|
|
641
|
-
try {
|
|
642
|
-
validateActionParams('decision', 'quick_set', params);
|
|
643
|
-
}
|
|
644
|
-
catch (error) {
|
|
645
|
-
throw error;
|
|
646
|
-
}
|
|
647
|
-
// Validate required parameters
|
|
648
|
-
if (!params.key || params.key.trim() === '') {
|
|
649
|
-
throw new Error('Parameter "key" is required and cannot be empty');
|
|
650
|
-
}
|
|
651
|
-
if (params.value === undefined || params.value === null) {
|
|
652
|
-
throw new Error('Parameter "value" is required');
|
|
653
|
-
}
|
|
654
|
-
// Track what was inferred
|
|
655
|
-
const inferred = {};
|
|
656
|
-
// Infer layer from key prefix (if not provided)
|
|
657
|
-
let inferredLayer = params.layer;
|
|
658
|
-
if (!inferredLayer) {
|
|
659
|
-
const keyLower = params.key.toLowerCase();
|
|
660
|
-
if (keyLower.startsWith('api/') || keyLower.startsWith('endpoint/') || keyLower.startsWith('ui/')) {
|
|
661
|
-
inferredLayer = 'presentation';
|
|
662
|
-
}
|
|
663
|
-
else if (keyLower.startsWith('service/') || keyLower.startsWith('logic/') || keyLower.startsWith('workflow/')) {
|
|
664
|
-
inferredLayer = 'business';
|
|
665
|
-
}
|
|
666
|
-
else if (keyLower.startsWith('db/') || keyLower.startsWith('model/') || keyLower.startsWith('schema/')) {
|
|
667
|
-
inferredLayer = 'data';
|
|
668
|
-
}
|
|
669
|
-
else if (keyLower.startsWith('config/') || keyLower.startsWith('deploy/')) {
|
|
670
|
-
inferredLayer = 'infrastructure';
|
|
671
|
-
}
|
|
672
|
-
else {
|
|
673
|
-
// Default layer
|
|
674
|
-
inferredLayer = 'business';
|
|
675
|
-
}
|
|
676
|
-
inferred.layer = inferredLayer;
|
|
677
|
-
}
|
|
678
|
-
// Extract tags from key hierarchy (if not provided)
|
|
679
|
-
let inferredTags = params.tags;
|
|
680
|
-
if (!inferredTags || inferredTags.length === 0) {
|
|
681
|
-
// Split key by '/', '-', or '_' to get hierarchy parts
|
|
682
|
-
const parts = params.key.split(/[\/\-_]/).filter(p => p.trim() !== '');
|
|
683
|
-
inferredTags = parts;
|
|
684
|
-
inferred.tags = inferredTags;
|
|
685
|
-
}
|
|
686
|
-
// Infer scope from key hierarchy (if not provided)
|
|
687
|
-
let inferredScopes = params.scopes;
|
|
688
|
-
if (!inferredScopes || inferredScopes.length === 0) {
|
|
689
|
-
// Get parent scope from key (everything except last part)
|
|
690
|
-
const parts = params.key.split('/');
|
|
691
|
-
if (parts.length > 1) {
|
|
692
|
-
// Take all but the last part
|
|
693
|
-
const scopeParts = parts.slice(0, -1);
|
|
694
|
-
const scope = scopeParts.join('/');
|
|
695
|
-
inferredScopes = [scope];
|
|
696
|
-
inferred.scope = scope;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
// Build full params for setDecision
|
|
700
|
-
const fullParams = {
|
|
701
|
-
key: params.key,
|
|
702
|
-
value: params.value,
|
|
703
|
-
agent: params.agent, // May be undefined, setDecision will default to 'system'
|
|
704
|
-
layer: inferredLayer,
|
|
705
|
-
version: params.version || DEFAULT_VERSION,
|
|
706
|
-
status: params.status || 'active',
|
|
707
|
-
tags: inferredTags,
|
|
708
|
-
scopes: inferredScopes
|
|
709
|
-
};
|
|
710
|
-
// Call setDecision with full params (pass adapter if provided)
|
|
711
|
-
const result = await setDecision(fullParams, adapter);
|
|
712
|
-
// Return response with inferred metadata
|
|
713
|
-
return {
|
|
714
|
-
success: result.success,
|
|
715
|
-
key: result.key,
|
|
716
|
-
key_id: result.key_id,
|
|
717
|
-
version: result.version,
|
|
718
|
-
inferred: inferred,
|
|
719
|
-
message: `Decision "${params.key}" set successfully with smart defaults`
|
|
720
|
-
};
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* Advanced query composition with complex filtering capabilities
|
|
724
|
-
* Supports multiple filter types, sorting, and pagination
|
|
725
|
-
*
|
|
726
|
-
* Filter Logic:
|
|
727
|
-
* - layers: OR relationship - match any layer in the array
|
|
728
|
-
* - tags_all: AND relationship - must have ALL tags
|
|
729
|
-
* - tags_any: OR relationship - must have ANY tag
|
|
730
|
-
* - exclude_tags: Exclude decisions with these tags
|
|
731
|
-
* - scopes: Wildcard support (e.g., "api/instruments/*")
|
|
732
|
-
* - updated_after/before: Temporal filtering (ISO timestamp or relative like "7d")
|
|
733
|
-
* - decided_by: Filter by agent names (OR relationship)
|
|
734
|
-
* - statuses: Multiple statuses (OR relationship)
|
|
735
|
-
* - search_text: Full-text search in value field
|
|
736
|
-
*
|
|
737
|
-
* @param params - Advanced search parameters with filtering, sorting, pagination
|
|
738
|
-
* @param adapter - Optional database adapter (for testing)
|
|
739
|
-
* @returns Filtered decisions with total count for pagination
|
|
740
|
-
*/
|
|
741
|
-
export async function searchAdvanced(params = {}, adapter) {
|
|
742
|
-
// Validate parameters
|
|
743
|
-
validateActionParams('decision', 'search_advanced', params);
|
|
744
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
745
|
-
const knex = actualAdapter.getKnex();
|
|
746
|
-
// Validate project context
|
|
747
|
-
const projectId = getProjectContext().getProjectId();
|
|
748
|
-
try {
|
|
749
|
-
// Parse relative time to Unix timestamp
|
|
750
|
-
const parseRelativeTime = (relativeTime) => {
|
|
751
|
-
const match = relativeTime.match(/^(\d+)(m|h|d)$/);
|
|
752
|
-
if (!match) {
|
|
753
|
-
// Try parsing as ISO timestamp
|
|
754
|
-
const date = new Date(relativeTime);
|
|
755
|
-
if (isNaN(date.getTime())) {
|
|
756
|
-
return null;
|
|
757
|
-
}
|
|
758
|
-
return Math.floor(date.getTime() / 1000);
|
|
759
|
-
}
|
|
760
|
-
const value = parseInt(match[1], 10);
|
|
761
|
-
const unit = match[2];
|
|
762
|
-
const now = Math.floor(Date.now() / 1000);
|
|
763
|
-
switch (unit) {
|
|
764
|
-
case 'm': return now - (value * 60);
|
|
765
|
-
case 'h': return now - (value * 3600);
|
|
766
|
-
case 'd': return now - (value * 86400);
|
|
767
|
-
default: return null;
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
// Build base query using v_tagged_decisions view
|
|
771
|
-
let query = knex('v_tagged_decisions').where('project_id', projectId);
|
|
772
|
-
// Filter by layers (OR relationship)
|
|
773
|
-
if (params.layers && params.layers.length > 0) {
|
|
774
|
-
query = query.whereIn('layer', params.layers);
|
|
775
|
-
}
|
|
776
|
-
// Filter by tags_all (AND relationship - must have ALL tags)
|
|
777
|
-
if (params.tags_all && params.tags_all.length > 0) {
|
|
778
|
-
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
779
|
-
const tagsAll = parseStringArray(params.tags_all);
|
|
780
|
-
for (const tag of tagsAll) {
|
|
781
|
-
query = query.where((builder) => {
|
|
782
|
-
builder.where('tags', 'like', `%${tag}%`).orWhere('tags', tag);
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
// Filter by tags_any (OR relationship - must have ANY tag)
|
|
787
|
-
if (params.tags_any && params.tags_any.length > 0) {
|
|
788
|
-
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
789
|
-
const tagsAny = parseStringArray(params.tags_any);
|
|
790
|
-
query = query.where((builder) => {
|
|
791
|
-
for (const tag of tagsAny) {
|
|
792
|
-
builder.orWhere('tags', 'like', `%${tag}%`).orWhere('tags', tag);
|
|
793
|
-
}
|
|
794
|
-
});
|
|
795
|
-
}
|
|
796
|
-
// Exclude tags
|
|
797
|
-
if (params.exclude_tags && params.exclude_tags.length > 0) {
|
|
798
|
-
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
799
|
-
const excludeTags = parseStringArray(params.exclude_tags);
|
|
800
|
-
for (const tag of excludeTags) {
|
|
801
|
-
query = query.where((builder) => {
|
|
802
|
-
builder.whereNull('tags')
|
|
803
|
-
.orWhere((subBuilder) => {
|
|
804
|
-
subBuilder.where('tags', 'not like', `%${tag}%`)
|
|
805
|
-
.where('tags', '!=', tag);
|
|
806
|
-
});
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
// Filter by scopes with wildcard support
|
|
811
|
-
if (params.scopes && params.scopes.length > 0) {
|
|
812
|
-
// Parse scopes (handles both arrays and JSON strings from MCP)
|
|
813
|
-
const scopes = parseStringArray(params.scopes);
|
|
814
|
-
query = query.where((builder) => {
|
|
815
|
-
for (const scope of scopes) {
|
|
816
|
-
if (scope.includes('*')) {
|
|
817
|
-
// Wildcard pattern - convert to LIKE pattern
|
|
818
|
-
const likePattern = scope.replace(/\*/g, '%');
|
|
819
|
-
builder.orWhere('scopes', 'like', `%${likePattern}%`)
|
|
820
|
-
.orWhere('scopes', likePattern);
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
// Exact match
|
|
824
|
-
builder.orWhere('scopes', 'like', `%${scope}%`)
|
|
825
|
-
.orWhere('scopes', scope);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
});
|
|
829
|
-
}
|
|
830
|
-
// Temporal filtering - updated_after
|
|
831
|
-
if (params.updated_after) {
|
|
832
|
-
const timestamp = parseRelativeTime(params.updated_after);
|
|
833
|
-
if (timestamp !== null) {
|
|
834
|
-
query = query.whereRaw('unixepoch(updated) >= ?', [timestamp]);
|
|
835
|
-
}
|
|
836
|
-
else {
|
|
837
|
-
throw new Error(`Invalid updated_after format: ${params.updated_after}. Use ISO timestamp or relative time like "7d", "2h", "30m"`);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
// Temporal filtering - updated_before
|
|
841
|
-
if (params.updated_before) {
|
|
842
|
-
const timestamp = parseRelativeTime(params.updated_before);
|
|
843
|
-
if (timestamp !== null) {
|
|
844
|
-
query = query.whereRaw('unixepoch(updated) <= ?', [timestamp]);
|
|
845
|
-
}
|
|
846
|
-
else {
|
|
847
|
-
throw new Error(`Invalid updated_before format: ${params.updated_before}. Use ISO timestamp or relative time like "7d", "2h", "30m"`);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
// Filter by decided_by (OR relationship)
|
|
851
|
-
if (params.decided_by && params.decided_by.length > 0) {
|
|
852
|
-
query = query.whereIn('decided_by', params.decided_by);
|
|
853
|
-
}
|
|
854
|
-
// Filter by statuses (OR relationship)
|
|
855
|
-
if (params.statuses && params.statuses.length > 0) {
|
|
856
|
-
query = query.whereIn('status', params.statuses);
|
|
857
|
-
}
|
|
858
|
-
// Full-text search in value field
|
|
859
|
-
if (params.search_text) {
|
|
860
|
-
query = query.where('value', 'like', `%${params.search_text}%`);
|
|
861
|
-
}
|
|
862
|
-
// Count total matching records (before pagination)
|
|
863
|
-
const countQuery = query.clone().count('* as total');
|
|
864
|
-
const countResult = await countQuery.first();
|
|
865
|
-
const totalCount = countResult.total;
|
|
866
|
-
// Sorting
|
|
867
|
-
const sortBy = params.sort_by || 'updated';
|
|
868
|
-
const sortOrder = params.sort_order || 'desc';
|
|
869
|
-
// Validate sort parameters
|
|
870
|
-
if (!['updated', 'key', 'version'].includes(sortBy)) {
|
|
871
|
-
throw new Error(`Invalid sort_by: ${sortBy}. Must be 'updated', 'key', or 'version'`);
|
|
872
|
-
}
|
|
873
|
-
if (!['asc', 'desc'].includes(sortOrder)) {
|
|
874
|
-
throw new Error(`Invalid sort_order: ${sortOrder}. Must be 'asc' or 'desc'`);
|
|
875
|
-
}
|
|
876
|
-
query = query.orderBy(sortBy, sortOrder);
|
|
877
|
-
// Pagination
|
|
878
|
-
const limit = params.limit !== undefined ? params.limit : 20;
|
|
879
|
-
const offset = params.offset || 0;
|
|
880
|
-
// Validate pagination parameters
|
|
881
|
-
if (limit < 0 || limit > 1000) {
|
|
882
|
-
throw new Error('Parameter "limit" must be between 0 and 1000');
|
|
883
|
-
}
|
|
884
|
-
if (offset < 0) {
|
|
885
|
-
throw new Error('Parameter "offset" must be non-negative');
|
|
886
|
-
}
|
|
887
|
-
query = query.limit(limit).offset(offset);
|
|
888
|
-
// Execute query
|
|
889
|
-
const rows = await query.select('*');
|
|
890
|
-
return {
|
|
891
|
-
decisions: rows,
|
|
892
|
-
count: rows.length,
|
|
893
|
-
total_count: totalCount
|
|
894
|
-
};
|
|
895
|
-
}
|
|
896
|
-
catch (error) {
|
|
897
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
898
|
-
throw new Error(`Failed to execute advanced search: ${message}`);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
/**
|
|
902
|
-
* Set multiple decisions in a single batch operation (FR-005)
|
|
903
|
-
* Supports atomic (all succeed or all fail) and non-atomic modes
|
|
904
|
-
* Limit: 50 items per batch (constraint #3)
|
|
905
|
-
*
|
|
906
|
-
* @param params - Batch parameters with array of decisions and atomic flag
|
|
907
|
-
* @param adapter - Optional database adapter (for testing)
|
|
908
|
-
* @returns Response with success status and detailed results for each item
|
|
909
|
-
*/
|
|
910
|
-
export async function setDecisionBatch(params, adapter) {
|
|
911
|
-
// Validate batch parameters
|
|
912
|
-
validateBatchParams('decision', 'decisions', params.decisions, 'set', 50);
|
|
913
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
914
|
-
if (params.decisions.length === 0) {
|
|
915
|
-
return {
|
|
916
|
-
success: true,
|
|
917
|
-
inserted: 0,
|
|
918
|
-
failed: 0,
|
|
919
|
-
results: []
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
if (params.decisions.length > 50) {
|
|
923
|
-
throw new Error('Parameter "decisions" must contain at most 50 items');
|
|
924
|
-
}
|
|
925
|
-
const atomic = params.atomic !== undefined ? params.atomic : true;
|
|
926
|
-
try {
|
|
927
|
-
if (atomic) {
|
|
928
|
-
// Atomic mode: All or nothing
|
|
929
|
-
const results = await connectionManager.executeWithRetry(async () => {
|
|
930
|
-
return await actualAdapter.transaction(async (trx) => {
|
|
931
|
-
const processedResults = [];
|
|
932
|
-
for (const decision of params.decisions) {
|
|
933
|
-
try {
|
|
934
|
-
const result = await setDecisionInternal(decision, actualAdapter, trx);
|
|
935
|
-
processedResults.push({
|
|
936
|
-
key: decision.key,
|
|
937
|
-
key_id: result.key_id,
|
|
938
|
-
version: result.version,
|
|
939
|
-
success: true,
|
|
940
|
-
error: undefined
|
|
941
|
-
});
|
|
942
|
-
}
|
|
943
|
-
catch (error) {
|
|
944
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
945
|
-
throw new Error(`Batch failed at decision "${decision.key}": ${message}`);
|
|
946
|
-
}
|
|
947
|
-
}
|
|
948
|
-
return processedResults;
|
|
949
|
-
});
|
|
950
|
-
});
|
|
951
|
-
return {
|
|
952
|
-
success: true,
|
|
953
|
-
inserted: results.length,
|
|
954
|
-
failed: 0,
|
|
955
|
-
results: results
|
|
956
|
-
};
|
|
957
|
-
}
|
|
958
|
-
else {
|
|
959
|
-
// Non-atomic mode: Process each independently
|
|
960
|
-
const results = [];
|
|
961
|
-
let inserted = 0;
|
|
962
|
-
let failed = 0;
|
|
963
|
-
for (const decision of params.decisions) {
|
|
964
|
-
try {
|
|
965
|
-
const result = await connectionManager.executeWithRetry(async () => {
|
|
966
|
-
return await actualAdapter.transaction(async (trx) => {
|
|
967
|
-
return await setDecisionInternal(decision, actualAdapter, trx);
|
|
968
|
-
});
|
|
969
|
-
});
|
|
970
|
-
results.push({
|
|
971
|
-
key: decision.key,
|
|
972
|
-
key_id: result.key_id,
|
|
973
|
-
version: result.version,
|
|
974
|
-
success: true,
|
|
975
|
-
error: undefined
|
|
976
|
-
});
|
|
977
|
-
inserted++;
|
|
978
|
-
}
|
|
979
|
-
catch (error) {
|
|
980
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
981
|
-
results.push({
|
|
982
|
-
key: decision.key,
|
|
983
|
-
key_id: undefined,
|
|
984
|
-
version: undefined,
|
|
985
|
-
success: false,
|
|
986
|
-
error: message
|
|
987
|
-
});
|
|
988
|
-
failed++;
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
return {
|
|
992
|
-
success: failed === 0,
|
|
993
|
-
inserted: inserted,
|
|
994
|
-
failed: failed,
|
|
995
|
-
results: results
|
|
996
|
-
};
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
catch (error) {
|
|
1000
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1001
|
-
throw new Error(`Failed to execute batch operation: ${message}`);
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
/**
|
|
1005
|
-
* Check for updates since a given timestamp (FR-003 Phase A)
|
|
1006
|
-
* Lightweight polling mechanism using COUNT queries
|
|
1007
|
-
* Token cost: ~5-10 tokens per check
|
|
1008
|
-
*
|
|
1009
|
-
* @param params - Agent name and since_timestamp (ISO 8601)
|
|
1010
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1011
|
-
* @returns Boolean flag and counts for decisions, messages, files
|
|
1012
|
-
*/
|
|
1013
|
-
export async function hasUpdates(params, adapter) {
|
|
1014
|
-
// Validate parameters
|
|
1015
|
-
validateActionParams('decision', 'has_updates', params);
|
|
1016
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1017
|
-
const knex = actualAdapter.getKnex();
|
|
1018
|
-
// Validate project context
|
|
1019
|
-
const projectId = getProjectContext().getProjectId();
|
|
1020
|
-
try {
|
|
1021
|
-
// Parse ISO timestamp to Unix epoch
|
|
1022
|
-
const sinceDate = new Date(params.since_timestamp);
|
|
1023
|
-
if (isNaN(sinceDate.getTime())) {
|
|
1024
|
-
throw new Error(`Invalid since_timestamp format: ${params.since_timestamp}. Use ISO 8601 format (e.g., "2025-10-14T08:00:00Z")`);
|
|
1025
|
-
}
|
|
1026
|
-
const sinceTs = Math.floor(sinceDate.getTime() / 1000);
|
|
1027
|
-
// Count decisions updated since timestamp (both string and numeric tables)
|
|
1028
|
-
const decisionCount1 = await knex('t_decisions')
|
|
1029
|
-
.where({ project_id: projectId })
|
|
1030
|
-
.where('ts', '>', sinceTs)
|
|
1031
|
-
.count('* as count')
|
|
1032
|
-
.first();
|
|
1033
|
-
const decisionCount2 = await knex('t_decisions_numeric')
|
|
1034
|
-
.where({ project_id: projectId })
|
|
1035
|
-
.where('ts', '>', sinceTs)
|
|
1036
|
-
.count('* as count')
|
|
1037
|
-
.first();
|
|
1038
|
-
const decisionsCount = (decisionCount1?.count || 0) + (decisionCount2?.count || 0);
|
|
1039
|
-
// Get agent_id for the requesting agent
|
|
1040
|
-
const agentResult = await knex('m_agents')
|
|
1041
|
-
.where({ name: params.agent_name })
|
|
1042
|
-
.first('id');
|
|
1043
|
-
// Count messages for the agent (received messages - to_agent_id matches OR broadcast messages)
|
|
1044
|
-
let messagesCount = 0;
|
|
1045
|
-
if (agentResult) {
|
|
1046
|
-
const agentId = agentResult.id;
|
|
1047
|
-
const messageResult = await knex('t_agent_messages')
|
|
1048
|
-
.where('ts', '>', sinceTs)
|
|
1049
|
-
.where((builder) => {
|
|
1050
|
-
builder.where('to_agent_id', agentId)
|
|
1051
|
-
.orWhereNull('to_agent_id');
|
|
1052
|
-
})
|
|
1053
|
-
.count('* as count')
|
|
1054
|
-
.first();
|
|
1055
|
-
messagesCount = messageResult?.count || 0;
|
|
1056
|
-
}
|
|
1057
|
-
// Count file changes since timestamp (project-scoped)
|
|
1058
|
-
const fileResult = await knex('t_file_changes')
|
|
1059
|
-
.where({ project_id: projectId })
|
|
1060
|
-
.where('ts', '>', sinceTs)
|
|
1061
|
-
.count('* as count')
|
|
1062
|
-
.first();
|
|
1063
|
-
const filesCount = fileResult?.count || 0;
|
|
1064
|
-
// Determine if there are any updates
|
|
1065
|
-
const hasUpdatesFlag = decisionsCount > 0 || messagesCount > 0 || filesCount > 0;
|
|
1066
|
-
return {
|
|
1067
|
-
has_updates: hasUpdatesFlag,
|
|
1068
|
-
counts: {
|
|
1069
|
-
decisions: decisionsCount,
|
|
1070
|
-
messages: messagesCount,
|
|
1071
|
-
files: filesCount
|
|
1072
|
-
}
|
|
1073
|
-
};
|
|
1074
|
-
}
|
|
1075
|
-
catch (error) {
|
|
1076
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1077
|
-
throw new Error(`Failed to check for updates: ${message}`);
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
/**
|
|
1081
|
-
* Set decision from template with defaults and required field validation (FR-006)
|
|
1082
|
-
* Applies template defaults while allowing overrides
|
|
1083
|
-
* Validates required fields if template specifies any
|
|
1084
|
-
*
|
|
1085
|
-
* @param params - Template name, key, value, and optional overrides
|
|
1086
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1087
|
-
* @returns Response with success status and applied defaults metadata
|
|
1088
|
-
*/
|
|
1089
|
-
export async function setFromTemplate(params, adapter) {
|
|
1090
|
-
// Validate parameters
|
|
1091
|
-
validateActionParams('decision', 'set_from_template', params);
|
|
1092
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1093
|
-
const knex = actualAdapter.getKnex();
|
|
1094
|
-
// Validate project context
|
|
1095
|
-
const projectId = getProjectContext().getProjectId();
|
|
1096
|
-
try {
|
|
1097
|
-
// Get template (templates are project-scoped)
|
|
1098
|
-
const templateRow = await knex('t_decision_templates')
|
|
1099
|
-
.where({ name: params.template, project_id: projectId })
|
|
1100
|
-
.first();
|
|
1101
|
-
if (!templateRow) {
|
|
1102
|
-
throw new Error(`Template not found: ${params.template}`);
|
|
1103
|
-
}
|
|
1104
|
-
// Parse template defaults
|
|
1105
|
-
const defaults = JSON.parse(templateRow.defaults);
|
|
1106
|
-
// Parse required fields
|
|
1107
|
-
const requiredFields = templateRow.required_fields ? JSON.parse(templateRow.required_fields) : null;
|
|
1108
|
-
// Validate required fields if specified
|
|
1109
|
-
if (requiredFields && requiredFields.length > 0) {
|
|
1110
|
-
for (const field of requiredFields) {
|
|
1111
|
-
if (!(field in params) || params[field] === undefined || params[field] === null) {
|
|
1112
|
-
throw new Error(`Template "${params.template}" requires field: ${field}`);
|
|
1113
|
-
}
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
// Build decision params with template defaults (overridable)
|
|
1117
|
-
const appliedDefaults = {};
|
|
1118
|
-
const decisionParams = {
|
|
1119
|
-
key: params.key,
|
|
1120
|
-
value: params.value,
|
|
1121
|
-
agent: params.agent,
|
|
1122
|
-
layer: params.layer || defaults.layer,
|
|
1123
|
-
version: params.version,
|
|
1124
|
-
status: params.status || defaults.status,
|
|
1125
|
-
tags: params.tags || defaults.tags,
|
|
1126
|
-
scopes: params.scopes
|
|
1127
|
-
};
|
|
1128
|
-
// Track what defaults were applied
|
|
1129
|
-
if (!params.layer && defaults.layer) {
|
|
1130
|
-
appliedDefaults.layer = defaults.layer;
|
|
1131
|
-
}
|
|
1132
|
-
if (!params.tags && defaults.tags) {
|
|
1133
|
-
appliedDefaults.tags = defaults.tags;
|
|
1134
|
-
}
|
|
1135
|
-
if (!params.status && defaults.status) {
|
|
1136
|
-
appliedDefaults.status = defaults.status;
|
|
1137
|
-
}
|
|
1138
|
-
// Call setDecision with merged params (pass adapter if provided)
|
|
1139
|
-
const result = await setDecision(decisionParams, actualAdapter);
|
|
1140
|
-
return {
|
|
1141
|
-
success: result.success,
|
|
1142
|
-
key: result.key,
|
|
1143
|
-
key_id: result.key_id,
|
|
1144
|
-
version: result.version,
|
|
1145
|
-
template_used: params.template,
|
|
1146
|
-
applied_defaults: appliedDefaults,
|
|
1147
|
-
message: `Decision "${params.key}" set successfully using template "${params.template}"`
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
catch (error) {
|
|
1151
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1152
|
-
throw new Error(`Failed to set decision from template: ${message}`);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
/**
|
|
1156
|
-
* Create a new decision template (FR-006)
|
|
1157
|
-
* Defines reusable defaults and required fields for decisions
|
|
1158
|
-
*
|
|
1159
|
-
* @param params - Template name, defaults, required fields, and creator
|
|
1160
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1161
|
-
* @returns Response with success status and template ID
|
|
1162
|
-
*/
|
|
1163
|
-
export async function createTemplate(params, adapter) {
|
|
1164
|
-
// Validate parameters
|
|
1165
|
-
validateActionParams('decision', 'create_template', params);
|
|
1166
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1167
|
-
const knex = actualAdapter.getKnex();
|
|
1168
|
-
// Validate project context (Constraint #29 - fail-fast before mutations)
|
|
1169
|
-
const projectId = getProjectContext().getProjectId();
|
|
1170
|
-
try {
|
|
1171
|
-
return await connectionManager.executeWithRetry(async () => {
|
|
1172
|
-
return await actualAdapter.transaction(async (trx) => {
|
|
1173
|
-
// Validate layer if provided in defaults
|
|
1174
|
-
if (params.defaults.layer) {
|
|
1175
|
-
const layerId = await getLayerId(actualAdapter, params.defaults.layer, trx);
|
|
1176
|
-
if (layerId === null) {
|
|
1177
|
-
throw new Error(`Invalid layer in defaults: ${params.defaults.layer}. Must be one of: presentation, business, data, infrastructure, cross-cutting`);
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
// Validate status if provided in defaults
|
|
1181
|
-
if (params.defaults.status && !STRING_TO_STATUS[params.defaults.status]) {
|
|
1182
|
-
throw new Error(`Invalid status in defaults: ${params.defaults.status}. Must be 'active', 'deprecated', or 'draft'`);
|
|
1183
|
-
}
|
|
1184
|
-
// Get or create agent if creator specified
|
|
1185
|
-
let createdById = null;
|
|
1186
|
-
if (params.created_by) {
|
|
1187
|
-
createdById = await getOrCreateAgent(actualAdapter, params.created_by, trx);
|
|
1188
|
-
}
|
|
1189
|
-
// Serialize defaults and required fields
|
|
1190
|
-
const defaultsJson = JSON.stringify(params.defaults);
|
|
1191
|
-
const requiredFieldsJson = params.required_fields ? JSON.stringify(params.required_fields) : null;
|
|
1192
|
-
// Insert template
|
|
1193
|
-
const [id] = await trx('t_decision_templates').insert({
|
|
1194
|
-
name: params.name,
|
|
1195
|
-
project_id: projectId,
|
|
1196
|
-
defaults: defaultsJson,
|
|
1197
|
-
required_fields: requiredFieldsJson,
|
|
1198
|
-
created_by: createdById
|
|
1199
|
-
});
|
|
1200
|
-
return {
|
|
1201
|
-
success: true,
|
|
1202
|
-
template_id: id,
|
|
1203
|
-
template_name: params.name,
|
|
1204
|
-
message: `Template "${params.name}" created successfully`
|
|
1205
|
-
};
|
|
1206
|
-
});
|
|
1207
|
-
});
|
|
1208
|
-
}
|
|
1209
|
-
catch (error) {
|
|
1210
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1211
|
-
throw new Error(`Failed to create template: ${message}`);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
/**
|
|
1215
|
-
* List all available decision templates (FR-006)
|
|
1216
|
-
* Returns all templates with their defaults and metadata
|
|
1217
|
-
*
|
|
1218
|
-
* @param params - No parameters required
|
|
1219
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1220
|
-
* @returns Array of all templates with parsed JSON fields
|
|
1221
|
-
*/
|
|
1222
|
-
export async function listTemplates(params = {}, adapter) {
|
|
1223
|
-
// Validate parameters
|
|
1224
|
-
validateActionParams('decision', 'list_templates', params);
|
|
1225
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1226
|
-
const knex = actualAdapter.getKnex();
|
|
1227
|
-
// Validate project context
|
|
1228
|
-
const projectId = getProjectContext().getProjectId();
|
|
1229
|
-
try {
|
|
1230
|
-
const rows = await knex('t_decision_templates as t')
|
|
1231
|
-
.leftJoin('m_agents as a', 't.created_by', 'a.id')
|
|
1232
|
-
.where('t.project_id', projectId)
|
|
1233
|
-
.select('t.id', 't.name', 't.defaults', 't.required_fields', 'a.name as created_by', knex.raw(`datetime(t.ts, 'unixepoch') as created_at`))
|
|
1234
|
-
.orderBy('t.name', 'asc');
|
|
1235
|
-
// Parse JSON fields
|
|
1236
|
-
const templates = rows.map(row => ({
|
|
1237
|
-
id: row.id,
|
|
1238
|
-
name: row.name,
|
|
1239
|
-
defaults: JSON.parse(row.defaults),
|
|
1240
|
-
required_fields: row.required_fields ? JSON.parse(row.required_fields) : null,
|
|
1241
|
-
created_by: row.created_by,
|
|
1242
|
-
created_at: row.created_at
|
|
1243
|
-
}));
|
|
1244
|
-
return {
|
|
1245
|
-
templates: templates,
|
|
1246
|
-
count: templates.length
|
|
1247
|
-
};
|
|
1248
|
-
}
|
|
1249
|
-
catch (error) {
|
|
1250
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1251
|
-
throw new Error(`Failed to list templates: ${message}`);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
/**
|
|
1255
|
-
* Permanently delete a decision and all related data (hard delete)
|
|
1256
|
-
* Unlike soft delete (status=deprecated), this removes all records from database
|
|
1257
|
-
*
|
|
1258
|
-
* Use cases:
|
|
1259
|
-
* - Manual cleanup after decision-to-task migration
|
|
1260
|
-
* - Remove test/debug decisions that are no longer needed
|
|
1261
|
-
* - Purge sensitive data that should not be retained
|
|
1262
|
-
*
|
|
1263
|
-
* WARNING: This operation is irreversible. Version history and all relationships
|
|
1264
|
-
* (tags, scopes) will also be deleted due to CASCADE constraints.
|
|
1265
|
-
*
|
|
1266
|
-
* @param params - Decision key to delete
|
|
1267
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1268
|
-
* @returns Response with success status
|
|
1269
|
-
*/
|
|
1270
|
-
export async function hardDeleteDecision(params, adapter) {
|
|
1271
|
-
// Validate parameters
|
|
1272
|
-
validateActionParams('decision', 'hard_delete', params);
|
|
1273
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1274
|
-
const knex = actualAdapter.getKnex();
|
|
1275
|
-
// Validate project context (fail-fast)
|
|
1276
|
-
const projectId = getProjectContext().getProjectId();
|
|
1277
|
-
try {
|
|
1278
|
-
return await connectionManager.executeWithRetry(async () => {
|
|
1279
|
-
return await actualAdapter.transaction(async (trx) => {
|
|
1280
|
-
// Get key_id
|
|
1281
|
-
const keyResult = await trx('m_context_keys')
|
|
1282
|
-
.where({ key: params.key })
|
|
1283
|
-
.first('id');
|
|
1284
|
-
if (!keyResult) {
|
|
1285
|
-
// Key doesn't exist - still return success (idempotent)
|
|
1286
|
-
return {
|
|
1287
|
-
success: true,
|
|
1288
|
-
key: params.key,
|
|
1289
|
-
message: `Decision "${params.key}" not found (already deleted or never existed)`
|
|
1290
|
-
};
|
|
1291
|
-
}
|
|
1292
|
-
const keyId = keyResult.id;
|
|
1293
|
-
// SECURITY: All deletes MUST filter by project_id to prevent cross-project deletion
|
|
1294
|
-
// Delete from t_decisions (if exists in this project)
|
|
1295
|
-
const deletedString = await trx('t_decisions')
|
|
1296
|
-
.where({ key_id: keyId, project_id: projectId })
|
|
1297
|
-
.delete();
|
|
1298
|
-
// Delete from t_decisions_numeric (if exists in this project)
|
|
1299
|
-
const deletedNumeric = await trx('t_decisions_numeric')
|
|
1300
|
-
.where({ key_id: keyId, project_id: projectId })
|
|
1301
|
-
.delete();
|
|
1302
|
-
// Delete from t_decision_history (for this project only)
|
|
1303
|
-
const deletedHistory = await trx('t_decision_history')
|
|
1304
|
-
.where({ key_id: keyId, project_id: projectId })
|
|
1305
|
-
.delete();
|
|
1306
|
-
// Delete from t_decision_tags (for this project only)
|
|
1307
|
-
const deletedTags = await trx('t_decision_tags')
|
|
1308
|
-
.where({ decision_key_id: keyId, project_id: projectId })
|
|
1309
|
-
.delete();
|
|
1310
|
-
// Delete from t_decision_scopes (for this project only)
|
|
1311
|
-
const deletedScopes = await trx('t_decision_scopes')
|
|
1312
|
-
.where({ decision_key_id: keyId, project_id: projectId })
|
|
1313
|
-
.delete();
|
|
1314
|
-
// Calculate total deleted records
|
|
1315
|
-
const totalDeleted = deletedString + deletedNumeric + deletedHistory + deletedTags + deletedScopes;
|
|
1316
|
-
if (totalDeleted === 0) {
|
|
1317
|
-
return {
|
|
1318
|
-
success: true,
|
|
1319
|
-
key: params.key,
|
|
1320
|
-
message: `Decision "${params.key}" not found (already deleted or never existed)`
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
return {
|
|
1324
|
-
success: true,
|
|
1325
|
-
key: params.key,
|
|
1326
|
-
message: `Decision "${params.key}" permanently deleted (${totalDeleted} record${totalDeleted === 1 ? '' : 's'})`
|
|
1327
|
-
};
|
|
1328
|
-
});
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
catch (error) {
|
|
1332
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1333
|
-
throw new Error(`Failed to hard delete decision: ${message}`);
|
|
1334
|
-
}
|
|
1335
|
-
}
|
|
1336
|
-
// ============================================================================
|
|
1337
|
-
// Decision Context Actions (v3.2.2)
|
|
1338
|
-
// ============================================================================
|
|
1339
|
-
/**
|
|
1340
|
-
* Add decision context action
|
|
1341
|
-
* Adds rich context (rationale, alternatives, tradeoffs) to a decision
|
|
1342
|
-
*
|
|
1343
|
-
* @param params - Context parameters
|
|
1344
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1345
|
-
* @returns Response with success status
|
|
1346
|
-
*/
|
|
1347
|
-
export async function addDecisionContextAction(params, adapter) {
|
|
1348
|
-
// Validate parameters
|
|
1349
|
-
validateActionParams('decision', 'add_decision_context', params);
|
|
1350
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1351
|
-
try {
|
|
1352
|
-
// Parse JSON if provided as strings
|
|
1353
|
-
let alternatives = params.alternatives_considered || null;
|
|
1354
|
-
let tradeoffs = params.tradeoffs || null;
|
|
1355
|
-
// Convert to JSON strings
|
|
1356
|
-
if (alternatives !== null) {
|
|
1357
|
-
if (typeof alternatives === 'object') {
|
|
1358
|
-
alternatives = JSON.stringify(alternatives);
|
|
1359
|
-
}
|
|
1360
|
-
else if (typeof alternatives === 'string') {
|
|
1361
|
-
try {
|
|
1362
|
-
JSON.parse(alternatives);
|
|
1363
|
-
}
|
|
1364
|
-
catch {
|
|
1365
|
-
alternatives = JSON.stringify([alternatives]);
|
|
1366
|
-
}
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
if (tradeoffs !== null) {
|
|
1370
|
-
if (typeof tradeoffs === 'object') {
|
|
1371
|
-
tradeoffs = JSON.stringify(tradeoffs);
|
|
1372
|
-
}
|
|
1373
|
-
else if (typeof tradeoffs === 'string') {
|
|
1374
|
-
try {
|
|
1375
|
-
JSON.parse(tradeoffs);
|
|
1376
|
-
}
|
|
1377
|
-
catch {
|
|
1378
|
-
tradeoffs = JSON.stringify({ description: tradeoffs });
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
const contextId = await dbAddDecisionContext(actualAdapter, params.key, params.rationale, alternatives, tradeoffs, params.decided_by || null, params.related_task_id || null, params.related_constraint_id || null);
|
|
1383
|
-
return {
|
|
1384
|
-
success: true,
|
|
1385
|
-
context_id: contextId,
|
|
1386
|
-
decision_key: params.key,
|
|
1387
|
-
message: `Decision context added successfully to "${params.key}"`
|
|
1388
|
-
};
|
|
1389
|
-
}
|
|
1390
|
-
catch (error) {
|
|
1391
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1392
|
-
throw new Error(`Failed to add decision context: ${message}`);
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
/**
|
|
1396
|
-
* List decision contexts action
|
|
1397
|
-
* Query decision contexts with optional filters
|
|
1398
|
-
*
|
|
1399
|
-
* @param params - Filter parameters
|
|
1400
|
-
* @param adapter - Optional database adapter (for testing)
|
|
1401
|
-
* @returns Array of decision contexts
|
|
1402
|
-
*/
|
|
1403
|
-
export async function listDecisionContextsAction(params, adapter) {
|
|
1404
|
-
// Validate parameters
|
|
1405
|
-
validateActionParams('decision', 'list_decision_contexts', params);
|
|
1406
|
-
const actualAdapter = adapter ?? getAdapter();
|
|
1407
|
-
try {
|
|
1408
|
-
const contexts = await dbListDecisionContexts(actualAdapter, {
|
|
1409
|
-
decisionKey: params.decision_key,
|
|
1410
|
-
relatedTaskId: params.related_task_id,
|
|
1411
|
-
relatedConstraintId: params.related_constraint_id,
|
|
1412
|
-
decidedBy: params.decided_by,
|
|
1413
|
-
limit: params.limit || 50,
|
|
1414
|
-
offset: params.offset || 0
|
|
1415
|
-
});
|
|
1416
|
-
return {
|
|
1417
|
-
success: true,
|
|
1418
|
-
contexts: contexts.map(ctx => ({
|
|
1419
|
-
...ctx,
|
|
1420
|
-
// Parse JSON fields for display
|
|
1421
|
-
alternatives_considered: ctx.alternatives_considered ? JSON.parse(ctx.alternatives_considered) : null,
|
|
1422
|
-
tradeoffs: ctx.tradeoffs ? JSON.parse(ctx.tradeoffs) : null
|
|
1423
|
-
})),
|
|
1424
|
-
count: contexts.length
|
|
1425
|
-
};
|
|
1426
|
-
}
|
|
1427
|
-
catch (error) {
|
|
1428
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1429
|
-
throw new Error(`Failed to list decision contexts: ${message}`);
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
/**
|
|
1433
|
-
* Help action for decision tool
|
|
1434
|
-
*/
|
|
1435
|
-
export function decisionHelp() {
|
|
1436
|
-
return {
|
|
1437
|
-
tool: 'decision',
|
|
1438
|
-
description: 'Manage decisions with metadata (tags, layers, versions, scopes)',
|
|
1439
|
-
note: '💡 TIP: Use action: "example" to see comprehensive usage scenarios and real-world examples for all decision actions.',
|
|
1440
|
-
purpose: {
|
|
1441
|
-
title: '⚠️ CRITICAL: Store WHY and REASON, Not WHAT',
|
|
1442
|
-
principle: 'Decisions table is for ARCHITECTURAL CONTEXT and REASONING, NOT implementation logs or task completion status',
|
|
1443
|
-
what_to_store: {
|
|
1444
|
-
correct: [
|
|
1445
|
-
'WHY a design choice was made (e.g., "Chose JWT over sessions because stateless auth scales better for our microservice architecture")',
|
|
1446
|
-
'REASONING behind architecture decisions (e.g., "Moved oscillator_type to MonophonicSynthConfig to separate synthesis methods - FM operators use different config")',
|
|
1447
|
-
'PROBLEM ANALYSIS and solution rationale (e.g., "Nested transaction bug: setDecision wraps in transaction, batch also wraps → solution: extract internal helper without transaction wrapper")',
|
|
1448
|
-
'DESIGN TRADE-OFFS and alternatives considered (e.g., "Query builder limited to simple filters, kept domain-specific logic inline for maintainability")',
|
|
1449
|
-
'CONSTRAINTS and requirements reasoning (e.g., "API response must be <100ms because mobile clients timeout at 200ms")',
|
|
1450
|
-
'BREAKING CHANGES with migration rationale (e.g., "Removed /v1/users endpoint - clients must use /v2/users with pagination for scalability")'
|
|
1451
|
-
],
|
|
1452
|
-
incorrect: [
|
|
1453
|
-
'❌ Task completion logs (e.g., "Task 5 completed", "Refactoring done", "Tests passing") → Use tasks tool instead',
|
|
1454
|
-
'❌ Implementation status (e.g., "Added validators.ts", "Fixed bug in batch_create", "Updated README") → These are WHAT, not WHY',
|
|
1455
|
-
'❌ Test results (e.g., "All tests passing", "Integration tests complete", "v3.0.2 testing verified") → Temporary status, not architectural context',
|
|
1456
|
-
'❌ Git commit summaries (e.g., "Released v3.0.2", "Created git commit 2bf55a0") → Belongs in git history',
|
|
1457
|
-
'❌ Documentation updates (e.g., "README reorganized", "Help actions enhanced") → Implementation logs, not decisions',
|
|
1458
|
-
'❌ Build status (e.g., "Build succeeded", "TypeScript compiled with zero errors") → Temporary status'
|
|
1459
|
-
]
|
|
1460
|
-
},
|
|
1461
|
-
analogy: {
|
|
1462
|
-
git_history: 'WHAT changed (files, lines, commits)',
|
|
1463
|
-
code_comments: 'HOW it works (implementation details, algorithms)',
|
|
1464
|
-
sqlew_decisions: 'WHY it was changed (reasoning, trade-offs, context)',
|
|
1465
|
-
sqlew_tasks: 'WHAT needs to be done (work items, status, completion)'
|
|
1466
|
-
},
|
|
1467
|
-
examples: [
|
|
1468
|
-
{
|
|
1469
|
-
key: 'api/auth/jwt-choice',
|
|
1470
|
-
value: 'Chose JWT over session-based auth because: (1) Stateless design scales horizontally, (2) Mobile clients can cache tokens, (3) Microservice architecture requires distributed auth. Trade-off: Revocation requires token blacklist, but acceptable for 15-min token lifetime.',
|
|
1471
|
-
explanation: 'Explains WHY JWT was chosen, considers trade-offs, provides architectural context'
|
|
1472
|
-
},
|
|
1473
|
-
{
|
|
1474
|
-
key: 'database/postgresql-choice',
|
|
1475
|
-
value: 'Selected PostgreSQL over MongoDB because: (1) Complex relational queries required for reporting, (2) ACID compliance critical for financial data, (3) Team has strong SQL expertise. Trade-off: Less flexible schema, but data integrity more important than schema flexibility for our use case.',
|
|
1476
|
-
explanation: 'Documents database choice with reasoning, alternatives considered, and trade-offs'
|
|
1477
|
-
},
|
|
1478
|
-
{
|
|
1479
|
-
key: 'security/encryption-at-rest',
|
|
1480
|
-
value: 'Implementing AES-256 encryption for all PII in database because: (1) GDPR compliance requires encryption at rest, (2) Recent security audit identified unencrypted sensitive data, (3) Performance impact <5ms per query acceptable. Alternative considered: Database-level encryption rejected due to backup/restore complexity.',
|
|
1481
|
-
explanation: 'Explains security decision with compliance reasoning and performance considerations'
|
|
1482
|
-
}
|
|
1483
|
-
],
|
|
1484
|
-
cleanup_rule: 'Delete decisions that start with "COMPLETED:", contain task status, test results, or implementation logs. Keep only architectural reasoning and design rationale.'
|
|
1485
|
-
},
|
|
1486
|
-
actions: {
|
|
1487
|
-
set: 'Set/update a decision. Params: key (required), value (required), agent, layer, version, status, tags, scopes',
|
|
1488
|
-
get: 'Get specific decision by key. Params: key (required), include_context (optional, boolean, default: false). When include_context=true, returns decision with attached context (rationale, alternatives, tradeoffs). Backward compatible - omitting flag returns standard decision format.',
|
|
1489
|
-
list: 'List/filter decisions. Params: status, layer, tags, scope, tag_match',
|
|
1490
|
-
search_tags: 'Search decisions by tags. Params: tags (required), match_mode, status, layer',
|
|
1491
|
-
search_layer: 'Search decisions by layer. Params: layer (required), status, include_tags',
|
|
1492
|
-
versions: 'Get version history for a decision. Params: key (required)',
|
|
1493
|
-
quick_set: 'Quick set with smart defaults (FR-002). Params: key (required), value (required), agent, layer, version, status, tags, scopes. Auto-infers layer from key prefix (api/*→presentation, db/*→data, service/*→business, config/*→infrastructure), tags from key hierarchy, scope from parent path. Defaults: status=active, version=1.0.0. All inferred fields can be overridden.',
|
|
1494
|
-
search_advanced: 'Advanced query with complex filtering (FR-004). Params: layers (OR), tags_all (AND), tags_any (OR), exclude_tags, scopes (wildcards), updated_after/before (ISO or relative like "7d"), decided_by, statuses, search_text, sort_by (updated/key/version), sort_order (asc/desc), limit (default:20, max:1000), offset (default:0). Returns decisions with total_count for pagination. All filters use parameterized queries (SQL injection protection).',
|
|
1495
|
-
set_batch: 'Batch set decisions (FR-005). Params: decisions (required, array of SetDecisionParams, max: 50), atomic (optional, boolean, default: true). Returns: {success, inserted, failed, results}. ATOMIC MODE BEHAVIOR (atomic: true): All decisions succeed or all fail as a single transaction. If ANY decision fails, entire batch is rolled back and error is thrown. Use for critical operations requiring consistency. NON-ATOMIC MODE (atomic: false): Each decision is processed independently. If some fail, others still succeed. Returns partial results with per-item success/error status. Use for best-effort batch operations or when individual failures are acceptable. RECOMMENDATION FOR AI AGENTS: Use atomic:false by default to avoid transaction failures from validation errors or malformed data. Only use atomic:true when all-or-nothing guarantee is required. 52% token reduction vs individual calls.',
|
|
1496
|
-
has_updates: 'Check for updates since timestamp (FR-003 Phase A - Lightweight Polling). Params: agent_name (required), since_timestamp (required, ISO 8601 format like "2025-10-14T08:00:00Z"). Returns: {has_updates: boolean, counts: {decisions: N, messages: N, files: N}}. Token cost: ~5-10 tokens per check. Uses COUNT queries on t_decisions, t_agent_messages, t_file_changes with timestamp filtering. Enables efficient polling without full data retrieval.',
|
|
1497
|
-
set_from_template: 'Set decision using template (FR-006). Params: template (required, template name), key (required), value (required), agent, layer (override), version, status (override), tags (override), scopes, plus any template-required fields. Applies template defaults (layer, status, tags) while allowing overrides. Validates required fields if specified by template. Returns: {success, key, key_id, version, template_used, applied_defaults, message}. Built-in templates: breaking_change, security_vulnerability, performance_optimization, deprecation, architecture_decision.',
|
|
1498
|
-
create_template: 'Create new decision template (FR-006). Params: name (required, unique), defaults (required, object with layer/status/tags/priority), required_fields (optional, array of field names), created_by (optional, agent name). Returns: {success, template_id, template_name, message}. Example defaults: {"layer":"business","status":"active","tags":["breaking"]}. Validates layer/status values.',
|
|
1499
|
-
list_templates: 'List all decision templates (FR-006). No params required. Returns: {templates: [{id, name, defaults, required_fields, created_by, created_at}], count}. Shows both built-in and custom templates.',
|
|
1500
|
-
hard_delete: 'Permanently delete a decision (hard delete). Params: key (required). WARNING: IRREVERSIBLE - removes all records including version history, tags, scopes. Use cases: manual cleanup after decision-to-task migration, remove test/debug decisions, purge sensitive data. Unlike soft delete (status=deprecated), this completely removes from database. Idempotent - safe to call even if already deleted. Returns: {success, key, message}.',
|
|
1501
|
-
add_decision_context: 'Add rich context to a decision (v3.2.2). Params: key (required), rationale (required), alternatives_considered (optional, JSON array), tradeoffs (optional, JSON object with pros/cons), decided_by (optional), related_task_id (optional), related_constraint_id (optional). Use to document WHY decisions were made, what alternatives were considered, and trade-offs. Multiple contexts can be attached to the same decision over time. Returns: {success, context_id, decision_key, message}.',
|
|
1502
|
-
list_decision_contexts: 'List decision contexts with filters (v3.2.2). Params: decision_key (optional), related_task_id (optional), related_constraint_id (optional), decided_by (optional), limit (default: 50), offset (default: 0). Returns: {success, contexts: [{id, decision_key, rationale, alternatives_considered, tradeoffs, decided_by, decision_date, related_task_id, related_constraint_id}], count}. JSON fields (alternatives, tradeoffs) are automatically parsed.'
|
|
1503
|
-
},
|
|
1504
|
-
examples: {
|
|
1505
|
-
set: '{ action: "set", key: "auth_method", value: "jwt", tags: ["security"] }',
|
|
1506
|
-
get: '{ action: "get", key: "auth_method" }',
|
|
1507
|
-
list: '{ action: "list", status: "active", layer: "infrastructure" }',
|
|
1508
|
-
search_tags: '{ action: "search_tags", tags: ["security", "api"] }',
|
|
1509
|
-
quick_set: '{ action: "quick_set", key: "api/instruments/oscillator-refactor", value: "Moved oscillator_type to MonophonicSynthConfig" }',
|
|
1510
|
-
search_advanced: '{ action: "search_advanced", layers: ["business", "data"], tags_all: ["breaking", "v0.3.3"], tags_any: ["api", "synthesis"], exclude_tags: ["deprecated"], scopes: ["api/instruments/*"], updated_after: "2025-10-01", statuses: ["active", "draft"], search_text: "oscillator", sort_by: "updated", sort_order: "desc", limit: 20, offset: 0 }',
|
|
1511
|
-
set_batch: '{ action: "set_batch", decisions: [{"key": "feat-1", "value": "...", "layer": "business"}, {"key": "feat-2", "value": "...", "layer": "data"}], atomic: true }',
|
|
1512
|
-
has_updates: '{ action: "has_updates", agent_name: "my-agent", since_timestamp: "2025-10-14T08:00:00Z" }',
|
|
1513
|
-
set_from_template: '{ action: "set_from_template", template: "breaking_change", key: "oscillator-type-moved", value: "oscillator_type moved to MonophonicSynthConfig" }',
|
|
1514
|
-
create_template: '{ action: "create_template", name: "bug_fix", defaults: {"layer":"business","tags":["bug","fix"],"status":"active"}, created_by: "my-agent" }',
|
|
1515
|
-
list_templates: '{ action: "list_templates" }',
|
|
1516
|
-
hard_delete: '{ action: "hard_delete", key: "task_old_authentication_refactor" }'
|
|
1517
|
-
},
|
|
1518
|
-
documentation: {
|
|
1519
|
-
tool_selection: 'docs/TOOL_SELECTION.md - Decision tree, tool comparison, when to use each tool (236 lines, ~12k tokens)',
|
|
1520
|
-
tool_reference: 'docs/TOOL_REFERENCE.md - Parameter requirements, batch operations, templates (471 lines, ~24k tokens)',
|
|
1521
|
-
workflows: 'docs/WORKFLOWS.md - Multi-step workflow examples, multi-agent coordination (602 lines, ~30k tokens)',
|
|
1522
|
-
best_practices: 'docs/BEST_PRACTICES.md - Common errors, best practices, troubleshooting (345 lines, ~17k tokens)',
|
|
1523
|
-
shared_concepts: 'docs/SHARED_CONCEPTS.md - Layer definitions, enum values (status/layer/priority), atomic mode (339 lines, ~17k tokens)'
|
|
1524
|
-
}
|
|
1525
|
-
};
|
|
1526
|
-
}
|
|
1527
|
-
/**
|
|
1528
|
-
* Example action for decision tool
|
|
1529
|
-
*/
|
|
1530
|
-
export function decisionExample() {
|
|
1531
|
-
return {
|
|
1532
|
-
tool: 'decision',
|
|
1533
|
-
description: 'Comprehensive decision tool examples without needing WebFetch access',
|
|
1534
|
-
scenarios: {
|
|
1535
|
-
basic_usage: {
|
|
1536
|
-
title: 'Basic Decision Management',
|
|
1537
|
-
examples: [
|
|
1538
|
-
{
|
|
1539
|
-
scenario: 'Record API design decision',
|
|
1540
|
-
request: '{ action: "set", key: "api_auth_method", value: "JWT with refresh tokens", layer: "business", tags: ["api", "security", "authentication"] }',
|
|
1541
|
-
explanation: 'Documents the choice of authentication method for the API'
|
|
1542
|
-
},
|
|
1543
|
-
{
|
|
1544
|
-
scenario: 'Retrieve a decision',
|
|
1545
|
-
request: '{ action: "get", key: "api_auth_method" }',
|
|
1546
|
-
response_structure: '{ key, value, layer, status, version, tags, scopes, decided_by, updated_at }'
|
|
1547
|
-
},
|
|
1548
|
-
{
|
|
1549
|
-
scenario: 'List all active decisions',
|
|
1550
|
-
request: '{ action: "list", status: "active", limit: 20 }',
|
|
1551
|
-
explanation: 'Returns active decisions with metadata for browsing'
|
|
1552
|
-
}
|
|
1553
|
-
]
|
|
1554
|
-
},
|
|
1555
|
-
advanced_filtering: {
|
|
1556
|
-
title: 'Advanced Search and Filtering',
|
|
1557
|
-
examples: [
|
|
1558
|
-
{
|
|
1559
|
-
scenario: 'Find all security-related decisions in business layer',
|
|
1560
|
-
request: '{ action: "search_advanced", layers: ["business"], tags_any: ["security", "authentication"], status: ["active"], sort_by: "updated", sort_order: "desc" }',
|
|
1561
|
-
explanation: 'Combines layer filtering, tag matching, and sorting'
|
|
1562
|
-
},
|
|
1563
|
-
{
|
|
1564
|
-
scenario: 'Search within API scope with multiple tags',
|
|
1565
|
-
request: '{ action: "search_advanced", scopes: ["api/*"], tags_all: ["breaking", "v2.0"], updated_after: "2025-01-01" }',
|
|
1566
|
-
explanation: 'Uses scope wildcards and timestamp filtering for recent breaking changes'
|
|
1567
|
-
}
|
|
1568
|
-
]
|
|
1569
|
-
},
|
|
1570
|
-
versioning_workflow: {
|
|
1571
|
-
title: 'Version Management',
|
|
1572
|
-
steps: [
|
|
1573
|
-
{
|
|
1574
|
-
step: 1,
|
|
1575
|
-
action: 'Create initial decision',
|
|
1576
|
-
request: '{ action: "set", key: "database_choice", value: "PostgreSQL", layer: "data", version: "1.0.0", tags: ["database"] }'
|
|
1577
|
-
},
|
|
1578
|
-
{
|
|
1579
|
-
step: 2,
|
|
1580
|
-
action: 'Update decision (creates new version)',
|
|
1581
|
-
request: '{ action: "set", key: "database_choice", value: "PostgreSQL with read replicas", layer: "data", version: "1.1.0", tags: ["database", "scaling"] }'
|
|
1582
|
-
},
|
|
1583
|
-
{
|
|
1584
|
-
step: 3,
|
|
1585
|
-
action: 'View version history',
|
|
1586
|
-
request: '{ action: "versions", key: "database_choice" }',
|
|
1587
|
-
result: 'Returns all versions with timestamps and changes'
|
|
1588
|
-
}
|
|
1589
|
-
]
|
|
1590
|
-
},
|
|
1591
|
-
batch_operations: {
|
|
1592
|
-
title: 'Batch Decision Management',
|
|
1593
|
-
examples: [
|
|
1594
|
-
{
|
|
1595
|
-
scenario: 'Record multiple related decisions atomically',
|
|
1596
|
-
request: '{ action: "set_batch", decisions: [{"key": "cache_layer", "value": "Redis", "layer": "infrastructure"}, {"key": "cache_ttl", "value": "3600", "layer": "infrastructure"}], atomic: true }',
|
|
1597
|
-
explanation: 'All decisions succeed or all fail together (atomic mode)'
|
|
1598
|
-
},
|
|
1599
|
-
{
|
|
1600
|
-
scenario: 'Best-effort batch insert',
|
|
1601
|
-
request: '{ action: "set_batch", decisions: [{...}, {...}, {...}], atomic: false }',
|
|
1602
|
-
explanation: 'Each decision processed independently - partial success allowed'
|
|
1603
|
-
}
|
|
1604
|
-
]
|
|
1605
|
-
},
|
|
1606
|
-
templates: {
|
|
1607
|
-
title: 'Using Decision Templates',
|
|
1608
|
-
examples: [
|
|
1609
|
-
{
|
|
1610
|
-
scenario: 'Use built-in breaking_change template',
|
|
1611
|
-
request: '{ action: "set_from_template", template: "breaking_change", key: "api_remove_legacy_endpoint", value: "Removed /v1/users endpoint - migrate to /v2/users" }',
|
|
1612
|
-
explanation: 'Automatically applies layer=business, tags=["breaking"], status=active'
|
|
1613
|
-
},
|
|
1614
|
-
{
|
|
1615
|
-
scenario: 'Create custom template',
|
|
1616
|
-
request: '{ action: "create_template", name: "feature_flag", defaults: {"layer": "presentation", "tags": ["feature-flag"], "status": "draft"}, created_by: "backend-team" }',
|
|
1617
|
-
explanation: 'Define reusable templates for common decision patterns'
|
|
1618
|
-
}
|
|
1619
|
-
]
|
|
1620
|
-
},
|
|
1621
|
-
quick_set_inference: {
|
|
1622
|
-
title: 'Quick Set with Smart Defaults',
|
|
1623
|
-
examples: [
|
|
1624
|
-
{
|
|
1625
|
-
scenario: 'Auto-infer layer from key prefix',
|
|
1626
|
-
request: '{ action: "quick_set", key: "api/instruments/oscillator-refactor", value: "Moved oscillator_type to MonophonicSynthConfig" }',
|
|
1627
|
-
inferred: 'layer=presentation (from api/*), tags=["instruments", "oscillator-refactor"], scope=api/instruments'
|
|
1628
|
-
},
|
|
1629
|
-
{
|
|
1630
|
-
scenario: 'Database decision with auto-inference',
|
|
1631
|
-
request: '{ action: "quick_set", key: "db/users/add-email-index", value: "Added index on email column" }',
|
|
1632
|
-
inferred: 'layer=data (from db/*), tags=["users", "add-email-index"]'
|
|
1633
|
-
}
|
|
1634
|
-
]
|
|
1635
|
-
}
|
|
1636
|
-
},
|
|
1637
|
-
best_practices: {
|
|
1638
|
-
key_naming: [
|
|
1639
|
-
'Use hierarchical keys: "api/users/authentication"',
|
|
1640
|
-
'Prefix with layer hint: api/* → presentation, db/* → data, service/* → business',
|
|
1641
|
-
'Use descriptive names that explain the decision context'
|
|
1642
|
-
],
|
|
1643
|
-
tagging: [
|
|
1644
|
-
'Tag with relevant categories: security, performance, breaking, etc.',
|
|
1645
|
-
'Include version tags for release-specific decisions',
|
|
1646
|
-
'Use consistent tag naming conventions across team'
|
|
1647
|
-
],
|
|
1648
|
-
versioning: [
|
|
1649
|
-
'Use semantic versioning: 1.0.0, 1.1.0, 2.0.0',
|
|
1650
|
-
'Increment major version for breaking changes',
|
|
1651
|
-
'Document rationale in decision value text'
|
|
1652
|
-
],
|
|
1653
|
-
cleanup: [
|
|
1654
|
-
'Mark deprecated decisions with status="deprecated"',
|
|
1655
|
-
'Use hard_delete only for sensitive data or migration cleanup',
|
|
1656
|
-
'Link related decisions using scopes'
|
|
1657
|
-
]
|
|
1658
|
-
}
|
|
1659
|
-
};
|
|
1660
|
-
}
|
|
1661
|
-
//# sourceMappingURL=context.js.map
|