Skip to content
Open
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
51 changes: 51 additions & 0 deletions docs/proposals/0056_supervisor_executor_adapter_gateway.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,31 @@ fields are the contract used by gate and validation logic.
observed and parseable. It does not mean the run is acceptable. Acceptance still
depends on deterministic post-run checks.

## SpecGraph and Future SpecAgent Boundary

This gateway is also the first explicit boundary between deterministic SpecGraph
core responsibilities and future non-deterministic agent runtime
responsibilities.

SpecGraph owns canonical graph state, specification/proposal records,
deterministic validation, search/indexing, structured reports, lifecycle state,
supervisor planning state, and review gates.

The executor adapter gateway owns only the launch-and-observe boundary:
normalizing execution requests, invoking an external executor adapter,
collecting structured reports, and classifying execution results before normal
supervisor validation.

A future dedicated **SpecAgent** runtime may eventually own provider adapters,
sandbox runtime, agent identity, capability enforcement, BYOK execution, and
tool policy. That extraction should not happen just because the name exists. It
becomes justified only after real use cases create pressure: a second executor,
direct SpecSpace runtime jobs, separate runtime deploy secrets, provider-specific
release cadence, or external-model behavior leaking into SpecGraph core tests.

Until then, `0056` keeps the boundary inside SpecGraph as a contract and
anti-corruption layer.

## Candidate Policy Artifact

Runtime implementation may introduce:
Expand Down Expand Up @@ -346,6 +371,32 @@ The adapter index should summarize:
SpecSpace should consume these artifacts or their projection in existing viewer
surfaces. It should not parse raw executor stdout/stderr.

## Contract-Only Realization Slice

The first bounded realization slice is intentionally smaller than a runnable
executor backend. It introduces the contract surfaces that future BYOK/demo
runners and alternate executor backends must satisfy:

- `tools/supervisor_executor_adapter_policy.json`
- `docs/supervisor_executor_adapter_gateway_contract.md`

This slice defines the request and report boundary:

- executor request contains workspace root, target reference, provider config
reference, policy envelope, and capability envelope;
- executor report returns status, run id, logs reference, produced artifacts,
policy decisions, and normalized error class;
- API keys, raw provider secrets, web auth sessions, billing/account details,
and raw prompts remain outside persisted artifacts;
- BYOK is represented as an injected `provider_config_ref`, not as stored
credentials;
- adapter success remains advisory until normal supervisor validation and gates
accept the result.

This contract slice does not implement SpecSpace login, BYOK UI, Timeweb deploy,
real Codex/Copilot/Claude/Gemini runner wiring, or Agent Passport enforcement.
Those remain later runtime layers.

## Safety Rules

- Codex remains default until an explicit policy changes it.
Expand Down
137 changes: 137 additions & 0 deletions docs/supervisor_executor_adapter_gateway_contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# Supervisor Executor Adapter Gateway Contract

## Purpose

This document is the first SpecGraph-side contract surface for proposal
`0056_supervisor_executor_adapter_gateway`.

The gateway is a launch-and-observe boundary for nested supervisor executors. It
does not implement a BYOK demo, a SpecSpace UI, a container runner, or an
alternate executor backend. It defines the request and report shapes that future
runtime implementations must use when they connect external executors to
SpecGraph.
Comment on lines +5 to +12
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Synchronize the new contract with DocC

This new contract is published technical guidance for future executor implementations, but the commit does not add a corresponding Sources/SpecGraph/Documentation.docc/ page or update tools/docc_sync_contract.json. AGENTS.md requires DocC to stay synchronized whenever docs/ changes affect published technical guidance, so the public DocC docs will omit this executor adapter contract while the repository docs present it as canonical.

Useful? React with 👍 / 👎.


## Boundary

```text
SpecGraph supervisor
-> bounded executor request
-> executor adapter gateway
-> backend-specific runner
-> normalized executor report
-> supervisor validation and gates
```

The adapter gateway is not the trust boundary. It prepares a backend-specific
run and reports what happened. Existing deterministic supervisor validation
continues to decide whether the run is acceptable.

## Responsibility Split

The executor adapter gateway is the current in-repository anti-corruption layer
between deterministic SpecGraph core behavior and future non-deterministic agent
runtime behavior.

SpecGraph owns:

- canonical graph state;
- specification and proposal records;
- deterministic validation;
- search, indexing, reports, and lifecycle state;
- supervisor planning state and review gates.

The gateway owns only the boundary:

- normalize a bounded execution request;
- invoke an external executor adapter;
- collect the structured report contract;
- classify execution results without deciding graph acceptance.

A future dedicated SpecAgent runtime may own provider adapters, sandbox runtime,
agent identity, capability enforcement, BYOK execution, and tool policy. That
future extraction is justified only after real runtime use cases prove the
boundary: for example a second executor backend, direct SpecSpace job execution,
separate deploy secrets, or provider-dependent release cadence.

## Request Contract

A bounded executor request must contain:

- `request_id`: stable request identifier for correlation.
- `workspace_root`: repo-relative or sandbox-root workspace reference.
- `target_ref`: target spec, proposal, operator request, or smoke fixture.
- `provider_config_ref`: opaque runtime provider configuration reference.
- `policy_envelope`: sandbox, approval, allowed-path, and timeout constraints.
- `capability_envelope`: declared backend capabilities for this run.

The gateway must not store API key values, raw provider secrets, billing account
details, or web authentication session data. BYOK-style provider configuration
is represented only through `provider_config_ref`.

## Report Contract

A normalized executor report must contain:

- `request_id`: the request being answered.
- `run_id`: concrete executor run identifier.
- `status`: `ready`, `blocked`, or `failed`.
- `logs_ref`: redacted/local-only log reference.
- `produced_artifacts`: repo-relative artifacts produced by the run.
- `policy_decisions`: adapter-side policy decisions and denials.
- `error_class`: normalized failure class.

`status: ready` means the executor produced a report that can enter supervisor
validation. It does not mean the task succeeded, the graph should be mutated, or
review gates can be skipped.

## Error Classes

The initial normalized error vocabulary is:

- `none`
- `provider_config_missing`
- `auth_unavailable`
- `unsupported_backend`
- `policy_denied`
- `timeout`
- `protocol_failure`
- `executor_crash`
- `unknown`

Backends may produce backend-specific details, but viewer-facing projections
should use the normalized class first.

## BYOK/Demo Precursor

This contract intentionally supports a future BYOK demo through
`provider_config_ref`, not through stored secrets.

Out of scope for this contract slice:

- SpecSpace login.
- BYOK form.
- OpenAI billing or account logic.
- Timeweb deployment wiring.
- Real Codex/Copilot/Claude/Gemini container runner.
- Agent Passport enforcement implementation.

## Safety Requirements

- The gateway must not persist raw prompt text or secrets.
- Backend fallback must not broaden permissions.
- Unsupported backends must fail before launch.
- Experimental backends require explicit operator selection.
- Canonical mutations require normal supervisor validation.
- Raw logs are local-only unless redacted into a derived artifact.
- Adapter success is never final supervisor success.

## Policy Artifact

The machine-readable policy surface is:

```text
tools/supervisor_executor_adapter_policy.json
```

The policy declares request/report required fields, status vocabulary, error
classes, BYOK boundary rules, and non-overridable invariants.
56 changes: 56 additions & 0 deletions tests/test_supervisor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25963,6 +25963,62 @@ def test_proposal_0054_product_workspace_initialization_runtime_is_covered(
assert entry["reflective_chain"]["next_gap"] == "none"


def test_supervisor_executor_adapter_policy_declares_request_report_contract() -> None:
"""Proposal 0056 starts with a contract-only executor gateway policy surface."""
policy_path = SPECGRAPH_ROOT / "tools" / "supervisor_executor_adapter_policy.json"
policy = json.loads(policy_path.read_text(encoding="utf-8"))

assert policy["artifact_kind"] == "supervisor_executor_adapter_policy"
assert policy["schema_version"] == 1
assert policy["default_backend_id"] == "codex"

request = policy["request_contract"]
assert request["artifact_kind"] == "supervisor_executor_request"
for field in (
"request_id",
"workspace_root",
"target_ref",
"provider_config_ref",
"policy_envelope",
"capability_envelope",
):
assert field in request["required_fields"]

report = policy["report_contract"]
assert report["artifact_kind"] == "supervisor_executor_report"
assert report["status_values"] == ["ready", "blocked", "failed"]
assert "provider_config_missing" in report["error_classes"]
assert "protocol_failure" in report["error_classes"]
assert report["logs_ref"]["raw_logs_are_local_only"] is True

byok = policy["future_byok_boundary"]
assert byok["supported_mechanism"] == "provider_config_ref"
assert "api_key_value" in byok["forbidden_in_gateway_artifacts"]
assert "BYOK form" in byok["out_of_scope"]

invariants = set(policy["non_overridable_invariants"])
assert "secrets_must_not_be_persisted" in invariants
assert "adapter_success_is_not_supervisor_success" in invariants


def test_proposal_0056_executor_adapter_contract_runtime_is_covered(
supervisor_module: object,
) -> None:
"""Proposal 0056 is covered by the executor adapter request/report contract slice."""
index = supervisor_module.build_proposal_runtime_index()
by_id = {e["proposal_id"]: e for e in index["entries"]}

assert "0056" in by_id, "Proposal 0056 missing from proposal_runtime_index"
entry = by_id["0056"]
assert entry["runtime_realization"]["status"] == "implemented"
assert entry["validation_closure"]["status"] == "covered"
assert entry["observation_coverage"]["status"] == "covered"
assert entry["runtime_realization"]["missing_markers"] == []
assert entry["validation_closure"]["missing_markers"] == []
assert entry["observation_coverage"]["missing_markers"] == []
assert entry["reflective_chain"]["next_gap"] == "none"


def test_all_implemented_proposals_have_registry_entries() -> None:
"""Every Implemented proposal must have a registry entry with at least one marker."""
registry_path = SPECGRAPH_ROOT / "tools" / "proposal_runtime_registry.json"
Expand Down
49 changes: 44 additions & 5 deletions tools/proposal_runtime_registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -2723,13 +2723,52 @@
"proposal_id": "0056",
"posture": "bounded_runtime_followup",
"runtime_surfaces": [
"tools/supervisor.py",
"tests/test_supervisor.py",
"tools/supervisor_executor_adapter_policy.json",
"docs/supervisor_executor_adapter_gateway_contract.md",
"docs/proposals/0056_supervisor_executor_adapter_gateway.md"
],
"runtime_markers": [],
"validation_markers": [],
"observation_markers": []
"runtime_markers": [
{
"path": "tools/supervisor_executor_adapter_policy.json",
"pattern": "\"artifact_kind\": \"supervisor_executor_adapter_policy\""
},
Comment on lines +2730 to +2734
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep 0056 in backlog until runtime criteria are met

With these runtime markers satisfied by only the new policy JSON/docs, build_proposal_runtime_index() now reports proposal 0056 as implemented/covered/covered with next_gap: none, so make backlog/make next-move skips it. That contradicts the same proposal's acceptance criteria, which still say runtime realization is complete only after policy-driven backend selection, pre-launch unsupported-backend failure, normalized run results feeding gates, smoke fixtures, and viewer-facing adapter artifacts exist; in the current contract-only slice those remain unimplemented, so this registry entry hides real remaining runtime work.

Useful? React with 👍 / 👎.

{
"path": "tools/supervisor_executor_adapter_policy.json",
"pattern": "\"request_contract\""
},
{
"path": "tools/supervisor_executor_adapter_policy.json",
"pattern": "\"report_contract\""
},
{
"path": "docs/supervisor_executor_adapter_gateway_contract.md",
"pattern": "## Request Contract"
},
{
"path": "docs/supervisor_executor_adapter_gateway_contract.md",
"pattern": "## Report Contract"
}
],
"validation_markers": [
{
"path": "tests/test_supervisor.py",
"pattern": "def test_supervisor_executor_adapter_policy_declares_request_report_contract("
},
{
"path": "tests/test_supervisor.py",
"pattern": "def test_proposal_0056_executor_adapter_contract_runtime_is_covered("
}
],
"observation_markers": [
{
"path": "docs/supervisor_executor_adapter_gateway_contract.md",
"pattern": "tools/supervisor_executor_adapter_policy.json"
},
{
"path": "docs/proposals/0056_supervisor_executor_adapter_gateway.md",
"pattern": "## Contract-Only Realization Slice"
}
]
},
{
"proposal_id": "0057",
Expand Down
Loading
Loading