ltcai 9.9.3 → 9.9.4
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 +43 -38
- package/docs/CHANGELOG.md +65 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +1 -1
- package/docs/SURFACE_PARITY.md +47 -0
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/kg-schema.md +1 -1
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/graph/_kg_common.py +335 -0
- package/lattice_brain/graph/discovery_index.py +8 -1
- package/lattice_brain/graph/ingest.py +43 -9
- package/lattice_brain/graph/projection.py +221 -37
- package/lattice_brain/graph/retrieval.py +61 -12
- package/lattice_brain/graph/retrieval_policy.py +174 -0
- package/lattice_brain/graph/retrieval_vector.py +122 -2
- package/lattice_brain/portability.py +41 -12
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/chat.py +6 -0
- package/latticeai/api/chat_agent_http.py +175 -6
- package/latticeai/api/chat_intents.py +37 -18
- package/latticeai/api/chat_stream.py +76 -2
- package/latticeai/api/knowledge_graph.py +35 -1
- package/latticeai/core/agent.py +264 -9
- package/latticeai/core/enterprise.py +5 -0
- package/latticeai/core/file_generation.py +130 -5
- package/latticeai/core/legacy_compatibility.py +1 -1
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/run_store.py +243 -0
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/models/router.py +25 -12
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/command_center.py +90 -1
- package/latticeai/services/folder_watch.py +5 -0
- package/latticeai/services/funnel_metrics.py +9 -1
- package/latticeai/services/product_readiness.py +1 -1
- package/latticeai/services/search_service.py +43 -13
- package/package.json +1 -1
- package/scripts/bench_agent_smoke.py +410 -0
- package/scripts/check_current_release_docs.mjs +1 -1
- package/scripts/funnel_soft_gate.py +192 -0
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +29 -28
- package/static/app/assets/Act-BCmTU0E2.js +1 -0
- package/static/app/assets/{Brain-DEY9jLVt.js → Brain-CTnjox7w.js} +2 -2
- package/static/app/assets/BrainHome-BJ3sFNX0.js +2 -0
- package/static/app/assets/BrainSignals-C52lwZVD.js +1 -0
- package/static/app/assets/{Capture-CVZ09QXi.js → Capture-B6vBhFa3.js} +1 -1
- package/static/app/assets/{CommandPalette-DepwOQFv.js → CommandPalette-90u9FWFH.js} +1 -1
- package/static/app/assets/{Library-Bp0n-HlW.js → Library-pKCK0_tk.js} +1 -1
- package/static/app/assets/{LivingBrain-DxP4efJF.js → LivingBrain-Jlf2wFqI.js} +1 -1
- package/static/app/assets/{ProductFlow-DRbm7NEq.js → ProductFlow-yg1fKP1P.js} +1 -1
- package/static/app/assets/{ReviewCard-C4HAO7A3.js → ReviewCard-DWvD7n9h.js} +1 -1
- package/static/app/assets/{System-ByQcmJW-.js → System-BAEuHqNY.js} +1 -1
- package/static/app/assets/{bot-BNDyZLR7.js → bot-nB_buEZD.js} +1 -1
- package/static/app/assets/circle-pause-DLNw6Ucp.js +1 -0
- package/static/app/assets/{circle-play-BkhdcHgd.js → circle-play-B-IsFL1y.js} +1 -1
- package/static/app/assets/{cpu-C6jjYm6i.js → cpu-CEPBHaBl.js} +1 -1
- package/static/app/assets/{folder-open-DjGIvDBQ.js → folder-open-hmN0N9cX.js} +1 -1
- package/static/app/assets/{hard-drive-BlSbwSaT.js → hard-drive-CBV_B_Yd.js} +1 -1
- package/static/app/assets/{index-Bge3DXW7.css → index-7FAfYm4v.css} +1 -1
- package/static/app/assets/{index-CHu7cgj3.js → index-DrmOCySv.js} +3 -3
- package/static/app/assets/{input-DVDI0YR3.js → input-gtVCg-ll.js} +1 -1
- package/static/app/assets/{navigation-BddhEWA0.js → navigation-Bot0hvuv.js} +1 -1
- package/static/app/assets/{network-pYQt5oBu.js → network-jE42eKfT.js} +1 -1
- package/static/app/assets/{primitives-D7gCdEvS.js → primitives-CX2Komon.js} +1 -1
- package/static/app/assets/{shield-alert-K9RKGQeg.js → shield-alert-BftATuAA.js} +1 -1
- package/static/app/assets/{textarea-sqQmoBKL.js → textarea-CiMJfOSI.js} +1 -1
- package/static/app/assets/{useFocusTrap-7EV9dFP2.js → useFocusTrap-B7RPGfFy.js} +1 -1
- package/static/app/assets/utils-SJUNVOj5.js +7 -0
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/static/app/assets/Act-DmdruVKV.js +0 -1
- package/static/app/assets/BrainHome-CeNaxjP1.js +0 -2
- package/static/app/assets/BrainSignals-CStjIqYi.js +0 -1
- package/static/app/assets/utils-uQYKXNeq.js +0 -7
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Funnel soft gate (review Wave 3.3) — funnel metrics as an advisory verdict.
|
|
3
|
+
|
|
4
|
+
Reads the same ``funnel_metrics.json`` production writes and grades it through
|
|
5
|
+
``FunnelMetricsService.snapshot()`` — no rate logic is duplicated here. Two
|
|
6
|
+
funnel-health rates carry WARN thresholds:
|
|
7
|
+
|
|
8
|
+
* ``code_only_rate`` — WARN above 0.05 (goal: >95% of recognized file
|
|
9
|
+
requests deliver a real artifact, not a code/prose-only answer);
|
|
10
|
+
* ``needs_review_rate`` — WARN above 0.30 (verifier fail-closed is healthy,
|
|
11
|
+
but a third of runs ending NEEDS_REVIEW means verification is starving).
|
|
12
|
+
|
|
13
|
+
Rates whose denominator is still zero come back ``None`` from the snapshot;
|
|
14
|
+
they are reported as "no data" and never warn — a fresh install stays green.
|
|
15
|
+
``real_file_rate``, ``approval_resume_rate`` and TTFV are shown as
|
|
16
|
+
informational context only.
|
|
17
|
+
|
|
18
|
+
Exit codes
|
|
19
|
+
==========
|
|
20
|
+
* default — advisory: ALWAYS ``0``; warnings are printed, not enforced;
|
|
21
|
+
* ``--strict`` — CI opt-in: ``1`` when any WARN fired ("no data" never
|
|
22
|
+
fails, even under --strict);
|
|
23
|
+
* bad flags — argparse's usual ``2`` (the only real script error).
|
|
24
|
+
|
|
25
|
+
Usage
|
|
26
|
+
=====
|
|
27
|
+
.venv/bin/python scripts/funnel_soft_gate.py # advisory report
|
|
28
|
+
.venv/bin/python scripts/funnel_soft_gate.py --strict # CI gate opt-in
|
|
29
|
+
.venv/bin/python scripts/funnel_soft_gate.py --json # machine output
|
|
30
|
+
.venv/bin/python scripts/funnel_soft_gate.py --path /tmp/m.json
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import argparse
|
|
36
|
+
import json
|
|
37
|
+
import os
|
|
38
|
+
import sys
|
|
39
|
+
from pathlib import Path
|
|
40
|
+
from typing import Any, Dict, List, Optional
|
|
41
|
+
|
|
42
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
43
|
+
|
|
44
|
+
from latticeai.services.funnel_metrics import FunnelMetricsService # noqa: E402
|
|
45
|
+
|
|
46
|
+
# Advisory thresholds (overridable per run via flags). WARN fires strictly
|
|
47
|
+
# ABOVE the threshold, so a rate sitting exactly on the goal boundary passes.
|
|
48
|
+
CODE_ONLY_WARN_THRESHOLD = 0.05
|
|
49
|
+
NEEDS_REVIEW_WARN_THRESHOLD = 0.30
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def default_metrics_path() -> Path:
|
|
53
|
+
"""The exact file production writes: ``Config.from_env`` data-dir pattern
|
|
54
|
+
(``LATTICEAI_DATA_DIR`` env or ``~/.ltcai``) + the ``funnel_metrics.json``
|
|
55
|
+
filename from ``latticeai/runtime/persistence_runtime.py``."""
|
|
56
|
+
data_dir = Path(os.environ.get("LATTICEAI_DATA_DIR") or (Path.home() / ".ltcai"))
|
|
57
|
+
return data_dir / "funnel_metrics.json"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def evaluate_snapshot(
|
|
61
|
+
snapshot: Dict[str, Any],
|
|
62
|
+
*,
|
|
63
|
+
code_only_warn: float = CODE_ONLY_WARN_THRESHOLD,
|
|
64
|
+
needs_review_warn: float = NEEDS_REVIEW_WARN_THRESHOLD,
|
|
65
|
+
) -> Dict[str, Any]:
|
|
66
|
+
"""Grade a ``FunnelMetricsService.snapshot()`` payload into verdicts."""
|
|
67
|
+
rates = snapshot.get("rates") or {}
|
|
68
|
+
checks: List[Dict[str, Any]] = []
|
|
69
|
+
|
|
70
|
+
def check(name: str, threshold: float, goal: str) -> None:
|
|
71
|
+
rate: Optional[float] = rates.get(name)
|
|
72
|
+
if rate is None:
|
|
73
|
+
verdict, detail = "no_data", "no denominator recorded yet"
|
|
74
|
+
elif rate > threshold:
|
|
75
|
+
verdict, detail = "warn", f"{rate} > {threshold} — {goal}"
|
|
76
|
+
else:
|
|
77
|
+
verdict, detail = "ok", f"{rate} <= {threshold}"
|
|
78
|
+
checks.append({
|
|
79
|
+
"name": name, "rate": rate, "threshold": threshold,
|
|
80
|
+
"verdict": verdict, "detail": detail,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
check("code_only_rate", code_only_warn,
|
|
84
|
+
"goal: >95% of file requests deliver real files")
|
|
85
|
+
check("needs_review_rate", needs_review_warn,
|
|
86
|
+
"goal: <30% of agent runs end NEEDS_REVIEW")
|
|
87
|
+
|
|
88
|
+
warnings = [c["name"] for c in checks if c["verdict"] == "warn"]
|
|
89
|
+
if warnings:
|
|
90
|
+
status = "warn"
|
|
91
|
+
elif all(c["verdict"] == "no_data" for c in checks):
|
|
92
|
+
status = "no_data"
|
|
93
|
+
else:
|
|
94
|
+
status = "ok"
|
|
95
|
+
return {
|
|
96
|
+
"status": status,
|
|
97
|
+
"warnings": warnings,
|
|
98
|
+
"checks": checks,
|
|
99
|
+
# Informational context — never gated.
|
|
100
|
+
"info": {
|
|
101
|
+
"real_file_rate": rates.get("real_file_rate"),
|
|
102
|
+
"approval_resume_rate": rates.get("approval_resume_rate"),
|
|
103
|
+
"ttfv_seconds": snapshot.get("ttfv_seconds"),
|
|
104
|
+
"counters": snapshot.get("counters") or {},
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def format_report(payload: Dict[str, Any]) -> str:
|
|
110
|
+
lines = [
|
|
111
|
+
f"Funnel soft gate (advisory) — {payload['path']}",
|
|
112
|
+
"=" * 72,
|
|
113
|
+
]
|
|
114
|
+
for check in payload["checks"]:
|
|
115
|
+
rate = "no data" if check["rate"] is None else str(check["rate"])
|
|
116
|
+
verdict = {"warn": "WARN", "ok": "ok", "no_data": "-"}[check["verdict"]]
|
|
117
|
+
lines.append(
|
|
118
|
+
f" {check['name']:<20} {rate:<8} {verdict:<5} {check['detail']}"
|
|
119
|
+
)
|
|
120
|
+
info = payload["info"]
|
|
121
|
+
lines.append("-" * 72)
|
|
122
|
+
lines.append(
|
|
123
|
+
f" info: real_file_rate={info['real_file_rate']} "
|
|
124
|
+
f"approval_resume_rate={info['approval_resume_rate']} "
|
|
125
|
+
f"ttfv_seconds={info['ttfv_seconds']}"
|
|
126
|
+
)
|
|
127
|
+
lines.append("=" * 72)
|
|
128
|
+
if payload["status"] == "warn":
|
|
129
|
+
mode = (
|
|
130
|
+
"STRICT — exiting 1" if payload["strict"]
|
|
131
|
+
else "advisory — exit 0; opt into enforcement with --strict"
|
|
132
|
+
)
|
|
133
|
+
lines.append(f"verdict: WARN ({', '.join(payload['warnings'])}) [{mode}]")
|
|
134
|
+
elif payload["status"] == "no_data":
|
|
135
|
+
lines.append("verdict: no data yet — nothing to grade (exit 0)")
|
|
136
|
+
else:
|
|
137
|
+
lines.append("verdict: OK — funnel rates within goals")
|
|
138
|
+
return "\n".join(lines)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def main(argv: List[str] | None = None) -> int:
|
|
142
|
+
parser = argparse.ArgumentParser(
|
|
143
|
+
description="Advisory funnel-metrics gate (warn on funnel-health regressions)"
|
|
144
|
+
)
|
|
145
|
+
parser.add_argument(
|
|
146
|
+
"--path",
|
|
147
|
+
help="metrics JSON path (default: the production data-dir funnel_metrics.json)",
|
|
148
|
+
)
|
|
149
|
+
parser.add_argument(
|
|
150
|
+
"--strict", action="store_true",
|
|
151
|
+
help="exit 1 when any WARN fired (CI opt-in; 'no data' still exits 0)",
|
|
152
|
+
)
|
|
153
|
+
parser.add_argument(
|
|
154
|
+
"--json", dest="json_out", action="store_true",
|
|
155
|
+
help="print the machine-readable verdict JSON to stdout",
|
|
156
|
+
)
|
|
157
|
+
parser.add_argument(
|
|
158
|
+
"--code-only-warn", type=float, default=CODE_ONLY_WARN_THRESHOLD,
|
|
159
|
+
help=f"code_only_rate WARN threshold (default {CODE_ONLY_WARN_THRESHOLD})",
|
|
160
|
+
)
|
|
161
|
+
parser.add_argument(
|
|
162
|
+
"--needs-review-warn", type=float, default=NEEDS_REVIEW_WARN_THRESHOLD,
|
|
163
|
+
help=f"needs_review_rate WARN threshold (default {NEEDS_REVIEW_WARN_THRESHOLD})",
|
|
164
|
+
)
|
|
165
|
+
args = parser.parse_args(argv)
|
|
166
|
+
|
|
167
|
+
path = Path(args.path) if args.path else default_metrics_path()
|
|
168
|
+
# A missing or corrupt file yields the service's zeroed state → all rates
|
|
169
|
+
# None → "no data" (never a crash, never a failure).
|
|
170
|
+
snapshot = FunnelMetricsService(path).snapshot()
|
|
171
|
+
result = evaluate_snapshot(
|
|
172
|
+
snapshot,
|
|
173
|
+
code_only_warn=args.code_only_warn,
|
|
174
|
+
needs_review_warn=args.needs_review_warn,
|
|
175
|
+
)
|
|
176
|
+
exit_code = 1 if (args.strict and result["status"] == "warn") else 0
|
|
177
|
+
payload = {
|
|
178
|
+
"mode": "funnel-soft-gate",
|
|
179
|
+
"path": str(path),
|
|
180
|
+
"strict": bool(args.strict),
|
|
181
|
+
"exit_code": exit_code,
|
|
182
|
+
**result,
|
|
183
|
+
}
|
|
184
|
+
if args.json_out:
|
|
185
|
+
print(json.dumps(payload, ensure_ascii=False, indent=2))
|
|
186
|
+
else:
|
|
187
|
+
print(format_report(payload))
|
|
188
|
+
return exit_code
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
if __name__ == "__main__":
|
|
192
|
+
raise SystemExit(main())
|
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "9.9.
|
|
2
|
+
"version": "9.9.4",
|
|
3
3
|
"generated_at": "vite",
|
|
4
4
|
"entrypoints": {
|
|
5
|
-
"app": "/static/app/assets/index-
|
|
5
|
+
"app": "/static/app/assets/index-DrmOCySv.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
|
-
"_ReviewCard-
|
|
12
|
-
"_bot-
|
|
13
|
-
"_circle-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"src/
|
|
29
|
-
"src/features/
|
|
30
|
-
"src/
|
|
31
|
-
"src/pages/
|
|
32
|
-
"src/pages/
|
|
33
|
-
"src/pages/
|
|
34
|
-
"src/pages/
|
|
9
|
+
"_BrainSignals-C52lwZVD.js": "/static/app/assets/BrainSignals-C52lwZVD.js",
|
|
10
|
+
"_LivingBrain-Jlf2wFqI.js": "/static/app/assets/LivingBrain-Jlf2wFqI.js",
|
|
11
|
+
"_ReviewCard-DWvD7n9h.js": "/static/app/assets/ReviewCard-DWvD7n9h.js",
|
|
12
|
+
"_bot-nB_buEZD.js": "/static/app/assets/bot-nB_buEZD.js",
|
|
13
|
+
"_circle-pause-DLNw6Ucp.js": "/static/app/assets/circle-pause-DLNw6Ucp.js",
|
|
14
|
+
"_circle-play-B-IsFL1y.js": "/static/app/assets/circle-play-B-IsFL1y.js",
|
|
15
|
+
"_cpu-CEPBHaBl.js": "/static/app/assets/cpu-CEPBHaBl.js",
|
|
16
|
+
"_folder-open-hmN0N9cX.js": "/static/app/assets/folder-open-hmN0N9cX.js",
|
|
17
|
+
"_hard-drive-CBV_B_Yd.js": "/static/app/assets/hard-drive-CBV_B_Yd.js",
|
|
18
|
+
"_input-gtVCg-ll.js": "/static/app/assets/input-gtVCg-ll.js",
|
|
19
|
+
"_navigation-Bot0hvuv.js": "/static/app/assets/navigation-Bot0hvuv.js",
|
|
20
|
+
"_network-jE42eKfT.js": "/static/app/assets/network-jE42eKfT.js",
|
|
21
|
+
"_primitives-CX2Komon.js": "/static/app/assets/primitives-CX2Komon.js",
|
|
22
|
+
"_shield-alert-BftATuAA.js": "/static/app/assets/shield-alert-BftATuAA.js",
|
|
23
|
+
"_textarea-CiMJfOSI.js": "/static/app/assets/textarea-CiMJfOSI.js",
|
|
24
|
+
"_useFocusTrap-B7RPGfFy.js": "/static/app/assets/useFocusTrap-B7RPGfFy.js",
|
|
25
|
+
"_utils-SJUNVOj5.js": "/static/app/assets/utils-SJUNVOj5.js",
|
|
26
|
+
"index.html": "/static/app/assets/index-DrmOCySv.js",
|
|
27
|
+
"assets/index-7FAfYm4v.css": "/static/app/assets/index-7FAfYm4v.css",
|
|
28
|
+
"src/components/ProductFlow.tsx": "/static/app/assets/ProductFlow-yg1fKP1P.js",
|
|
29
|
+
"src/features/brain/BrainHome.tsx": "/static/app/assets/BrainHome-BJ3sFNX0.js",
|
|
30
|
+
"src/features/command/CommandPalette.tsx": "/static/app/assets/CommandPalette-90u9FWFH.js",
|
|
31
|
+
"src/pages/Act.tsx": "/static/app/assets/Act-BCmTU0E2.js",
|
|
32
|
+
"src/pages/Brain.tsx": "/static/app/assets/Brain-CTnjox7w.js",
|
|
33
|
+
"src/pages/Capture.tsx": "/static/app/assets/Capture-B6vBhFa3.js",
|
|
34
|
+
"src/pages/Library.tsx": "/static/app/assets/Library-pKCK0_tk.js",
|
|
35
|
+
"src/pages/System.tsx": "/static/app/assets/System-BAEuHqNY.js"
|
|
35
36
|
}
|
|
36
37
|
}
|