Skip to content
Closed
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
69 changes: 67 additions & 2 deletions .agents/skills/launch-openshell-gator/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ command -v ruby
```

The local `openshell` wrapper may recompile the CLI. If that fails, fix the local build or ask the operator before changing unrelated source.
Remote gateway launches also require Docker with Buildx:

```bash
command -v docker
docker buildx version
```

Authenticate Docker to an operator-selected private OCI repository before the
launch. Do not print registry credentials or credential-helper configuration.

### Step 3: Verify GitHub Auth

Expand Down Expand Up @@ -132,6 +141,17 @@ sandbox_name="gator-pr-${pr_number}-supervised"

For local image contexts passed to `--from`, use an agent-created path such as `mktemp -d`; do not pass raw user-supplied paths without validating that they are expected local Dockerfile contexts.

For remote publication, accept only a repository without whitespace, a tag, or
a digest. A registry port is allowed:

```bash
publish_repository="<operator-selected-private-repository>"
[[ -n "$publish_repository" ]] || { echo "empty publish repository" >&2; exit 1; }
[[ "$publish_repository" != *[[:space:]]* ]] || { echo "publish repository contains whitespace" >&2; exit 1; }
[[ "$publish_repository" != *@* ]] || { echo "publish repository must not contain a digest" >&2; exit 1; }
[[ "${publish_repository##*/}" != *:* ]] || { echo "publish repository must not contain a tag" >&2; exit 1; }
```

## Standard Launches

### Launch A PR Watcher
Expand All @@ -157,6 +177,43 @@ sandbox_name="gator-pr-${pr_number}-supervised"

The launcher builds the gator sandbox image when needed, stages the immutable payload, imports provider profiles, configures provider credentials and refresh, creates the sandbox, and writes a background log under `scripts/agents/gator/logs/`.

### Launch A PR Watcher On A Remote Gateway

Use `--publish-to` when the selected gateway cannot access the operator's local
Docker context. The registry repository must be private, authenticated on the
host, and pullable by the remote gateway.

```bash
gateway_name="<selected-remote-gateway-name>"
publish_repository="<operator-selected-private-repository>"
pr_number="<digits-only>"
[[ "$gateway_name" =~ ^[A-Za-z0-9_.-]+$ ]] || { echo "invalid gateway name" >&2; exit 1; }
[[ -n "$publish_repository" ]] || { echo "empty publish repository" >&2; exit 1; }
[[ "$publish_repository" != *[[:space:]]* ]] || { echo "publish repository contains whitespace" >&2; exit 1; }
[[ "$publish_repository" != *@* ]] || { echo "publish repository must not contain a digest" >&2; exit 1; }
[[ "${publish_repository##*/}" != *:* ]] || { echo "publish repository must not contain a tag" >&2; exit 1; }
[[ "$pr_number" =~ ^[0-9]+$ ]] || { echo "invalid PR number" >&2; exit 1; }
sandbox_name="gator-pr-${pr_number}-supervised"
[[ "$sandbox_name" =~ ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$ ]] || { echo "invalid sandbox name" >&2; exit 1; }

./scripts/agents/run.sh \
--agent gator \
--gateway "$gateway_name" \
--name "$sandbox_name" \
--publish-to "$publish_repository" \
--platform linux/amd64 \
--watch \
--background \
"Review and monitor PR #${pr_number} through the gator-gate workflow. Scope this invocation only to PR #${pr_number}."
```

The launcher stages the same immutable payload used for local launches, pushes
it with a content-derived tag, reads the pushed digest from BuildKit metadata,
and creates the sandbox from `repository@sha256:...`. Publication finishes
before gateway settings or providers are changed. The image contains the
rendered operator prompt and injected agent assets, so use an appropriate
registry retention policy.

### Launch An Issue Or Issue/PR Pair

```bash
Expand Down Expand Up @@ -342,12 +399,19 @@ Action: load `debug-openshell-cluster` and diagnose the gateway/driver. Do not k

### Image Build Failure

Symptoms: Dockerfile step failure, missing package, incompatible Codex CLI, registry pull failure.
Symptoms: Dockerfile step failure, missing package, incompatible Codex CLI,
Buildx push failure, missing published digest, or registry pull failure.

Actions:

- Confirm the build context is `scripts/agents/gator/` or the intended temporary `--from` context.
- Confirm Docker or the selected gateway runtime can pull `nvcr.io/nvidia/base/ubuntu:noble-20251013`.
- For remote gateways, confirm Docker is authenticated to the publish repository
and the gateway runtime has pull access to it.
- Pass a repository without a tag or digest to `--publish-to`; the launcher owns
the content tag and launches the registry-reported digest.
- If publication fails, fix registry authentication or Buildx before retrying.
The launcher has not changed gateway settings or providers at that point.
- For Codex CLI version experiments, adjust a temporary Docker context first.
- Do not commit Dockerfile version changes unless the repo should permanently use that version.

Expand Down Expand Up @@ -386,7 +450,8 @@ When you launch or inspect gator, report:
- Log path.
- Target issue/PR scope.
- Harness and model when relevant.
- Whether image build and sandbox creation succeeded.
- Whether image build, optional publication, and sandbox creation succeeded.
- The digest-pinned image reference for remote launches.
- Latest sentinel or heartbeat status.
- Any human action needed.

Expand Down
8 changes: 8 additions & 0 deletions architecture/sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ only when the set is already empty; any other outcome fails the spawn.
sync, config polling, and log push.
6. It launches the agent command as the restricted sandbox user.

Repository-owned agent launchers treat their rendered prompt, skills, subagents,
and runtime as an immutable image payload. A local gateway can build the staged
Docker context directly. For a remote gateway, the launcher can publish the
context to an operator-selected OCI repository and submit the registry-reported
digest to the gateway. Registry authentication and retention remain
operator-owned, and digest pinning ensures the launched payload is the one that
was staged.

## Isolation Layers

OpenShell uses overlapping controls rather than a single sandbox primitive:
Expand Down
74 changes: 63 additions & 11 deletions scripts/agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ and execution live in `runtime/harnesses/<name>/`.
```text
scripts/agents/
run.sh # Generic manifest-driven launcher
publish.sh # Agent-agnostic OCI publisher
run_test.sh # Launcher integration tests with isolated mocks
runtime/ # Shared in-sandbox runtime
entrypoint.sh # Starts the in-sandbox supervisor
supervisor.sh # Runs bounded harness cycles in once/watch mode
Expand Down Expand Up @@ -75,24 +77,27 @@ Manifest paths support these prefixes:
manifest-declared subagent variables such as `{{REVIEWER_COMMAND}}`.
9. Build a temporary Docker context that bakes the rendered payload into
`/etc/openshell/agent-payload`.
10. Apply manifest-declared gateway settings.
11. Resolve provider profile IDs by scanning `profile_paths` in order.
12. Import each provider profile into the gateway. If an active profile already
10. When `--publish-to` is set, publish that context for the selected platform
and replace the local source with the repository's immutable image digest.
11. Apply manifest-declared gateway settings.
12. Resolve provider profile IDs by scanning `profile_paths` in order.
13. Import each provider profile into the gateway. If an active profile already
exists, the launcher keeps going and uses it.
13. Resolve provider credentials from host commands, JSON files, or literal
14. Resolve provider credentials from host commands, JSON files, or literal
manifest values.
14. Create or update each provider instance and attach every selected provider
15. Create or update each provider instance and attach every selected provider
to the sandbox.
15. Configure and rotate refresh-backed provider credentials when declared by
16. Configure and rotate refresh-backed provider credentials when declared by
the manifest.
16. Run `openshell sandbox create` from that temporary Dockerfile source.
17. Inside the sandbox, run `/etc/openshell/agent-payload/runtime/entrypoint.sh`.
18. The runtime entrypoint starts
17. Run `openshell sandbox create` from the temporary Dockerfile source or
published digest.
18. Inside the sandbox, run `/etc/openshell/agent-payload/runtime/entrypoint.sh`.
19. The runtime entrypoint starts
`/etc/openshell/agent-payload/runtime/supervisor.sh`.
19. The supervisor invokes
20. The supervisor invokes
`/etc/openshell/agent-payload/runtime/harnesses/<harness>/exec.sh` as a
bounded child execution.
20. Harness adapters prepare harness-local auth/config and execute the agent
21. Harness adapters prepare harness-local auth/config and execute the agent
prompt headlessly.

The payload directory is baked into the image under `/etc/openshell`, which the
Expand All @@ -101,6 +106,53 @@ subagent definitions, and runtime scripts are agent guts, not workspace state.
Agents should write session artifacts, checkouts, temporary files, and future
memory records under `/sandbox` or `/tmp` instead.

## Remote Gateways

A remote gateway cannot build a Dockerfile from the operator's filesystem. Pass
an OCI repository to make the launcher build and push the staged context before
it changes gateway settings or providers:

```shell
./scripts/agents/run.sh \
--agent gator \
--gateway drew-sandbox \
--publish-to us-west1-docker.pkg.dev/example-project/agents/gator \
--platform linux/amd64 \
"Review and monitor PR #2253 through the gator-gate workflow."
```

Authenticate Docker to the registry first and use a repository the remote
gateway can pull. `--publish-to` accepts a repository without a tag or digest.
The launcher derives a content tag for the push, reads the pushed digest from
BuildKit metadata, and gives `openshell sandbox create` the digest-pinned image.
This prevents a mutable tag from changing between publication and launch.

The staged image contains the rendered operator prompt, skills, subagents, and
runtime. Use a private repository with an appropriate access and retention
policy. Set `OPENSHELL_AGENT_PUBLISH_TO` and `OPENSHELL_AGENT_PLATFORM` for
environment-based configuration. The platform defaults to `linux/amd64`.

Publishing is not gator-specific. `scripts/agents/publish.sh` accepts any
Dockerfile or Docker context and prints only the digest-pinned reference on
standard output:

```shell
image_ref="$(
./scripts/agents/publish.sh \
--from ./path/to/context \
--publish-to us-west1-docker.pkg.dev/example-project/agents/example \
--platform linux/amd64
)"
```

This lets other agent launchers and CI workflows reuse the publisher without
depending on gator's manifest, providers, prompt, or runtime.

If the selected gateway is known to be remote and `--publish-to` is omitted, the
launcher stops with guidance before changing gateway state. If gateway metadata
cannot be read, the existing local-source behavior is preserved and the
OpenShell CLI reports any incompatibility.

## Runtime Modes

Agents can run in `once` or `watch` mode. In `once` mode the supervisor runs one
Expand Down
26 changes: 25 additions & 1 deletion scripts/agents/gator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ Launch a headless sandbox agent that runs the `gator-gate` skill against OpenShe
- `gh` is authenticated on the host and has access to `NVIDIA/OpenShell` and `NVIDIA/OpenShell-Community`.
- For `--harness codex`, `codex login` has created `$HOME/.codex/auth.json`.
- For `--harness codex`, local Codex auth must include an access token, refresh token, and account ID.
- A local gateway is available when using the default local Dockerfile source.
- A local gateway is available when using the default local Dockerfile source,
or Docker Buildx is authenticated to a private OCI repository that the remote
gateway can pull.

## Usage

Expand All @@ -21,6 +23,28 @@ Launch a headless sandbox agent that runs the `gator-gate` skill against OpenShe

By default the launcher uses `scripts/agents/gator/Dockerfile` as the sandbox source. Local gateways build `scripts/agents/gator/` as the image context, so gator-specific image files such as `policy.yaml` and `bin/gh` stay with the gator agent. The launcher bakes rendered prompts, skills, subagents, and shared runtime files into `/etc/openshell/agent-payload`, so `--from` must point to a local Dockerfile or directory containing a Dockerfile.

For a remote gateway, publish that fully staged context and launch its immutable
digest:

```shell
./scripts/agents/run.sh \
--agent gator \
--gateway drew-sandbox \
--publish-to us-west1-docker.pkg.dev/example-project/agents/gator \
--platform linux/amd64 \
--watch \
--background \
"Review and monitor PR #2253 through the gator-gate workflow. Scope this invocation only to PR #2253."
```

Configure Docker's registry credential helper before launching. The repository
must not include a tag or digest, and the remote gateway needs pull access. The
launcher uses a content-derived push tag but creates the sandbox from the
registry-reported digest. Because the image includes the rendered operator
prompt and injected agent assets, use a private repository and an appropriate
retention policy. `OPENSHELL_AGENT_PUBLISH_TO` and
`OPENSHELL_AGENT_PLATFORM` are the equivalent environment variables.

Use `--harness codex` to select Codex explicitly. Other harness names are rejected until their support is added to `agent.yaml` and `scripts/agents/runtime/harnesses/<name>/`. Agent directories do not carry their own harness implementations; they provide prompt templates and optional skills or subagents for the shared runtime to inject.

Use `--codex-bin "$(command -v codex)"` only when the host executable is compatible with the sandbox OS and architecture.
Expand Down
Loading
Loading