ltcai 9.9.0 → 9.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -35
- package/bin/ltcai.js +1 -1
- package/desktop/electron/main.cjs +1 -1
- package/docs/CHANGELOG.md +83 -0
- package/docs/CI_AND_RELEASE_GATES.md +1 -1
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/LEGACY_COMPATIBILITY.md +48 -49
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/kg-schema.md +6 -6
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/graph/schema.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/chat.py +3 -0
- package/latticeai/api/chat_agent_http.py +2 -1
- package/latticeai/api/chat_intents.py +130 -7
- package/latticeai/app_factory.py +1 -0
- package/latticeai/core/agent.py +114 -2
- package/latticeai/core/file_generation.py +58 -0
- package/latticeai/core/legacy_compatibility.py +71 -47
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/app_context.py +3 -0
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/product_readiness.py +7 -2
- package/latticeai/services/tool_dispatch.py +36 -0
- package/latticeai/tools/__init__.py +1 -1
- package/latticeai/tools/knowledge.py +1 -1
- package/package.json +6 -16
- package/scripts/check_current_release_docs.mjs +20 -1
- package/scripts/check_legacy_debt.mjs +91 -0
- package/scripts/prune_release_evidence.mjs +38 -0
- package/scripts/wheel_smoke.py +22 -6
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/src/main.rs +12 -12
- package/src-tauri/tauri.conf.json +1 -13
- package/static/app/asset-manifest.json +27 -27
- package/static/app/assets/Act-Cx_gZNbE.js +1 -0
- package/static/app/assets/{Brain-Cgkh0Hpn.js → Brain-BnGbytHa.js} +2 -2
- package/static/app/assets/BrainHome-CRUMJL93.js +2 -0
- package/static/app/assets/BrainSignals-BP8-Qh2g.js +1 -0
- package/static/app/assets/Capture-CAKnLcb0.js +1 -0
- package/static/app/assets/CommandPalette-BoUTXBfm.js +1 -0
- package/static/app/assets/Library-PcfVUco6.js +1 -0
- package/static/app/assets/LivingBrain-C3VbogVo.js +1 -0
- package/static/app/assets/ProductFlow-BLau7c7N.js +1 -0
- package/static/app/assets/ReviewCard-CX5RqRqx.js +1 -0
- package/static/app/assets/System-DRHc_6Su.js +1 -0
- package/static/app/assets/bot-DZkDdh-A.js +1 -0
- package/static/app/assets/cpu-DyvsDBbj.js +1 -0
- package/static/app/assets/download-C7yxYHvz.js +1 -0
- package/static/app/assets/folder-open-CffoIr9t.js +1 -0
- package/static/app/assets/hard-drive-C1oojrHb.js +1 -0
- package/static/app/assets/{index-BjaXCeOZ.js → index-BS_3aN1n.js} +3 -3
- package/static/app/assets/index-DU78Kogz.css +2 -0
- package/static/app/assets/input-B_U7zvbR.js +1 -0
- package/static/app/assets/navigation-xG-gyjbe.js +1 -0
- package/static/app/assets/network-BF13HJJF.js +1 -0
- package/static/app/assets/primitives-DsuKh3M8.js +1 -0
- package/static/app/assets/sunrise-CIP2ELJ1.js +1 -0
- package/static/app/assets/textarea-DsDL4ET8.js +1 -0
- package/static/app/assets/utils-Dh-Dwtkb.js +7 -0
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/auto_setup.py +0 -21
- package/kg_schema.py +0 -13
- package/knowledge_graph.py +0 -51
- package/knowledge_graph_api.py +0 -24
- package/llm_router.py +0 -20
- package/local_knowledge_api.py +0 -16
- package/ltcai_cli.py +0 -21
- package/mcp_registry.py +0 -20
- package/p_reinforce.py +0 -16
- package/setup_wizard.py +0 -16
- package/static/app/assets/Act-CfOPUKPs.js +0 -2
- package/static/app/assets/BrainHome-D8e3wQiW.js +0 -3
- package/static/app/assets/BrainSignals-BjRBA18L.js +0 -1
- package/static/app/assets/Capture-CQQYQ1Ga.js +0 -1
- package/static/app/assets/CommandPalette-pss56Mg4.js +0 -1
- package/static/app/assets/Library-CoI3xYJk.js +0 -1
- package/static/app/assets/LivingBrain-CaU_hCxQ.js +0 -1
- package/static/app/assets/ProductFlow-Db-1O71-.js +0 -1
- package/static/app/assets/System-Dfocn0zN.js +0 -1
- package/static/app/assets/bot-Bp2x1i6F.js +0 -1
- package/static/app/assets/circle-check-CyGal42W.js +0 -1
- package/static/app/assets/cpu-DQFk82hG.js +0 -1
- package/static/app/assets/download-C70gKQVi.js +0 -1
- package/static/app/assets/folder-open-DNGytsVw.js +0 -1
- package/static/app/assets/hard-drive-CYo_bEl4.js +0 -1
- package/static/app/assets/i18n-BBMJshCW.js +0 -7
- package/static/app/assets/index-BqRcLZR3.css +0 -2
- package/static/app/assets/input-ChWD-Fsh.js +0 -1
- package/static/app/assets/navigation-D9D9_FPC.js +0 -1
- package/static/app/assets/network-DzLDGmtV.js +0 -1
- package/static/app/assets/primitives-CmaSAyGG.js +0 -1
- package/static/app/assets/sparkles-DXiaM1NS.js +0 -1
- package/static/app/assets/textarea-CV43-o79.js +0 -1
- package/telegram_bot.py +0 -16
- package/tools/__init__.py +0 -29
|
@@ -49,7 +49,7 @@ __all__ = [
|
|
|
49
49
|
"remove_skill_directory",
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
-
WORKSPACE_OS_VERSION = "9.9.
|
|
52
|
+
WORKSPACE_OS_VERSION = "9.9.2"
|
|
53
53
|
|
|
54
54
|
# Workspace types separate single-user Personal workspaces from shared
|
|
55
55
|
# Organization workspaces. Both keep the same local-first JSON store; the type
|
|
@@ -34,6 +34,9 @@ class AppContext:
|
|
|
34
34
|
chat_service: Any = None
|
|
35
35
|
context_assembler: Any = None
|
|
36
36
|
brain_memory: Any = None
|
|
37
|
+
# Unified ingestion gateway (lattice_brain.ingestion.IngestionPipeline);
|
|
38
|
+
# None when the knowledge graph is disabled.
|
|
39
|
+
ingestion_pipeline: Any = None
|
|
37
40
|
chat_agent_runtime: Any = None
|
|
38
41
|
gardener: Any = None
|
|
39
42
|
hooks: Any = None
|
|
@@ -18,7 +18,7 @@ from typing import Any, Dict, List
|
|
|
18
18
|
|
|
19
19
|
from latticeai.services.architecture_readiness import architecture_readiness
|
|
20
20
|
|
|
21
|
-
PRODUCT_VERSION_TARGET = "9.9.
|
|
21
|
+
PRODUCT_VERSION_TARGET = "9.9.2"
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@dataclass(frozen=True)
|
|
@@ -60,6 +60,11 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
60
60
|
"latticeai/api/chat.py::is_file_action_request",
|
|
61
61
|
"latticeai/api/chat_intents.py::direct_file_action",
|
|
62
62
|
"latticeai/api/chat_intents.py::direct_write_file",
|
|
63
|
+
# v9.9.2 ArtifactWritePipeline: every write path shares the same
|
|
64
|
+
# extract → validate → repair guarantee, proven by the FG harness.
|
|
65
|
+
"latticeai/core/file_generation.py::sanitize_write_content",
|
|
66
|
+
"latticeai/core/agent.py::content_sanitize",
|
|
67
|
+
"tests/unit/test_artifact_write_scenarios.py::test_fg06_agent_dispatch_strips_fences_from_write_file_content",
|
|
63
68
|
"tests/unit/test_chat_telegram_decoupling.py::test_chat_file_creation_intent_writes_real_file",
|
|
64
69
|
],
|
|
65
70
|
),
|
|
@@ -140,7 +145,7 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
140
145
|
evidence=[
|
|
141
146
|
"scripts/brain_quality_eval.py",
|
|
142
147
|
"scripts/product_readiness.py",
|
|
143
|
-
"tests/unit/
|
|
148
|
+
"tests/unit/test_product_readiness.py",
|
|
144
149
|
"tests/visual/v3.spec.js::Brain Chat Home",
|
|
145
150
|
".github/workflows/ci.yml::scripts/product_readiness.py",
|
|
146
151
|
".github/workflows/release.yml::npm run lint",
|
|
@@ -307,6 +307,42 @@ def collect_created_files(transcript: list) -> list:
|
|
|
307
307
|
return files
|
|
308
308
|
|
|
309
309
|
|
|
310
|
+
def collect_artifacts(transcript: list) -> list:
|
|
311
|
+
"""Artifact-first view of a run: every produced file with honesty flags.
|
|
312
|
+
|
|
313
|
+
``repaired`` surfaces the ArtifactWritePipeline verdict recorded on the
|
|
314
|
+
transcript step (``content_sanitize``) so the UI can badge deterministic
|
|
315
|
+
scaffolds instead of presenting them as high-quality model output.
|
|
316
|
+
"""
|
|
317
|
+
from latticeai.core.file_generation import PREVIEWABLE_EXTENSIONS
|
|
318
|
+
|
|
319
|
+
artifacts = []
|
|
320
|
+
for step in transcript:
|
|
321
|
+
if step.get("action") not in FILE_CREATE_ACTIONS:
|
|
322
|
+
continue
|
|
323
|
+
result = step.get("result", {})
|
|
324
|
+
if not isinstance(result, dict):
|
|
325
|
+
continue
|
|
326
|
+
sanitize = step.get("content_sanitize") or {}
|
|
327
|
+
repaired = bool(sanitize.get("repaired"))
|
|
328
|
+
rel_paths = (
|
|
329
|
+
result["created_files"]
|
|
330
|
+
if isinstance(result.get("created_files"), list)
|
|
331
|
+
else ([result["path"]] if result.get("path") else [])
|
|
332
|
+
)
|
|
333
|
+
for rel_path in rel_paths:
|
|
334
|
+
artifacts.append({
|
|
335
|
+
"kind": "file",
|
|
336
|
+
"path": rel_path,
|
|
337
|
+
"filename": Path(rel_path).name,
|
|
338
|
+
"bytes": result.get("bytes", 0) if len(rel_paths) == 1 else 0,
|
|
339
|
+
"previewable": Path(rel_path).suffix.lower() in PREVIEWABLE_EXTENSIONS,
|
|
340
|
+
"valid": True,
|
|
341
|
+
"repaired": repaired,
|
|
342
|
+
})
|
|
343
|
+
return artifacts
|
|
344
|
+
|
|
345
|
+
|
|
310
346
|
def build_agent_runtime(
|
|
311
347
|
*,
|
|
312
348
|
model_router: Any,
|
|
@@ -23,7 +23,7 @@ from pathlib import Path
|
|
|
23
23
|
from typing import Any, Callable, Dict, List, Optional
|
|
24
24
|
|
|
25
25
|
from latticeai.core.tool_registry import ToolRegistry
|
|
26
|
-
from p_reinforce import BRAIN_DIR, STRUCTURE
|
|
26
|
+
from latticeai.services.p_reinforce import BRAIN_DIR, STRUCTURE
|
|
27
27
|
|
|
28
28
|
_PLATFORM = platform.system() # "Darwin" | "Windows" | "Linux"
|
|
29
29
|
|
|
@@ -6,7 +6,7 @@ import hashlib
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
from typing import Any, Dict, List, Optional
|
|
8
8
|
|
|
9
|
-
from p_reinforce import BRAIN_DIR, STRUCTURE
|
|
9
|
+
from latticeai.services.p_reinforce import BRAIN_DIR, STRUCTURE
|
|
10
10
|
from latticeai.tools import MAX_FILE_BYTES, ToolError
|
|
11
11
|
|
|
12
12
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ltcai",
|
|
3
|
-
"version": "9.9.
|
|
3
|
+
"version": "9.9.2",
|
|
4
4
|
"description": "Lattice AI — local-first Digital Brain that keeps your knowledge durable across any AI model.",
|
|
5
5
|
"homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"start": "LTCAI",
|
|
19
|
-
"dev": "python3
|
|
19
|
+
"dev": "python3 -m latticeai.cli.entrypoint --reload",
|
|
20
20
|
"build": "npm run build:assets && npm run build:python",
|
|
21
21
|
"frontend:dev": "vite --host 127.0.0.1",
|
|
22
22
|
"frontend:openapi": "node scripts/run_python.mjs scripts/export_openapi.py frontend/openapi.json && npx openapi-typescript frontend/openapi.json -o frontend/src/api/openapi.ts",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"build:assets": "vite build && node scripts/build_frontend_assets.mjs",
|
|
25
25
|
"build:python": "node scripts/run_python.mjs -m build",
|
|
26
26
|
"check:python": "node scripts/run_python.mjs scripts/check_python.py",
|
|
27
|
-
"lint": "npm run lint:python && node --check tests/visual/mock_server.cjs && node --check tests/visual/v3.spec.js && npm run lint:frontend && npm run frontend:openapi:check && node scripts/check_i18n_literals.mjs && npm run check:bundle && npm run test:browser-extension",
|
|
27
|
+
"lint": "npm run lint:python && node --check tests/visual/mock_server.cjs && node --check tests/visual/v3.spec.js && npm run lint:frontend && npm run frontend:openapi:check && node scripts/check_i18n_literals.mjs && npm run check:bundle && npm run check:legacy-debt && npm run test:browser-extension",
|
|
28
|
+
"check:legacy-debt": "node scripts/check_legacy_debt.mjs",
|
|
28
29
|
"lint:python": "node scripts/run_python.mjs -m ruff check .",
|
|
29
30
|
"lint:frontend": "node scripts/lint_frontend.mjs",
|
|
30
31
|
"check:bundle": "node scripts/check_bundle_budget.mjs",
|
|
@@ -46,7 +47,8 @@
|
|
|
46
47
|
"desktop:tauri:check": "cd src-tauri && cargo check",
|
|
47
48
|
"desktop:electron": "electron desktop/electron/main.cjs",
|
|
48
49
|
"package:vsix": "node scripts/build_vsix.mjs",
|
|
49
|
-
"release:evidence": "node scripts/capture_release_evidence.mjs",
|
|
50
|
+
"release:evidence": "node scripts/capture_release_evidence.mjs && node scripts/prune_release_evidence.mjs",
|
|
51
|
+
"release:evidence:prune": "node scripts/prune_release_evidence.mjs",
|
|
50
52
|
"release:artifacts": "node scripts/clean_release_artifacts.mjs $npm_package_version && npm run build:assets && npm run build:python && npm pack && npm run package:vsix && npm run desktop:tauri:build",
|
|
51
53
|
"release:validate": "node scripts/run_python.mjs scripts/validate_release_artifacts.py $npm_package_version --require-vsix --require-tgz --require-dmg",
|
|
52
54
|
"release:smoke": "node scripts/run_python.mjs scripts/release_smoke.py $npm_package_version",
|
|
@@ -76,17 +78,7 @@
|
|
|
76
78
|
"bin/ltcai.js",
|
|
77
79
|
"LICENSE",
|
|
78
80
|
"requirements.txt",
|
|
79
|
-
"ltcai_cli.py",
|
|
80
|
-
"auto_setup.py",
|
|
81
81
|
"server.py",
|
|
82
|
-
"kg_schema.py",
|
|
83
|
-
"knowledge_graph.py",
|
|
84
|
-
"local_knowledge_api.py",
|
|
85
|
-
"llm_router.py",
|
|
86
|
-
"p_reinforce.py",
|
|
87
|
-
"telegram_bot.py",
|
|
88
|
-
"tools/",
|
|
89
|
-
"mcp_registry.py",
|
|
90
82
|
"latticeai/**/*.py",
|
|
91
83
|
"lattice_brain/**/*.py",
|
|
92
84
|
"skills/",
|
|
@@ -113,8 +105,6 @@
|
|
|
113
105
|
"!**/*.pyc",
|
|
114
106
|
"!**/*.map",
|
|
115
107
|
"README.md",
|
|
116
|
-
"setup_wizard.py",
|
|
117
|
-
"knowledge_graph_api.py",
|
|
118
108
|
"static/vendor/",
|
|
119
109
|
"src-tauri/",
|
|
120
110
|
"!src-tauri/gen/",
|
|
@@ -6,7 +6,7 @@ const root = process.cwd();
|
|
|
6
6
|
const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
|
|
7
7
|
const version = pkg.version;
|
|
8
8
|
const releaseDir = `output/release/v${version}`;
|
|
9
|
-
const releaseTheme = "
|
|
9
|
+
const releaseTheme = "Artifact Trust";
|
|
10
10
|
const title = `${version} — ${releaseTheme}`;
|
|
11
11
|
const escapedVersion = version.replaceAll(".", "\\.");
|
|
12
12
|
|
|
@@ -71,6 +71,25 @@ for (const rel of [
|
|
|
71
71
|
requireIncludes(rel, version);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
// The Release Artifact Map in ARCHITECTURE.md must name current-version
|
|
75
|
+
// artifacts exactly — this block drifted silently before 9.9.1.
|
|
76
|
+
requireIncludes("ARCHITECTURE.md", `${version} exact artifact names:`);
|
|
77
|
+
for (const artifact of [
|
|
78
|
+
`dist/ltcai-${version}-py3-none-any.whl`,
|
|
79
|
+
`dist/ltcai-${version}.tar.gz`,
|
|
80
|
+
`ltcai-${version}.tgz`,
|
|
81
|
+
`dist/ltcai-${version}.vsix`,
|
|
82
|
+
`src-tauri/target/release/bundle/dmg/Lattice AI_${version}_aarch64.dmg`,
|
|
83
|
+
]) {
|
|
84
|
+
requireIncludes("ARCHITECTURE.md", artifact);
|
|
85
|
+
}
|
|
86
|
+
const architecture = read("ARCHITECTURE.md");
|
|
87
|
+
for (const match of architecture.matchAll(/ltcai-(\d+\.\d+\.\d+)/g)) {
|
|
88
|
+
if (match[1] !== version) {
|
|
89
|
+
errors.push(`ARCHITECTURE.md: stale artifact version reference ${match[0]}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
74
93
|
requireIncludes("README.md", `The current release is **${title}**`);
|
|
75
94
|
requireIncludes("README.md", `![v${version} Living Brain walkthrough]`);
|
|
76
95
|
requireIncludes("RELEASE.md", `## v${version} — ${releaseTheme}`);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Legacy debt gate (9.9.1): the root shim layer stays removed.
|
|
3
|
+
//
|
|
4
|
+
// Fails when:
|
|
5
|
+
// 1. a Python module other than server.py appears at the repository root;
|
|
6
|
+
// 2. any source tree imports a removed root shim module;
|
|
7
|
+
// 3. a removed shim directory (tools/) reappears at the root.
|
|
8
|
+
//
|
|
9
|
+
// Mirror of tests/unit/test_legacy_root_shims.py, but static and runnable in
|
|
10
|
+
// `npm run lint` without a Python environment.
|
|
11
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
12
|
+
import { join, relative } from "node:path";
|
|
13
|
+
|
|
14
|
+
const repo = join(import.meta.dirname, "..");
|
|
15
|
+
|
|
16
|
+
const ALLOWED_ROOT_MODULES = new Set(["server.py"]);
|
|
17
|
+
const REMOVED_ROOT_DIRS = ["tools"];
|
|
18
|
+
const REMOVED_MODULES = [
|
|
19
|
+
"ltcai_cli",
|
|
20
|
+
"auto_setup",
|
|
21
|
+
"setup_wizard",
|
|
22
|
+
"mcp_registry",
|
|
23
|
+
"kg_schema",
|
|
24
|
+
"knowledge_graph",
|
|
25
|
+
"knowledge_graph_api",
|
|
26
|
+
"local_knowledge_api",
|
|
27
|
+
"llm_router",
|
|
28
|
+
"p_reinforce",
|
|
29
|
+
"telegram_bot",
|
|
30
|
+
"tools",
|
|
31
|
+
];
|
|
32
|
+
// Trees that must not import removed shims. static/app and node_modules are
|
|
33
|
+
// build output; src-tauri/target is compiler output.
|
|
34
|
+
const SOURCE_TREES = ["latticeai", "lattice_brain", "tests", "scripts", "bin", "desktop/electron"];
|
|
35
|
+
|
|
36
|
+
const failures = [];
|
|
37
|
+
|
|
38
|
+
for (const entry of readdirSync(repo)) {
|
|
39
|
+
if (entry.endsWith(".py") && !ALLOWED_ROOT_MODULES.has(entry)) {
|
|
40
|
+
failures.push(`root module reappeared: ${entry} — put code in latticeai/ or lattice_brain/`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
for (const dir of REMOVED_ROOT_DIRS) {
|
|
44
|
+
if (existsSync(join(repo, dir))) {
|
|
45
|
+
failures.push(`removed root package reappeared: ${dir}/ — use latticeai.${dir} instead`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const modulePattern = REMOVED_MODULES.join("|");
|
|
50
|
+
const pyImport = new RegExp(`^\\s*(?:import\\s+(?:${modulePattern})\\b|from\\s+(?:${modulePattern})\\s+import\\b)`);
|
|
51
|
+
const jsSpawn = new RegExp(`(?:${modulePattern})\\.py\\b`);
|
|
52
|
+
|
|
53
|
+
function* walk(dir) {
|
|
54
|
+
for (const entry of readdirSync(dir)) {
|
|
55
|
+
if (entry === "__pycache__" || entry === "node_modules" || entry === ".venv") continue;
|
|
56
|
+
const full = join(dir, entry);
|
|
57
|
+
const st = statSync(full);
|
|
58
|
+
if (st.isDirectory()) yield* walk(full);
|
|
59
|
+
else yield full;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const tree of SOURCE_TREES) {
|
|
64
|
+
const base = join(repo, tree);
|
|
65
|
+
if (!existsSync(base)) continue;
|
|
66
|
+
for (const file of walk(base)) {
|
|
67
|
+
const rel = relative(repo, file);
|
|
68
|
+
if (/\.py$/.test(file)) {
|
|
69
|
+
const lines = readFileSync(file, "utf8").split("\n");
|
|
70
|
+
lines.forEach((line, i) => {
|
|
71
|
+
if (pyImport.test(line)) {
|
|
72
|
+
failures.push(`${rel}:${i + 1} imports a removed root shim: ${line.trim()}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
} else if (/\.(mjs|cjs|js)$/.test(file) && !/\.min\.js$/.test(file)) {
|
|
76
|
+
const lines = readFileSync(file, "utf8").split("\n");
|
|
77
|
+
lines.forEach((line, i) => {
|
|
78
|
+
if (jsSpawn.test(line) && !line.includes("check_legacy_debt")) {
|
|
79
|
+
failures.push(`${rel}:${i + 1} references a removed root shim file: ${line.trim()}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (failures.length > 0) {
|
|
87
|
+
console.error("legacy debt gate FAILED:");
|
|
88
|
+
for (const failure of failures) console.error(` - ${failure}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
console.log("legacy debt gate ok: root shim layer stays removed (server.py only)");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Retention policy for output/release/: keep the newest N versioned evidence
|
|
3
|
+
// directories (default 3, override with LTCAI_RELEASE_EVIDENCE_KEEP or argv).
|
|
4
|
+
// Older captures are reproducible on demand via `npm run release:evidence`,
|
|
5
|
+
// so keeping the full history only burns disk (13 versions ≈ 90MB).
|
|
6
|
+
import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
|
|
9
|
+
const repo = join(import.meta.dirname, "..");
|
|
10
|
+
const releaseDir = join(repo, "output", "release");
|
|
11
|
+
const keep = Math.max(1, Number(process.argv[2] || process.env.LTCAI_RELEASE_EVIDENCE_KEEP || 3));
|
|
12
|
+
|
|
13
|
+
if (!existsSync(releaseDir)) {
|
|
14
|
+
console.log(`release evidence: nothing to prune (${releaseDir} missing)`);
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const semver = (name) => {
|
|
19
|
+
const m = /^v(\d+)\.(\d+)\.(\d+)$/.exec(name);
|
|
20
|
+
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const versioned = readdirSync(releaseDir)
|
|
24
|
+
.filter((name) => semver(name) && statSync(join(releaseDir, name)).isDirectory())
|
|
25
|
+
.sort((a, b) => {
|
|
26
|
+
const [a1, a2, a3] = semver(a);
|
|
27
|
+
const [b1, b2, b3] = semver(b);
|
|
28
|
+
return b1 - a1 || b2 - a2 || b3 - a3;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const stale = versioned.slice(keep);
|
|
32
|
+
for (const name of stale) {
|
|
33
|
+
rmSync(join(releaseDir, name), { recursive: true, force: true });
|
|
34
|
+
console.log(`release evidence: pruned ${name}`);
|
|
35
|
+
}
|
|
36
|
+
console.log(
|
|
37
|
+
`release evidence: keeping ${Math.min(keep, versioned.length)} of ${versioned.length} versions (policy: newest ${keep})`,
|
|
38
|
+
);
|
package/scripts/wheel_smoke.py
CHANGED
|
@@ -32,7 +32,6 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
|
32
32
|
|
|
33
33
|
# Every importable module the wheel ships (pyproject py-modules + packages).
|
|
34
34
|
WHEEL_MODULES = [
|
|
35
|
-
"setup_wizard",
|
|
36
35
|
"lattice_brain",
|
|
37
36
|
"lattice_brain.graph",
|
|
38
37
|
"lattice_brain.graph.store",
|
|
@@ -55,9 +54,18 @@ WHEEL_MODULES = [
|
|
|
55
54
|
"latticeai.services.p_reinforce",
|
|
56
55
|
"latticeai.tools",
|
|
57
56
|
"latticeai.tools.knowledge",
|
|
57
|
+
"latticeai.setup.auto_setup",
|
|
58
|
+
"latticeai.setup.wizard",
|
|
59
|
+
"latticeai.services.local_knowledge",
|
|
60
|
+
"lattice_brain.graph.schema",
|
|
61
|
+
"server",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
# Root shims removed in 9.9.1 — the wheel must NOT ship them anymore.
|
|
65
|
+
REMOVED_ROOT_MODULES = [
|
|
58
66
|
"ltcai_cli",
|
|
59
67
|
"auto_setup",
|
|
60
|
-
"
|
|
68
|
+
"setup_wizard",
|
|
61
69
|
"mcp_registry",
|
|
62
70
|
"kg_schema",
|
|
63
71
|
"knowledge_graph",
|
|
@@ -67,15 +75,23 @@ WHEEL_MODULES = [
|
|
|
67
75
|
"p_reinforce",
|
|
68
76
|
"telegram_bot",
|
|
69
77
|
"tools",
|
|
70
|
-
"tools.knowledge",
|
|
71
78
|
]
|
|
72
79
|
|
|
73
80
|
IMPORT_CHECK = (
|
|
74
81
|
"import importlib\n"
|
|
75
82
|
+ "".join(f"importlib.import_module({mod!r})\n" for mod in WHEEL_MODULES)
|
|
76
|
-
+ "
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
+ "".join(
|
|
84
|
+
f"""
|
|
85
|
+
try:
|
|
86
|
+
importlib.import_module({mod!r})
|
|
87
|
+
except ImportError:
|
|
88
|
+
pass
|
|
89
|
+
else:
|
|
90
|
+
raise AssertionError('removed root shim {mod} is still shipped in the wheel')
|
|
91
|
+
"""
|
|
92
|
+
for mod in REMOVED_ROOT_MODULES
|
|
93
|
+
)
|
|
94
|
+
+ f"print('wheel imports ok: {len(WHEEL_MODULES)} modules, {len(REMOVED_ROOT_MODULES)} shims gone')\n"
|
|
79
95
|
)
|
|
80
96
|
|
|
81
97
|
HEALTH_CHECK = """
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
package/src-tauri/src/main.rs
CHANGED
|
@@ -164,9 +164,9 @@ fn resource_dir() -> Option<PathBuf> {
|
|
|
164
164
|
fn bundled_python_root() -> Option<PathBuf> {
|
|
165
165
|
let resources = resource_dir()?;
|
|
166
166
|
let up = resources.join("_up_");
|
|
167
|
-
if up.join("
|
|
167
|
+
if up.join("latticeai").join("cli").join("entrypoint.py").is_file() {
|
|
168
168
|
Some(up)
|
|
169
|
-
} else if resources.join("
|
|
169
|
+
} else if resources.join("latticeai").join("cli").join("entrypoint.py").is_file() {
|
|
170
170
|
Some(resources)
|
|
171
171
|
} else {
|
|
172
172
|
None
|
|
@@ -222,13 +222,13 @@ fn backend_launch(origin: &str) -> BackendLaunch {
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
for python in python_candidates() {
|
|
225
|
-
if module_importable(&python, "
|
|
225
|
+
if module_importable(&python, "latticeai.cli.entrypoint") {
|
|
226
226
|
return BackendLaunch {
|
|
227
|
-
command: format!("{python} -m
|
|
227
|
+
command: format!("{python} -m latticeai.cli.entrypoint --host 127.0.0.1 --port {port}"),
|
|
228
228
|
program: python,
|
|
229
229
|
args: vec![
|
|
230
230
|
"-m".into(),
|
|
231
|
-
"
|
|
231
|
+
"latticeai.cli.entrypoint".into(),
|
|
232
232
|
"--host".into(),
|
|
233
233
|
"127.0.0.1".into(),
|
|
234
234
|
"--port".into(),
|
|
@@ -240,27 +240,27 @@ fn backend_launch(origin: &str) -> BackendLaunch {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
if let Some(resources) = bundled_python_root() {
|
|
243
|
-
|
|
244
|
-
if launcher.is_file() {
|
|
243
|
+
if resources.join("latticeai").join("cli").join("entrypoint.py").is_file() {
|
|
245
244
|
if let Some(python) = python_candidates().into_iter().next() {
|
|
246
245
|
return BackendLaunch {
|
|
247
|
-
command: format!("{python}
|
|
246
|
+
command: format!("{python} -m latticeai.cli.entrypoint --host 127.0.0.1 --port {port}"),
|
|
248
247
|
program: python,
|
|
249
248
|
args: vec![
|
|
250
|
-
|
|
249
|
+
"-m".into(),
|
|
250
|
+
"latticeai.cli.entrypoint".into(),
|
|
251
251
|
"--host".into(),
|
|
252
252
|
"127.0.0.1".into(),
|
|
253
253
|
"--port".into(),
|
|
254
254
|
port,
|
|
255
255
|
],
|
|
256
|
-
cwd:
|
|
256
|
+
cwd: Some(resources),
|
|
257
257
|
};
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
BackendLaunch {
|
|
263
|
-
command: "unavailable: LTCAI executable or importable
|
|
263
|
+
command: "unavailable: LTCAI executable or importable latticeai.cli.entrypoint module not found".to_string(),
|
|
264
264
|
program: String::new(),
|
|
265
265
|
args: Vec::new(),
|
|
266
266
|
cwd: None,
|
|
@@ -278,7 +278,7 @@ fn spawn_backend(origin: &str, launch: &BackendLaunch) -> Result<Option<Child>,
|
|
|
278
278
|
return Ok(None);
|
|
279
279
|
}
|
|
280
280
|
if launch.program.is_empty() {
|
|
281
|
-
return Err("Desktop backend unavailable: LTCAI executable or importable
|
|
281
|
+
return Err("Desktop backend unavailable: LTCAI executable or importable latticeai.cli.entrypoint module not found.".to_string());
|
|
282
282
|
}
|
|
283
283
|
|
|
284
284
|
let mut cmd = Command::new(&launch.program);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://schema.tauri.app/config/2",
|
|
3
3
|
"productName": "Lattice AI",
|
|
4
|
-
"version": "9.9.
|
|
4
|
+
"version": "9.9.2",
|
|
5
5
|
"identifier": "ai.lattice.desktop",
|
|
6
6
|
"build": {
|
|
7
7
|
"beforeDevCommand": "npm run frontend:dev",
|
|
@@ -33,22 +33,10 @@
|
|
|
33
33
|
"app"
|
|
34
34
|
],
|
|
35
35
|
"resources": [
|
|
36
|
-
"../auto_setup.py",
|
|
37
|
-
"../kg_schema.py",
|
|
38
|
-
"../knowledge_graph.py",
|
|
39
|
-
"../knowledge_graph_api.py",
|
|
40
|
-
"../llm_router.py",
|
|
41
|
-
"../local_knowledge_api.py",
|
|
42
|
-
"../ltcai_cli.py",
|
|
43
|
-
"../mcp_registry.py",
|
|
44
|
-
"../p_reinforce.py",
|
|
45
36
|
"../server.py",
|
|
46
|
-
"../setup_wizard.py",
|
|
47
|
-
"../telegram_bot.py",
|
|
48
37
|
"../requirements.txt",
|
|
49
38
|
"../latticeai",
|
|
50
39
|
"../lattice_brain",
|
|
51
|
-
"../tools",
|
|
52
40
|
"../static"
|
|
53
41
|
],
|
|
54
42
|
"icon": [
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "9.9.
|
|
2
|
+
"version": "9.9.2",
|
|
3
3
|
"generated_at": "vite",
|
|
4
4
|
"entrypoints": {
|
|
5
|
-
"app": "/static/app/assets/index-
|
|
5
|
+
"app": "/static/app/assets/index-BS_3aN1n.js"
|
|
6
6
|
},
|
|
7
7
|
"assets": {
|
|
8
8
|
"../node_modules/@tauri-apps/api/core.js": "/static/app/assets/core-CwxXejkd.js",
|
|
9
|
-
"_BrainSignals-
|
|
10
|
-
"_LivingBrain-
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"_cpu-
|
|
14
|
-
"_download-
|
|
15
|
-
"_folder-open-
|
|
16
|
-
"_hard-drive-
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"index.html": "/static/app/assets/index-
|
|
25
|
-
"assets/index-
|
|
26
|
-
"src/components/ProductFlow.tsx": "/static/app/assets/ProductFlow-
|
|
27
|
-
"src/features/brain/BrainHome.tsx": "/static/app/assets/BrainHome-
|
|
28
|
-
"src/features/command/CommandPalette.tsx": "/static/app/assets/CommandPalette-
|
|
29
|
-
"src/pages/Act.tsx": "/static/app/assets/Act-
|
|
30
|
-
"src/pages/Brain.tsx": "/static/app/assets/Brain-
|
|
31
|
-
"src/pages/Capture.tsx": "/static/app/assets/Capture-
|
|
32
|
-
"src/pages/Library.tsx": "/static/app/assets/Library-
|
|
33
|
-
"src/pages/System.tsx": "/static/app/assets/System-
|
|
9
|
+
"_BrainSignals-BP8-Qh2g.js": "/static/app/assets/BrainSignals-BP8-Qh2g.js",
|
|
10
|
+
"_LivingBrain-C3VbogVo.js": "/static/app/assets/LivingBrain-C3VbogVo.js",
|
|
11
|
+
"_ReviewCard-CX5RqRqx.js": "/static/app/assets/ReviewCard-CX5RqRqx.js",
|
|
12
|
+
"_bot-DZkDdh-A.js": "/static/app/assets/bot-DZkDdh-A.js",
|
|
13
|
+
"_cpu-DyvsDBbj.js": "/static/app/assets/cpu-DyvsDBbj.js",
|
|
14
|
+
"_download-C7yxYHvz.js": "/static/app/assets/download-C7yxYHvz.js",
|
|
15
|
+
"_folder-open-CffoIr9t.js": "/static/app/assets/folder-open-CffoIr9t.js",
|
|
16
|
+
"_hard-drive-C1oojrHb.js": "/static/app/assets/hard-drive-C1oojrHb.js",
|
|
17
|
+
"_input-B_U7zvbR.js": "/static/app/assets/input-B_U7zvbR.js",
|
|
18
|
+
"_navigation-xG-gyjbe.js": "/static/app/assets/navigation-xG-gyjbe.js",
|
|
19
|
+
"_network-BF13HJJF.js": "/static/app/assets/network-BF13HJJF.js",
|
|
20
|
+
"_primitives-DsuKh3M8.js": "/static/app/assets/primitives-DsuKh3M8.js",
|
|
21
|
+
"_sunrise-CIP2ELJ1.js": "/static/app/assets/sunrise-CIP2ELJ1.js",
|
|
22
|
+
"_textarea-DsDL4ET8.js": "/static/app/assets/textarea-DsDL4ET8.js",
|
|
23
|
+
"_utils-Dh-Dwtkb.js": "/static/app/assets/utils-Dh-Dwtkb.js",
|
|
24
|
+
"index.html": "/static/app/assets/index-BS_3aN1n.js",
|
|
25
|
+
"assets/index-DU78Kogz.css": "/static/app/assets/index-DU78Kogz.css",
|
|
26
|
+
"src/components/ProductFlow.tsx": "/static/app/assets/ProductFlow-BLau7c7N.js",
|
|
27
|
+
"src/features/brain/BrainHome.tsx": "/static/app/assets/BrainHome-CRUMJL93.js",
|
|
28
|
+
"src/features/command/CommandPalette.tsx": "/static/app/assets/CommandPalette-BoUTXBfm.js",
|
|
29
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-Cx_gZNbE.js",
|
|
30
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-BnGbytHa.js",
|
|
31
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-CAKnLcb0.js",
|
|
32
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-PcfVUco6.js",
|
|
33
|
+
"src/pages/System.tsx": "/static/app/assets/System-DRHc_6Su.js"
|
|
34
34
|
}
|
|
35
35
|
}
|