sdlc-agent-4-enterprise-server 1.21.0 → 1.22.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/dist/config/CoreTools.js +1 -1
- package/dist/config/CoreTools.js.map +1 -1
- package/dist/engine/graph/__tests__/code-edge-extractor.test.d.ts +6 -0
- package/dist/engine/graph/__tests__/code-edge-extractor.test.js +116 -0
- package/dist/engine/graph/__tests__/code-edge-extractor.test.js.map +1 -0
- package/dist/engine/graph/code-edge-extractor.d.ts +38 -0
- package/dist/engine/graph/code-edge-extractor.js +89 -0
- package/dist/engine/graph/code-edge-extractor.js.map +1 -0
- package/dist/engine/graph/graph-sync-service.d.ts +2 -0
- package/dist/engine/graph/graph-sync-service.js +15 -0
- package/dist/engine/graph/graph-sync-service.js.map +1 -1
- package/dist/modules/memory/__tests__/edge-on-ingest.test.d.ts +6 -0
- package/dist/modules/memory/__tests__/edge-on-ingest.test.js +115 -0
- package/dist/modules/memory/__tests__/edge-on-ingest.test.js.map +1 -0
- package/dist/modules/memory/__tests__/graph-fallback.test.d.ts +6 -0
- package/dist/modules/memory/__tests__/graph-fallback.test.js +169 -0
- package/dist/modules/memory/__tests__/graph-fallback.test.js.map +1 -0
- package/dist/modules/memory/dispatchers/graph-fallback.d.ts +35 -0
- package/dist/modules/memory/dispatchers/graph-fallback.js +118 -0
- package/dist/modules/memory/dispatchers/graph-fallback.js.map +1 -0
- package/dist/modules/memory/dispatchers/search.js +26 -1
- package/dist/modules/memory/dispatchers/search.js.map +1 -1
- package/dist/modules/memory/engine/crud.js +16 -0
- package/dist/modules/memory/engine/crud.js.map +1 -1
- package/dist/modules/memory/engine/edge-on-ingest.d.ts +54 -0
- package/dist/modules/memory/engine/edge-on-ingest.js +113 -0
- package/dist/modules/memory/engine/edge-on-ingest.js.map +1 -0
- package/dist/modules/pega/PegaHashCache.d.ts +45 -0
- package/dist/modules/pega/PegaHashCache.js +57 -0
- package/dist/modules/pega/PegaHashCache.js.map +1 -0
- package/dist/modules/pega/PegaIndexerHelpers.d.ts +28 -0
- package/dist/modules/pega/PegaIndexerHelpers.js +100 -0
- package/dist/modules/pega/PegaIndexerHelpers.js.map +1 -0
- package/dist/modules/pega/PegaIndexerTool.d.ts +69 -0
- package/dist/modules/pega/PegaIndexerTool.js +144 -0
- package/dist/modules/pega/PegaIndexerTool.js.map +1 -0
- package/dist/modules/pega/__tests__/PegaIndexerTool.test.d.ts +5 -0
- package/dist/modules/pega/__tests__/PegaIndexerTool.test.js +208 -0
- package/dist/modules/pega/__tests__/PegaIndexerTool.test.js.map +1 -0
- package/dist/modules/pega/scripts/__tests__/populate-graph-edges.test.d.ts +5 -0
- package/dist/modules/pega/scripts/__tests__/populate-graph-edges.test.js +232 -0
- package/dist/modules/pega/scripts/__tests__/populate-graph-edges.test.js.map +1 -0
- package/dist/modules/pega/scripts/edge-extractors.d.ts +53 -0
- package/dist/modules/pega/scripts/edge-extractors.js +187 -0
- package/dist/modules/pega/scripts/edge-extractors.js.map +1 -0
- package/dist/modules/pega/scripts/populate-graph-edges.d.ts +30 -0
- package/dist/modules/pega/scripts/populate-graph-edges.js +125 -0
- package/dist/modules/pega/scripts/populate-graph-edges.js.map +1 -0
- package/package.json +1 -1
- package/src/config/CoreTools.ts +1 -1
- package/src/engine/graph/__tests__/code-edge-extractor.test.ts +147 -0
- package/src/engine/graph/code-edge-extractor.ts +123 -0
- package/src/engine/graph/graph-sync-service.ts +17 -0
- package/src/modules/memory/__tests__/edge-on-ingest.test.ts +166 -0
- package/src/modules/memory/__tests__/graph-fallback.test.ts +210 -0
- package/src/modules/memory/dispatchers/graph-fallback.ts +150 -0
- package/src/modules/memory/dispatchers/search.ts +29 -1
- package/src/modules/memory/engine/crud.ts +16 -0
- package/src/modules/memory/engine/edge-on-ingest.ts +159 -0
- package/src/modules/pega/PegaHashCache.ts +83 -0
- package/src/modules/pega/PegaIndexerHelpers.ts +95 -0
- package/src/modules/pega/PegaIndexerTool.ts +200 -0
- package/src/modules/pega/__tests__/PegaIndexerTool.test.ts +271 -0
- package/src/modules/pega/scripts/__tests__/populate-graph-edges.test.ts +270 -0
- package/src/modules/pega/scripts/edge-extractors.ts +219 -0
- package/src/modules/pega/scripts/populate-graph-edges.ts +155 -0
- package/tests/integration/mcp-tools.test.ts +25 -5
- package/tests/vitest.setup.ts +6 -0
- package/documents/ARCHITECTURE.md +0 -1043
- package/documents/ARCHITECTURE.pdf +0 -0
- package/documents/Architecture-v2.md +0 -165
- package/documents/Architecture-v3.md +0 -99
- package/documents/Architecture-v4.md +0 -122
- package/documents/Architecture-v5.md +0 -140
- package/documents/Architecture-v6.md +0 -94
- package/documents/F1-memory-kb/BRD.md +0 -597
- package/documents/F1-memory-kb/FSD.md +0 -756
- package/documents/F1-memory-kb/STATUS.json +0 -43
- package/documents/F1-memory-kb/TDD.md +0 -453
- package/documents/F10-hook-system/BRD.md +0 -434
- package/documents/F10-hook-system/FSD.md +0 -715
- package/documents/F10-hook-system/STATUS.json +0 -43
- package/documents/F10-hook-system/TDD.md +0 -642
- package/documents/F11-webview-panels/BRD.md +0 -432
- package/documents/F11-webview-panels/FSD.md +0 -669
- package/documents/F11-webview-panels/STATUS.json +0 -43
- package/documents/F11-webview-panels/TDD.md +0 -468
- package/documents/F12-backend-connection/BRD.md +0 -479
- package/documents/F12-backend-connection/FSD.md +0 -622
- package/documents/F12-backend-connection/STATUS.json +0 -43
- package/documents/F12-backend-connection/TDD.md +0 -386
- package/documents/F2-code-intelligence/BRD.md +0 -604
- package/documents/F2-code-intelligence/FSD.md +0 -492
- package/documents/F2-code-intelligence/STATUS.json +0 -43
- package/documents/F2-code-intelligence/TDD.md +0 -486
- package/documents/F3-orchestration/BRD.md +0 -527
- package/documents/F3-orchestration/FSD.md +0 -686
- package/documents/F3-orchestration/STATUS.json +0 -43
- package/documents/F3-orchestration/TDD.md +0 -477
- package/documents/F4-context-assembly/BRD.md +0 -448
- package/documents/F4-context-assembly/FSD.md +0 -372
- package/documents/F4-context-assembly/STATUS.json +0 -43
- package/documents/F4-context-assembly/TDD.md +0 -338
- package/documents/F5-incremental-indexer/BRD.md +0 -472
- package/documents/F5-incremental-indexer/FSD.md +0 -800
- package/documents/F5-incremental-indexer/STATUS.json +0 -16
- package/documents/F5-incremental-indexer/TDD.md +0 -628
- package/documents/F6-drawio-engine/BRD.md +0 -365
- package/documents/F6-drawio-engine/FSD.md +0 -1100
- package/documents/F6-drawio-engine/STATUS.json +0 -43
- package/documents/F6-drawio-engine/TDD.md +0 -581
- package/documents/F7-langgraph-pipeline/BRD.md +0 -520
- package/documents/F7-langgraph-pipeline/FSD.md +0 -597
- package/documents/F7-langgraph-pipeline/STATUS.json +0 -43
- package/documents/F7-langgraph-pipeline/TDD.md +0 -421
- package/documents/F8-chat-panel/BRD.md +0 -479
- package/documents/F8-chat-panel/FSD.md +0 -719
- package/documents/F8-chat-panel/STATUS.json +0 -43
- package/documents/F8-chat-panel/TDD.md +0 -459
- package/documents/F9-auth-sso/BRD.md +0 -356
- package/documents/F9-auth-sso/FSD.md +0 -663
- package/documents/F9-auth-sso/STATUS.json +0 -43
- package/documents/F9-auth-sso/TDD.md +0 -708
- package/documents/FAILURE-MODES.md +0 -112
- package/documents/GRAPH-EMAIL/BRD.md +0 -488
- package/documents/GRAPH-EMAIL/FSD.md +0 -558
- package/documents/GRAPH-EMAIL/STATUS.json +0 -25
- package/documents/GRAPH-EMAIL/TDD.md +0 -531
- package/documents/LOOP-ENGINEERING-PLAN.md +0 -279
- package/documents/SA4E-12/BRD.md +0 -454
- package/documents/SA4E-12/FSD.md +0 -639
- package/documents/SA4E-12/STATUS.json +0 -59
- package/documents/SA4E-12/STC.md +0 -1502
- package/documents/SA4E-12/STP.md +0 -348
- package/documents/SA4E-12/TDD.md +0 -427
- package/documents/SA4E-12/TEST-REPORT-SA4E-12.csv +0 -66
- package/documents/SA4E-12/test-data/api-keys.csv +0 -16
- package/documents/SA4E-12/test-data/models.csv +0 -18
- package/documents/SA4E-12/test-data/providers.csv +0 -7
- package/documents/SA4E-124/BRD.md +0 -126
- package/documents/SA4E-124/DPG+RLN.md +0 -74
- package/documents/SA4E-124/FSD.md +0 -102
- package/documents/SA4E-124/RUN-LOG.md +0 -13
- package/documents/SA4E-124/STATUS.json +0 -18
- package/documents/SA4E-124/STP+STC.md +0 -118
- package/documents/SA4E-124/TDD.md +0 -87
- package/documents/SA4E-125/Architecture-v2.md +0 -165
- package/documents/SA4E-125/Architecture-v3.md +0 -99
- package/documents/SA4E-125/Architecture-v4.md +0 -122
- package/documents/SA4E-125/Architecture-v5.md +0 -140
- package/documents/SA4E-125/Architecture-v6.md +0 -94
- package/documents/SA4E-125/BRD.md +0 -168
- package/documents/SA4E-125/DPG.md +0 -189
- package/documents/SA4E-125/FSD.md +0 -742
- package/documents/SA4E-125/Langgrap.md +0 -648
- package/documents/SA4E-125/Langgraph-Module-Reference.md +0 -448
- package/documents/SA4E-125/STATUS.json +0 -18
- package/documents/SA4E-125/STC.md +0 -410
- package/documents/SA4E-125/STP.md +0 -101
- package/documents/SA4E-125/TDD.md +0 -252
- package/documents/SA4E-125/UG.md +0 -153
- package/documents/SA4E-125/review-1.md +0 -244
- package/documents/SA4E-125/review-2.md +0 -93
- package/documents/SA4E-125/review-3.md +0 -90
- package/documents/SA4E-125/review-4.md +0 -119
- package/documents/SA4E-125/review-5.md +0 -94
- package/documents/SA4E-125/review-6.md +0 -75
- package/documents/SA4E-14/BRD.md +0 -532
- package/documents/SA4E-14/FSD.md +0 -890
- package/documents/SA4E-14/SECURITY-REPORT.md +0 -470
- package/documents/SA4E-14/STATUS.json +0 -16
- package/documents/SA4E-14/STC.md +0 -337
- package/documents/SA4E-14/STP.md +0 -170
- package/documents/SA4E-14/TDD.md +0 -653
- package/documents/SA4E-18/BRD-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/BRD.md +0 -382
- package/documents/SA4E-18/FSD-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/FSD.md +0 -895
- package/documents/SA4E-18/STATUS.json +0 -23
- package/documents/SA4E-18/STC-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/STC.md +0 -998
- package/documents/SA4E-18/STP-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/STP.md +0 -323
- package/documents/SA4E-18/TDD-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/TDD.md +0 -827
- package/documents/SA4E-18/TEST-REPORT-SA4E-18.csv +0 -35
- package/documents/SA4E-18/TEST-REPORT-v1-SA4E-18.docx +0 -0
- package/documents/SA4E-18/TEST-REPORT.md +0 -122
- package/documents/SA4E-26/BRD-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/BRD.md +0 -306
- package/documents/SA4E-26/DPG-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/DPG.md +0 -210
- package/documents/SA4E-26/FSD-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/FSD.md +0 -953
- package/documents/SA4E-26/RLN-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/RLN.md +0 -122
- package/documents/SA4E-26/RUN-LOG.md +0 -41
- package/documents/SA4E-26/STATUS.json +0 -25
- package/documents/SA4E-26/STC-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/STC.md +0 -1011
- package/documents/SA4E-26/STP-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/STP.md +0 -292
- package/documents/SA4E-26/TDD-v1-SA4E-26.docx +0 -0
- package/documents/SA4E-26/TDD.md +0 -506
- package/documents/SA4E-27/BRD.md +0 -471
- package/documents/SA4E-27/FSD.md +0 -1100
- package/documents/SA4E-27/RUN-LOG.md +0 -5
- package/documents/SA4E-27/STATUS.json +0 -15
- package/documents/SA4E-27/TDD.md +0 -1156
- package/documents/SA4E-28/RUN-LOG.md +0 -9
- package/documents/SA4E-28/STATUS.json +0 -24
- package/documents/SA4E-28/TICKET-PLAN.md +0 -121
- package/documents/SA4E-29/ARCHITECTURE-BASE64-PROXY.md +0 -145
- package/documents/SA4E-29/BRD.md +0 -366
- package/documents/SA4E-29/FSD.md +0 -675
- package/documents/SA4E-29/RUN-LOG.md +0 -5
- package/documents/SA4E-29/STATUS.json +0 -16
- package/documents/SA4E-29/STC.md +0 -667
- package/documents/SA4E-29/STP.md +0 -299
- package/documents/SA4E-29/TDD.md +0 -491
- package/documents/SA4E-30/BRD.md +0 -258
- package/documents/SA4E-30/FSD.md +0 -168
- package/documents/SA4E-30/RUN-LOG.md +0 -5
- package/documents/SA4E-30/STATUS.json +0 -32
- package/documents/SA4E-30/TDD.md +0 -153
- package/documents/SA4E-31/RUN-LOG.md +0 -39
- package/documents/SA4E-31/STATUS.json +0 -53
- package/documents/SA4E-32/BRD.md +0 -163
- package/documents/SA4E-32/FSD.md +0 -226
- package/documents/SA4E-32/RUN-LOG.md +0 -11
- package/documents/SA4E-32/STATUS.json +0 -18
- package/documents/SA4E-32/STC.md +0 -64
- package/documents/SA4E-32/STP.md +0 -72
- package/documents/SA4E-32/TDD.md +0 -132
- package/documents/SA4E-34/BRD.md +0 -324
- package/documents/SA4E-34/FSD.md +0 -291
- package/documents/SA4E-34/RUN-LOG.md +0 -14
- package/documents/SA4E-34/STATUS.json +0 -31
- package/documents/SA4E-34/TDD.md +0 -236
- package/documents/SA4E-35/BRD.md +0 -79
- package/documents/SA4E-35/RUN-LOG.md +0 -9
- package/documents/SA4E-35/STATUS.json +0 -14
- package/documents/SA4E-36/BRD.md +0 -485
- package/documents/SA4E-36/FSD.md +0 -886
- package/documents/SA4E-36/RUN-LOG.md +0 -30
- package/documents/SA4E-36/STATUS.json +0 -46
- package/documents/SA4E-36/STC.md +0 -1376
- package/documents/SA4E-36/STP.md +0 -445
- package/documents/SA4E-36/TDD.md +0 -846
- package/documents/SA4E-36/UG.md +0 -240
- package/documents/SA4E-37/BRD.md +0 -350
- package/documents/SA4E-37/FSD.md +0 -1087
- package/documents/SA4E-37/RUN-LOG.md +0 -14
- package/documents/SA4E-37/STATUS.json +0 -32
- package/documents/SA4E-37/TDD.md +0 -498
- package/documents/SA4E-37/UG.md +0 -135
- package/documents/SA4E-38/BRD.md +0 -441
- package/documents/SA4E-38/FSD.md +0 -671
- package/documents/SA4E-38/RUN-LOG.md +0 -12
- package/documents/SA4E-38/STC.md +0 -1286
- package/documents/SA4E-38/STP.md +0 -360
- package/documents/SA4E-38/TDD.md +0 -737
- package/documents/SA4E-38/UG.md +0 -78
- package/documents/SA4E-38/test-data/business-messages.csv +0 -11
- package/documents/SA4E-38/test-data/edge-case-messages.csv +0 -12
- package/documents/SA4E-38/test-data/llm-mock-responses.csv +0 -11
- package/documents/SA4E-38/test-data/social-messages.csv +0 -11
- package/documents/SA4E-38/test-data/unfiltered-entries-seed.csv +0 -11
- package/documents/SA4E-39/RUN-LOG.md +0 -11
- package/documents/SA4E-39/STATUS.json +0 -22
- package/documents/SA4E-40/RUN-LOG.md +0 -9
- package/documents/SA4E-42/BRD.md +0 -329
- package/documents/SA4E-42/FSD.md +0 -873
- package/documents/SA4E-42/PENTEST-REPORT.md +0 -247
- package/documents/SA4E-42/RUN-LOG.md +0 -24
- package/documents/SA4E-42/SECURITY-REVIEW.md +0 -430
- package/documents/SA4E-42/STATUS.json +0 -38
- package/documents/SA4E-42/STC.md +0 -351
- package/documents/SA4E-42/STP.md +0 -340
- package/documents/SA4E-42/TDD.md +0 -344
- package/documents/SA4E-42/TEST-REPORT.md +0 -198
- package/documents/SA4E-42/test-data-events.csv +0 -15
- package/documents/SA4E-42/test-data-tools.csv +0 -14
- package/documents/SA4E-44/BRD.md +0 -614
- package/documents/SA4E-44/DISCREPANCY.md +0 -82
- package/documents/SA4E-44/DPG.md +0 -170
- package/documents/SA4E-44/FSD.md +0 -1340
- package/documents/SA4E-44/RLN.md +0 -176
- package/documents/SA4E-44/RUN-LOG.md +0 -41
- package/documents/SA4E-44/SECURITY-ASSESSMENT.md +0 -465
- package/documents/SA4E-44/SECURITY-REVIEW.md +0 -287
- package/documents/SA4E-44/STATUS.json +0 -31
- package/documents/SA4E-44/STC.md +0 -1794
- package/documents/SA4E-44/STP.md +0 -281
- package/documents/SA4E-44/TDD-REFACTOR-PG.md +0 -171
- package/documents/SA4E-44/TDD.md +0 -1130
- package/documents/SA4E-44/UG.md +0 -147
- package/documents/SA4E-45/BRD.md +0 -413
- package/documents/SA4E-45/FSD.md +0 -1549
- package/documents/SA4E-45/RUN-LOG.md +0 -20
- package/documents/SA4E-45/SECURITY-ASSESSMENT.md +0 -352
- package/documents/SA4E-45/SECURITY-REVIEW.md +0 -487
- package/documents/SA4E-45/STATUS.json +0 -35
- package/documents/SA4E-45/STC.md +0 -1080
- package/documents/SA4E-45/STP.md +0 -249
- package/documents/SA4E-45/TDD.md +0 -648
- package/documents/SA4E-45/UG.md +0 -112
- package/documents/SA4E-45/deployment_guide.md +0 -209
- package/documents/SA4E-45/release_notes.md +0 -118
- package/documents/SA4E-45/test-data/dialect-inputs.csv +0 -9
- package/documents/SA4E-45/test-data/fts-queries.csv +0 -11
- package/documents/SA4E-45/test-data/graph-symbols.csv +0 -11
- package/documents/SA4E-45/test-data/knowledge-entries.csv +0 -11
- package/documents/SA4E-45/test-data/migration-tables.csv +0 -17
- package/documents/SA4E-45/test-data/security-inputs.csv +0 -13
- package/documents/SA4E-47/BRD.md +0 -721
- package/documents/SA4E-47/FSD.md +0 -1150
- package/documents/SA4E-47/STC.md +0 -1126
- package/documents/SA4E-47/STP.md +0 -409
- package/documents/SA4E-47/TDD.md +0 -1450
- package/documents/SA4E-47/TEST-REPORT-SA4E-47.csv +0 -36
- package/documents/SA4E-48/BRD-v1-SA4E-48.docx +0 -0
- package/documents/SA4E-48/BRD.md +0 -355
- package/documents/SA4E-48/FSD-v1-SA4E-48.docx +0 -0
- package/documents/SA4E-48/FSD-v2-SA4E-48.docx +0 -0
- package/documents/SA4E-48/FSD.md +0 -1253
- package/documents/SA4E-48/STC-v1.0-SA4E-48.xlsx +0 -0
- package/documents/SA4E-48/STC.md +0 -1837
- package/documents/SA4E-48/STP-v1.0-SA4E-48.docx +0 -0
- package/documents/SA4E-48/STP.md +0 -325
- package/documents/SA4E-48/TDD-v1-SA4E-48.docx +0 -0
- package/documents/SA4E-48/TDD.md +0 -960
- package/documents/SA4E-49/RUN-LOG.md +0 -13
- package/documents/SA4E-49/STATUS.json +0 -45
- package/documents/SA4E-50/UG.md +0 -167
- package/documents/SA4E-52/RUN-LOG.md +0 -8
- package/documents/SA4E-53/RUN-LOG.md +0 -48
- package/documents/SA4E-6/BRD-TOUCH.md +0 -366
- package/documents/SA4E-6/BRD.md +0 -531
- package/documents/SA4E-6/FSD.md +0 -1621
- package/documents/SA4E-6/STATUS.json +0 -19
- package/documents/SA4E-6/TDD-TOUCH.md +0 -768
- package/documents/SA4E-6/TDD.md +0 -1123
- package/documents/SA4E-CODEINTEL-MT/RUN-LOG.md +0 -27
- package/documents/SA4E-CODEINTEL-MT/SECURITY-ASSESSMENT.md +0 -197
- package/documents/SA4E-CODEINTEL-MT/STATUS.json +0 -25
- package/documents/SA4E-CODEINTEL-MT/TDD.md +0 -746
- package/documents/SKILLS-REPO-TICKETS.md +0 -64
- package/documents/analysis/langgraph-vs-deerflow-report.md +0 -603
- package/documents/architecture/ARCH.md +0 -395
- package/documents/architecture/TECH-REF.md +0 -397
- package/documents/drawio-optimize/drawio-anti-edge-collision.md +0 -97
- package/documents/evolution-memory/Soliution-3-GPT.md +0 -649
- package/documents/evolution-memory/Solution-1-Deepseek.md +0 -267
- package/documents/evolution-memory/Solution-2-Grok.md +0 -166
- package/documents/evolution-memory/Solution4-gemini.pdf +0 -0
- package/documents/workflows/SA4E-workflows.md +0 -167
package/dist/config/CoreTools.js
CHANGED
|
@@ -15,7 +15,7 @@ export const CORE_TOOLS = [
|
|
|
15
15
|
'pega_get_rule', 'pega_get_session_context',
|
|
16
16
|
'pega_query_rule', 'pega_list_rules', 'pega_save_rule',
|
|
17
17
|
'pega_checkout_rule', 'pega_run_tests', 'pega_get_class_metadata',
|
|
18
|
-
'pega_create_branch',
|
|
18
|
+
'pega_create_branch', 'pega_index_workspace',
|
|
19
19
|
];
|
|
20
20
|
/**
|
|
21
21
|
* Normalize allowlist: drop invalid (BR-05), de-dup (BR-08),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CoreTools.js","sourceRoot":"","sources":["../../src/config/CoreTools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,YAAY,EAAE,sBAAsB,EAAE,sBAAsB;CACpD,CAAC;AAEX,sFAAsF;AACtF,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,YAAY,EAAE,YAAY,EAAE,iBAAiB;IAC7C,aAAa,EAAE,qBAAqB;IACpC,YAAY,EAAE,sBAAsB,EAAE,sBAAsB;IAC5D,mBAAmB,EAAE,oBAAoB;IACzC,eAAe,EAAE,0BAA0B;IAC3C,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB;IACtD,oBAAoB,EAAE,gBAAgB,EAAE,yBAAyB;IACjE,oBAAoB;
|
|
1
|
+
{"version":3,"file":"CoreTools.js","sourceRoot":"","sources":["../../src/config/CoreTools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,YAAY,EAAE,sBAAsB,EAAE,sBAAsB;CACpD,CAAC;AAEX,sFAAsF;AACtF,MAAM,CAAC,MAAM,UAAU,GAAsB;IAC3C,YAAY,EAAE,YAAY,EAAE,iBAAiB;IAC7C,aAAa,EAAE,qBAAqB;IACpC,YAAY,EAAE,sBAAsB,EAAE,sBAAsB;IAC5D,mBAAmB,EAAE,oBAAoB;IACzC,eAAe,EAAE,0BAA0B;IAC3C,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB;IACtD,oBAAoB,EAAE,gBAAgB,EAAE,yBAAyB;IACjE,oBAAoB,EAAE,sBAAsB;CACpC,CAAC;AAEX;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAe;IAClD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;QAC3B,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,EAAE;YAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,4CAA4C,CAAC,CAAC;QAClF,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,GAAG,CAAS,CAAC,GAAG,KAAK,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA4E-91 — Tests for CodeEdgeExtractor strategies.
|
|
3
|
+
* Verifies IMPORTS, CALLS, and EXTENDS edges are extracted from code_dependencies,
|
|
4
|
+
* code_call_graph, and symbols tables, then inserted into graph_edges.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import pino from 'pino';
|
|
9
|
+
import { SqliteDbAdapter } from '../../../modules/memory/task-queue/SqliteDbAdapter.js';
|
|
10
|
+
import { ImportsEdgeStrategy, CallsEdgeStrategy, ExtendsEdgeStrategy, extractAndInsertCodeEdges, } from '../code-edge-extractor.js';
|
|
11
|
+
const PID = 'proj_test';
|
|
12
|
+
const log = pino({ level: 'silent' });
|
|
13
|
+
const INDEX_SCHEMA = `
|
|
14
|
+
CREATE TABLE files (id INTEGER PRIMARY KEY AUTOINCREMENT, project_id TEXT NOT NULL DEFAULT '',
|
|
15
|
+
path TEXT, relative_path TEXT, language TEXT, module TEXT, content_hash TEXT, size_bytes INTEGER, line_count INTEGER);
|
|
16
|
+
CREATE TABLE symbols (id INTEGER PRIMARY KEY AUTOINCREMENT, project_id TEXT NOT NULL DEFAULT '',
|
|
17
|
+
file_id INTEGER, name TEXT, kind TEXT, signature TEXT, start_line INTEGER, end_line INTEGER,
|
|
18
|
+
parent_symbol TEXT, parent_symbol_id INTEGER, visibility TEXT, doc_comment TEXT, complexity INTEGER, is_exported INTEGER DEFAULT 0);
|
|
19
|
+
CREATE TABLE code_dependencies (id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
source_file_id INTEGER NOT NULL, target_file_id INTEGER, target_path TEXT NOT NULL DEFAULT '',
|
|
21
|
+
dependency_type TEXT NOT NULL DEFAULT 'import');
|
|
22
|
+
CREATE TABLE code_call_graph (id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
23
|
+
caller_symbol_id INTEGER NOT NULL, callee_symbol_id INTEGER NOT NULL, call_site_line INTEGER);
|
|
24
|
+
`;
|
|
25
|
+
const ADMIN_SCHEMA = `
|
|
26
|
+
CREATE TABLE graph_nodes (entry_id TEXT PRIMARY KEY, label TEXT NOT NULL DEFAULT '',
|
|
27
|
+
type TEXT NOT NULL DEFAULT 'DOCUMENT', tier TEXT NOT NULL DEFAULT 'SHARED', project_id TEXT NOT NULL DEFAULT '',
|
|
28
|
+
x REAL DEFAULT 0, y REAL DEFAULT 0, z REAL DEFAULT 0, level INTEGER DEFAULT 2, cluster_id TEXT,
|
|
29
|
+
created_at TEXT DEFAULT (datetime('now')));
|
|
30
|
+
CREATE TABLE graph_edges (id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
31
|
+
source TEXT NOT NULL, target TEXT NOT NULL,
|
|
32
|
+
weight REAL NOT NULL DEFAULT 0.5, rel_type TEXT NOT NULL DEFAULT 'RELATED_TO',
|
|
33
|
+
UNIQUE(source, target));
|
|
34
|
+
`;
|
|
35
|
+
describe('SA4E-91 CodeEdgeExtractor', () => {
|
|
36
|
+
let indexDb;
|
|
37
|
+
let adminDb;
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
indexDb = new Database(':memory:');
|
|
40
|
+
indexDb.exec(INDEX_SCHEMA);
|
|
41
|
+
adminDb = new Database(':memory:');
|
|
42
|
+
adminDb.exec(ADMIN_SCHEMA);
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => { indexDb.close(); adminDb.close(); });
|
|
45
|
+
describe('ImportsEdgeStrategy', () => {
|
|
46
|
+
it('extracts IMPORTS edges from code_dependencies', async () => {
|
|
47
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/a.ts', 'a.ts')`).run(PID);
|
|
48
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/b.ts', 'b.ts')`).run(PID);
|
|
49
|
+
indexDb.prepare(`INSERT INTO code_dependencies (source_file_id, target_file_id, target_path) VALUES (1, 2, './b')`).run();
|
|
50
|
+
const strategy = new ImportsEdgeStrategy();
|
|
51
|
+
const edges = await strategy.extract(new SqliteDbAdapter(indexDb), PID);
|
|
52
|
+
expect(edges).toHaveLength(1);
|
|
53
|
+
expect(edges[0]).toEqual({ source: 'code:1', target: 'code:2', label: 'IMPORTS', weight: 0.8 });
|
|
54
|
+
});
|
|
55
|
+
it('skips dependencies with null target_file_id', async () => {
|
|
56
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/a.ts', 'a.ts')`).run(PID);
|
|
57
|
+
indexDb.prepare(`INSERT INTO code_dependencies (source_file_id, target_file_id, target_path) VALUES (1, NULL, 'lodash')`).run();
|
|
58
|
+
const strategy = new ImportsEdgeStrategy();
|
|
59
|
+
const edges = await strategy.extract(new SqliteDbAdapter(indexDb), PID);
|
|
60
|
+
expect(edges).toHaveLength(0);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('CallsEdgeStrategy', () => {
|
|
64
|
+
it('extracts CALLS edges from code_call_graph', async () => {
|
|
65
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/x.ts', 'x.ts')`).run(PID);
|
|
66
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind) VALUES (?, 1, 'foo', 'function')`).run(PID);
|
|
67
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind) VALUES (?, 1, 'bar', 'function')`).run(PID);
|
|
68
|
+
indexDb.prepare(`INSERT INTO code_call_graph (caller_symbol_id, callee_symbol_id, call_site_line) VALUES (1, 2, 10)`).run();
|
|
69
|
+
const strategy = new CallsEdgeStrategy();
|
|
70
|
+
const edges = await strategy.extract(new SqliteDbAdapter(indexDb), PID);
|
|
71
|
+
expect(edges).toHaveLength(1);
|
|
72
|
+
expect(edges[0]).toEqual({ source: 'code:1', target: 'code:2', label: 'CALLS', weight: 0.7 });
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('ExtendsEdgeStrategy', () => {
|
|
76
|
+
it('extracts EXTENDS edges from parent_symbol_id', async () => {
|
|
77
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/c.ts', 'c.ts')`).run(PID);
|
|
78
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind, parent_symbol_id) VALUES (?, 1, 'Base', 'class', NULL)`).run(PID);
|
|
79
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind, parent_symbol_id) VALUES (?, 1, 'Child', 'class', 1)`).run(PID);
|
|
80
|
+
const strategy = new ExtendsEdgeStrategy();
|
|
81
|
+
const edges = await strategy.extract(new SqliteDbAdapter(indexDb), PID);
|
|
82
|
+
expect(edges).toHaveLength(1);
|
|
83
|
+
expect(edges[0]).toEqual({ source: 'code:2', target: 'code:1', label: 'EXTENDS', weight: 0.9 });
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('extractAndInsertCodeEdges (integration)', () => {
|
|
87
|
+
it('inserts all edge types into graph_edges', async () => {
|
|
88
|
+
// File A=1 imports File B=2, but Symbol X=3 (in file A) calls Symbol Y=4 (in file B)
|
|
89
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/a.ts', 'a.ts')`).run(PID);
|
|
90
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/b.ts', 'b.ts')`).run(PID);
|
|
91
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind) VALUES (?, 1, 'fn1', 'function')`).run(PID);
|
|
92
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind) VALUES (?, 1, 'fn2', 'function')`).run(PID);
|
|
93
|
+
indexDb.prepare(`INSERT INTO symbols (project_id, file_id, name, kind) VALUES (?, 2, 'fn3', 'function')`).run(PID);
|
|
94
|
+
// File 1 → File 2 (IMPORTS edge: code:1 → code:2)
|
|
95
|
+
indexDb.prepare(`INSERT INTO code_dependencies (source_file_id, target_file_id, target_path) VALUES (1, 2, './b')`).run();
|
|
96
|
+
// Symbol 2 → Symbol 3 (CALLS edge: code:2 → code:3)
|
|
97
|
+
indexDb.prepare(`INSERT INTO code_call_graph (caller_symbol_id, callee_symbol_id, call_site_line) VALUES (2, 3, 10)`).run();
|
|
98
|
+
const count = await extractAndInsertCodeEdges(new SqliteDbAdapter(indexDb), new SqliteDbAdapter(adminDb), PID, log);
|
|
99
|
+
expect(count).toBe(2);
|
|
100
|
+
const edges = adminDb.prepare('SELECT * FROM graph_edges ORDER BY rel_type').all();
|
|
101
|
+
expect(edges).toHaveLength(2);
|
|
102
|
+
expect(edges.some((e) => e.rel_type === 'IMPORTS')).toBe(true);
|
|
103
|
+
expect(edges.some((e) => e.rel_type === 'CALLS')).toBe(true);
|
|
104
|
+
});
|
|
105
|
+
it('is idempotent — duplicate inserts ignored', async () => {
|
|
106
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/a.ts', 'a.ts')`).run(PID);
|
|
107
|
+
indexDb.prepare(`INSERT INTO files (project_id, path, relative_path) VALUES (?, '/b.ts', 'b.ts')`).run(PID);
|
|
108
|
+
indexDb.prepare(`INSERT INTO code_dependencies (source_file_id, target_file_id, target_path) VALUES (1, 2, './b')`).run();
|
|
109
|
+
await extractAndInsertCodeEdges(new SqliteDbAdapter(indexDb), new SqliteDbAdapter(adminDb), PID, log);
|
|
110
|
+
await extractAndInsertCodeEdges(new SqliteDbAdapter(indexDb), new SqliteDbAdapter(adminDb), PID, log);
|
|
111
|
+
const edges = adminDb.prepare('SELECT * FROM graph_edges').all();
|
|
112
|
+
expect(edges.length).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
//# sourceMappingURL=code-edge-extractor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-edge-extractor.test.js","sourceRoot":"","sources":["../../../../src/engine/graph/__tests__/code-edge-extractor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA4E-91 — Code Edge Extractor.
|
|
3
|
+
* Extracts IMPORTS, EXTENDS, and CALLS edges from code intelligence data
|
|
4
|
+
* (code_dependencies, code_call_graph, symbols) after graph node projection.
|
|
5
|
+
* Non-blocking, best-effort: failures never break the index run.
|
|
6
|
+
*/
|
|
7
|
+
import type { DatabaseAdapter } from '../../database/adapters/DatabaseAdapter.js';
|
|
8
|
+
import type { Logger } from 'pino';
|
|
9
|
+
/** A graph edge extracted from code intelligence tables. */
|
|
10
|
+
export interface CodeGraphEdge {
|
|
11
|
+
source: string;
|
|
12
|
+
target: string;
|
|
13
|
+
label: string;
|
|
14
|
+
weight: number;
|
|
15
|
+
}
|
|
16
|
+
/** Strategy interface for code edge extraction. */
|
|
17
|
+
export interface CodeEdgeStrategy {
|
|
18
|
+
/** Extract edges for the given project from the index DB. */
|
|
19
|
+
extract(indexAdapter: DatabaseAdapter, projectId: string): Promise<CodeGraphEdge[]>;
|
|
20
|
+
}
|
|
21
|
+
/** Extracts IMPORTS edges from code_dependencies table. */
|
|
22
|
+
export declare class ImportsEdgeStrategy implements CodeEdgeStrategy {
|
|
23
|
+
extract(indexAdapter: DatabaseAdapter, projectId: string): Promise<CodeGraphEdge[]>;
|
|
24
|
+
}
|
|
25
|
+
/** Extracts CALLS edges from code_call_graph table. */
|
|
26
|
+
export declare class CallsEdgeStrategy implements CodeEdgeStrategy {
|
|
27
|
+
extract(indexAdapter: DatabaseAdapter, projectId: string): Promise<CodeGraphEdge[]>;
|
|
28
|
+
}
|
|
29
|
+
/** Extracts EXTENDS edges from class inheritance (parent_symbol_id). */
|
|
30
|
+
export declare class ExtendsEdgeStrategy implements CodeEdgeStrategy {
|
|
31
|
+
extract(indexAdapter: DatabaseAdapter, projectId: string): Promise<CodeGraphEdge[]>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Batch-insert extracted code edges into graph_edges (admin DB).
|
|
35
|
+
* Uses ON CONFLICT DO NOTHING for idempotency.
|
|
36
|
+
* Non-fatal: catches all errors to avoid breaking index pipeline.
|
|
37
|
+
*/
|
|
38
|
+
export declare function extractAndInsertCodeEdges(indexAdapter: DatabaseAdapter, adminAdapter: DatabaseAdapter, projectId: string, log: Logger): Promise<number>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA4E-91 — Code Edge Extractor.
|
|
3
|
+
* Extracts IMPORTS, EXTENDS, and CALLS edges from code intelligence data
|
|
4
|
+
* (code_dependencies, code_call_graph, symbols) after graph node projection.
|
|
5
|
+
* Non-blocking, best-effort: failures never break the index run.
|
|
6
|
+
*/
|
|
7
|
+
/** Extracts IMPORTS edges from code_dependencies table. */
|
|
8
|
+
export class ImportsEdgeStrategy {
|
|
9
|
+
async extract(indexAdapter, projectId) {
|
|
10
|
+
const rows = await indexAdapter.allAsync(`SELECT cd.source_file_id, cd.target_file_id
|
|
11
|
+
FROM code_dependencies cd
|
|
12
|
+
JOIN files f ON cd.source_file_id = f.id
|
|
13
|
+
WHERE f.project_id = ? AND cd.target_file_id IS NOT NULL`, [projectId]);
|
|
14
|
+
return rows.map(r => ({
|
|
15
|
+
source: `code:${r.source_file_id}`,
|
|
16
|
+
target: `code:${r.target_file_id}`,
|
|
17
|
+
label: 'IMPORTS',
|
|
18
|
+
weight: 0.8,
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Extracts CALLS edges from code_call_graph table. */
|
|
23
|
+
export class CallsEdgeStrategy {
|
|
24
|
+
async extract(indexAdapter, projectId) {
|
|
25
|
+
const rows = await indexAdapter.allAsync(`SELECT cg.caller_symbol_id AS caller_id, cg.callee_symbol_id AS callee_id
|
|
26
|
+
FROM code_call_graph cg
|
|
27
|
+
JOIN symbols s ON cg.caller_symbol_id = s.id
|
|
28
|
+
WHERE s.project_id = ?`, [projectId]);
|
|
29
|
+
return rows.map(r => ({
|
|
30
|
+
source: `code:${r.caller_id}`,
|
|
31
|
+
target: `code:${r.callee_id}`,
|
|
32
|
+
label: 'CALLS',
|
|
33
|
+
weight: 0.7,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Extracts EXTENDS edges from class inheritance (parent_symbol_id). */
|
|
38
|
+
export class ExtendsEdgeStrategy {
|
|
39
|
+
async extract(indexAdapter, projectId) {
|
|
40
|
+
const rows = await indexAdapter.allAsync(`SELECT s.id AS child_id, s.parent_symbol_id AS parent_id
|
|
41
|
+
FROM symbols s
|
|
42
|
+
WHERE s.project_id = ? AND s.parent_symbol_id IS NOT NULL`, [projectId]);
|
|
43
|
+
return rows.map(r => ({
|
|
44
|
+
source: `code:${r.child_id}`,
|
|
45
|
+
target: `code:${r.parent_id}`,
|
|
46
|
+
label: 'EXTENDS',
|
|
47
|
+
weight: 0.9,
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Registry of all code-edge strategies. */
|
|
52
|
+
const CODE_EDGE_STRATEGIES = [
|
|
53
|
+
new ImportsEdgeStrategy(),
|
|
54
|
+
new CallsEdgeStrategy(),
|
|
55
|
+
new ExtendsEdgeStrategy(),
|
|
56
|
+
];
|
|
57
|
+
/**
|
|
58
|
+
* Batch-insert extracted code edges into graph_edges (admin DB).
|
|
59
|
+
* Uses ON CONFLICT DO NOTHING for idempotency.
|
|
60
|
+
* Non-fatal: catches all errors to avoid breaking index pipeline.
|
|
61
|
+
*/
|
|
62
|
+
export async function extractAndInsertCodeEdges(indexAdapter, adminAdapter, projectId, log) {
|
|
63
|
+
let totalInserted = 0;
|
|
64
|
+
for (const strategy of CODE_EDGE_STRATEGIES) {
|
|
65
|
+
try {
|
|
66
|
+
const edges = await strategy.extract(indexAdapter, projectId);
|
|
67
|
+
totalInserted += await batchInsertEdges(adminAdapter, edges);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
// Best-effort: log and continue with next strategy
|
|
71
|
+
log.warn({ err }, `[code-edge-extractor] Strategy ${strategy.constructor.name} failed`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return totalInserted;
|
|
75
|
+
}
|
|
76
|
+
/** Insert edges in batch, ignoring conflicts (idempotent). */
|
|
77
|
+
async function batchInsertEdges(adapter, edges) {
|
|
78
|
+
let count = 0;
|
|
79
|
+
const sql = adapter.getEngine() === 'sqlite'
|
|
80
|
+
? `INSERT OR IGNORE INTO graph_edges (source, target, weight, rel_type) VALUES (?, ?, ?, ?)`
|
|
81
|
+
: `INSERT INTO graph_edges (source, target, weight, rel_type) VALUES ($1, $2, $3, $4) ON CONFLICT (source, target) DO NOTHING`;
|
|
82
|
+
for (const edge of edges) {
|
|
83
|
+
const result = await adapter.runAsync(sql, [edge.source, edge.target, edge.weight, edge.label]);
|
|
84
|
+
if ((result.changes ?? 0) > 0)
|
|
85
|
+
count++;
|
|
86
|
+
}
|
|
87
|
+
return count;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=code-edge-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-edge-extractor.js","sourceRoot":"","sources":["../../../src/engine/graph/code-edge-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,8 @@ export declare class GraphSyncService {
|
|
|
17
17
|
constructor(indexAdapter: DatabaseAdapter, adminAdapter: DatabaseAdapter, log: Logger);
|
|
18
18
|
/** Re-project a tenant's code symbols into graph_nodes. SA4E-53: async. */
|
|
19
19
|
syncProjectSymbols(projectId: string): Promise<void>;
|
|
20
|
+
/** SA4E-91: Extract code relationships into graph_edges (non-fatal). */
|
|
21
|
+
private syncCodeEdges;
|
|
20
22
|
private readTopSymbols;
|
|
21
23
|
private replaceCodeNodes;
|
|
22
24
|
private toLabel;
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { DialectHelper } from '../../database/dialect/DialectHelper.js';
|
|
10
10
|
import { KIND_TO_TYPE } from '../../modules/kb-graph/service/constants.js';
|
|
11
|
+
import { extractAndInsertCodeEdges } from './code-edge-extractor.js';
|
|
11
12
|
const CODE_KINDS = ['class', 'interface', 'function', 'method', 'enum', 'type', 'constructor'];
|
|
12
13
|
export class GraphSyncService {
|
|
13
14
|
indexAdapter;
|
|
@@ -33,12 +34,26 @@ export class GraphSyncService {
|
|
|
33
34
|
const symbols = await this.readTopSymbols(projectId);
|
|
34
35
|
await this.replaceCodeNodes(projectId, symbols);
|
|
35
36
|
this.log.info(`[graph-sync] Synced ${symbols.length} code nodes for project ${projectId}`);
|
|
37
|
+
// SA4E-91: Extract and insert code edges (IMPORTS, CALLS, EXTENDS)
|
|
38
|
+
await this.syncCodeEdges(projectId);
|
|
36
39
|
}
|
|
37
40
|
catch (err) {
|
|
38
41
|
// Non-fatal: visualization projection must never fail the index run.
|
|
39
42
|
this.log.error({ err }, `[graph-sync] Failed to sync code nodes for ${projectId}`);
|
|
40
43
|
}
|
|
41
44
|
}
|
|
45
|
+
/** SA4E-91: Extract code relationships into graph_edges (non-fatal). */
|
|
46
|
+
async syncCodeEdges(projectId) {
|
|
47
|
+
try {
|
|
48
|
+
const count = await extractAndInsertCodeEdges(this.indexAdapter, this.adminAdapter, projectId, this.log);
|
|
49
|
+
if (count > 0) {
|
|
50
|
+
this.log.info(`[graph-sync] Inserted ${count} code edges for project ${projectId}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
this.log.warn({ err }, `[graph-sync] Code edge extraction failed (non-fatal)`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
42
57
|
async readTopSymbols(projectId) {
|
|
43
58
|
const placeholders = CODE_KINDS.map(() => '?').join(',');
|
|
44
59
|
return this.indexAdapter.allAsync(`SELECT s.id, s.name, s.kind, f.relative_path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-sync-service.js","sourceRoot":"","sources":["../../../src/engine/graph/graph-sync-service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-sync-service.js","sourceRoot":"","sources":["../../../src/engine/graph/graph-sync-service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,6CAA6C,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAUrE,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAE/F,MAAM,OAAO,gBAAgB;IAKR;IACA;IACA;IANF,YAAY,CAAgB;IAC5B,YAAY,CAAgB;IAE7C,YACmB,YAA6B,EAC7B,YAA6B,EAC7B,GAAW;QAFX,iBAAY,GAAZ,YAAY,CAAiB;QAC7B,iBAAY,GAAZ,YAAY,CAAiB;QAC7B,QAAG,GAAH,GAAG,CAAQ;QAE5B,IAAI,CAAC,YAAY,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,YAAY,GAAG,IAAI,aAAa,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;QAChE,IAAI,YAAY,CAAC,SAAS,EAAE,KAAK,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC;YAC1D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IAED,2EAA2E;IAC3E,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QACxC,IAAI,CAAC,SAAS;YAAE,OAAO,CAAC,cAAc;QACtC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;YACrD,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,OAAO,CAAC,MAAM,2BAA2B,SAAS,EAAE,CAAC,CAAC;YAC3F,mEAAmE;YACnE,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QACtC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,qEAAqE;YACrE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,8CAA8C,SAAS,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IAED,wEAAwE;IAChE,KAAK,CAAC,aAAa,CAAC,SAAiB;QAC3C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,yBAAyB,CAC3C,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAC1D,CAAC;YACF,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,yBAAyB,KAAK,2BAA2B,SAAS,EAAE,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,EAAE,sDAAsD,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,SAAiB;QAC5C,MAAM,YAAY,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAC/B;;+CAEyC,YAAY;4DACC,EACtD,CAAC,SAAS,EAAE,GAAG,UAAU,CAAC,CAC3B,CAAC;IACJ,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,SAAiB,EAAE,OAAwB;QACxE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC1C,gGAAgG;QAChG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAC9B,yEAAyE,EACzE,CAAC,SAAS,CAAC,CACZ,CAAC;QACF,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,aAAa,EACtD,CAAC,UAAU,EAAC,OAAO,EAAC,MAAM,EAAC,MAAM,EAAC,YAAY,EAAC,GAAG,EAAC,GAAG,EAAC,GAAG,EAAC,OAAO,EAAC,YAAY,CAAC,EAAE,UAAU,CAAC,CAAC;QAChG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,GAAG,GAAG,eAAe,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YACtC,MAAM,QAAQ,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC;YACvD,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,EAAE;gBACpC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM;gBACjD,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,SAAS,EAAE;aAC7D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,CAAgB;QAC9B,MAAM,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3E,OAAO,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;CACF;AAED,wEAAwE;AACxE,SAAS,eAAe,CAAC,KAAa,EAAE,KAAa;IACnD,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACrD,MAAM,CAAC,GAAG,GAAG,CAAC;IACd,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;QAC9D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;QAC9D,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG;KAC7C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA4E-91 — Tests for edge-on-ingest extraction strategies.
|
|
3
|
+
* Verifies DISCUSSES, REFERENCES, and BELONGS_TO edges are created
|
|
4
|
+
* when KB entries are ingested.
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { SqliteDbAdapter } from '../task-queue/SqliteDbAdapter.js';
|
|
9
|
+
import { TicketRefStrategy, FilePathRefStrategy, ClassNameRefStrategy, BelongsToStrategy, extractAndInsertIngestEdges, } from '../engine/edge-on-ingest.js';
|
|
10
|
+
const SCHEMA = `
|
|
11
|
+
CREATE TABLE graph_nodes (entry_id TEXT PRIMARY KEY, label TEXT NOT NULL DEFAULT '',
|
|
12
|
+
type TEXT NOT NULL DEFAULT 'DOCUMENT', tier TEXT NOT NULL DEFAULT 'SHARED', project_id TEXT NOT NULL DEFAULT '',
|
|
13
|
+
x REAL DEFAULT 0, y REAL DEFAULT 0, z REAL DEFAULT 0, level INTEGER DEFAULT 2, cluster_id TEXT,
|
|
14
|
+
created_at TEXT DEFAULT (datetime('now')));
|
|
15
|
+
CREATE TABLE graph_edges (id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
16
|
+
source TEXT NOT NULL, target TEXT NOT NULL,
|
|
17
|
+
weight REAL NOT NULL DEFAULT 0.5, rel_type TEXT NOT NULL DEFAULT 'RELATED_TO',
|
|
18
|
+
UNIQUE(source, target));
|
|
19
|
+
`;
|
|
20
|
+
describe('SA4E-91 Edge-on-Ingest', () => {
|
|
21
|
+
let db;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
db = new Database(':memory:');
|
|
24
|
+
db.exec(SCHEMA);
|
|
25
|
+
// Seed some existing nodes for matching
|
|
26
|
+
db.prepare(`INSERT INTO graph_nodes (entry_id, label, type) VALUES (?, ?, ?)`).run('kb-entry:1', 'SA4E-50 Feature BRD', 'DOCUMENT');
|
|
27
|
+
db.prepare(`INSERT INTO graph_nodes (entry_id, label, type) VALUES (?, ?, ?)`).run('code:42', 'GraphService (graph-service.ts)', 'CODE_ENTITY');
|
|
28
|
+
db.prepare(`INSERT INTO graph_nodes (entry_id, label, type) VALUES (?, ?, ?)`).run('kb-entry:5', 'crud.ts analysis', 'KNOWLEDGE_ENTRY');
|
|
29
|
+
});
|
|
30
|
+
afterEach(() => { db.close(); });
|
|
31
|
+
const nodes = [
|
|
32
|
+
{ entry_id: 'kb-entry:1', label: 'SA4E-50 Feature BRD' },
|
|
33
|
+
{ entry_id: 'code:42', label: 'GraphService (graph-service.ts)' },
|
|
34
|
+
{ entry_id: 'kb-entry:5', label: 'crud.ts analysis' },
|
|
35
|
+
];
|
|
36
|
+
describe('TicketRefStrategy', () => {
|
|
37
|
+
it('creates DISCUSSES edge for ticket key references', () => {
|
|
38
|
+
const strategy = new TicketRefStrategy();
|
|
39
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'This relates to SA4E-50 implementation' }, nodes);
|
|
40
|
+
expect(edges).toHaveLength(1);
|
|
41
|
+
expect(edges[0]).toEqual({
|
|
42
|
+
source: 'kb-entry:99', target: 'kb-entry:1', label: 'DISCUSSES', weight: 0.5,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
it('does not self-reference', () => {
|
|
46
|
+
const strategy = new TicketRefStrategy();
|
|
47
|
+
const edges = strategy.extract({ entryId: 'kb-entry:1', content: 'SA4E-50 is the current entry' }, nodes);
|
|
48
|
+
expect(edges).toHaveLength(0);
|
|
49
|
+
});
|
|
50
|
+
it('returns empty for no ticket matches', () => {
|
|
51
|
+
const strategy = new TicketRefStrategy();
|
|
52
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'No tickets here' }, nodes);
|
|
53
|
+
expect(edges).toHaveLength(0);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('FilePathRefStrategy', () => {
|
|
57
|
+
it('creates REFERENCES edge for file path mentions', () => {
|
|
58
|
+
const strategy = new FilePathRefStrategy();
|
|
59
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'Modified crud.ts to fix the bug' }, nodes);
|
|
60
|
+
expect(edges).toHaveLength(1);
|
|
61
|
+
expect(edges[0].label).toBe('REFERENCES');
|
|
62
|
+
expect(edges[0].target).toBe('kb-entry:5');
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('ClassNameRefStrategy', () => {
|
|
66
|
+
it('creates REFERENCES edge for PascalCase class names', () => {
|
|
67
|
+
const strategy = new ClassNameRefStrategy();
|
|
68
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'The GraphService handles node sync' }, nodes);
|
|
69
|
+
expect(edges).toHaveLength(1);
|
|
70
|
+
expect(edges[0].label).toBe('REFERENCES');
|
|
71
|
+
expect(edges[0].target).toBe('code:42');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('BelongsToStrategy', () => {
|
|
75
|
+
it('creates BELONGS_TO edge from source field', () => {
|
|
76
|
+
const strategy = new BelongsToStrategy();
|
|
77
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'Some content', source: 'crud.ts' }, nodes);
|
|
78
|
+
expect(edges).toHaveLength(1);
|
|
79
|
+
expect(edges[0]).toEqual({
|
|
80
|
+
source: 'kb-entry:99', target: 'kb-entry:5', label: 'BELONGS_TO', weight: 0.6,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
it('returns empty when source is null', () => {
|
|
84
|
+
const strategy = new BelongsToStrategy();
|
|
85
|
+
const edges = strategy.extract({ entryId: 'kb-entry:99', content: 'content', source: null }, nodes);
|
|
86
|
+
expect(edges).toHaveLength(0);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe('extractAndInsertIngestEdges (integration)', () => {
|
|
90
|
+
it('inserts edges into graph_edges table', async () => {
|
|
91
|
+
const count = await extractAndInsertIngestEdges(new SqliteDbAdapter(db), { entryId: 'kb-entry:99', content: 'SA4E-50 uses GraphService in crud.ts', source: null });
|
|
92
|
+
expect(count).toBeGreaterThanOrEqual(1);
|
|
93
|
+
const edges = db.prepare('SELECT * FROM graph_edges').all();
|
|
94
|
+
expect(edges.length).toBeGreaterThanOrEqual(1);
|
|
95
|
+
});
|
|
96
|
+
it('is idempotent — no duplicate edges', async () => {
|
|
97
|
+
const adapter = new SqliteDbAdapter(db);
|
|
98
|
+
const ctx = { entryId: 'kb-entry:99', content: 'SA4E-50 feature', source: null };
|
|
99
|
+
await extractAndInsertIngestEdges(adapter, ctx);
|
|
100
|
+
await extractAndInsertIngestEdges(adapter, ctx);
|
|
101
|
+
const edges = db.prepare('SELECT * FROM graph_edges').all();
|
|
102
|
+
// UNIQUE constraint prevents duplicates
|
|
103
|
+
const unique = new Set(edges.map((e) => `${e.source}-${e.target}`));
|
|
104
|
+
expect(unique.size).toBe(edges.length);
|
|
105
|
+
});
|
|
106
|
+
it('returns 0 when no graph_nodes exist', async () => {
|
|
107
|
+
const emptyDb = new Database(':memory:');
|
|
108
|
+
emptyDb.exec(SCHEMA);
|
|
109
|
+
const count = await extractAndInsertIngestEdges(new SqliteDbAdapter(emptyDb), { entryId: 'kb-entry:1', content: 'SA4E-50 test' });
|
|
110
|
+
expect(count).toBe(0);
|
|
111
|
+
emptyDb.close();
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=edge-on-ingest.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-on-ingest.test.js","sourceRoot":"","sources":["../../../../src/modules/memory/__tests__/edge-on-ingest.test.ts"],"names":[],"mappings":"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"}
|