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,57 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Brain storage migration utility.
|
|
3
|
-
|
|
4
|
-
Examples:
|
|
5
|
-
python scripts/migrate_brain_storage.py plan --sqlite ~/.ltcai/knowledge_graph.sqlite --dsn postgresql://...
|
|
6
|
-
python scripts/migrate_brain_storage.py migrate --sqlite ~/.ltcai/knowledge_graph.sqlite --dsn postgresql://...
|
|
7
|
-
python scripts/migrate_brain_storage.py docker-plan --data-dir ~/.ltcai/postgres
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from __future__ import annotations
|
|
11
|
-
|
|
12
|
-
import argparse
|
|
13
|
-
import json
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
|
|
16
|
-
from lattice_brain.storage import (
|
|
17
|
-
DockerPostgresWizard,
|
|
18
|
-
PostgresEngine,
|
|
19
|
-
SQLiteToPostgresMigrator,
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _print_json(value: object) -> None:
|
|
24
|
-
print(json.dumps(value, ensure_ascii=False, indent=2))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def main() -> int:
|
|
28
|
-
parser = argparse.ArgumentParser(description=__doc__)
|
|
29
|
-
sub = parser.add_subparsers(dest="command", required=True)
|
|
30
|
-
|
|
31
|
-
for name in ("plan", "migrate"):
|
|
32
|
-
p = sub.add_parser(name)
|
|
33
|
-
p.add_argument("--sqlite", type=Path, required=True)
|
|
34
|
-
p.add_argument("--dsn", required=True)
|
|
35
|
-
p.add_argument("--schema", default="lattice_brain")
|
|
36
|
-
|
|
37
|
-
docker = sub.add_parser("docker-plan")
|
|
38
|
-
docker.add_argument("--data-dir", type=Path, required=True)
|
|
39
|
-
docker.add_argument("--port", type=int, default=5432)
|
|
40
|
-
|
|
41
|
-
args = parser.parse_args()
|
|
42
|
-
if args.command == "docker-plan":
|
|
43
|
-
wizard = DockerPostgresWizard(args.data_dir, port=args.port)
|
|
44
|
-
result = wizard.start(consent=False)
|
|
45
|
-
_print_json(result)
|
|
46
|
-
return 0
|
|
47
|
-
|
|
48
|
-
migrator = SQLiteToPostgresMigrator(
|
|
49
|
-
args.sqlite,
|
|
50
|
-
PostgresEngine(args.dsn, schema=args.schema),
|
|
51
|
-
)
|
|
52
|
-
_print_json(migrator.migrate(dry_run=args.command == "plan"))
|
|
53
|
-
return 0
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if __name__ == "__main__":
|
|
57
|
-
raise SystemExit(main())
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""The context-assembly half of the Python↔Rust parity corpus (v11.5.2).
|
|
3
|
-
|
|
4
|
-
``scripts/generate_rust_parity_fixtures.py`` owns the store, the harness and the
|
|
5
|
-
goldens; this module owns the specs and runners for the two context ports, so
|
|
6
|
-
neither file grows past the tree's file-size ceiling. The split follows the
|
|
7
|
-
``parity_fixture_corpus_docgen`` precedent: specs and their runners live side by
|
|
8
|
-
side, because a spec list that arrives without the runner that answers it is a
|
|
9
|
-
suite that silently checks nothing.
|
|
10
|
-
|
|
11
|
-
Two ports, deliberately separate:
|
|
12
|
-
|
|
13
|
-
* **``context_assemble``** pins :class:`~lattice_brain.context.ContextAssembler`
|
|
14
|
-
over the seams the *production* assembler supplies
|
|
15
|
-
(``latticeai/runtime/context_runtime.py``): memories, artifacts, hybrid
|
|
16
|
-
knowledge and garden notes. It does **not** supply ``recent_chat`` — that seam
|
|
17
|
-
has never been wired live, and a golden that pinned it claimed cross-runtime
|
|
18
|
-
agreement about a code path the product does not execute.
|
|
19
|
-
* **``recent_chat``** pins the recent-conversation transcript as the product
|
|
20
|
-
really builds it: ``chat.py`` prepends ``build_recent_chat_context(...)`` on
|
|
21
|
-
every non-hybrid turn and the agent loop injects the same text each executor
|
|
22
|
-
step. Its Rust twin is ``lattice_retrieval::history::recent_chat``.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
from __future__ import annotations
|
|
26
|
-
|
|
27
|
-
from typing import Any, Callable, Dict, List
|
|
28
|
-
|
|
29
|
-
#: ``h`` is the generator's ``Harness``. It is typed ``Any`` rather than
|
|
30
|
-
#: imported: the harness owns the live store and the service layer, so importing
|
|
31
|
-
#: it here would make the corpus depend on the generator that imports *it*.
|
|
32
|
-
|
|
33
|
-
#: The organization workspace the corpus seeds; the same literal the generator
|
|
34
|
-
#: and the docgen corpus use.
|
|
35
|
-
WS_ALPHA = "ws-alpha"
|
|
36
|
-
|
|
37
|
-
CONTEXT_MEMORIES: Dict[str, Any] = {
|
|
38
|
-
"results": [
|
|
39
|
-
{"id": "mem-1", "kind": "preference", "snippet": "답변은 한국어로", "score": 0.91, "source": "workspace"},
|
|
40
|
-
{"id": "mem-2", "kind": None, "snippet": "", "score": 0.0, "source": "workspace"},
|
|
41
|
-
{"id": "mem-3", "kind": "decision", "snippet": "ranking keeps alpha fusion", "score": 0.4, "source": "personal"},
|
|
42
|
-
{"id": "mem-4", "kind": "fact", "snippet": "온보딩은 다섯 걸음", "score": 0.3, "source": "workspace"},
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
#: A ledger with a pathless row, a non-dict row, and more than the ten-row cut.
|
|
47
|
-
CONTEXT_ARTIFACTS: List[Any] = [
|
|
48
|
-
{"path": "notes/ranking.md", "at": "2026-07-20T09:00:00", "run_id": "run-1"},
|
|
49
|
-
{"path": "notes/onboarding.md", "run_id": "run-2"},
|
|
50
|
-
{"path": "", "at": "2026-07-20T09:00:01"},
|
|
51
|
-
"not-a-dict",
|
|
52
|
-
] + [{"path": f"out/file-{index}.md", "at": None, "run_id": f"r{index}"} for index in range(10)]
|
|
53
|
-
|
|
54
|
-
def _context_seams(h: Any, spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
55
|
-
"""The seam set for one context spec — data seams plus the real engines.
|
|
56
|
-
|
|
57
|
-
``memories`` / ``artifacts`` / ``notes`` are *data* seams: the payload is the
|
|
58
|
-
spec, so both runtimes feed the assembler the same bytes and what is under
|
|
59
|
-
test is the assembler. ``knowledge`` is a real engine — the service-layer
|
|
60
|
-
hybrid search.
|
|
61
|
-
|
|
62
|
-
There is deliberately no ``recent_chat`` seam here: the production
|
|
63
|
-
assembler does not supply one, so a golden that did would pin agreement
|
|
64
|
-
about a path neither runtime reaches in the product. The recent transcript
|
|
65
|
-
is pinned by the ``recent_chat`` suite instead.
|
|
66
|
-
"""
|
|
67
|
-
# Signatures matter: the assembler inspects them to decide which context
|
|
68
|
-
# fields a seam may be handed, so each one declares exactly what it accepts.
|
|
69
|
-
seams: Dict[str, Any] = {}
|
|
70
|
-
if spec.get("memories") is not None:
|
|
71
|
-
memories = spec["memories"]
|
|
72
|
-
seams["memory_recall"] = (
|
|
73
|
-
lambda query, *, user_email=None, workspace_id=None, limit=5: memories
|
|
74
|
-
)
|
|
75
|
-
if spec.get("artifacts") is not None:
|
|
76
|
-
artifacts = spec["artifacts"]
|
|
77
|
-
seams["recent_artifacts"] = (
|
|
78
|
-
lambda *, user_email=None, conversation_id=None, workspace_id=None: artifacts
|
|
79
|
-
)
|
|
80
|
-
if spec.get("knowledge", True):
|
|
81
|
-
# Loopback trust: no workspace scoping, exactly as on the native route.
|
|
82
|
-
seams["hybrid_search"] = (
|
|
83
|
-
lambda query, *, limit=5, user_email=None, workspace_id=None:
|
|
84
|
-
h.service.hybrid_search(query, limit=limit)
|
|
85
|
-
)
|
|
86
|
-
if spec.get("notes") is not None:
|
|
87
|
-
notes = spec["notes"]
|
|
88
|
-
seams["notes_context"] = lambda query, *, user_email=None, workspace_id=None: notes
|
|
89
|
-
return seams
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _run_context_assemble(h: Any, spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
93
|
-
from lattice_brain.context import ContextAssembler
|
|
94
|
-
|
|
95
|
-
assembled = ContextAssembler(**_context_seams(h, spec)).assemble(
|
|
96
|
-
spec["query"], user_email=spec.get("user_email"),
|
|
97
|
-
workspace_id=spec.get("workspace_id"),
|
|
98
|
-
conversation_id=spec.get("conversation_id"), budget=spec.get("budget", 2000),
|
|
99
|
-
memory_limit=spec.get("memory_limit", 5),
|
|
100
|
-
knowledge_limit=spec.get("knowledge_limit", 5),
|
|
101
|
-
)
|
|
102
|
-
return {"text": assembled.text, "approx_tokens": assembled.approx_tokens,
|
|
103
|
-
"trace": assembled.trace()}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _run_recent_chat(h: Any, spec: Dict[str, Any]) -> str:
|
|
107
|
-
"""The recent-conversation transcript, exactly as ``/chat`` builds it."""
|
|
108
|
-
from latticeai.api.chat_helpers import build_recent_chat_context
|
|
109
|
-
|
|
110
|
-
return build_recent_chat_context(
|
|
111
|
-
get_history=h.history_runtime["get_history"],
|
|
112
|
-
limit=spec.get("limit", 10),
|
|
113
|
-
include_image_missing_replies=spec.get("images", True),
|
|
114
|
-
user_email=spec.get("user_email"),
|
|
115
|
-
conversation_id=spec.get("conversation_id"),
|
|
116
|
-
workspace_id=spec.get("workspace_id"),
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
#: The two context suites, as the generator merges them into :data:`SUITES` /
|
|
121
|
-
#: :data:`SUITE_RUNNERS`.
|
|
122
|
-
CONTEXT_SUITES: Dict[str, List[Dict[str, Any]]] = {
|
|
123
|
-
# 11.5.2: these pin the assembler over the seams the *production* assembler
|
|
124
|
-
# supplies (`latticeai/runtime/context_runtime.py`). The `recent_chat` seam
|
|
125
|
-
# is not one of them — it has never been wired live — so pinning it here
|
|
126
|
-
# claimed cross-runtime agreement about a code path the product does not
|
|
127
|
-
# run. The recent-conversation text itself is still pinned, in the
|
|
128
|
-
# `recent_chat` suite below, against the function chat really calls.
|
|
129
|
-
"context_assemble": [
|
|
130
|
-
{"key": "all_seams", "query": "회의 결정 사항", "memories": CONTEXT_MEMORIES, "artifacts": CONTEXT_ARTIFACTS, "notes": "정원 노트: 랭킹은 alpha 융합을 유지한다."},
|
|
131
|
-
{"key": "knowledge_only", "query": "hybrid retrieval ranking"},
|
|
132
|
-
{"key": "no_seams", "query": "hybrid retrieval ranking", "knowledge": False},
|
|
133
|
-
{"key": "memories_only", "query": "온보딩", "knowledge": False, "memories": CONTEXT_MEMORIES, "memory_limit": 2},
|
|
134
|
-
{"key": "artifacts_only", "query": "온보딩", "knowledge": False, "artifacts": CONTEXT_ARTIFACTS},
|
|
135
|
-
{"key": "notes_blank", "query": "온보딩", "knowledge": False, "notes": " "},
|
|
136
|
-
{"key": "budget_tiny", "query": "회의 결정 사항", "memories": CONTEXT_MEMORIES, "artifacts": CONTEXT_ARTIFACTS, "notes": "정원 노트: 랭킹은 alpha 융합을 유지한다.", "budget": 20},
|
|
137
|
-
{"key": "budget_one", "query": "회의 결정 사항", "memories": CONTEXT_MEMORIES, "artifacts": CONTEXT_ARTIFACTS, "notes": "노트", "budget": 1},
|
|
138
|
-
{"key": "budget_zero", "query": "회의 결정 사항", "memories": CONTEXT_MEMORIES, "notes": "노트", "budget": 0},
|
|
139
|
-
{"key": "knowledge_limit_one", "query": "hybrid retrieval ranking", "knowledge_limit": 1},
|
|
140
|
-
],
|
|
141
|
-
# The recent-conversation transcript as the product actually builds it:
|
|
142
|
-
# `chat.py` prepends `build_recent_chat_context(...)` on every non-hybrid
|
|
143
|
-
# turn, and the agent loop injects the same text each executor step. This
|
|
144
|
-
# is the live twin of `lattice_retrieval::history::recent_chat`.
|
|
145
|
-
"recent_chat": [
|
|
146
|
-
{"key": "everything"},
|
|
147
|
-
{"key": "conversation", "conversation_id": "conv-a"},
|
|
148
|
-
{"key": "conversation_missing", "conversation_id": "nope"},
|
|
149
|
-
{"key": "personal_workspace", "workspace_id": "personal", "limit": 6},
|
|
150
|
-
{"key": "workspace_alpha", "workspace_id": WS_ALPHA},
|
|
151
|
-
{"key": "user_scoped", "user_email": "jiwon@lattice.ai", "limit": 5},
|
|
152
|
-
{"key": "user_and_conversation", "user_email": "jiwon@lattice.ai", "conversation_id": "conv-a"},
|
|
153
|
-
{"key": "limit_one", "limit": 1},
|
|
154
|
-
{"key": "limit_zero", "limit": 0},
|
|
155
|
-
{"key": "image_replies_dropped", "images": False},
|
|
156
|
-
],
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
CONTEXT_RUNNERS: Dict[str, Callable[..., Any]] = {
|
|
160
|
-
"context_assemble": _run_context_assemble,
|
|
161
|
-
"recent_chat": _run_recent_chat,
|
|
162
|
-
}
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""The document-generation half of the Python↔Rust parity corpus (v11.5.1).
|
|
3
|
-
|
|
4
|
-
``scripts/generate_rust_parity_fixtures.py`` owns the store and the goldens;
|
|
5
|
-
this module owns the rows and specs the **document-generation** ports need, so
|
|
6
|
-
neither file has to grow past the tree's file-size ceiling. Nothing here runs
|
|
7
|
-
anything — it is data plus one normalization helper.
|
|
8
|
-
|
|
9
|
-
Three things are shaped on purpose:
|
|
10
|
-
|
|
11
|
-
* **Every allow-listed node type appears.** ``search_for_document_generation``
|
|
12
|
-
admits fifteen types and boosts four of them; a corpus that only carried
|
|
13
|
-
``Document`` would prove the boost and the filter equally badly.
|
|
14
|
-
* **The Self-Model subgraph is real.** ``summary_for_prompt`` reads the legacy
|
|
15
|
-
``nodes`` table for ``self:%`` ids, so the profile rows are written through
|
|
16
|
-
the same write door as everything else, including the root the read excludes
|
|
17
|
-
and a ``self:`` row whose metadata carries no recognised kind (dropped).
|
|
18
|
-
* **``updated_at`` is spread against the frozen clock**, including one stamp
|
|
19
|
-
that does not parse — the recency term's ``0.0`` branch is otherwise
|
|
20
|
-
unreachable from a fixture whose every row is well formed.
|
|
21
|
-
|
|
22
|
-
:func:`normalize_multi_hop` is the one deliberate deviation, and it is a
|
|
23
|
-
*golden* normalization rather than a port divergence: see its docstring.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
from __future__ import annotations
|
|
27
|
-
|
|
28
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
29
|
-
|
|
30
|
-
WS_ALPHA = "ws-alpha"
|
|
31
|
-
WS_BETA = "ws-beta"
|
|
32
|
-
|
|
33
|
-
# ── the document-generation corpus ───────────────────────────────────────────
|
|
34
|
-
# (node_id, type, title, summary, metadata, workspace_id, updated_at)
|
|
35
|
-
DOCGEN_NODES: List[Tuple[str, str, str, str, Dict[str, Any], Optional[str], str]] = [
|
|
36
|
-
# ── the Self-Model subgraph (read by `summary_for_prompt`) ──────────────
|
|
37
|
-
# `self:root` is excluded by id, and `self:unknown:*` carries no
|
|
38
|
-
# `self_model_kind`, so `_row_to_fact` drops it — both are read branches
|
|
39
|
-
# that only exist if the fixture actually contains them.
|
|
40
|
-
("self:root", "Self", "나", "Brain이 사용자에 대해 알고 있는 사실의 뿌리입니다.",
|
|
41
|
-
{"self_model": True, "self_model_kind": "root"}, None, "2026-07-01T09:00:00"),
|
|
42
|
-
("self:decision:a1", "Decision", "문서는 한국어로 쓴다",
|
|
43
|
-
"문서는 한국어로 쓴다",
|
|
44
|
-
{"self_model": True, "self_model_kind": "decision", "origin": "user",
|
|
45
|
-
"confidence": 0.9, "signal": "ko_decision_marker", "workspace_id": WS_ALPHA},
|
|
46
|
-
WS_ALPHA, "2026-07-02T09:00:00"),
|
|
47
|
-
("self:habit:b2", "Habit", "매주 월요일 회의록을 정리한다",
|
|
48
|
-
"매주 월요일 회의록을 정리한다",
|
|
49
|
-
{"self_model": True, "self_model_kind": "habit", "origin": "extraction",
|
|
50
|
-
"confidence": 0.6, "signal": "ko_habit", "workspace_id": None},
|
|
51
|
-
None, "2026-07-03T09:00:00"),
|
|
52
|
-
("self:preference:c3", "Preference", "설명은 짧고 근거를 먼저",
|
|
53
|
-
"설명은 짧고 근거를 먼저",
|
|
54
|
-
{"self_model": True, "self_model_kind": "preference", "origin": "user",
|
|
55
|
-
"confidence": 0.8, "signal": "ko_prefer", "workspace_id": None},
|
|
56
|
-
None, "2026-07-04T09:00:00"),
|
|
57
|
-
("self:relationship:d4", "Relationship", "박민서 님과 빌드 파이프라인을 함께 본다",
|
|
58
|
-
"박민서 님과 빌드 파이프라인을 함께 본다",
|
|
59
|
-
{"self_model": True, "self_model_kind": "relationship", "origin": "extraction",
|
|
60
|
-
"confidence": 0.5, "signal": "ko_with", "workspace_id": WS_BETA},
|
|
61
|
-
WS_BETA, "2026-07-05T09:00:00"),
|
|
62
|
-
("self:trait:e5", "Self", "검색 품질 담당자",
|
|
63
|
-
"검색 품질 담당자",
|
|
64
|
-
{"self_model": True, "self_model_kind": "trait", "origin": "user",
|
|
65
|
-
"confidence": 0.7, "signal": "ko_role", "workspace_id": None},
|
|
66
|
-
None, "2026-07-06T09:00:00"),
|
|
67
|
-
("self:unknown:f6", "Concept", "kind가 없는 self 노드",
|
|
68
|
-
"self_model_kind가 없어 프로필에서 제외되는 행입니다.",
|
|
69
|
-
{"self_model": True}, None, "2026-07-07T09:00:00"),
|
|
70
|
-
# ── the proposal cluster: one hub document with more qualifying
|
|
71
|
-
# neighbours than the eight the related-concept join keeps ───────────
|
|
72
|
-
("doc:proposal", "Document", "제안서 초안: 검색 품질 개선",
|
|
73
|
-
"검색 품질 개선 제안서 초안입니다. 근거는 주간 회의 기록과 분기 리뷰 발표자료입니다.",
|
|
74
|
-
{"relative_path": "docs/proposal.md", "filename": "proposal.md", "ext": ".md"},
|
|
75
|
-
WS_ALPHA, "2026-07-30T09:00:00"),
|
|
76
|
-
("doc:release-notes", "Document", "Release notes for the retrieval port",
|
|
77
|
-
"Release notes describing the ranking port and the parity harness.",
|
|
78
|
-
{"source": "release"}, None, "2026-07-28T09:00:00"),
|
|
79
|
-
("file:meeting-minutes", "File", "meeting-minutes.md",
|
|
80
|
-
"회의록: 랭킹 개선과 온보딩 체크리스트를 확정했습니다.",
|
|
81
|
-
{"filename": "meeting-minutes.md", "relative_path": "notes/meeting-minutes.md"},
|
|
82
|
-
WS_ALPHA, "2026-08-01T11:00:00"),
|
|
83
|
-
("deck:proposal", "SlideDeck", "제안 발표자료",
|
|
84
|
-
"제안서 초안을 발표용으로 정리한 자료입니다.",
|
|
85
|
-
{"filename": "proposal.pptx", "ext": ".pptx"}, WS_BETA, "2026-07-29T09:00:00"),
|
|
86
|
-
("chat:proposal", "Chat", "제안서 관련 대화",
|
|
87
|
-
"제안서 초안을 어떻게 쓸지 논의한 대화입니다.",
|
|
88
|
-
{"conversation_id": "conv-f"}, WS_ALPHA, "2026-07-26T09:00:00"),
|
|
89
|
-
("task:proposal-review", "Task", "제안서 검토",
|
|
90
|
-
"제안서 초안을 검토하고 근거를 확인합니다.", {"status": "open"},
|
|
91
|
-
WS_ALPHA, "2026-07-27T09:00:00"),
|
|
92
|
-
("dec:doc-format", "Decision", "문서 형식은 마크다운으로 통일",
|
|
93
|
-
"문서 생성 결과는 마크다운으로 통일하기로 했습니다.", {},
|
|
94
|
-
WS_ALPHA, "2026-07-22T09:00:00"),
|
|
95
|
-
("feature:doc-generation", "Feature", "문서 생성",
|
|
96
|
-
"질문에서 문서를 만들어 주는 기능입니다.", {}, WS_ALPHA, "2026-07-25T09:00:00"),
|
|
97
|
-
("concept:proposal", "Concept", "제안서",
|
|
98
|
-
"제안서는 결정을 요청하는 문서입니다.", {}, None, "2026-07-24T09:00:00"),
|
|
99
|
-
("concept:evidence", "Concept", "근거",
|
|
100
|
-
"근거는 주장을 뒷받침하는 자료입니다.", {}, WS_ALPHA, "2026-07-23T09:00:00"),
|
|
101
|
-
("page:proposal-outline", "Page", "제안서 목차",
|
|
102
|
-
"제안서 목차 페이지입니다.", {}, None, "2026-07-21T09:00:00"),
|
|
103
|
-
("slide:proposal-1", "Slide", "제안 슬라이드 1",
|
|
104
|
-
"제안서 요약 슬라이드입니다.", {}, WS_BETA, "2026-07-19T09:00:00"),
|
|
105
|
-
("sheet:proposal-budget", "Spreadsheet", "proposal-budget.xlsx",
|
|
106
|
-
"제안서 예산 표입니다.", {"filename": "proposal-budget.xlsx", "ext": ".xlsx"},
|
|
107
|
-
WS_ALPHA, "2026-07-17T09:00:00"),
|
|
108
|
-
("img:proposal-sketch", "Image", "proposal-sketch.png",
|
|
109
|
-
"제안서 구조 스케치입니다.", {"filename": "proposal-sketch.png", "ext": ".png"},
|
|
110
|
-
WS_BETA, "2026-07-16T09:00:00"),
|
|
111
|
-
("imgtext:proposal-ocr", "ImageText", "제안서 스케치 OCR",
|
|
112
|
-
"제안서 구조: 배경, 근거, 결론.",
|
|
113
|
-
{"filename": "proposal-sketch.png", "ocr": True}, WS_BETA, "2026-07-16T09:01:00"),
|
|
114
|
-
("audio:proposal-call", "Audio", "proposal-call.m4a",
|
|
115
|
-
"제안서 관련 통화 녹음입니다.", {"filename": "proposal-call.m4a", "ext": ".m4a"},
|
|
116
|
-
WS_ALPHA, "2026-07-15T09:00:00"),
|
|
117
|
-
("code:doc-builder", "CodeFile", "context_builder.py",
|
|
118
|
-
"문서 생성 컨텍스트를 조합하는 코드입니다. 제안서 생성도 여기를 지납니다.",
|
|
119
|
-
{"filename": "context_builder.py",
|
|
120
|
-
"relative_path": "latticeai/core/context_builder.py"},
|
|
121
|
-
WS_ALPHA, "2026-07-14T09:00:00"),
|
|
122
|
-
# The recency term's `0.0` branch: a stamp `datetime.fromisoformat` refuses.
|
|
123
|
-
("doc:undated", "Document", "Undated 제안서 memo",
|
|
124
|
-
"An undated memo about 제안서; its stamp does not parse.", {},
|
|
125
|
-
None, "not-a-timestamp"),
|
|
126
|
-
]
|
|
127
|
-
|
|
128
|
-
# (from, to, type, weight, created_at) — appended to the base edge set.
|
|
129
|
-
DOCGEN_EDGES: List[Tuple[str, str, str, float, str]] = [
|
|
130
|
-
("doc:proposal", "concept:proposal", "mentions", 0.92, "2026-07-30T00:00:00"),
|
|
131
|
-
("doc:proposal", "concept:evidence", "mentions", 0.91, "2026-07-30T00:01:00"),
|
|
132
|
-
("doc:proposal", "feature:doc-generation", "relates_to", 0.90, "2026-07-30T00:02:00"),
|
|
133
|
-
("doc:proposal", "dec:doc-format", "relates_to", 0.89, "2026-07-30T00:03:00"),
|
|
134
|
-
("doc:proposal", "task:proposal-review", "relates_to", 0.88, "2026-07-30T00:04:00"),
|
|
135
|
-
("doc:proposal", "concept:retrieval", "mentions", 0.87, "2026-07-30T00:05:00"),
|
|
136
|
-
("doc:proposal", "concept:ranking", "mentions", 0.86, "2026-07-30T00:06:00"),
|
|
137
|
-
("doc:proposal", "feature:command-palette", "mentions", 0.85, "2026-07-30T00:07:00"),
|
|
138
|
-
("doc:proposal", "task:parity-harness", "relates_to", 0.84, "2026-07-30T00:08:00"),
|
|
139
|
-
("doc:proposal", "page:proposal-outline", "contains", 0.83, "2026-07-30T00:09:00"),
|
|
140
|
-
("deck:proposal", "doc:proposal", "relates_to", 0.82, "2026-07-29T00:00:00"),
|
|
141
|
-
("deck:proposal", "slide:proposal-1", "contains", 0.81, "2026-07-29T00:01:00"),
|
|
142
|
-
("file:meeting-minutes", "dec:doc-format", "relates_to", 0.80, "2026-07-28T00:00:00"),
|
|
143
|
-
("file:meeting-minutes", "meeting:weekly", "relates_to", 0.79, "2026-07-28T00:01:00"),
|
|
144
|
-
("chat:proposal", "doc:proposal", "mentions", 0.78, "2026-07-27T00:00:00"),
|
|
145
|
-
("img:proposal-sketch", "imgtext:proposal-ocr", "relates_to", 0.77, "2026-07-26T00:00:00"),
|
|
146
|
-
("imgtext:proposal-ocr", "concept:proposal", "mentions", 0.76, "2026-07-26T00:01:00"),
|
|
147
|
-
("audio:proposal-call", "task:proposal-review", "mentions", 0.75, "2026-07-25T00:00:00"),
|
|
148
|
-
("code:doc-builder", "feature:doc-generation", "relates_to", 0.74, "2026-07-24T00:00:00"),
|
|
149
|
-
("sheet:proposal-budget", "doc:proposal", "relates_to", 0.73, "2026-07-23T00:00:00"),
|
|
150
|
-
("doc:release-notes", "concept:ranking", "mentions", 0.72, "2026-07-22T00:00:00"),
|
|
151
|
-
("doc:undated", "concept:proposal", "mentions", 0.71, "2026-07-21T00:00:00"),
|
|
152
|
-
# The Self-Model's own shape: every fact points at the root.
|
|
153
|
-
("self:decision:a1", "self:root", "PART_OF", 1.0, "2026-07-02T00:00:00"),
|
|
154
|
-
("self:habit:b2", "self:root", "PART_OF", 1.0, "2026-07-03T00:00:00"),
|
|
155
|
-
("self:preference:c3", "self:root", "PART_OF", 1.0, "2026-07-04T00:00:00"),
|
|
156
|
-
("self:relationship:d4", "self:root", "PART_OF", 1.0, "2026-07-05T00:00:00"),
|
|
157
|
-
("self:trait:e5", "self:root", "PART_OF", 1.0, "2026-07-06T00:00:00"),
|
|
158
|
-
("self:unknown:f6", "self:root", "PART_OF", 1.0, "2026-07-07T00:00:00"),
|
|
159
|
-
]
|
|
160
|
-
|
|
161
|
-
# ── suite specs ──────────────────────────────────────────────────────────────
|
|
162
|
-
DOCGEN_SEARCH_SPECS: List[Dict[str, Any]] = [
|
|
163
|
-
{"key": "ko_proposal", "query": "제안서 초안"},
|
|
164
|
-
{"key": "ko_meeting", "query": "회의 결정 사항"},
|
|
165
|
-
{"key": "en_ranking", "query": "hybrid retrieval ranking"},
|
|
166
|
-
{"key": "ko_sketch", "query": "스케치"},
|
|
167
|
-
{"key": "ko_self_model", "query": "문서는 한국어로"},
|
|
168
|
-
{"key": "en_undated", "query": "Undated"},
|
|
169
|
-
{"key": "hub_deck", "query": "제안 발표자료"},
|
|
170
|
-
{"key": "tie", "query": "Tie candidate"},
|
|
171
|
-
{"key": "no_hit", "query": "zzqq wumpus nonsense"},
|
|
172
|
-
{"key": "empty_query", "query": ""},
|
|
173
|
-
{"key": "blank_query", "query": " "},
|
|
174
|
-
{"key": "limit_one", "query": "제안서", "limit": 1},
|
|
175
|
-
{"key": "limit_zero", "query": "제안서", "limit": 0},
|
|
176
|
-
{"key": "limit_over", "query": "제안서", "limit": 900},
|
|
177
|
-
{"key": "scoped_alpha", "query": "제안서", "allowed": [WS_ALPHA]},
|
|
178
|
-
{"key": "scoped_alpha_legacy", "query": "제안서", "allowed": [WS_ALPHA], "legacy": True},
|
|
179
|
-
{"key": "scoped_beta", "query": "제안서", "allowed": [WS_BETA]},
|
|
180
|
-
{"key": "scoped_empty", "query": "제안서", "allowed": []},
|
|
181
|
-
]
|
|
182
|
-
|
|
183
|
-
MULTI_HOP_SPECS: List[Dict[str, Any]] = [
|
|
184
|
-
*[{"key": f"hub_h{hops}", "node_ids": ["doc:proposal"], "max_hops": hops}
|
|
185
|
-
for hops in (0, 1, 2, 3)],
|
|
186
|
-
{"key": "hub_hneg", "node_ids": ["doc:proposal"], "max_hops": -1},
|
|
187
|
-
{"key": "multi_seed", "node_ids": ["doc:proposal", "dec:fusion-alpha"], "max_hops": 2},
|
|
188
|
-
{"key": "leaf", "node_ids": ["slide:proposal-1"], "max_hops": 2},
|
|
189
|
-
{"key": "isolated", "node_ids": ["tie:c"], "max_hops": 2},
|
|
190
|
-
{"key": "self_root", "node_ids": ["self:root"], "max_hops": 2},
|
|
191
|
-
{"key": "missing_seed", "node_ids": ["nope:missing"], "max_hops": 2},
|
|
192
|
-
{"key": "no_seeds", "node_ids": [], "max_hops": 2},
|
|
193
|
-
{"key": "scoped_alpha", "node_ids": ["doc:proposal"], "max_hops": 2,
|
|
194
|
-
"allowed": [WS_ALPHA]},
|
|
195
|
-
{"key": "scoped_alpha_legacy", "node_ids": ["doc:proposal"], "max_hops": 2,
|
|
196
|
-
"allowed": [WS_ALPHA], "legacy": True},
|
|
197
|
-
{"key": "scoped_beta", "node_ids": ["deck:proposal"], "max_hops": 2,
|
|
198
|
-
"allowed": [WS_BETA]},
|
|
199
|
-
{"key": "scoped_empty", "node_ids": ["doc:proposal"], "max_hops": 2, "allowed": []},
|
|
200
|
-
]
|
|
201
|
-
|
|
202
|
-
CONTEXT_DOCUMENT_SPECS: List[Dict[str, Any]] = [
|
|
203
|
-
{"key": "default", "query": "제안서 초안"},
|
|
204
|
-
{"key": "no_self_model", "query": "제안서 초안", "include_self_model": False},
|
|
205
|
-
{"key": "self_model_tokens_small", "query": "제안서 초안", "self_model_tokens": 12},
|
|
206
|
-
{"key": "budget_240", "query": "제안서 초안", "budget": 240},
|
|
207
|
-
{"key": "budget_120", "query": "제안서 초안", "budget": 120},
|
|
208
|
-
{"key": "budget_40", "query": "제안서 초안", "budget": 40},
|
|
209
|
-
{"key": "budget_one", "query": "제안서 초안", "budget": 1},
|
|
210
|
-
{"key": "budget_zero", "query": "제안서 초안", "budget": 0},
|
|
211
|
-
{"key": "hops_zero", "query": "제안서 초안", "max_hops": 0},
|
|
212
|
-
{"key": "hops_three", "query": "제안서 초안", "max_hops": 3},
|
|
213
|
-
{"key": "results_two", "query": "제안서 초안", "max_results": 2},
|
|
214
|
-
{"key": "ko_meeting", "query": "회의 결정 사항"},
|
|
215
|
-
{"key": "en_ranking", "query": "hybrid retrieval ranking"},
|
|
216
|
-
{"key": "ko_sketch", "query": "스케치"},
|
|
217
|
-
{"key": "fallback_lexical", "query": "박민서 님"},
|
|
218
|
-
{"key": "fallback_empty", "query": "zzqq wumpus nonsense"},
|
|
219
|
-
{"key": "empty_query", "query": ""},
|
|
220
|
-
{"key": "scoped_alpha", "query": "제안서 초안", "allowed": [WS_ALPHA]},
|
|
221
|
-
{"key": "scoped_alpha_legacy", "query": "제안서 초안", "allowed": [WS_ALPHA],
|
|
222
|
-
"legacy": True},
|
|
223
|
-
{"key": "scoped_empty", "query": "제안서 초안", "allowed": []},
|
|
224
|
-
]
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def normalize_multi_hop(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
228
|
-
"""Order a ``multi_hop_context`` answer deterministically.
|
|
229
|
-
|
|
230
|
-
**This is a golden normalization, not a port divergence.** Python's
|
|
231
|
-
traversal iterates ``frontier``, a ``set`` — so the order in which the
|
|
232
|
-
nodes of one hop are appended (and therefore the order their incident
|
|
233
|
-
edges are appended) depends on string hashing, which CPython randomizes
|
|
234
|
-
per process unless ``PYTHONHASHSEED`` is pinned. The *contents* are fully
|
|
235
|
-
determined (which nodes are visited, which edges are collected, and every
|
|
236
|
-
node's hop label); only the sequence is not, so the live response ordering
|
|
237
|
-
is unspecified and there is nothing for a port to reproduce.
|
|
238
|
-
|
|
239
|
-
Both sides therefore sort before comparing: nodes by ``(hop, id)``, edges
|
|
240
|
-
by ``(from, to, type, weight)``. The Rust port emits that order natively —
|
|
241
|
-
it is deterministic where Python is not, which is a strictly stronger
|
|
242
|
-
promise and not a different answer.
|
|
243
|
-
"""
|
|
244
|
-
return {
|
|
245
|
-
"nodes": sorted(payload["nodes"], key=lambda node: (node["hop"], node["id"])),
|
|
246
|
-
"edges": sorted(
|
|
247
|
-
payload["edges"],
|
|
248
|
-
key=lambda edge: (edge["from"], edge["to"], edge["type"], edge["weight"]),
|
|
249
|
-
),
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
class OrderedMultiHopStore:
|
|
254
|
-
"""The store, with ``multi_hop_context`` ordered deterministically.
|
|
255
|
-
|
|
256
|
-
``retrieve_context_for_generation`` feeds the traversal's node list into
|
|
257
|
-
``extra_nodes``, and the concept section renders the first eight of it — so
|
|
258
|
-
Python's unordered ``frontier`` iteration reaches the *rendered markdown*,
|
|
259
|
-
not only the traversal payload. Both sides therefore see the normalized
|
|
260
|
-
order (see :func:`normalize_multi_hop`); every other attribute is forwarded
|
|
261
|
-
to the real store untouched.
|
|
262
|
-
"""
|
|
263
|
-
|
|
264
|
-
def __init__(self, store: Any):
|
|
265
|
-
self._store = store
|
|
266
|
-
|
|
267
|
-
def __getattr__(self, name: str) -> Any:
|
|
268
|
-
return getattr(self._store, name)
|
|
269
|
-
|
|
270
|
-
def multi_hop_context(self, *args: Any, **kwargs: Any) -> Dict[str, Any]:
|
|
271
|
-
return normalize_multi_hop(self._store.multi_hop_context(*args, **kwargs))
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
def _scope(spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
275
|
-
"""The graph-layer scope every document-generation read takes."""
|
|
276
|
-
allowed = spec.get("allowed")
|
|
277
|
-
return {
|
|
278
|
-
"allowed_workspaces": None if allowed is None else set(allowed),
|
|
279
|
-
"include_legacy_global": spec.get("legacy", False),
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
def run_docgen_search(harness: Any, spec: Dict[str, Any]) -> List[Dict[str, Any]]:
|
|
284
|
-
"""``KnowledgeGraphStore.search_for_document_generation`` for one spec."""
|
|
285
|
-
return harness.store.search_for_document_generation(
|
|
286
|
-
spec["query"], limit=spec.get("limit", 10), **_scope(spec)
|
|
287
|
-
)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def run_multi_hop(harness: Any, spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
291
|
-
"""``multi_hop_context`` for one spec, in the normalized order."""
|
|
292
|
-
return normalize_multi_hop(
|
|
293
|
-
harness.store.multi_hop_context(
|
|
294
|
-
spec["node_ids"], max_hops=spec.get("max_hops", 2), **_scope(spec)
|
|
295
|
-
)
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
def run_context_document(harness: Any, spec: Dict[str, Any]) -> Dict[str, Any]:
|
|
300
|
-
"""``retrieve_context_for_generation`` plus the footnote over its sources.
|
|
301
|
-
|
|
302
|
-
The footnote is a second public entry point over the same ``sources`` list;
|
|
303
|
-
carrying it here proves that port too, without a suite of its own.
|
|
304
|
-
"""
|
|
305
|
-
from lattice_brain.self_model import DEFAULT_SUMMARY_TOKENS
|
|
306
|
-
from latticeai.core.context_builder import (
|
|
307
|
-
DEFAULT_DOCUMENT_CONTEXT_BUDGET,
|
|
308
|
-
format_sources_footnote,
|
|
309
|
-
retrieve_context_for_generation,
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
context = retrieve_context_for_generation(
|
|
313
|
-
OrderedMultiHopStore(harness.store),
|
|
314
|
-
spec["query"],
|
|
315
|
-
max_results=spec.get("max_results", 10),
|
|
316
|
-
max_hops=spec.get("max_hops", 2),
|
|
317
|
-
budget=spec.get("budget", DEFAULT_DOCUMENT_CONTEXT_BUDGET),
|
|
318
|
-
include_self_model=spec.get("include_self_model", True),
|
|
319
|
-
self_model_tokens=spec.get("self_model_tokens", DEFAULT_SUMMARY_TOKENS),
|
|
320
|
-
**_scope(spec),
|
|
321
|
-
)
|
|
322
|
-
return {
|
|
323
|
-
"context": context,
|
|
324
|
-
"sources_footnote": format_sources_footnote(context["sources"]),
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
#: The three document-generation suites, as the generator merges them into
|
|
329
|
-
#: :data:`SUITES` / :data:`SUITE_RUNNERS`. Keeping the pair side by side is what
|
|
330
|
-
#: stops a spec list from arriving without the runner that answers it.
|
|
331
|
-
DOCGEN_SUITES: Dict[str, List[Dict[str, Any]]] = {
|
|
332
|
-
"docgen_search": DOCGEN_SEARCH_SPECS,
|
|
333
|
-
"multi_hop": MULTI_HOP_SPECS,
|
|
334
|
-
"context_document": CONTEXT_DOCUMENT_SPECS,
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
DOCGEN_RUNNERS: Dict[str, Any] = {
|
|
338
|
-
"docgen_search": run_docgen_search,
|
|
339
|
-
"multi_hop": run_multi_hop,
|
|
340
|
-
"context_document": run_context_document,
|
|
341
|
-
}
|