dsh-data-domain-knowledge 0.1.0-alpha.9 → 0.1.1-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +118 -567
- package/cordis.patch.yml +5 -418
- package/eval/README.md +19 -8
- package/eval/benchmark-extraction-format.mjs +20 -0
- package/eval/evaluate-retrieval.mjs +17 -8
- package/eval/queries.example.jsonl +1 -0
- package/lib/client.js +4181 -3239
- package/lib/contract-envelope.d.ts +91 -0
- package/lib/contract-envelope.js +106 -0
- package/lib/contract-layout.d.ts +130 -0
- package/lib/contract-layout.js +138 -0
- package/lib/contract-refs.d.ts +39 -0
- package/lib/contract-refs.js +9 -0
- package/lib/contract-version.d.ts +311 -0
- package/lib/contract-version.js +270 -0
- package/lib/contract-wire.d.ts +147 -0
- package/lib/contract-wire.js +99 -0
- package/lib/contracts.d.ts +12 -0
- package/lib/contracts.js +12 -0
- package/lib/doc-page.js +2 -2
- package/lib/pages.js +3329 -1296
- package/lib/types/agent-behavior-rules.d.ts +10 -0
- package/lib/types/agent-behavior-rules.d.ts.map +1 -0
- package/lib/types/agent-behavior-rules.js +28 -0
- package/lib/types/agent-behavior-rules.js.map +1 -0
- package/lib/types/axis-registry.d.ts +37 -5
- package/lib/types/axis-registry.d.ts.map +1 -1
- package/lib/types/axis-registry.js +234 -26
- package/lib/types/axis-registry.js.map +1 -1
- package/lib/types/card-organize.d.ts +27 -12
- package/lib/types/card-organize.d.ts.map +1 -1
- package/lib/types/card-organize.js +58 -73
- package/lib/types/card-organize.js.map +1 -1
- package/lib/types/compiler/embedding-identity.d.ts +3 -0
- package/lib/types/compiler/embedding-identity.d.ts.map +1 -0
- package/lib/types/compiler/embedding-identity.js +24 -0
- package/lib/types/compiler/embedding-identity.js.map +1 -0
- package/lib/types/compiler/snapshot.d.ts +16 -0
- package/lib/types/compiler/snapshot.d.ts.map +1 -0
- package/lib/types/compiler/snapshot.js +2 -0
- package/lib/types/compiler/snapshot.js.map +1 -0
- package/lib/types/config-schema.d.ts +6 -3
- package/lib/types/config-schema.d.ts.map +1 -1
- package/lib/types/config-schema.js +6 -2
- package/lib/types/config-schema.js.map +1 -1
- package/lib/types/convert/host.d.ts +6 -5
- package/lib/types/convert/host.d.ts.map +1 -1
- package/lib/types/convert/host.js +58 -18
- package/lib/types/convert/host.js.map +1 -1
- package/lib/types/convert/ingest.d.ts +10 -1
- package/lib/types/convert/ingest.d.ts.map +1 -1
- package/lib/types/convert/ingest.js +68 -9
- package/lib/types/convert/ingest.js.map +1 -1
- package/lib/types/derive-contract.d.ts +3 -0
- package/lib/types/derive-contract.d.ts.map +1 -0
- package/lib/types/derive-contract.js +15 -0
- package/lib/types/derive-contract.js.map +1 -0
- package/lib/types/diagnosis/cards.d.ts +7 -3
- package/lib/types/diagnosis/cards.d.ts.map +1 -1
- package/lib/types/diagnosis/cards.js +13 -8
- package/lib/types/diagnosis/cards.js.map +1 -1
- package/lib/types/diagnosis/run.d.ts +4 -13
- package/lib/types/diagnosis/run.d.ts.map +1 -1
- package/lib/types/diagnosis/run.js +26 -16
- package/lib/types/diagnosis/run.js.map +1 -1
- package/lib/types/diagnosis/schema.js +2 -2
- package/lib/types/diagnosis/schema.js.map +1 -1
- package/lib/types/diagnosis/seed-source.d.ts +1 -1
- package/lib/types/diagnosis/seed-source.d.ts.map +1 -1
- package/lib/types/diagnosis/seed-source.js +5 -4
- package/lib/types/diagnosis/seed-source.js.map +1 -1
- package/lib/types/diagnosis/seed.d.ts +4 -4
- package/lib/types/diagnosis/seed.d.ts.map +1 -1
- package/lib/types/diagnosis/seed.js +6 -8
- package/lib/types/diagnosis/seed.js.map +1 -1
- package/lib/types/diagnosis/store.d.ts +24 -18
- package/lib/types/diagnosis/store.d.ts.map +1 -1
- package/lib/types/diagnosis/store.js +130 -65
- package/lib/types/diagnosis/store.js.map +1 -1
- package/lib/types/diagnosis/types.d.ts +47 -15
- package/lib/types/diagnosis/types.d.ts.map +1 -1
- package/lib/types/diagnosis/types.js.map +1 -1
- package/lib/types/environment/dsh-python.d.ts +77 -0
- package/lib/types/environment/dsh-python.d.ts.map +1 -0
- package/lib/types/environment/dsh-python.js +139 -0
- package/lib/types/environment/dsh-python.js.map +1 -0
- package/lib/types/environment/install.d.ts +15 -0
- package/lib/types/environment/install.d.ts.map +1 -0
- package/lib/types/environment/install.js +297 -0
- package/lib/types/environment/install.js.map +1 -0
- package/lib/types/environment/manifest.d.ts +208 -0
- package/lib/types/environment/manifest.d.ts.map +1 -0
- package/lib/types/environment/manifest.js +26 -0
- package/lib/types/environment/manifest.js.map +1 -0
- package/lib/types/environment/model-catalog.d.ts +223 -0
- package/lib/types/environment/model-catalog.d.ts.map +1 -0
- package/lib/types/environment/model-catalog.js +129 -0
- package/lib/types/environment/model-catalog.js.map +1 -0
- package/lib/types/environment/process.d.ts +10 -0
- package/lib/types/environment/process.d.ts.map +1 -0
- package/lib/types/environment/process.js +54 -0
- package/lib/types/environment/process.js.map +1 -0
- package/lib/types/environment/selection.d.ts +9 -0
- package/lib/types/environment/selection.d.ts.map +1 -0
- package/lib/types/environment/selection.js +29 -0
- package/lib/types/environment/selection.js.map +1 -0
- package/lib/types/environment/service.d.ts +64 -0
- package/lib/types/environment/service.d.ts.map +1 -0
- package/lib/types/environment/service.js +424 -0
- package/lib/types/environment/service.js.map +1 -0
- package/lib/types/environment/types.d.ts +56 -0
- package/lib/types/environment/types.d.ts.map +1 -0
- package/lib/types/environment/types.js +2 -0
- package/lib/types/environment/types.js.map +1 -0
- package/lib/types/events.d.ts +76 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +52 -0
- package/lib/types/events.js.map +1 -0
- package/lib/types/extract-contract.d.ts +3 -0
- package/lib/types/extract-contract.d.ts.map +1 -0
- package/lib/types/extract-contract.js +41 -0
- package/lib/types/extract-contract.js.map +1 -0
- package/lib/types/extract-model.d.ts +5 -0
- package/lib/types/extract-model.d.ts.map +1 -1
- package/lib/types/extract-model.js.map +1 -1
- package/lib/types/extract-table-contract.d.ts +3 -0
- package/lib/types/extract-table-contract.d.ts.map +1 -0
- package/lib/types/extract-table-contract.js +27 -0
- package/lib/types/extract-table-contract.js.map +1 -0
- package/lib/types/extract-table.d.ts +8 -0
- package/lib/types/extract-table.d.ts.map +1 -0
- package/lib/types/extract-table.js +158 -0
- package/lib/types/extract-table.js.map +1 -0
- package/lib/types/extraction-runs.d.ts +30 -6
- package/lib/types/extraction-runs.d.ts.map +1 -1
- package/lib/types/extraction-runs.js +69 -8
- package/lib/types/extraction-runs.js.map +1 -1
- package/lib/types/fs-atomic.d.ts +0 -7
- package/lib/types/fs-atomic.d.ts.map +1 -1
- package/lib/types/fs-atomic.js +17 -2
- package/lib/types/fs-atomic.js.map +1 -1
- package/lib/types/images.d.ts +26 -0
- package/lib/types/images.d.ts.map +1 -0
- package/lib/types/images.js +196 -0
- package/lib/types/images.js.map +1 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +598 -209
- package/lib/types/index.js.map +1 -1
- package/lib/types/intent/engine.d.ts +12 -4
- package/lib/types/intent/engine.d.ts.map +1 -1
- package/lib/types/intent/engine.js +43 -5
- package/lib/types/intent/engine.js.map +1 -1
- package/lib/types/intent/host.d.ts +5 -8
- package/lib/types/intent/host.d.ts.map +1 -1
- package/lib/types/intent/host.js +56 -11
- package/lib/types/intent/host.js.map +1 -1
- package/lib/types/intent/scope.d.ts +25 -0
- package/lib/types/intent/scope.d.ts.map +1 -0
- package/lib/types/intent/scope.js +116 -0
- package/lib/types/intent/scope.js.map +1 -0
- package/lib/types/intent/tools.d.ts +24 -20
- package/lib/types/intent/tools.d.ts.map +1 -1
- package/lib/types/intent/tools.js +65 -23
- package/lib/types/intent/tools.js.map +1 -1
- package/lib/types/intent/types.d.ts +11 -4
- package/lib/types/intent/types.d.ts.map +1 -1
- package/lib/types/knowledge-bases.d.ts +11 -5
- package/lib/types/knowledge-bases.d.ts.map +1 -1
- package/lib/types/knowledge-bases.js +52 -20
- package/lib/types/knowledge-bases.js.map +1 -1
- package/lib/types/knowledge-contract.d.ts +32 -0
- package/lib/types/knowledge-contract.d.ts.map +1 -0
- package/lib/types/knowledge-contract.js +116 -0
- package/lib/types/knowledge-contract.js.map +1 -0
- package/lib/types/knowledge.d.ts +31 -9
- package/lib/types/knowledge.d.ts.map +1 -1
- package/lib/types/knowledge.js +137 -60
- package/lib/types/knowledge.js.map +1 -1
- package/lib/types/layout.d.ts +10 -29
- package/lib/types/layout.d.ts.map +1 -1
- package/lib/types/layout.js +17 -36
- package/lib/types/layout.js.map +1 -1
- package/lib/types/materialize-snapshot.d.ts +49 -0
- package/lib/types/materialize-snapshot.d.ts.map +1 -0
- package/lib/types/materialize-snapshot.js +2 -0
- package/lib/types/materialize-snapshot.js.map +1 -0
- package/lib/types/migrate.d.ts +11 -0
- package/lib/types/migrate.d.ts.map +1 -1
- package/lib/types/migrate.js +83 -2
- package/lib/types/migrate.js.map +1 -1
- package/lib/types/model-text.d.ts +58 -1
- package/lib/types/model-text.d.ts.map +1 -1
- package/lib/types/model-text.js +85 -30
- package/lib/types/model-text.js.map +1 -1
- package/lib/types/oplog.d.ts.map +1 -1
- package/lib/types/oplog.js +7 -0
- package/lib/types/oplog.js.map +1 -1
- package/lib/types/organize-contract.d.ts +18 -0
- package/lib/types/organize-contract.d.ts.map +1 -0
- package/lib/types/organize-contract.js +82 -0
- package/lib/types/organize-contract.js.map +1 -0
- package/lib/types/pipeline/engine.d.ts +66 -0
- package/lib/types/pipeline/engine.d.ts.map +1 -0
- package/lib/types/pipeline/engine.js +352 -0
- package/lib/types/pipeline/engine.js.map +1 -0
- package/lib/types/pipeline/store.d.ts +73 -0
- package/lib/types/pipeline/store.d.ts.map +1 -0
- package/lib/types/pipeline/store.js +143 -0
- package/lib/types/pipeline/store.js.map +1 -0
- package/lib/types/pipeline/types.d.ts +102 -0
- package/lib/types/pipeline/types.d.ts.map +1 -0
- package/lib/types/pipeline/types.js +5 -0
- package/lib/types/pipeline/types.js.map +1 -0
- package/lib/types/present.d.ts +2 -0
- package/lib/types/present.d.ts.map +1 -1
- package/lib/types/present.js +9 -4
- package/lib/types/present.js.map +1 -1
- package/lib/types/preset-ids.d.ts +4 -0
- package/lib/types/preset-ids.d.ts.map +1 -0
- package/lib/types/preset-ids.js +6 -0
- package/lib/types/preset-ids.js.map +1 -0
- package/lib/types/query-analysis.d.ts +13 -1
- package/lib/types/query-analysis.d.ts.map +1 -1
- package/lib/types/query-analysis.js +62 -6
- package/lib/types/query-analysis.js.map +1 -1
- package/lib/types/recall-rank.d.ts +3 -3
- package/lib/types/recall-rank.d.ts.map +1 -1
- package/lib/types/recall-rank.js +4 -4
- package/lib/types/recall-rank.js.map +1 -1
- package/lib/types/retention.d.ts +39 -0
- package/lib/types/retention.d.ts.map +1 -0
- package/lib/types/retention.js +42 -0
- package/lib/types/retention.js.map +1 -0
- package/lib/types/retrieval/vector-index.d.ts +32 -0
- package/lib/types/retrieval/vector-index.d.ts.map +1 -0
- package/lib/types/retrieval/vector-index.js +15 -0
- package/lib/types/retrieval/vector-index.js.map +1 -0
- package/lib/types/retrieval/visibility.d.ts +6 -0
- package/lib/types/retrieval/visibility.d.ts.map +1 -0
- package/lib/types/retrieval/visibility.js +11 -0
- package/lib/types/retrieval/visibility.js.map +1 -0
- package/lib/types/runtime.d.ts +272 -27
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/runtime.js +2751 -537
- package/lib/types/runtime.js.map +1 -1
- package/lib/types/settings-schema.d.ts +17 -15
- package/lib/types/settings-schema.d.ts.map +1 -1
- package/lib/types/settings-schema.js +50 -47
- package/lib/types/settings-schema.js.map +1 -1
- package/lib/types/settings-volatile.d.ts +4 -4
- package/lib/types/settings-volatile.js +4 -4
- package/lib/types/source-evidence.d.ts +14 -0
- package/lib/types/source-evidence.d.ts.map +1 -0
- package/lib/types/source-evidence.js +36 -0
- package/lib/types/source-evidence.js.map +1 -0
- package/lib/types/store/axis-references.d.ts +5 -0
- package/lib/types/store/axis-references.d.ts.map +1 -0
- package/lib/types/store/axis-references.js +106 -0
- package/lib/types/store/axis-references.js.map +1 -0
- package/lib/types/store/derived.d.ts +12 -1
- package/lib/types/store/derived.d.ts.map +1 -1
- package/lib/types/store/derived.js +71 -12
- package/lib/types/store/derived.js.map +1 -1
- package/lib/types/store/knowledge-db.d.ts +31 -1
- package/lib/types/store/knowledge-db.d.ts.map +1 -1
- package/lib/types/store/knowledge-db.js +252 -18
- package/lib/types/store/knowledge-db.js.map +1 -1
- package/lib/types/store/migrate.d.ts.map +1 -1
- package/lib/types/store/migrate.js +17 -6
- package/lib/types/store/migrate.js.map +1 -1
- package/lib/types/trajectory-types.d.ts +172 -0
- package/lib/types/trajectory-types.d.ts.map +1 -0
- package/lib/types/trajectory-types.js +36 -0
- package/lib/types/trajectory-types.js.map +1 -0
- package/lib/types/types.d.ts +59 -27
- package/lib/types/types.d.ts.map +1 -1
- package/lib/types/types.js +6 -15
- package/lib/types/types.js.map +1 -1
- package/lib/types/wiki-finalize.d.ts +16 -0
- package/lib/types/wiki-finalize.d.ts.map +1 -1
- package/lib/types/wiki-finalize.js +26 -0
- package/lib/types/wiki-finalize.js.map +1 -1
- package/lib/types/wiki-materialize.d.ts +4 -0
- package/lib/types/wiki-materialize.d.ts.map +1 -1
- package/lib/types/wiki-materialize.js +21 -7
- package/lib/types/wiki-materialize.js.map +1 -1
- package/lib/types/wiki-trial-types.d.ts +87 -0
- package/lib/types/wiki-trial-types.d.ts.map +1 -1
- package/lib/types/wiki-trial-types.js +0 -16
- package/lib/types/wiki-trial-types.js.map +1 -1
- package/lib/types/wiki-trial.d.ts +40 -16
- package/lib/types/wiki-trial.d.ts.map +1 -1
- package/lib/types/wiki-trial.js +337 -224
- package/lib/types/wiki-trial.js.map +1 -1
- package/package.json +29 -20
- package/python/prepare-models.py +19 -0
- package/python/requirements.txt +8 -6
- package/scripts/doctor.mjs +13 -19
- package/scripts/environment.mjs +29 -0
- package/scripts/setup-embedding.sh +15 -5
- package/src/agent-behavior-rules.ts +37 -0
- package/src/axis-registry.ts +234 -27
- package/src/card-organize.ts +69 -75
- package/src/client/AgentBehaviorRulesCard.tsx +65 -0
- package/src/client/AttributionEventGuide.tsx +41 -39
- package/src/client/AxisRegistrySection.tsx +204 -164
- package/src/client/CompileDialogs.tsx +44 -29
- package/src/client/DeleteDocumentDialog.tsx +36 -5
- package/src/client/DirectoryPicker.tsx +0 -10
- package/src/client/EnvironmentSetup.tsx +243 -0
- package/src/client/ExpansionGraph.tsx +13 -7
- package/src/client/ExtractionTasksPage.tsx +578 -0
- package/src/client/GuideArchitectureCanvas.tsx +470 -0
- package/src/client/ImportFilesDialog.tsx +2 -13
- package/src/client/IntentLogic.tsx +2 -2
- package/src/client/IntentTab.tsx +118 -47
- package/src/client/KnowledgeBaseTab.tsx +277 -197
- package/src/client/KnowledgeLayerSection.tsx +24 -6
- package/src/client/KnowledgePanel.tsx +58 -93
- package/src/client/KnowledgeSettingsDrawer.tsx +90 -0
- package/src/client/ListPager.tsx +15 -5
- package/src/client/MaterializeTrajectoryView.tsx +124 -0
- package/src/client/NodeSettings.tsx +210 -89
- package/src/client/NormalizeTrajectoryView.tsx +136 -0
- package/src/client/PipelineNotice.tsx +26 -0
- package/src/client/PreviewSections.tsx +118 -51
- package/src/client/RecallPanel.tsx +89 -85
- package/src/client/TabGuide.tsx +159 -184
- package/src/client/TrialReportView.tsx +391 -214
- package/src/client/TypeDefinitionDrawer.tsx +150 -23
- package/src/client/WikiCardPreview.tsx +62 -16
- package/src/client/WikiFlowPanel.tsx +4 -4
- package/src/client/arch/NodeLogicPanel.tsx +3 -4
- package/src/client/arch/model.ts +6 -9
- package/src/client/architecture.tsx +23 -33
- package/src/client/attribution/AttributionGraph.tsx +10 -6
- package/src/client/attribution/AttributionTab.tsx +136 -84
- package/src/client/attribution/CaseView.tsx +3 -1
- package/src/client/attribution/EventView.tsx +108 -0
- package/src/client/attribution/RunView.tsx +2 -2
- package/src/client/attribution/StageChrome.tsx +34 -3
- package/src/client/attribution/ViewSwitch.tsx +20 -5
- package/src/client/attribution/graph-options.ts +47 -39
- package/src/client/attribution/model.ts +17 -10
- package/src/client/config-scope.ts +3 -3
- package/src/client/graph/palette.ts +165 -0
- package/src/client/index.ts +49 -42
- package/src/client/pages.css +459 -135
- package/src/client/pages.tsx +37 -9
- package/src/client/problem-domains.ts +1 -1
- package/src/client/session-remote.ts +9 -0
- package/src/client/styles.css +205 -62
- package/src/client/wiki-trial.ts +44 -3
- package/src/compiler/embedding-identity.ts +21 -0
- package/src/compiler/snapshot.ts +17 -0
- package/src/config-schema.ts +8 -3
- package/src/convert/host.ts +56 -21
- package/src/convert/ingest.ts +74 -10
- package/src/derive-contract.ts +14 -0
- package/src/diagnosis/cards.ts +13 -8
- package/src/diagnosis/run.ts +27 -17
- package/src/diagnosis/schema.ts +2 -2
- package/src/diagnosis/seed-source.ts +5 -4
- package/src/diagnosis/seed.ts +6 -8
- package/src/diagnosis/store.ts +138 -69
- package/src/diagnosis/types.ts +34 -15
- package/src/environment/dsh-python.ts +156 -0
- package/src/environment/install.ts +244 -0
- package/src/environment/manifest.ts +28 -0
- package/src/environment/model-catalog.ts +147 -0
- package/src/environment/process.ts +54 -0
- package/src/environment/selection.ts +29 -0
- package/src/environment/service.ts +348 -0
- package/src/environment/types.ts +45 -0
- package/src/events.ts +108 -0
- package/src/extract-contract.ts +42 -0
- package/src/extract-model.ts +10 -1
- package/src/extract-table-contract.ts +26 -0
- package/src/extract-table.ts +132 -0
- package/src/extraction-runs.ts +70 -11
- package/src/fs-atomic.ts +19 -2
- package/src/images.ts +203 -0
- package/src/index.ts +553 -205
- package/src/intent/README.md +8 -6
- package/src/intent/engine.ts +44 -6
- package/src/intent/host.ts +59 -18
- package/src/intent/scope.ts +125 -0
- package/src/intent/tools.ts +70 -28
- package/src/intent/types.ts +11 -4
- package/src/knowledge-bases.ts +56 -20
- package/src/knowledge-contract.ts +114 -0
- package/src/knowledge.ts +138 -69
- package/src/layout.ts +17 -37
- package/src/materialize-snapshot.ts +46 -0
- package/src/migrate.ts +75 -2
- package/src/model-text.ts +109 -4
- package/src/oplog.ts +7 -0
- package/src/organize-contract.ts +83 -0
- package/src/pipeline/engine.ts +323 -0
- package/src/pipeline/store.ts +147 -0
- package/src/pipeline/types.ts +93 -0
- package/src/present.ts +10 -4
- package/src/preset-ids.ts +6 -0
- package/src/python/embedding_worker.py +66 -2
- package/src/query-analysis.ts +68 -8
- package/src/recall-rank.ts +5 -5
- package/src/retention.ts +76 -0
- package/src/retrieval/vector-index.ts +45 -0
- package/src/retrieval/visibility.ts +14 -0
- package/src/runtime.ts +2708 -567
- package/src/settings-schema.ts +11 -8
- package/src/settings-volatile.ts +4 -4
- package/src/source-evidence.ts +37 -0
- package/src/store/axis-references.ts +96 -0
- package/src/store/derived.ts +70 -12
- package/src/store/knowledge-db.ts +248 -17
- package/src/store/migrate.ts +16 -6
- package/src/trajectory-types.ts +142 -0
- package/src/types.ts +61 -35
- package/src/wiki-finalize.ts +28 -0
- package/src/wiki-materialize.ts +25 -6
- package/src/wiki-trial-types.ts +83 -1
- package/src/wiki-trial.ts +357 -185
- package/lib/types/intent/preset-tools.d.ts +0 -37
- package/lib/types/intent/preset-tools.d.ts.map +0 -1
- package/lib/types/intent/preset-tools.js +0 -45
- package/lib/types/intent/preset-tools.js.map +0 -1
- package/preset/tita-data-agent/agent.cordis.yml +0 -394
- package/preset/tita-data-agent/preset.yml +0 -3
- package/scripts/install-agent-preset.mjs +0 -92
- package/scripts/sync-agent-preset.mjs +0 -188
- package/src/client/AgentPresetCard.tsx +0 -247
- package/src/client/agent-preset.ts +0 -121
- package/src/client/convert/ConvertPanel.tsx +0 -583
- package/src/client/convert/styles.css +0 -138
- package/src/client/convert/styles.ts +0 -49
- package/src/intent/preset-tools.ts +0 -48
package/src/diagnosis/schema.ts
CHANGED
|
@@ -247,8 +247,8 @@ export function validateDiagnosis(graph: AttributionGraphData): DiagnosisIssue[]
|
|
|
247
247
|
if (!node.verdict) issues.push(fieldIssue(node, 'verdict', '证据必须给出结论:supports / refutes / inconclusive'))
|
|
248
248
|
if (!node.why?.trim()) issues.push(fieldIssue(node, 'why', '证据必须说明「为什么这个结果算数或不算数」—— 采信与剔除都得能说理由'))
|
|
249
249
|
}
|
|
250
|
-
// `case`
|
|
251
|
-
//
|
|
250
|
+
// `case` 节点只是兼容旧图的桩;当前排查视图由 SourceRaw 记录派生,
|
|
251
|
+
// 新排查不会再写 diagnosis/case WikiCard。
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
// ── 第二层:引用完整性 ────────────────────────────────────────────────────
|
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
* 所以 seed 也走完整条动线:
|
|
7
7
|
*
|
|
8
8
|
* ```
|
|
9
|
-
*
|
|
9
|
+
* 原文(SourceRaw) → 抽取 Knowledge / Event → 归一
|
|
10
|
+
* 排查运行记录(SourceRaw) → 只读 Case 视图
|
|
10
11
|
* ```
|
|
11
12
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* 手册与复盘是**人写的散文**(就是下面这些字面量)。载入示例只保存来源与可复用诊断卡;
|
|
14
|
+
* Case 从独立的排查运行记录派生,不生成第二张诊断卡。
|
|
14
15
|
*/
|
|
15
16
|
import { SEED_CASES, SEED_RUNS } from './seed.js'
|
|
16
17
|
import { renderRunSource } from './run.js'
|
|
@@ -83,7 +84,7 @@ export const SEED_HANDBOOK = `# 日报指标异常排查手册(内部版)
|
|
|
83
84
|
同一批假设被反复验证,而永远不会被剪掉 —— 图上会长出一堆僵尸边。
|
|
84
85
|
`
|
|
85
86
|
|
|
86
|
-
/**
|
|
87
|
+
/** 三篇复盘:供后续抽取 Knowledge / Event 的来源文档。 */
|
|
87
88
|
export function seedCaseSources(): SeedSource[] {
|
|
88
89
|
return SEED_CASES.map(item => ({
|
|
89
90
|
id: item.id,
|
package/src/diagnosis/seed.ts
CHANGED
|
@@ -19,7 +19,7 @@ import type { AttributionCase, AttributionGraphData, DiagnosisRunRecord } from '
|
|
|
19
19
|
* | `question` | 人 | 手册与复盘 —— 卡片 `source_refs` 指向这里 |
|
|
20
20
|
* | `agent_diagnosis_case` | Agent | 一次排查的过程记录(`SEED_RUNS`) |
|
|
21
21
|
*
|
|
22
|
-
* `SEED_GRAPH`
|
|
22
|
+
* `SEED_GRAPH` 里有可复用诊断 Knowledge 与引用层资产;历史案例桩只用于旧格式兼容夹具。
|
|
23
23
|
* `evidence` / `cause` 与四条执行边由 `SEED_RUNS` 读时解析出来 —— 把「上次查到什么」
|
|
24
24
|
* 写进卡片,等于让一份可复用的知识绑死在一次执行上。
|
|
25
25
|
*/
|
|
@@ -122,10 +122,8 @@ export const SEED_GRAPH: AttributionGraphData = {
|
|
|
122
122
|
{ id: 'metric_daily_gmv', kind: 'asset', layer: 'reference', title: 'metric_daily_gmv', assetType: 'metric' },
|
|
123
123
|
{ id: 'bi_daily_dashboard', kind: 'asset', layer: 'reference', title: 'bi_daily_dashboard', assetType: 'linkage' },
|
|
124
124
|
|
|
125
|
-
// ──
|
|
126
|
-
//
|
|
127
|
-
// (而且还真的不一致过:「只剩」vs「只有」)。画布要在标签前显示案例 id,
|
|
128
|
-
// 那是渲染层的事(见 `nodeStyleFor` 的 labelText)。
|
|
125
|
+
// ── 兼容层:旧格式里的案例节点桩。新样例的排查记录由 SEED_RUNS 派生为只读视图。 ──
|
|
126
|
+
// 保留稳定 ID,供旧卡片编解码与历史图迁移夹具使用。
|
|
129
127
|
{ id: 'CASE-001', kind: 'case', layer: 'instance', title: '日报 GMV 为 0' },
|
|
130
128
|
{ id: 'CASE-002', kind: 'case', layer: 'instance', title: '订单数只有昨日 12%' },
|
|
131
129
|
{ id: 'CASE-003', kind: 'case', layer: 'instance', title: 'DAU 突增 3.1 倍' },
|
|
@@ -197,7 +195,7 @@ export const SEED_GRAPH: AttributionGraphData = {
|
|
|
197
195
|
],
|
|
198
196
|
}
|
|
199
197
|
|
|
200
|
-
/**
|
|
198
|
+
/** 旧版示例 Case 投影夹具;仅供历史卡片编解码与来源文案使用,当前载入流程不落盘。 */
|
|
201
199
|
export const SEED_CASES: AttributionCase[] = [
|
|
202
200
|
{
|
|
203
201
|
id: 'CASE-001',
|
|
@@ -280,8 +278,8 @@ export const SEED_CASES: AttributionCase[] = [
|
|
|
280
278
|
* 三次排查的**过程记录**(`agent_diagnosis_case`)。
|
|
281
279
|
*
|
|
282
280
|
* 它们与 `SEED_CASES` 一一对应,但**不是同一份东西**:这里是 Agent 跑出来的原始记录
|
|
283
|
-
*
|
|
284
|
-
*
|
|
281
|
+
* (每条检查点真跑了什么、看到什么、这个结果算不算数);当前 Case 视图从运行记录派生,
|
|
282
|
+
* `SEED_CASES` 仅保留作旧卡片格式夹具。
|
|
285
283
|
*
|
|
286
284
|
* `E7` 是 CASE-001 里那次**贵的否定**:T7.2 直连明细对账推翻了 H7。它不在案例的
|
|
287
285
|
* 主路径上(主路径早就确认了 H1),但它是这次排查最贵的一条知识 —— 40 分钟的误导段
|
package/src/diagnosis/store.ts
CHANGED
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
cardFromRecord, cardsToGraph, CARD_EDGE_KINDS, graphToCards, parseCard, serializeCard,
|
|
8
8
|
RUN_EDGE_KINDS, type DiagnosisCard,
|
|
9
9
|
} from './cards.js'
|
|
10
|
-
import {
|
|
10
|
+
import { caseViewOfRun, parseRunSource, renderRunSource, runReferenceProblems, runToGraph } from './run.js'
|
|
11
11
|
import type {
|
|
12
|
-
AttributionCase, AttributionEdge, AttributionGraphData, AttributionNode, AttributionNodeKind, DiagnosisRunRecord,
|
|
12
|
+
AttributionCase, AttributionEdge, AttributionEvent, AttributionGraphData, AttributionNode, AttributionNodeKind, DiagnosisRunRecord,
|
|
13
13
|
} from './types.js'
|
|
14
14
|
import type { KnowledgeRuntime } from '../runtime.js'
|
|
15
15
|
import type { SchemaType } from '../types.js'
|
|
@@ -22,7 +22,7 @@ import type { SchemaType } from '../types.js'
|
|
|
22
22
|
* | 目录 | 内容 | 谁是真相 |
|
|
23
23
|
* | --- | --- | --- |
|
|
24
24
|
* | `01_source_raw/` | 手册、复盘与排查原文 | SourceRaw 的唯一真相 |
|
|
25
|
-
* | `02_wiki/diagnosis/` |
|
|
25
|
+
* | `02_wiki/diagnosis/` | 历史诊断卡片 | 仅为旧数据兼容读取;新排查不再写 diagnosis/case 卡片 |
|
|
26
26
|
*
|
|
27
27
|
* `05_diagnosis/` 在 v1.1 撤销了(0021 §0.3)。它同时装着两类东西 —— 「一次排查的产物」
|
|
28
28
|
* (源头)与「五类模板卡」(配置)—— 一个编号段混装两种性质,`rebuild --only` 的语义
|
|
@@ -58,12 +58,13 @@ const LEGACY_RUN_SHARDS: Record<string, AttributionNodeKind> = {
|
|
|
58
58
|
'causes.jsonl': 'cause',
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/**
|
|
62
|
-
export type DiagnosisSource = 'cards' | 'jsonl' | 'empty'
|
|
61
|
+
/** 读取来源,界面据此说明当前展示的是卡片、记录、旧快照还是空库。 */
|
|
62
|
+
export type DiagnosisSource = 'cards' | 'records' | 'jsonl' | 'empty'
|
|
63
63
|
|
|
64
64
|
export interface DiagnosisSnapshot {
|
|
65
65
|
graph: AttributionGraphData
|
|
66
66
|
cases: AttributionCase[]
|
|
67
|
+
events: AttributionEvent[]
|
|
67
68
|
issues: DiagnosisIssue[]
|
|
68
69
|
/** 数据是不是本次调用从内置示例写进去的(只有 `loadSample()` 会把它变成 true)。 */
|
|
69
70
|
seeded: boolean
|
|
@@ -86,7 +87,7 @@ export interface DiagnosisSnapshot {
|
|
|
86
87
|
* `loadSources` 是 v1.1 新增的:一次排查的产物现在是一条 `agent_diagnosis_case`
|
|
87
88
|
* 的 SourceRaw,归因图读的是它,而不是自造的 jsonl。
|
|
88
89
|
*/
|
|
89
|
-
type DiagnosisHost = Pick<KnowledgeRuntime, 'rootDir' | 'addSource' | 'writeCard' | 'loadSources' | 'loadCards' | 'readCard'>
|
|
90
|
+
type DiagnosisHost = Pick<KnowledgeRuntime, 'rootDir' | 'addSource' | 'writeCard' | 'loadSources' | 'loadCards' | 'loadEvents' | 'readCard' | 'knowledgeStoreAvailable'>
|
|
90
91
|
|
|
91
92
|
export class DiagnosisStore {
|
|
92
93
|
constructor(private readonly host: DiagnosisHost) {}
|
|
@@ -112,65 +113,111 @@ export class DiagnosisStore {
|
|
|
112
113
|
* 造出「设置里改了、磁盘上那份没改」的第二真源。
|
|
113
114
|
*/
|
|
114
115
|
async ensure(): Promise<{ seeded: boolean; migrated: boolean; problems: string[] }> {
|
|
116
|
+
/**
|
|
117
|
+
* **「读不到」不等于「空」**(0070)。
|
|
118
|
+
*
|
|
119
|
+
* `readCards()` 在存储不可用时返回空数组,于是「node:sqlite 连不上 / 属主标记不符 /
|
|
120
|
+
* 权限不对」会被读成「这个库什么都还没有」,接着走下面的旧格式迁移 —— 那是一次
|
|
121
|
+
* **写**(会写入内置种子来源与几十张卡)。一次可恢复的读故障就这样变成不可逆的污染。
|
|
122
|
+
* 所以先问一句存储到底在不在,不在就什么都不做,并如实报出来。
|
|
123
|
+
*/
|
|
124
|
+
if (!await this.host.knowledgeStoreAvailable()) {
|
|
125
|
+
return { seeded: false, migrated: false, problems: ['知识存储当前不可用,已跳过内置示例与旧格式迁移;请先解决存储问题再打开本页。'] }
|
|
126
|
+
}
|
|
115
127
|
if ((await this.readCards()).length > 0) return { seeded: false, migrated: false, problems: [] }
|
|
116
128
|
if ((await this.legacyShardFiles()).length > 0) return await this.migrate()
|
|
117
129
|
return { seeded: false, migrated: false, problems: [] }
|
|
118
130
|
}
|
|
119
131
|
|
|
120
132
|
/**
|
|
121
|
-
* 载入**内置示例**:一份排查手册 + 三篇复盘 + 三次排查日志 → SourceRaw
|
|
133
|
+
* 载入**内置示例**:一份排查手册 + 三篇复盘 + 三次排查日志 → SourceRaw、可复用诊断卡与只读排查视图。
|
|
122
134
|
*
|
|
123
135
|
* 只有用户明确点了「载入内置示例」才走这里(`ensure()` 不再自动调用)。幂等:
|
|
124
136
|
* `addSource` 按 `externalId`、`writeCard` 按 entityId,点两次不会写出第二份。
|
|
125
137
|
*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* `confirmedBy = user:load-sample`,然后照常走 `writeCard`。这样做的两个好处:
|
|
129
|
-
* 待办区里能看到这批卡片是怎么来的;而「未确认不落 `02_wiki/`」这条规则没有被开一个
|
|
130
|
-
* 后门 —— 例外是**确认者的身份**,不是门的缺失。
|
|
138
|
+
* 示例里的可复用诊断 Knowledge 是预先整理好的演示数据,直接写入当前知识库。
|
|
139
|
+
* 三条排查记录作为 SourceRaw 写入,并由读取层派生只读 Case 视图;不创建 `diagnosis/case` WikiCard。
|
|
131
140
|
*/
|
|
132
141
|
async loadSample(): Promise<{ seeded: boolean; migrated: boolean; problems: string[] }> {
|
|
142
|
+
/**
|
|
143
|
+
* 载入示例是一次**写**,所以门要在服务端,不能只在界面上。
|
|
144
|
+
*
|
|
145
|
+
* `canLoadSample` 原来只出现在 `snapshot()` 的返回值里,用来决定那枚按钮显不显示 ——
|
|
146
|
+
* 而 `POST /diagnosis/sample` 直接调这里。任何非界面的调用方(脚本、旧标签页、
|
|
147
|
+
* 以后的 runbook)打一次,就能在一个已经有真实知识的库上注入一整套演示数据,
|
|
148
|
+
* 库里于是有两份互相矛盾的知识,而这正是本文件开头要防的事。
|
|
149
|
+
*
|
|
150
|
+
* **不给覆盖开关**:曾经加过一个 `force`,但它没有任何调用方(路由按无参调用),
|
|
151
|
+
* 而且「往有真实知识的库里再塞一套演示」本来就不该是一个可选项 —— 那正是这条门要防的。
|
|
152
|
+
*/
|
|
153
|
+
const allowed = await this.sampleAllowed()
|
|
154
|
+
if (!allowed.ok) {
|
|
155
|
+
return { seeded: false, migrated: false, problems: [`这个知识库里已经有内容(${allowed.reason}),不再载入内置示例。`] }
|
|
156
|
+
}
|
|
133
157
|
const { problems: sourceProblems, refs } = await this.writeSources(seedSources())
|
|
134
|
-
const cards = withSourceRefs(
|
|
158
|
+
const cards = withSourceRefs(
|
|
159
|
+
graphToCards(SEED_GRAPH),
|
|
160
|
+
refs,
|
|
161
|
+
SEED_CASES,
|
|
162
|
+
)
|
|
135
163
|
const problems = [...sourceProblems, ...await this.writeCards(cards, 'user:load-sample')]
|
|
136
164
|
return { seeded: true, migrated: false, problems }
|
|
137
165
|
}
|
|
138
166
|
|
|
167
|
+
/** Read Event entities for the Knowledge & Event view without building the diagnosis graph. */
|
|
168
|
+
async listEvents(): Promise<AttributionEvent[]> {
|
|
169
|
+
return this.readEvents()
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 「能不能载入内置示例」的**唯一**判据 —— 只看四个计数。
|
|
174
|
+
*
|
|
175
|
+
* 抽出来是因为它有两个消费者(`snapshot()` 的 `canLoadSample` 与 `loadSample()` 的门),
|
|
176
|
+
* 各写一份的话,界面说「可以」而服务端说「不行」只是时间问题。判据与**读取**分开:
|
|
177
|
+
* 两边各自的读取是必要的(一个已经拿到了卡片/Event,一个还没读),规则不必要各写一遍。
|
|
178
|
+
*/
|
|
179
|
+
private static sampleGate(state: { cards: number; events: number; runs: number; shards: number }): { ok: boolean; reason?: string } {
|
|
180
|
+
if (state.cards > 0) return { ok: false, reason: '已经有卡片' }
|
|
181
|
+
if (state.events > 0) return { ok: false, reason: '已经有 Event' }
|
|
182
|
+
if (state.runs > 0) return { ok: false, reason: '已经有排查记录' }
|
|
183
|
+
if (state.shards > 0) return { ok: false, reason: '还有旧格式的 05_diagnosis 分片等待迁移' }
|
|
184
|
+
return { ok: true }
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private async sampleAllowed(): Promise<{ ok: boolean; reason?: string }> {
|
|
188
|
+
return DiagnosisStore.sampleGate({
|
|
189
|
+
cards: (await this.readCards()).length,
|
|
190
|
+
events: (await this.readEvents()).length,
|
|
191
|
+
runs: (await this.readRuns()).records.length,
|
|
192
|
+
shards: (await this.legacyShardFiles()).length,
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
139
196
|
async snapshot(): Promise<DiagnosisSnapshot> {
|
|
140
197
|
const { seeded, migrated, problems } = await this.ensure()
|
|
141
198
|
const cards = await this.readCards()
|
|
199
|
+
const events = await this.readEvents()
|
|
200
|
+
const baseGraph = cards.length > 0 ? { nodes: [], edges: [] } : await this.readLegacyGraph()
|
|
201
|
+
const baseCases = cards.length > 0 ? [] : await this.readLegacyCases()
|
|
202
|
+
const built = await this.buildGraph(cards, baseGraph, baseCases)
|
|
203
|
+
const runRecords = (await this.readRuns()).records
|
|
142
204
|
/**
|
|
143
|
-
* 「什么都没有」=
|
|
205
|
+
* 「什么都没有」= 没有卡片、Event、排查日志和旧 jsonl。它是**可以载入内置示例**的唯一条件:
|
|
144
206
|
* 已经有知识(不管哪一代形态)时不该再往里塞示例 —— 那会变成第二份互相矛盾的知识。
|
|
145
207
|
*/
|
|
146
|
-
const canLoadSample =
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const built = await this.buildGraph(cards)
|
|
150
|
-
return {
|
|
151
|
-
graph: built.graph,
|
|
152
|
-
cases: built.cases,
|
|
153
|
-
issues: validateDiagnosis(built.graph),
|
|
154
|
-
seeded,
|
|
155
|
-
migrated,
|
|
156
|
-
source: 'cards',
|
|
157
|
-
canLoadSample: false,
|
|
158
|
-
problems: [...problems, ...built.problems],
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// 还没有卡片:旧 jsonl 就是当前可读的来源;两份都没有就是一个空库。
|
|
163
|
-
const graph = await this.readLegacyGraph()
|
|
164
|
-
const cases = await this.readLegacyCases()
|
|
208
|
+
const canLoadSample = DiagnosisStore.sampleGate({
|
|
209
|
+
cards: cards.length, events: events.length, runs: runRecords.length, shards: (await this.legacyShardFiles()).length,
|
|
210
|
+
}).ok
|
|
165
211
|
return {
|
|
166
|
-
graph,
|
|
167
|
-
cases,
|
|
168
|
-
|
|
212
|
+
graph: built.graph,
|
|
213
|
+
cases: built.cases,
|
|
214
|
+
events,
|
|
215
|
+
issues: validateDiagnosis(built.graph),
|
|
169
216
|
seeded,
|
|
170
217
|
migrated,
|
|
171
|
-
source: canLoadSample ? 'empty' : 'jsonl',
|
|
218
|
+
source: canLoadSample ? 'empty' : cards.length > 0 ? 'cards' : events.length > 0 || runRecords.length > 0 ? 'records' : 'jsonl',
|
|
172
219
|
canLoadSample,
|
|
173
|
-
problems,
|
|
220
|
+
problems: [...problems, ...built.problems],
|
|
174
221
|
}
|
|
175
222
|
}
|
|
176
223
|
|
|
@@ -181,21 +228,27 @@ export class DiagnosisStore {
|
|
|
181
228
|
* 与四条执行边全部来自 `agent_diagnosis_case` 的 SourceRaw。合成一张图是**读**的时候
|
|
182
229
|
* 做的,不是写的时候 —— 写的时候合成,等于让一次执行的结果变成可复用的知识。
|
|
183
230
|
*/
|
|
184
|
-
private async buildGraph(cards: DiagnosisCard[]): Promise<{ graph: AttributionGraphData; cases: AttributionCase[]; problems: string[] }> {
|
|
231
|
+
private async buildGraph(cards: DiagnosisCard[], baseGraph: AttributionGraphData = { nodes: [], edges: [] }, baseCases: AttributionCase[] = []): Promise<{ graph: AttributionGraphData; cases: AttributionCase[]; problems: string[] }> {
|
|
185
232
|
const compiled = cardsToGraph(cards)
|
|
186
233
|
const problems = [...compiled.problems]
|
|
187
|
-
const nodes: AttributionNode[] = [...compiled.graph.nodes]
|
|
188
|
-
const edges: AttributionEdge[] = [...compiled.graph.edges]
|
|
234
|
+
const nodes: AttributionNode[] = [...baseGraph.nodes, ...compiled.graph.nodes]
|
|
235
|
+
const edges: AttributionEdge[] = [...baseGraph.edges, ...compiled.graph.edges]
|
|
236
|
+
const knownCardNodes = [...baseGraph.nodes, ...compiled.graph.nodes]
|
|
237
|
+
const cases = new Map<string, AttributionCase>()
|
|
238
|
+
for (const item of [...baseCases, ...compiled.cases]) cases.set(item.id, item)
|
|
189
239
|
|
|
190
240
|
const runs = await this.readRuns()
|
|
191
241
|
problems.push(...runs.problems)
|
|
192
242
|
for (const record of runs.records) {
|
|
193
243
|
const run = runToGraph(record)
|
|
194
244
|
// 引用完整性要**连这次排查自己产出的 id 一起算**:路径里的 `E1` / `C1` 正是它写下的。
|
|
195
|
-
const known = new Set([...
|
|
245
|
+
const known = new Set([...knownCardNodes.map(node => node.id), ...run.nodes.map(node => node.id)])
|
|
196
246
|
problems.push(...run.problems, ...runReferenceProblems(record, known))
|
|
197
247
|
nodes.push(...run.nodes)
|
|
198
248
|
edges.push(...run.edges)
|
|
249
|
+
const symptomTitle = knownCardNodes.find(node => node.id === record.symptomId)?.title ?? record.symptomId
|
|
250
|
+
const view = caseViewOfRun(record, symptomTitle)
|
|
251
|
+
cases.set(view.id, view)
|
|
199
252
|
}
|
|
200
253
|
|
|
201
254
|
/**
|
|
@@ -210,7 +263,7 @@ export class DiagnosisStore {
|
|
|
210
263
|
nodes.push(...legacyRun.nodes)
|
|
211
264
|
edges.push(...legacyRun.edges)
|
|
212
265
|
|
|
213
|
-
return { graph: dedupe({ nodes, edges }, problems), cases:
|
|
266
|
+
return { graph: dedupe({ nodes, edges }, problems), cases: [...cases.values()], problems }
|
|
214
267
|
}
|
|
215
268
|
|
|
216
269
|
/**
|
|
@@ -238,14 +291,15 @@ export class DiagnosisStore {
|
|
|
238
291
|
|
|
239
292
|
async readGraph(): Promise<AttributionGraphData> {
|
|
240
293
|
const cards = await this.readCards()
|
|
241
|
-
|
|
242
|
-
return await this.
|
|
294
|
+
const baseGraph = cards.length > 0 ? { nodes: [], edges: [] } : await this.readLegacyGraph()
|
|
295
|
+
return (await this.buildGraph(cards, baseGraph)).graph
|
|
243
296
|
}
|
|
244
297
|
|
|
245
298
|
async readCases(): Promise<AttributionCase[]> {
|
|
246
299
|
const cards = await this.readCards()
|
|
247
|
-
|
|
248
|
-
|
|
300
|
+
const baseGraph = cards.length > 0 ? { nodes: [], edges: [] } : await this.readLegacyGraph()
|
|
301
|
+
const baseCases = cards.length > 0 ? [] : await this.readLegacyCases()
|
|
302
|
+
return (await this.buildGraph(cards, baseGraph, baseCases)).cases
|
|
249
303
|
}
|
|
250
304
|
|
|
251
305
|
/* ────────────────────────────────────────────── 卡片:读写 ── */
|
|
@@ -267,6 +321,35 @@ export class DiagnosisStore {
|
|
|
267
321
|
return cards
|
|
268
322
|
}
|
|
269
323
|
|
|
324
|
+
/** Event 与 Knowledge 同层,读取独立的 event 实体表。 */
|
|
325
|
+
private async readEvents(): Promise<AttributionEvent[]> {
|
|
326
|
+
const events = await this.host.loadEvents()
|
|
327
|
+
return events.map(event => ({
|
|
328
|
+
id: event.id,
|
|
329
|
+
title: event.title,
|
|
330
|
+
summary: event.summary,
|
|
331
|
+
identityType: event.identityType,
|
|
332
|
+
...(event.externalId ? { externalId: event.externalId } : {}),
|
|
333
|
+
...(event.occurredAt ? { occurredAt: event.occurredAt } : {}),
|
|
334
|
+
...(event.symptom ? { symptom: event.symptom } : {}),
|
|
335
|
+
coordinate: event.coordinate,
|
|
336
|
+
timeline: event.timeline.map((step, index) => ({
|
|
337
|
+
id: step.id || `timeline-${index + 1}`,
|
|
338
|
+
type: step.type,
|
|
339
|
+
description: step.description,
|
|
340
|
+
...(step.result ? { result: step.result } : {}),
|
|
341
|
+
...(step.at ? { at: step.at } : {}),
|
|
342
|
+
sourceId: step.sourceId,
|
|
343
|
+
})),
|
|
344
|
+
rootCauses: event.rootCauses,
|
|
345
|
+
outcomes: event.outcomes,
|
|
346
|
+
missing: event.missing,
|
|
347
|
+
sources: event.sources.filter(source => source.found && source.documentId && source.quote)
|
|
348
|
+
.map(source => ({ documentId: source.documentId, quote: source.quote })),
|
|
349
|
+
recordCount: event.records.length,
|
|
350
|
+
})).sort((left, right) => (right.occurredAt ?? '').localeCompare(left.occurredAt ?? '') || left.title.localeCompare(right.title))
|
|
351
|
+
}
|
|
352
|
+
|
|
270
353
|
/* ────────────────────────────────────────────── 一次排查的记录 ── */
|
|
271
354
|
|
|
272
355
|
/**
|
|
@@ -279,6 +362,7 @@ export class DiagnosisStore {
|
|
|
279
362
|
const records: DiagnosisRunRecord[] = []
|
|
280
363
|
const problems: string[] = []
|
|
281
364
|
for (const source of await this.host.loadSources()) {
|
|
365
|
+
if (!source.sourceId.startsWith('diagnosis:') && !source.content.includes('```json diagnosis-run')) continue
|
|
282
366
|
const record = parseRunSource(source.content)
|
|
283
367
|
if (record) records.push(record)
|
|
284
368
|
else problems.push(`诊断日志 ${source.sourceId} 里没有可解析的 \`json diagnosis-run\` 块,已跳过`)
|
|
@@ -287,15 +371,11 @@ export class DiagnosisStore {
|
|
|
287
371
|
}
|
|
288
372
|
|
|
289
373
|
/**
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
* 一次排查的价值就在于「当时是怎么走的」,让它停在待办队列里等于把经验丢掉。
|
|
294
|
-
* 卡片会被标成 `unreviewed`,人在「知识库 → Wiki」里 review 它。
|
|
295
|
-
*
|
|
296
|
-
* 幂等:`externalId` = runId,同一次排查重跑不会写出第二条来源;卡片按 entityId 写入。
|
|
374
|
+
* 一次排查结束只写一条 SourceRaw。案例视图从这条记录派生;Knowledge / Event 的抽取与归一
|
|
375
|
+
* 仍由知识处理阶段执行,避免把同一份排查过程再写成另一张 WikiCard。
|
|
376
|
+
* 幂等:`externalId` = runId,同一次排查重跑不会写出第二条来源。
|
|
297
377
|
*/
|
|
298
|
-
async recordRun(record: DiagnosisRunRecord): Promise<{ sourceId?: string;
|
|
378
|
+
async recordRun(record: DiagnosisRunRecord): Promise<{ sourceId?: string; problems: string[] }> {
|
|
299
379
|
const problems: string[] = []
|
|
300
380
|
const added = await this.host.addSource({
|
|
301
381
|
title: `AI 诊断日志 · ${record.symptomId} · ${record.runId}`,
|
|
@@ -306,18 +386,7 @@ export class DiagnosisStore {
|
|
|
306
386
|
if (added.ok === false) return { problems: [`诊断日志 ${record.runId} 写入失败:${added.error.code} ${added.error.message}`] }
|
|
307
387
|
const sourceId = added.data.sourceId
|
|
308
388
|
|
|
309
|
-
|
|
310
|
-
const draft = caseCardOf(record, symptomTitle)
|
|
311
|
-
const written = await this.host.writeCard({
|
|
312
|
-
entityType: draft.entityType as SchemaType,
|
|
313
|
-
entityId: draft.entityId,
|
|
314
|
-
title: draft.title,
|
|
315
|
-
content: renderCardBody(draft),
|
|
316
|
-
sourceRefs: [sourceId],
|
|
317
|
-
status: 'unreviewed',
|
|
318
|
-
})
|
|
319
|
-
if (written.ok === false) problems.push(`案例卡片 ${draft.entityId} 写入失败:${written.error.code} ${written.error.message}`)
|
|
320
|
-
return { sourceId, ...(written.ok === false ? {} : { entityId: draft.entityId }), problems }
|
|
389
|
+
return { sourceId, problems }
|
|
321
390
|
}
|
|
322
391
|
|
|
323
392
|
/* ────────────────────────────────────────────── 旧知识根迁移 ── */
|
|
@@ -460,8 +529,8 @@ export function renderCardBody(card: DiagnosisCard): string {
|
|
|
460
529
|
/**
|
|
461
530
|
* 给卡片挂出处。
|
|
462
531
|
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
532
|
+
* 规则是**数据驱动的**,不是凭印象分的:可复用诊断卡优先引用第一篇走过该节点的复盘;
|
|
533
|
+
* 没有经过复盘的节点引用手册。历史 Case 卡仍由旧数据读取,不在新示例里生成。
|
|
465
534
|
*/
|
|
466
535
|
function withSourceRefs(
|
|
467
536
|
cards: DiagnosisCard[],
|
package/src/diagnosis/types.ts
CHANGED
|
@@ -15,7 +15,8 @@ import type { ProblemClassId } from './problem-classes.js'
|
|
|
15
15
|
export type NodeLayer = 'type' | 'reference' | 'instance'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* 九类归因图节点。当前 Knowledge 节点可对应 WikiCard;`case` 是排查记录视图,
|
|
19
|
+
* `asset` 与执行产物也不对应 WikiCard。历史 Case WikiCard 仅为兼容数据。
|
|
19
20
|
*
|
|
20
21
|
* **两个名字用的是下划线**(`check_point` / `failure_reason`),卡片类型用连字符
|
|
21
22
|
* (`diagnosis/check-point` / `diagnosis/failure-reason`):kind 是代码里的标识符,
|
|
@@ -187,18 +188,9 @@ export interface AttributionGraphData {
|
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* (`cardsToGraph()` 从卡片把它算出来,`/diagnosis/graph` 把它发给界面),
|
|
194
|
-
* 而示例只是**一份**案例的取值来源。视图要渲染「服务端给的案例」,
|
|
195
|
-
* 那它 import 的形状就不该从示例模块里拿。
|
|
196
|
-
*
|
|
197
|
-
* 两段各有明确消费者,不能合并:
|
|
198
|
-
* - `sections` 是给人读、给向量召回的散文(可 diff、可评审、可追溯);
|
|
199
|
-
* - `path` 是给图和剪枝用的结构(有序、可判真假、带被否定的分支)。
|
|
200
|
-
*
|
|
201
|
-
* 序和枚举一旦写进散文,归并算法就再也读不到它们了 —— 所以路径单独成段。
|
|
191
|
+
* Case 是一次排查记录的只读展示投影,不是持久化实体。
|
|
192
|
+
* `sections` 供人阅读,`path` 保留检查顺序与被否定的分支;来源是 SourceRaw 运行记录。
|
|
193
|
+
* 历史 `diagnosis/case` WikiCard 仍可读取,但新的运行与示例载入不再生成它。
|
|
202
194
|
*/
|
|
203
195
|
export interface CaseSection {
|
|
204
196
|
heading: string
|
|
@@ -223,6 +215,33 @@ export interface AttributionCase {
|
|
|
223
215
|
/** 误导段:最贵的那条知识。没有它,下次还会有人在同一个假设上烧掉四十分钟。 */
|
|
224
216
|
misleading?: { nodeId: string; label: string; wastedMinutes: number; why: string }
|
|
225
217
|
rootCause: string
|
|
218
|
+
/** 排查记录里的根因确认状态;旧案例卡片缺省时按已有内容展示。 */
|
|
219
|
+
rootCauseStatus?: 'confirmed' | 'unconfirmed'
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** 从独立 Event 实体读取的一次具体发生,供智能归因的事件视图展示。 */
|
|
223
|
+
export interface AttributionEvent {
|
|
224
|
+
id: string
|
|
225
|
+
title: string
|
|
226
|
+
summary: string
|
|
227
|
+
identityType: 'external_id' | 'composite' | 'source'
|
|
228
|
+
externalId?: string
|
|
229
|
+
occurredAt?: string
|
|
230
|
+
symptom?: string
|
|
231
|
+
coordinate: { object: string | null; action: string | null; scene: string | null }
|
|
232
|
+
timeline: Array<{
|
|
233
|
+
id: string
|
|
234
|
+
type: string
|
|
235
|
+
description: string
|
|
236
|
+
result?: string
|
|
237
|
+
at?: string
|
|
238
|
+
sourceId: string
|
|
239
|
+
}>
|
|
240
|
+
rootCauses: Array<{ text: string; status: 'confirmed' | 'suspected' | null; sourceId: string }>
|
|
241
|
+
outcomes: Array<{ text: string; sourceId: string }>
|
|
242
|
+
missing: string[]
|
|
243
|
+
sources: Array<{ documentId: string; quote: string }>
|
|
244
|
+
recordCount: number
|
|
226
245
|
}
|
|
227
246
|
|
|
228
247
|
export interface AttributionStats {
|
|
@@ -298,8 +317,8 @@ export interface DiagnosisRunCause {
|
|
|
298
317
|
/**
|
|
299
318
|
* 一次排查的完整记录。落到 SourceRaw 正文里的 ```json diagnosis-run 块。
|
|
300
319
|
*
|
|
301
|
-
*
|
|
302
|
-
*
|
|
320
|
+
* 它是 Agent 跑完一圈留下的原始记录。Case 视图从这条记录派生;可复用 Knowledge 与 Event
|
|
321
|
+
* 由独立抽取和归一阶段生成,不在这条记录写成第二张卡片。
|
|
303
322
|
*/
|
|
304
323
|
export interface DiagnosisRunRecord {
|
|
305
324
|
/** 本次排查的 runId。同时用作 SourceRaw 的 `externalId`,重跑不产生第二条记录。 */
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DSH 自带 Python 的落点(2026-10-18)。
|
|
3
|
+
*
|
|
4
|
+
* 桌面端把 Python 3.12 **打在自己的运行时里**:
|
|
5
|
+
* `<App>/Contents/Resources/runtime/primary-runtime/dependencies/python`(清单见同目录
|
|
6
|
+
* `runtime.json` 的 `python` 字段)。但这一层没把位置告诉插件 —— 宿主不导出 `DSH_PYTHON`,
|
|
7
|
+
* 于是「一键准备」的默认值 `python3` 落到了系统那个 3.9(macOS 命令行工具自带的正是 3.9),
|
|
8
|
+
* 第一步就报「Python 版本不受支持」,而机器上明明有 3.12。
|
|
9
|
+
*
|
|
10
|
+
* 所以这里自己找,顺序是:
|
|
11
|
+
*
|
|
12
|
+
* 1. **`DSH_PYTHON`** —— 显式覆盖永远是第一位的(文档里承诺的自定义入口)。
|
|
13
|
+
* 2. **DSH 自带的那一个** —— 从宿主告诉我们的两个锚点推:Electron 的 `resourcesPath`,
|
|
14
|
+
* 以及 `process.execPath`(桌面端是 `Contents/MacOS/<App>`,`ELECTRON_RUN_AS_NODE` 下
|
|
15
|
+
* 它就是运行时用的那个可执行文件)。两者都会向上找几级,因为包装脚本与真实二进制的
|
|
16
|
+
* 层级不一定一样。
|
|
17
|
+
* 3. **PATH 上的 `python3`** —— 都没有才退回。
|
|
18
|
+
*
|
|
19
|
+
* ## 这里只回答「哪个路径最可能是它」,不回答「它是哪个版本」
|
|
20
|
+
*
|
|
21
|
+
* 版本判断必须由准备阶段做(它要跑一次 `sys.version_info`,并把结论写进安装日志)。
|
|
22
|
+
* 在这里再探测一遍等于把同步可判的事情做成两次异步调用,而且拿到版本也不知道该报给谁。
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { existsSync } from 'node:fs'
|
|
26
|
+
import { posix, win32 } from 'node:path'
|
|
27
|
+
import { runProcess } from './process.js'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 按**目标平台**拼路径,不按跑这段代码的机器。
|
|
31
|
+
*
|
|
32
|
+
* 生产里两者永远一致(Windows 上 `process.platform` 就是 `win32`),但这里允许注入平台 ——
|
|
33
|
+
* 而 POSIX 上的 `dirname('C:\\x\\node.exe')` 会给出 `'.'`,于是那条 Windows 断言在 mac 上
|
|
34
|
+
* 跑不通。用平台自己的路径工具,注入才是真的能测。
|
|
35
|
+
*/
|
|
36
|
+
const pathsFor = (platform: NodeJS.Platform): typeof posix => platform === 'win32' ? win32 : posix
|
|
37
|
+
|
|
38
|
+
/** 相对 App 资源根的落点。`runtime.json` 就在它的上一级。 */
|
|
39
|
+
const BUNDLE_RELATIVE = ['runtime/primary-runtime/dependencies/python']
|
|
40
|
+
|
|
41
|
+
/** 一个解释器可能叫的几个名字。Windows 的独立发行版把 `python.exe` 放在根上。 */
|
|
42
|
+
function interpreterNames(root: string, platform: NodeJS.Platform): string[] {
|
|
43
|
+
const { join } = pathsFor(platform)
|
|
44
|
+
return platform === 'win32'
|
|
45
|
+
? [join(root, 'python.exe'), join(root, 'python3.exe')]
|
|
46
|
+
: [join(root, 'bin', 'python3'), join(root, 'bin', 'python')]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 从锚点向上走几级,每一级都试「本体」和「本体/Resources」两种排法。 */
|
|
50
|
+
function bundleCandidates(anchor: string, platform: NodeJS.Platform): string[] {
|
|
51
|
+
const { dirname, join } = pathsFor(platform)
|
|
52
|
+
const found: string[] = []
|
|
53
|
+
let dir = anchor
|
|
54
|
+
for (let depth = 0; depth < 6; depth += 1) {
|
|
55
|
+
for (const relative of BUNDLE_RELATIVE) {
|
|
56
|
+
for (const name of interpreterNames(join(dir, relative), platform)) found.push(name)
|
|
57
|
+
// macOS / Windows 的 `.app`:真实资源在 `Contents/Resources`,而锚点是 `Contents/MacOS`。
|
|
58
|
+
for (const name of interpreterNames(join(dir, 'Resources', relative), platform)) found.push(name)
|
|
59
|
+
}
|
|
60
|
+
const parent = dirname(dir)
|
|
61
|
+
if (parent === dir) break
|
|
62
|
+
dir = parent
|
|
63
|
+
}
|
|
64
|
+
return found
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface PythonPick {
|
|
68
|
+
/** 要拿去建虚拟环境的解释器。 */
|
|
69
|
+
path: string
|
|
70
|
+
/** 它从哪来 —— 报错时要能说清「我没找到自带的那个」。 */
|
|
71
|
+
source: 'override' | 'bundled' | 'path'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PythonProbe {
|
|
75
|
+
env?: Record<string, string | undefined>
|
|
76
|
+
/** Electron 的 `process.resourcesPath`;不在 Electron 里时省略。 */
|
|
77
|
+
resourcesPath?: string
|
|
78
|
+
/** 宿主的可执行文件路径;默认取 `process.execPath`。 */
|
|
79
|
+
execPath?: string
|
|
80
|
+
platform?: NodeJS.Platform
|
|
81
|
+
/** 存在性判断,测试里换成假的。 */
|
|
82
|
+
exists?: (path: string) => boolean
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 挑一个基础解释器。**纯函数**(存在性判断可注入),所以「自带优先于 PATH」这条能被单独断言。
|
|
87
|
+
*/
|
|
88
|
+
export function pickBasePython(probe: PythonProbe = {}): PythonPick {
|
|
89
|
+
const env = probe.env ?? process.env
|
|
90
|
+
const override = env.DSH_PYTHON?.trim()
|
|
91
|
+
if (override) return { path: override, source: 'override' }
|
|
92
|
+
const platform = probe.platform ?? process.platform
|
|
93
|
+
const exists = probe.exists ?? existsSync
|
|
94
|
+
const anchors: string[] = []
|
|
95
|
+
if (probe.resourcesPath) anchors.push(probe.resourcesPath)
|
|
96
|
+
const { dirname } = pathsFor(platform)
|
|
97
|
+
const executables = [env.DSH_DESKTOP_NODE_EXECUTABLE, probe.execPath ?? process.execPath]
|
|
98
|
+
for (const executable of executables) {
|
|
99
|
+
const value = executable?.trim()
|
|
100
|
+
if (value) anchors.push(dirname(value))
|
|
101
|
+
}
|
|
102
|
+
for (const anchor of anchors) {
|
|
103
|
+
for (const candidate of bundleCandidates(anchor, platform)) {
|
|
104
|
+
if (exists(candidate)) return { path: candidate, source: 'bundled' }
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return { path: 'python3', source: 'path' }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** 报错里那句「没找到自带的那一个」用得上。 */
|
|
111
|
+
export function pythonSourceLabel(source: PythonPick['source']): string {
|
|
112
|
+
return source === 'override' ? 'DSH_PYTHON' : source === 'bundled' ? 'DSH 自带运行时' : 'PATH 上的 python3'
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 这个解释器能不能加载**第三方原生扩展**(torch 这类 pip 装的 dylib)。
|
|
117
|
+
*
|
|
118
|
+
* macOS 上不行的一种情况是真实存在过的(2026-10-18 实测):DSH 桌面端把 Python 3.12
|
|
119
|
+
* 打在自己的运行时里,并给它签了 Developer ID + **hardened runtime**
|
|
120
|
+
* (`flags=0x10000(runtime)`),又没有 `com.apple.security.cs.disable-library-validation`。
|
|
121
|
+
* 库校验因此生效 —— 它只肯加载**同一 Team ID** 签的 dylib。pip 上的 torch 是 ad-hoc 签名
|
|
122
|
+
* (Team ID 为空),于是:
|
|
123
|
+
*
|
|
124
|
+
* ```
|
|
125
|
+
* OSError: dlopen(.../libtorch_global_deps.dylib, 0x000A):
|
|
126
|
+
* code signature ... not valid for use in process:
|
|
127
|
+
* mapping process and mapped file (non-platform) have different Team IDs
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* 同一个 dylib 换成 uv 管的独立 CPython(`adhoc, linker-signed`,没有 runtime 标记)
|
|
131
|
+
* 就能加载 —— 这一条在同一台机器上验过。
|
|
132
|
+
*
|
|
133
|
+
* 判据读的是 `codesign` 的 flags,不看路径:运行时目录在某些安装形态下不在 `.app` 里,
|
|
134
|
+
* 而「带不带 hardened runtime」才是真正决定库校验的那件事。没有 `codesign`(Linux/Windows)
|
|
135
|
+
* 或读不到(没签名)时一律当「能加载」—— 不因为探测失败就改道去下载解释器。
|
|
136
|
+
*/
|
|
137
|
+
export async function hasHardenedRuntime(path: string, run: typeof runProcess = runProcess): Promise<boolean> {
|
|
138
|
+
if (process.platform !== 'darwin') return false
|
|
139
|
+
try {
|
|
140
|
+
const output = await run('/usr/bin/codesign', ['-dv', '--verbose=2', path], { timeoutMs: 10_000 })
|
|
141
|
+
const flags = /flags=0x[0-9a-f]+\(([^)]*)\)/i.exec(output)?.[1] ?? ''
|
|
142
|
+
return flags.split(',').some(flag => flag.trim() === 'runtime')
|
|
143
|
+
} catch {
|
|
144
|
+
return false
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 这个解释器要不要换成 uv 管的那一个。
|
|
150
|
+
*
|
|
151
|
+
* 判据只有一条:**带 hardened runtime 就用不了第三方原生扩展**(见 `hasHardenedRuntime`)。
|
|
152
|
+
* `DSH_PYTHON` 显式给的不改道 —— 那是用户的选择;插件只把风险写进日志。
|
|
153
|
+
*/
|
|
154
|
+
export function needsManagedInterpreter(pick: PythonPick, hardened: boolean): boolean {
|
|
155
|
+
return hardened && pick.source !== 'override'
|
|
156
|
+
}
|