mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-10 00:56:52 +01:00
Report the native private host-control protocol version (#19488)
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Native Runner executes agent work and reports its binary contract through build metadata. > - Unix Runner already supports a private host-control socket for park, claim, and retire requests. > - A host cannot identify that protocol from the current metadata. > - This PR adds an explicit version field for that existing private protocol. > - Hosts can verify the selected binary before opening the private channel. ## Linked Issues or Issue Description Refs #19140 and #19129, which added the existing native lifecycle and private channel. **What existing behavior does this improve?** The `paperclip-runnerd --build-metadata` response. **Current behavior** The native binary implements the private fd 4 protocol on Unix. Its metadata has no field that identifies this protocol. Recovery versions describe different contracts. **Proposed behavior** Report `privateHostControlVersion: 1` on Unix builds. Omit the field on other builds. Keep ordinary artifact checks and runtime behavior unchanged. **Reason and benefit** A host can verify protocol support on the selected binary before using the channel. This field does not mean a provider is ready to park or that a host implements public release/resume or qualified sleep/wake. **Breaking changes** The JSON response gains one optional field on Unix. Current artifact parsers and launch checks accept extra fields. Binary contract version 2 stays unchanged. ## What Changed - Add the Unix-only private host-control metadata version. - Check the exact version and non-Unix absence in metadata unit and real CLI tests. Keep hosted parking and public release/resume fields absent. - Add a regression test that proves ordinary artifact parsing accepts and ignores the new field. - Document the field, exact-version checks, and separate provider and host qualification. ## Verification - On macOS arm64 with Rust 1.97.1, passed narrow offline, locked Cargo tests for the metadata unit, six existing private-protocol cases, wrong-fd CLI rejection, and real CLI metadata output. - Passed `cargo fmt --manifest-path packages/paperclip-runner/runner/Cargo.toml --all -- --check`. - Passed `vitest run src/evals/runnerd-artifact.test.ts` from the Runner package: 5 tests. Initial collection could not resolve Ajv in the fresh worktree. Connecting existing local dependencies resolved that setup failure; no source change was needed. - `git diff --check` passed. Reviewed the diff for secrets, personal data, and private references. - GitHub CI passed on commit `0790af690afaff10f3b69fd9130b5be1c5bab38c`: [main PR workflow](https://github.com/paperclipai/paperclip/actions/runs/42248006277), [Docker Runner check](https://github.com/paperclipai/paperclip/actions/runs/42248006207), and [Windows Runner](https://github.com/paperclipai/paperclip/actions/runs/42248006518). Windows tests cover omission of the field on non-Unix builds. All 61 current-head check runs settled without failure; the latest status context passed. - [Standard Greptile review](https://github.com/paperclipai/paperclip/pull/19488#issuecomment-6689260747) scored that same commit 5/5 with no actionable findings or unresolved threads. - No live provider or host sleep/wake test was run for this metadata-only change. ## Risks The main risk is treating protocol support as permission to park a provider or as proof that a host supports release/resume. The documentation keeps those checks separate. No caller enables the channel from this field in this PR. Current parsers check named fields or project known fields, so the optional field does not change ordinary artifact checks. No migrations, new dependencies, runtime flags, checkpoints, or provider pins. ## Model Used OpenAI GPT-6.1 Sol (`gpt-6.1-sol`), High reasoning, through Codex with tool use and code execution. Independent agent review checked the metadata boundary and compatibility. The context window size is not exposed by this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
e2f0fc9e7d
commit
5e62d8ee82
4 files changed
+36
-2
No files matched your search
@@ -179,6 +179,18 @@ validate the exact Runner identity and acknowledged sequence cut.
|
||||
|
||||
### Hosted park and reclaim loop
|
||||
|
||||
On Unix builds, `paperclip-runnerd --build-metadata` reports
|
||||
`privateHostControlVersion: 1` for the existing private fd 4 protocol below.
|
||||
Other builds omit this field. A consumer must verify the selected executable's
|
||||
identity and require the exact supported version before using this channel;
|
||||
an absent or unknown version does not establish support. Recovery and warm-task
|
||||
versions do not establish it either. Ordinary artifact admission can ignore this
|
||||
optional field.
|
||||
|
||||
This field describes protocol support only. It does not mean a provider is ready
|
||||
to park or that a host implements the public `releaseResumeVersion` contract.
|
||||
Runner readiness checks and host sleep/wake qualification are still required.
|
||||
|
||||
A trusted Launcher may pass a connected Unix stream at fd 4 and start durable
|
||||
listener mode with `--host-control-fd 4`. The descriptor is close-on-exec before
|
||||
provider startup. The private channel accepts the `park`, `claim`, and `retire`
|
||||
|
||||
@@ -115,7 +115,7 @@ fn install_crypto_provider() {
|
||||
}
|
||||
|
||||
fn build_metadata() -> serde_json::Value {
|
||||
json!({
|
||||
let mut metadata = json!({
|
||||
"schema": RUNNERD_BUILD_METADATA_SCHEMA,
|
||||
"binaryName": "paperclip-runnerd",
|
||||
"packageName": "@paperclipai/paperclip-runner",
|
||||
@@ -133,7 +133,11 @@ fn build_metadata() -> serde_json::Value {
|
||||
"maximumVersion": 2
|
||||
},
|
||||
"prpTransportModes": ["dial_ws_loopback", "dial_wss", "listen_ws"]
|
||||
})
|
||||
});
|
||||
if cfg!(unix) {
|
||||
metadata["privateHostControlVersion"] = json!(1);
|
||||
}
|
||||
metadata
|
||||
}
|
||||
|
||||
// The publisher seals image installations. Check only path metadata at startup;
|
||||
@@ -726,6 +730,12 @@ mod tests {
|
||||
assert_eq!(metadata["acpxRecoveryIntegrityVersion"], 1);
|
||||
assert!(metadata.get("acpxSourceRecoveryVersion").is_none());
|
||||
assert!(metadata.get("hostedParkingVersion").is_none());
|
||||
assert!(metadata.get("releaseResumeVersion").is_none());
|
||||
if cfg!(unix) {
|
||||
assert_eq!(metadata["privateHostControlVersion"], 1);
|
||||
} else {
|
||||
assert!(metadata.get("privateHostControlVersion").is_none());
|
||||
}
|
||||
assert_eq!(metadata["schema"], RUNNERD_BUILD_METADATA_SCHEMA);
|
||||
assert_eq!(metadata["binaryContractVersion"], 2);
|
||||
assert_eq!(
|
||||
|
||||
@@ -79,6 +79,13 @@ fn runnerd_startup_reports_build_metadata_without_panicking() {
|
||||
let metadata: Value =
|
||||
serde_json::from_slice(&output.stdout).expect("build metadata should be valid JSON");
|
||||
assert_eq!(metadata["binaryName"], "paperclip-runnerd");
|
||||
if cfg!(unix) {
|
||||
assert_eq!(metadata["privateHostControlVersion"], 1);
|
||||
} else {
|
||||
assert!(metadata.get("privateHostControlVersion").is_none());
|
||||
}
|
||||
assert!(metadata.get("hostedParkingVersion").is_none());
|
||||
assert!(metadata.get("releaseResumeVersion").is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -28,6 +28,11 @@ describe("runnerd artifact metadata", () => {
|
||||
expect(parsePaperclipRunnerdBuildMetadata(valid)).toEqual(valid);
|
||||
});
|
||||
|
||||
it("accepts private host-control metadata without changing ordinary artifact admission", () => {
|
||||
expect(parsePaperclipRunnerdBuildMetadata({ ...valid, privateHostControlVersion: 1 }))
|
||||
.toEqual(valid);
|
||||
});
|
||||
|
||||
it("rejects an unknown binary metadata schema", () => {
|
||||
expect(() => parsePaperclipRunnerdBuildMetadata({ ...valid, schema: "runnerd/v2" }))
|
||||
.toThrow(PaperclipRunnerdArtifactError);
|
||||
|
||||
Reference in new issue
Block a user