Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/desktop/src/main/engine/local-models/run-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export function admitLocalConfiguration(read: ConfigRead, requirements: Requirem
want("model_reasoning_summary", config.model_reasoning_summary ?? null, null);
const features = record(config.features);
want("features.view_image", features?.view_image ?? null, false);
want("features.multi_agent", features?.multi_agent ?? null, false);
want("features.multi_agent_v2", features?.multi_agent_v2 ?? null, false);
const servers = record(config.mcp_servers);
if (servers && Object.keys(servers).length) refuse(`MCP servers are configured (${Object.keys(servers).join(", ")}).`);
return { sessionFlags, layers: summary, managedRequirements: false };
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/test/local-model-execution.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ test("a configuration another layer governs, managed requirements or a Codex wit
const cases: [string, Parameters<typeof setup>[0], RegExp][] = [
["managed base_url", { configRead: r => { r.origins["model_providers.modex_local.base_url"] = { name: { type: "system", file: "/etc/codex/config.toml" }, version: "sha256:m" }; return r; } }, /the system configuration at \/etc\/codex\/config.toml sets `model_providers.modex_local.base_url`/],
["effective destination", { configRead: r => { r.config.model_providers.modex_local.base_url = "https://api.openai.com/v1"; return r; } }, /`model_providers.modex_local.base_url` is "https:\/\/api.openai.com\/v1"/],
["enabled multi_agent", { configRead: r => { r.config.features.multi_agent = true; return r; } }, /`features\.multi_agent` is true/],
["missing multi_agent", { configRead: r => { delete r.config.features.multi_agent; return r; } }, /`features\.multi_agent` is null/],
["enabled multi_agent_v2", { configRead: r => { r.config.features.multi_agent_v2 = true; return r; } }, /`features\.multi_agent_v2` is true/],
["missing multi_agent_v2", { configRead: r => { delete r.config.features.multi_agent_v2; return r; } }, /`features\.multi_agent_v2` is null/],
["requirements", { requirements: { allowedSandboxModes: ["read-only"] } }, /managed requirements/],
["old codex", { configRead: () => new Error("Method not found: config/read") }, /did not report its effective configuration \(Method not found: config\/read\)\. Local execution needs codex-cli 0.164.0 or later/],
];
Expand Down
22 changes: 18 additions & 4 deletions apps/desktop/test/local-run-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ const EXPECTED = { provider: "modex_local", origin: "http://127.0.0.1:18501", co
const FLAGS = "sha256:b3932b4abe963781145150a5f8db02bf0afb5fe03385d52c15122db85463fce3";
const EMPTY = "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a";

/** The shape codex-cli 0.164.0 returned for an LM-3 child on 2026-10-27 (docs/reviews/2026-10-27-lm5-destination-policy.md), trimmed to what the policy reads. */
/** The shape codex-cli 0.164.0 returned for an LM-3 child on 2026-10-27 (docs/reviews/2026-10-27-lm5-destination-policy.md), trimmed to what the policy reads, with subagent flags verified by the 2026-10-30 codex-cli 0.166.0 configuration-only probe. */
function read(): ConfigRead {
const flags = {
model_provider: "modex_local",
model_providers: { modex_local: { name: "Modex local", base_url: "http://127.0.0.1:18501/v1", wire_api: "responses", requires_openai_auth: false, env_key: "MODEX_LOCAL_TOKEN", request_max_retries: 0 } },
model_context_window: 32768, web_search: "disabled", features: { view_image: false }, shell_environment_policy: { exclude: ["MODEX_LOCAL_TOKEN"] },
model_context_window: 32768, web_search: "disabled", features: { view_image: false, multi_agent: false, multi_agent_v2: false }, shell_environment_policy: { exclude: ["MODEX_LOCAL_TOKEN"] },
};
const origin = { name: { type: "sessionFlags" }, version: FLAGS };
return {
config: { model: null, model_provider: "modex_local", model_context_window: 32768, web_search: "disabled", model_reasoning_summary: null, openai_base_url: null, mcp_servers: {},
model_providers: { modex_local: { ...flags.model_providers.modex_local, experimental_bearer_token: null, auth: null, http_headers: null, env_http_headers: null, query_params: null } },
features: { view_image: false, mentions_v2: true, remote_control: false }, file_opener: "vscode" },
features: { view_image: false, multi_agent: false, multi_agent_v2: false, mentions_v2: true, remote_control: false }, file_opener: "vscode" },
origins: Object.fromEntries(["model_provider", "model_providers.modex_local.name", "model_providers.modex_local.base_url", "model_providers.modex_local.wire_api", "model_providers.modex_local.requires_openai_auth",
"model_providers.modex_local.env_key", "model_providers.modex_local.request_max_retries", "model_context_window", "web_search", "features.view_image", "shell_environment_policy.exclude.0"].map(k => [k, origin])),
"model_providers.modex_local.env_key", "model_providers.modex_local.request_max_retries", "model_context_window", "web_search", "features.view_image", "features.multi_agent", "features.multi_agent_v2.enabled", "shell_environment_policy.exclude.0"].map(k => [k, origin])),
layers: [{ name: { type: "sessionFlags" }, version: FLAGS, config: flags }, { name: { type: "user", file: "/tmp/process-x/.codex/config.toml", profile: null }, version: EMPTY, config: {} }, { name: { type: "system", file: "/etc/codex/config.toml" }, version: EMPTY, config: {} }],
};
}
Expand Down Expand Up @@ -94,3 +94,17 @@ test("governed keys and layer descriptions", () => {
assert.equal(describeLayer({ type: "sessionFlags" }), "Modex's session settings");
assert.equal(describeLayer({ type: "something_new" }), "a something_new configuration layer");
});

for (const flag of ["multi_agent", "multi_agent_v2"] as const) {
for (const value of [true, undefined, null, "false", { enabled: true }]) {
test(`local admission refuses ${flag}=${JSON.stringify(value) ?? "missing"}`, () => {
const reported = read();
const features = reported.config.features as Record<string, unknown>;
if (value === undefined) delete features[flag];
else features[flag] = value;
assert.throws(() => admitLocalConfiguration(reported, { requirements: null }, EXPECTED),
error => error instanceof Error && error.message.includes(`features.${flag}`),
"unqualified native subagents must be refused before any thread opens");
});
}
}
13 changes: 13 additions & 0 deletions docs/reviews/2026-10-30-lm5-subagent-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# LM-5 effective subagent admission — 2026-10-30

Issue #380 requires unqualified native subagents to stay disabled. LocalExecution already passes `features.multi_agent=false` and `features.multi_agent_v2=false`, but admission verified only the effective image flag. A pure-policy probe using a modified historical receipt admitted either subagent flag as true. This establishes a missing effective-value check, not observed native subagent execution.

Admission now requires both effective subagent flags to be explicitly false. True, missing, null, string and object values are refused by key before a native thread opens. Existing layer/provenance, destination and credential checks remain in force. A CLI that omits either flag is refused rather than treated as qualified; product local execution remains unadmitted.

A configuration-only probe of installed codex-cli 0.166.0 in a temporary empty home reported both flags false and their origins as session flags. `features list` also reported both stable and false. The probe created no thread, sent no prompts and ran no inference. Its [trimmed receipt](2026-10-30-lm5-subagent-policy/config-receipt.json) supports the reported configuration shape, not offline execution or qualification of older CLI versions.

## Verification

The clean baseline passed build and full unit checks (2,244 passes, 26 skips). Ten new pure-policy cases first failed because no exception was thrown. After the two effective-value checks, the focused policy/execution suites passed 26 tests with no failures or skips. Execution fixtures also verify that enabled and missing values produce a failed turn with no `thread/start`, no `turn/start` and no admitted provenance. Final `pnpm build && pnpm test` completed with exit 0: 2,254 passes, 26 skips and zero failures. Independent read-only review found no blocking findings. Protected delivery remains pending.

Logs are preserved outside the worktree under `~/Documents/Codex/artifacts/modex-land-and-prune/lm5-subagent-*`. This repair addresses an admission invariant only. The native offline canary, full auxiliary matrix, capacity/runtime qualification, entry-point policy, context evidence and human acceptance remain open; #380 is not complete.
50 changes: 50 additions & 0 deletions docs/reviews/2026-10-30-lm5-subagent-policy/config-receipt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"cli": "0.166.0",
"scope": "configuration-only in temporary empty home; no thread or inference",
"features": {
"multi_agent_v2": false,
"network_proxy": null,
"multi_agent": false,
"api_key_cyber_access_programs": true,
"api_key_model_discovery": true,
"auth_elicitation": true,
"background_paginated_rollout_migration": false,
"codex_apps_mcp_2026_07_28": false,
"mcp_2026_07_28": false,
"mcp_connection_sharing": false,
"memories": false,
"mentions_v2": true,
"remote_control": false,
"remote_plugin": true,
"tool_suggest": true,
"windows_sandbox_service": false
},
"origins": {
"features.multi_agent": {
"name": {
"type": "sessionFlags"
},
"version": "sha256:a9409150a66a83ac8ffe500daa6eba5fe887b9beb82608cc9a59f0f8ddf58548"
},
"features.multi_agent_v2.enabled": {
"name": {
"type": "sessionFlags"
},
"version": "sha256:a9409150a66a83ac8ffe500daa6eba5fe887b9beb82608cc9a59f0f8ddf58548"
}
},
"session_flags": [
{
"name": {
"type": "sessionFlags"
},
"version": "sha256:a9409150a66a83ac8ffe500daa6eba5fe887b9beb82608cc9a59f0f8ddf58548",
"config": {
"features": {
"multi_agent": false,
"multi_agent_v2": false
}
}
}
]
}
2 changes: 2 additions & 0 deletions docs/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ The published application source is `2eda138` (v0.4.0). Later source deliveries

- **Notes history identity repair.** Repeated history toggles could duplicate revision rows or leave history visible after closing because the history and editor siblings shared a React key. The isolated `notes-history-identity` repair gives them distinct identities; three regression repetitions failed before the fix and passed afterward. Independent review found no blockers. Build and full unit/E2E checks passed (2,191 unit passed, 23 skipped; 470 desktop passed, seven skipped; seven site passed). Protected delivery landed in #429 (`7a01df2`); its successful merge-queue run passed 473 desktop tests with four skips and seven site tests. See [repair evidence](reviews/2026-10-28-notes-history-identity.md).

- **LM-5 effective subagent admission.** A reproduced policy gap accepted enabled native subagent flags despite disabled launch settings. The repair requires both effective values to be false; ten regressions failed before the fix, and 26 focused policy/execution tests now pass, including refusal before a native thread opens. A configuration-only CLI 0.166.0 probe confirms the explicit false report shape. Build and full unit validation passed (2,254 passes, 26 skips); independent review found no blocking findings. Protected delivery remains pending; native qualification stays separate. [Evidence](reviews/2026-10-30-lm5-subagent-policy.md).

- **LM-2 credential repair, included in v0.4.0.** PR #418 delivered the credential-copy and stale-discovery fixes from closed #401, together with isolation that prevents fake child PIDs from reaching OS signals, at `6c9000f`. Build, full unit tests, typechecks and the Electron IPC journey are recorded in the [reconciliation evidence](reviews/2026-10-26-lm2-credential-repair.md). This source delivery is separate from local-runtime qualification and product admission.

- **v0.4.0 post-publication acceptance and Companion 0.4.0 (9).** Desktop publication is complete. The v0.3.0-to-v0.4.0 background upgrade remains unverified: the installed Mac already reports signed 0.4.0 and was left unchanged. Companion build 9 has not been delivered by this release session; its TestFlight upload and physical-device checks remain separate. Human accessibility, real-provider and native-platform account/session checks retain their existing gates. [Publication evidence and limits](reviews/2026-10-24-v0.4.0-release-review.md#published--2026-10-30-utc).
Expand Down
Loading