From b03542883971550c3014fde70ab662c165a94ad3 Mon Sep 17 00:00:00 2001 From: ymote <151983+ymote@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:47:40 -0700 Subject: [PATCH 1/5] native-apps: host Sheets and Reference in-process everywhere [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR 0004 §2: the Terminal is the only process app for now, and Linux without Vulkan and Wayland runs every app in-process. The opt-in Sheets and Reference were declared plain `process` on macOS, Windows and Linux. Declare them `module` on every target, and make tools/native_apps.py refuse plain `process` on Linux (`process-if-vulkan` only). Co-Authored-By: Claude Opus 5.5 --- crates/shell/src/apps.rs | 7 +++---- crates/shell/src/native_apps.rs | 12 ++++++------ desktop/README.md | 2 +- desktop/README.zh-CN.md | 2 +- docs/architecture.md | 8 ++++---- docs/architecture.zh-CN.md | 8 ++++---- native-apps.json | 4 ++-- tools/native_apps.py | 13 +++++++++---- tools/test_native_apps.py | 9 ++++++++- 9 files changed, 38 insertions(+), 27 deletions(-) diff --git a/crates/shell/src/apps.rs b/crates/shell/src/apps.rs index 9d4d0b4a..23e550af 100644 --- a/crates/shell/src/apps.rs +++ b/crates/shell/src/apps.rs @@ -622,8 +622,8 @@ mod tests { assert_eq!(manifest_default(Declared::Process, || false, true), Hosting::Module, "no binary: in-process"); assert_eq!(manifest_default(Declared::ProcessIfVulkan, || true, false), Hosting::Module, "OpenGL or X11"); assert_eq!(manifest_default(Declared::ProcessIfVulkan, || true, true), Hosting::Process); - // App Hub and Rinx stay in-process everywhere (ADR 0004 §2). - for id in ["apphub", "rinx"] { + // Every app but the Terminal stays in-process everywhere (ADR 0004 §2). + for id in ["apphub", "rinx", "sheets", "reference", "appcard"] { let app = crate::native_apps::find(id).unwrap(); assert_eq!(manifest_default(app.on_this_target(), || true, true), Hosting::Module, "{id}"); } @@ -650,8 +650,7 @@ mod tests { assert_eq!(registry.hosting("sheets"), Hosting::Module); assert!(registry.linked_ids().contains(&"sheets")); let plain = AppRegistry::default(); - let expected = if process_form("sheets") { Hosting::Process } else { Hosting::Module }; - assert_eq!(plain.hosting("sheets"), expected, "desktop default is a process where it can start"); + assert_eq!(plain.hosting("sheets"), Hosting::Module, "Terminal is the only process app for now (ADR 0004 §2)"); } } diff --git a/crates/shell/src/native_apps.rs b/crates/shell/src/native_apps.rs index d0df11fe..1b05f1aa 100644 --- a/crates/shell/src/native_apps.rs +++ b/crates/shell/src/native_apps.rs @@ -78,9 +78,9 @@ pub const APPS: &[NativeApp] = &[ id: "reference", feature: "app-reference", bin: Some("octosense-reference"), - macos: Hosting::Process, - windows: Hosting::Process, - linux: Hosting::Process, + macos: Hosting::Module, + windows: Hosting::Module, + linux: Hosting::Module, android: Hosting::Module, ios: Hosting::Module, ohos: Hosting::Module, @@ -92,9 +92,9 @@ pub const APPS: &[NativeApp] = &[ id: "sheets", feature: "app-sheets", bin: Some("sheets"), - macos: Hosting::Process, - windows: Hosting::Process, - linux: Hosting::Process, + macos: Hosting::Module, + windows: Hosting::Module, + linux: Hosting::Module, android: Hosting::Module, ios: Hosting::Module, ohos: Hosting::Module, diff --git a/desktop/README.md b/desktop/README.md index 9db52004..08c6e213 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -89,7 +89,7 @@ The native apps' features (`app-hub`, `app-rinx`, `app-reference`, `app-sheets`, | `app-aichat` | off | Links Makepad's AI chat as a module, without its model engine. | | `mobile-apps` | off | `app-rinx` + `app-reference` + `app-sheets` + `app-hub` + `octos-core`: the set phone builds link, for testing on desktop. Not AppCard. | -A linked native app is hosted as its `hosting` in `native-apps.json` says for the platform: App Hub, Rinx and AppCard in-process everywhere, the Terminal as a process on macOS and Windows, Reference and Sheets as processes on the desktop. `--module ` (or a `: Module` line in `wm/apps.splash` under the state directory) opens one in-process instead: +A linked native app is hosted as its `hosting` in `native-apps.json` says for the platform: App Hub, Rinx and AppCard in-process everywhere, Reference and Sheets in-process everywhere, the Terminal as a process on macOS and Windows (and on Linux with a Vulkan build in a Wayland session). `--module ` (or a `: Module` line in `wm/apps.splash` under the state directory) opens one in-process instead: ```sh cargo run --release -p octosense --features mobile-apps -- --module reference --module sheets diff --git a/desktop/README.zh-CN.md b/desktop/README.zh-CN.md index 94a6e73e..b1d46212 100644 --- a/desktop/README.zh-CN.md +++ b/desktop/README.zh-CN.md @@ -89,7 +89,7 @@ cargo run --release -p octosense | `app-aichat` | 关 | 以模块形式链接 Makepad 的 AI chat,不含其模型引擎。 | | `mobile-apps` | 关 | `app-rinx` + `app-reference` + `app-sheets` + `app-hub` + `octos-core`:手机构建所链接的集合,用于在桌面上测试。不含 AppCard。 | -已链接的原生应用按照 `native-apps.json` 中该平台的 `hosting` 托管:App Hub、Rinx 和 AppCard 在所有平台上都在进程内运行,Terminal 在 macOS 和 Windows 上作为独立进程运行,Reference 和 Sheets 在桌面端作为独立进程运行。用 `--module `(或在状态目录下的 `wm/apps.splash` 中写一行 `: Module`)可改为在进程内打开: +已链接的原生应用按照 `native-apps.json` 中该平台的 `hosting` 托管:App Hub、Rinx、AppCard、Reference 和 Sheets 在所有平台上都在进程内运行,Terminal 在 macOS 和 Windows 上(以及 Vulkan 构建且处于 Wayland 会话的 Linux 上)作为独立进程运行。用 `--module `(或在状态目录下的 `wm/apps.splash` 中写一行 `: Module`)可改为在进程内打开: ```sh cargo run --release -p octosense --features mobile-apps -- --module reference --module sheets diff --git a/docs/architecture.md b/docs/architecture.md index b4d0a30c..2c2a3f91 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -39,7 +39,7 @@ flowchart LR aihost["ai-host + app-peers broker
host connection to the kernel"] bus["AI services bus
crates/shell/src/ai_bus.rs"] end - term["Process apps (desktop)
Terminal; opt-in Sheets, Reference"] + term["Process app (desktop)
Terminal"] subgraph kern["octos kernel (one per shell)"] sys["System agent session
(profile _main)"] peers["App peers
one per (app, account)"] @@ -110,10 +110,10 @@ Native apps are first-party Rust crates declared only in [`native-apps.json`](.. | App Hub (`apphub`: the store and the Card runner) | in process | in process | in process | default / default | – | | Rinx | in process | in process | in process | default / default | granted the four `octos.*` services | | Terminal | **own process** | own process with a Vulkan build and a Wayland session, else in process | in process | default / off | – (its `run` tool is `confirm: host`, `auto_approvable: false`) | -| Sheets, Reference | own process | own process | in process | opt-in / `mobile-apps` | – | +| Sheets, Reference | in process | in process | in process | opt-in / `mobile-apps` | – | | AppCard | in process | in process | in process | opt-in / opt-in | its own kernel connection | -So among the apps a shell ships by default, **only the Terminal is a process app**, and only on the desktop. App Hub stays in process because it hosts the Card runner every script app runs in; Rinx stays in process until the peer link and the process sandboxes exist (ADR 0004 §2). +So **only the Terminal is a process app**, and only on the desktop; `tools/native_apps.py` refuses plain `process` on Linux (`process-if-vulkan` only), so Linux without Vulkan and Wayland runs every app in process. App Hub stays in process because it hosts the Card runner every script app runs in; Rinx stays in process until the peer link and the process sandboxes exist (ADR 0004 §2). How the shell decides at run time (`crates/shell/src/apps.rs`, `AppRegistry::hosting`): if the target cannot run processes (`host::processes_available()` is false on wasm and native mobile), every app is a module; App Hub and Settings are always modules; otherwise a native app follows its manifest entry, and runs as a process only when a process form exists (a checkout to `cargo run` from, or a sibling binary). Release packages do not ship process apps' binaries yet ([#94](https://github.com/OctoSense-org/OctoSense/pull/94), in progress), so there they fall back to in-process. A per-app override (`~/.makepad/wm/apps.splash`, `--module `) can switch a module to a process. @@ -426,7 +426,7 @@ sequenceDiagram Found while writing this page (2026-09-28); none is fixed here, as this change is documentation only. -1. **Process apps beyond the Terminal.** ADR 0004 §2 says the Terminal is the only process app for now and that Linux without Vulkan runs every app in process. `native-apps.json` declares the opt-in Sheets and Reference as `process` on macOS, Windows and Linux (plain `process`, not `process-if-vulkan`), so an OpenGL or X11 Linux build would run them as processes with CPU readback. +1. **Process apps beyond the Terminal.** Fixed: the opt-in Sheets and Reference are `module` on every target, and the generator refuses plain `process` on Linux (ADR 0004 §2). 2. **Restart of a dead process app.** ADR 0004 §2 says its tile shows it closed with a restart. The shell removes the client and posts "App stopped"; the Restart face exists only for in-process modules (`module_view.rs`). 3. **Agent workspace = account folder.** ADR 0004 §11 names it the `peer/prepare` `cwd`. The broker sends no `cwd` to `peer/prepare` and binds the peer to the kernel-provisioned workspace; the storage API's `agent_workspace` is not connected to it. The account folder name (`account_hash`, SHA-256) and the memory namespace tag (FNV-1a in `broker.rs`) are also different hashes of the account. 4. **ADR 0003 "What the profile runs"** says OctoSense configures neither the tool set nor the sandbox. Since [#117](https://github.com/OctoSense-org/OctoSense/pull/117) the shell writes a `tool_policy` denying `group:runtime` into the `_main` profile before every start, so the host's own turns have no octos shell either. diff --git a/docs/architecture.zh-CN.md b/docs/architecture.zh-CN.md index 76e4c6c3..21699df6 100644 --- a/docs/architecture.zh-CN.md +++ b/docs/architecture.zh-CN.md @@ -39,7 +39,7 @@ flowchart LR aihost["ai-host + app-peers broker
到内核的宿主连接"] bus["AI 服务总线
crates/shell/src/ai_bus.rs"] end - term["进程应用(桌面端)
Terminal;可选 Sheets、Reference"] + term["进程应用(桌面端)
Terminal"] subgraph kern["octos 内核(每个 Shell 一个)"] sys["系统 Agent 会话
(profile _main)"] peers["应用 peer
每个(应用,账号)一个"] @@ -110,10 +110,10 @@ flowchart LR | App Hub(`apphub`:商店和 Card runner) | 进程内 | 进程内 | 进程内 | 默认 / 默认 | – | | Rinx | 进程内 | 进程内 | 进程内 | 默认 / 默认 | 获授权四个 `octos.*` 服务 | | Terminal | **独立进程** | Vulkan 构建且在 Wayland 会话中时为独立进程,否则进程内 | 进程内 | 默认 / 关闭 | –(其 `run` 工具为 `confirm: host`、`auto_approvable: false`) | -| Sheets、Reference | 独立进程 | 独立进程 | 进程内 | 可选 / `mobile-apps` | – | +| Sheets、Reference | 进程内 | 进程内 | 进程内 | 可选 / `mobile-apps` | – | | AppCard | 进程内 | 进程内 | 进程内 | 可选 / 可选 | 自己的内核连接 | -因此在 Shell 默认附带的应用中,**只有 Terminal 是进程应用**,而且只在桌面端。App Hub 留在进程内,因为它承载所有脚本应用运行所在的 Card runner;Rinx 留在进程内,直到 peer link 和进程沙箱就绪(ADR 0004 §2)。 +因此**只有 Terminal 是进程应用**,而且只在桌面端;`tools/native_apps.py` 拒绝 Linux 上的普通 `process`(只允许 `process-if-vulkan`),所以没有 Vulkan 和 Wayland 的 Linux 上所有应用都在进程内运行。App Hub 留在进程内,因为它承载所有脚本应用运行所在的 Card runner;Rinx 留在进程内,直到 peer link 和进程沙箱就绪(ADR 0004 §2)。 Shell 在运行时如何决定(`crates/shell/src/apps.rs`,`AppRegistry::hosting`):如果目标平台不能运行进程(在 wasm 和原生移动平台上 `host::processes_available()` 为 false),所有应用都作为模块;App Hub 和 Settings 始终是模块;其他情况下原生应用按清单条目托管,并且只有存在进程形态(可以 `cargo run` 的源码检出,或同目录下的二进制)时才作为进程运行。发布包目前还不附带进程应用的二进制([#94](https://github.com/OctoSense-org/OctoSense/pull/94),进行中),因此在发布包中会回退到进程内。按应用的覆盖设置(`~/.makepad/wm/apps.splash`、`--module `)可以把模块切换为进程。 @@ -426,7 +426,7 @@ sequenceDiagram 撰写本文时(2026-09-28)发现;本次改动只涉及文档,这里都没有修复。 -1. **Terminal 之外的进程应用。** ADR 0004 §2 说目前只有 Terminal 是进程应用,并且没有 Vulkan 的 Linux 上所有应用都在进程内运行。`native-apps.json` 把可选的 Sheets 和 Reference 在 macOS、Windows 和 Linux 上都声明为 `process`(普通的 `process`,不是 `process-if-vulkan`),因此 OpenGL 或 X11 的 Linux 构建会把它们作为进程运行,并经 CPU 回读画面。 +1. **Terminal 之外的进程应用。** 已修复:可选的 Sheets 和 Reference 在所有目标上都是 `module`,生成器拒绝 Linux 上的普通 `process`(ADR 0004 §2)。 2. **崩溃进程应用的重启。** ADR 0004 §2 说它的磁贴会显示已关闭并提供重启。Shell 实际上移除客户端并发出 “App stopped” 通知;Restart 界面只用于进程内模块(`module_view.rs`)。 3. **Agent 工作区 = 账号目录。** ADR 0004 §11 说它就是 `peer/prepare` 的 `cwd`。broker 不向 `peer/prepare` 发送 `cwd`,把 peer 绑定到内核分配的工作区;存储 API 的 `agent_workspace` 没有与之连接。账号目录名(`account_hash`,SHA-256)和记忆命名空间标签(`broker.rs` 中的 FNV-1a)也是对账号的两种不同 hash。 4. **ADR 0003 的 “What the profile runs”** 说 OctoSense 既不配置工具集也不配置沙箱。自 [#117](https://github.com/OctoSense-org/OctoSense/pull/117) 起,Shell 每次启动前都向 `_main` profile 写入拒绝 `group:runtime` 的 `tool_policy`,因此宿主自己的回合也没有 octos shell。 diff --git a/native-apps.json b/native-apps.json index 09737814..695e20d9 100644 --- a/native-apps.json +++ b/native-apps.json @@ -26,7 +26,7 @@ "default_features": true, "crate_features": [], "implies": [], - "hosting": { "macos": "process", "windows": "process", "linux": "process", "android": "module", "ios": "module", "ohos": "module" }, + "hosting": { "macos": "module", "windows": "module", "linux": "module", "android": "module", "ios": "module", "ohos": "module" }, "shells": { "desktop": "opt-in", "phone": "mobile-apps" }, "native_mobile": "always", "sandbox": { "network": "none", "processes": false }, @@ -42,7 +42,7 @@ "default_features": false, "crate_features": [], "implies": [], - "hosting": { "macos": "process", "windows": "process", "linux": "process", "android": "module", "ios": "module", "ohos": "module" }, + "hosting": { "macos": "module", "windows": "module", "linux": "module", "android": "module", "ios": "module", "ohos": "module" }, "shells": { "desktop": "opt-in", "phone": "mobile-apps" }, "native_mobile": "always", "sandbox": { "network": "none", "processes": false }, diff --git a/tools/native_apps.py b/tools/native_apps.py index f41ac93b..cafaefb3 100644 --- a/tools/native_apps.py +++ b/tools/native_apps.py @@ -21,10 +21,12 @@ pushes under which feature, and each app's hosting per target (the default the shell uses when the person has not switched an app). -It refuses `process` hosting on mobile or wasm targets, `process` without a -`bin`, and two revisions of one git repository in the root pins. After a -write, Cargo.lock is brought in step by cargo itself (`cargo update -p` for -a pin that changed, then `cargo metadata`); --no-lock skips that. +It refuses `process` hosting on mobile or wasm targets, plain `process` on +Linux (non-Vulkan Linux runs every app in-process: `process-if-vulkan`), +`process` without a `bin`, and two revisions of one git repository in the +root pins. After a write, Cargo.lock is brought in step by cargo itself +(`cargo update -p` for a pin that changed, then `cargo metadata`); --no-lock +skips that. python3 tools/native_apps.py # regenerate after editing the manifest python3 tools/native_apps.py --check # CI: exit 1 when anything drifted @@ -142,6 +144,9 @@ def validate(data): problems.append(f"{where}: hosting.{target}: {value!r} is not one of {', '.join(HOSTINGS)}") elif value != "module" and target in MODULE_ONLY: problems.append(f"{where}: hosting.{target}: {target} has no processes; only 'module'") + elif value == "process" and target == "linux": + problems.append(f"{where}: hosting.linux: 'process' would run without Vulkan+Wayland; " + "use 'process-if-vulkan' (ADR 0004 §2)") elif value != "module" and not app["bin"]: problems.append(f"{where}: hosting.{target}: '{value}' needs a bin") shells = app["shells"] diff --git a/tools/test_native_apps.py b/tools/test_native_apps.py index 18154826..e0853b6a 100644 --- a/tools/test_native_apps.py +++ b/tools/test_native_apps.py @@ -35,8 +35,11 @@ def test_the_manifest_declares_todays_native_apps(self): self.assertEqual(hosting["terminal"]["macos"], "process") self.assertEqual(hosting["terminal"]["windows"], "process") self.assertEqual(hosting["terminal"]["linux"], "process-if-vulkan") - for ident in ("apphub", "rinx"): + for ident in ("apphub", "rinx", "sheets", "reference", "appcard"): self.assertEqual(set(hosting[ident].values()), {"module"}, ident) + # Non-Vulkan Linux is in-process for everything. + for ident, h in hosting.items(): + self.assertIn(h["linux"], ("module", "process-if-vulkan"), ident) class Fixture(unittest.TestCase): @@ -73,6 +76,10 @@ def test_refuses_process_on_mobile_and_wasm(self): self.assertRefused(rf"hosting\.{target}: {target} has no processes") self.app("terminal")["hosting"][target] = "module" + def test_refuses_plain_process_on_linux(self): + self.app("terminal")["hosting"]["linux"] = "process" + self.assertRefused(r"terminal: hosting\.linux: 'process' would run without Vulkan\+Wayland") + def test_refuses_process_without_a_bin(self): self.app("rinx")["hosting"]["macos"] = "process" self.assertRefused(r"rinx: hosting\.macos: 'process' needs a bin") From 15e287444df1b65af9df3b2249c66ace593f4494 Mon Sep 17 00:00:00 2001 From: ymote <151983+ymote@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:52:37 -0700 Subject: [PATCH 2/5] approvals: consent reads StorageSpec; storage.accounts defaults to false [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit App storage defaulted `storage.accounts` to false (one `device` folder) while the first-use consent sheet re-parsed the block and treated a missing value as true. The sheet now reads the block through StorageSpec, so an app keeps data per account only when it declares `"accounts": true` (ADR 0004 §11, now saying so), and a test checks both agree. Co-Authored-By: Claude Opus 5.5 --- crates/shell/src/approvals/consent.rs | 17 ++++++++------ crates/shell/src/approvals/tests.rs | 22 +++++++++++++++++++ .../adr/0004-native-apps-hosting-and-peers.md | 2 +- docs/architecture.md | 2 +- docs/architecture.zh-CN.md | 2 +- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/crates/shell/src/approvals/consent.rs b/crates/shell/src/approvals/consent.rs index 42a69319..a14e8058 100644 --- a/crates/shell/src/approvals/consent.rs +++ b/crates/shell/src/approvals/consent.rs @@ -8,6 +8,7 @@ //! app) and the Rinx/native offer path ask before handing an app its peer. use super::rules::ApprovalGesture; +use crate::app_storage::{AgentWorkspace, AppKind, StorageSpec}; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::BTreeMap; @@ -36,13 +37,15 @@ impl AgentSummary { /// with the grants the person gave at install and the model's place. pub fn from_manifest(app: &str, name: &str, manifest: &Value, granted: &[String], model: &str) -> AgentSummary { let mut reads = Vec::new(); - let storage = manifest.get("storage"); - let workspace = storage.and_then(|s| s.get("agent_workspace")).and_then(|v| v.as_str()).unwrap_or("account"); - if workspace == "none" { - reads.push("No files: only what its tools return".to_string()); - } else { - let per_account = storage.and_then(|s| s.get("accounts")).and_then(|v| v.as_bool()).unwrap_or(true); - reads.push(if per_account { format!("{name}'s files for the signed-in account") } else { format!("{name}'s files on this device") }); + // The storage block as app storage reads it, so the sheet and the + // folders agree (a block the store refuses is shown as no block; + // the install check reports it). `external` is native-only and is + // never an agent's workspace, so parse as native. + let storage = StorageSpec::from_manifest(manifest, AppKind::Native).unwrap_or_default(); + match storage.agent_workspace { + AgentWorkspace::None => reads.push("No files: only what its tools return".to_string()), + AgentWorkspace::Account if storage.accounts => reads.push(format!("{name}'s files for the signed-in account")), + AgentWorkspace::Account => reads.push(format!("{name}'s files on this device")), } reads.push("Its own memory".to_string()); let mut declared: Vec = Vec::new(); diff --git a/crates/shell/src/approvals/tests.rs b/crates/shell/src/approvals/tests.rs index 2927f86e..7c5460e2 100644 --- a/crates/shell/src/approvals/tests.rs +++ b/crates/shell/src/approvals/tests.rs @@ -486,6 +486,28 @@ fn news() -> AgentSummary { ) } +/// The consent sheet and app storage read one `storage` block the same +/// way: `accounts` defaults to false (one `device` folder) in both. +#[test] +fn consent_and_app_storage_agree_on_accounts() { + use crate::app_storage::{AppKind, StorageSpec}; + for manifest in [ + json!({}), + json!({"storage": {}}), + json!({"storage": {"agent_workspace": "account"}}), + json!({"storage": {"accounts": false}}), + json!({"storage": {"accounts": true}}), + json!({"storage": {"accounts": true, "agent_workspace": "account"}}), + ] { + let per_account = StorageSpec::from_manifest(&manifest, AppKind::Script).unwrap().accounts; + let summary = AgentSummary::from_manifest("os.x", "X", &manifest, &[], "m"); + let says_account = summary.reads.iter().any(|r| r.contains("signed-in account")); + let says_device = summary.reads.iter().any(|r| r.contains("on this device")); + assert_eq!((says_account, says_device), (per_account, !per_account), "{manifest}"); + } + assert!(!StorageSpec::from_manifest(&json!({}), AppKind::Script).unwrap().accounts, "an app declares accounts"); +} + #[test] fn consent_at_first_use_is_asked_once_and_remembered() { let mut c = ConsentStore::memory(); diff --git a/docs/adr/0004-native-apps-hosting-and-peers.md b/docs/adr/0004-native-apps-hosting-and-peers.md index 31f4c882..fba4830f 100644 --- a/docs/adr/0004-native-apps-hosting-and-peers.md +++ b/docs/adr/0004-native-apps-hosting-and-peers.md @@ -230,7 +230,7 @@ The contract, one block in both manifests (App Hub's `manifest.json` extends its } ``` -- `accounts`: the app keeps data per account (one agent per account); `false` means one `device` folder. +- `accounts`: the app keeps data per account (one agent per account); `false`, the default, means one `device` folder (an app with accounts declares `true`). - `agent_workspace`: `"account"` (default: the account folder) or `"none"` (the agent reads no files; tools only). - `external`: native apps only, paths outside the jail the app needs, reviewed in `native-apps.json` (the terminal's `home:rw`). They are part of its OS sandbox and are **never** in an agent's workspace. diff --git a/docs/architecture.md b/docs/architecture.md index 2c2a3f91..873aab95 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -434,7 +434,7 @@ Found while writing this page (2026-09-28); none is fixed here, as this change i 6. **Command execution "turned on in Settings"** (`crates/kernel/README.md`, `system_tools.rs` docs): no Settings switch exists yet; `SystemAgentTools::grant_command_execution` is a seam. 7. **`host::processes_available()`'s test** checks only `wasm32` while the function also excludes native mobile. 8. **Approvals, ADR 0004 §8.** Every app tool call is to reach the router through `peer/tool/call`; today only the AI bus feeds it (above). No app registers its own `confirm: app` sheet, so such a call would wait and be refused. The audit keeps a digest of the arguments, not the arguments. The send queue and undo window are not built. -9. **Storage, ADR 0004 §11.** Secrets use the OS keychain only on macOS and iOS (plaintext 0600 files elsewhere). The startup check refuses workspaces that reach the secrets through links or containment rather than looking for a `secrets/` path, and does not stop startup. `storage.accounts` defaults to `false` in `spec.rs` but `consent.rs` treats a missing value as `true`. +9. **Storage, ADR 0004 §11.** Secrets use the OS keychain only on macOS and iOS (plaintext 0600 files elsewhere). The startup check refuses workspaces that reach the secrets through links or containment rather than looking for a `secrets/` path, and does not stop startup. (Fixed: `storage.accounts` defaults to `false` in both app storage and the consent sheet, which now reads `StorageSpec`.) 10. **Developer mode, ADR 0004 §13.** `dev.run` is not registered; Settings turns it on only for all apps (a chosen list only through `OCTOSENSE_DEV_MODE`); there is no phone gesture; in-process modules still show their own confirmation sheets. ## Source map diff --git a/docs/architecture.zh-CN.md b/docs/architecture.zh-CN.md index 21699df6..27830ddd 100644 --- a/docs/architecture.zh-CN.md +++ b/docs/architecture.zh-CN.md @@ -434,7 +434,7 @@ sequenceDiagram 6. **“在 Settings 中开启”命令执行**(`crates/kernel/README.md`、`system_tools.rs` 文档):还没有 Settings 开关;`SystemAgentTools::grant_command_execution` 只是接口。 7. **`host::processes_available()` 的测试**只检查 `wasm32`,而函数本身还排除了原生移动平台。 8. **审批,ADR 0004 §8。** 每次应用工具调用都应通过 `peer/tool/call` 到达路由;目前只有 AI 总线向它提交请求(见上文)。没有应用注册自己的 `confirm: app` 面板,因此这类调用会等待后被拒绝。审计记录的是参数摘要而不是参数。发送队列和撤销窗口尚未实现。 -9. **存储,ADR 0004 §11。** 机密只在 macOS 和 iOS 上使用系统钥匙串(其他平台为 0600 明文文件)。启动检查拒绝通过链接或包含关系通向机密的工作区,而不是查找 `secrets/` 路径,并且不会中止启动。`spec.rs` 中 `storage.accounts` 默认为 `false`,而 `consent.rs` 把缺省值当作 `true`。 +9. **存储,ADR 0004 §11。** 机密只在 macOS 和 iOS 上使用系统钥匙串(其他平台为 0600 明文文件)。启动检查拒绝通过链接或包含关系通向机密的工作区,而不是查找 `secrets/` 路径,并且不会中止启动。(已修复:app storage 和同意面板中 `storage.accounts` 都默认为 `false`,同意面板现在读取 `StorageSpec`。) 10. **开发者模式,ADR 0004 §13。** `dev.run` 尚未注册;Settings 只能为所有应用开启(选定应用只能通过 `OCTOSENSE_DEV_MODE`);手机上没有开启手势;进程内模块仍会显示自己的确认面板。 ## 源码位置 From bbf5e1ecd38de1dd94b1a2c086833d0032f99802 Mon Sep 17 00:00:00 2001 From: ymote <151983+ymote@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:53:07 -0700 Subject: [PATCH 3/5] kernel: command execution for the system agent is planned, not available [skip ci] The kernel README and system_tools.rs said the person can turn command execution on in Settings. No Settings switch calls SystemAgentTools::grant_command_execution, and the host tool cannot be registered on the system session before octos#2567's per-session tool registration. Say so. Docs only. Co-Authored-By: Claude Opus 5.5 --- crates/kernel/README.md | 9 ++++++--- crates/kernel/README.zh-CN.md | 5 +++-- crates/kernel/src/system_tools.rs | 13 ++++++++----- docs/architecture.md | 2 +- docs/architecture.zh-CN.md | 2 +- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/kernel/README.md b/crates/kernel/README.md index a0398614..406a120f 100644 --- a/crates/kernel/README.md +++ b/crates/kernel/README.md @@ -164,9 +164,12 @@ system agent's tool set is its grants. Its default octos tools are file tools (octos fences them to the session's working directory), memory, `ask_user_question`, media viewing, octos's `web_search` / `web_fetch` (until toolbox grants replace them, #108) and `tool_search`. Granted toolbox and -cross-app tools, and command execution when the person turns it on in -Settings (off by default), join it as host tools through `SystemAgentTools`; -command execution is a host tool with a live approval (`terminal.run`). +cross-app tools join it as host tools through `SystemAgentTools`. Command +execution is **planned, not available**: it is to be a host tool with a live +approval (`terminal.run`), off by default and turned on by a Settings +switch. `SystemAgentTools::grant_command_execution` is the seam, but no +Settings switch sets it yet, and the host tool cannot be registered on the +system session until octos can register tools per session (octos#2567). **What the kernel enforces today.** octos has no tool list the host can set for one session, so every start writes the `_main` profile's `tool_policy` diff --git a/crates/kernel/README.zh-CN.md b/crates/kernel/README.zh-CN.md index 4433daef..859f378f 100644 --- a/crates/kernel/README.zh-CN.md +++ b/crates/kernel/README.zh-CN.md @@ -134,8 +134,9 @@ adb -s SERIAL forward tcp:PORT tcp:PORT [ADR 0004](../../docs/adr/0004-native-apps-hosting-and-peers.md) §12:系统智能体的工具集就是它获得的授权。它默认的 octos 工具是 `system_tools::SYSTEM_AGENT_TOOLS`:监督(`peer_send_input`、`peer_gather`、`peer_list`、`peer_respond`、 `peer_close`)、其工作区内的文件工具(octos 将其限制在会话工作目录内)、记忆、`ask_user_question`、查看媒体、octos 的 -`web_search` / `web_fetch`(在工具箱授权取代它们之前,#108)以及 `tool_search`。授予的工具箱工具和跨应用工具,以及用户在设置中开启 -(默认关闭)的命令执行,通过 `SystemAgentTools` 作为宿主工具加入;命令执行是需要实时批准的宿主工具(`terminal.run`)。 +`web_search` / `web_fetch`(在工具箱授权取代它们之前,#108)以及 `tool_search`。授予的工具箱工具和跨应用工具通过 `SystemAgentTools` 作为宿主工具加入。命令执行**尚在计划中,目前不可用**: +它将是需要实时批准的宿主工具(`terminal.run`),默认关闭,由设置中的开关开启。`SystemAgentTools::grant_command_execution` +是预留接口,但目前还没有设置开关调用它,而且在 octos 支持按会话注册工具(octos#2567)之前,无法在系统会话上注册该宿主工具。 **内核今天执行的内容。** octos 没有宿主可为单个会话设置的工具名单,因此每次启动都写入 `_main` profile 的 `tool_policy` (`system_tools::tool_policy`):任何授权可给予的一切,唯独去掉 octos 自己的 shell(`group:runtime`:`shell`、`bash`、 diff --git a/crates/kernel/src/system_tools.rs b/crates/kernel/src/system_tools.rs index b5d07a5d..06a024d6 100644 --- a/crates/kernel/src/system_tools.rs +++ b/crates/kernel/src/system_tools.rs @@ -4,8 +4,9 @@ //! - [`SYSTEM_AGENT_TOOLS`]: the octos tools the system agent //! (`_main:api:octosense#system`) gets by default. With what the person //! grants it ([`SystemAgentTools`]: toolbox tools, other apps' shareable -//! tools, and command execution when turned on in Settings) that is its -//! whole set: ADR 0004 §12's "exactly its grants". +//! tools, and, planned, command execution behind a Settings switch that +//! does not exist yet; see [`SystemAgentTools::grant_command_execution`]) +//! that is its whole set: ADR 0004 §12's "exactly its grants". //! - [`tool_policy`]: the `_main` profile's policy, the ceiling for every //! `_main` session. It is every tool any grant can give: OctoSense //! hard-codes no exclusions (§12) except ONE, octos's own shell @@ -66,7 +67,8 @@ use serde_json::{json, Value}; /// agent `toolbox.search` / `toolbox.web_read`. /// /// Anything else it may have is by grant ([`SystemAgentTools`]); command -/// execution only as a host tool the person turns on in Settings. +/// execution only as a host tool the person turns on (planned: no Settings +/// switch yet, and it needs octos#2567's per-session tool registration). pub const SYSTEM_AGENT_TOOLS: &[&str] = &[ // Supervision. "peer_send_input", @@ -172,8 +174,9 @@ impl SystemAgentTools { self } - /// The person's Settings switch for the system agent's command - /// execution (ADR 0004 §12; off by default). On, the system agent gets + /// The seam for the person's planned Settings switch for the system + /// agent's command execution (ADR 0004 §12; off by default). Nothing + /// calls it outside tests yet. On, the system agent gets /// the host tool [`COMMAND_EXECUTION_TOOL`], each command approved live /// (section 8); never octos's shell. /// diff --git a/docs/architecture.md b/docs/architecture.md index 873aab95..9e81702f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -431,7 +431,7 @@ Found while writing this page (2026-09-28); none is fixed here, as this change i 3. **Agent workspace = account folder.** ADR 0004 §11 names it the `peer/prepare` `cwd`. The broker sends no `cwd` to `peer/prepare` and binds the peer to the kernel-provisioned workspace; the storage API's `agent_workspace` is not connected to it. The account folder name (`account_hash`, SHA-256) and the memory namespace tag (FNV-1a in `broker.rs`) are also different hashes of the account. 4. **ADR 0003 "What the profile runs"** says OctoSense configures neither the tool set nor the sandbox. Since [#117](https://github.com/OctoSense-org/OctoSense/pull/117) the shell writes a `tool_policy` denying `group:runtime` into the `_main` profile before every start, so the host's own turns have no octos shell either. 5. **Stale context lines.** ADR 0004's context table and the root README's layout table still mention native News, Maps and Photos comparison modules (`apps/*/native`); ADR 0004 step 1 deleted them. [ai-services.md](ai-services.md) is dated 2026-09-27: its architecture diagram shows "no `octos.*` service" for the Card runner (merged in #106), and it says contained apps are off "until first-use consent lands" (consent landed in #120; the `Policy::contained_apps` switch is still off by default). -6. **Command execution "turned on in Settings"** (`crates/kernel/README.md`, `system_tools.rs` docs): no Settings switch exists yet; `SystemAgentTools::grant_command_execution` is a seam. +6. **Command execution "turned on in Settings".** Fixed in the docs: `crates/kernel/README.md` and `system_tools.rs` now say it is planned (no Settings switch sets `SystemAgentTools::grant_command_execution`; the host tool needs octos#2567). 7. **`host::processes_available()`'s test** checks only `wasm32` while the function also excludes native mobile. 8. **Approvals, ADR 0004 §8.** Every app tool call is to reach the router through `peer/tool/call`; today only the AI bus feeds it (above). No app registers its own `confirm: app` sheet, so such a call would wait and be refused. The audit keeps a digest of the arguments, not the arguments. The send queue and undo window are not built. 9. **Storage, ADR 0004 §11.** Secrets use the OS keychain only on macOS and iOS (plaintext 0600 files elsewhere). The startup check refuses workspaces that reach the secrets through links or containment rather than looking for a `secrets/` path, and does not stop startup. (Fixed: `storage.accounts` defaults to `false` in both app storage and the consent sheet, which now reads `StorageSpec`.) diff --git a/docs/architecture.zh-CN.md b/docs/architecture.zh-CN.md index 27830ddd..96b4c5f4 100644 --- a/docs/architecture.zh-CN.md +++ b/docs/architecture.zh-CN.md @@ -431,7 +431,7 @@ sequenceDiagram 3. **Agent 工作区 = 账号目录。** ADR 0004 §11 说它就是 `peer/prepare` 的 `cwd`。broker 不向 `peer/prepare` 发送 `cwd`,把 peer 绑定到内核分配的工作区;存储 API 的 `agent_workspace` 没有与之连接。账号目录名(`account_hash`,SHA-256)和记忆命名空间标签(`broker.rs` 中的 FNV-1a)也是对账号的两种不同 hash。 4. **ADR 0003 的 “What the profile runs”** 说 OctoSense 既不配置工具集也不配置沙箱。自 [#117](https://github.com/OctoSense-org/OctoSense/pull/117) 起,Shell 每次启动前都向 `_main` profile 写入拒绝 `group:runtime` 的 `tool_policy`,因此宿主自己的回合也没有 octos shell。 5. **过时的背景描述。** ADR 0004 的背景表格和根 README 的目录结构表仍提到原生 News、Maps 和 Photos 对比模块(`apps/*/native`);ADR 0004 步骤 1 已删除它们。[ai-services.zh-CN.md](ai-services.zh-CN.md) 的日期是 2026-09-27:其架构图显示 Card runner “没有 `octos.*` 服务”(#106 已合入),并说脚本应用“在首次使用同意落地之前”关闭(同意机制已在 #120 落地;`Policy::contained_apps` 开关默认仍关闭)。 -6. **“在 Settings 中开启”命令执行**(`crates/kernel/README.md`、`system_tools.rs` 文档):还没有 Settings 开关;`SystemAgentTools::grant_command_execution` 只是接口。 +6. **“在 Settings 中开启”命令执行。** 文档已修复:`crates/kernel/README.md` 和 `system_tools.rs` 现在说明它尚在计划中(没有 Settings 开关调用 `SystemAgentTools::grant_command_execution`;宿主工具需要 octos#2567)。 7. **`host::processes_available()` 的测试**只检查 `wasm32`,而函数本身还排除了原生移动平台。 8. **审批,ADR 0004 §8。** 每次应用工具调用都应通过 `peer/tool/call` 到达路由;目前只有 AI 总线向它提交请求(见上文)。没有应用注册自己的 `confirm: app` 面板,因此这类调用会等待后被拒绝。审计记录的是参数摘要而不是参数。发送队列和撤销窗口尚未实现。 9. **存储,ADR 0004 §11。** 机密只在 macOS 和 iOS 上使用系统钥匙串(其他平台为 0600 明文文件)。启动检查拒绝通过链接或包含关系通向机密的工作区,而不是查找 `secrets/` 路径,并且不会中止启动。(已修复:app storage 和同意面板中 `storage.accounts` 都默认为 `false`,同意面板现在读取 `StorageSpec`。) From ee0362f9ddca9b55956091d473b6a8e045ed90b6 Mon Sep 17 00:00:00 2001 From: ymote <151983+ymote@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:54:13 -0700 Subject: [PATCH 4/5] docs: drop the deleted native News, Maps and Photos modules [skip ci] The README layout tables (root, apps/, phone's `mobile-apps` row) still listed the native comparison modules (`apps/*/native`) that #113 deleted; the script apps are the only versions. ADR 0004's Context "Today" row now says the crates were deleted by #113 (not #110, as a few pages had it). The desktop README drops the now-redundant `--module reference --module sheets` example. Docs only. Co-Authored-By: Claude Opus 5.5 --- README.md | 2 +- README.zh-CN.md | 2 +- apps/README.md | 4 ++-- apps/README.zh-CN.md | 4 ++-- desktop/README.md | 3 +-- desktop/README.zh-CN.md | 1 - docs/adr/0004-native-apps-hosting-and-peers.md | 2 +- docs/adr/home/0004-system-apps-are-contained-script-apps.md | 4 ++-- docs/architecture.md | 2 +- docs/architecture.zh-CN.md | 2 +- phone/README.md | 4 ++-- phone/README.zh-CN.md | 4 ++-- 12 files changed, 16 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index dbdd5a97..6fac329f 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Processes, agents, protocols, tools, approvals, storage and trust boundaries, wi | [`crates/ai-host/`](crates/ai-host/README.md) | The shell's AI services behind one entry point, package `octosense-ai-host`: the octos kernel service, the `llm` host service with the platform's QR import, and apps' assistant access. | | [`crates/kernel/`](crates/kernel/README.md) | The octos kernel service, package `octosense-kernel`: the [octos](https://github.com/octos-org/octos) agent kernel as a shell service, one per process, configured by AI providers and shared by its consumers. | | [`crates/app-peers/`](crates/app-peers/README.md) | The app-agent broker: apps' access to the assistant ([Rinx ADR 0007](https://github.com/hagency-org/Rinx/blob/main/docs/adr/0007-host-owned-octos-app-peers.md)). | -| [`apps/`](apps/README.md) | The system apps (News, Photos, Maps, Camera, Mail, AI providers, YouTube) as contained script apps, their host services (`mail`, `llm`), the native comparison modules (`apps/*/native`), `apps/reference`, and the opt-in AppCard assistant (`apps/appcard`). | +| [`apps/`](apps/README.md) | The system apps (News, Photos, Maps, Camera, Mail, AI providers, YouTube) as contained script apps, their host services (`mail`, `llm`), `apps/reference`, and the opt-in AppCard assistant (`apps/appcard`). | | `tools/` | `setup.py` (the pinned framework sources), the reviewed Makepad runtime patch (`runtime-patches/`), `kernel-artifact.py` (the octos kernel an Android APK bundles as `liboctos.so`), `check-shell-graph.sh` (the dependency-graph guards every shell build passes). | | [`docs/adr/`](docs/adr/README.md) | Architecture decisions: this repository's, and the Home decisions 0001–0006 kept as history. | | `Cargo.toml`, `Cargo.lock` | One workspace. Every external dependency is pinned once in `[workspace.dependencies]`. | diff --git a/README.zh-CN.md b/README.zh-CN.md index e9019e2b..8946fa9d 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -43,7 +43,7 @@ | [`crates/ai-host/`](crates/ai-host/README.md) | Shell 的 AI 服务,统一入口,package `octosense-ai-host`:octos 内核服务、带平台二维码导入的 `llm` 宿主服务,以及应用访问助手的通道。 | | [`crates/kernel/`](crates/kernel/README.md) | octos 内核服务,package `octosense-kernel`:把 [octos](https://github.com/octos-org/octos) Agent 内核作为 Shell 服务,每个进程一个,由 AI 服务商配置,供所有使用方共享。 | | [`crates/app-peers/`](crates/app-peers/README.md) | 应用与 Agent 之间的代理:应用访问助手的通道([Rinx ADR 0007(英文)](https://github.com/hagency-org/Rinx/blob/main/docs/adr/0007-host-owned-octos-app-peers.md))。 | -| [`apps/`](apps/README.zh-CN.md) | 系统应用(新闻、相册、地图、相机、邮件、AI 服务商、YouTube),均为受隔离约束的脚本应用;它们的宿主服务(`mail`、`llm`);用于对比的原生模块(`apps/*/native`);`apps/reference`;以及需显式启用的 AppCard 助手(`apps/appcard`)。 | +| [`apps/`](apps/README.zh-CN.md) | 系统应用(新闻、相册、地图、相机、邮件、AI 服务商、YouTube),均为受隔离约束的脚本应用;它们的宿主服务(`mail`、`llm`);`apps/reference`;以及需显式启用的 AppCard 助手(`apps/appcard`)。 | | `tools/` | `setup.py`(锁定版本的框架源码)、经审查的 Makepad 运行时补丁(`runtime-patches/`)、`kernel-artifact.py`(Android APK 以 `liboctos.so` 形式打包的 octos 内核)、`check-shell-graph.sh`(每个 Shell 构建都要通过的依赖图检查)。 | | [`docs/adr/`](docs/adr/README.zh-CN.md) | 架构决策记录:本仓库的决策,以及作为历史保留的 Home 决策 0001–0006。 | | `Cargo.toml`、`Cargo.lock` | 一个工作区。所有外部依赖都只在 `[workspace.dependencies]` 中锁定一次。 | diff --git a/apps/README.md b/apps/README.md index 93f21304..31c38741 100644 --- a/apps/README.md +++ b/apps/README.md @@ -29,7 +29,7 @@ them. They live in `apps/` of the [OctoSense repository](../README.md); until `app-reference` (always on phones). Every native app the shells link is declared in [`../native-apps.json`](../native-apps.json). News, Photos and Maps are script apps only: their earlier native modules were deleted - (native-apps ADR 0004 §1, [#110](https://github.com/OctoSense-org/OctoSense/pull/110)). Photos' sample library, which Home mounts, is in + (native-apps ADR 0004 §1, [#113](https://github.com/OctoSense-org/OctoSense/pull/113)). Photos' sample library, which Home mounts, is in `photos/resources/`. The shell services these apps rely on are next door: @@ -156,7 +156,7 @@ request. ``` /bundle/ a contained script app: manifest.json, main.splash, artwork -/native/ native comparison module (news, photos, maps); Photos' full-size library +photos/resources/ Photos' sample library, which Home mounts mail/host-service/ octosense-mail-service, the `mail` host service (Rust) ai-providers/ the `llm` host service (host-service/) and octosense-llm-config (config/: octos's model catalog and provider registry, the profile merge, OCTOS1/OCTOS1E QR) diff --git a/apps/README.zh-CN.md b/apps/README.zh-CN.md index 9bb4fa38..2a3c0c5a 100644 --- a/apps/README.zh-CN.md +++ b/apps/README.zh-CN.md @@ -26,7 +26,7 @@ OctoSense-System-Apps 仓库(已归档)。 - **Reference**(`reference`):Shell 通过 `app-reference` 链接的 Rust 模块(手机上始终链接)。Shell 链接的所有原生应用都在 [`../native-apps.json`](../native-apps.json) 中声明。News、Photos 和 Maps - 只有脚本应用版本:早期的原生模块已删除(原生应用 ADR 0004 §1,[#110](https://github.com/OctoSense-org/OctoSense/pull/110))。Home 挂载的 + 只有脚本应用版本:早期的原生模块已删除(原生应用 ADR 0004 §1,[#113](https://github.com/OctoSense-org/OctoSense/pull/113))。Home 挂载的 Photos 示例图库位于 `photos/resources/`。 这些应用依赖的 Shell 服务就在旁边: @@ -131,7 +131,7 @@ OctoScript-App-Design-Flow 的 `AGENTS.md`,再读 `docs/QUICKSTART.md`), ``` /bundle/ 隔离运行的脚本应用:manifest.json、main.splash、图片资源 -/native/ 原生对比模块(news、photos、maps);Photos 的原图库 +photos/resources/ Home 挂载的 Photos 示例图库 mail/host-service/ octosense-mail-service,`mail` 宿主服务(Rust) ai-providers/ `llm` 宿主服务(host-service/)和 octosense-llm-config(config/: octos 模型目录与服务商注册表、profile 合并、OCTOS1/OCTOS1E 二维码) diff --git a/desktop/README.md b/desktop/README.md index 08c6e213..357d92a9 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -89,10 +89,9 @@ The native apps' features (`app-hub`, `app-rinx`, `app-reference`, `app-sheets`, | `app-aichat` | off | Links Makepad's AI chat as a module, without its model engine. | | `mobile-apps` | off | `app-rinx` + `app-reference` + `app-sheets` + `app-hub` + `octos-core`: the set phone builds link, for testing on desktop. Not AppCard. | -A linked native app is hosted as its `hosting` in `native-apps.json` says for the platform: App Hub, Rinx and AppCard in-process everywhere, Reference and Sheets in-process everywhere, the Terminal as a process on macOS and Windows (and on Linux with a Vulkan build in a Wayland session). `--module ` (or a `: Module` line in `wm/apps.splash` under the state directory) opens one in-process instead: +A linked native app is hosted as its `hosting` in `native-apps.json` says for the platform: App Hub, Rinx, AppCard, Reference and Sheets in-process everywhere, the Terminal as a process on macOS and Windows (and on Linux with a Vulkan build in a Wayland session). `--module ` (or a `: Module` line in `wm/apps.splash` under the state directory) opens one in-process instead: ```sh -cargo run --release -p octosense --features mobile-apps -- --module reference --module sheets cargo run --release -p octosense -- --module terminal ``` diff --git a/desktop/README.zh-CN.md b/desktop/README.zh-CN.md index b1d46212..35f01338 100644 --- a/desktop/README.zh-CN.md +++ b/desktop/README.zh-CN.md @@ -92,7 +92,6 @@ cargo run --release -p octosense 已链接的原生应用按照 `native-apps.json` 中该平台的 `hosting` 托管:App Hub、Rinx、AppCard、Reference 和 Sheets 在所有平台上都在进程内运行,Terminal 在 macOS 和 Windows 上(以及 Vulkan 构建且处于 Wayland 会话的 Linux 上)作为独立进程运行。用 `--module `(或在状态目录下的 `wm/apps.splash` 中写一行 `: Module`)可改为在进程内打开: ```sh -cargo run --release -p octosense --features mobile-apps -- --module reference --module sheets cargo run --release -p octosense -- --module terminal ``` diff --git a/docs/adr/0004-native-apps-hosting-and-peers.md b/docs/adr/0004-native-apps-hosting-and-peers.md index fba4830f..4f879b79 100644 --- a/docs/adr/0004-native-apps-hosting-and-peers.md +++ b/docs/adr/0004-native-apps-hosting-and-peers.md @@ -11,7 +11,7 @@ | | Native app | Script system app | | --- | --- | --- | -| Today | App Hub (the store and the Card runner), Rinx, Terminal; opt-in Sheets, Reference, AppCard; native News, Maps and Photos crates kept "for comparison" | News, Maps, Photos, Camera, Mail, AI providers | +| Today | App Hub (the store and the Card runner), Rinx, Terminal; opt-in Sheets, Reference, AppCard; the native News, Maps and Photos crates once kept "for comparison" were deleted by [#113](https://github.com/OctoSense-org/OctoSense/pull/113) (the script apps are the only versions) | News, Maps, Photos, Camera, Mail, AI providers | | Source | a crate pinned in the root `Cargo.toml` | `apps//bundle/`, packed from the same commit (`desktop/system-apps.json`) | | Code | Rust: full process rights, `unsafe`, files, PTYs, threads | OctoScript in App Hub's Card runner; reaches the shell only through `host.request` for families its manifest was granted | | Runs | in the shell process, one splash isolate per instance (`crates/shell/src/module_host.rs`); the isolate separates the script heap only | in the shell process, a nested isolate per instance with `mod.res` and `mod.run` stripped | diff --git a/docs/adr/home/0004-system-apps-are-contained-script-apps.md b/docs/adr/home/0004-system-apps-are-contained-script-apps.md index 0d03f892..51d75e66 100644 --- a/docs/adr/home/0004-system-apps-are-contained-script-apps.md +++ b/docs/adr/home/0004-system-apps-are-contained-script-apps.md @@ -2,7 +2,7 @@ - **Date:** 2026-09-25 - **Status:** Proposed -- **Implementation status:** News, Photos, Maps, Camera and Mail are built as script apps. News, Photos, Maps and Mail run on the desktop card host and in the phone shell (Android emulator: Mail's sign-in reached Gmail's POP3 server, and its demo account's password was sealed by the Android Keystore; the IMAP client was checked against Gmail's sign-in and a scripted server). Camera's capture path exists only in the Android and HarmonyOS backends and the emulator refuses the camera texture, so Camera awaits a real device. The native News, Photos and Maps crates were deleted on 2026-09-28 (native-apps ADR 0004 §1, [#110](https://github.com/OctoSense-org/OctoSense/pull/110)), before that measurement; the native Mail and Camera modules were removed on 2026-09-25, when their apps moved to Octoscript-AppCard as script bundles (since moved to OctoSense-System-Apps, `apps//bundle/`) (they remain in Git history). Ported from OctoSense-mobile into this Home on 2026-09-25 (both the standalone and the ROM variant link them; the makepad side rode a reviewed runtime patch until makepad#30 merged on 2026-09-26; the runtime now includes it) and run on the OnePlus 6 as a separate test package: the home tiles, dock and app list show all five, Mail signs in to its demo account and reads, Photos opens, and Camera takes a photo. Performance measurement against the native apps is outstanding. +- **Implementation status:** News, Photos, Maps, Camera and Mail are built as script apps. News, Photos, Maps and Mail run on the desktop card host and in the phone shell (Android emulator: Mail's sign-in reached Gmail's POP3 server, and its demo account's password was sealed by the Android Keystore; the IMAP client was checked against Gmail's sign-in and a scripted server). Camera's capture path exists only in the Android and HarmonyOS backends and the emulator refuses the camera texture, so Camera awaits a real device. The native News, Photos and Maps crates were deleted on 2026-09-28 (native-apps ADR 0004 §1, [#113](https://github.com/OctoSense-org/OctoSense/pull/113)), before that measurement; the native Mail and Camera modules were removed on 2026-09-25, when their apps moved to Octoscript-AppCard as script bundles (since moved to OctoSense-System-Apps, `apps//bundle/`) (they remain in Git history). Ported from OctoSense-mobile into this Home on 2026-09-25 (both the standalone and the ROM variant link them; the makepad side rode a reviewed runtime patch until makepad#30 merged on 2026-09-26; the runtime now includes it) and run on the OnePlus 6 as a separate test package: the home tiles, dock and app list show all five, Mail signs in to its demo account and reads, Photos opens, and Camera takes a photo. Performance measurement against the native apps is outstanding. - **Scope:** First-party apps that ship with the shell and the ROM: which tier they run in and how they are packaged. It amends [ADR 0002](0002-agentic-app-security-model.md), where every first-party app is a trusted native module. - **Relates to:** [ADR 0003](0003-app-hub-and-store.md) (bundles, manifests, the card runner). @@ -54,7 +54,7 @@ Found by building these three apps; each fix is general, not app-specific. - A fault in one of these apps is contained to its isolate: it can exhaust its budget or its heap, not the shell. - These apps can be updated by rebuilding the bundle, and could later be delivered through the catalog like any other app. - Script is interpreted. Rows are built in script and each isolate entry is capped at 64 ms. The apps keep per-render work small (thumbnails rather than full images in grids, one render per refresh), and a virtualized script list is the next runtime step for long lists. -- The native News, Photos and Maps crates were to remain until on-device measurement on the OnePlus 6 showed the script apps at least as fast and as light. Like Mail and Camera before them, they were removed ahead of that measurement (2026-09-28, [#110](https://github.com/OctoSense-org/OctoSense/pull/110)), so the platform carries one version of each system app. +- The native News, Photos and Maps crates were to remain until on-device measurement on the OnePlus 6 showed the script apps at least as fast and as light. Like Mail and Camera before them, they were removed ahead of that measurement (2026-09-28, [#113](https://github.com/OctoSense-org/OctoSense/pull/113)), so the platform carries one version of each system app. ## Known gaps diff --git a/docs/architecture.md b/docs/architecture.md index 9e81702f..6292d04f 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -430,7 +430,7 @@ Found while writing this page (2026-09-28); none is fixed here, as this change i 2. **Restart of a dead process app.** ADR 0004 §2 says its tile shows it closed with a restart. The shell removes the client and posts "App stopped"; the Restart face exists only for in-process modules (`module_view.rs`). 3. **Agent workspace = account folder.** ADR 0004 §11 names it the `peer/prepare` `cwd`. The broker sends no `cwd` to `peer/prepare` and binds the peer to the kernel-provisioned workspace; the storage API's `agent_workspace` is not connected to it. The account folder name (`account_hash`, SHA-256) and the memory namespace tag (FNV-1a in `broker.rs`) are also different hashes of the account. 4. **ADR 0003 "What the profile runs"** says OctoSense configures neither the tool set nor the sandbox. Since [#117](https://github.com/OctoSense-org/OctoSense/pull/117) the shell writes a `tool_policy` denying `group:runtime` into the `_main` profile before every start, so the host's own turns have no octos shell either. -5. **Stale context lines.** ADR 0004's context table and the root README's layout table still mention native News, Maps and Photos comparison modules (`apps/*/native`); ADR 0004 step 1 deleted them. [ai-services.md](ai-services.md) is dated 2026-09-27: its architecture diagram shows "no `octos.*` service" for the Card runner (merged in #106), and it says contained apps are off "until first-use consent lands" (consent landed in #120; the `Policy::contained_apps` switch is still off by default). +5. **Stale context lines.** Fixed: ADR 0004's context table and the README layout tables no longer list the native News, Maps and Photos modules ADR 0004 step 1 deleted (#113). Still open: [ai-services.md](ai-services.md) is dated 2026-09-27: its architecture diagram shows "no `octos.*` service" for the Card runner (merged in #106), and it says contained apps are off "until first-use consent lands" (consent landed in #120; the `Policy::contained_apps` switch is still off by default). 6. **Command execution "turned on in Settings".** Fixed in the docs: `crates/kernel/README.md` and `system_tools.rs` now say it is planned (no Settings switch sets `SystemAgentTools::grant_command_execution`; the host tool needs octos#2567). 7. **`host::processes_available()`'s test** checks only `wasm32` while the function also excludes native mobile. 8. **Approvals, ADR 0004 §8.** Every app tool call is to reach the router through `peer/tool/call`; today only the AI bus feeds it (above). No app registers its own `confirm: app` sheet, so such a call would wait and be refused. The audit keeps a digest of the arguments, not the arguments. The send queue and undo window are not built. diff --git a/docs/architecture.zh-CN.md b/docs/architecture.zh-CN.md index 96b4c5f4..548966bb 100644 --- a/docs/architecture.zh-CN.md +++ b/docs/architecture.zh-CN.md @@ -430,7 +430,7 @@ sequenceDiagram 2. **崩溃进程应用的重启。** ADR 0004 §2 说它的磁贴会显示已关闭并提供重启。Shell 实际上移除客户端并发出 “App stopped” 通知;Restart 界面只用于进程内模块(`module_view.rs`)。 3. **Agent 工作区 = 账号目录。** ADR 0004 §11 说它就是 `peer/prepare` 的 `cwd`。broker 不向 `peer/prepare` 发送 `cwd`,把 peer 绑定到内核分配的工作区;存储 API 的 `agent_workspace` 没有与之连接。账号目录名(`account_hash`,SHA-256)和记忆命名空间标签(`broker.rs` 中的 FNV-1a)也是对账号的两种不同 hash。 4. **ADR 0003 的 “What the profile runs”** 说 OctoSense 既不配置工具集也不配置沙箱。自 [#117](https://github.com/OctoSense-org/OctoSense/pull/117) 起,Shell 每次启动前都向 `_main` profile 写入拒绝 `group:runtime` 的 `tool_policy`,因此宿主自己的回合也没有 octos shell。 -5. **过时的背景描述。** ADR 0004 的背景表格和根 README 的目录结构表仍提到原生 News、Maps 和 Photos 对比模块(`apps/*/native`);ADR 0004 步骤 1 已删除它们。[ai-services.zh-CN.md](ai-services.zh-CN.md) 的日期是 2026-09-27:其架构图显示 Card runner “没有 `octos.*` 服务”(#106 已合入),并说脚本应用“在首次使用同意落地之前”关闭(同意机制已在 #120 落地;`Policy::contained_apps` 开关默认仍关闭)。 +5. **过时的背景描述。** 已修复:ADR 0004 的背景表格和各 README 的目录结构表不再列出 ADR 0004 步骤 1 删除的原生 News、Maps 和 Photos 模块(#113)。仍未修复:[ai-services.zh-CN.md](ai-services.zh-CN.md) 的日期是 2026-09-27:其架构图显示 Card runner “没有 `octos.*` 服务”(#106 已合入),并说脚本应用“在首次使用同意落地之前”关闭(同意机制已在 #120 落地;`Policy::contained_apps` 开关默认仍关闭)。 6. **“在 Settings 中开启”命令执行。** 文档已修复:`crates/kernel/README.md` 和 `system_tools.rs` 现在说明它尚在计划中(没有 Settings 开关调用 `SystemAgentTools::grant_command_execution`;宿主工具需要 octos#2567)。 7. **`host::processes_available()` 的测试**只检查 `wasm32`,而函数本身还排除了原生移动平台。 8. **审批,ADR 0004 §8。** 每次应用工具调用都应通过 `peer/tool/call` 到达路由;目前只有 AI 总线向它提交请求(见上文)。没有应用注册自己的 `confirm: app` 面板,因此这类调用会等待后被拒绝。审计记录的是参数摘要而不是参数。发送队列和撤销窗口尚未实现。 diff --git a/phone/README.md b/phone/README.md index 73c6ac13..64865b75 100644 --- a/phone/README.md +++ b/phone/README.md @@ -46,7 +46,7 @@ cargo run --release -p octosense-home --features mobile-only | Switch | Effect | | --- | --- | -| `--features mobile-apps` | Also link the native modules (Reference, Sheets, and the native News, Photos and Maps, which then replace their script apps); not AppCard | +| `--features mobile-apps` | Also link the native modules Reference and Sheets; not AppCard | | `--features app-appcard` | Also link the AppCard assistant, which is not shipped by default for now | | `-- --module ` | Host a linked module in-process instead of as a child process | | `-- --test-action ` | Fire a shell action at startup (see [Run on a desktop](#run-on-a-desktop)) | @@ -182,7 +182,7 @@ MAKEPAD_APP_CONFIG='{"mail_demo":true}' cargo run --release -p octosense-home -- adb shell am start -n /.MakepadApp --es makepad.APP_CONFIG '{"mail_demo":true}' ``` -The earlier native News, Photos and Maps modules are deleted (native-apps ADR 0004 §1, [#110](https://github.com/OctoSense-org/OctoSense/pull/110)); +The earlier native News, Photos and Maps modules are deleted (native-apps ADR 0004 §1, [#113](https://github.com/OctoSense-org/OctoSense/pull/113)); none of the system apps has a native module any more. ### The octos kernel diff --git a/phone/README.zh-CN.md b/phone/README.zh-CN.md index 3792bd5d..98a44a0b 100644 --- a/phone/README.zh-CN.md +++ b/phone/README.zh-CN.md @@ -22,7 +22,7 @@ cargo run --release -p octosense-home --features mobile-only | 开关 | 作用 | | --- | --- | -| `--features mobile-apps` | 同时链接原生模块(Reference、Sheets,以及原生的 News、Photos 和 Maps,它们会替代对应的脚本应用);不包括 AppCard | +| `--features mobile-apps` | 同时链接原生模块 Reference 和 Sheets;不包括 AppCard | | `--features app-appcard` | 同时链接 AppCard 助手,它目前默认不随产品发布 | | `-- --module ` | 在进程内托管已链接的模块,而不是作为子进程 | | `-- --test-action ` | 启动时触发一个 Shell 动作(见[在桌面电脑上运行](#在桌面电脑上运行)) | @@ -114,7 +114,7 @@ MAKEPAD_APP_CONFIG='{"mail_demo":true}' cargo run --release -p octosense-home -- adb shell am start -n /.MakepadApp --es makepad.APP_CONFIG '{"mail_demo":true}' ``` -早期的原生 News、Photos 和 Maps 模块已删除(原生应用 ADR 0004 §1,[#110](https://github.com/OctoSense-org/OctoSense/pull/110));所有系统应用都不再有原生模块。 +早期的原生 News、Photos 和 Maps 模块已删除(原生应用 ADR 0004 §1,[#113](https://github.com/OctoSense-org/OctoSense/pull/113));所有系统应用都不再有原生模块。 ### octos 内核 From 678e41c8b3a75358c97d16076e2be9c64f71c663 Mon Sep 17 00:00:00 2001 From: ymote <151983+ymote@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:54:30 -0700 Subject: [PATCH 5/5] docs(adr-0004): list the follow-ups found after acceptance [skip ci] A "Follow-ups" section at the end of the Plan: dev.run registration (octos#2567), developer mode per app in Settings and the phone gesture, the system agent's exact tool list (octos#2567 M1), the Settings switch for its command execution, peer/prepare's cwd as the account folder with one account hash for folders (SHA-256) and memory tags (FNV-1a, with a migration note), and a shell-native chat with the system agent. Docs only. Co-Authored-By: Claude Opus 5.5 --- docs/adr/0004-native-apps-hosting-and-peers.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/adr/0004-native-apps-hosting-and-peers.md b/docs/adr/0004-native-apps-hosting-and-peers.md index 4f879b79..22a194ea 100644 --- a/docs/adr/0004-native-apps-hosting-and-peers.md +++ b/docs/adr/0004-native-apps-hosting-and-peers.md @@ -320,6 +320,17 @@ How it is turned on and kept from leaking into normal use: 10. The storage layout and contract (section 11): App Hub's `storage` fields; the host paths and secrets APIs; Rinx and the host services move under `apps/` and `secrets/` (the Rinx move, #101, and any App Hub pin move through the tagged-Rinx rule and the lockstep fix, hagency-org/Rinx#37); the startup check. 11. Developer mode (section 13): the developer profile, the grants, `dev.run`, the banner and audit, and a test that an external client gets neither developer grants nor `dev.run`; `terminal.run` as a confirmed shareable tool (section 12). +### Follow-ups + +Gaps between this decision and `main` found after it was accepted (2026-09-28; see [the architecture overview](../architecture.md#where-the-code-and-the-adrs-disagree)): + +- **`dev.run` registration** (section 13) waits on octos#2567's host tool registration. +- **Developer mode per app** (section 13): choosing which apps it covers in Settings (today only through `OCTOSENSE_DEV_MODE`), and the phone gesture that turns it on. +- **The system agent's exact tool list** (section 12, step 4): the `_main` profile's `tool_policy` is a ceiling, not the list; the exact list needs octos#2567's session tool lists (its review item M1). +- **The Settings switch for the system agent's command execution** (section 12): `SystemAgentTools::grant_command_execution` exists, but no Settings switch sets it, and its host tool needs octos#2567. +- **The agent workspace is the account folder** (section 11): `peer/prepare` is to get the account folder as its `cwd` (today the broker sends none and the peer uses the kernel-provisioned workspace). The account folder name (SHA-256, `app_storage`'s `account_hash`) and the memory namespace tag (FNV-1a, `account_tag` in the `crates/app-peers` broker) are two different hashes of one account; one should derive from the other. Changing the memory tag re-keys every app's memory, so it needs a migration (or the folder name follows the tag). +- **A shell-native chat with the system agent**: today only a paired Talk to Octos client reaches it; the desktop's AI pane is Makepad's `aichat`, not the system agent. + ## Open questions - D1 is decided on #110 (section 7): app agents and the system agent may call other apps' granted tools, and the shell authorizes each call.