machine-bridge-mcp 0.12.1 → 0.13.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.
- package/CHANGELOG.md +37 -0
- package/README.md +6 -4
- package/SECURITY.md +5 -1
- package/browser-extension/manifest.json +2 -2
- package/docs/AGENT_CONTEXT.md +16 -6
- package/docs/ARCHITECTURE.md +14 -6
- package/docs/AUDIT.md +25 -1
- package/docs/CLIENTS.md +1 -1
- package/docs/ENGINEERING.md +5 -4
- package/docs/LOCAL_AUTOMATION.md +1 -1
- package/docs/LOGGING.md +3 -1
- package/docs/OPERATIONS.md +6 -1
- package/docs/PRIVACY.md +8 -3
- package/docs/RELEASING.md +5 -5
- package/docs/TESTING.md +11 -9
- package/package.json +6 -2
- package/scripts/github-release.mjs +28 -0
- package/scripts/privacy-check.mjs +150 -2
- package/scripts/release-ci.mjs +18 -0
- package/src/local/agent-context.mjs +75 -18
- package/src/local/app-automation.mjs +15 -1
- package/src/local/atomic-fs.mjs +14 -2
- package/src/local/browser-bridge.mjs +3 -1
- package/src/local/capability-observer.mjs +56 -0
- package/src/local/default-instructions.mjs +21 -91
- package/src/local/network-proxy.mjs +34 -0
- package/src/local/process-sessions.mjs +7 -0
- package/src/local/project-package.mjs +234 -0
- package/src/local/relay-connection.mjs +26 -0
- package/src/local/runtime.mjs +21 -20
- package/src/shared/tool-catalog.json +4 -4
- package/src/worker/index.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.13.0 - 2026-07-13
|
|
4
|
+
|
|
5
|
+
### Automatic capability routing and observability
|
|
6
|
+
|
|
7
|
+
- Register bounded `package.*` commands from safe root `package.json` script names, while preserving explicit manifest override/deletion and never injecting script bodies. Windows uses a fixed `cmd.exe` wrapper for package-manager shims; Unix keeps direct executable argv. Extend default skill discovery to project `.codex/skills` and unrestricted `CODEX_HOME/skills` compatibility roots.
|
|
8
|
+
- Match installed applications by their actual names for every canonical-full task instead of requiring generic “app/window” words, with a bounded discovery cache to avoid repeated filesystem scans.
|
|
9
|
+
- Normalize a bounded set of common English inflections and Chinese workflow intents before skill/command ranking, and weight capability-name matches above incidental description overlap. This fixes Chinese selection of `skill-creator`, `smart-search-cli`, and `skill-installer` and prevents generic “create” wording from preferring unrelated design skills.
|
|
10
|
+
- Record privacy-preserving bootstrap and task-resolution telemetry in `server_info` and `project_overview`: counts, timestamps, source/load flags, selected capability metadata, and a runtime-keyed task fingerprint rather than raw task text. Suppress weak skill-overlap recommendations and clarify that the MCP host still controls whether the resolver and recommended tools are invoked.
|
|
11
|
+
|
|
12
|
+
### Process and network lifecycle
|
|
13
|
+
|
|
14
|
+
- Consolidate graceful process-tree termination plus forced escalation. Timeout, cancellation, and replacement now retain the escalation timer after the direct child exits, preventing a SIGTERM-resistant descendant with detached stdio from surviving as an orphan.
|
|
15
|
+
- Add relay support for standard `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` routing through a reviewed HTTP(S) proxy agent. Invalid proxy URLs or unsupported proxy protocols fail fast with corrective guidance; status exposes only direct/proxy/invalid route state and never proxy URLs or credentials.
|
|
16
|
+
|
|
17
|
+
### Architecture, tests, and documentation
|
|
18
|
+
|
|
19
|
+
- Extract package metadata/command discovery and capability observation into focused modules, add domain-to-adapter import-boundary checks, remove duplicate object fields, and centralize reused metadata parsing.
|
|
20
|
+
- Add behavior-level regression coverage for automatic package commands, direct `.codex/skills` compatibility, capability telemetry privacy, application-cache refresh, proxy selection/failure, and the direct-child-exits-first orphan-process boundary. Synchronize architecture, operations, logging, security, testing, and agent-context documentation.
|
|
21
|
+
|
|
22
|
+
## 0.12.2 - 2026-07-12
|
|
23
|
+
|
|
24
|
+
### Cross-platform persistence and browser reliability
|
|
25
|
+
|
|
26
|
+
- Extend transient Windows atomic replacement from eight short linear retries to sixteen bounded exponential retries with jitter. The implementation continues to use one same-directory atomic rename and never falls back to deleting the destination, while tolerating longer antivirus/indexer/reader sharing windows.
|
|
27
|
+
- Eliminate a broker-test race that could miss the runtime `hello` message between WebSocket `open` and listener registration. Pairing HTTP requests and WebSocket open/message/close waits are now bounded, and failed proxy candidates are terminated so a handshake cannot retain the test process indefinitely.
|
|
28
|
+
|
|
29
|
+
### CI, release, and supply-chain integrity
|
|
30
|
+
|
|
31
|
+
- Require a completed successful push-triggered GitHub Actions run for the exact `origin/main` commit before creating or verifying a version tag, GitHub Release, or release asset. A local test pass is necessary but no longer sufficient for publication.
|
|
32
|
+
- Pin all third-party GitHub Actions to immutable commit SHAs, retain Dependabot updates, and enforce the pinning plus the release-CI wiring through architecture and dedicated release-gate tests.
|
|
33
|
+
- Run a reachable-history privacy audit in the package-audit job. The scanner covers historical UTF-8 blob contents, historical paths, and commit messages without printing matched values, while narrowly ignoring the standard public Dependabot signing trailer.
|
|
34
|
+
|
|
35
|
+
### Regression coverage and audit follow-up
|
|
36
|
+
|
|
37
|
+
- Add deterministic tests for twelve consecutive transient Windows replacement failures, exponential delay selection, lost browser handshakes, bounded socket waits, portable simulated-Linux launcher paths on Windows, POSIX-versus-Windows daemon-stop semantics, deleted historical credential blobs, public automation trailers, and successful/failed/pending release CI states.
|
|
38
|
+
- Update the architecture, engineering, privacy, testing, release, security, and audit documentation. Record remaining immutable Git-history identity metadata separately from current-tree and active-credential findings.
|
|
39
|
+
|
|
3
40
|
## 0.12.1 - 2026-07-12
|
|
4
41
|
|
|
5
42
|
### Real local automation corrections
|
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ Two lower-precedence virtual sources are generated in memory:
|
|
|
128
128
|
- `machine-bridge://defaults/working-agreements` supplies conservative cross-project rules for inspection, scoped changes, preservation of unrelated work, validation, security, Git discipline, and explicit authorization for deployment/publication/destructive operations.
|
|
129
129
|
- `machine-bridge://project-context/current` derives bounded facts from the active repository: target path, common project/build files, package-manager declarations and lockfiles, package script names, runtime constraints, documentation files, and CI entrypoints. It never injects package-script bodies or source contents and does not claim commands were validated.
|
|
130
130
|
|
|
131
|
-
No files are created or modified by this bootstrap. Explicit user and repository instructions load later and therefore override the defaults. `session_bootstrap` supplies the chain during MCP initialization; `agent_context` exposes every source and hash; `resolve_task_capabilities` refreshes project facts, instructions, skills, and
|
|
131
|
+
No files are created or modified by this bootstrap. Explicit user and repository instructions load later and therefore override the defaults. `session_bootstrap` supplies the chain during MCP initialization; `agent_context` exposes every source and hash; `resolve_task_capabilities` refreshes project facts, instructions, skills, commands, and installed-application matches for the current task. `server_info` and `project_overview` expose whether bootstrap and task resolution actually reached the local runtime without retaining raw task text.
|
|
132
132
|
|
|
133
133
|
Optional user-global preferences still live in `~/.config/machine-bridge-mcp/agent.json`:
|
|
134
134
|
|
|
@@ -153,7 +153,7 @@ To disable either automatic layer globally:
|
|
|
153
153
|
|
|
154
154
|
Repositories cannot disable these user-level controls. Editing instruction files or project metadata does not require a daemon restart; start a new MCP conversation or reconnect when initialization-time injection must be guaranteed from the beginning.
|
|
155
155
|
|
|
156
|
-
Skill discovery follows Codex-style progressive disclosure. Default roots
|
|
156
|
+
Skill discovery follows Codex-style progressive disclosure. Default project roots include target-to-project `.agents/skills` and `.codex/skills`; unrestricted policy also enables `~/.agents/skills`, `CODEX_HOME/skills` (normally `~/.codex/skills`), and the Unix admin root. Newly added or edited skills are found on the next resolver/list call without restarting the daemon. Safe root `package.json` script names are also exposed as `package.*` command aliases with bounded deterministic English/Chinese workflow-intent terms; explicit `.machine-bridge/agent.json` commands can override or delete them. Package-script bodies are never injected, but invoking one still runs repository-controlled code with the active local policy. See [Session instructions, defaults, skills, commands, and capability discovery](docs/AGENT_CONTEXT.md).
|
|
157
157
|
|
|
158
158
|
Under canonical `full`, Machine Bridge also exposes structured local automation:
|
|
159
159
|
|
|
@@ -170,7 +170,7 @@ machine-mcp browser status
|
|
|
170
170
|
|
|
171
171
|
Load the printed unpacked-extension directory once in Chrome, Edge, Brave, Vivaldi, or another compatible Chromium browser. The extension badge reports connection state, and clicking it opens the saved local pairing page. The local pairing token remains in owner-only state and the loopback pairing page; it is not returned through MCP. For a mass-market release, distribute the same extension as a signed browser-store build rather than asking end users to enable Developer mode. See [Local application and browser automation](docs/LOCAL_AUTOMATION.md).
|
|
172
172
|
|
|
173
|
-
Machine Bridge can discover, refresh, rank, and load capabilities automatically. The ChatGPT/MCP host still owns tool selection and approval, so the server cannot force a host to expose or invoke a recommended skill, command, app, or browser operation.
|
|
173
|
+
Machine Bridge can discover, refresh, rank, and load capabilities automatically. The ChatGPT/MCP host still owns tool selection and approval, so the server cannot force a host to expose or invoke a recommended skill, command, app, or browser operation. Check `server_info.observability.capability_routing` or `project_overview.capabilityRouting` to distinguish “the host never called the resolver” from “the resolver ran but found no relevant capability.”
|
|
174
174
|
|
|
175
175
|
## Policy controls
|
|
176
176
|
|
|
@@ -357,7 +357,7 @@ Managed jobs are non-interactive and persist independently of the MCP connection
|
|
|
357
357
|
|
|
358
358
|
### Processes
|
|
359
359
|
|
|
360
|
-
- `run_local_command` —
|
|
360
|
+
- `run_local_command` — fixed argv execution of an explicit or automatic package-script command
|
|
361
361
|
- `run_process` — one-shot argv execution without a shell
|
|
362
362
|
- `start_process`
|
|
363
363
|
- `read_process`
|
|
@@ -424,6 +424,8 @@ Default state roots:
|
|
|
424
424
|
|
|
425
425
|
State/config writes use owner-only temporary files, `fsync`, and atomic replacement. Exclusive locks are fully written before a same-directory hard-link claim becomes visible; lock ownership includes a token and process start time so PID reuse and lock replacement cannot silently transfer ownership. Only successfully read but invalid JSON is retained as a bounded corrupt backup; permission, symbolic-link, size, encoding, and I/O failures remain explicit. A custom state root must not equal, contain, or be contained by the selected workspace. Resource source paths are redacted from `status` output. Active managed-job plans are owner-only and are deleted after a terminal result; bounded redacted results are retained temporarily. Uninstall first acquires a state-root maintenance lock that blocks new profile/state operations and state-backed operations from already constructed managed-job/browser managers, stops the platform service and all verified workspace daemons before removing definitions, rechecks jobs and locks, then validates markers, canonical paths, workspace/source exclusions, and known contents before recursive deletion.
|
|
426
426
|
|
|
427
|
+
The relay honors standard `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` environment routing. Invalid or unsupported proxy configuration fails fast; runtime status reports only `direct`, `proxy`, or `invalid-proxy-configuration`, never proxy URLs or credentials.
|
|
428
|
+
|
|
427
429
|
Default foreground logs report authenticated relay readiness, readable persistent-degradation summaries, and recovery rather than raw WebSocket callbacks or JSON field dumps. Brief self-healing disconnects and close codes/reasons are debug-only. Stalled connection attempts have a deadline, and sustained-outage reminders use autonomous exponential backoff. Every per-tool event—including success, failure, cancellation, and slow-call timing—also appears only at `--log-level debug` or `--verbose`. Background services use `warn`, so ordinary tool outcomes and brief network changes do not fill daemon logs. Log messages and structured fields are bounded, secret-like keys and known token formats are redacted, and tool arguments/results are not written. See [docs/LOGGING.md](docs/LOGGING.md) and [docs/OPERATIONS.md](docs/OPERATIONS.md).
|
|
428
430
|
|
|
429
431
|
## Development and verification
|
package/SECURITY.md
CHANGED
|
@@ -19,7 +19,7 @@ Do not include live MCP passwords, daemon secrets, OAuth tokens, Cloudflare cred
|
|
|
19
19
|
|
|
20
20
|
## Repository and documentation privacy
|
|
21
21
|
|
|
22
|
-
Tests, examples, documentation, release notes, and package metadata are publication surfaces. Use only synthetic hostnames, resource aliases, usernames, paths, and project names. Run `npm run privacy:check` before committing
|
|
22
|
+
Tests, examples, documentation, release notes, and package metadata are publication surfaces. Use only synthetic hostnames, resource aliases, usernames, paths, and project names. Run `npm run privacy:check` before committing, review `npm run privacy:history` before publishing, and maintain private local identifiers in the ignored `.privacy-denylist`; neither scanner mode prints matched values. See [Repository privacy hygiene](docs/PRIVACY.md).
|
|
23
23
|
|
|
24
24
|
Removing a value from the current branch does not remove it from Git history, caches, forks, or an already published npm package. Rotate any exposed credential immediately and coordinate destructive history rewriting separately when its risk is justified.
|
|
25
25
|
|
|
@@ -57,6 +57,10 @@ Machine Bridge prepends a package-controlled built-in working-agreement block an
|
|
|
57
57
|
|
|
58
58
|
Repository and user instruction files remain untrusted content from the model's perspective. `agent_context` returns their text in deterministic precedence order but does not certify correctness or safety. A malicious `AGENTS.md`, custom instruction file, filename, script name, or `SKILL.md` can attempt prompt injection or recommend destructive operations. Use only trusted repositories and skill roots, keep host approvals/policy enabled, or isolate the bridge externally.
|
|
59
59
|
|
|
60
|
+
Automatic `package.*` commands expose only validated script names and fixed package-manager argv; they do not expose script bodies. Executing one still runs repository-controlled package-script code with local-user authority and is not a sandbox or trust upgrade.
|
|
61
|
+
|
|
62
|
+
Relay proxy selection honors `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. Only HTTP(S) proxy URLs are accepted. Proxy endpoints, credentials, and authorization headers are not returned through MCP or written to operational logs; status exposes only coarse route state.
|
|
63
|
+
|
|
60
64
|
Skill loading is non-executing. `load_local_skill` returns an entrypoint and bounded file inventory; scripts remain inert until a separate process or command tool is called. Symlinked skill directories are followed only after canonical path-policy validation, while symbolic-link `SKILL.md` entrypoints are rejected. Traversal, cycles, content, summaries, and inventory are bounded.
|
|
61
65
|
|
|
62
66
|
Registered commands are available only under direct-execution-capable policy. They use argv spawning rather than shell parsing, reject undeclared caller arguments, and enforce the manifest timeout as a ceiling. They are not an approval or sandbox boundary: a repository-controlled package script, interpreter, compiler, or executable can still run arbitrary code with local-user authority. Deeper manifests can override or remove inherited commands, so callers must obtain context for the actual target path rather than assuming the repository-root registry applies everywhere.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "Machine Bridge Browser",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.0",
|
|
5
5
|
"description": "Connects the current Chromium browser profile to the local Machine Bridge runtime for user-authorized automation.",
|
|
6
6
|
"permissions": [
|
|
7
7
|
"tabs",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"action": {
|
|
30
30
|
"default_title": "Machine Bridge Browser"
|
|
31
31
|
},
|
|
32
|
-
"version_name": "0.
|
|
32
|
+
"version_name": "0.13.0"
|
|
33
33
|
}
|
package/docs/AGENT_CONTEXT.md
CHANGED
|
@@ -14,7 +14,7 @@ This approximates a local coding agent without pretending that the MCP server ow
|
|
|
14
14
|
- `list_local_commands` returns effective registered commands.
|
|
15
15
|
- `run_local_command` executes a registered direct-argv command when policy permits.
|
|
16
16
|
|
|
17
|
-
Both stdio and remote Worker connection initialization attempt `session_bootstrap`. Its instruction text is appended to the MCP `initialize` result. Because a host may reuse one MCP connection across conversations, the explicit tool and per-task `resolve_task_capabilities` call remain necessary to refresh and reapply instructions reliably.
|
|
17
|
+
Both stdio and remote Worker connection initialization attempt `session_bootstrap`. Its instruction text is appended to the MCP `initialize` result. Because a host may reuse one MCP connection across conversations, the explicit tool and per-task `resolve_task_capabilities` call remain necessary to refresh and reapply instructions reliably. `server_info.observability.capability_routing` and `project_overview.capabilityRouting` report whether those calls reached the local runtime, their counts and timestamps, loaded-source flags, selected capability metadata, and a runtime-keyed HMAC task fingerprint. Raw task text is not retained.
|
|
18
18
|
|
|
19
19
|
## Useful defaults without configuration
|
|
20
20
|
|
|
@@ -171,9 +171,13 @@ Use `AGENTS.md` for durable facts a new contributor or agent must know: validate
|
|
|
171
171
|
Without explicit `skill_roots`, discovery scans:
|
|
172
172
|
|
|
173
173
|
- target-to-root `.agents/skills` directories;
|
|
174
|
+
- target-to-root `.codex/skills` compatibility directories;
|
|
174
175
|
- under unrestricted policy, `~/.agents/skills`;
|
|
176
|
+
- under unrestricted policy, `CODEX_HOME/skills` (normally `~/.codex/skills`);
|
|
175
177
|
- under unrestricted policy on Unix-like systems, `/etc/codex/skills`.
|
|
176
178
|
|
|
179
|
+
Canonical paths are deduplicated, so a compatibility symlink from `.agents/skills` to `.codex/skills` does not duplicate a skill.
|
|
180
|
+
|
|
177
181
|
A skill directory contains `SKILL.md` or `skill.md` with simple front matter:
|
|
178
182
|
|
|
179
183
|
```markdown
|
|
@@ -189,15 +193,21 @@ No persistent skill or project-context index is trusted as authoritative. `sessi
|
|
|
189
193
|
|
|
190
194
|
## Progressive disclosure and task selection
|
|
191
195
|
|
|
192
|
-
`agent_context` returns bounded skill metadata. `load_local_skill` returns full instructions only for one selected bundle. `resolve_task_capabilities` tokenizes the current task, ranks skill names/descriptions and command names/descriptions/argv, returns matches with scores, and loads the leading skill only when its relevance threshold is met.
|
|
196
|
+
`agent_context` returns bounded skill metadata. `load_local_skill` returns full instructions only for one selected bundle. `resolve_task_capabilities` tokenizes the current task, ranks skill names/descriptions and command names/descriptions/argv, returns matches with scores, and loads the leading skill only when its relevance threshold is met. Under canonical `full`, it also compares the task with installed application names on every call; application discovery is cached briefly and refreshed after a bounded interval.
|
|
197
|
+
|
|
198
|
+
Matching remains deterministic and local. Hyphens, underscores, dots, and whitespace are normalized; common English inflections are reduced to a small canonical form; and a bounded Chinese/English workflow vocabulary covers creation, improvement, installation, search, current/official documentation, verification, testing, frontend/design, browser/web, email, performance, and security intents. Capability-name token matches receive more weight than incidental words in a long description. This lets Chinese tasks select English-metadata skills such as `skill-creator`, `smart-search-cli`, and `skill-installer`, while avoiding the prior tie where generic “create” wording could select `frontend-design`. An explicitly named skill or registered command still receives the strongest deterministic boost.
|
|
199
|
+
|
|
200
|
+
This ranking is deterministic local assistance, not semantic certainty. Weak positive matches remain visible for diagnosis, but only a skill meeting the selection threshold is recommended for loading. The model must still evaluate whether the selected skill applies. Machine Bridge does not execute skill scripts implicitly and does not fabricate a dynamically named MCP tool per skill.
|
|
201
|
+
|
|
202
|
+
## Registered and automatic package commands
|
|
193
203
|
|
|
194
|
-
|
|
204
|
+
`run_local_command` spawns the registered argv directly rather than parsing caller text through a Machine Bridge shell. Manifest commands control working directory, timeout ceiling, and whether caller arguments are accepted. A caller may reduce but not increase the timeout.
|
|
195
205
|
|
|
196
|
-
|
|
206
|
+
When the project root has a valid, non-symbolic-link `package.json`, safe script names are exposed automatically as `package.<normalized-name>` commands. The manager is selected from the validated `packageManager` field or one unambiguous lockfile; npm is used only when no manager signal exists. Conflicting lockfiles suppress automatic commands until the ambiguity is resolved. Only script names and bounded built-in workflow-intent terms are exposed. Script bodies and dependency values are not injected. Automatic commands accept no caller-supplied extra arguments, use the project root as cwd, and have a bounded timeout. Explicit manifests are applied afterward, so they can override or delete an automatic command by name.
|
|
197
207
|
|
|
198
|
-
|
|
208
|
+
On Unix-like systems the package-manager executable is spawned directly. On Windows, npm/pnpm/yarn/bun are command shims rather than native executables, so the bridge uses a fixed `cmd.exe /d /s /c` command assembled only from an allowlisted manager and a validated script name; callers still cannot append arguments or shell syntax. This wrapper is transport compatibility, not a trust boundary.
|
|
199
209
|
|
|
200
|
-
|
|
210
|
+
Directly invoking `npm run`, `pnpm run`, `yarn run`, or `bun run` does not make the repository script itself shell-free: package managers execute repository-controlled script bodies according to their own semantics. All registered commands are workflow aliases, not an approval boundary or sandbox. Package scripts, interpreters, compilers, and executables retain local-user authority. Use `review` or `edit`, or external VM/container isolation, for untrusted content.
|
|
201
211
|
|
|
202
212
|
## Recommended host workflow
|
|
203
213
|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -40,13 +40,13 @@ A canonical workspace receives an independent profile, Worker name, secret set,
|
|
|
40
40
|
|
|
41
41
|
`RelayConnection` owns remote WebSocket transport, authenticated `hello_ack` readiness, heartbeat liveness, reconnect backoff, and outage logging. Stdio mode invokes `LocalRuntime` directly without that adapter.
|
|
42
42
|
|
|
43
|
-
`daemon-process.mjs` owns workspace-daemon inspection and takeover. It distinguishes platform service state from the lock-owning Node process, validates PID and process-start identity, canonicalizes workspace/state paths before comparison, parses bounded process command lines without executing them, and sends `SIGTERM` only to a verified same-workspace `--daemon-only` process. CLI orchestration never treats a missing launchd/systemd job as proof that the process exited.
|
|
43
|
+
`daemon-process.mjs` owns workspace-daemon inspection and takeover. It distinguishes platform service state from the lock-owning Node process, validates PID and process-start identity, canonicalizes workspace/state paths before comparison, parses bounded process command lines without executing them, and sends `SIGTERM` only to a verified same-workspace `--daemon-only` process. POSIX daemons may ignore that signal and reach the bounded non-escalating timeout; Node's Windows signal mapping terminates the verified process directly. CLI orchestration never treats a missing launchd/systemd job as proof that the process exited.
|
|
44
44
|
|
|
45
45
|
### Agent context and capability resolver
|
|
46
46
|
|
|
47
|
-
`AgentContextManager` discovers the nearest Git/workspace scope, applies the user configuration and hierarchical `.machine-bridge/agent.json` files, selects built-in/user/root-to-target instructions, discovers bounded filesystem skills, and resolves registered commands. `default-instructions.mjs` supplies a versioned in-package working-agreement block and derives a small virtual project-context block from root filenames and bounded metadata. It reads package script names but not bodies, does not inspect dependency values or source contents, executes nothing, and writes no user/repository files. A global `model_instructions_file` is a separate user-designated session source and cannot be overridden by a project.
|
|
47
|
+
`AgentContextManager` discovers the nearest Git/workspace scope, applies the user configuration and hierarchical `.machine-bridge/agent.json` files, selects built-in/user/root-to-target instructions, discovers bounded filesystem skills, and resolves registered commands. `project-package.mjs` owns no-follow package metadata parsing, package-manager selection (including fail-closed conflicting-lockfile handling), script-name normalization, bounded workflow-intent aliases, and automatic `package.*` command construction so instruction rendering and command execution do not duplicate package parsing. `default-instructions.mjs` supplies a versioned in-package working-agreement block and derives a small virtual project-context block from root filenames and bounded metadata. It reads package script names but not bodies, does not inspect dependency values or source contents, executes nothing, and writes no user/repository files. A global `model_instructions_file` is a separate user-designated session source and cannot be overridden by a project.
|
|
48
48
|
|
|
49
|
-
`session_bootstrap` is requested during both stdio and remote MCP initialization. The Worker delegates this read to the connected daemon with a short bounded timeout; failure falls back to static server instructions rather than blocking initialization indefinitely. `resolve_task_capabilities` performs a fresh deterministic scan, rebuilds automatic project facts, and ranks skill/command metadata for the current task. Application and browser capability metadata is added by `LocalRuntime
|
|
49
|
+
`session_bootstrap` is requested during both stdio and remote MCP initialization. The Worker delegates this read to the connected daemon with a short bounded timeout; failure falls back to static server instructions rather than blocking initialization indefinitely. `resolve_task_capabilities` performs a fresh deterministic scan, rebuilds automatic project facts, and ranks skill/command metadata for the current task. Application and browser capability metadata is added by `LocalRuntime`; installed application inventory uses a short bounded cache. `CapabilityObserver` records only counts, timestamps, source flags, selected metadata, match counts, recommended tool names, and a runtime-keyed task fingerprint so operators can verify routing without creating a task-content log.
|
|
50
50
|
|
|
51
51
|
The MCP catalog remains static: local skills and commands do not become dynamically named tools. This avoids stale host catalog caches and keeps Worker/stdio schema parity. Progressive disclosure separates discovery, instruction loading, and execution authority. A refresh fingerprint is descriptive rather than a cache-validity guarantee.
|
|
52
52
|
|
|
@@ -208,7 +208,9 @@ Managed jobs use the same argv/environment primitives but a different lifecycle.
|
|
|
208
208
|
|
|
209
209
|
## Daemon reconnect and replacement
|
|
210
210
|
|
|
211
|
-
The local `RelayConnection` treats transport construction, transport open, authenticated readiness, and outage recovery as separate states.
|
|
211
|
+
The local `RelayConnection` treats proxy selection, transport construction, transport open, authenticated readiness, and outage recovery as separate states. `network-proxy.mjs` maps WebSocket targets to standard HTTP(S) environment-proxy resolution, honors `NO_PROXY`, rejects non-HTTP(S) proxy schemes, and creates the proxy agent without exposing its URL or credentials. Invalid proxy configuration is a fatal configuration error rather than a retryable outage.
|
|
212
|
+
|
|
213
|
+
The local `RelayConnection` otherwise treats transport construction, transport open, authenticated readiness, and outage recovery as separate states. A connection-attempt deadline terminates sockets stuck in `CONNECTING`; after WebSocket open it sends `hello` and reports readiness only after `hello_ack`. A missing acknowledgement reaches a distinct handshake deadline and the candidate is terminated. Once ready, application heartbeats require inbound activity; a silent half-open socket is terminated and reconnected. Outage reminders run on their own exponential-backoff timer rather than depending on another transport callback.
|
|
212
214
|
|
|
213
215
|
Reconnect uses bounded exponential backoff with jitter. Brief self-healing interruptions are debug-only. An unresolved outage is promoted to a rate-limited warning after a grace period, and recovery produces one summary. Raw close codes and reason strings remain debug-only.
|
|
214
216
|
|
|
@@ -216,7 +218,7 @@ The Worker also treats a new connection as a bounded candidate until it authenti
|
|
|
216
218
|
|
|
217
219
|
## Persistence
|
|
218
220
|
|
|
219
|
-
Local state and global config are owner-only, versioned, and size-bounded. Shared persistence primitives write a complete private temporary file, `fsync` it, and either hard-link it for an exclusive claim or atomically replace the destination. Machine-level browser pairing state is owner-only and shared across workspace runtimes through the local broker; its bearer token is not part of workspace state responses. State, managed-job manager, detached runner, browser pairing, and service definitions share the same flushed atomic-replacement primitive
|
|
221
|
+
Local state and global config are owner-only, versioned, and size-bounded. Shared persistence primitives write a complete private temporary file, `fsync` it, and either hard-link it for an exclusive claim or atomically replace the destination. Machine-level browser pairing state is owner-only and shared across workspace runtimes through the local broker; its bearer token is not part of workspace state responses. State, managed-job manager, detached runner, browser pairing, and service definitions share the same flushed atomic-replacement primitive. Only classified transient Windows sharing failures are retried, using a bounded sixteen-attempt exponential schedule with jitter; the implementation never deletes the destination as a retry fallback, so readers are not intentionally exposed to a missing-file interval.
|
|
220
222
|
|
|
221
223
|
Process locks contain purpose, workspace, ownership token, lock time, and process start time. Stale removal rechecks device/inode/size/mtime and token so an old observer cannot delete a replacement lock. Recent malformed claims receive a grace period. Startup/state operations wait a bounded interval; daemon and runner identity remain process-lifetime locks. Managed-job transition and recovery locks use the same ownership/snapshot principles and support an atomic runner handoff.
|
|
222
224
|
|
|
@@ -230,12 +232,18 @@ OAuth metadata is pruned on access. Expired codes/tokens, old throttling records
|
|
|
230
232
|
|
|
231
233
|
## Observability
|
|
232
234
|
|
|
233
|
-
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status, policy origin/revision, managed-job counts, resource alias names without paths or values,
|
|
235
|
+
Public health exposes only server identity and version. Authenticated `server_info` exposes bounded runtime status, policy origin/revision, managed-job counts, resource alias names without paths or values, daemon/relay-advertised tool counts, relay route state without endpoint details, and privacy-preserving capability-routing evidence. It explicitly reports that the host-exposed subset is unknown to the server. `diagnose_runtime` runs fixed local probes and explicitly reports that its own request reached the daemon.
|
|
234
236
|
|
|
235
237
|
Foreground logging defaults to `info`; autostart uses `warn`. Authenticated readiness, persistent degradation, and recovery are user-visible state transitions. Brief relay interruptions, raw transport close details, retry timing, and all per-tool starts/successes/failures/cancellations/durations are debug-only. Unexpected local and Worker infrastructure errors are reduced to classes. Messages, strings, arrays, object depth/key counts, and serialized fields are bounded.
|
|
236
238
|
|
|
237
239
|
Cloudflare sampling is size control rather than an audit log. The project intentionally does not claim complete forensic logging. See [LOGGING.md](LOGGING.md).
|
|
238
240
|
|
|
241
|
+
## Release integrity
|
|
242
|
+
|
|
243
|
+
Repository-local checks are necessary but cannot prove behavior on every supported operating system. `scripts/github-release.mjs` therefore queries `.github/workflows/ci.yml` for the exact `origin/main` commit and requires the newest push-triggered run to be completed with `success` before it creates or verifies a version tag, GitHub Release, or package asset. Pull-request runs, older successful runs, pending runs, and successful runs for another SHA do not satisfy the gate. The selection policy is isolated in `scripts/release-ci.mjs` and tested independently.
|
|
244
|
+
|
|
245
|
+
Third-party workflow actions are pinned to immutable commit SHAs. Dependabot proposes reviewed SHA updates, and `architecture:test` rejects a return to movable action tags or removal of the reachable-history package-audit step.
|
|
246
|
+
|
|
239
247
|
## Explicit non-goals
|
|
240
248
|
|
|
241
249
|
- operating-system sandboxing of arbitrary executables;
|
package/docs/AUDIT.md
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
# Engineering and security audit
|
|
2
2
|
|
|
3
|
-
This document records the cross-cutting audit
|
|
3
|
+
This document records the cross-cutting audit initiated for version 0.12.0, the 0.12.2 cross-platform CI follow-up, and the 0.13.0 architecture/automatic-routing follow-up. It complements, but does not replace, the continuously enforced contracts in `SECURITY.md`, `docs/ENGINEERING.md`, and the test suite.
|
|
4
|
+
|
|
5
|
+
## 2026-07-13 architecture and automatic-routing follow-up
|
|
6
|
+
|
|
7
|
+
A new behavior-level review found that the existing global/project instruction path was functioning, but three gaps explained weak user-visible automation: direct `.codex/skills` compatibility depended on user-created symlinks, root package scripts were described but not executable through the registered-command surface, and the runtime provided no proof that the host had called bootstrap or task resolution. The review added direct compatibility roots, bounded automatic package commands, and privacy-preserving routing telemetry while retaining the host/model invocation boundary.
|
|
8
|
+
|
|
9
|
+
The review also reproduced a lifecycle defect not covered by the previous descendant test: when a direct child exited after group `SIGTERM` while a detached-stdio descendant ignored the signal, `runProcess` cleared the pending `SIGKILL` escalation and left the descendant alive. Timeout/cancellation/replacement now use one escalation primitive whose forced phase remains referenced independently of direct-child tracking. A dedicated real-process regression covers that exact ordering.
|
|
10
|
+
|
|
11
|
+
Relay routing now honors standard HTTP(S) proxy environment variables and `NO_PROXY`, rejects invalid/unsupported proxy configuration before reconnect, and exposes only coarse route state. Package metadata parsing and capability observation were extracted from orchestration code, and architecture tests now reject domain-to-adapter imports.
|
|
12
|
+
|
|
13
|
+
A real macOS stdio smoke test used the user's actual global instructions, repository instructions, installed skills, package scripts, and installed applications with an isolated temporary state root. Initialization advertised 49 tools and contained all four instruction layers. A Chinese skill-creation task selected `skill-creator` at score 16 and loaded 22,047 bytes of instructions; 42 automatic package commands were discovered and `package.version-check` executed with exit code 0; 100 applications were discovered, `Chess` matched at score 15, opened in the background, was observed running, then quit cleanly. Capability telemetry recorded bootstrap plus three task resolutions without retaining raw task text.
|
|
14
|
+
|
|
15
|
+
The same review reproduced two daily-use ranking failures before the fix: Chinese tasks did not match English skill metadata, and an English skill-creation request tied several generic “create” descriptions and selected `frontend-design` alphabetically. Cross-platform CI then exposed a separate Windows execution defect: automatic commands spawned `npm` as if it were a native executable, but Windows provides `npm.cmd`, producing `spawn npm ENOENT`. Windows package commands now use one fixed command-shell wrapper built from allowlisted manager and validated script names. Bounded bilingual intent normalization plus capability-name weighting corrected both cases. Residual limits remain external: the MCP host can filter initialization instructions or tools, a package manager can execute arbitrary repository script bodies, HTTP(S) proxy support is not SOCKS support, and OS process-tree guarantees remain platform dependent. In the observed remote ChatGPT path, the 0.12.2 relay advertised 49 tools while the host made only 11 available to this conversation, demonstrating that server-side discovery cannot by itself guarantee host invocation.
|
|
16
|
+
|
|
17
|
+
## 0.12.2 follow-up findings
|
|
18
|
+
|
|
19
|
+
The failed `0.12.1` workflow had two independent causes. Windows exhausted the old approximately half-second atomic-replacement retry window while a stress reader repeatedly held the destination open. Linux and macOS lost an immediately emitted browser runtime `hello` between awaiting `open` and registering the message listener, then waited without a deadline until the 20-minute job timeout. The fixes preserve atomic replacement, extend only classified transient retries, pre-register the browser handshake listener, bound all relevant HTTP/WebSocket waits, and terminate failed proxy candidates.
|
|
20
|
+
|
|
21
|
+
The review also found three governance gaps not represented by the original failure message:
|
|
22
|
+
|
|
23
|
+
- GitHub Releases could be created from a local pass while the exact cross-platform push CI was failing. Publication now requires successful exact-commit push CI before tagging or release verification.
|
|
24
|
+
- Workflow actions used movable major-version tags. They are now pinned to immutable official commit SHAs, with an executable invariant.
|
|
25
|
+
- Repository privacy checks covered only the current tree. Package audit now scans reachable historical paths, bounded UTF-8 blobs, and commit messages; deleted credential fixtures fail without echoing their values.
|
|
26
|
+
|
|
27
|
+
No generic active credential pattern was found in the current tree or reachable history after excluding standard public automation trailers. The developer-local denylist does match legacy historical identifiers, and the Git metadata audit found a legacy non-noreply author/committer identity. These are identity/privacy metadata rather than active credentials. Removing them would require a coordinated history rewrite and force-update of affected refs, which is intentionally not performed as an incidental code fix.
|
|
4
28
|
|
|
5
29
|
## Scope
|
|
6
30
|
|
package/docs/CLIENTS.md
CHANGED
|
@@ -54,7 +54,7 @@ The MCP specification defines stdio and Streamable HTTP as standard transports.
|
|
|
54
54
|
|
|
55
55
|
## Automatic capability selection
|
|
56
56
|
|
|
57
|
-
MCP initialization and `resolve_task_capabilities` give the host a current view of conservative built-in working agreements, bounded project facts, explicit global/project instructions, skills,
|
|
57
|
+
MCP initialization and `resolve_task_capabilities` give the host a current view of conservative built-in working agreements, bounded project facts, explicit global/project instructions, skills, explicit/automatic package commands, applications, and browser capability. The resolver rescans rather than relying on a stale dynamic tool list and can return the best matching skill instructions in one call. No instruction file is required for the default layers, and no repository file is written automatically.
|
|
58
58
|
|
|
59
59
|
The host still owns the agent loop. ChatGPT web may use the recommendation automatically, ask for confirmation, expose only part of the catalog, or ignore server instructions. No MCP implementation can guarantee automatic invocation from the server side. Machine Bridge models that limitation explicitly instead of treating a recommendation as execution.
|
|
60
60
|
|
package/docs/ENGINEERING.md
CHANGED
|
@@ -9,7 +9,7 @@ This document records project-wide decisions that must survive individual fixes,
|
|
|
9
9
|
3. **Machine Bridge authority and host authority are separate.** `full` removes Machine Bridge's own policy, path, shell, and environment restrictions. It cannot override an MCP host, connector gateway, operating system, endpoint-security product, cloud IAM, remote authentication, or `sudo`.
|
|
10
10
|
4. **Publication surfaces contain no real environment metadata.** Source, tests, fixtures, examples, release notes, filenames, package contents, tags, and release assets use synthetic identifiers and reserved example domains.
|
|
11
11
|
5. **Secrets are never operational log data.** Tool arguments, command text, stdin, stdout, stderr, file content, OAuth bodies, credentials, and local resource values are not logged.
|
|
12
|
-
6. **A release is one version
|
|
12
|
+
6. **A release is one version with successful cross-platform evidence.** Package metadata, Worker version, browser-extension version/name, Git tag, GitHub Release, npm version, documentation, and deployed health version must agree, and the exact `origin/main` commit must have a completed successful push-triggered GitHub Actions run before a tag or release is created.
|
|
13
13
|
7. **Generic local automation is structured, not arbitrary evaluation.** Browser/application features may expose broad user authority under canonical `full`, but must not accept caller-provided JavaScript, AppleScript, JXA, or extension code.
|
|
14
14
|
8. **Daily-browser integration uses the existing profile.** The supported primary browser path is the packaged authenticated extension and machine-level loopback broker, preserving current tabs/login state; a separate automation profile is not an equivalent replacement.
|
|
15
15
|
9. **Pairing and resource secrets are not conversation or log data.** Tokens and injected local-resource values must not be returned, embedded in URLs, or written to operational logs.
|
|
@@ -46,6 +46,7 @@ CLI, service, release, and deployment orchestration
|
|
|
46
46
|
Rules:
|
|
47
47
|
|
|
48
48
|
- Transport lifecycle, domain execution, persistence, and presentation are separate modules.
|
|
49
|
+
- Domain modules must not import CLI, service, stdio, or relay adapters. Architecture tests enforce this dependency direction for agent context, package metadata, default instructions, capability observation, application automation, process sessions, and proxy selection.
|
|
49
50
|
- Pure classification and normalization functions are exported and tested directly when practical.
|
|
50
51
|
- Adapters may translate data but should not duplicate policy or schemas.
|
|
51
52
|
- Every protocol control message emitted by one side must be explicitly accepted, rejected, or version-gated by the other side, with an end-to-end contract test covering the message name and semantics.
|
|
@@ -123,7 +124,7 @@ Every defect fix includes a regression test that fails for the original reason.
|
|
|
123
124
|
The required matrix includes:
|
|
124
125
|
|
|
125
126
|
- Linux, macOS, and Windows on the pinned Node/npm baseline;
|
|
126
|
-
-
|
|
127
|
+
- current-tree and reachable-history privacy gates, release-impact enforcement, and exact-commit release-CI gating;
|
|
127
128
|
- package-manifest and sensitive-artifact inspection;
|
|
128
129
|
- generated type checks and recursively discovered JavaScript/shell syntax checks;
|
|
129
130
|
- concurrent exclusive-lock/atomic-replacement tests, PID-reuse/age tests, and fail-closed service-lifecycle tests;
|
|
@@ -134,7 +135,7 @@ The required matrix includes:
|
|
|
134
135
|
- managed-job integrity, recovery, cancellation, cleanup, and redaction;
|
|
135
136
|
- dependency audit, registry signatures/attestations, SBOM, and Worker dry run.
|
|
136
137
|
|
|
137
|
-
Cross-platform tests must not depend on shell syntax, case-sensitive Windows paths, Unix-only executable shims, or timing races when a deterministic scheduler can be injected.
|
|
138
|
+
Cross-platform tests must not depend on shell syntax, case-sensitive Windows paths, Unix-only executable shims, or timing races when a deterministic scheduler can be injected. Local success cannot substitute for the required Linux/macOS/Windows push CI result used by the release gate.
|
|
138
139
|
|
|
139
140
|
## Documentation rules
|
|
140
141
|
|
|
@@ -177,7 +178,7 @@ A thorough review asks:
|
|
|
177
178
|
- Are persistent files atomic, owner-only, size-bounded, and symlink-aware?
|
|
178
179
|
- Can browser/app automation be expressed without arbitrary evaluation, and are pairing/resource values absent from results and logs?
|
|
179
180
|
- Can a stale PID, stale socket, duplicate request, partial write, or ambiguous remote response violate integrity?
|
|
180
|
-
- Are package, CI, Worker, service, and release behavior tested on every supported platform?
|
|
181
|
+
- Are package, CI, Worker, service, and release behavior tested on every supported platform, and does publication verify the exact successful push CI run?
|
|
181
182
|
- Does the complete diff contain any real identifier, path, host, account, or credential-shaped value?
|
|
182
183
|
- Does the change require a new npm version and deployment?
|
|
183
184
|
|
package/docs/LOCAL_AUTOMATION.md
CHANGED
|
@@ -89,7 +89,7 @@ Menu-bar and menu subtrees are not recursively expanded by default. This keeps m
|
|
|
89
89
|
|
|
90
90
|
## Capability discovery and automatic selection
|
|
91
91
|
|
|
92
|
-
`resolve_task_capabilities` rescans instruction files, skills,
|
|
92
|
+
`resolve_task_capabilities` rescans instruction files, skills, explicit/automatic package commands, and relevant local automation metadata on every call. It ranks matching skills and commands, optionally loads the best skill, and compares every canonical-full task with cached installed-application names, so a task that directly names an app does not need generic “app/window” wording. Application inventory is refreshed after a bounded cache interval.
|
|
93
93
|
|
|
94
94
|
This is the strongest reliable server-side automation boundary available through MCP: discovery, refresh, ranking, and progressive skill loading are automatic. The MCP host still owns the model loop and decides whether a recommended tool is exposed, approved, or invoked. Machine Bridge cannot force ChatGPT web or another host to make a call that the host declines.
|
|
95
95
|
|
package/docs/LOGGING.md
CHANGED
|
@@ -39,6 +39,8 @@ A TCP/WebSocket `open` event is only transport availability. The daemon is repor
|
|
|
39
39
|
|
|
40
40
|
Brief network interruptions are expected on laptop network changes, Worker deployment, proxy rotation, and ordinary internet transport. They are handled as follows:
|
|
41
41
|
|
|
42
|
+
- proxy selection records only `direct` or `proxy` at debug level; proxy URLs, usernames, passwords, and headers are never log fields;
|
|
43
|
+
- invalid proxy URLs or unsupported schemes fail fast with a sanitized corrective error rather than repeated reconnect warnings;
|
|
42
44
|
- the raw close code, close reason, error class, connected duration, and retry delay are debug-only;
|
|
43
45
|
- a brief interruption that reconnects within the grace period produces no `info` or `warn` line;
|
|
44
46
|
- an outage that remains unresolved for 10 seconds produces a user-readable warning stating the duration, reconnect attempt count, classified cause, and automatic recovery behavior;
|
|
@@ -118,7 +120,7 @@ Each managed job has owner-only runner diagnostic logs. Child-step output is ret
|
|
|
118
120
|
|
|
119
121
|
Machine Bridge does not classify filenames as sensitive and does not block credential-looking names under canonical `full`. An MCP host, connector, model provider, desktop application, operating system, or endpoint-security layer may independently reject a request before it reaches Machine Bridge.
|
|
120
122
|
|
|
121
|
-
Use `server_info`, `machine-mcp status`, `machine-mcp doctor`, and `diagnose_runtime` to distinguish local policy from host-side enforcement. Changing the Machine Bridge profile cannot override another layer.
|
|
123
|
+
Use `server_info`, `project_overview`, `machine-mcp status`, `machine-mcp doctor`, and `diagnose_runtime` to distinguish local policy from host-side enforcement. Capability-routing status is returned on demand rather than written as task logs; it stores a runtime-keyed task fingerprint, not raw task text. Changing the Machine Bridge profile cannot override another layer.
|
|
122
124
|
|
|
123
125
|
## Adding or changing logs
|
|
124
126
|
|
package/docs/OPERATIONS.md
CHANGED
|
@@ -15,6 +15,9 @@ machine-mcp service status
|
|
|
15
15
|
| Result | Interpretation |
|
|
16
16
|
|---|---|
|
|
17
17
|
| `server_info` reports full and all relay tools, but the current session UI exposes fewer tools | Host/connector post-relay filtering; Machine Bridge cannot enumerate or override that subset |
|
|
18
|
+
| `capability_routing.bootstrap_observed` is false | The current local runtime has not received `session_bootstrap`; reconnect or inspect host initialization handling |
|
|
19
|
+
| `task_resolution_observed` is false after a substantive task | The host/model did not call `resolve_task_capabilities`; server-side discovery cannot force that host decision |
|
|
20
|
+
| Task resolution ran but all match counts are zero | The resolver ran successfully but found no sufficiently relevant local skill, command, or application |
|
|
18
21
|
| No structured result because the host rejects the call | Host/connector approval or safety layer, or transport before daemon delivery |
|
|
19
22
|
| `mcp-host-to-daemon` passes but `local-filesystem` fails | Local state/runtime permissions, disk policy, sandbox, or endpoint security |
|
|
20
23
|
| Filesystem passes but `local-process-spawn` fails | Local executable policy, endpoint security, OS permissions, or damaged Node runtime |
|
|
@@ -30,6 +33,8 @@ A brief relay interruption is retried automatically and is visible only with `--
|
|
|
30
33
|
|
|
31
34
|
Use `--verbose` only when close codes, close reasons, heartbeat timeouts, and retry delays are needed for diagnosis. A close code of 1006 means the transport ended without a normal close handshake; it does not by itself identify the cause.
|
|
32
35
|
|
|
36
|
+
The daemon honors `HTTPS_PROXY`/`HTTP_PROXY` and `NO_PROXY` through standard environment-proxy resolution. `wss:` targets use HTTPS proxy selection and `ws:` targets use HTTP proxy selection. Only HTTP and HTTPS proxy URLs are accepted. Invalid URLs or unsupported protocols fail startup with corrective guidance instead of entering the reconnect loop. `server_info.runtime.relay.network_route` reports only `direct`, `proxy`, or `invalid-proxy-configuration`; proxy endpoints and credentials are never returned or logged.
|
|
37
|
+
|
|
33
38
|
## Browser extension setup and diagnosis
|
|
34
39
|
|
|
35
40
|
The full-profile daemon starts the loopback browser broker automatically. Install/pair the packaged extension once:
|
|
@@ -61,7 +66,7 @@ Application UI inspection/actions require Accessibility permission for the Node/
|
|
|
61
66
|
|
|
62
67
|
`machine-mcp` is a foreground command. It remains attached to the terminal, defaults to `info` logging, and stops on `Ctrl+C`. `machine-mcp service start` launches the installed platform service in the background and returns to the shell; that service uses `warn` logging.
|
|
63
68
|
|
|
64
|
-
A global npm install changes the CLI files on disk but does not replace an already running Node process. Startup and other state-changing CLI operations use a token/process-identity lock and wait up to 30 seconds for a normal concurrent startup to finish; a short launchd/systemd overlap is therefore serialized rather than reported immediately as an error. On a normal foreground start, Machine Bridge unloads the platform service and then independently examines the workspace daemon lock. This second path handles a detached/orphan `--daemon-only` process that launchd/systemd/task scheduling no longer tracks, including legacy locks without mode/version metadata. Before sending `SIGTERM`, Machine Bridge verifies PID and process start time plus the live command line, entrypoint, canonical workspace, canonical state root, and daemon-only flag. It waits up to 15 seconds for both the PID and lock to disappear and
|
|
69
|
+
A global npm install changes the CLI files on disk but does not replace an already running Node process. Startup and other state-changing CLI operations use a token/process-identity lock and wait up to 30 seconds for a normal concurrent startup to finish; a short launchd/systemd overlap is therefore serialized rather than reported immediately as an error. On a normal foreground start, Machine Bridge unloads the platform service and then independently examines the workspace daemon lock. This second path handles a detached/orphan `--daemon-only` process that launchd/systemd/task scheduling no longer tracks, including legacy locks without mode/version metadata. Before sending `SIGTERM`, Machine Bridge verifies PID and process start time plus the live command line, entrypoint, canonical workspace, canonical state root, and daemon-only flag. It waits up to 15 seconds for both the PID and lock to disappear and does not add a later forced-kill escalation. On POSIX, a daemon that handles and ignores `SIGTERM` therefore reaches the bounded timeout and remains alive. Node maps the supported termination signals to immediate process termination on Windows, so the same verified-daemon stop normally completes rather than exercising the POSIX timeout branch. A foreground or unverifiable process is left untouched; stop a foreground instance with `Ctrl+C`.
|
|
65
70
|
|
|
66
71
|
`machine-mcp service status [WORKSPACE]` reports two independent layers: the platform service (`active`) and `workspace_daemon`, plus `effective_active` and `orphaned_workspace_daemon` summary flags. On macOS it is possible for launchd to report inactive while a prior Node process remains alive with parent PID 1; that is an orphan-daemon condition, not proof that the daemon stopped. `service stop` unloads the provider when present and then terminates only a verified service-style workspace daemon. `service uninstall` and full uninstall are ordered fail-closed operations: provider stop → verified daemon stop(s) → definition removal. A failed or ambiguous stop leaves definitions and state intact. If takeover reaches its deadline, run:
|
|
67
72
|
|
package/docs/PRIVACY.md
CHANGED
|
@@ -8,9 +8,14 @@ Run:
|
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npm run privacy:check
|
|
11
|
+
npm run privacy:history
|
|
11
12
|
```
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
`privacy:check` scans tracked and unignored new UTF-8 files and relative names for generic/encrypted/algorithm-specific private-key headers, AWS/GitHub/GitLab/npm/Slack/Google/live-payment/API token forms, JWT-shaped bearer values, embedded-credential URLs, absolute user-home paths, non-example email/`user@host` identifiers, credential-shaped filenames, and locally configured private identifiers. A tracked `.npmrc` is parsed: non-secret repository settings such as `engine-strict=true` are allowed, while authentication/identity keys, environment interpolation, and embedded credentials fail closed. Publication-surface symbolic links are rejected rather than followed. Binary, invalid UTF-8, and files above the bounded scanner limit require explicit manual review instead of being silently skipped. Findings report only file, line, and rule; the matched value is never printed.
|
|
15
|
+
|
|
16
|
+
`privacy:history` first runs the same current-tree checks, then scans every reachable historical blob path and bounded UTF-8 blob plus every reachable commit message. It catches values that were committed and later deleted. Standard public Dependabot signing trailers are ignored only in that exact commit-message context; the same non-example address remains disallowed in ordinary files. The local `.privacy-denylist` is also applied to history, so a developer may discover legacy identifiers that CI cannot know. Such a finding is real publication history, but ordinary commits cannot erase it.
|
|
17
|
+
|
|
18
|
+
Git author and committer identity headers are canonical Git metadata rather than blob or commit-message content and are not automatically rejected. Audit them separately with `git log`; changing historical identity metadata requires a coordinated history rewrite and force-update of affected refs.
|
|
14
19
|
|
|
15
20
|
Maintain machine-specific names in an ignored owner-only file:
|
|
16
21
|
|
|
@@ -41,13 +46,13 @@ Before committing or publishing:
|
|
|
41
46
|
|
|
42
47
|
- inspect the complete staged diff, including tests, snapshots, examples, release notes, and generated metadata;
|
|
43
48
|
- use reserved example domains and neutral aliases;
|
|
44
|
-
- run `npm run privacy:check`, `npm run check`, and `npm pack --dry-run`;
|
|
49
|
+
- run `npm run privacy:check`, review `npm run privacy:history`, run `npm run check`, and inspect `npm pack --dry-run`;
|
|
45
50
|
- treat paths, host aliases, usernames, codenames, real browser URLs/page captures, application names tied to a user, and form data as private metadata even when they are not authentication secrets;
|
|
46
51
|
- keep browser pairing-state files and captured source/screenshots out of fixtures, documentation, support logs, and release assets;
|
|
47
52
|
- review any tracked `.npmrc` as configuration code and never commit authentication, registry identity, environment interpolation, cert/key paths, or credential-bearing URLs;
|
|
48
53
|
- inspect package modes and filenames as well as file contents—an empty `.env`, private-key filename, database, or log is still an inappropriate publication artifact.
|
|
49
54
|
|
|
50
|
-
The scanner is heuristic. It cannot identify every personal or organizational name, split/transformed/encrypted value, image, archive, binary fixture, custom credential format,
|
|
55
|
+
The scanner is heuristic. It cannot identify every personal or organizational name, split/transformed/encrypted value, image, archive, binary fixture, custom credential format, unreachable/pruned object, reflog-only object, fork/cache copy, or Git identity header. Passing current-tree and reachable-history checks is a gate, not proof that every publication copy contains no private data.
|
|
51
56
|
|
|
52
57
|
## Incident response
|
|
53
58
|
|
package/docs/RELEASING.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The release invariant is:
|
|
4
4
|
|
|
5
|
-
- `main` points to the release commit.
|
|
5
|
+
- `main` points to the release commit, and the exact commit has a completed successful push-triggered `.github/workflows/ci.yml` run.
|
|
6
6
|
- `v<package version>` points to that same commit locally and on GitHub.
|
|
7
7
|
- A final GitHub Release exists for the tag.
|
|
8
8
|
- The GitHub Release contains the npm tarball generated from that commit.
|
|
@@ -21,8 +21,8 @@ The release invariant is:
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
2. Add the matching dated `CHANGELOG.md` section.
|
|
24
|
-
3. Run `npm run release-impact:check`, `npm run privacy:check`, `npm run check`, both dependency audits, `npm audit signatures`, and generate a CycloneDX `npm sbom`.
|
|
25
|
-
4. Inspect the complete diff and `npm pack --dry-run`, including packaged file modes and every helper referenced by package scripts, then commit and push all release changes to `main`.
|
|
24
|
+
3. Run `npm run release-impact:check`, `npm run privacy:check`, review `npm run privacy:history`, run `npm run check`, both dependency audits, `npm audit signatures`, and generate a CycloneDX `npm sbom`.
|
|
25
|
+
4. Inspect the complete diff and `npm pack --dry-run`, including packaged file modes and every helper referenced by package scripts, then commit and push all release changes to `main`. Wait for the push-triggered Linux/macOS/Windows and package-audit checks to complete successfully.
|
|
26
26
|
|
|
27
27
|
A privacy/security documentation correction is not “docs only” for release purposes. It requires a replacement npm version and, when appropriate, deprecation or unpublication of the affected version.
|
|
28
28
|
|
|
@@ -34,7 +34,7 @@ From a clean `main` worktree:
|
|
|
34
34
|
npm run release:publish
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
The command validates the project, including repository privacy checks, fast-forwards `origin/main
|
|
37
|
+
The command validates the project, including repository privacy checks, fast-forwards `origin/main` when needed, then requires the latest push-triggered CI run for that exact commit to be completed successfully before it creates or verifies the annotated version tag. It then pushes the tag, builds the npm tarball, creates or updates the GitHub Release, uploads the tarball, and verifies the resulting state. Read-only GitHub operations, Git pushes, and idempotent release updates use bounded retries only for classified transient network failures; ambiguous Release creation responses are resolved by querying server state before continuing.
|
|
38
38
|
|
|
39
39
|
To verify without changing anything:
|
|
40
40
|
|
|
@@ -64,4 +64,4 @@ The npm lifecycle repeats the full project checks and the GitHub synchronization
|
|
|
64
64
|
- An authenticated GitHub CLI session with repository release permission.
|
|
65
65
|
- An npm account that owns the package or has maintainer permission.
|
|
66
66
|
|
|
67
|
-
GitHub Actions is
|
|
67
|
+
GitHub Actions is a required publication boundary. The authenticated GitHub CLI must be able to read Actions runs, and a missing, pending, cancelled, skipped, or failed exact-commit push run blocks both `release:publish` and `release:check`. This prevents a machine-specific local pass from publishing a version that fails another supported platform.
|
package/docs/TESTING.md
CHANGED
|
@@ -13,15 +13,16 @@ The repository requires Node.js 26 and npm 12. `.node-version`, `.nvmrc`, `packa
|
|
|
13
13
|
The suite includes:
|
|
14
14
|
|
|
15
15
|
- release-impact enforcement requiring a new package version and CHANGELOG section for release-relevant changes;
|
|
16
|
-
- release-state diagnostics distinguishing missing local/remote version tags from tags that point to the wrong commit,
|
|
16
|
+
- release-state diagnostics distinguishing missing local/remote version tags from tags that point to the wrong commit, plus a release-CI gate that rejects missing, pending, failed, pull-request-only, stale, or wrong-commit runs;
|
|
17
17
|
- generated Cloudflare Worker types and strict TypeScript checking, including unused-local and unused-parameter rejection;
|
|
18
18
|
- recursive syntax validation for every JavaScript file under the shipped/runtime/test roots plus the shell wrapper;
|
|
19
19
|
- shared tool-catalog schema, annotation, and profile-inventory checks;
|
|
20
|
-
- default working-agreement injection without user files, bounded automatic project metadata, script-body non-disclosure, user-global opt-out, repository opt-out rejection, global `model_instructions_file` injection in stdio/remote initialization, hierarchical precedence, live project/skill rescanning and fingerprints, automatic task ranking/loading, command override/removal, direct argv handling, timeout ceilings, and execution-profile denial;
|
|
20
|
+
- default working-agreement injection without user files, bounded automatic project metadata, script-body non-disclosure, user-global opt-out, repository opt-out rejection, global `model_instructions_file` injection in stdio/remote initialization, hierarchical precedence, `.agents/skills` and `.codex/skills` compatibility discovery, live project/skill rescanning and fingerprints, automatic task ranking/loading with English inflection normalization, bounded Chinese/English intent aliases, capability-name weighting, and selected-skill instruction loading; automatic `package.*` commands with English/Chinese workflow-intent matching and Windows command-shim execution, explicit command override/removal, direct argv handling, timeout ceilings, runtime-keyed routing-telemetry privacy, and execution-profile denial;
|
|
21
21
|
- concurrent complete-before-visible lock claims, atomic replacement under active readers, malformed-lock grace, snapshot/token-safe reclamation, absolute-age expiry, PID-reuse detection, and bounded startup-lock waiting;
|
|
22
|
-
- foreground takeover of active and orphaned background daemons, legacy lock identification from canonicalized process arguments, foreground-process protection, actual-PID exit waiting, non-
|
|
22
|
+
- foreground takeover of active and orphaned background daemons, legacy lock identification from canonicalized process arguments, foreground-process protection, actual-PID exit waiting, POSIX non-escalating timeout behavior, Windows verified-daemon stop semantics, daemon lock mode/version/process-start metadata, launchd service-target semantics, and silent idempotent duplicate service starts;
|
|
23
23
|
- fail-closed service lifecycle ordering for provider-stop, all-workspace daemon-stop, and definition removal, including platform/daemon/removal failure injection and normalized macOS/systemd/Windows results;
|
|
24
|
-
- machine-level browser-broker ownership/client proxying, authenticated extension origin/subprotocol, non-cacheable local pairing, pairing-token non-disclosure, resource-backed upload routing,
|
|
24
|
+
- machine-level browser-broker ownership/client proxying, authenticated extension origin/subprotocol, non-cacheable local pairing, pairing-token non-disclosure, resource-backed upload routing, broker result redaction, pre-registered runtime-handshake listeners, bounded socket/HTTP waits, installed-application discovery caching, and name-based task matching;
|
|
25
|
+
- relay environment-proxy direct/bypass/agent selection, unsupported proxy rejection, fail-fast invalid configuration, and route observability without endpoint or credential disclosure;
|
|
25
26
|
- canonical path and symbolic-link escape tests;
|
|
26
27
|
- relative-path privacy and error-path redaction tests;
|
|
27
28
|
- atomic create/update, optimistic hash, exact edit, and patch transaction tests;
|
|
@@ -31,12 +32,12 @@ The suite includes:
|
|
|
31
32
|
- nested Git repository detection and helper suppression;
|
|
32
33
|
- author-email privacy in `git_log`;
|
|
33
34
|
- isolated command HOME/temp/cache behavior;
|
|
34
|
-
- one-shot timeout, descendant process-group/tree termination including descendants that ignore graceful shutdown, cancellation, and process-session interaction;
|
|
35
|
+
- one-shot timeout, descendant process-group/tree termination including descendants that ignore graceful shutdown after the direct child has already exited, cancellation, and process-session interaction;
|
|
35
36
|
- layered fixed runtime diagnostics for filesystem, direct process, shell, managed-job storage, and resource availability;
|
|
36
37
|
- local resource CLI registration, permission checks, dynamic reload, state-path redaction, and content non-disclosure;
|
|
37
38
|
- real Ed25519 and RSA generation, idempotent reuse, public/private correspondence, mode enforcement, incomplete/mismatched/symlink rejection, and private-content non-disclosure;
|
|
38
39
|
- real-machine canonical-full sandbox acceptance for outside-workspace I/O, direct/shell execution, full environment inheritance, SSH prerequisites, temporary authorized-key writing, and detached cleanup without external state changes;
|
|
39
|
-
- deterministic injected atomic-replace failures and repeated Windows full-sandbox runs
|
|
40
|
+
- deterministic injected atomic-replace failures, sustained transient Windows sharing contention beyond the old retry budget, bounded exponential delay selection, and repeated Windows full-sandbox runs;
|
|
40
41
|
- canonical named-profile repair and full-only tool exposure parity between local and Worker policy filters;
|
|
41
42
|
- managed-job staging/local approval/cancel-before-start, detachment, job-scoped temporary files, resource hash verification/redaction, discard capture, finally execution, descendant-tree escalation, token/snapshot-safe transition locks, runner process identity, plan scrubbing, PID-reuse-safe dead-runner recovery, and legacy PID-file compatibility;
|
|
42
43
|
- daemon/startup locking, successfully-read corrupt-JSON recovery, and explicit propagation/preservation of oversized, symbolic-link, permission, and I/O failures;
|
|
@@ -64,6 +65,7 @@ For browser changes, perform an isolated-profile smoke test with the packaged un
|
|
|
64
65
|
## Additional release checks
|
|
65
66
|
|
|
66
67
|
```sh
|
|
68
|
+
npm run privacy:history
|
|
67
69
|
npm run worker:dry-run
|
|
68
70
|
npm audit --audit-level=high
|
|
69
71
|
npm audit --omit=dev --audit-level=high
|
|
@@ -74,7 +76,7 @@ npm run version:check
|
|
|
74
76
|
npm run release-impact:check
|
|
75
77
|
```
|
|
76
78
|
|
|
77
|
-
GitHub Actions executes the main suite on Linux, macOS, and Windows using the pinned Node 26/npm 12 baseline. Because Node 26 currently bundles npm 11, CI explicitly disables setup-node's automatic package-manager cache and upgrades npm from the runner temporary directory before any project-local npm command can trigger strict `devEngines`. Checkout fetches version tags so the release-impact gate can compare the branch with the latest release. A separate package-audit job audits both the complete dependency graph and the production-only graph, verifies registry signatures and attestations, validates a CycloneDX SBOM written under the runner temporary directory, exercises the documented isolated global installation, then performs a dry-run package build. The macOS matrix job also runs the installation smoke test because Wrangler's optional `fsevents` resolution is platform-specific.
|
|
79
|
+
GitHub Actions executes the main suite on Linux, macOS, and Windows using the pinned Node 26/npm 12 baseline. Because Node 26 currently bundles npm 11, CI explicitly disables setup-node's automatic package-manager cache and upgrades npm from the runner temporary directory before any project-local npm command can trigger strict `devEngines`. Checkout fetches version tags so the release-impact gate can compare the branch with the latest release. A separate package-audit job scans reachable Git history, audits both the complete dependency graph and the production-only graph, verifies registry signatures and attestations, validates a CycloneDX SBOM written under the runner temporary directory, exercises the documented isolated global installation, then performs a dry-run package build. The macOS matrix job also runs the installation smoke test because Wrangler's optional `fsevents` resolution is platform-specific. Third-party Actions are pinned to immutable 40-character commit SHAs; architecture tests reject movable tags, and Dependabot monitors both action and dependency updates.
|
|
78
80
|
|
|
79
81
|
## Test design rules
|
|
80
82
|
|
|
@@ -91,7 +93,7 @@ GitHub Actions executes the main suite on Linux, macOS, and Windows using the pi
|
|
|
91
93
|
|
|
92
94
|
## Privacy hygiene
|
|
93
95
|
|
|
94
|
-
Run `npm run privacy:check` before committing and before packaging. Developers should maintain an ignored owner-only `.privacy-denylist` for machine aliases, usernames, internal codenames, and other private identifiers that a generic scanner cannot know. See [Repository privacy hygiene](PRIVACY.md).
|
|
96
|
+
Run `npm run privacy:check` before committing and before packaging. Run and review `npm run privacy:history` before release; local denylist findings may require an explicit owner decision because ordinary commits cannot remove public history. Developers should maintain an ignored owner-only `.privacy-denylist` for machine aliases, usernames, internal codenames, and other private identifiers that a generic scanner cannot know. See [Repository privacy hygiene](PRIVACY.md).
|
|
95
97
|
|
|
96
98
|
## Package manifest
|
|
97
99
|
|
|
@@ -101,4 +103,4 @@ The stdio integration test also sends an oversized line, verifies bounded reject
|
|
|
101
103
|
|
|
102
104
|
## Architecture and documentation regression checks
|
|
103
105
|
|
|
104
|
-
`npm run architecture:test` rejects local-module dependency cycles, missing static or dynamic relative imports, package scripts that reference missing files, drift from the recursive syntax scanner, incomplete executable package directories, inconsistent installation guidance, obsolete `LocalDaemon`/`daemon.mjs` naming, broken relative Markdown links, invisible ASCII control bytes in repository text, removal of the owner-required default-`full` engineering invariant, and accidental publication of `.project-local/` notes.
|
|
106
|
+
`npm run architecture:test` rejects movable GitHub Action references and loss of the CI history scan, release-gate script drift, local-module dependency cycles, missing static or dynamic relative imports, package scripts that reference missing files, drift from the recursive syntax scanner, incomplete executable package directories, inconsistent installation guidance, obsolete `LocalDaemon`/`daemon.mjs` naming, broken relative Markdown links, invisible ASCII control bytes in repository text, removal of the owner-required default-`full` engineering invariant, and accidental publication of `.project-local/` notes.
|