ltcai 11.1.0 → 11.4.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 +47 -54
- package/docs/CHANGELOG.md +94 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/FEATURE_AUDIT_v11.2.0.md +393 -0
- package/docs/LAYOUT_REBUILD_SPEC.md +9 -1
- package/docs/MULTI_AGENT_RUNTIME.md +1 -1
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +6 -2
- package/docs/PERMISSION_MODE.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/architecture.md +6 -2
- package/docs/kg-schema.md +2 -2
- package/docs/v11.3.0_PLAN.md +202 -0
- package/docs/v11.4.0_RUST_FOUNDATION_PLAN.md +176 -0
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/gates.py +125 -0
- package/lattice_brain/graph/_kg_common/__init__.py +287 -0
- package/lattice_brain/graph/_kg_common/extraction.py +516 -0
- package/lattice_brain/graph/_kg_common/relations.py +161 -0
- package/lattice_brain/graph/_kg_common/text.py +479 -0
- package/lattice_brain/graph/discovery_index/__init__.py +35 -0
- package/lattice_brain/graph/discovery_index/cleanup.py +182 -0
- package/lattice_brain/graph/discovery_index/extract.py +137 -0
- package/lattice_brain/graph/discovery_index/scan.py +411 -0
- package/lattice_brain/graph/discovery_index/upsert.py +495 -0
- package/lattice_brain/graph/fusion.py +35 -4
- package/lattice_brain/graph/projection/__init__.py +42 -0
- package/lattice_brain/graph/projection/curation.py +500 -0
- package/lattice_brain/graph/{projection.py → projection/v2_schema.py} +81 -485
- package/lattice_brain/graph/retrieval/__init__.py +54 -0
- package/lattice_brain/graph/retrieval/context.py +197 -0
- package/lattice_brain/graph/retrieval/graph_view.py +319 -0
- package/lattice_brain/graph/retrieval/hybrid.py +488 -0
- package/lattice_brain/graph/retrieval/maintenance.py +121 -0
- package/lattice_brain/graph/retrieval/signals.py +95 -0
- package/lattice_brain/graph/retrieval_vector/__init__.py +42 -0
- package/lattice_brain/graph/retrieval_vector/fingerprint.py +97 -0
- package/lattice_brain/graph/retrieval_vector/indexing.py +347 -0
- package/lattice_brain/graph/retrieval_vector/search.py +560 -0
- package/lattice_brain/graph/retrieval_vector/status.py +374 -0
- package/lattice_brain/graph/schema.py +9 -0
- package/lattice_brain/graph/store.py +9 -0
- package/lattice_brain/graph/vector_index/selector.py +32 -2
- package/lattice_brain/ingestion/__init__.py +130 -0
- package/lattice_brain/ingestion/_contract.py +90 -0
- package/lattice_brain/ingestion/constants.py +127 -0
- package/lattice_brain/ingestion/folder_scan.py +57 -0
- package/lattice_brain/ingestion/folders.py +258 -0
- package/lattice_brain/ingestion/hashing.py +26 -0
- package/lattice_brain/ingestion/jobs_api.py +107 -0
- package/lattice_brain/ingestion/models.py +80 -0
- package/lattice_brain/ingestion/pipeline.py +486 -0
- package/lattice_brain/ingestion/quality.py +209 -0
- package/lattice_brain/ingestion/routing.py +295 -0
- package/lattice_brain/multimodal/__init__.py +164 -0
- package/lattice_brain/multimodal/audio.py +77 -0
- package/lattice_brain/multimodal/common.py +118 -0
- package/lattice_brain/{multimodal.py → multimodal/images.py} +22 -262
- package/lattice_brain/multimodal/ports.py +169 -0
- package/lattice_brain/multimodal/video.py +410 -0
- package/lattice_brain/portability/__init__.py +90 -0
- package/lattice_brain/portability/_contract.py +42 -0
- package/lattice_brain/portability/backups.py +338 -0
- package/lattice_brain/portability/bundles.py +136 -0
- package/lattice_brain/portability/constants.py +93 -0
- package/lattice_brain/portability/fsops.py +138 -0
- package/lattice_brain/portability/service.py +41 -0
- package/lattice_brain/portability/sharing.py +714 -0
- package/lattice_brain/runtime/__init__.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/lattice_brain/sealed_box.py +244 -0
- package/lattice_brain/synthesis.py +24 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/brain_intelligence.py +4 -0
- package/latticeai/api/chat.py +11 -0
- package/latticeai/api/chat_helpers.py +16 -3
- package/latticeai/api/chat_hybrid.py +32 -1
- package/latticeai/api/chronicle.py +63 -0
- package/latticeai/api/features.py +70 -0
- package/latticeai/api/local_files.py +102 -0
- package/latticeai/api/portability.py +39 -4
- package/latticeai/api/review_queue.py +126 -0
- package/latticeai/api/search.py +16 -2
- package/latticeai/core/agent/__init__.py +93 -0
- package/latticeai/core/agent/_contract.py +79 -0
- package/latticeai/core/agent/context.py +57 -0
- package/latticeai/core/agent/deps.py +125 -0
- package/latticeai/core/agent/execution.py +622 -0
- package/latticeai/core/agent/planning.py +145 -0
- package/latticeai/core/agent/recovery.py +157 -0
- package/latticeai/core/agent/runtime.py +210 -0
- package/latticeai/core/agent/verification.py +231 -0
- package/latticeai/core/config.py +4 -1
- package/latticeai/core/context_builder.py +6 -3
- package/latticeai/core/embedding_providers/__init__.py +151 -0
- package/latticeai/core/embedding_providers/base.py +199 -0
- package/latticeai/core/embedding_providers/captions.py +162 -0
- package/latticeai/core/embedding_providers/profiles.py +126 -0
- package/latticeai/core/embedding_providers/text.py +350 -0
- package/latticeai/core/embedding_providers/vision.py +352 -0
- package/latticeai/core/file_generation/__init__.py +115 -0
- package/latticeai/core/file_generation/bundles.py +76 -0
- package/latticeai/core/file_generation/extraction.py +154 -0
- package/latticeai/core/file_generation/inference.py +235 -0
- package/latticeai/core/file_generation/orchestration.py +152 -0
- package/latticeai/core/file_generation/prompting.py +117 -0
- package/latticeai/core/file_generation/repair.py +114 -0
- package/latticeai/core/file_generation/sanitize.py +61 -0
- package/latticeai/core/file_generation/validation.py +201 -0
- package/latticeai/core/legacy_compatibility.py +1 -1
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/messages.py +152 -0
- package/latticeai/core/model_compat.py +73 -2
- package/latticeai/core/workspace_os_constants.py +1 -1
- package/latticeai/integrations/telegram_bot/__init__.py +123 -0
- package/latticeai/integrations/telegram_bot/__main__.py +17 -0
- package/latticeai/integrations/telegram_bot/config.py +86 -0
- package/latticeai/integrations/telegram_bot/dispatch.py +311 -0
- package/latticeai/integrations/telegram_bot/flows.py +478 -0
- package/latticeai/integrations/telegram_bot/helpers.py +322 -0
- package/latticeai/integrations/telegram_bot/screens.py +394 -0
- package/latticeai/models/model_providers.py +12 -4
- package/latticeai/models/router/__init__.py +88 -0
- package/latticeai/models/router/_contract.py +66 -0
- package/latticeai/models/router/branding.py +56 -0
- package/latticeai/models/router/catalog.py +69 -0
- package/latticeai/models/router/documents.py +199 -0
- package/latticeai/models/router/errors.py +37 -0
- package/latticeai/models/router/generation.py +258 -0
- package/latticeai/models/router/loading.py +291 -0
- package/latticeai/models/router/local_models.py +85 -0
- package/latticeai/models/router/registry.py +147 -0
- package/latticeai/runtime/build_phases/__init__.py +82 -0
- package/latticeai/runtime/build_phases/features.py +407 -0
- package/latticeai/runtime/build_phases/foundation.py +555 -0
- package/latticeai/runtime/build_phases/web.py +492 -0
- package/latticeai/runtime/chat_wiring.py +4 -0
- package/latticeai/runtime/feature_toggle_wiring.py +163 -0
- package/latticeai/runtime/router_registration.py +11 -0
- package/latticeai/runtime/runtime_context.py +1 -0
- package/latticeai/services/app_context.py +8 -0
- package/latticeai/services/architecture_readiness.py +48 -19
- package/latticeai/services/automation_intelligence.py +22 -2
- package/latticeai/services/brain_intelligence/__init__.py +58 -0
- package/latticeai/services/brain_intelligence/_contract.py +71 -0
- package/latticeai/services/brain_intelligence/consistency.py +193 -0
- package/latticeai/services/brain_intelligence/constants.py +47 -0
- package/latticeai/services/brain_intelligence/digest.py +258 -0
- package/latticeai/services/brain_intelligence/health.py +331 -0
- package/latticeai/services/brain_intelligence/proposals.py +264 -0
- package/latticeai/services/brain_intelligence/sampling.py +84 -0
- package/latticeai/services/brain_intelligence/service.py +48 -0
- package/latticeai/services/chronicle.py +557 -0
- package/latticeai/services/command_center.py +10 -4
- package/latticeai/services/feature_toggles.py +502 -0
- package/latticeai/services/folder_watch.py +122 -1
- package/latticeai/services/hybrid_chat.py +56 -5
- package/latticeai/services/interop_bridges.py +978 -0
- package/latticeai/services/memory_service/__init__.py +52 -0
- package/latticeai/services/memory_service/_contract.py +100 -0
- package/latticeai/services/memory_service/brief.py +431 -0
- package/latticeai/services/memory_service/constants.py +57 -0
- package/latticeai/services/memory_service/maintenance.py +138 -0
- package/latticeai/services/memory_service/manager.py +186 -0
- package/latticeai/services/memory_service/proof.py +136 -0
- package/latticeai/services/memory_service/recall.py +225 -0
- package/latticeai/services/memory_service/service.py +48 -0
- package/latticeai/services/memory_service/stores.py +110 -0
- package/latticeai/services/model_capability_registry.py +434 -261
- package/latticeai/services/model_catalog.py +95 -61
- package/latticeai/services/model_recommendation.py +18 -11
- package/latticeai/services/model_runtime/__init__.py +322 -0
- package/latticeai/services/model_runtime/cloud.py +87 -0
- package/latticeai/services/model_runtime/download.py +282 -0
- package/latticeai/services/model_runtime/engines.py +341 -0
- package/latticeai/services/model_runtime/loading.py +178 -0
- package/latticeai/services/model_runtime/service.py +129 -0
- package/latticeai/services/model_runtime/state.py +131 -0
- package/latticeai/services/model_runtime/status.py +255 -0
- package/latticeai/services/multimodal_ports.py +26 -1
- package/latticeai/services/obsidian_bridge.py +16 -25
- package/latticeai/services/product_readiness.py +15 -7
- package/latticeai/services/search_service.py +149 -2
- package/latticeai/services/tool_dispatch.py +4 -0
- package/latticeai/setup/auto_setup.py +27 -30
- package/latticeai/setup/wizard/__init__.py +126 -0
- package/latticeai/setup/wizard/catalog.py +172 -0
- package/latticeai/setup/wizard/detect.py +323 -0
- package/latticeai/setup/wizard/install.py +348 -0
- package/latticeai/setup/wizard/paths.py +168 -0
- package/latticeai/setup/wizard/plans.py +74 -0
- package/latticeai/setup/wizard/recommend.py +320 -0
- package/package.json +6 -2
- package/scripts/bump_version.py +14 -0
- package/scripts/capture_release_evidence.mjs +33 -21
- package/scripts/check_current_release_docs.mjs +1 -1
- package/scripts/check_i18n_namespace_coverage.mjs +41 -4
- package/scripts/check_max_file_lines.mjs +102 -0
- package/scripts/check_release_evidence_bound.mjs +30 -15
- package/scripts/check_screenshot_pixel_delta.py +34 -4
- package/scripts/check_server_i18n.mjs +2 -0
- package/scripts/generate_rust_parity_fixtures.py +562 -0
- package/scripts/lib/mock_server_fingerprint.mjs +94 -0
- package/scripts/release_screen_claims.json +44 -2
- package/scripts/verify_hf_model_registry.py +253 -218
- package/src-tauri/Cargo.lock +361 -3
- package/src-tauri/Cargo.toml +6 -1
- package/src-tauri/src/backend.rs +349 -0
- package/src-tauri/src/folder.rs +33 -0
- package/src-tauri/src/main.rs +97 -399
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +41 -37
- package/static/app/assets/Act-yYpYnn0v.js +1 -0
- package/static/app/assets/AdminConsole-DL3Cr5pL.js +1 -0
- package/static/app/assets/{Brain-CzCsI1mi.js → Brain-C1HBN0Wf.js} +2 -2
- package/static/app/assets/BrainHome-DoXRhUUC.js +2 -0
- package/static/app/assets/BrainSignals-6yR6ir5t.js +1 -0
- package/static/app/assets/Capture-CFIRsFNE.js +1 -0
- package/static/app/assets/Chronicle-BZbEgiwN.js +1 -0
- package/static/app/assets/CommandPalette-D2pMxC2I.js +1 -0
- package/static/app/assets/Library-DwO3yZST.js +1 -0
- package/static/app/assets/{LivingBrain-BXMWIK_2.js → LivingBrain-Jn1GK0-S.js} +1 -1
- package/static/app/assets/ProductFlow-B-w1R4Oo.js +1 -0
- package/static/app/assets/ReviewCard-6B27X8Vg.js +3 -0
- package/static/app/assets/System-DW8F-2xL.js +1 -0
- package/static/app/assets/arrow-left-DXvKg9U6.js +1 -0
- package/static/app/assets/{bot-4BvN07ux.js → bot-IM_E_Y12.js} +1 -1
- package/static/app/assets/brain-Ci1CkWjM.js +1 -0
- package/static/app/assets/{button-CDjtnAoU.js → button-COwyqfHM.js} +1 -1
- package/static/app/assets/circle-check-DfInj-qD.js +1 -0
- package/static/app/assets/{circle-pause-D_RMn7tp.js → circle-pause-DEM4A1Y5.js} +1 -1
- package/static/app/assets/{circle-play-B5OpB8ae.js → circle-play-C9djDuLd.js} +1 -1
- package/static/app/assets/{cpu-BIlWInHf.js → cpu-DFdo1gw-.js} +1 -1
- package/static/app/assets/{download-BtjXfL3z.js → download-SnJL6oqk.js} +1 -1
- package/static/app/assets/{folder-open-DefMpxI2.js → folder-open-CqZeDkjE.js} +1 -1
- package/static/app/assets/{hard-drive-BQ8NZVkw.js → hard-drive-j1jJXYYf.js} +1 -1
- package/static/app/assets/{index-vtEfYvQY.css → index-BLPb5lmE.css} +1 -1
- package/static/app/assets/index-_u5iUHDr.js +10 -0
- package/static/app/assets/input-B0lPdRQZ.js +1 -0
- package/static/app/assets/link-2-CoFbooHS.js +1 -0
- package/static/app/assets/{permissionCopy-BqZ5tsgL.js → permissionCopy-BsyLxtao.js} +1 -1
- package/static/app/assets/primitives-DEbN-d6p.js +1 -0
- package/static/app/assets/search-BybIWPNd.js +1 -0
- package/static/app/assets/{share-2-D5zg_0fY.js → share-2-CVtZ_ewX.js} +1 -1
- package/static/app/assets/{shield-alert-B5pZzkUb.js → shield-alert-CBi2GNWM.js} +1 -1
- package/static/app/assets/{textarea-nEVIweKY.js → textarea-DNMpB5ih.js} +1 -1
- package/static/app/assets/{useFocusTrap-Cm99AHlz.js → useFocusTrap-C83t3GXF.js} +1 -1
- package/static/app/assets/useMutation-DtbJDoyz.js +1 -0
- package/static/app/assets/{useQuery-Dm__N6bL.js → useQuery-Dcp1OChy.js} +1 -1
- package/static/app/assets/utils-BlZr7Pd4.js +4 -0
- package/static/app/assets/workspace-jJY4RuAV.js +1 -0
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/lattice_brain/graph/_kg_common.py +0 -1331
- package/lattice_brain/graph/discovery_index.py +0 -1141
- package/lattice_brain/graph/retrieval.py +0 -1120
- package/lattice_brain/graph/retrieval_vector.py +0 -1293
- package/lattice_brain/ingestion.py +0 -1377
- package/lattice_brain/portability.py +0 -1210
- package/latticeai/core/agent.py +0 -1412
- package/latticeai/core/embedding_providers.py +0 -1196
- package/latticeai/core/file_generation.py +0 -1047
- package/latticeai/integrations/telegram_bot.py +0 -1390
- package/latticeai/models/router.py +0 -1007
- package/latticeai/runtime/build_phases.py +0 -1422
- package/latticeai/services/brain_intelligence.py +0 -967
- package/latticeai/services/memory_service.py +0 -1177
- package/latticeai/services/model_runtime.py +0 -1281
- package/latticeai/setup/wizard.py +0 -1277
- package/static/app/assets/Act-D0HWqtn0.js +0 -1
- package/static/app/assets/AdminConsole-D-QDW-A4.js +0 -1
- package/static/app/assets/BrainHome-Btns-_TA.js +0 -2
- package/static/app/assets/BrainSignals-2dHQNkns.js +0 -1
- package/static/app/assets/Capture-CT8v1StE.js +0 -1
- package/static/app/assets/CommandPalette-DoLXC2KH.js +0 -1
- package/static/app/assets/Library-DDoxFE5c.js +0 -1
- package/static/app/assets/ProductFlow-DOYf7JIs.js +0 -1
- package/static/app/assets/ReviewCard-COQsqidK.js +0 -3
- package/static/app/assets/System-BRllvYXd.js +0 -1
- package/static/app/assets/arrow-left-DnyMzss-.js +0 -1
- package/static/app/assets/brain-uMb_5hnO.js +0 -1
- package/static/app/assets/index-0AvoEBzJ.js +0 -10
- package/static/app/assets/input-B_5ZJ9oy.js +0 -1
- package/static/app/assets/primitives-CVwew78r.js +0 -1
- package/static/app/assets/search-DkhnOKZt.js +0 -1
- package/static/app/assets/utils-DcDMoZIe.js +0 -4
- package/static/app/assets/workspace-LtRRSKTf.js +0 -1
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
# Feature Audit — v11.2.0
|
|
2
|
+
|
|
3
|
+
> **Status: reference** — a point-in-time, evidence-based sweep of every row in
|
|
4
|
+
> [`FEATURE_STATUS.md`](../FEATURE_STATUS.md). It records what was true when it
|
|
5
|
+
> was run, not what the current release claims; the canonical feature state
|
|
6
|
+
> stays in `FEATURE_STATUS.md`.
|
|
7
|
+
|
|
8
|
+
Audited against the `release/v11.2.0` working tree on 2026-08-10, starting from
|
|
9
|
+
the 11.1.0 feature table. Continues the evidence-based audit tradition started
|
|
10
|
+
in 3.3.0: **every row gets a verdict and a way to reproduce it**, and a row
|
|
11
|
+
whose sentence outruns its code is lowered rather than defended.
|
|
12
|
+
|
|
13
|
+
## Method
|
|
14
|
+
|
|
15
|
+
Claims were checked by running the product, not by reading about it.
|
|
16
|
+
|
|
17
|
+
* **Hermetic full-app boot.** `latticeai.app_factory.build_runtime()` inside
|
|
18
|
+
`scripts/export_openapi.py`'s `isolated_runtime_environment`, which points
|
|
19
|
+
`HOME`, `LATTICEAI_DATA_DIR`, `LATTICEAI_BRAIN_DIR`, the agent workspace, the
|
|
20
|
+
vault dir and the static dir at a throwaway temp tree. No real HOME, no real
|
|
21
|
+
network, no live server. Endpoints were exercised through `TestClient`.
|
|
22
|
+
* **Three passes.** (1) anonymous read surface, (2) corrected paths with
|
|
23
|
+
redirect-following off plus API introspection, (3) a registered-and-signed-in
|
|
24
|
+
session driving the local-file approval dance end to end.
|
|
25
|
+
* **Route inventory** from the app's own route table and its generated OpenAPI
|
|
26
|
+
schema, cross-checked against the checked-in `frontend/openapi.json` that
|
|
27
|
+
`scripts/check_openapi_drift.mjs` already proves is regenerated from the live
|
|
28
|
+
app.
|
|
29
|
+
* **Code-level verification** for claims an endpoint cannot show (constants,
|
|
30
|
+
defaults, guard order, which collaborator writes which key).
|
|
31
|
+
|
|
32
|
+
Where a claim is pinned by an existing regression test, that test is the
|
|
33
|
+
evidence: it is cheaper to keep true than a paragraph.
|
|
34
|
+
|
|
35
|
+
## Cross-cutting smoke
|
|
36
|
+
|
|
37
|
+
Measured on the hermetic boot described above.
|
|
38
|
+
|
|
39
|
+
| Measure | Value |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| Routers registered (`include_router` calls, all distinct) | 35 |
|
|
42
|
+
| Total routes on the app | 451 |
|
|
43
|
+
| Of those, API routes | 446 |
|
|
44
|
+
| Non-API routes | 4 (`/openapi.json`, `/docs`, `/docs/oauth2-redirect`, `/redoc`) |
|
|
45
|
+
| Static mounts | `/static` always; `/icons` only when `static/icons/` exists (it does in the repo; it did not in the sandboxed static dir) |
|
|
46
|
+
| OpenAPI paths | 404 |
|
|
47
|
+
| OpenAPI operations | 445 |
|
|
48
|
+
| `frontend/openapi.json` drift | clean (`node scripts/check_openapi_drift.mjs`) |
|
|
49
|
+
| Health snapshot | `status: ok`, `version 11.1.0`, `mode local`, `graph_enabled true`, `telegram_enabled false`, `autoload_models false` |
|
|
50
|
+
| Probes run | 70 (pass 1) + 42 (pass 2) + the signed-in pass; **zero 5xx, zero unhandled exceptions** |
|
|
51
|
+
|
|
52
|
+
Every non-200 in the sweep was a *designed* refusal, and each named its
|
|
53
|
+
reason: `403` on the share routes while `LATTICEAI_BRAIN_NETWORK` is off,
|
|
54
|
+
`401` on local-file routes without a session, `405` on a POST-only path,
|
|
55
|
+
`422` on a malformed body.
|
|
56
|
+
|
|
57
|
+
### Frontend ↔ real routes
|
|
58
|
+
|
|
59
|
+
320 server-path literals were extracted from `frontend/src`. **Every one
|
|
60
|
+
resolves to a real route.** Ten looked missing on a first pass and all ten are
|
|
61
|
+
template routes the client builds with an interpolated id (`/models/switch` →
|
|
62
|
+
`/models/switch/{model_id:path}`, `/mcp/connectors` → `/mcp/connectors/{mcp_id}`,
|
|
63
|
+
and so on); the eleventh, `/workspace-admin`, is a client-side hash route, not a
|
|
64
|
+
server path.
|
|
65
|
+
|
|
66
|
+
### mock_server ↔ real routes
|
|
67
|
+
|
|
68
|
+
`tests/visual/mock_server.cjs` serves the twelve release-capture screens.
|
|
69
|
+
|
|
70
|
+
| Measure | Value |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| Exact path literals in the mock | 132 |
|
|
73
|
+
| Matching a real route (exact or template) | 131 |
|
|
74
|
+
| Mock-only | **1** — `/v3`, a legacy alias for `/app` that the server no longer serves |
|
|
75
|
+
| Prefix handlers in the mock | 17, all resolving to real routes or mounts |
|
|
76
|
+
| Real routes the frontend can call that the mock does not serve | 183 |
|
|
77
|
+
|
|
78
|
+
The 183 are capture-fidelity headroom, not product defects: the mock answers
|
|
79
|
+
what the twelve screens need and falls through for the rest. The gap is bounded
|
|
80
|
+
by a real gate — `tests/visual/v3.spec.js` asserts
|
|
81
|
+
`service-unavailable-banner` count is zero across all ten plain-mode routes, so
|
|
82
|
+
a mock gap that reaches a core panel fails the visual suite rather than shipping
|
|
83
|
+
a screenshot of a working feature rendered as broken.
|
|
84
|
+
|
|
85
|
+
## Verdict table
|
|
86
|
+
|
|
87
|
+
`WORKS` — the claim was exercised and held. `PARTIAL` — the mechanism exists
|
|
88
|
+
and is tested, but a surface the sentence implies does not reach it.
|
|
89
|
+
`MISMATCH` — the doc said something the code does not do.
|
|
90
|
+
|
|
91
|
+
| # | Row | Verdict | Evidence |
|
|
92
|
+
| --- | --- | --- | --- |
|
|
93
|
+
| 1 | Brain Home | **MISMATCH → doc fixed** | Living Brain + composer in-viewport asserted at 1280×800 and 390×780 (`tests/visual/v3.spec.js`); the Brain Brief renders only inside `BrainHomeDock`'s `stats` tab, and `BrainHome.test.tsx` asserts the dock opens closed |
|
|
94
|
+
| 2 | Automation Intelligence | WORKS | `GET /api/automation/{overview,patterns,suggestions}` → 200 with `consent.default_state: "draft_disabled"`, `requires_user_enable: true`, `review_before_run: true` |
|
|
95
|
+
| 3 | Brain Intelligence | **PARTIAL → code fixed** | `GET /api/brain/health` → 200 with all four dimensions; on an empty Brain three read `unavailable` yet the composite reported `overall_score: 100, grade: "excellent"` (see Finding 3) |
|
|
96
|
+
| 4 | Temporal Knowledge | WORKS | `KnowledgeGraphStore.as_of(timestamp, …)` and `neighbors(…, as_of=None)` present with the documented defaults; `tests/unit/test_t2_temporal_schema.py`, `test_t2_temporal_reads.py`, `test_kg_temporal.py` |
|
|
97
|
+
| 5 | Proactive Synthesis | WORKS | `POST /api/brain/synthesize` → 200 with the four proposal kinds; `SYNTHESIS_THRESHOLD_ENV` / `DEFAULT_SYNTHESIS_THRESHOLD = 25`; `tests/unit/test_t2_synthesis_job.py` |
|
|
98
|
+
| 6 | Memory Decay | WORKS | `GET /api/brain/importance` → 200 (`half_life_days: 30.0`, `access_source: "metadata"`); `/api/brain/quality-report` carries `importance` + `tidying`; `tests/unit/test_t2_importance_decay.py` |
|
|
99
|
+
| 7 | Hybrid Recall | WORKS | `POST /api/memory/recall` → 200 with `quality_gate.gate == "hybrid-evidence/v2"`; `GET /api/search/hybrid` reports per-channel weights and recall detail |
|
|
100
|
+
| 8 | Folder Ingestion | WORKS | `GET /api/ingestion/jobs` → 200; `/api/ingestion/folder`, `/jobs/{id}`, `/jobs/{id}/resume` present |
|
|
101
|
+
| 9 | Extraction Quality | WORKS | `assess_extraction_quality` + observe-mode `_observe_quality_gate` (every failure path returns `None` and the ingest proceeds); `tests/unit/test_ingestion_quality_jobs.py` |
|
|
102
|
+
| 10 | Vector Freshness | **PARTIAL → code fixed** | `GET /api/brain/vector-freshness` returned only `{status, pending_items, total_items, detail}` while `vector_freshness_breakdown()` had **no product caller** (see Finding 4) |
|
|
103
|
+
| 11 | Vector Index Backends | WORKS | `resolve_vector_index({})` → `brute`/exact; an unknown name falls back **and says why** in `detail`; choices are exactly `brute`/`quantized`/`hnsw` |
|
|
104
|
+
| 12 | Background Embedding | WORKS | `IngestionPipeline.drain_vector_queue` present; the Known Limitation that nothing schedules it is accurate |
|
|
105
|
+
| 13 | Fusion Strategy | WORKS (off) | `LATTICEAI_FUSION_STRATEGY` unset in a clean boot; alpha fusion is what `/api/search/hybrid` reports |
|
|
106
|
+
| 14 | Graph Candidate Expansion | WORKS (off) | `graph_expansion_enabled()` false with no env; `GRAPH_EXPANSION_ENV` as documented |
|
|
107
|
+
| 15 | Self-Model (Personal Ontology) | WORKS | `POST /api/memory/self-model/propose` with `저는 …를 선호합니다` returned 1 candidate and **one pending review item**, nothing written; `apply` calls `review_queue.approve()` before `_write_fact`; summary capped at half the context budget |
|
|
108
|
+
| 16 | Workspace Reorganization | WORKS | one `folder_reorganization` proposal, targets always `topics/<주제>/`, `unplaced` reasons, **no delete path exists in the module**, skip-and-report on apply |
|
|
109
|
+
| 17 | Change Governance | WORKS | `MUTATING_TOOL_INVENTORY` + `assert_governance_coverage`; base-SHA conflict → 409; `_atomic_write` via `os.replace` under a lock; verifier fails closed to `NEEDS_REVIEW` |
|
|
110
|
+
| 18 | Brain Brief | WORKS | `/api/memory/brain-brief` and `/api/brain/proactive-brief` → 200; the proactive brief counts existing proposals and raises none |
|
|
111
|
+
| 19 | Conversation | WORKS | `tests/unit/test_chat_no_model.py`; the loaded-model list is empty in a clean boot and chat refuses rather than inventing output |
|
|
112
|
+
| 20 | Knowledge Graph | WORKS | `/api/graph`, `/knowledge-graph/stats`, `/api/knowledge-graph/provenance` → 200; v2 schema reported alongside v1 |
|
|
113
|
+
| 21 | Source Capture | WORKS | unified pipeline reachable from files/folders/notes/web; provenance keyed by origin (no wall-clock component) |
|
|
114
|
+
| 22 | Local Models | WORKS | `GET /models`, `/models/recommendations` → 200 with a real device profile; `allow_model_downloads: false` in a clean boot |
|
|
115
|
+
| 23 | Installer Audit | WORKS | `auto_setup` refuses to apply on a confirmation-token mismatch (`CommandConfirmationError`); `tests/unit/test_setup_wizard.py`, `test_cov_wp04_wizard_install.py` |
|
|
116
|
+
| 24 | Cloud Models | WORKS | `_load_cloud_model` raises `Missing API key env var: …` **before** the client is constructed; egress is audited before any call |
|
|
117
|
+
| 25 | Telegram | WORKS | `run_bot` returns without polling on any of: no token, empty allowlist, no server session; ACL check precedes `register_chat_id` on both message and callback paths |
|
|
118
|
+
| 26 | Agent Runtime | WORKS | `/agents/api/runtime/health` → `status: "unavailable"` with the honest reason ("No LLM-backed model is loaded; product execution API refuses simulation runs"); preview records no run; unknown roles rejected |
|
|
119
|
+
| 27 | Tool Registry / MCP | WORKS | `/tools/registry/diagnostics` → `registered_tools 47 / governed_tools 47`, empty `governance_without_handler` and `handler_without_governance`; `/mcp/installed`, `/mcp/tools` → 200 |
|
|
120
|
+
| 28 | Workspaces | WORKS | `/workspace/os` → 200 with the personal workspace default; admin surfaces on separate routes |
|
|
121
|
+
| 29 | VS Code Extension | WORKS | `/workspace/vscode/status` → 200 (`connected:false, status:"offline"`); `POST /agent` `stream:true` dispatches `agent_step`; 4xx never reads as success |
|
|
122
|
+
| 30 | Browser Extension | WORKS | every outbound call is `http://127.0.0.1:${port}`; an absent verdict renders `근거 확인 불가`; no approve/reject call exists in the extension |
|
|
123
|
+
| 31 | Telegram Review | WORKS | `/review` reads the same `/api/proposals`; 409 → "아무것도 쓰지 않았습니다", no retry |
|
|
124
|
+
| 32 | Knowledge Garden | WORKS | `GET /api/brain/garden` → 200 with exactly four beds; an unavailable graph yields empty beds |
|
|
125
|
+
| 33 | Agent File Tasks | WORKS | `executor_prompt_for(base, *, profile, self_model_summary)`; `EXECUTOR_PROMPT` itself carries no file-task hints; summary injected only when passed |
|
|
126
|
+
| 34 | Agent Profiles | WORKS | `COMPACT_MAX_PARAMS_B = 4.0`; an id naming no size keeps `standard`; a failed direct-path write is reported as not written |
|
|
127
|
+
| 35 | Folder Memory State | WORKS | `GET /knowledge-graph/local/health` → 200; vector freshness reported once and labelled `vector_freshness_global` |
|
|
128
|
+
| 36 | Voice Capture | WORKS | `GET /api/capture/voice/status` → `capture:true, transcription:false` with a plain-language reason; the transcriber really is one shared port (`ctx.MULTIMODAL_PORTS.transcriber` feeds both the pipeline and `VoiceCaptureService`) |
|
|
129
|
+
| 37 | Multi-modal Memories | WORKS | `ALLOW_MULTIMODAL_ENV` default `"0"`; both modes asserted in `tests/unit/test_t3_ingest_routing.py`; `NodeType.AUDIO` and `IMAGE` are first-class |
|
|
130
|
+
| 38 | Vision OCR / Caption / Embedding | WORKS | `VisionStub` is gone from product code and from the shipped wheel/sdist, with a test asserting its absence; `resolve_vision_embedder` has no hash fallback |
|
|
131
|
+
| 39 | Image Retrieval | **PARTIAL → code fixed** | late fusion, the separate `image_embeddings` table, width-mismatch skipping and the `multimodal` result block are all real and tested — but no production caller passed `multimodal=` to `context_quality_signal` (see Finding 5) |
|
|
132
|
+
| 40 | Evidence Thumbnails | WORKS | `THUMBNAIL_EDGE = 96`; the 24,000-char cap is enforced on write **and** on read; only `data:image/…` is accepted, server-side and client-side |
|
|
133
|
+
| 41 | Video Ingestion | WORKS | ingest returns `status:"unavailable"`, `indexing_status:"skipped"`, `node_id: None`; nothing is stored |
|
|
134
|
+
| 42 | Frontend Reliability | WORKS | `CoreServiceUnavailableBanner`; `ActionButton` does not fire success callbacks for `ok:false`; vitest 100% on all four metrics |
|
|
135
|
+
| 43 | Trusted Agent Loop | WORKS | `LoopTrace`, the `loop` payload on both the streaming and non-streaming terminals, python-literal repair, the agent-eval CI gate |
|
|
136
|
+
| 44 | Command Center | **MISMATCH → code fixed** | `/api/command/briefing` returned `health: {available:false, grade:null, score:null}` on a Brain reporting `grade: "excellent"` (see Finding 1) |
|
|
137
|
+
| 45 | Evidence → Action | WORKS | `POST /api/evidence/actions` with no resolvable citations → 200 with an explicit reason, never a silent empty list |
|
|
138
|
+
| 46 | Run Explanation | WORKS | `"ok": code == "done"`, reachable only from `state == "DONE"`; rendered on web, VS Code and Telegram |
|
|
139
|
+
| 47 | Project Sessions | WORKS | `GET /api/projects` → 200; `/agent` accepts `project_id`; a `NEEDS_REVIEW` run never becomes a project `done` |
|
|
140
|
+
| 48 | Citation Precision | WORKS | `tests/unit/test_typed_chunking.py`, `tests/unit/test_citation_grounding.py`; `plain` chunking stays byte-identical to the legacy walk |
|
|
141
|
+
| 49 | Graph Relation Evidence | WORKS | `tests/unit/test_relation_evidence.py` |
|
|
142
|
+
| 50 | Funnel Alerts | WORKS | `GET /api/admin/funnel-metrics` → 200 with named counters, `rates: null` and `alerts: []` below the 10-sample floor |
|
|
143
|
+
| 51 | Frontend Payload | **MISMATCH → doc fixed** | `npm run check:bundle` measures **103.0 KiB** gzip initial JS against the 150 KiB budget; the doc had read "~99 KiB" since 9.9.9 (see Finding 2) |
|
|
144
|
+
| 52 | Permission Modes | WORKS | `GET /api/permission-mode` → `strict` default with `proposal_first: true`; circuit breakers mode-invariant; the selector renders the server catalog and blocks `bypass` until acknowledged. One wording nuance: the home dial uses a confirmation dialog rather than a checkbox — consent is still explicit |
|
|
145
|
+
| 53 | Network Boundary | WORKS | `local_only` default; `hard_block_metadata_flags` = `do_not_share/local_only/private/sensitive` applied with no mode branch; `POST /api/network-boundary/preview` answers in `local_only` and reports `would_block` |
|
|
146
|
+
| 54 | Hybrid Cloud Chat | WORKS | all seven named modules exist; the adapter raises before opening a socket without `LATTICEAI_CLOUD_API_KEY`; the local path is a pure early return |
|
|
147
|
+
| 55 | Cloud Memory Write-Back | **MISMATCH → code fixed** | the enqueue was implemented and unit-tested, but both live call sites constructed `CloudResponseIngestor(store=knowledge_graph)` with no review sink (see Finding 6) |
|
|
148
|
+
| 56 | Obsidian Vault Bridge | WORKS | driven end to end in the signed-in pass: `permission_required` + token → `/permissions/approve/{token}` → `status: "dry_run"`, `scanned 2 / notes 2 / tags 1 / links.resolved 1` (see Finding 7 for the anonymous case) |
|
|
149
|
+
| 57 | Selective Brain Network | WORKS (flag off) | `GET /api/knowledge-graph/share` → `enabled:false` with the flag named; all four mutating share routes → 403 with the reason. **The encryption half of this row was being changed by a parallel track while this audit ran — see Caveat** |
|
|
150
|
+
| 58 | Release Assets | WORKS | package/pyproject/tauri/vsix all 11.1.0; `check_current_release_docs`, `check_doc_status`, `validate_release_artifacts`, `check_release_evidence_bound` all clean. Rolling the markers to 11.2.0 is the release lead's step, not this audit's |
|
|
151
|
+
|
|
152
|
+
**Totals as swept: 51 WORKS, 3 PARTIAL, 4 MISMATCH.** Of the four mismatches,
|
|
153
|
+
one was fixed in code during the sweep (Command Center), two were fixed in the
|
|
154
|
+
docs (Brain Home, Frontend Payload) and one was reported to its owning track
|
|
155
|
+
(Cloud Memory Write-Back). All three `PARTIAL` rows were reported rather than
|
|
156
|
+
changed: each needed a code change in a file another track owned this sprint,
|
|
157
|
+
or a behaviour decision that does not belong inside an audit. One Known
|
|
158
|
+
Limitation was retired as no longer true.
|
|
159
|
+
|
|
160
|
+
**Dispositions after the sweep (v11.2.0 integration close).** The four rows the
|
|
161
|
+
audit could not touch itself were closed once the parallel tracks had landed —
|
|
162
|
+
Findings 3, 4, 5 and 6 are all fixed in code, each with a regression test that
|
|
163
|
+
drives the shipped entry point rather than the collaborator (see
|
|
164
|
+
`tests/unit/test_t8_integration_close.py`). The verdict column above keeps the
|
|
165
|
+
*swept* verdict with its disposition appended, because a point-in-time audit
|
|
166
|
+
that silently rewrites itself is worth nothing; `FEATURE_STATUS.md` carries the
|
|
167
|
+
current state.
|
|
168
|
+
|
|
169
|
+
## Findings
|
|
170
|
+
|
|
171
|
+
### Finding 1 — the Command Center's health section was reading a key nothing writes (FIXED)
|
|
172
|
+
|
|
173
|
+
`CommandCenterService._health_section` read the Brain's health out of a nested
|
|
174
|
+
`overall` block:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
overall = report.get("overall") or {}
|
|
178
|
+
"available": overall.get("score") is not None,
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`BrainIntelligenceService.health_report()` — the only producer — publishes
|
|
182
|
+
`overall_score` and `grade` at the **top level**. So the briefing's health
|
|
183
|
+
section was permanently `{available: false, grade: null, score: null}` while
|
|
184
|
+
`/api/brain/health` reported `grade: "excellent"` on the very same graph, and
|
|
185
|
+
the `check-health` quick action below it could never fire.
|
|
186
|
+
|
|
187
|
+
User-visible: `DailyBriefingPanel` renders
|
|
188
|
+
`{health.available && health.grade ? String(health.grade) : "—"}`, so Today's
|
|
189
|
+
Briefing showed a permanent dash with no reason beside it — the exact failure
|
|
190
|
+
mode the 9.9.7 rule ("a `—` must state why") exists to prevent.
|
|
191
|
+
|
|
192
|
+
Why the suite stayed green: `tests/unit/test_command_center.py`'s `FakeBrain`
|
|
193
|
+
returned `{"overall": {"score": …, "grade": …}}` — a shape no real collaborator
|
|
194
|
+
has ever produced. The test and the code agreed with each other and neither
|
|
195
|
+
agreed with production.
|
|
196
|
+
|
|
197
|
+
Fixed in `latticeai/services/command_center.py` (read the real shape), the fake
|
|
198
|
+
corrected to match its real counterpart, and pinned by
|
|
199
|
+
`tests/unit/test_a3_feature_audit.py`, which wires the two **real** services
|
|
200
|
+
together — the only arrangement that can catch this class of drift.
|
|
201
|
+
|
|
202
|
+
### Finding 2 — the initial-JS figure had not been re-measured since 9.9.9 (FIXED)
|
|
203
|
+
|
|
204
|
+
FEATURE_STATUS claimed "~99 KiB gzip". `node scripts/check_bundle_budget.mjs`
|
|
205
|
+
measures **103.0 KiB** (index 66.1 + utils 29.2 + useQuery 7.6), against a build
|
|
206
|
+
`scripts/check_frontend_build_freshness.mjs` confirms is byte-identical to
|
|
207
|
+
source. The budget gate itself passes with room to spare — only the sentence was
|
|
208
|
+
stale. Lowered to the measured figure with the tool that measures it named.
|
|
209
|
+
The same stale number also appears in `ARCHITECTURE.md`.
|
|
210
|
+
|
|
211
|
+
### Finding 3 — an empty Brain grades itself 100 / "excellent" (FIXED after the sweep)
|
|
212
|
+
|
|
213
|
+
`health_report()` averages only the dimensions it could measure. On a
|
|
214
|
+
first-run Brain, freshness, connectivity and consistency all report
|
|
215
|
+
`status: "unavailable", score: null` and embedding coverage reports 100 (zero
|
|
216
|
+
of zero indexed) — so the composite is `overall_score: 100, grade: "excellent"`
|
|
217
|
+
from a single dimension over an empty graph.
|
|
218
|
+
|
|
219
|
+
Each dimension is individually honest; the composite is not. This is a
|
|
220
|
+
behaviour question rather than a documentation one (the row does not promise a
|
|
221
|
+
specific empty-Brain grade), and changing the score would move a number the
|
|
222
|
+
frontend and its tests render — so it is named here rather than changed inside
|
|
223
|
+
an audit.
|
|
224
|
+
|
|
225
|
+
**Disposition.** The lie was upstream of the composite: an index holding
|
|
226
|
+
nothing reports `coverage_ratio: 1.0`, which is 100% of nothing. That dimension
|
|
227
|
+
now reads `unavailable` with the reason `"no indexable items yet"` whenever
|
|
228
|
+
`source_items` is zero, so the empty Brain has *no* measurable dimension and
|
|
229
|
+
the existing `scores or None` path already returns `overall_score: None,
|
|
230
|
+
grade: null` — which the frontend already renders as 데이터 없음 / "No data
|
|
231
|
+
yet". Two additions keep the partial cases honest too: every unavailable
|
|
232
|
+
dimension now carries a `reason` (the graph could not be read vs. nothing saved
|
|
233
|
+
yet vs. no relationships yet), and the report gains a `coverage` block
|
|
234
|
+
(`measured` / `total` / `unavailable` / `partial`) so a verdict drawn from two
|
|
235
|
+
of four checks says so. When nothing could be measured a top-level `reason`
|
|
236
|
+
names each gap — the 9.9.7 rule that a "—" must state why.
|
|
237
|
+
|
|
238
|
+
### Finding 4 — `vector_freshness_breakdown()` has no surface (FIXED after the sweep)
|
|
239
|
+
|
|
240
|
+
The Vector Freshness row explains that "12 pending" hides the difference
|
|
241
|
+
between twelve never-embedded imports and twelve edits whose current answers
|
|
242
|
+
are quietly wrong, and names `vector_freshness_breakdown()` as the answer. The
|
|
243
|
+
method exists on the store and is tested — and has **zero product callers**.
|
|
244
|
+
`GET /api/brain/vector-freshness` still returns the aggregate
|
|
245
|
+
(`{status, pending_items, total_items, detail}`), so the distinction the
|
|
246
|
+
sentence sells is not visible anywhere in the product.
|
|
247
|
+
|
|
248
|
+
Either the endpoint should carry the breakdown or the row should say the split
|
|
249
|
+
is store-level only. The fix lives in store/API files owned by another track
|
|
250
|
+
this sprint, so it is reported rather than edited.
|
|
251
|
+
|
|
252
|
+
**Disposition.** The endpoint carries it. `BrainIntelligenceService.vector_freshness`
|
|
253
|
+
now returns the four-key contract from an unchanged private method and attaches
|
|
254
|
+
`breakdown` beside it when the store can compute one. The key is **omitted**
|
|
255
|
+
rather than zero-filled for every reason it cannot be had — graph off, an older
|
|
256
|
+
store without the method, an unreadable index, an empty answer — because a
|
|
257
|
+
zeroed backlog nobody measured is exactly the dishonesty the split exists to
|
|
258
|
+
remove. The frontend chip reads `pending_items` and is untouched.
|
|
259
|
+
|
|
260
|
+
### Finding 5 — `context_quality` never gains its `multimodal` key in production (FIXED after the sweep)
|
|
261
|
+
|
|
262
|
+
The Image Retrieval row says `context_quality` "gains a `multimodal` key only
|
|
263
|
+
when image nodes are really in the context". The mechanism is real and tested,
|
|
264
|
+
but the only call site that passes `multimodal=` to `context_quality_signal` is
|
|
265
|
+
`context_for_query(with_meta=True)`, which has no production caller. Both live
|
|
266
|
+
producers of `context_quality` — `api/chat_helpers.build_context_quality` and
|
|
267
|
+
`core/context_builder` — discard the hybrid result's `multimodal` block. Net
|
|
268
|
+
effect: on every shipped surface `context_quality` keeps the four-key shape
|
|
269
|
+
even when the answer cites `Image` nodes. Owned by the multi-modal track.
|
|
270
|
+
|
|
271
|
+
**Disposition.** Both producers pass it now. `build_context_quality` calls
|
|
272
|
+
`multimodal_signal(matches)` on **both** of its arms — the hybrid store and the
|
|
273
|
+
lexical-only fallback, since a picture found by keyword is still a picture —
|
|
274
|
+
and `retrieve_context_for_generation` does the same for the document path. The
|
|
275
|
+
present-only-when-true contract is unchanged: `multimodal_signal` returns
|
|
276
|
+
`None` for an all-text result set and `context_quality_signal` omits the key,
|
|
277
|
+
so an all-text answer is byte-identical to what 11.1.0 returned.
|
|
278
|
+
|
|
279
|
+
### Finding 6 — cloud write-back is never enqueued on the live path (FIXED after the sweep)
|
|
280
|
+
|
|
281
|
+
`CloudResponseIngestor.ingest` stages a `change_proposal` **only when a
|
|
282
|
+
`review_queue` sink is bound**. Both production call sites bind none:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
latticeai/services/hybrid_chat.py: ingestor = CloudResponseIngestor(store=knowledge_graph)
|
|
286
|
+
latticeai/services/hybrid_chat.py: ingest_status = CloudResponseIngestor(store=knowledge_graph).ingest(plan)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
With `plan.auto_commit` hardcoded `False`, `ingest()` returns
|
|
290
|
+
`{"status": "staged", "review_item_id": None, "written_nodes": 0}` — knowledge
|
|
291
|
+
extracted from a cloud answer is neither written nor queued. It is discarded
|
|
292
|
+
after the `hybrid_done` frame. The unit tests pass a `review_queue` directly to
|
|
293
|
+
the ingestor, so the wiring gap is invisible to CI. Related: the hybrid policy's
|
|
294
|
+
`auto_commit` flag is settable through `POST /api/network-boundary/policy` but
|
|
295
|
+
has no consumer.
|
|
296
|
+
|
|
297
|
+
The row's "is enqueued as a Review Center `change_proposal`" is therefore not
|
|
298
|
+
true as shipped. Threading a review sink through
|
|
299
|
+
`stream_hybrid_cloud_turn` / `run_hybrid_cloud_turn` / `maybe_hybrid_stream_response`
|
|
300
|
+
touches the chat router and the review-queue seam, both of which other tracks
|
|
301
|
+
were editing during this sweep — reported, not changed.
|
|
302
|
+
|
|
303
|
+
**Disposition.** Threaded, exactly there. Both turn functions take
|
|
304
|
+
`review_queue` and `auto_commit` as arguments (defaults `None` / `False`, so a
|
|
305
|
+
headless caller still stages nothing), `maybe_hybrid_stream_response` forwards
|
|
306
|
+
the sink and resolves the flag through the new
|
|
307
|
+
`chat_hybrid.resolve_hybrid_auto_commit`, and `/chat` supplies the live queue
|
|
308
|
+
through a new `AppContext.review_queue` **provider** — a callable rather than a
|
|
309
|
+
value, because `REVIEW_QUEUE` is produced in `phase_platform_features`, two
|
|
310
|
+
phases after the context is built, and a captured value would have been `None`
|
|
311
|
+
forever. `resolve_hybrid_auto_commit` treats an unreadable policy as the
|
|
312
|
+
default rather than as permission.
|
|
313
|
+
|
|
314
|
+
The reason CI could not see this — the unit tests handed the ingestor its
|
|
315
|
+
collaborator directly — is also the reason the new test drives `POST /chat`
|
|
316
|
+
with the dial on `cloud_allowed` and a fake adapter, and asserts the item
|
|
317
|
+
landed in the queue with `source: "change_proposal"`.
|
|
318
|
+
|
|
319
|
+
### Finding 7 — the local-file 401 is a gate, not a defect (CLEARED)
|
|
320
|
+
|
|
321
|
+
Worth recording because it looks like a defect and is not. In the default local
|
|
322
|
+
profile (`require_auth = false`), `POST /api/ingestion/obsidian` and every other
|
|
323
|
+
local-file route answer **401** to an anonymous caller:
|
|
324
|
+
`PermissionGateway.require_local_user` resolves the raw session identity and
|
|
325
|
+
does **not** fall through to the anonymous local owner that `require_user`
|
|
326
|
+
returns. Reading only that line suggests the vault bridge is unreachable out of
|
|
327
|
+
the box.
|
|
328
|
+
|
|
329
|
+
It is not. Driven end to end in the signed-in pass — register (first user
|
|
330
|
+
becomes admin) → login → `POST /api/ingestion/obsidian` →
|
|
331
|
+
`permission_required: true` with an `approval_token` →
|
|
332
|
+
`POST /permissions/approve/{token}` → re-post with the token →
|
|
333
|
+
`status: "dry_run", scanned: 2, notes: 2, tags: 1, links.resolved: 1`. That
|
|
334
|
+
sequence *is* the "standard local-read approval dance" the row describes.
|
|
335
|
+
Filesystem access deliberately demands a named account even where the rest of
|
|
336
|
+
the local API accepts the anonymous owner. Verdict: WORKS.
|
|
337
|
+
|
|
338
|
+
### Finding 8 — a retired Known Limitation
|
|
339
|
+
|
|
340
|
+
"The approval card under 작업 → 실행 still labels raw payload fields (`Action`,
|
|
341
|
+
`Action Label`, `User Email`) in plain mode" is no longer true. `Act.tsx`'s
|
|
342
|
+
`HumanPermissionDetails` renders a translated action badge, the target
|
|
343
|
+
filename, a free-text reason and a labelled requester line, with a regression
|
|
344
|
+
test forbidding raw i18n keys from reaching the DOM; the repo carries no
|
|
345
|
+
rendered `Action Label` / `User Email` literal. The screenshot the bullet cited
|
|
346
|
+
as proof — `output/release/v10.6.3/screenshots/09-automation-runs.png` — no
|
|
347
|
+
longer exists (release evidence now starts at v11.0.0). The bullet was removed;
|
|
348
|
+
carrying a fixed defect as a standing limitation is its own kind of dishonesty.
|
|
349
|
+
|
|
350
|
+
## prefix-static hermeticity (wp19 / wp36) — re-confirmed
|
|
351
|
+
|
|
352
|
+
`Config.from_env` resolves a *missing* static dir to `sys.prefix/static` when
|
|
353
|
+
that exists, which on a pip-installed machine it genuinely does. `_empty_prefix`
|
|
354
|
+
in `tests/unit/test_cov_wp19_build_phases.py` and
|
|
355
|
+
`tests/unit/test_cov_wp36_build_phases_late.py` neutralizes that so the
|
|
356
|
+
assertions describe the resolver rather than the runner.
|
|
357
|
+
|
|
358
|
+
Re-verified by simulating the release-runner condition for a whole session: a
|
|
359
|
+
pytest plugin pointed `sys.prefix` at a temp directory that **does** carry
|
|
360
|
+
`static/` (with a sentinel file), and the two suites plus
|
|
361
|
+
`test_cov_wp19_cli_entrypoint.py` were run under it.
|
|
362
|
+
|
|
363
|
+
* **81 passed.**
|
|
364
|
+
* The simulated prefix's `static/` still contained only the sentinel afterwards
|
|
365
|
+
— no test wrote into it.
|
|
366
|
+
* The hazard itself was confirmed live under the same plugin: with a missing
|
|
367
|
+
configured static dir, `Config.from_env` resolves to the fake prefix's
|
|
368
|
+
`static/`. The hermeticity is load-bearing, not decorative.
|
|
369
|
+
|
|
370
|
+
## Caveat — a concurrently mutating tree
|
|
371
|
+
|
|
372
|
+
This sweep ran while two other tracks were writing to the same working tree.
|
|
373
|
+
Files under `lattice_brain/` (portability, sealed box, multimodal, ingestion,
|
|
374
|
+
graph schema) and `latticeai/services/model_*` were changing during the run, and
|
|
375
|
+
one intermediate state was observed directly (a partially-rewired
|
|
376
|
+
`latticeai/services/obsidian_bridge.py` raising `NameError` mid-refactor, and a
|
|
377
|
+
`KnowledgeGraphStore` attribute warning at boot). Rows 37–41, 55 and 57 are
|
|
378
|
+
therefore reported **as of this snapshot**; their owning tracks are the
|
|
379
|
+
authority on where they land. Everything measured for rows outside those files
|
|
380
|
+
was stable across repeated runs.
|
|
381
|
+
|
|
382
|
+
## Changes this audit made
|
|
383
|
+
|
|
384
|
+
* `latticeai/services/command_center.py` — read the health shape the Brain
|
|
385
|
+
actually publishes (Finding 1).
|
|
386
|
+
* `tests/unit/test_command_center.py` — corrected the `FakeBrain` fixture to
|
|
387
|
+
its real counterpart's shape.
|
|
388
|
+
* `tests/unit/test_a3_feature_audit.py` — new. Pins the two drift classes this
|
|
389
|
+
audit found: a doc naming an endpoint the app does not serve, and the
|
|
390
|
+
briefing reading a health score the Brain never published.
|
|
391
|
+
* `FEATURE_STATUS.md` — Brain Home (Brain Brief is on the dock, not the first
|
|
392
|
+
screen), Frontend Payload (103 KiB, measured), and the retired approval-card
|
|
393
|
+
limitation.
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
이 문서의 모든 파일 경로와 줄 번호는 실제로 열어서 확인한 것이다.
|
|
6
6
|
추측한 경로는 한 줄도 없다.
|
|
7
7
|
|
|
8
|
+
> **증거 기준선 안내 (v11.2.0 기준).** 이 설계서가 인용하는
|
|
9
|
+
> `output/release/v10.6.3/screenshots/` 는 **더 이상 리포에 없다** — 릴리스 증거는
|
|
10
|
+
> v11.0.0 부터만 보관한다(`output/release/v11.0.0` · `v11.0.1` · `v11.1.0`).
|
|
11
|
+
> 따라서 아래의 "이전 캡처와 해시 대조" 절차는 그대로는 재현할 수 없다.
|
|
12
|
+
> 문서는 당시 측정값을 기록한 사료로 남기고, 지금 다시 채점한다면 기준선은
|
|
13
|
+
> **가장 최근 릴리스의 `output/release/<버전>/screenshots/`** 로 바꿔서 읽는다.
|
|
14
|
+
|
|
8
15
|
---
|
|
9
16
|
|
|
10
17
|
## 0. 이 재구성이 존재하는 이유
|
|
@@ -706,7 +713,8 @@ npm run frontend:openapi:check # OpenAPI drift 게이트
|
|
|
706
713
|
|
|
707
714
|
### 7.1 릴리스 캡처 12개 화면 전부 변경 — **24점** (화면당 2점)
|
|
708
715
|
|
|
709
|
-
**확인 명령:**
|
|
716
|
+
**확인 명령:** (기준선 경로는 문서 상단 안내대로 최신 릴리스 디렉터리로 바꿔 읽는다 —
|
|
717
|
+
`output/release/v10.6.3/` 는 리포에서 사라졌다.)
|
|
710
718
|
```
|
|
711
719
|
npm run build:assets
|
|
712
720
|
LTCAI_RELEASE_EVIDENCE_DIR=/tmp/lattice-after npm run release:evidence
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The Multi-Agent Runtime is the **orchestration layer** introduced in v2.0.0 and
|
|
4
4
|
operationalized in v2.2.0. It sits
|
|
5
|
-
*above* the v1.x single-agent state machine ([`SingleAgentRuntime`](../latticeai/core/agent.py))
|
|
5
|
+
*above* the v1.x single-agent state machine ([`SingleAgentRuntime`](../latticeai/core/agent/runtime.py))
|
|
6
6
|
and coordinates a pipeline of named **roles** that hand off work to one another,
|
|
7
7
|
retry on a failing review, and emit a fully observable, replayable timeline.
|
|
8
8
|
|
package/docs/ONBOARDING.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI Onboarding
|
|
2
2
|
|
|
3
|
-
Current release: **11.
|
|
3
|
+
Current release: **11.4.0 — Rust Foundation**.
|
|
4
4
|
|
|
5
5
|
The first-run goal is a five-minute path from "I opened the app" to "my Brain
|
|
6
6
|
has a source, a question, and proof." This page is the product contract behind
|
package/docs/OPERATIONS.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Lattice AI — Operations Guide (v11.
|
|
1
|
+
# Lattice AI — Operations Guide (v11.4.0)
|
|
2
2
|
|
|
3
3
|
> **Status: canonical** — kept in sync with the current release. Storage layout
|
|
4
4
|
> below reflects the SQLite live Brain store and workspace scoping, not the
|
|
@@ -176,7 +176,11 @@ Ctrl+C 또는 kill <pid>
|
|
|
176
176
|
캡처 → 오래된 버전 정리 → **픽셀 델타 검사**까지 한 번에 돈다.
|
|
177
177
|
4. 결속 검사 — `SCREENSHOT_INDEX.md` 의 `asset-manifest.sha256` 과
|
|
178
178
|
`mock-server.sha256` 이 각각 `static/app/asset-manifest.json`,
|
|
179
|
-
`tests/visual/mock_server.cjs`
|
|
179
|
+
그리고 목 API 표면 전체(`tests/visual/mock_server.cjs` +
|
|
180
|
+
`tests/visual/mock_server/*.cjs`) 와 일치해야 `npm run lint` 가 통과한다.
|
|
181
|
+
v11.3.0 부터 지문이 진입 파일 하나가 아니라 라우트 모듈까지 덮으므로,
|
|
182
|
+
v11.3.0 이전에 찍은 증거는 재캡처 전까지 불일치로 보고된다
|
|
183
|
+
(지문 계산은 `scripts/lib/mock_server_fingerprint.mjs` 한 곳에만 있다).
|
|
180
184
|
|
|
181
185
|
레이아웃을 바꿨다고 보고했는데 배치는 그대로인 경우를 잡기 위해 v10.7.0 부터
|
|
182
186
|
`scripts/check_screenshot_pixel_delta.py` 가 12개 캡처를 직전 버전과 대조한다
|
package/docs/PERMISSION_MODE.md
CHANGED
|
@@ -101,7 +101,7 @@ before routers are mounted would otherwise pin the store to the fallback
|
|
|
101
101
|
|--------|------|
|
|
102
102
|
| `latticeai/core/permission_mode.py` | Pure decision table |
|
|
103
103
|
| `latticeai/core/agent_permission.py` | Agent plan/tool gate helpers |
|
|
104
|
-
| `latticeai/core/agent
|
|
104
|
+
| `latticeai/core/agent/` | `SingleAgentRuntime` gates (mode-aware in-line: `planning.py` for the plan gate, `execution.py` for the per-tool gates) |
|
|
105
105
|
| `frontend/src/components/PermissionModePanel.tsx` | Settings selector |
|
|
106
106
|
| `latticeai/services/permission_mode_service.py` | Persistence |
|
|
107
107
|
| `latticeai/runtime/permission_mode_wiring.py` | Process-wide service + router mount |
|
package/docs/TRUST_MODEL.md
CHANGED
package/docs/WHY_LATTICE.md
CHANGED
package/docs/architecture.md
CHANGED
|
@@ -130,8 +130,12 @@ hardware scan
|
|
|
130
130
|
-> download/install/load/verify
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
The current default recommendation family is Gemma 4. Qwen3
|
|
134
|
-
|
|
133
|
+
The current default recommendation family is Gemma 4. Qwen3.6 and Qwen3.5 are
|
|
134
|
+
the current multimodal alternatives; GPT-OSS 20B and LFM2.5 2.6B fill the
|
|
135
|
+
general-purpose and ultralight tiers as text-only models. Superseded families
|
|
136
|
+
(Qwen3-VL, Llama 4, Qwen2.5-VL, Llama 3.2 Vision) stay in the capability
|
|
137
|
+
registry as *recognised* entries so already-downloaded weights keep working,
|
|
138
|
+
but they never appear in the catalog or a download path. See MODEL_POLICY.md.
|
|
135
139
|
|
|
136
140
|
## Modes
|
|
137
141
|
|
package/docs/kg-schema.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Knowledge Graph Schema
|
|
2
2
|
|
|
3
|
-
Current release: **11.
|
|
3
|
+
Current release: **11.4.0 — Rust Foundation**.
|
|
4
4
|
|
|
5
5
|
명세 출처: `lattice_ai_full_spec.pptx` 슬라이드 20·21·22
|
|
6
6
|
구현: `lattice_brain/graph/schema.py`
|
|
@@ -142,7 +142,7 @@ provenance(source_type, source_uri, content_hash, captured_at, modified_at,
|
|
|
142
142
|
범위 없는 로컬 폴더는 개인 Brain으로 재투영하되 기존 노드 ID는 보존하며,
|
|
143
143
|
같은 폴더를 다른 워크스페이스로 조용히 재할당하지 않는다.
|
|
144
144
|
|
|
145
|
-
구현: `lattice_brain/ingestion
|
|
145
|
+
구현: `lattice_brain/ingestion/` (`IngestionPipeline`) 가 단일 진입점이며,
|
|
146
146
|
파일/로컬폴더/URL/브라우저 탭/텍스트를 모두 이 형태로 정규화한다.
|
|
147
147
|
|
|
148
148
|
---
|