Skip to content

Commit 0be2e10

Browse files
authored
Require explicit Runtime and Harness capability contracts (#256)
* Require explicit Runtime capability support declarations * Make Harness extension implementations and declarations explicit * Clarify capability admission mapping for Harness extensions * Regenerate Harness onboarding guide * Migrate shared registration and capability consumers to explicit declarations * Freeze admitted capabilities and reject undeclared optional operations * Guard evolving Harness interfaces and complete wire projections * Verify declaration admission and document the Runtime extension contract * Declare exercised capabilities in Core and lifecycle fixtures * Preserve unknown Harness classification during availability admission * Run declaration coverage in the focused gate and parameterize live provider selection * Mutate the onboarding peer wire declaration instead of its storage projection
1 parent 3a4ad5f commit 0be2e10

104 files changed

Lines changed: 1848 additions & 436 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CONTRIBUTING.md‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ The Runtime is not a sandbox; see
213213
- Fix shared lifecycle, admission, cancellation, reuse and performance problems
214214
in the common protocol or flow, not with Harness-, Runtime- or vendor-specific
215215
branches in Core. Adapters may differ natively but keep shared semantics.
216+
- Public Harnesses explicitly implement every extension interface, returning the
217+
shared Unsupported error when unqualified; required lifecycle obligations cannot
218+
be skipped. Capability declarations must be complete. Follow the single
219+
[Harness onboarding contract](contracts/agents-api/harness-onboarding.md).
216220
- Express compatibility through declared capabilities and validate selected
217221
combinations explicitly. Public MCP origin and credential authority follow the
218222
[Environment MCP contract](contracts/agents-api/environments.md#public-mcp-connection-origin);
@@ -241,7 +245,9 @@ The Runtime is not a sandbox; see
241245

242246
Shared wire types and validators live only in `internal/agentdaemon/proto`.
243247
Change both peers together with an exact wire-version check; do not add a
244-
parallel schema or a historical wire fallback.
248+
parallel schema or a historical wire fallback. Capability completeness and
249+
interface coverage are mandatory extension gates under the
250+
[explicit declaration contract](docs/runtime-protocol.md#explicit-capability-declarations).
245251

246252
### Pre-release policy
247253

‎Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ check-go:
5656
check-runtime-contract:
5757
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
5858
go test ./services/agents-api/internal/execution -run '^TestRuntimeProtocol' -count=1
59-
go test ./apps/parsar-daemon/internal/agent/... -run '^TestSharedTextLifecycle$$' -count=1
59+
go test ./apps/parsar-daemon/internal/agent/... -run '^(TestSharedTextLifecycle|TestPublicHarnessContractDeclarations|TestRegistryRejectsEveryOmittedCapabilityBeforeReplacement|TestUnsupportedExtensionsHaveNoNativeEffects)$$' -count=1
6060

6161
build-daemon:
6262
@set -e; output="$${OAC_DEV_HOME:-$$HOME/.oac}/build/daemon"; \

‎apps/docs/content/docs/harness-onboarding.mdx‎

Lines changed: 106 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Start from two entry points:
1414
- [`internal/harnessconfig/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/internal/harnessconfig/harness.go):
1515
the shared model configuration contract (declarations and preparation).
1616
- [`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/apps/parsar-daemon/internal/agent/harness.go): the
17-
execution lifecycle, optional interfaces and registration methods.
17+
execution lifecycle, explicit extension contracts and registration methods.
1818

1919

2020
## Ownership
@@ -77,11 +77,15 @@ model communication configuration, not Turn scheduling or native process ownersh
7777
[Harness integration](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/contracts/agents-api/harnesses.md#acceptance-checklist). Record results in
7878
the [qualification table](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/contracts/agents-api/harnesses.md#current-qualified-operations).
7979

80-
Start with the mandatory text lifecycle, then qualify optional operations one at
81-
a time. Call the reusable `agent/contracttest.TextLifecycle` assertions with the
80+
Implement the mandatory text lifecycle and explicitly handle every extension.
81+
Qualify supported extensions one at a time; an unqualified extension returns
82+
`agent.ErrUnsupportedOperation` without native effects. Call the reusable `agent/contracttest.TextLifecycle` assertions with the
8283
adapter's prepared Executor and deterministic native fixture. These assertions
83-
cover healthy reuse, durable input and cancellation; keep native fault and live
84-
acceptance separate. Name the entry test `TestSharedTextLifecycle` so
84+
cover healthy reuse, durable input and cancellation for adapters whose native
85+
owner remains reusable. A native cancellation may instead require retirement:
86+
`Reusable=false` carries a reason and the caller must confirm `Executor.Close`.
87+
Do not force reuse to fit a test helper. Keep native fault and live acceptance
88+
separate. Name the entry test `TestSharedTextLifecycle` so
8589
`make check-runtime-contract` includes it. Do not copy an adapter's native
8690
limitations into the shared Core protocol.
8791

@@ -94,15 +98,16 @@ limitations into the shared Core protocol.
9498
- A new engine supplies an adapter, a qualified profile, registration and an
9599
independently verified deployment. It adds no engine-name branches to API
96100
handlers, persistence, dispatch, scheduling or Environment providers.
97-
- Keep required lifecycle declarations, optional interfaces and registration
101+
- Keep required lifecycle declarations, extension interfaces and registration
98102
methods in `agent/harness.go`. Result types, errors and Registry storage may
99103
stay in focused files. Keep this guide linked to that entry point.
100104
- Use the existing `proto.SupportedAgentKind` and `AgentKindCapabilities`
101105
schema. Do not add a second capability descriptor or a combined optional
102106
interface.
103107
- Onboarding does not require feature equality. Verify common lifecycle
104108
obligations and use the same public assertions for each declared operation.
105-
Optional native differences are separate capability work, not onboarding blockers.
109+
Native differences do not block onboarding, but an omitted declaration or
110+
missing extension implementation does.
106111
- Never equate accepted parameters with applied native behavior.
107112

108113
## Native model configuration
@@ -156,9 +161,11 @@ ownership are in the [unified model configuration design](https://github.com/Min
156161

157162
[`agent/harness.go`](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/apps/parsar-daemon/internal/agent/harness.go) is the
158163
canonical interface entry point. Its required lifecycle is `ExecutorFactory`,
159-
`Executor`, `Turn` and `TurnSettlement`. Optional Turn and workspace interfaces
160-
remain separate; their result types and error values stay in the corresponding
161-
operation files in the same package. All use the existing neutral protocol types.
164+
`Executor`, `Turn` (including `DurableSteerer`) and `TurnSettlement`. Required
165+
methods must perform their native obligations; returning Unsupported is not an
166+
implementation of cancellation, receipts, settlement or cleanup. Turn and workspace
167+
extension interfaces remain small and separate, but every public adapter implements
168+
each explicitly. Their result types and errors stay in focused operation files. All use the existing neutral protocol types.
162169

163170
The [Core–Runtime lifecycle contract](/runtime-protocol#executor-and-turn-lifetimes)
164171
owns preparation failure, partial StartTurn results, output closure, settlement,
@@ -175,7 +182,7 @@ native Session. Their implementations expose the same Executor and Turn contract
175182
Implement cancellation on the exact Turn through `agent.Session`. Follow the
176183
[lifecycle and settlement rules](/runtime-protocol#executor-and-turn-lifetimes);
177184
the adapter must supply native completion evidence to the shared Runtime.
178-
Permission and user-choice responses use the optional interfaces below.
185+
Permission and user-choice responses use the explicit extension interfaces below.
179186

180187
## Events, inputs and optional capabilities
181188

@@ -194,20 +201,50 @@ before consuming a pending interaction. Do not map answers by header or position
194201
Resume only the exact history bound to the Session; missing or ambiguous required
195202
history fails before new model input.
196203

197-
| Interface or contract | When required | Obligation |
204+
| Interface or contract | Required handling | Obligation |
198205
| --- | --- | --- |
199-
| `agent.DurableSteerer` | Current public text execution | Distinguish write and application receipts; preserve retry identity; independent of the optional non-durable `Steerer` |
200-
| `agent.FunctionResultSubmitter` | Public function tools | Match call/result identity and acknowledge native application |
201-
| `agent.PermissionResponder`, `agent.UserChoiceResponder` | When emitting these interactions | Route exact identities and settle receipts |
202-
| `agent.WorkspaceReader`, `agent.WorkspaceDirectoryLister`, `agent.WorkspaceWriter` | Qualified workspace operations | Use the fixed authorized workspace and retain accepted operations through close |
203-
| Neutral message, image, MCP, structured-output and Subagent observations | Only when qualified and advertised | Preserve the operation-specific contract and reject unsupported combinations |
204-
205-
Optional features need not match another harness. The service profile qualifies
206-
public combinations; the Runtime advertises this installation's available support.
207-
Neither replaces schema validation or tenant authorization. Declaring a capability
208-
without implementing its semantics is an error. Workspace reads may use separate
209-
read-only preparations; those do not start model work or provide another execution
210-
lifecycle.
206+
| `ExecutorFactory`, `Executor.StartTurn`, `Executor.Close` | Real implementation | Prepare without model input; keep failed or uncertain resource ownership; confirm cleanup |
207+
| `Turn`, `Session.Cancel`, `CancellationOutcome`, `AwaitSettlement` | Real implementation | Cancel the exact Turn, preserve observed results and confirm settlement independently of cancellation requests |
208+
| `DurableSteerer` | Real implementation on every Turn | Distinguish complete write from native application receipt; preserve retry identity |
209+
| `Steerer` | Explicit implementation or Unsupported | Additional non-durable active-turn input |
210+
| `FunctionResultSubmitter` | Explicit implementation or Unsupported | Match native call/result identity and acknowledge application |
211+
| `PermissionResponder`, `UserChoiceResponder` | Explicit implementation or Unsupported | Respond to exact emitted identities; unknown/expired interactions remain distinct from Unsupported |
212+
| `WorkspaceReader`, `WorkspaceDirectoryLister`, `WorkspaceWriter` | Explicit on Turn, Executor and Prepared owners | Use the authorized workspace, confirm access/commit/close, or return the operation's Unsupported error |
213+
| `Prepared`, `PreparedCancellation` | Real implementation for an executable preparation | Preserve resource and output ownership across Start, cancellation and unused cleanup |
214+
| Neutral messages, images, MCP, structured output and Subagent observations | Explicit capability decisions | Preserve each operation's protocol semantics; reject unsupported input before submission |
215+
216+
Each adapter's `contracts.go` contains individual compile-time assertions for these
217+
small interfaces. Do not embed a default implementation that makes future
218+
interfaces appear implemented. Adding a contract also requires classification in
219+
the common completeness check and an explicit assertion for every public adapter;
220+
the check follows the authored Harness catalog.
221+
222+
For a design-level refusal, implement the method directly, for example:
223+
224+
```go
225+
func (s *Session) SubmitFunctionResult(context.Context, proto.FunctionResultPayload) error {
226+
return fmt.Errorf("%w: native public function tools are not qualified", agent.ErrUnsupportedOperation)
227+
}
228+
```
229+
230+
The reason is a fixed safe string, never submitted content, a credential or raw
231+
native diagnostics. Unsupported guarantees no native side effect. It is not a
232+
successful empty operation. Installation unavailability, unknown interaction IDs,
233+
native failures and uncertain outcomes keep their existing errors and ownership.
234+
A nil `Turn` still means no input was submitted and output remains with the caller;
235+
it must not be repurposed as an Unsupported marker.
236+
237+
Workspace capability describes the actual Runtime/resource-owner combination.
238+
Codex and MiniMax resource objects explicitly reject native workspace access while
239+
the common authorized `localworkspace` owner provides it. Claude can expose native
240+
read/list access; writes are provided by the common owner. Interface presence alone
241+
must never select a resource or advertise support.
242+
243+
The service profile qualifies public combinations; the Runtime advertises the
244+
installed combination. Neither replaces schema validation or tenant authorization.
245+
Native behavior tests must agree with supported declarations. An advertised
246+
operation returning Unsupported is a contract violation, never success or grounds
247+
for automatic replay.
211248

212249
## Register the adapter
213250

@@ -224,8 +261,29 @@ from [`cli/agent_registration.go`](https://github.com/MiniMax-AI/parsar-core/blo
224261
| 3 | `RegisterPreparation(kind, workspaceRead, agent.PreparationFactory)` | Optional. Separate read-only workspace preparation when qualified workspace operations need it. |
225262

226263
The direct-call `agent.Factory` should delegate to the same Executor
227-
implementation. Every other capability declaration must match behavior verified
228-
for that installation. Runtime registration does not grant Core qualification;
264+
implementation. Every `proto.AgentKindCapabilities` field must be explicitly
265+
`proto.CapabilitySupported` or `proto.CapabilityUnsupported`.
266+
`proto.CapabilityUnspecified` is invalid: zero values and omitted fields do not mean
267+
Unsupported. Installation probes may use `proto.CapabilityFromBool` for an
268+
individual field; they must not populate all unmentioned or future fields.
269+
Availability remains separate in `SupportedAgentKind.Available`.
270+
271+
Registration and wire decoding validate the complete declaration. The wire carries
272+
an explicit boolean for every field; omitted and null fields are invalid. A new
273+
field requires a decision by every production declaration. Runtime consumers use
274+
`IsSupported()` and reject unsupported requests before native operations; an
275+
interface assertion only verifies implementation, never support. Every declaration
276+
must match behavior verified for that installation.
277+
278+
The admission mapping is explicit: `Steering` controls non-durable `Steerer` input;
279+
`DurableInputReceipts` controls `DurableSteerer` input and also requires the Turn
280+
settlement contract. Neither implies the other. Core's current public text profile
281+
requires both advertised capabilities. `Permissions` qualifies permission and
282+
user-choice responses together; a supported declaration requires both native
283+
response paths. Workspace declarations describe the selected authorized resource
284+
owner, including the common Runtime workspace implementation.
285+
286+
Runtime registration does not grant Core qualification;
229287
that belongs to the service profile.
230288

231289
The runnable test-only example is
@@ -276,7 +334,7 @@ The [Harness selection contract](https://github.com/MiniMax-AI/parsar-core/blob/
276334
deployment enablement, defaults and immutable Session binding. This guide adds no
277335
second selector or fallback rule.
278336

279-
## Required versus optional operations
337+
## Required versus extension operations
280338

281339
The current public text path requires durable turns, applied input receipts,
282340
ordered observations, cancellation and enforcement of disabled execution controls.
@@ -287,7 +345,7 @@ of enforcement.
287345

288346
MCP, public function calls, deferred function discovery, structured output, image inputs, verbosity controls and other optional
289347
operations do not need to match another engine. Reject unqualified combinations
290-
explicitly and record the gap. Never advertise a capability to bypass selection.
348+
with Unsupported and record the gap. Never advertise a capability to bypass selection.
291349

292350
Structured-output adapters consume `ExecutionControls.OutputFormat` and publish
293351
confirmed native output through the existing Message contract. Register public
@@ -334,6 +392,26 @@ not add routes, storage branches or a harness-specific Core scheduler. Report
334392
unsupported native facts explicitly; completing a child task is not closing its
335393
Subagent. Native background work must remain owned through settlement and cancel.
336394

395+
## Contract verification
396+
397+
Run `make check-runtime-contract`, the three adapter test packages and `make check`.
398+
The common completeness gate covers capability omissions and interface assertions;
399+
adapter tests must cover actual native semantics, not only method presence.
400+
401+
| Boundary | Existing focused evidence |
402+
| --- | --- |
403+
| Codex reuse, cancellation and unconfirmed cleanup | `codex/executor_test.go`, `terminal_cleanup_test.go`, `prepared_cancel_test.go` |
404+
| Codex input receipts and strict recovery | `codex/function_write_receipt_test.go`, `function_receipt_test.go`, `resume_test.go`, `recovery_test.go` |
405+
| Claude input ownership, cancellation and preparation cleanup | `claudesdk/executor_test.go`, `cancellation_test.go`, `preparation_test.go` |
406+
| MiniMax cancellation retirement, failed Start and cleanup retry | `mcode/executor_test.go`, `executor_backpressure_test.go` |
407+
| MiniMax native history binding | `mcode/session_test.go` |
408+
| Explicit refusals without native effects or fabricated results | Each adapter's `unsupported_test.go` |
409+
410+
These paths are relative to `apps/parsar-daemon/internal/agent`. Controlled native
411+
transport fixtures establish failure and ownership behavior; they are not live model
412+
qualification. Preserve the separate native acceptance requirements in
413+
[Harness integration](https://github.com/MiniMax-AI/parsar-core/blob/f6d258735fc601c521dd990e6f9e1ed261f4ef2d/contracts/agents-api/harnesses.md#acceptance-checklist).
414+
337415
## Native installer participation
338416

339417
An adapter may supply `agent.Installation` from `installation.go` in its own

‎apps/docs/content/docs/runtime-protocol.mdx‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,37 @@ leases and evicts old Run/interaction routes; the new connection does not inheri
5959
them. A valid credential and connection are not authority to choose another
6060
Session or Environment binding.
6161

62+
### Explicit capability declarations
63+
64+
`AgentKindCapabilities` describes the composed Runtime and Harness, independently
65+
of `Available` and the Core model profile. Every field uses `CapabilitySupport`:
66+
`CapabilitySupported` or `CapabilityUnsupported`. Zero means unspecified and is
67+
invalid even for an unavailable Harness. Registration validates the complete
68+
struct before changing the registry; there is no implicit basic descriptor.
69+
70+
The wire still uses JSON booleans and includes every field, including `false`.
71+
Encoding incomplete declarations fails; decoding rejects omitted, null, invalid
72+
or unknown capability fields, including a missing capability object. An invalid
73+
heartbeat clears the connection's admission snapshot and closes its transport.
74+
That establishes no native completion or cancellation result. Both peers use the
75+
same exact wire version; no historical declaration format is accepted.
76+
77+
Each admitted Executor and Turn retains its declaration. Rediscovery cannot add
78+
operations to an existing owner. Optional operations check this snapshot before
79+
native calls; interface presence alone never grants support. A declared operation
80+
returning `agent.ErrUnsupportedOperation` is a contract violation, distinct from
81+
unavailability, a failed native call or an uncertain write. Uncertain operations
82+
keep their existing receipts and ownership; they are never automatically replayed.
83+
Workspace support includes the common Runtime workspace implementation, so a
84+
native adapter's unsupported workspace method does not disable that composition.
85+
86+
New fields require an explicit decision in each production declaration. Contract
87+
tests enumerate every field for registration, wire round trips and the persisted
88+
boolean projection. The shared test fixture lists current fields individually;
89+
it does not supply defaults for future fields. The Harness interface inventory
90+
also requires a role decision and compile assertions for every public adapter;
91+
see [Harness onboarding](/harness-onboarding).
92+
6293
### Executor and Turn lifetimes
6394

6495
This section owns the separation of execution and resource lifetimes.

0 commit comments

Comments
 (0)