Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ab59020
docs(webui): the engine layer has six files, not five (webui-parity 107)
fengzhi09 Oct 1, 2026
1dc559a
test(webui): M2 capability-declaration snapshot vs the real host (eng…
fengzhi09 Oct 1, 2026
8c085fa
test(webui): point the capability snapshot at the engine layer's real…
fengzhi09 Oct 1, 2026
aa5ab47
fix(webui): stop the shell from carrying one session's state into ano…
fengzhi09 Oct 1, 2026
af01e0e
refactor(webui): the plugins and turn-diff routes take the host from …
fengzhi09 Oct 1, 2026
f1842ba
test(webui): make the run-mirror, first-turn-guard and mavis-usage su…
fengzhi09 Oct 1, 2026
726d286
refactor(webui): the plugins and turn-diff routes take the host from …
fengzhi09 Oct 1, 2026
a4fad96
test(webui): make the run-mirror, first-turn-guard and mavis-usage su…
fengzhi09 Oct 1, 2026
e7c0ce9
feat(webui): the five read endpoints ask the engine facade, not the t…
fengzhi09 Oct 1, 2026
e053ae7
feat(webui): the session-tree and export endpoints ask the engine fac…
fengzhi09 Oct 1, 2026
4fb8267
feat(webui): the usage endpoints ask the engine facade, and the deriv…
fengzhi09 Oct 1, 2026
88b9a48
fix(webui): rebase M3-B3 onto M3-B2, register B2's two tmp prefixes, …
fengzhi09 Oct 1, 2026
6bc24bd
feat(webui): the account, model and capability reads ask the engine f…
fengzhi09 Oct 2, 2026
eb2a429
feat(webui): #73 swaps the ACP wire table for the 14-key engine-capab…
fengzhi09 Oct 2, 2026
2baf051
fix(webui): stop two B4 comments describing behaviour the code no lon…
fengzhi09 Oct 2, 2026
edf2b1e
feat(webui): move the session write family behind the engine facade
fengzhi09 Oct 2, 2026
1506cc2
fix(webui): drop whitespace text nodes in markdown tables and dedupe …
fengzhi09 Oct 2, 2026
8cca235
fix(webui): sweep the non-flipping inverted text token off primary su…
fengzhi09 Oct 2, 2026
eecd8c0
feat(webui): move session switch behind the engine facade
fengzhi09 Oct 2, 2026
0cfd51f
Merge main into dev-lhl
fengzhi09 Oct 2, 2026
e4cf052
chore: allowlist the leak-tripwire fixture in model-reads tests
fengzhi09 Oct 2, 2026
3f5b8d2
test(webui): pin session-writes cleanup-orphans test to isolated paths
fengzhi09 Oct 2, 2026
e7df93d
chore: ignore gitleaks fingerprints of deliberate test fixtures
fengzhi09 Oct 2, 2026
62814ff
chore: make the gitleaks fixture allowlists path-only
fengzhi09 Oct 2, 2026
3074010
feat(webui): move interrupt and load endpoints behind the engine facade
fengzhi09 Oct 3, 2026
063a43a
fix(webui): take the plan's 5s abort force-kill bound by product call
fengzhi09 Oct 3, 2026
90cf85e
Merge main into dev-lhl
fengzhi09 Oct 3, 2026
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
9 changes: 5 additions & 4 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,10 @@ regexTarget = "match"
regexes = ['''^[A-Za-z_$][A-Za-z0-9_$]*\.setRsaPrivateKey = [A-Za-z_$][A-Za-z0-9_$]*\.rsa\.setPrivateKey ?$''', '''^[A-Za-z_$][A-Za-z0-9_$]*\.privateKeyToAsn1 = [A-Za-z_$][A-Za-z0-9_$]*\.privateKeyToRSAPrivateKey ?$''', '''^[A-Za-z_$][A-Za-z0-9_$]*\.generateKey = [A-Za-z_$][A-Za-z0-9_$]*\.pbe\.generatePkcs12Key;?$''']

[[rules.allowlists]]
description = "Leak-prevention tripwire fixture: asserts the facade never serializes this fake key"
condition = "AND"
description = "Leak-prevention tripwire fixture: asserts the facade never serializes fake provider keys"
paths = ['''(^|/)packages/webui/test/lib/engine/model-reads\.test\.js$''']
regexTarget = "match"
regexes = ['''apiKey: "sk-secret-should-never-leak"''']

[[rules.allowlists]]
description = "Credential-guard fixture: fake canary key material asserts the 403 guard"
paths = ['''(^|/)packages/webui/test/routes/fs-credential-guard\.test\.js$''']

7 changes: 7 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# gitleaks fingerprints for deliberate fake-credential fixtures in tests.
# Both files exist to handle fake key material (a leak-prevention tripwire and
# a credential-guard canary); the flagged content is synthetic by construction.
985b78803621f04efa6498384319ed588b361dff:packages/webui/test/routes/fs-credential-guard.test.js:private-key:79
985b78803621f04efa6498384319ed588b361dff:packages/webui/test/routes/fs-credential-guard.test.js:private-key:81
985b78803621f04efa6498384319ed588b361dff:packages/webui/test/lib/engine/model-reads.test.js:generic-api-key:149
985b78803621f04efa6498384319ed588b361dff:packages/webui/test/lib/engine/model-reads.test.js:generic-api-key:117
67 changes: 64 additions & 3 deletions packages/webui/server/engine/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
// catalogue host itself is now reached through this facade too
// (engine/host.js), so the plugins and turn-diff routes no longer name
// lib/acp-client.js. M3 batches B1 (#9 #10 #72 #74 #75), B2 (#8 #11),
// B3 (#15 #16 #17 #19), B4 (#20 #57 #73), B5 (#7 #4 #6) and B6 (#3)
// done. The rest of M3, then M4, will route their consumers through
// this facade one endpoint family at a time.
// B3 (#15 #16 #17 #19), B4 (#20 #57 #73), B5 (#7 #4 #6), B6 (#3) and
// B7 (#13 #69 #70 #71) done. The rest of M3, then M4, will route their
// consumers through this facade one endpoint family at a time.

import { ENGINE_CAPABILITY_KEYS } from "./capabilities.js";
// Declarations only — importing the provider *host-construction* modules
Expand Down Expand Up @@ -262,6 +262,67 @@ export {
} from "./session-switch.js";
export { LOCAL_RUNTIME_V2_CAPABILITIES } from "./providers/local-runtime-v2.capabilities.js";
export { TUI_RUNTIME_ADAPTER_CAPABILITIES } from "./providers/tui-runtime-adapter.js";
// The INTERRUPT family (step M3, batch B7): #13 POST /api/stop, #69
// POST /api/protocol/cancel. Same cycle, same TDZ rule, same reasoning
// as session-reads.js above: interrupt.js reads NOTHING from this module
// at module scope — its `INTERRUPT_ENDPOINTS` table is a literal and
// every binding it needs (`getEngineProvider`,
// `DEFAULT_ENGINE_PROVIDER_ID`) is read inside a function body. A new
// top-level `const X = SOMETHING_FROM_INDEX` in interrupt.js breaks the
// re-export exactly as it would in session-reads.js. Its ONLY static
// imports are `engine/index.js` and the node builtins; the state bus,
// the RPC wrapper and the config are reached through `await import()`
// inside the data-plane functions, which is what keeps the escalation
// timer and the kill cascade off the boot path.
//
// It gates SOFT for both endpoints, and the reason is endpoint-specific
// rather than family-wide: #13's escalation is webui's own
// child-process management and its zombie-claim reset is the user's
// only escape hatch from a stuck run, so hard-gating it would delete a
// working endpoint over a doubt about its GENTLE half; #69 already has
// a truthful "I could not deliver it" shape as its documented contract.
// The 501 machinery stays unused by this family, and the suite pins that.
export {
INTERRUPT_ENDPOINTS,
STOP_FORCE_KILL_MS,
applyEngineStop,
checkInterruptCapability,
resolveInterruptProvider,
sendEngineSessionCancel,
stopLeftStaleClaim,
} from "./interrupt.js";
// The LOAD / ACTIVATE family (step M3, batch B7): #70
// POST /api/protocol/load-session, #71
// POST /api/protocol/activate-session. Same cycle, same TDZ rule, same
// reasoning: session-load.js's `SESSION_LOAD_ENDPOINTS` table is a
// literal and every binding it needs is read inside a function body; a
// new top-level `const X = SOMETHING_FROM_INDEX` there breaks this
// re-export exactly as it would anywhere else. Its only static imports
// are `engine/capabilities.js` and `engine/index.js`.
//
// This is the one M3 family that carries BOTH gate forms, and the split
// is a decision rather than an inconsistency: #70 gates HARD on
// `sessionCrud` · `loadSession`, because a "success" that skipped the
// engine would write a sidebar entry for a session the engine never
// loaded — the fake success the gate exists to prevent — while #71 gates
// SOFT, because hard-gating it would be silently answering the
// activate-semantic-collapse question the plan leaves open (semantic
// collapse vs 501). Both branches are costed in that module's KNOWN
// DEBT 1. Two functions, one family, one store, one route module:
// splitting it would duplicate the transport table, the resolver and
// the status mappers to preserve a distinction one `enforcement` field
// wide.
export {
SESSION_LOAD_ENDPOINTS,
activateEngineSession,
activateFailureStatus,
assertSessionLoadCapability,
checkSessionActivateCapability,
loadEngineSession,
loadFailureStatus,
loadFailureWireCode,
resolveSessionLoadProvider,
} from "./session-load.js";

/**
* Registered providers. `transport` records which wire form the provider
Expand Down
Loading
Loading