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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ isolation remain separate work.
the pinned public API, or authorize unrelated refactors or live Session
configuration switching.

## Core–Runtime integration contract

The [Core–Runtime protocol](docs/runtime-protocol.md) is the integration entry
point for message order, identities, receipts, capability declarations and failure
ownership. The shared types and validators live only in
`internal/agentdaemon/proto`; do not introduce a parallel schema or per-Harness
orchestration path. Both hosted and self-hosted peers use the same contract.
Protocol changes update matching peers together, with an exact wire-version
check and no historical wire fallback.

Core queues and Runtime writes are transport observations, not native acceptance
or completion. The gateway exposes only durable Run subscriptions: connection
loss or overflow closes the subscription with an error and never fabricates
native error/done events. A timeout leaves unconfirmed effects unknown; transport
reconnection never authorizes mutation replay. The public Turn may still be
`failed` for an observation failure (`delivery_unknown` or
`event_stream_incomplete`); that status does not prove native failure or cleanup.
Runtime owns native settlement
and cleanup; Executor release does not reclaim Sandbox Provider compute.
The daemon runs with its starting user's authority, not as an isolation boundary;
Core-managed sandbox infrastructure owns outer isolation.

`make check-runtime-contract` is the focused shared-contract entry point. Its
wire, gateway, transport, dispatcher, real WebSocket and observation-result tests
also run in the required `make check` through `check-go` and `check-agents-api`. Keep failure, cancellation, disconnect
and cleanup assertions in that common suite; native adapter acceptance remains
required for advertised capabilities.

## Workflow and quality

Develop in an isolated worktree on a feature branch and submit a PR. Do not edit
Expand Down Expand Up @@ -496,7 +524,7 @@ forwarding. The explicit daemon-executor decision supersedes the previous native
executor interoperability requirement. The superseded execution route is removed;
retain reusable filesystem helpers,
necessary regressions and historical evidence without a compatibility layer.
The private daemon wire protocol is 0.7.0. Initial, prepared and active input use
The private daemon wire protocol is 0.8.0. Initial, prepared and active input use
the same ordered MessageInput contract, replacing scalar prompts and attachments.
User-message boundaries and text/image order remain intact through Core and the
Runtime wire; adapters own native conversion and receipt aggregation. Text-only
Expand All @@ -506,8 +534,8 @@ unqualified harnesses (Claude SDK, MiniMax Code) reject them at admission rather
their input rewritten. Codex has a flat native
input list and uses blank-line separators between messages; this does not preserve
independent native user-message boundaries. No old wire fallback is maintained.
Deploy Core and daemon together; the existing major/minor WebSocket check rejects
older major/minor peers before dispatch rather than ignoring removed fields.
Deploy Core and daemon together; the WebSocket check requires the exact wire
version, including patch, and rejects mismatches before dispatch.
The independently packaged Claude bridge uses protocol 3 for a prepared Executor
and separately identified Turns; readiness rejects other protocol versions.
Image-bearing messages require a qualified profile/placement before persistence
Expand Down Expand Up @@ -1176,7 +1204,7 @@ a chain of old writable disks across suspension cycles. No Kubernetes, distribut
scheduler or snapshot replication belongs in this V1 profile.

Queued work and live Environment file access request wake. History and published
artifact reads do not. Planned suspension uses private daemon wire 0.7.0 with an
artifact reads do not. Planned suspension uses private daemon wire 0.8.0 with an
Environment and suspension token; a PID/start-time fenced local control signal
wakes the parked daemon, which reauthenticates before admitting new work. A
transient disconnect before confirmation retries the same armed suspension with
Expand Down Expand Up @@ -1278,11 +1306,12 @@ through the provider-neutral bootstrap and checked against execution preparation
The shared policy includes enabled, disabled and an exact-host restricted allowlist.
Core preserves public spelling/order/duplicates and only permits Template overrides
that narrow authority. Adapters translate a normalized copy into native settings;
Core and Docker never select native profile names. Every hosted execution peer
must support `local_environment_network_policy` and receive the complete bound
policy; missing policy never falls back to enabled or an older peer path. Read-only
workspace access does not require execution network policy. A declaration alone
does not qualify an image or admit public hosted creation.
Core and Docker never select native profile names. Execution preparation receives
the complete bound policy; missing policy never falls back to enabled or an older
peer path. Network isolation belongs to the surrounding sandbox, not a daemon
capability declaration. Read-only workspace access does not require execution
network policy. A declaration alone does not qualify an image or admit public
hosted creation.

Codex restricted networking uses its native managed network requirements and proxy.
Its adapter preserves the image's filesystem, approval and hook requirements and
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ check-sqlc:
check-go:
go test ./apps/parsar-daemon/... ./internal/... ./contracts/agents-api/... ./scripts/openapi-split -count=1

.PHONY: check-runtime-contract
check-runtime-contract:
go test ./internal/agentdaemon/proto ./internal/agentdaemon/gateway ./apps/parsar-daemon/internal/transport ./apps/parsar-daemon/internal/dispatch ./apps/parsar-daemon/internal/contracttest -count=1
go test ./services/agents-api/internal/execution -run '^TestRuntimeProtocol' -count=1

build-daemon:
@set -e; output="$${OAC_DEV_HOME:-$$HOME/.oac}/build/daemon"; \
[[ "$$output" == /* ]] || { echo 'Daemon output directory must be absolute' >&2; exit 1; }; \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ native differences.
| [API reference](docs/api/README.md) | The `/v1`, `/core/v1` and `/api/v1` namespaces |
| [Nodes and sandbox backends: operator reference](services/agents-api/HOSTED-SANDBOX-MANAGER.md) | Node protocol, manual registration, placement, reset |
| [Protocol coverage](contracts/agents-api/README.md) and [harness selection](contracts/agents-api/harness-selection.md) | Supported operations and native differences |
| [Core–Runtime protocol](docs/runtime-protocol.md) | Runtime integration, messages, receipts, failure ownership and contract checks |
| [Add a Harness](contracts/agents-api/harness-onboarding.md) | Required adapter interfaces, lifecycle, capabilities, registration and acceptance |
| [Landing page source](site/index.html) | The public site |

Expand Down
1 change: 0 additions & 1 deletion apps/parsar-daemon/internal/cli/agent_discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ func discoverAgentCLIs(rc *runContext, profile string, checks agentCLIChecks) (a
out.Codex.Version = codexVersion
out.Codex.Capabilities.NativeSessionRecovery = codex.SupportsNativeSessionRecovery(codexVersion)
out.Codex.Capabilities.LocalEnvironment = codex.SupportsLocalEnvironment(codexVersion)
out.Codex.Capabilities.LocalEnvironmentNetworkPolicy = codex.SupportsLocalNetworkPolicy(codexVersion)
out.Codex.Capabilities.MCPHTTPRequired = codex.SupportsNativeSessionRecovery(codexVersion)
fmt.Fprintf(rc.stdout, "Codex preflight ok (%s)\n", codexVersion)
} else if errors.Is(codexErr, codex.ErrCLINotFound) {
Expand Down
2 changes: 1 addition & 1 deletion apps/parsar-daemon/internal/cli/claude_sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func discoverClaudeSDK(rc *runContext, profile string, check func(context.Contex
}
caps := &out.Info.Capabilities
caps.EnvironmentNone, caps.FunctionTools = false, info.SupportsWorkspaceFunctions()
caps.Preparation, caps.LocalEnvironment, caps.LocalEnvironmentNetworkPolicy = true, true, true
caps.Preparation, caps.LocalEnvironment = true, true
caps.WorkspaceReadPreparation, caps.NativeSessionRecovery = true, true
}
out.Info.Available, out.Info.Version = true, info.SDK
Expand Down
3 changes: 1 addition & 2 deletions apps/parsar-daemon/internal/cli/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ func mainLoopRemote(rc *runContext, profile string, prof auth.Profile, agentCLIs
DeviceID: boot.DeviceID,
Credential: prof.RunnerCredential,
// DaemonVersion is the WIRE-PROTOCOL version, not the build
// tag. proto.VersionCompatible is a strict major.minor
// tag. proto.VersionCompatible requires an exact version
// match against proto.Version. Build-tag reporting goes
// in heartbeat's DaemonVersion field.
DaemonVersion: proto.Version,
Expand Down Expand Up @@ -420,7 +420,6 @@ func pumpConn(parentCtx context.Context, conn *transport.Conn, registry *agent.R
Timestamp: time.Now().Unix(),
ActiveRequests: router.ActiveRuns(),
DaemonVersion: Version,
ClaudeAvailable: agentCLIs.ClaudeCode.Available, // legacy server compatibility
SupportedAgentKinds: kinds,
}
}, obslog.Bg().With("component", "heartbeat"))
Expand Down
2 changes: 1 addition & 1 deletion apps/parsar-daemon/internal/cli/connect_suspend.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func (s *suspendedRouter) heartbeats(ctx context.Context, conn *transport.Conn,
caps := &kinds[i].Capabilities
caps.WorkspaceOutputExport = s.local.CanExport() && caps.LocalEnvironment && caps.WorkspaceReadPreparation
}
return proto.HeartbeatPayload{Timestamp: time.Now().Unix(), ActiveRequests: s.router.ActiveRuns(), DaemonVersion: Version, ClaudeAvailable: discovery.ClaudeCode.Available, SupportedAgentKinds: kinds}
return proto.HeartbeatPayload{Timestamp: time.Now().Unix(), ActiveRequests: s.router.ActiveRuns(), DaemonVersion: Version, SupportedAgentKinds: kinds}
}, obslog.Bg())
}

Expand Down
2 changes: 1 addition & 1 deletion apps/parsar-daemon/internal/cli/mcode_workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ func discoverMCodeWorkspace(rc *runContext, discovery *agentCLIDiscovery) {
discovery.MCodeWorkspace = &c
caps := &discovery.MCode.Capabilities
caps.EnvironmentNone = false
caps.Preparation, caps.LocalEnvironment, caps.LocalEnvironmentNetworkPolicy = true, true, true
caps.Preparation, caps.LocalEnvironment = true, true
caps.WorkspaceReadPreparation = true
}
Loading
Loading