ltcai 11.5.2 → 11.7.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/README.md +93 -148
- package/bin/ltcai.js +234 -24
- package/docs/CHANGELOG.md +119 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +8 -6
- package/docs/ENTERPRISE.md +2 -1
- package/docs/MULTI_AGENT_RUNTIME.md +12 -5
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +6 -3
- package/docs/REALTIME_COLLABORATION.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/WORKFLOW_DESIGNER.md +3 -2
- package/docs/kg-schema.md +1 -1
- package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
- package/lattice_brain/__init__.py +42 -79
- package/lattice_brain/graph/__init__.py +9 -24
- package/lattice_brain/graph/_kg_common/__init__.py +13 -24
- package/lattice_brain/ingestion/__init__.py +19 -58
- package/lattice_brain/ingestion/pipeline.py +20 -398
- package/lattice_brain/multimodal/__init__.py +7 -18
- package/lattice_brain/multimodal/images.py +6 -264
- package/lattice_brain/multimodal/video.py +8 -247
- package/lattice_brain/runtime/__init__.py +8 -79
- package/lattice_brain/runtime/hooks.py +22 -584
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/agent_worker_seam.py +7 -80
- package/latticeai/api/health.py +6 -20
- package/latticeai/api/local_files.py +16 -613
- package/latticeai/api/models.py +12 -87
- package/latticeai/api/search.py +17 -255
- package/latticeai/api/tools.py +69 -750
- package/latticeai/api/voice_capture.py +8 -70
- package/latticeai/api/worker_compute.py +842 -0
- package/latticeai/api/worker_seams.py +216 -0
- package/latticeai/app_factory.py +23 -232
- package/latticeai/cli/entrypoint.py +36 -249
- package/latticeai/core/agent_permission.py +16 -91
- package/latticeai/core/messages.py +89 -531
- package/latticeai/runtime/access_runtime.py +0 -14
- package/latticeai/runtime/bootstrap.py +10 -21
- package/latticeai/runtime/brain_runtime.py +35 -43
- package/latticeai/runtime/build_phases/__init__.py +21 -37
- package/latticeai/runtime/build_phases/features.py +99 -389
- package/latticeai/runtime/build_phases/foundation.py +82 -392
- package/latticeai/runtime/build_phases/web.py +91 -408
- package/latticeai/runtime/build_phases/worker_profile.py +244 -0
- package/latticeai/runtime/lifespan_runtime.py +7 -16
- package/latticeai/runtime/platform_services_runtime.py +1 -15
- package/latticeai/runtime/runtime_context.py +13 -130
- package/latticeai/runtime/security_runtime.py +10 -103
- package/latticeai/services/architecture_readiness.py +82 -43
- package/latticeai/services/model_runtime/__init__.py +2 -11
- package/latticeai/services/model_runtime/service.py +4 -28
- package/latticeai/services/p_reinforce.py +10 -261
- package/latticeai/services/product_readiness.py +31 -38
- package/latticeai/services/search_service.py +37 -795
- package/latticeai/services/tool_dispatch.py +30 -386
- package/latticeai/services/voice_capture.py +13 -107
- package/latticeai/tools/__init__.py +22 -49
- package/latticeai/tools/commands.py +0 -163
- package/latticeai/tools/computer.py +0 -39
- package/latticeai/tools/documents.py +1 -134
- package/latticeai/tools/filesystem.py +1 -247
- package/latticeai/tools/knowledge.py +1 -52
- package/latticeai/tools/local_files.py +0 -20
- package/latticeai/worker_app.py +75 -0
- package/package.json +2 -3
- package/requirements.txt +0 -5
- package/scripts/agent_eval.py +16 -28
- package/scripts/brain_quality_eval.py +20 -183
- package/scripts/bump_version.py +5 -5
- package/scripts/check_current_release_docs.mjs +7 -4
- package/scripts/check_openapi_drift.mjs +10 -0
- package/scripts/check_server_i18n.mjs +2 -18
- package/scripts/compose_openapi.py +377 -0
- package/scripts/export_openapi.py +32 -4
- package/scripts/gen_messages_catalog_fixture.py +302 -0
- package/scripts/gen_openapi_fragments.py +365 -0
- package/scripts/gen_redact_fixture.py +196 -0
- package/scripts/gen_worker_allowlist_fixture.py +115 -0
- package/scripts/generate_agent_parity_fixtures.py +33 -14
- package/scripts/openapi_route_families.json +2161 -0
- package/scripts/release_screen_claims.json +54 -0
- package/scripts/run_integration_tests.mjs +134 -29
- package/scripts/run_sidecar_e2e.mjs +104 -11
- package/scripts/wheel_smoke.py +32 -22
- package/src-tauri/Cargo.lock +375 -9
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/src/backend.rs +151 -45
- package/src-tauri/src/main.rs +18 -18
- package/src-tauri/src/topology.rs +58 -88
- package/src-tauri/tauri.conf.json +1 -2
- package/static/app/asset-manifest.json +41 -41
- package/static/app/assets/{Act-DcQizkl1.js → Act-BPcVAbOL.js} +1 -1
- package/static/app/assets/AdminConsole-Bw1ATQL0.js +1 -0
- package/static/app/assets/{Brain-3VCSHFcn.js → Brain-CT92Kos0.js} +2 -2
- package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-CFBkt1K_.js} +1 -1
- package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-ReLWF2H8.js} +1 -1
- package/static/app/assets/Capture-BsTokYkk.js +1 -0
- package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-B6f0T9id.js} +1 -1
- package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-CuvjTv1u.js} +1 -1
- package/static/app/assets/{Library-BV6NnF0a.js → Library-BGJbG9Hd.js} +1 -1
- package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-DGYK_Jsa.js} +1 -1
- package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-DXBC6brE.js} +1 -1
- package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-HXRle3qq.js} +2 -2
- package/static/app/assets/System-CMHSO9qM.js +1 -0
- package/static/app/assets/arrow-left-BfmkskWx.js +1 -0
- package/static/app/assets/{bot-B_K1Tdmw.js → bot-Cn8bWRuq.js} +1 -1
- package/static/app/assets/{brain-DWyaV1L1.js → brain-CQJberbE.js} +1 -1
- package/static/app/assets/{button-aTn4s84A.js → button-Ct9f2_oT.js} +1 -1
- package/static/app/assets/circle-check-DruOxB-4.js +1 -0
- package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-CmzC_apg.js} +1 -1
- package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-D8mW2aQ7.js} +1 -1
- package/static/app/assets/{cpu-85xYObUC.js → cpu-DZcdd0PZ.js} +1 -1
- package/static/app/assets/{download-B5Fm7YXo.js → download-bv1KEPGQ.js} +1 -1
- package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-d-Pip5gr.js} +1 -1
- package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-D20iavUb.js} +1 -1
- package/static/app/assets/index-D9x-kSNy.css +2 -0
- package/static/app/assets/{index-BMPdTmlY.js → index-Do83hDzJ.js} +3 -3
- package/static/app/assets/{input-B0nRf2jO.js → input-BLXVNmj1.js} +1 -1
- package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-BPJOFlAy.js} +1 -1
- package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-ChdJd493.js} +1 -1
- package/static/app/assets/primitives-Cv5tbZBY.js +1 -0
- package/static/app/assets/search-CT9aho2j.js +1 -0
- package/static/app/assets/{share-2-BsrxFglO.js → share-2-YNX_NtMU.js} +1 -1
- package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-DuQ3zrVL.js} +1 -1
- package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-DqwLnli4.js} +1 -1
- package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-ZVI98jaW.js} +1 -1
- package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-CVC4qv_D.js} +1 -1
- package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-C7BeG4HU.js} +1 -1
- package/static/app/assets/{utils-Ddol2RWD.js → utils-CiFtIdZq.js} +1 -1
- package/static/app/assets/{workspace-BqDwOz_p.js → workspace-DQz9vIId.js} +1 -1
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/lattice_brain/archive.py +0 -522
- package/lattice_brain/context.py +0 -325
- package/lattice_brain/conversations.py +0 -382
- package/lattice_brain/core.py +0 -82
- package/lattice_brain/graph/_kg_contract.py +0 -249
- package/lattice_brain/graph/curator.py +0 -676
- package/lattice_brain/graph/discovery.py +0 -595
- package/lattice_brain/graph/discovery_index/__init__.py +0 -35
- package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
- package/lattice_brain/graph/discovery_index/extract.py +0 -137
- package/lattice_brain/graph/discovery_index/scan.py +0 -411
- package/lattice_brain/graph/discovery_index/upsert.py +0 -495
- package/lattice_brain/graph/documents.py +0 -380
- package/lattice_brain/graph/fusion.py +0 -395
- package/lattice_brain/graph/identity.py +0 -175
- package/lattice_brain/graph/image_vectors.py +0 -230
- package/lattice_brain/graph/ingest.py +0 -829
- package/lattice_brain/graph/network.py +0 -205
- package/lattice_brain/graph/proactive.py +0 -724
- package/lattice_brain/graph/projection/__init__.py +0 -42
- package/lattice_brain/graph/projection/curation.py +0 -500
- package/lattice_brain/graph/projection/v2_schema.py +0 -518
- package/lattice_brain/graph/provenance.py +0 -524
- package/lattice_brain/graph/rerank.py +0 -163
- package/lattice_brain/graph/retrieval/__init__.py +0 -54
- package/lattice_brain/graph/retrieval/context.py +0 -197
- package/lattice_brain/graph/retrieval/graph_view.py +0 -319
- package/lattice_brain/graph/retrieval/hybrid.py +0 -488
- package/lattice_brain/graph/retrieval/maintenance.py +0 -121
- package/lattice_brain/graph/retrieval/signals.py +0 -95
- package/lattice_brain/graph/retrieval_docgen.py +0 -253
- package/lattice_brain/graph/retrieval_policy.py +0 -180
- package/lattice_brain/graph/retrieval_reads.py +0 -769
- package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
- package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
- package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
- package/lattice_brain/graph/retrieval_vector/search.py +0 -560
- package/lattice_brain/graph/retrieval_vector/status.py +0 -374
- package/lattice_brain/graph/schema.py +0 -792
- package/lattice_brain/graph/store.py +0 -268
- package/lattice_brain/graph/vector_index/__init__.py +0 -85
- package/lattice_brain/graph/vector_index/base.py +0 -167
- package/lattice_brain/graph/vector_index/brute_force.py +0 -110
- package/lattice_brain/graph/vector_index/hnsw.py +0 -290
- package/lattice_brain/graph/vector_index/jobs.py +0 -287
- package/lattice_brain/graph/vector_index/quantized.py +0 -148
- package/lattice_brain/graph/vector_index/selector.py +0 -161
- package/lattice_brain/graph/write_master.py +0 -308
- package/lattice_brain/ingestion/_contract.py +0 -90
- package/lattice_brain/ingestion/folder_scan.py +0 -57
- package/lattice_brain/ingestion/folders.py +0 -258
- package/lattice_brain/ingestion/jobs_api.py +0 -107
- package/lattice_brain/ingestion/routing.py +0 -295
- package/lattice_brain/ingestion_jobs.py +0 -380
- package/lattice_brain/memory.py +0 -75
- package/lattice_brain/portability/__init__.py +0 -90
- package/lattice_brain/portability/_contract.py +0 -42
- package/lattice_brain/portability/backups.py +0 -338
- package/lattice_brain/portability/bundles.py +0 -136
- package/lattice_brain/portability/constants.py +0 -93
- package/lattice_brain/portability/fsops.py +0 -138
- package/lattice_brain/portability/service.py +0 -41
- package/lattice_brain/portability/sharing.py +0 -710
- package/lattice_brain/quality.py +0 -543
- package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
- package/lattice_brain/runtime/agent_runtime.py +0 -859
- package/lattice_brain/runtime/contracts.py +0 -460
- package/lattice_brain/runtime/multi_agent.py +0 -942
- package/lattice_brain/runtime/statuses.py +0 -10
- package/lattice_brain/sealed_box.py +0 -240
- package/lattice_brain/self_model.py +0 -675
- package/lattice_brain/sensitivity.py +0 -94
- package/lattice_brain/storage/__init__.py +0 -22
- package/lattice_brain/storage/base.py +0 -100
- package/lattice_brain/storage/docker.py +0 -105
- package/lattice_brain/storage/factory.py +0 -31
- package/lattice_brain/storage/migration.py +0 -191
- package/lattice_brain/storage/postgres.py +0 -123
- package/lattice_brain/storage/sqlite.py +0 -143
- package/lattice_brain/synthesis.py +0 -824
- package/lattice_brain/workflow.py +0 -497
- package/latticeai/api/admin.py +0 -471
- package/latticeai/api/agent_registry.py +0 -105
- package/latticeai/api/agents.py +0 -228
- package/latticeai/api/auth.py +0 -383
- package/latticeai/api/automation_intelligence.py +0 -401
- package/latticeai/api/brain_intelligence.py +0 -199
- package/latticeai/api/browser.py +0 -493
- package/latticeai/api/change_proposals.py +0 -89
- package/latticeai/api/chat.py +0 -572
- package/latticeai/api/chat_agent_http.py +0 -892
- package/latticeai/api/chat_contracts.py +0 -73
- package/latticeai/api/chat_documents.py +0 -276
- package/latticeai/api/chat_helpers.py +0 -460
- package/latticeai/api/chat_history.py +0 -101
- package/latticeai/api/chat_hybrid.py +0 -113
- package/latticeai/api/chat_intents.py +0 -646
- package/latticeai/api/chat_stream.py +0 -216
- package/latticeai/api/chronicle.py +0 -63
- package/latticeai/api/command_center.py +0 -51
- package/latticeai/api/computer_use.py +0 -474
- package/latticeai/api/evidence_actions.py +0 -48
- package/latticeai/api/features.py +0 -70
- package/latticeai/api/funnel_metrics.py +0 -31
- package/latticeai/api/garden.py +0 -34
- package/latticeai/api/hooks.py +0 -165
- package/latticeai/api/index_jobs.py +0 -145
- package/latticeai/api/invitations.py +0 -100
- package/latticeai/api/knowledge_graph.py +0 -536
- package/latticeai/api/marketplace.py +0 -105
- package/latticeai/api/mcp.py +0 -482
- package/latticeai/api/memory.py +0 -270
- package/latticeai/api/network.py +0 -81
- package/latticeai/api/network_boundary.py +0 -225
- package/latticeai/api/permission_mode.py +0 -61
- package/latticeai/api/permissions.py +0 -436
- package/latticeai/api/plugins.py +0 -126
- package/latticeai/api/portability.py +0 -391
- package/latticeai/api/project_sessions.py +0 -114
- package/latticeai/api/realtime.py +0 -118
- package/latticeai/api/review_queue.py +0 -364
- package/latticeai/api/security_dashboard.py +0 -604
- package/latticeai/api/setup.py +0 -319
- package/latticeai/api/static_routes.py +0 -354
- package/latticeai/api/ui_redirects.py +0 -26
- package/latticeai/api/workflow_designer.py +0 -394
- package/latticeai/api/workspace.py +0 -856
- package/latticeai/api/workspace_scope.py +0 -125
- package/latticeai/core/agent/__init__.py +0 -93
- package/latticeai/core/agent/_contract.py +0 -79
- package/latticeai/core/agent/context.py +0 -57
- package/latticeai/core/agent/deps.py +0 -125
- package/latticeai/core/agent/execution.py +0 -622
- package/latticeai/core/agent/planning.py +0 -145
- package/latticeai/core/agent/recovery.py +0 -157
- package/latticeai/core/agent/runtime.py +0 -210
- package/latticeai/core/agent/verification.py +0 -231
- package/latticeai/core/agent_eval.py +0 -739
- package/latticeai/core/agent_helpers.py +0 -493
- package/latticeai/core/agent_profiles.py +0 -110
- package/latticeai/core/agent_prompts.py +0 -171
- package/latticeai/core/agent_registry.py +0 -232
- package/latticeai/core/agent_state.py +0 -41
- package/latticeai/core/agent_trace.py +0 -104
- package/latticeai/core/artifact_ledger.py +0 -109
- package/latticeai/core/audit.py +0 -260
- package/latticeai/core/builtin_hooks.py +0 -105
- package/latticeai/core/context_builder.py +0 -394
- package/latticeai/core/document_generator.py +0 -103
- package/latticeai/core/enterprise.py +0 -154
- package/latticeai/core/enterprise_admin.py +0 -158
- package/latticeai/core/file_generation/__init__.py +0 -115
- package/latticeai/core/file_generation/bundles.py +0 -76
- package/latticeai/core/file_generation/extraction.py +0 -154
- package/latticeai/core/file_generation/inference.py +0 -235
- package/latticeai/core/file_generation/orchestration.py +0 -152
- package/latticeai/core/file_generation/prompting.py +0 -117
- package/latticeai/core/file_generation/repair.py +0 -114
- package/latticeai/core/file_generation/sanitize.py +0 -61
- package/latticeai/core/file_generation/validation.py +0 -201
- package/latticeai/core/invitations.py +0 -132
- package/latticeai/core/legacy_compatibility.py +0 -243
- package/latticeai/core/logging_safety.py +0 -46
- package/latticeai/core/marketplace.py +0 -293
- package/latticeai/core/mcp_catalog.py +0 -452
- package/latticeai/core/mcp_registry.py +0 -506
- package/latticeai/core/network_boundary.py +0 -168
- package/latticeai/core/oidc.py +0 -208
- package/latticeai/core/plugins.py +0 -432
- package/latticeai/core/product_hardening.py +0 -218
- package/latticeai/core/project_sessions.py +0 -337
- package/latticeai/core/realtime.py +0 -238
- package/latticeai/core/run_explain.py +0 -426
- package/latticeai/core/run_store.py +0 -252
- package/latticeai/core/timezones.py +0 -80
- package/latticeai/core/workspace_computer_memory.py +0 -84
- package/latticeai/core/workspace_graph_trace.py +0 -155
- package/latticeai/core/workspace_indexing.py +0 -102
- package/latticeai/core/workspace_memory.py +0 -77
- package/latticeai/core/workspace_onboarding.py +0 -104
- package/latticeai/core/workspace_os.py +0 -978
- package/latticeai/core/workspace_os_constants.py +0 -126
- package/latticeai/core/workspace_os_state.py +0 -180
- package/latticeai/core/workspace_os_utils.py +0 -103
- package/latticeai/core/workspace_permissions.py +0 -101
- package/latticeai/core/workspace_plugins.py +0 -97
- package/latticeai/core/workspace_relationships.py +0 -99
- package/latticeai/core/workspace_reorganization.py +0 -335
- package/latticeai/core/workspace_review_items.py +0 -112
- package/latticeai/core/workspace_runs.py +0 -726
- package/latticeai/core/workspace_skills.py +0 -109
- package/latticeai/core/workspace_snapshots.py +0 -198
- package/latticeai/core/workspace_timeline.py +0 -110
- package/latticeai/integrations/__init__.py +0 -0
- package/latticeai/integrations/telegram_bot/__init__.py +0 -123
- package/latticeai/integrations/telegram_bot/__main__.py +0 -17
- package/latticeai/integrations/telegram_bot/config.py +0 -86
- package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
- package/latticeai/integrations/telegram_bot/flows.py +0 -478
- package/latticeai/integrations/telegram_bot/helpers.py +0 -322
- package/latticeai/integrations/telegram_bot/screens.py +0 -394
- package/latticeai/runtime/audit_runtime.py +0 -76
- package/latticeai/runtime/automation_runtime.py +0 -81
- package/latticeai/runtime/chat_wiring.py +0 -141
- package/latticeai/runtime/context_runtime.py +0 -66
- package/latticeai/runtime/feature_toggle_wiring.py +0 -157
- package/latticeai/runtime/history_runtime.py +0 -163
- package/latticeai/runtime/history_writer.py +0 -138
- package/latticeai/runtime/hooks_runtime.py +0 -77
- package/latticeai/runtime/model_wiring.py +0 -68
- package/latticeai/runtime/namespace_runtime.py +0 -163
- package/latticeai/runtime/network_boundary_wiring.py +0 -117
- package/latticeai/runtime/network_config_runtime.py +0 -56
- package/latticeai/runtime/permission_mode_wiring.py +0 -112
- package/latticeai/runtime/persistence_runtime.py +0 -159
- package/latticeai/runtime/platform_runtime_wiring.py +0 -89
- package/latticeai/runtime/review_wiring.py +0 -42
- package/latticeai/runtime/router_registration.py +0 -693
- package/latticeai/runtime/service_singletons.py +0 -55
- package/latticeai/runtime/sso_config_runtime.py +0 -128
- package/latticeai/runtime/user_key_runtime.py +0 -106
- package/latticeai/runtime/web_runtime.py +0 -92
- package/latticeai/server_app.py +0 -51
- package/latticeai/services/app_context.py +0 -130
- package/latticeai/services/automation_execution.py +0 -266
- package/latticeai/services/automation_intelligence.py +0 -614
- package/latticeai/services/brain_automation.py +0 -191
- package/latticeai/services/brain_intelligence/__init__.py +0 -58
- package/latticeai/services/brain_intelligence/_contract.py +0 -71
- package/latticeai/services/brain_intelligence/consistency.py +0 -193
- package/latticeai/services/brain_intelligence/constants.py +0 -47
- package/latticeai/services/brain_intelligence/digest.py +0 -258
- package/latticeai/services/brain_intelligence/health.py +0 -331
- package/latticeai/services/brain_intelligence/proposals.py +0 -259
- package/latticeai/services/brain_intelligence/sampling.py +0 -84
- package/latticeai/services/brain_intelligence/service.py +0 -48
- package/latticeai/services/change_proposals.py +0 -471
- package/latticeai/services/chat_service.py +0 -243
- package/latticeai/services/chronicle.py +0 -555
- package/latticeai/services/cloud_egress_audit.py +0 -85
- package/latticeai/services/cloud_extraction.py +0 -129
- package/latticeai/services/cloud_streaming.py +0 -268
- package/latticeai/services/cloud_token_guard.py +0 -84
- package/latticeai/services/command_center.py +0 -548
- package/latticeai/services/evidence_actions.py +0 -258
- package/latticeai/services/feature_toggles.py +0 -502
- package/latticeai/services/folder_watch.py +0 -520
- package/latticeai/services/funnel_metrics.py +0 -307
- package/latticeai/services/hybrid_chat.py +0 -316
- package/latticeai/services/hybrid_context.py +0 -228
- package/latticeai/services/hybrid_policy.py +0 -129
- package/latticeai/services/interop_bridges.py +0 -978
- package/latticeai/services/local_knowledge.py +0 -465
- package/latticeai/services/memory_service/__init__.py +0 -52
- package/latticeai/services/memory_service/_contract.py +0 -100
- package/latticeai/services/memory_service/brief.py +0 -431
- package/latticeai/services/memory_service/constants.py +0 -57
- package/latticeai/services/memory_service/maintenance.py +0 -138
- package/latticeai/services/memory_service/manager.py +0 -186
- package/latticeai/services/memory_service/proof.py +0 -136
- package/latticeai/services/memory_service/recall.py +0 -225
- package/latticeai/services/memory_service/service.py +0 -48
- package/latticeai/services/memory_service/stores.py +0 -110
- package/latticeai/services/mode_store.py +0 -132
- package/latticeai/services/model_recommendation.py +0 -224
- package/latticeai/services/model_runtime/cloud.py +0 -87
- package/latticeai/services/network_boundary_service.py +0 -117
- package/latticeai/services/obsidian_bridge.py +0 -609
- package/latticeai/services/openai_compatible_adapter.py +0 -101
- package/latticeai/services/permission_mode_service.py +0 -122
- package/latticeai/services/platform_runtime.py +0 -366
- package/latticeai/services/review_queue.py +0 -380
- package/latticeai/services/router_context.py +0 -59
- package/latticeai/services/run_executor.py +0 -387
- package/latticeai/services/self_model_service.py +0 -171
- package/latticeai/services/setup_detection.py +0 -147
- package/latticeai/services/triggers.py +0 -378
- package/latticeai/services/upload_service.py +0 -172
- package/latticeai/services/workspace_service.py +0 -165
- package/latticeai/setup/__init__.py +0 -25
- package/latticeai/setup/auto_setup.py +0 -846
- package/latticeai/setup/demo_corpus.py +0 -98
- package/latticeai/setup/wizard/__init__.py +0 -126
- package/latticeai/setup/wizard/catalog.py +0 -175
- package/latticeai/setup/wizard/detect.py +0 -302
- package/latticeai/setup/wizard/install.py +0 -348
- package/latticeai/setup/wizard/paths.py +0 -165
- package/latticeai/setup/wizard/plans.py +0 -74
- package/latticeai/setup/wizard/recommend.py +0 -320
- package/scripts/bench_agent_smoke.py +0 -409
- package/scripts/bench_models.py +0 -540
- package/scripts/bench_vector_index.py +0 -295
- package/scripts/funnel_soft_gate.py +0 -192
- package/scripts/generate_agent_loop_fixtures.py +0 -994
- package/scripts/generate_rust_parity_fixtures.py +0 -908
- package/scripts/migrate_brain_storage.py +0 -57
- package/scripts/parity_fixture_corpus_context.py +0 -162
- package/scripts/parity_fixture_corpus_docgen.py +0 -341
- package/scripts/profile_kg.py +0 -355
- package/server.py +0 -30
- package/static/app/assets/AdminConsole-cf4npybT.js +0 -1
- package/static/app/assets/Capture-DiQ219jW.js +0 -1
- package/static/app/assets/System-CieofHQa.js +0 -1
- package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
- package/static/app/assets/circle-check-qqLug9nU.js +0 -1
- package/static/app/assets/index-DxmOfNRi.css +0 -2
- package/static/app/assets/primitives-SNp0LRJz.js +0 -1
- package/static/app/assets/search-BcHqkjoy.js +0 -1
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
"""Consent-first Brain automation recipes.
|
|
2
|
-
|
|
3
|
-
The recipes here are product-level starter workflows, not hidden background
|
|
4
|
-
jobs. Installing one creates a disabled draft workflow so the user can inspect
|
|
5
|
-
and enable it deliberately.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from copy import deepcopy
|
|
11
|
-
from dataclasses import dataclass
|
|
12
|
-
from typing import Any, Dict, List
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass(frozen=True)
|
|
16
|
-
class BrainAutomationRecipe:
|
|
17
|
-
id: str
|
|
18
|
-
name: str
|
|
19
|
-
summary: str
|
|
20
|
-
user_value: str
|
|
21
|
-
cadence: str
|
|
22
|
-
trigger: Dict[str, Any]
|
|
23
|
-
prompt: str
|
|
24
|
-
creates: List[str]
|
|
25
|
-
|
|
26
|
-
def as_dict(self) -> Dict[str, Any]:
|
|
27
|
-
return {
|
|
28
|
-
"id": self.id,
|
|
29
|
-
"name": self.name,
|
|
30
|
-
"summary": self.summary,
|
|
31
|
-
"user_value": self.user_value,
|
|
32
|
-
"cadence": self.cadence,
|
|
33
|
-
"trigger": deepcopy(self.trigger),
|
|
34
|
-
"creates": list(self.creates),
|
|
35
|
-
"consent": {
|
|
36
|
-
"default_state": "draft_disabled",
|
|
37
|
-
"local_only": True,
|
|
38
|
-
"external_actions": False,
|
|
39
|
-
"requires_user_enable": True,
|
|
40
|
-
"review_before_run": True,
|
|
41
|
-
},
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
_RECIPES: List[BrainAutomationRecipe] = [
|
|
46
|
-
BrainAutomationRecipe(
|
|
47
|
-
id="daily-memory-digest",
|
|
48
|
-
name="Daily Memory Digest",
|
|
49
|
-
summary="Collects the day's new memories into a short review draft.",
|
|
50
|
-
user_value="Users see what the Brain kept today without searching through chats.",
|
|
51
|
-
cadence="daily",
|
|
52
|
-
trigger={"trigger": "interval", "interval_seconds": 86_400},
|
|
53
|
-
prompt=(
|
|
54
|
-
"Review today's new Brain memories and draft a concise digest with "
|
|
55
|
-
"important decisions, unresolved questions, and suggested next actions. "
|
|
56
|
-
"Do not contact external services."
|
|
57
|
-
),
|
|
58
|
-
creates=["memory digest", "decision summary", "next-action suggestions"],
|
|
59
|
-
),
|
|
60
|
-
BrainAutomationRecipe(
|
|
61
|
-
id="weekly-project-review",
|
|
62
|
-
name="Weekly Project Review",
|
|
63
|
-
summary="Turns project context into a weekly checkpoint draft.",
|
|
64
|
-
user_value="Users can restart a project without explaining the week again.",
|
|
65
|
-
cadence="weekly",
|
|
66
|
-
trigger={"trigger": "interval", "interval_seconds": 604_800},
|
|
67
|
-
prompt=(
|
|
68
|
-
"Review this workspace's recent memories, workflow runs, and decisions. "
|
|
69
|
-
"Draft a project checkpoint with progress, risks, blockers, and next steps. "
|
|
70
|
-
"Keep it local and ask before any external action."
|
|
71
|
-
),
|
|
72
|
-
creates=["project checkpoint", "risk list", "next-week plan"],
|
|
73
|
-
),
|
|
74
|
-
BrainAutomationRecipe(
|
|
75
|
-
id="follow-up-radar",
|
|
76
|
-
name="Follow-up Radar",
|
|
77
|
-
summary="Looks for follow-up candidates when new knowledge enters the Brain.",
|
|
78
|
-
user_value="Users get gentle reminders for loose ends without a noisy task system.",
|
|
79
|
-
cadence="when new memory is saved",
|
|
80
|
-
trigger={"trigger": "brain_event"},
|
|
81
|
-
prompt=(
|
|
82
|
-
"Inspect the new Brain memory for follow-up signals such as decisions, "
|
|
83
|
-
"promises, deadlines, unresolved questions, or 'later' language. "
|
|
84
|
-
"Return suggestions only; do not create tasks without approval."
|
|
85
|
-
),
|
|
86
|
-
creates=["follow-up suggestions", "open-question list", "approval-ready task drafts"],
|
|
87
|
-
),
|
|
88
|
-
]
|
|
89
|
-
|
|
90
|
-
_RECIPE_BY_ID = {recipe.id: recipe for recipe in _RECIPES}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def list_brain_automation_recipes() -> Dict[str, Any]:
|
|
94
|
-
"""Return user-facing, consent-first automation recipe metadata."""
|
|
95
|
-
return {
|
|
96
|
-
"recipes": [recipe.as_dict() for recipe in _RECIPES],
|
|
97
|
-
"principles": {
|
|
98
|
-
"local_first": True,
|
|
99
|
-
"drafts_before_automation": True,
|
|
100
|
-
"no_external_actions_without_consent": True,
|
|
101
|
-
},
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def find_installed_recipe_workflow(
|
|
106
|
-
workflows: Any, recipe_id: str
|
|
107
|
-
) -> Dict[str, Any] | None:
|
|
108
|
-
"""Return an existing draft installed from ``recipe_id``, if any.
|
|
109
|
-
|
|
110
|
-
Installing a recipe is idempotent: clicking "Create reviewable draft" twice
|
|
111
|
-
should surface the existing draft instead of accumulating duplicates. We
|
|
112
|
-
match on the ``brain_automation_recipe`` provenance metadata stamped by
|
|
113
|
-
:func:`build_brain_automation_workflow`.
|
|
114
|
-
"""
|
|
115
|
-
for workflow in workflows or []:
|
|
116
|
-
metadata = (workflow or {}).get("metadata") or {}
|
|
117
|
-
if (
|
|
118
|
-
metadata.get("created_from") == "brain_automation_recipe"
|
|
119
|
-
and metadata.get("recipe_id") == recipe_id
|
|
120
|
-
):
|
|
121
|
-
return workflow
|
|
122
|
-
return None
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def build_brain_automation_workflow(recipe_id: str, *, enabled: bool = False) -> Dict[str, Any]:
|
|
126
|
-
"""Build a workflow definition for a recipe.
|
|
127
|
-
|
|
128
|
-
``enabled`` defaults to ``False`` so installing a recipe creates an
|
|
129
|
-
inspectable draft. The trigger service treats explicit ``enabled: false`` as
|
|
130
|
-
disarmed, while legacy workflows without the field keep their behavior.
|
|
131
|
-
"""
|
|
132
|
-
recipe = _RECIPE_BY_ID.get(recipe_id)
|
|
133
|
-
if recipe is None:
|
|
134
|
-
raise KeyError(recipe_id)
|
|
135
|
-
|
|
136
|
-
trigger_config = {
|
|
137
|
-
**deepcopy(recipe.trigger),
|
|
138
|
-
"enabled": bool(enabled),
|
|
139
|
-
"review_queue": True,
|
|
140
|
-
"consent_required": True,
|
|
141
|
-
"local_only": True,
|
|
142
|
-
"external_actions": False,
|
|
143
|
-
}
|
|
144
|
-
return {
|
|
145
|
-
"name": recipe.name,
|
|
146
|
-
"nodes": [
|
|
147
|
-
{
|
|
148
|
-
"id": "trigger",
|
|
149
|
-
"type": "trigger",
|
|
150
|
-
"name": "User-enabled schedule" if recipe.trigger["trigger"] == "interval" else "New Brain memory",
|
|
151
|
-
"config": trigger_config,
|
|
152
|
-
"next": "draft",
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
"id": "draft",
|
|
156
|
-
"type": "agent",
|
|
157
|
-
"name": "Draft Brain review",
|
|
158
|
-
"config": {
|
|
159
|
-
"agent": "agent:planner",
|
|
160
|
-
"goal": recipe.prompt,
|
|
161
|
-
"prompt": recipe.prompt,
|
|
162
|
-
"roles": ["researcher", "planner", "executor", "reviewer"],
|
|
163
|
-
"mode": "draft",
|
|
164
|
-
"local_only": True,
|
|
165
|
-
"external_actions": False,
|
|
166
|
-
"requires_review": True,
|
|
167
|
-
},
|
|
168
|
-
"next": "output",
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"id": "output",
|
|
172
|
-
"type": "output",
|
|
173
|
-
"name": "Review before saving",
|
|
174
|
-
"config": {
|
|
175
|
-
"value": "Draft ready for review. Save, edit, or discard it before it becomes durable memory.",
|
|
176
|
-
},
|
|
177
|
-
"next": None,
|
|
178
|
-
},
|
|
179
|
-
],
|
|
180
|
-
"metadata": {
|
|
181
|
-
"created_from": "brain_automation_recipe",
|
|
182
|
-
"recipe_id": recipe.id,
|
|
183
|
-
"recipe_summary": recipe.summary,
|
|
184
|
-
"recipe_user_value": recipe.user_value,
|
|
185
|
-
"automation_state": "enabled" if enabled else "draft_disabled",
|
|
186
|
-
"local_only": True,
|
|
187
|
-
"external_actions": False,
|
|
188
|
-
"requires_user_enable": not enabled,
|
|
189
|
-
"creates": list(recipe.creates),
|
|
190
|
-
},
|
|
191
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"""Proactive Brain Intelligence service (v9.3.0).
|
|
2
|
-
|
|
3
|
-
The Brain graduates from a passive store to an active steward of its own
|
|
4
|
-
knowledge. This service wires the previously dormant quality layer
|
|
5
|
-
(:mod:`lattice_brain.quality` — dedupe, merge, conflict and temporal
|
|
6
|
-
contradiction detection, retention) into router-facing capabilities:
|
|
7
|
-
|
|
8
|
-
* **health_report** — scored diagnosis of the Brain across freshness,
|
|
9
|
-
connectivity, embedding coverage, and contradiction pressure, with
|
|
10
|
-
recommended next actions. Every number is read from the live stores;
|
|
11
|
-
a missing store degrades the dimension to ``unavailable``, never a guess.
|
|
12
|
-
* **insights** — a proactive digest: recent knowledge growth, most active
|
|
13
|
-
types, stale knowledge, orphan (disconnected) nodes, and suggested
|
|
14
|
-
questions grounded in real node titles.
|
|
15
|
-
* **contradictions** — surfaced conflicts across workspace memories
|
|
16
|
-
(negation/preference conflicts, temporal contradictions) plus explicit
|
|
17
|
-
CONTRADICTS edges already recorded in the graph.
|
|
18
|
-
* **consolidate** — duplicate-memory and duplicate-edge detection. Dry-run
|
|
19
|
-
by default (consent-first, like every Brain automation); ``apply=True``
|
|
20
|
-
prunes only exact duplicate workspace memories through the audited
|
|
21
|
-
MemoryService path and never touches graph content.
|
|
22
|
-
|
|
23
|
-
Pure service: no FastAPI, no globals. Collaborators are injected.
|
|
24
|
-
|
|
25
|
-
Split into cohesive submodules in v11.3.0 (no behaviour change): ``constants``
|
|
26
|
-
(windows + the two shared readings), ``proposals`` (the review-queue path and
|
|
27
|
-
the proactive brief), ``sampling`` (the shared graph slice and memory read),
|
|
28
|
-
``health`` (the scored diagnosis and vector freshness), ``digest`` (insights,
|
|
29
|
-
garden, graph-layer quality reads), ``consistency`` (contradiction and
|
|
30
|
-
consolidation scans), and ``service`` (the composed class). This module
|
|
31
|
-
re-exports every name the single file exposed, so
|
|
32
|
-
``latticeai.services.brain_intelligence.X`` keeps working.
|
|
33
|
-
|
|
34
|
-
Stubbing note: rebinding one of these *here* changes only this module's name.
|
|
35
|
-
The submodule that calls it holds its own reference, so a test standing in for
|
|
36
|
-
``LOGGER`` or ``_parse_ts`` patches the submodule that uses it.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
from __future__ import annotations
|
|
40
|
-
|
|
41
|
-
from lattice_brain.quality import GraphEdgeQualityManager as GraphEdgeQualityManager
|
|
42
|
-
from lattice_brain.quality import MemoryQualityManager as MemoryQualityManager
|
|
43
|
-
|
|
44
|
-
# noqa on the next line, not a redundant alias: the single file exposed this
|
|
45
|
-
# name *renamed* (``brain_intelligence._now``), and reproducing that surface
|
|
46
|
-
# exactly is the point — importing it as ``now_iso`` would add a name the
|
|
47
|
-
# module never had.
|
|
48
|
-
from latticeai.core.timeutil import now_iso as _now # noqa: F401
|
|
49
|
-
|
|
50
|
-
from .constants import _GRAPH_SAMPLE_LIMIT as _GRAPH_SAMPLE_LIMIT
|
|
51
|
-
from .constants import _RECENT_DAYS as _RECENT_DAYS
|
|
52
|
-
from .constants import _STALE_DAYS as _STALE_DAYS
|
|
53
|
-
from .constants import LOGGER as LOGGER
|
|
54
|
-
from .constants import _no_graph_reason as _no_graph_reason
|
|
55
|
-
from .constants import _parse_ts as _parse_ts
|
|
56
|
-
from .service import BrainIntelligenceService as BrainIntelligenceService
|
|
57
|
-
|
|
58
|
-
__all__ = ["BrainIntelligenceService"]
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"""The seam the Brain Intelligence mixins share.
|
|
2
|
-
|
|
3
|
-
``BrainIntelligenceService`` is assembled from the proposal, sampling, health,
|
|
4
|
-
digest and consistency mixins. Each reads constructor state it does not own,
|
|
5
|
-
and several call methods another mixin implements — ``_graph_sample`` feeds
|
|
6
|
-
almost everything, ``_proactive`` gates the graph-layer surfaces, and the
|
|
7
|
-
garden view composes the contradiction scan. That contract existed as an
|
|
8
|
-
unwritten convention inside one class; this module writes it down.
|
|
9
|
-
|
|
10
|
-
Typing-only, exactly like :mod:`lattice_brain.portability._contract`: every
|
|
11
|
-
body below is a bare ``raise NotImplementedError`` that the composed class
|
|
12
|
-
always overrides, so the MRO and every method resolution stay what the
|
|
13
|
-
single-file class had. Adding a cross-mixin call without declaring it here is a
|
|
14
|
-
type error.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
from __future__ import annotations
|
|
18
|
-
|
|
19
|
-
from typing import Any, Dict, List, Optional
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class BrainIntelligenceCore:
|
|
23
|
-
"""What any Brain Intelligence mixin may assume about ``self``.
|
|
24
|
-
|
|
25
|
-
Members are declared, not implemented: the implementation lives in
|
|
26
|
-
``service.py`` (constructor state) or in whichever mixin owns the method.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
# ── State owned by BrainIntelligenceService.__init__ ─────────────────────
|
|
30
|
-
_kg: Any
|
|
31
|
-
_memory: Any
|
|
32
|
-
_enable_graph: bool
|
|
33
|
-
_memory_quality: Any
|
|
34
|
-
_edge_quality: Any
|
|
35
|
-
_proactive_brain: Any
|
|
36
|
-
_review_queue_service: Any
|
|
37
|
-
_synthesizer: Any
|
|
38
|
-
|
|
39
|
-
# ── proposals.py: the review-queue seam every write door goes through ────
|
|
40
|
-
def _review_queue(self) -> Any:
|
|
41
|
-
raise NotImplementedError
|
|
42
|
-
|
|
43
|
-
def _synthesis(self) -> Any:
|
|
44
|
-
raise NotImplementedError
|
|
45
|
-
|
|
46
|
-
@staticmethod
|
|
47
|
-
def _no_queue(detail: str) -> Dict[str, Any]:
|
|
48
|
-
raise NotImplementedError
|
|
49
|
-
|
|
50
|
-
def importance_report(
|
|
51
|
-
self, *, user_email: Optional[str] = None, workspace_id: Optional[str] = None
|
|
52
|
-
) -> Dict[str, Any]:
|
|
53
|
-
raise NotImplementedError
|
|
54
|
-
|
|
55
|
-
# ── sampling.py: the graph slice and the memory tier ─────────────────────
|
|
56
|
-
def _proactive(self) -> Any:
|
|
57
|
-
raise NotImplementedError
|
|
58
|
-
|
|
59
|
-
def _graph_sample(self, *, workspace_id: Optional[str]) -> Dict[str, Any]:
|
|
60
|
-
raise NotImplementedError
|
|
61
|
-
|
|
62
|
-
def _workspace_memories(
|
|
63
|
-
self, *, user_email: Optional[str], workspace_id: Optional[str]
|
|
64
|
-
) -> List[Dict[str, Any]]:
|
|
65
|
-
raise NotImplementedError
|
|
66
|
-
|
|
67
|
-
# ── consistency.py: what the garden view composes ────────────────────────
|
|
68
|
-
def contradictions(
|
|
69
|
-
self, *, user_email: Optional[str] = None, workspace_id: Optional[str] = None
|
|
70
|
-
) -> Dict[str, Any]:
|
|
71
|
-
raise NotImplementedError
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
"""What the Brain disagrees with itself about, and what it says twice.
|
|
2
|
-
|
|
3
|
-
Two scans that wire the previously dormant quality layer
|
|
4
|
-
(:mod:`lattice_brain.quality`) to real stores:
|
|
5
|
-
|
|
6
|
-
* :meth:`contradictions` — four independent signals in one list: negation and
|
|
7
|
-
preference conflicts between workspace memories, temporal contradictions,
|
|
8
|
-
explicit ``CONTRADICTS`` edges already recorded in the graph, and the graph
|
|
9
|
-
layer's own node-content detector. Each item carries the signal that found
|
|
10
|
-
it, so a reviewer can weigh them differently.
|
|
11
|
-
* :meth:`consolidate` — duplicate memories and duplicate edges. Dry-run by
|
|
12
|
-
default, consent-first like every Brain automation. ``apply=True`` prunes
|
|
13
|
-
only exact duplicate *workspace memories*, through the audited MemoryService
|
|
14
|
-
path; graph content is never mutated here — the node merge plan is surfaced
|
|
15
|
-
for a governed apply path to adopt.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
from __future__ import annotations
|
|
19
|
-
|
|
20
|
-
from typing import Any, Dict, List, Optional
|
|
21
|
-
|
|
22
|
-
from latticeai.core.timeutil import now_iso as _now
|
|
23
|
-
|
|
24
|
-
from ._contract import BrainIntelligenceCore as _Core
|
|
25
|
-
from .constants import LOGGER
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class BrainConsistencyMixin(_Core):
|
|
29
|
-
"""Contradiction and consolidation scans. Mixed into the service."""
|
|
30
|
-
|
|
31
|
-
# ── contradictions ───────────────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
def contradictions(
|
|
34
|
-
self, *, user_email: Optional[str] = None, workspace_id: Optional[str] = None
|
|
35
|
-
) -> Dict[str, Any]:
|
|
36
|
-
memories = self._workspace_memories(user_email=user_email, workspace_id=workspace_id)
|
|
37
|
-
memory_rows = [
|
|
38
|
-
{
|
|
39
|
-
"id": str(m.get("id") or f"mem-{i}"),
|
|
40
|
-
"content": str(m.get("content") or ""),
|
|
41
|
-
"score": 0.6,
|
|
42
|
-
"source": "workspace",
|
|
43
|
-
"timestamp": m.get("created_at") or m.get("timestamp") or 0,
|
|
44
|
-
}
|
|
45
|
-
for i, m in enumerate(memories)
|
|
46
|
-
if str(m.get("content") or "").strip()
|
|
47
|
-
]
|
|
48
|
-
|
|
49
|
-
conflicts: List[Dict[str, Any]] = []
|
|
50
|
-
candidates = self._memory_quality.extract_candidates(memory_rows)
|
|
51
|
-
for candidate in self._memory_quality.detect_conflicts(candidates):
|
|
52
|
-
pair_conflicts = [c for c in candidate.conflicts if c.startswith("conflict:contradicts:")]
|
|
53
|
-
for marker in pair_conflicts:
|
|
54
|
-
other_id = marker.rsplit(":", 1)[-1]
|
|
55
|
-
if any(
|
|
56
|
-
c["kind"] == "memory_pair"
|
|
57
|
-
and {c["left_id"], c["right_id"]} == {candidate.id, other_id}
|
|
58
|
-
for c in conflicts
|
|
59
|
-
):
|
|
60
|
-
continue
|
|
61
|
-
other: Dict[str, Any] | None = next(
|
|
62
|
-
(r for r in memory_rows if r["id"] == other_id), None
|
|
63
|
-
)
|
|
64
|
-
conflicts.append({
|
|
65
|
-
"kind": "memory_pair",
|
|
66
|
-
"left_id": candidate.id,
|
|
67
|
-
"left_content": candidate.content[:200],
|
|
68
|
-
"right_id": other_id,
|
|
69
|
-
"right_content": (other or {}).get("content", "")[:200],
|
|
70
|
-
"signal": "preference_negation",
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
temporal = self._memory_quality.detect_temporal_contradictions(memory_rows)
|
|
74
|
-
temporal_items = [
|
|
75
|
-
{
|
|
76
|
-
"kind": "temporal",
|
|
77
|
-
"id": item.get("id"),
|
|
78
|
-
"content": str(item.get("content") or "")[:200],
|
|
79
|
-
"signal": item.get("proactive_flag"),
|
|
80
|
-
}
|
|
81
|
-
for item in temporal
|
|
82
|
-
]
|
|
83
|
-
|
|
84
|
-
edge_items: List[Dict[str, Any]] = []
|
|
85
|
-
sample = self._graph_sample(workspace_id=workspace_id)
|
|
86
|
-
for edge in sample["edges"]:
|
|
87
|
-
if "CONTRADICT" in str(edge.get("type") or "").upper():
|
|
88
|
-
edge_items.append({
|
|
89
|
-
"kind": "graph_edge",
|
|
90
|
-
"id": edge.get("id"),
|
|
91
|
-
"source": edge.get("source") or edge.get("from_node"),
|
|
92
|
-
"target": edge.get("target") or edge.get("to_node"),
|
|
93
|
-
"signal": "contradicts_edge",
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
# v9.6.x additive: graph-layer node-content contradictions (proactive
|
|
97
|
-
# detector over node title/summary), on top of the memory + edge scans.
|
|
98
|
-
graph_pair_items: List[Dict[str, Any]] = []
|
|
99
|
-
proactive = self._proactive()
|
|
100
|
-
if proactive is not None:
|
|
101
|
-
try:
|
|
102
|
-
graph_result = proactive.detect_contradictions(workspace_id=workspace_id)
|
|
103
|
-
graph_pair_items = [
|
|
104
|
-
{"kind": "graph_node_pair", **pair}
|
|
105
|
-
for pair in graph_result.get("node_pairs") or []
|
|
106
|
-
]
|
|
107
|
-
except Exception:
|
|
108
|
-
LOGGER.exception("graph contradiction scan failed")
|
|
109
|
-
|
|
110
|
-
items = conflicts + temporal_items + edge_items + graph_pair_items
|
|
111
|
-
return {
|
|
112
|
-
"items": items,
|
|
113
|
-
"count": len(items),
|
|
114
|
-
"sources": {
|
|
115
|
-
"memory_pairs": len(conflicts),
|
|
116
|
-
"temporal": len(temporal_items),
|
|
117
|
-
"graph_edges": len(edge_items),
|
|
118
|
-
"graph_node_pairs": len(graph_pair_items),
|
|
119
|
-
},
|
|
120
|
-
"memories_scanned": len(memory_rows),
|
|
121
|
-
"generated_at": _now(),
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
# ── consolidation ────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
def consolidate(
|
|
127
|
-
self,
|
|
128
|
-
*,
|
|
129
|
-
apply: bool = False,
|
|
130
|
-
user_email: Optional[str] = None,
|
|
131
|
-
workspace_id: Optional[str] = None,
|
|
132
|
-
) -> Dict[str, Any]:
|
|
133
|
-
memories = self._workspace_memories(user_email=user_email, workspace_id=workspace_id)
|
|
134
|
-
memory_rows = [
|
|
135
|
-
{
|
|
136
|
-
"id": str(m.get("id") or f"mem-{i}"),
|
|
137
|
-
"content": str(m.get("content") or ""),
|
|
138
|
-
"score": 0.6,
|
|
139
|
-
"source": "workspace",
|
|
140
|
-
}
|
|
141
|
-
for i, m in enumerate(memories)
|
|
142
|
-
if str(m.get("content") or "").strip()
|
|
143
|
-
]
|
|
144
|
-
candidates = self._memory_quality.extract_candidates(memory_rows)
|
|
145
|
-
kept = self._memory_quality.dedupe(candidates)
|
|
146
|
-
kept_ids = {c.id for c in kept}
|
|
147
|
-
duplicate_memory_ids = [c.id for c in candidates if c.id not in kept_ids]
|
|
148
|
-
|
|
149
|
-
sample = self._graph_sample(workspace_id=workspace_id)
|
|
150
|
-
duplicate_edge_ids = [
|
|
151
|
-
edge_id
|
|
152
|
-
for edge_id in self._edge_quality.detect_duplicate_edges(sample["edges"])
|
|
153
|
-
if edge_id
|
|
154
|
-
]
|
|
155
|
-
|
|
156
|
-
pruned = 0
|
|
157
|
-
if apply and duplicate_memory_ids and self._memory is not None:
|
|
158
|
-
try:
|
|
159
|
-
result = self._memory.prune(
|
|
160
|
-
ids=duplicate_memory_ids,
|
|
161
|
-
user_email=user_email,
|
|
162
|
-
workspace_id=workspace_id,
|
|
163
|
-
)
|
|
164
|
-
pruned = int(result.get("count") or 0)
|
|
165
|
-
except Exception:
|
|
166
|
-
LOGGER.exception("consolidation prune failed")
|
|
167
|
-
|
|
168
|
-
# v9.6.x additive: graph-layer node merge plan. Always dry-run from
|
|
169
|
-
# this service — graph content changes stay proposal-first; the plan
|
|
170
|
-
# is surfaced so a governed apply path can adopt it later.
|
|
171
|
-
graph_consolidation: Optional[Dict[str, Any]] = None
|
|
172
|
-
proactive = self._proactive()
|
|
173
|
-
if proactive is not None:
|
|
174
|
-
try:
|
|
175
|
-
graph_consolidation = proactive.consolidate_duplicates(
|
|
176
|
-
workspace_id=workspace_id, dry_run=True
|
|
177
|
-
)
|
|
178
|
-
except Exception:
|
|
179
|
-
LOGGER.exception("graph consolidation plan failed")
|
|
180
|
-
|
|
181
|
-
return {
|
|
182
|
-
"mode": "applied" if apply else "dry_run",
|
|
183
|
-
"memories_scanned": len(memory_rows),
|
|
184
|
-
"duplicate_memories": duplicate_memory_ids,
|
|
185
|
-
"duplicate_memory_count": len(duplicate_memory_ids),
|
|
186
|
-
"pruned": pruned,
|
|
187
|
-
# Graph edges are reported for review only; consolidation never
|
|
188
|
-
# mutates graph content directly.
|
|
189
|
-
"duplicate_edges": duplicate_edge_ids[:50],
|
|
190
|
-
"duplicate_edge_count": len(duplicate_edge_ids),
|
|
191
|
-
"graph_consolidation": graph_consolidation,
|
|
192
|
-
"generated_at": _now(),
|
|
193
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"""Windows, sample sizes, and the two readings every surface shares.
|
|
2
|
-
|
|
3
|
-
Leaf module: literals and pure functions only, no service and no store. The
|
|
4
|
-
health report, the insights digest, the garden and the contradiction scan all
|
|
5
|
-
measure against the same windows, which is what makes their numbers
|
|
6
|
-
comparable.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
import logging
|
|
12
|
-
from datetime import datetime, timezone
|
|
13
|
-
from typing import Any, Optional
|
|
14
|
-
|
|
15
|
-
LOGGER = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
_STALE_DAYS = 45
|
|
18
|
-
_RECENT_DAYS = 7
|
|
19
|
-
_GRAPH_SAMPLE_LIMIT = 800
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def _parse_ts(value: Any) -> Optional[datetime]:
|
|
23
|
-
text = str(value or "").strip()
|
|
24
|
-
if not text:
|
|
25
|
-
return None
|
|
26
|
-
try:
|
|
27
|
-
parsed = datetime.fromisoformat(text.replace("Z", "+00:00"))
|
|
28
|
-
except ValueError:
|
|
29
|
-
return None
|
|
30
|
-
if parsed.tzinfo is None:
|
|
31
|
-
parsed = parsed.replace(tzinfo=timezone.utc)
|
|
32
|
-
return parsed
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def _no_graph_reason(graph_available: bool) -> str:
|
|
36
|
-
"""Why a graph-derived health dimension has nothing to say.
|
|
37
|
-
|
|
38
|
-
Two different situations that both end in ``status: "unavailable"``: the
|
|
39
|
-
graph could not be read at all, and the graph read fine but holds nothing
|
|
40
|
-
yet. Telling them apart is the difference between "something is broken"
|
|
41
|
-
and "you have not saved anything yet".
|
|
42
|
-
"""
|
|
43
|
-
return (
|
|
44
|
-
"no knowledge saved yet"
|
|
45
|
-
if graph_available
|
|
46
|
-
else "the knowledge graph could not be read"
|
|
47
|
-
)
|