ltcai 7.6.0 → 7.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +31 -34
  2. package/docs/CHANGELOG.md +19 -0
  3. package/frontend/src/App.tsx +1 -1
  4. package/frontend/src/api/client.ts +9 -2
  5. package/frontend/src/components/LivingBrain.tsx +9 -1
  6. package/frontend/src/components/ProductFlow.tsx +31 -3
  7. package/frontend/src/components/onboarding/RecommendationScreen.tsx +36 -28
  8. package/frontend/src/features/brain/BrainConversation.tsx +123 -2
  9. package/frontend/src/features/brain/BrainHome.tsx +5 -0
  10. package/frontend/src/features/review/ReviewInbox.tsx +2 -2
  11. package/frontend/src/features/review/reviewHelpers.ts +11 -11
  12. package/frontend/src/i18n.ts +121 -19
  13. package/frontend/src/pages/Act.tsx +28 -14
  14. package/frontend/src/routes.ts +6 -6
  15. package/frontend/src/styles.css +242 -0
  16. package/lattice_brain/__init__.py +1 -1
  17. package/lattice_brain/runtime/multi_agent.py +1 -1
  18. package/latticeai/__init__.py +1 -1
  19. package/latticeai/core/marketplace.py +1 -1
  20. package/latticeai/core/workspace_os.py +1 -1
  21. package/latticeai/services/architecture_readiness.py +25 -7
  22. package/latticeai/services/product_readiness.py +159 -0
  23. package/package.json +1 -1
  24. package/scripts/product_readiness.py +37 -0
  25. package/src-tauri/Cargo.lock +1 -1
  26. package/src-tauri/Cargo.toml +1 -1
  27. package/src-tauri/tauri.conf.json +1 -1
  28. package/static/app/asset-manifest.json +28 -28
  29. package/static/app/assets/Act-CX5hL0Z3.js +2 -0
  30. package/static/app/assets/{Act-CSeeIWB4.js.map → Act-CX5hL0Z3.js.map} +1 -1
  31. package/static/app/assets/{Brain-D_Ne4YoR.js → Brain-m19en5wz.js} +3 -3
  32. package/static/app/assets/{Brain-D_Ne4YoR.js.map → Brain-m19en5wz.js.map} +1 -1
  33. package/static/app/assets/Capture-CdFSrZnA.js +2 -0
  34. package/static/app/assets/Capture-CdFSrZnA.js.map +1 -0
  35. package/static/app/assets/Library-CZFVGSmG.js +2 -0
  36. package/static/app/assets/{Library-C4zmA8O2.js.map → Library-CZFVGSmG.js.map} +1 -1
  37. package/static/app/assets/System-CMoOoUrZ.js +2 -0
  38. package/static/app/assets/{System-Da-Kxwiz.js.map → System-CMoOoUrZ.js.map} +1 -1
  39. package/static/app/assets/index-B4_drWel.js +17 -0
  40. package/static/app/assets/index-B4_drWel.js.map +1 -0
  41. package/static/app/assets/index-DjpDeE0c.css +2 -0
  42. package/static/app/assets/{primitives-CSsF_Ymb.js → primitives-CFhU5Rka.js} +2 -2
  43. package/static/app/assets/{primitives-CSsF_Ymb.js.map → primitives-CFhU5Rka.js.map} +1 -1
  44. package/static/app/assets/textarea-uBpGDOJM.js +2 -0
  45. package/static/app/assets/{textarea-CJMFSyfQ.js.map → textarea-uBpGDOJM.js.map} +1 -1
  46. package/static/app/index.html +2 -2
  47. package/static/app/assets/Act-CSeeIWB4.js +0 -2
  48. package/static/app/assets/Capture-YFRAO4bJ.js +0 -2
  49. package/static/app/assets/Capture-YFRAO4bJ.js.map +0 -1
  50. package/static/app/assets/Library-C4zmA8O2.js +0 -2
  51. package/static/app/assets/System-Da-Kxwiz.js +0 -2
  52. package/static/app/assets/index-BwmCpRoW.css +0 -2
  53. package/static/app/assets/index-D1hsexMt.js +0 -17
  54. package/static/app/assets/index-D1hsexMt.js.map +0 -1
  55. package/static/app/assets/textarea-CJMFSyfQ.js +0 -2
@@ -39,10 +39,41 @@ export const COPY: Record<Language, TextMap> = {
39
39
  "brain.aria.overview": "Brain 한눈에 보기",
40
40
  "brain.aria.graph": "지식 그래프",
41
41
  "brain.title": "Lattice Brain",
42
+ "brain.edition": "정식 제품",
43
+ "brain.edition.tip": "Lattice AI 7.7 — 완성된 정식 출시 디지털 브레인",
42
44
  "brain.local": "로컬 우선",
43
45
  "brain.portable": "이동 가능",
44
46
  "brain.private": "개인 소유",
45
47
  "brain.admin": "관리자 콘솔",
48
+ "brain.command.aria": "제품 상태와 다음 행동",
49
+ "brain.command.kicker": "제품 상태판",
50
+ "brain.command.title": "지금 바로 쓸 수 있는 Brain",
51
+ "brain.command.score": "제품 준비도",
52
+ "brain.command.next": "다음 행동",
53
+ "brain.command.next.empty": "첫 자료를 넣고 바로 질문하세요.",
54
+ "brain.command.next.forming": "주제를 열어 기억이 어떻게 묶이는지 확인하세요.",
55
+ "brain.command.next.alive": "근거를 확인하고 필요하면 모델을 바꿔 보세요.",
56
+ "brain.command.metrics": "Brain 제품 지표",
57
+ "brain.command.metric.memories": "기억 {count}개",
58
+ "brain.command.metric.topics": "주제 {count}개",
59
+ "brain.command.metric.sources": "정상 출처 {count}개",
60
+ "brain.command.metric.proof": "근거 {count}개",
61
+ "brain.command.source.empty": "아직 수집 전",
62
+ "brain.command.action.add": "자료 넣기",
63
+ "brain.command.action.find": "주제 확인",
64
+ "brain.command.action.find.detail": "기억이 묶인 구조 보기",
65
+ "brain.command.action.proof": "근거 확인",
66
+ "brain.command.action.own": "소유권 관리",
67
+ "brain.command.action.own.detail": "백업, 복원, 설정",
68
+ "brain.command.signal.local": "로컬 우선",
69
+ "brain.command.signal.private": "명시 동의",
70
+ "brain.command.signal.portable": "백업 가능",
71
+ "shell.route.brain": "Lattice Brain",
72
+ "shell.route.capture": "자료",
73
+ "shell.route.memory": "그래프",
74
+ "shell.route.library": "모델",
75
+ "shell.route.system": "설정",
76
+ "shell.route.act": "실행",
46
77
  "shell.workspace.label": "작업공간 및 프로필",
47
78
  "shell.workspace.current": "현재 작업공간",
48
79
  "shell.workspace.switch": "전환",
@@ -76,9 +107,9 @@ export const COPY: Record<Language, TextMap> = {
76
107
  "brain.empty.trail.save": "1. 첫 기억 저장",
77
108
  "brain.empty.trail.recall": "2. Brain Home에서 확인",
78
109
  "brain.empty.trail.backup": "3. 백업으로 소유",
79
- "brain.prompt.remember": "이 프로젝트 목표를 기억해줘: ",
80
- "brain.prompt.know": " 문서를 내 Brain에 넣고 요약해줘: ",
81
- "brain.prompt.plan": "지난 결정들을 나중에 찾을 있게 정리해줘: ",
110
+ "brain.prompt.remember": "이 목표를 Brain이 영원히 기억하게 해줘: ",
111
+ "brain.prompt.know": "이걸 Brain에 넣고 핵심을 뽑아줘: ",
112
+ "brain.prompt.plan": "과거 결정들을 Brain이 구조화해서 나중에 쉽게 찾게 해줘: ",
82
113
  "brain.placeholder": "Brain에게 말하기...",
83
114
  "brain.upload.cta": "파일/문서 넣기",
84
115
  "brain.upload.ctaShort": "문서",
@@ -140,7 +171,7 @@ export const COPY: Record<Language, TextMap> = {
140
171
  "brain.timeline.minutesAgo": "{count}분 전",
141
172
  "brain.timeline.empty": "아직 수집 기록이 없습니다. 위에서 무엇이든 넣어보세요.",
142
173
  "brain.image": "이미지",
143
- "brain.unavailable": "지금은 답할없음",
174
+ "brain.unavailable": "지금은 응답할없습니다",
144
175
  "brain.imageAttached": "이미지 첨부됨",
145
176
  "brain.send": "보내기",
146
177
  "brain.saved": "기억에 저장됨 · 연결된 주제 {topics}개 · 관련 기억 {memories}개",
@@ -175,7 +206,7 @@ export const COPY: Record<Language, TextMap> = {
175
206
  "brain.proof.recall": "방금 Brain이 다시 꺼낸 기억",
176
207
  "brain.proof.recallEmpty.kicker": "Brain 증거 자리",
177
208
  "brain.proof.recallEmpty.title": "첫 대화 후 여기에 다시 꺼낸 기억이 표시됩니다.",
178
- "brain.proof.recallEmpty.detail": "아직 저장된 기억이 없어서 가짜 예시는 보여주지 않습니다.",
209
+ "brain.proof.recallEmpty.detail": "아직 저장된 기억이 없어, 예시를 꾸며내는 대신 실제 기억이 쌓이기를 기다립니다.",
179
210
  "brain.proof.recallPending": "기억은 저장됐고 recall 증거를 준비 중입니다.",
180
211
  "brain.proof.recallPending.detail": "인덱싱이 끝나면 이 자리에서 실제 기억을 다시 보여줍니다.",
181
212
  "brain.modelDemo.aria": "모델 교체 증거",
@@ -330,6 +361,26 @@ export const COPY: Record<Language, TextMap> = {
330
361
  "review.dismiss": "기각",
331
362
  "review.feedback.open": "승인 또는 기각 전까지 항목은 열린 상태로 유지됩니다.",
332
363
  "review.action.failed": "{action} 실패",
364
+ "review.filter.status.pending": "대기",
365
+ "review.filter.status.snoozed": "일시 중지",
366
+ "review.filter.status.all": "전체",
367
+ "review.filter.status.approved": "승인됨",
368
+ "review.filter.status.dismissed": "기각됨",
369
+ "review.filter.source.all": "전체 출처",
370
+ "review.filter.source.workflow_run": "워크플로",
371
+ "review.filter.source.trigger": "트리거",
372
+ "review.filter.source.kg_change_digest": "KG 요약",
373
+ "act.kicker": "자동화",
374
+ "act.title": "중요한 변경은 검토하면서 일을 진행합니다.",
375
+ "act.copy": "목표를 맡기고, 각 실행 결과를 확인한 뒤 민감한 작업만 명시적으로 승인하세요.",
376
+ "act.tab.goals": "목표",
377
+ "act.tab.runs": "실행",
378
+ "act.tab.review": "검토함",
379
+ "act.tab.recipes": "레시피",
380
+ "act.tab.safeguards": "보호 장치",
381
+ "act.tab.permissions": "권한",
382
+ "act.tab.hooks": "훅",
383
+ "act.tab.tools": "도구",
333
384
  "admin.back": "Brain",
334
385
  "admin.aria.console": "Lattice 관리자",
335
386
  "admin.kicker": "분리된 관리자 작업공간",
@@ -470,16 +521,16 @@ export const COPY: Record<Language, TextMap> = {
470
521
  "flow.install.expectedCompletion": "끝나면 바로 Brain이 열립니다.",
471
522
  "flow.shell": "내 로컬 AI 브레인 만들기",
472
523
  "flow.wake.aria": "Brain 깨우기",
473
- "flow.wake.title": " Brain을 깨웁니다.",
474
- "flow.wake.body": " Brain은 컴퓨터에 살고, 모델은 목소리처럼 바꿔도 기억과 지식 그래프는 계속 남습니다.",
524
+ "flow.wake.title": "당신의 지식이 영원히 살아 숨쉬는 Brain을 지금 시작하세요.",
525
+ "flow.wake.body": "대화할수록 똑똑해지는 당신만의 AI. 모델 바꿔도 기억은 영원히. 로컬, 직관적, 강력. 처음 보는 순간 쓰고 싶어지는 Brain을 시작하세요.",
475
526
  "flow.wake.plan.aria": "Brain 시작 단계",
476
527
  "flow.wake.step.identity": "주인 확인",
477
528
  "flow.wake.step.check": "컴퓨터 확인",
478
529
  "flow.wake.step.voice": "목소리 선택",
479
- "flow.wake.primary": "Brain 깨우기",
480
- "flow.wake.existing": "이미 있는 Brain 열기",
481
- "flow.login.title": " AI 브레인의 주인을 정합니다.",
482
- "flow.login.body": "Lattice AI는 내 지식과 맥락을 이 컴퓨터에 보관하는 로컬 우선 AI 브레인입니다. 모델은 바꿀 있고, 외부 전송은 사용자가 선택할 때만 시작됩니다.",
530
+ "flow.wake.primary": "Brain 지금 깨우기",
531
+ "flow.wake.existing": "기존 Brain 열기",
532
+ "flow.login.title": " Brain의 주인은 바로 당신입니다.",
533
+ "flow.login.body": "이 컴퓨터에 사는, 당신만의 영원한 지식 Brain. 3단계로 직관적으로 시작. 모델은 나중에 바꿔도 모든 것이 그대로입니다.",
483
534
  "flow.name": "이름",
484
535
  "flow.name.placeholder": "나",
485
536
  "flow.email": "이메일",
@@ -500,8 +551,8 @@ export const COPY: Record<Language, TextMap> = {
500
551
  "flow.promise.ownership.k": "사용자 소유",
501
552
  "flow.promise.ownership.v": "백업, 복원, 이동을 직접 결정합니다.",
502
553
  "flow.promise.aria": "Lattice AI 제품 약속",
503
- "flow.analysis.title": "이 컴퓨터에서 가능한 경험을 확인합니다.",
504
- "flow.analysis.body": "스펙 점수가 아니라, Mac에서 어떤 로컬 AI 브레인 경험이 편한지 알려드립니다. 확인은 로컬 상태를 읽는 것이고, 클라우드 모델은 선택 사항입니다.",
554
+ "flow.analysis.title": "이 컴퓨터에서 가장 자연스럽고 강력한 Brain 경험을 확인합니다.",
555
+ "flow.analysis.body": "스펙이 아니라, 당신의 Mac에서 즉시 직관적으로 쓸 수 있는 로컬 AI 브레인 수준을 보여드립니다. 로컬 상태만 읽고, 클라우드는 선택입니다. 바로 쓰고 싶어지게 준비됐습니다.",
505
556
  "flow.analysis.finding": "가장 편한 설정을 찾는 중...",
506
557
  "flow.analysis.ready": "추천 모델을 바로 시작할 수 있게 준비했습니다.",
507
558
  "flow.analysis.wait": "잠시만 기다리면 자동으로 정리됩니다.",
@@ -512,18 +563,18 @@ export const COPY: Record<Language, TextMap> = {
512
563
  "flow.analysis.os.windows": "Windows PC",
513
564
  "flow.analysis.os.linux": "Linux 컴퓨터",
514
565
  "flow.recommend.title": "추천대로 시작하세요.",
515
- "flow.recommend.body": "모델은 Brain의 현재 목소리입니다. 가장 안전한 추천, 빠른 모델, 강한 모델만 먼저 보여드립니다.",
516
- "flow.recommend.primary": "추천대로 시작하기",
566
+ "flow.recommend.body": "모델은 Brain의 목소리일 뿐. 가장 직관적이고 빠른 시작을 위한 추천, 빠른 모델, 강력한 모델을 먼저 보여드립니다. 선택하면 바로 대화가 시작됩니다.",
567
+ "flow.recommend.primary": "추천으로 바로 시작",
517
568
  "flow.recommend.unsupported": "이 컴퓨터에서 추가 확인이 필요합니다",
518
569
  "flow.recommend.back": "뒤로",
519
570
  "flow.recommend.skip": "모델 없이 Brain 열기",
520
- "flow.recommend.hint": " 모르겠다면 추천대로 시작하면 됩니다.",
571
+ "flow.recommend.hint": "추천을 선택하면 가장 부드럽고 직관적인 경험이 시작됩니다.",
521
572
  "flow.recommend.rank.best": "추천",
522
573
  "flow.recommend.rank.faster": "빠른 선택",
523
574
  "flow.recommend.rank.advanced": "고급 선택",
524
575
  "flow.recommend.rank.choice": "선택 {index}",
525
576
  "flow.install.title": "모델을 설치하고 시작합니다.",
526
- "flow.install.body": "이 모델이 Brain의 로컬 목소리가 됩니다. 인터넷은 다운로드할 때만 필요하고, 실행과 기억은 컴퓨터에서 유지됩니다.",
577
+ "flow.install.body": "이 모델이 당신 Brain의 로컬 목소리가 됩니다. 다운로드는 번뿐, 모든 대화와 기억은 완전 로컬. 직관적이고 강력한 경험을 바로 느껴보세요.",
527
578
  "flow.install.wait": "Brain이 사용할 모델을 기다리고 있습니다.",
528
579
  "flow.install.prepare": "Brain 준비 중입니다.",
529
580
  "flow.install.done": "Brain이 준비되었습니다.",
@@ -612,10 +663,41 @@ export const COPY: Record<Language, TextMap> = {
612
663
  "brain.aria.overview": "Brain overview",
613
664
  "brain.aria.graph": "Knowledge Graph",
614
665
  "brain.title": "Lattice Brain",
666
+ "brain.edition": "Production Ready",
667
+ "brain.edition.tip": "Lattice AI 7.7 — your finished, production-ready Digital Brain",
615
668
  "brain.local": "Local-first",
616
669
  "brain.portable": "Portable",
617
670
  "brain.private": "Private",
618
671
  "brain.admin": "Admin Console",
672
+ "brain.command.aria": "Product status and next action",
673
+ "brain.command.kicker": "Product command center",
674
+ "brain.command.title": "A Brain ready to use now",
675
+ "brain.command.score": "Product readiness",
676
+ "brain.command.next": "Next action",
677
+ "brain.command.next.empty": "Add a first source, then ask immediately.",
678
+ "brain.command.next.forming": "Open topics to see how memories are grouping.",
679
+ "brain.command.next.alive": "Verify proof, then switch models when useful.",
680
+ "brain.command.metrics": "Brain product metrics",
681
+ "brain.command.metric.memories": "{count} memories",
682
+ "brain.command.metric.topics": "{count} topics",
683
+ "brain.command.metric.sources": "{count} healthy sources",
684
+ "brain.command.metric.proof": "{count} proof points",
685
+ "brain.command.source.empty": "No ingestion yet",
686
+ "brain.command.action.add": "Add source",
687
+ "brain.command.action.find": "Inspect topics",
688
+ "brain.command.action.find.detail": "See grouped memory structure",
689
+ "brain.command.action.proof": "Verify proof",
690
+ "brain.command.action.own": "Manage ownership",
691
+ "brain.command.action.own.detail": "Backup, restore, settings",
692
+ "brain.command.signal.local": "Local-first",
693
+ "brain.command.signal.private": "Consent gated",
694
+ "brain.command.signal.portable": "Backup ready",
695
+ "shell.route.brain": "Lattice Brain",
696
+ "shell.route.capture": "Files",
697
+ "shell.route.memory": "Graph",
698
+ "shell.route.library": "Models",
699
+ "shell.route.system": "Settings",
700
+ "shell.route.act": "Act",
619
701
  "shell.workspace.label": "Workspace and profile",
620
702
  "shell.workspace.current": "Current workspace",
621
703
  "shell.workspace.switch": "Switch",
@@ -713,7 +795,7 @@ export const COPY: Record<Language, TextMap> = {
713
795
  "brain.timeline.minutesAgo": "{count}m ago",
714
796
  "brain.timeline.empty": "No ingestion yet. Add anything above to begin.",
715
797
  "brain.image": "Image",
716
- "brain.unavailable": "Unavailable",
798
+ "brain.unavailable": "Temporarily unavailable",
717
799
  "brain.imageAttached": "Image attached",
718
800
  "brain.send": "Send",
719
801
  "brain.saved": "Saved to memory · {topics} linked topics · {memories} related memories",
@@ -748,7 +830,7 @@ export const COPY: Record<Language, TextMap> = {
748
830
  "brain.proof.recall": "Just recalled by Brain",
749
831
  "brain.proof.recallEmpty.kicker": "Brain proof slot",
750
832
  "brain.proof.recallEmpty.title": "After your first exchange, recalled memory appears here.",
751
- "brain.proof.recallEmpty.detail": "No saved memory yet, so Lattice does not show a fake example.",
833
+ "brain.proof.recallEmpty.detail": "No saved memory yet Lattice waits for real memory instead of inventing a placeholder example.",
752
834
  "brain.proof.recallPending": "Memory is saved; recall proof is preparing.",
753
835
  "brain.proof.recallPending.detail": "When indexing finishes, this slot shows the actual memory Brain can bring back.",
754
836
  "brain.modelDemo.aria": "Model switch proof",
@@ -903,6 +985,26 @@ export const COPY: Record<Language, TextMap> = {
903
985
  "review.dismiss": "Dismiss",
904
986
  "review.feedback.open": "item stays open until you approve or dismiss.",
905
987
  "review.action.failed": "{action} failed",
988
+ "review.filter.status.pending": "Pending",
989
+ "review.filter.status.snoozed": "Snoozed",
990
+ "review.filter.status.all": "All",
991
+ "review.filter.status.approved": "Approved",
992
+ "review.filter.status.dismissed": "Dismissed",
993
+ "review.filter.source.all": "All sources",
994
+ "review.filter.source.workflow_run": "Workflow",
995
+ "review.filter.source.trigger": "Trigger",
996
+ "review.filter.source.kg_change_digest": "KG digest",
997
+ "act.kicker": "Automate",
998
+ "act.title": "Make work move, with a hand on the door.",
999
+ "act.copy": "Give Lattice a goal, review each run, and approve sensitive actions before anything important changes.",
1000
+ "act.tab.goals": "Goals",
1001
+ "act.tab.runs": "Runs",
1002
+ "act.tab.review": "Review Center",
1003
+ "act.tab.recipes": "Recipes",
1004
+ "act.tab.safeguards": "Safeguards",
1005
+ "act.tab.permissions": "Permissions",
1006
+ "act.tab.hooks": "Hooks",
1007
+ "act.tab.tools": "Tools",
906
1008
  "admin.back": "Brain",
907
1009
  "admin.aria.console": "Lattice Admin",
908
1010
  "admin.kicker": "Separate admin workspace",
@@ -12,25 +12,27 @@ import { Textarea } from "@/components/ui/textarea";
12
12
  import { ReviewInbox } from "@/features/review/ReviewInbox";
13
13
  import { useAppStore } from "@/store/appStore";
14
14
  import { asArray, shortId } from "@/lib/utils";
15
+ import { t } from "@/i18n";
15
16
 
16
17
  type ActTab = "agents" | "runs" | "workflows" | "hooks" | "tools";
17
18
  type RunsSubTab = "runs" | "review";
18
19
 
19
- const runsSubTabs: Array<{ id: RunsSubTab; label: string }> = [
20
- { id: "runs", label: "Runs" },
21
- { id: "review", label: "Review Center" },
20
+ const runsSubTabs: Array<{ id: RunsSubTab; labelKey: string }> = [
21
+ { id: "runs", labelKey: "act.tab.runs" },
22
+ { id: "review", labelKey: "act.tab.review" },
22
23
  ];
23
24
 
24
- const tabs: Array<{ id: ActTab; label: string }> = [
25
- { id: "agents", label: "Goals" },
26
- { id: "runs", label: "Runs" },
27
- { id: "workflows", label: "Recipes" },
28
- { id: "hooks", label: "Safeguards" },
29
- { id: "tools", label: "Permissions" },
25
+ const tabs: Array<{ id: ActTab; labelKey: string; advancedLabelKey?: string }> = [
26
+ { id: "agents", labelKey: "act.tab.goals" },
27
+ { id: "runs", labelKey: "act.tab.runs" },
28
+ { id: "workflows", labelKey: "act.tab.recipes" },
29
+ { id: "hooks", labelKey: "act.tab.safeguards", advancedLabelKey: "act.tab.hooks" },
30
+ { id: "tools", labelKey: "act.tab.permissions", advancedLabelKey: "act.tab.tools" },
30
31
  ];
31
32
 
32
33
  export function ActPage({ initialTab }: { initialTab?: string }) {
33
34
  const mode = useAppStore((state) => state.mode);
35
+ const language = useAppStore((state) => state.language);
34
36
  const [tab, setTab] = React.useState<ActTab>(() => {
35
37
  if (initialTab === "review") return "runs";
36
38
  return (initialTab as ActTab) || "agents";
@@ -47,11 +49,18 @@ export function ActPage({ initialTab }: { initialTab?: string }) {
47
49
  return (
48
50
  <div className="space-y-5">
49
51
  <header className="page-hero">
50
- <div className="page-kicker"><Workflow className="h-4 w-4" /> Automate</div>
51
- <h1 className="page-title">Make work move, with a hand on the door.</h1>
52
- <p className="page-copy">Give Lattice a goal, review each run, and approve sensitive actions before anything important changes.</p>
52
+ <div className="page-kicker"><Workflow className="h-4 w-4" /> {t(language, "act.kicker")}</div>
53
+ <h1 className="page-title">{t(language, "act.title")}</h1>
54
+ <p className="page-copy">{t(language, "act.copy")}</p>
53
55
  </header>
54
- <Tabs tabs={tabs.map((item) => mode === "basic" ? item : item.id === "hooks" ? { ...item, label: "Hooks" } : item.id === "tools" ? { ...item, label: "Tools" } : item)} value={tab} onChange={(id) => setTab(id as ActTab)} />
56
+ <Tabs
57
+ tabs={tabs.map((item) => ({
58
+ id: item.id,
59
+ label: t(language, mode === "basic" || !item.advancedLabelKey ? item.labelKey : item.advancedLabelKey),
60
+ }))}
61
+ value={tab}
62
+ onChange={(id) => setTab(id as ActTab)}
63
+ />
55
64
  {tab === "agents" ? <AgentsPanel /> : null}
56
65
  {tab === "runs" ? <RunsPanel subTab={runsSubTab} onSubTabChange={setRunsSubTab} /> : null}
57
66
  {tab === "workflows" ? <WorkflowsPanel /> : null}
@@ -140,9 +149,14 @@ function AgentsPanel() {
140
149
  }
141
150
 
142
151
  function RunsPanel({ subTab, onSubTabChange }: { subTab: RunsSubTab; onSubTabChange: (tab: RunsSubTab) => void }) {
152
+ const language = useAppStore((state) => state.language);
143
153
  return (
144
154
  <div className="space-y-4">
145
- <Tabs tabs={runsSubTabs} value={subTab} onChange={(id) => onSubTabChange(id as RunsSubTab)} />
155
+ <Tabs
156
+ tabs={runsSubTabs.map((item) => ({ id: item.id, label: t(language, item.labelKey) }))}
157
+ value={subTab}
158
+ onChange={(id) => onSubTabChange(id as RunsSubTab)}
159
+ />
146
160
  {subTab === "runs" ? <RunsListPanel /> : <ReviewInbox />}
147
161
  </div>
148
162
  );
@@ -12,12 +12,12 @@ export type PrimaryRoute = "brain" | "memory" | "capture" | "act" | "library" |
12
12
  export type RouteTarget = { primary: PrimaryRoute; tab?: string };
13
13
 
14
14
  export const productShellRoutes = [
15
- { id: "brain", path: "brain", label: "Lattice Brain", icon: Brain, description: "Talk with your living Brain" },
16
- { id: "capture", path: "capture", label: "Files", icon: FolderInput, description: "Bring in files, folders, and pages" },
17
- { id: "memory", path: "knowledge-graph", label: "Graph", icon: Database, description: "Search and inspect Brain knowledge" },
18
- { id: "library", path: "models", label: "Models", icon: Library, description: "Choose the local model powering your Brain" },
19
- { id: "system", path: "settings", label: "Settings", icon: Settings, description: "Keep your Brain safe and portable" },
20
- { id: "act", path: "review", label: "Act", icon: Workflow, description: "Turn goals into supervised runs" },
15
+ { id: "brain", path: "brain", labelKey: "shell.route.brain", icon: Brain, description: "Talk with your living Brain" },
16
+ { id: "capture", path: "capture", labelKey: "shell.route.capture", icon: FolderInput, description: "Bring in files, folders, and pages" },
17
+ { id: "memory", path: "knowledge-graph", labelKey: "shell.route.memory", icon: Database, description: "Search and inspect Brain knowledge" },
18
+ { id: "library", path: "models", labelKey: "shell.route.library", icon: Library, description: "Choose the local model powering your Brain" },
19
+ { id: "system", path: "settings", labelKey: "shell.route.system", icon: Settings, description: "Keep your Brain safe and portable" },
20
+ { id: "act", path: "review", labelKey: "shell.route.act", icon: Workflow, description: "Turn goals into supervised runs" },
21
21
  ] as const;
22
22
 
23
23
  export const directProductRoutes: Record<string, RouteTarget> = {
@@ -1423,6 +1423,206 @@ body {
1423
1423
  mask-image: linear-gradient(transparent, black 6%, black 92%, transparent);
1424
1424
  }
1425
1425
 
1426
+ .brain-edition-badge,
1427
+ .ritual-edition {
1428
+ display: inline-flex;
1429
+ align-items: center;
1430
+ min-height: 1.35rem;
1431
+ border: 1px solid hsl(var(--brain-core) / 0.42);
1432
+ border-radius: 999px;
1433
+ background: hsl(var(--brain-core) / 0.1);
1434
+ color: hsl(var(--fg));
1435
+ padding: 0 0.48rem;
1436
+ font-size: 0.62rem;
1437
+ font-weight: 820;
1438
+ letter-spacing: 0;
1439
+ white-space: nowrap;
1440
+ }
1441
+
1442
+ .brain-edition-badge {
1443
+ margin-left: 0.45rem;
1444
+ vertical-align: middle;
1445
+ }
1446
+
1447
+ .ritual-edition {
1448
+ position: absolute;
1449
+ right: 50%;
1450
+ bottom: 0.35rem;
1451
+ transform: translateX(50%);
1452
+ background: hsl(var(--surface-glass));
1453
+ box-shadow: 0 10px 24px hsl(200 30% 3% / 0.18);
1454
+ }
1455
+
1456
+ .brain-command-center {
1457
+ display: grid;
1458
+ gap: 0.72rem;
1459
+ margin: 0 0 0.85rem;
1460
+ border: 1px solid hsl(var(--brain-core) / 0.36);
1461
+ border-radius: 8px;
1462
+ background: linear-gradient(135deg, hsl(var(--surface-glass)), hsl(var(--brain-core) / 0.07));
1463
+ padding: 0.82rem;
1464
+ box-shadow: 0 14px 34px hsl(200 30% 3% / 0.16);
1465
+ backdrop-filter: blur(18px);
1466
+ }
1467
+
1468
+ .brain-command-head,
1469
+ .brain-command-next,
1470
+ .brain-command-metrics,
1471
+ .brain-command-signals {
1472
+ display: flex;
1473
+ align-items: center;
1474
+ gap: 0.55rem;
1475
+ }
1476
+
1477
+ .brain-command-head {
1478
+ justify-content: space-between;
1479
+ }
1480
+
1481
+ .brain-command-head span,
1482
+ .brain-command-next span,
1483
+ .brain-command-score span {
1484
+ display: block;
1485
+ color: hsl(var(--fg-muted));
1486
+ font-size: 0.64rem;
1487
+ font-weight: 840;
1488
+ text-transform: uppercase;
1489
+ }
1490
+
1491
+ .brain-command-head strong {
1492
+ display: block;
1493
+ margin-top: 0.12rem;
1494
+ font-size: 0.98rem;
1495
+ }
1496
+
1497
+ .brain-command-score {
1498
+ display: grid;
1499
+ justify-items: end;
1500
+ min-width: 5.9rem;
1501
+ }
1502
+
1503
+ .brain-command-score strong {
1504
+ color: hsl(var(--brain-core));
1505
+ font-size: 1.45rem;
1506
+ line-height: 1;
1507
+ }
1508
+
1509
+ .brain-command-next {
1510
+ min-height: 2.35rem;
1511
+ border: 1px solid hsl(var(--border) / 0.54);
1512
+ border-radius: 8px;
1513
+ background: hsl(var(--bg) / 0.34);
1514
+ padding: 0.5rem 0.58rem;
1515
+ }
1516
+
1517
+ .brain-command-next svg {
1518
+ color: hsl(var(--brain-core));
1519
+ }
1520
+
1521
+ .brain-command-next strong {
1522
+ min-width: 0;
1523
+ color: hsl(var(--fg));
1524
+ font-size: 0.82rem;
1525
+ line-height: 1.25;
1526
+ }
1527
+
1528
+ .brain-command-metrics {
1529
+ flex-wrap: wrap;
1530
+ }
1531
+
1532
+ .brain-command-metrics span,
1533
+ .brain-command-signals span {
1534
+ display: inline-flex;
1535
+ align-items: center;
1536
+ gap: 0.28rem;
1537
+ min-height: 1.65rem;
1538
+ border: 1px solid hsl(var(--border) / 0.5);
1539
+ border-radius: 999px;
1540
+ background: hsl(var(--surface) / 0.6);
1541
+ color: hsl(var(--fg-muted));
1542
+ padding: 0 0.5rem;
1543
+ font-size: 0.68rem;
1544
+ font-weight: 760;
1545
+ }
1546
+
1547
+ .brain-command-actions {
1548
+ display: grid;
1549
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1550
+ gap: 0.5rem;
1551
+ }
1552
+
1553
+ .brain-command-actions button {
1554
+ display: grid;
1555
+ min-height: 5.1rem;
1556
+ align-content: start;
1557
+ gap: 0.28rem;
1558
+ border: 1px solid hsl(var(--border) / 0.55);
1559
+ border-radius: 8px;
1560
+ background: hsl(var(--surface) / 0.64);
1561
+ color: hsl(var(--fg));
1562
+ padding: 0.58rem;
1563
+ text-align: left;
1564
+ transition: border-color 150ms ease, background 150ms ease, transform 150ms ease;
1565
+ }
1566
+
1567
+ .brain-command-actions button:hover,
1568
+ .brain-command-actions button:focus-visible {
1569
+ border-color: hsl(var(--brain-core) / 0.66);
1570
+ background: hsl(var(--brain-core) / 0.08);
1571
+ outline: none;
1572
+ transform: translateY(-1px);
1573
+ }
1574
+
1575
+ .brain-command-actions svg {
1576
+ color: hsl(var(--brain-core));
1577
+ }
1578
+
1579
+ .brain-command-actions span {
1580
+ font-size: 0.78rem;
1581
+ font-weight: 820;
1582
+ line-height: 1.18;
1583
+ }
1584
+
1585
+ .brain-command-actions small {
1586
+ overflow: hidden;
1587
+ color: hsl(var(--fg-muted));
1588
+ font-size: 0.68rem;
1589
+ line-height: 1.2;
1590
+ text-overflow: ellipsis;
1591
+ }
1592
+
1593
+ .brain-command-signals {
1594
+ flex-wrap: wrap;
1595
+ }
1596
+
1597
+ .brain-command-signals svg {
1598
+ color: hsl(var(--success));
1599
+ }
1600
+
1601
+ @media (max-width: 760px) {
1602
+ .brain-command-head,
1603
+ .brain-command-next {
1604
+ align-items: flex-start;
1605
+ }
1606
+
1607
+ .brain-command-head {
1608
+ flex-direction: column;
1609
+ }
1610
+
1611
+ .brain-command-score {
1612
+ justify-items: start;
1613
+ }
1614
+
1615
+ .brain-command-actions {
1616
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1617
+ }
1618
+ }
1619
+
1620
+ @media (max-width: 460px) {
1621
+ .brain-command-actions {
1622
+ grid-template-columns: 1fr;
1623
+ }
1624
+ }
1625
+
1426
1626
  .brain-ingestion-panel {
1427
1627
  margin: 0 0 0.85rem;
1428
1628
  border: 1px solid hsl(var(--memory) / 0.34);
@@ -3686,6 +3886,7 @@ body {
3686
3886
  }
3687
3887
 
3688
3888
  .ritual-brain {
3889
+ position: relative;
3689
3890
  margin: 1.4rem auto 1.6rem;
3690
3891
  }
3691
3892
 
@@ -6009,4 +6210,45 @@ body {
6009
6210
  left: 50%;
6010
6211
  transform: translateX(-50%);
6011
6212
  }
6213
+
6214
+ /* Stronger first-impression UX polish for intuitive "want to use" */
6215
+ .ritual-value-grid > div {
6216
+ transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease;
6217
+ }
6218
+ .ritual-value-grid > div:hover {
6219
+ transform: translateY(-2px);
6220
+ border-color: hsl(var(--brain-core) / 0.65);
6221
+ box-shadow: 0 4px 14px hsl(var(--brain-core) / 0.08);
6222
+ }
6223
+ .ritual-full-button {
6224
+ background: linear-gradient(90deg, hsl(var(--brain-core)), hsl(var(--accent)));
6225
+ color: hsl(var(--bg));
6226
+ border: none;
6227
+ border-radius: 999px;
6228
+ font-weight: 700;
6229
+ padding: 0.75rem 1.8rem;
6230
+ box-shadow: 0 2px 8px hsl(var(--brain-core) / 0.35);
6231
+ transition: transform 120ms ease, box-shadow 120ms ease;
6232
+ }
6233
+ .ritual-full-button:hover {
6234
+ transform: translateY(-1px) scale(1.01);
6235
+ box-shadow: 0 6px 18px hsl(var(--brain-core) / 0.45);
6236
+ }
6237
+ .ritual-model-card {
6238
+ position: relative;
6239
+ overflow: hidden;
6240
+ }
6241
+ .ritual-model-card::after {
6242
+ content: "";
6243
+ position: absolute;
6244
+ top: -50%;
6245
+ left: -100%;
6246
+ width: 40%;
6247
+ height: 200%;
6248
+ background: linear-gradient(120deg, transparent, hsl(var(--brain-core)/0.12), transparent);
6249
+ transition: left 420ms ease;
6250
+ }
6251
+ .ritual-model-card:hover::after {
6252
+ left: 250%;
6253
+ }
6012
6254
  }
@@ -26,7 +26,7 @@ from .storage import (
26
26
  storage_from_env,
27
27
  )
28
28
 
29
- __version__ = "7.6.0"
29
+ __version__ = "7.7.0"
30
30
 
31
31
  __all__ = [
32
32
  "AgentRuntime",
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, List, Optional
21
21
  from .contracts import multi_agent_contract
22
22
 
23
23
 
24
- MULTI_AGENT_VERSION = "7.6.0"
24
+ MULTI_AGENT_VERSION = "7.7.0"
25
25
 
26
26
  AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
27
27
  CORE_PIPELINE = ("planner", "executor", "reviewer")
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "7.6.0"
3
+ __version__ = "7.7.0"
@@ -11,7 +11,7 @@ from copy import deepcopy
11
11
  from typing import Any, Dict, List, Optional
12
12
 
13
13
 
14
- MARKETPLACE_VERSION = "7.6.0"
14
+ MARKETPLACE_VERSION = "7.7.0"
15
15
  TEMPLATE_KINDS = ("plugin", "workflow", "agent")
16
16
 
17
17
 
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, Iterable, List, Optional
21
21
  from lattice_brain.runtime.contracts import realtime_event_contract, run_record_contract, workflow_run_contract
22
22
 
23
23
 
24
- WORKSPACE_OS_VERSION = "7.6.0"
24
+ WORKSPACE_OS_VERSION = "7.7.0"
25
25
 
26
26
  # Workspace types separate single-user Personal workspaces from shared
27
27
  # Organization workspaces. Both keep the same local-first JSON store; the type