{"owner":"NVIDIA","repo":"OpenShell","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","crates/openshell-supervisor-process/src/skills/policy-advisor/SKILL.md",".agents/skills/watch-github-actions/SKILL.md",".agents/skills/update-docs/SKILL.md",".agents/skills/build-from-issue/SKILL.md"],"skills":{"AGENTS.md":"# Agent Instructions\n\nThis file is the primary instruction surface for agents contributing to OpenShell. It is injected into your context on every interaction — keep that in mind when proposing changes to it.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for build instructions, task reference, project structure, and the full agent skills table.\n\n## Project Identity\n\nOpenShell is built agent-first. We design systems and use agents to implement them — this is not vibe coding. The product provides safe, sandboxed runtimes for autonomous AI agents, and the project itself is built using the same agent-driven workflows it enables.\n\n## Skills\n\nAgent skills live in `.agents/skills/`. Your harness can discover and load them natively — do not rely on this file for a full inventory. The detailed skills table is in [CONTRIBUTING.md](CONTRIBUTING.md) (for humans).\n\n## Workflow Chains\n\nThese pipelines connect skills into end-to-end workflows. Individual skill files don't describe these relationships.\n\n- **Community inflow:** `triage-issue` → human disposition and roadmap placement → `create-spike` when needed → `build-from-issue`\n  - Triage establishes facts and marks technically valid issues `state:validated`. A human signals that the project should pursue the work by applying `state:accepted` or placing the issue on the roadmap. The `agent:*` labels support unattended agents that scan for queued work: a human queues a plan with `agent:plan-requested`, the agent returns `agent:plan-ready`, and a human queues implementation with `agent:implementation-requested`. A direct user request to an agent authorizes the requested phase without those labels.\n- **Internal development:** `create-spike` → human disposition and roadmap placement → `build-from-issue`\n  - Spike explores feasibility and marks its issue `state:validated` when sufficient evidence exists. A human accepts it with `state:accepted` or roadmap placement, or declines it, and optionally queues it through the `agent:*` workflow or directs an agent to it.\n- **Security:** `review-security-issue` → `fix-security-issue`\n  - General build agents must not process `topic:security` issues. For unattended processing, a human queues specialized review with `agent:plan-requested`; review produces a severity assessment and remediation plan; a human queues remediation with `agent:implementation-requested`. Direct requests to the specialized skills do not require those labels.\n- **Policy iteration:** `openshell-cli` → `generate-sandbox-policy`\n  - CLI manages the sandbox lifecycle; policy generation authors the YAML constraints.\n\n## Architecture Overview\n\n| Path | Components | Purpose |\n|------|-----------|---------|\n| `crates/openshell-cli/` | CLI binary | User-facing command-line interface |\n| `crates/openshell-server/` | Gateway server | Control-plane API, sandbox lifecycle, auth boundary |\n| `crates/openshell-sandbox/` | Sandbox runtime | Container supervision, policy-enforced egress routing |\n| `crates/openshell-policy/` | Policy engine | Filesystem, network, process, and inference constraints |\n| `crates/openshell-router/` | Privacy router | Privacy-aware LLM routing |\n| `crates/openshell-bootstrap/` | Gateway metadata | Gateway registration metadata, auth token storage, mTLS bundle storage |\n| `crates/openshell-gateway-interceptors/` | Gateway interceptors | Intercepts and transforms configured gRPC requests at the gateway routing boundary |\n| `crates/openshell-ocsf/` | OCSF logging | OCSF v1.7.0 event types, builders, shorthand/JSONL formatters, tracing layers |\n| `crates/openshell-otel/` | OpenTelemetry support | Shared OTLP trace provider, resource, and tracing-layer construction |\n| `crates/openshell-core/` | Shared core | Common types, configuration, error handling |\n| `crates/openshell-extension-core/` | Extension core | Shared extension identity, JWT claims, bearer-token rotation, and TLS transport primitives |\n| `crates/openshell-sdk/` | Shared client SDK | Async Rust gateway client (gRPC transport, TLS, OIDC refresh, edge tunnel); consumed by CLI, TUI, and `@openshell/sdk` |\n| `crates/openshell-providers/` | Provider management | Credential provider backends |\n| `crates/openshell-tui/` | Terminal UI | Ratatui-based dashboard for monitoring |\n| `crates/openshell-driver-kubernetes-secrets/` | Kubernetes Secrets credential driver | In-process `CredentialDriver` backend for OpenShell-managed K8s Secret storage |\n| `crates/openshell-driver-vault/` | Vault credential driver | In-process `CredentialDriver` backend for Vault-compatible KV storage |\n| `crates/openshell-driver-db-credstore/` | Database credential driver | In-process `CredentialDriver` backend for gateway database credential storage |\n| `crates/openshell-driver-kubernetes/` | Kubernetes compute driver | In-process `ComputeDriver` backend for K8s sandbox pods |\n| `crates/openshell-driver-docker/` | Docker compute driver | In-process `ComputeDriver` backend for local Docker sandbox containers |\n| `crates/openshell-driver-podman/` | Podman compute driver | In-process `ComputeDriver` backend for local Podman sandbox containers |\n| `crates/openshell-driver-vm/` | VM compute driver | Standalone libkrun-backed `ComputeDriver` subprocess (embeds its own rootfs + runtime) |\n| `crates/openshell-prover/` | Policy prover | Policy verification and proof generation |\n| `crates/openshell-server-macros/` | Server macros | Compile-time helpers for gateway RPC authorization |\n| `crates/openshell-supervisor-middleware/` | Middleware runtime | Generic middleware registry, remote service integration, and chain execution |\n| `crates/openshell-supervisor-middleware-builtins/` | Built-in middleware | First-party in-process middleware implementations |\n| `crates/openshell-supervisor-network/` | Network supervisor | Proxying, L7 enforcement, policy evaluation, and inference routing |\n| `crates/openshell-supervisor-process/` | Process supervisor | Process lifecycle, namespace, and bypass monitoring |\n| `crates/openshell-vfio/` | VFIO support | PCI and GPU passthrough preparation and lifecycle |\n| `python/openshell/` | Python SDK | Python bindings and CLI packaging |\n| `sdk/typescript/` | TypeScript SDK | Native Connect client, curated sandbox API, and generated protobuf types |\n| `proto/` | Protobuf definitions | gRPC service contracts |\n| `deploy/` | Docker, Helm, K8s | Dockerfiles, Helm chart, manifests |\n| `docs/` | Published docs | MDX pages, navigation, and content assets |\n| `fern/` | Docs site config | Fern site config, components, and theme assets |\n| `.agents/skills/` | Agent skills | Workflow automation for development |\n| `.agents/agents/` | Agent personas | Sub-agent definitions (e.g., reviewer, doc writer) |\n| `architecture/` | Architecture docs | Design decisions and component documentation |\n\n## Vouch System\n\n- First-time external contributors must be vouched before their PRs are accepted. The `vouch-check` workflow auto-closes PRs from unvouched users.\n- Org members and collaborators bypass the vouch gate automatically.\n- Maintainers vouch users by commenting `/vouch` on a Vouch Request discussion. The `vouch-command` workflow appends the username to `.github/VOUCHED.td`.\n- Skills that create PRs (`create-github-pr`, `build-from-issue`) should note this requirement when operating on behalf of external contributors.\n\n## Issue and PR Conventions\n\n- **Bug reports and feature requests** must include a User Story, Problem Statement, Impact / Why This Matters, and Acceptance Criteria. The impact should explain the consequences of the current behavior, the current workaround, and why that workaround is insufficient. Bug reports additionally require reproduction steps and environment details and may include concise, redacted logs.\n- **Feature requests** must also include a Proposed Design and Alternatives Considered. The design should define the user-facing workflow and externally observable behavior while leaving internal implementation choices open. Agent investigation is optional.\n- **New features** must start as GitHub issues using the feature request template. Open an RFC only after an issue exists; maintainers decide when one is needed and assign RFC numbers from the issue.\n- **Issue triage** establishes technical validity and impact evidence. Agents never decide acceptance, apply `state:accepted`, place issues on the roadmap, or apply `agent:plan-requested` or `agent:implementation-requested`. Humans accept or decline validated work; `state:accepted` or roadmap placement records acceptance, and roadmap association additionally carries sequencing. The request labels queue work for unattended agents; an explicit user instruction can instead authorize an agent to plan or implement a specific issue. OpenShell has no `priority:*` labels.\n- **PRs** must follow the PR template structure: Summary, Related Issue, Changes, Testing, Checklist. Contributors should use their agent to investigate the current code and behavior for accepted issue-backed work, verify any diagnostics already on the issue, understand the change they submit, and report the resulting implementation and verification—not paste an earlier issue-filing diagnostic.\n- **PRs for features, user-visible behavior, public APIs, architecture, or multi-PR efforts** must link an accepted issue. Small docs fixes, mechanical maintenance, and obvious localized bug fixes may state why no issue is required.\n- **PRs from unvouched external contributors** are automatically closed. See the Vouch System section above.\n- **Security vulnerabilities** must NOT be filed as GitHub issues. Follow [SECURITY.md](SECURITY.md).\n- Skills that create issues or PRs (`create-github-issue`, `create-github-pr`, `build-from-issue`) should produce output conforming to these templates.\n\n## Plans\n\n- Store plan documents in `architecture/plans`. This is git ignored so its for easier access for humans. When asked to create Spikes or issues, you can skip to GitHub issues. Only use the plans dir when you aren't writing data somewhere else specific.\n- When asked to write a plan, write it there without asking for the location.\n\n## Sandbox Logging (OCSF)\n\nWhen adding or modifying log emissions in `openshell-sandbox`, determine whether the event should use OCSF structured logging or plain `tracing`.\n\n### When to use OCSF\n\nUse an OCSF builder + `ocsf_emit!()` for events that represent **observable sandbox behavior** visible to operators, security teams, or agents monitoring the sandbox:\n\n- Network decisions (allow, deny, bypass detection)\n- HTTP/L7 enforcement decisions\n- SSH authentication (accepted, denied, nonce replay)\n- Process lifecycle (start, exit, timeout, signal failure)\n- Security findings (unsafe policy, unavailable controls, replay attacks)\n- Configuration changes (policy load/reload, TLS setup, inference routes, settings)\n- Application lifecycle (supervisor start, SSH server ready)\n\n### When to use plain tracing\n\nUse `info!()`, `debug!()`, `warn!()` for **internal operational plumbing** that doesn't represent a security decision or observable state change:\n\n- gRPC connection attempts and retries\n- \"About to do X\" events where the result is logged separately\n- Internal SSH channel state (unknown channel, PTY resize)\n- Zombie process reaping, denial flush telemetry\n- DEBUG/TRACE level diagnostics\n\n### Choosing the OCSF event class\n\n| Event type | Builder | When to use |\n|---|---|---|\n| TCP connections, proxy tunnels, bypass | `NetworkActivityBuilder` | L4 network decisions, proxy operational events |\n| HTTP requests, L7 enforcement | `HttpActivityBuilder` | Per-request method/path decisions |\n| SSH sessions | `SshActivityBuilder` | Authentication, channel operations |\n| Process start/stop | `ProcessActivityBuilder` | Entrypoint lifecycle, signal failures |\n| Security alerts | `DetectionFindingBuilder` | Nonce replay, bypass detection, unsafe policy. Dual-emit with the domain event. |\n| Policy/config changes | `ConfigStateChangeBuilder` | Policy load, Landlock apply, TLS setup, inference routes, settings |\n| Supervisor lifecycle | `AppLifecycleBuilder` | Sandbox start, SSH server ready/failed |\n\n### Severity guidelines\n\n| Severity | When |\n|---|---|\n| `Informational` | Allowed connections, successful operations, config loaded |\n| `Low` | DNS failures, non-fatal operational warnings, LOG rule failures |\n| `Medium` | Denied connections, policy violations, deprecated config |\n| `High` | Security findings (nonce replay, Landlock unavailable) |\n| `Critical` | Process timeout kills |\n\n### Example: adding a new network event\n\n```rust\nuse openshell_ocsf::{\n    ocsf_emit, NetworkActivityBuilder, ActivityId, ActionId,\n    DispositionId, Endpoint, Process, SeverityId, StatusId,\n};\n\nlet event = NetworkActivityBuilder::new(crate::ocsf_ctx())\n    .activity(ActivityId::Open)\n    .action(ActionId::Denied)\n    .disposition(DispositionId::Blocked)\n    .severity(SeverityId::Medium)\n    .status(StatusId::Failure)\n    .dst_endpoint(Endpoint::from_domain(&host, port))\n    .actor_process(Process::new(&binary, pid))\n    .firewall_rule(&policy_name, &engine_type)\n    .message(format!(\"CONNECT denied {host}:{port}\"))\n    .build();\nocsf_emit!(event);\n```\n\n### Key points\n\n- `crate::ocsf_ctx()` returns the process-wide `SandboxContext`. It is always available (falls back to defaults in tests).\n- `ocsf_emit!()` is non-blocking and cannot panic. It stores the event in a thread-local and emits via `tracing::info!()`.\n- The shorthand layer and JSONL layer extract the event from the thread-local. The shorthand format is derived automatically from the builder fields.\n- For security findings, **dual-emit**: one domain event (e.g., `SshActivityBuilder`) AND one `DetectionFindingBuilder` for the same incident.\n- Never log secrets, credentials, or query parameters in OCSF messages. The OCSF JSONL file may be shipped to external systems.\n- The `message` field should be a concise, grep-friendly summary. Details go in builder fields (dst_endpoint, firewall_rule, etc.).\n\n## Sandbox Infra Changes\n\n- If you change sandbox infrastructure, ensure the relevant sandbox e2e path succeeds.\n\n## Network Sockets\n\n- On latency-sensitive TCP streams, disable Nagle's algorithm so small\n  request/response frames don't stall on delayed ACKs. Use\n  `openshell_core::net::set_tcp_nodelay_best_effort` on an accepted or\n  already-connected stream, or `openshell_core::net::connect_tcp_nodelay_best_effort`\n  when dialing.\n- This applies to loopback/localhost TCP too — the delayed-ACK stall is a timer\n  behavior, not wire latency.\n- You should skip it for unix domain sockets (no Nagle). It's not critical for\n  test-only connections, though using it on any non-UDS TCP stream — tests\n  included — is fine and preferred.\n\n## Commits\n\n- Always use [Conventional Commits](https://www.conventionalcommits.org/) format for commit messages\n- Format: `<type>(<scope>): <description>` (scope is optional)\n- Common types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `ci`, `perf`\n- Sign off on each commit for DCO compliance. Use the `--signoff` option to `git commit` to add the `Signed-off-by` footer to ensure the user's configured email address is used.\n- Never mention Claude or any AI agent in commits (no author attribution, no Co-Authored-By, no references in commit messages)\n\n## Pre-commit\n\n- Run `mise run pre-commit` before committing.\n- Install the git hook when working locally: `mise generate git-pre-commit --write --task=pre-commit`\n\n## Testing\n\n- `mise run pre-commit` — Lint, format, license headers. Run before every commit.\n- `mise run test` — Unit test suite. Run after code changes.\n- `mise run e2e` — End-to-end tests against a running gateway. Run for infrastructure, sandbox, or policy changes.\n- `mise run ci` — Full local CI (lint + compile/type checks + tests). Run before opening a PR.\n\n## Go SDK (`sdk/go/`)\n\n- The Go SDK lives in `sdk/go/` with module path `github.com/NVIDIA/OpenShell/sdk/go`.\n- Run `mise run go:ci` for the full SDK CI pipeline (lint, build, test, proto-check, docs-check).\n- Proto bindings are generated with `mise run go:proto:gen` from the `.proto` files in `proto/`.\n- Domain types in `sdk/go/openshell/v1/types/` must not import proto packages.\n- Converters in `sdk/go/openshell/v1/internal/converter/` deep-copy slices and maps at boundaries.\n- Tests use bufconn for in-process gRPC and testify for assertions.\n\n## TypeScript SDK (`sdk/typescript/`)\n\n- Run `mise run sdk:ts:ci` for codegen, proto lint, Biome lint, type checking, unit tests, coverage, and build validation.\n- Proto bindings are generated with `mise run sdk:ts:proto` from the files selected in `sdk/typescript/buf.gen.yaml`.\n- Generated files under `sdk/typescript/src/gen/` are build outputs and must not be committed.\n- Keep the curated API free of generated wire types; expose full generated messages and RPCs through `@nvidia/openshell-sdk/raw`.\n- The release workflow publishes the package to GitHub Packages. Branch checks exercise the publish path with `npm publish --dry-run`.\n\n## Python\n\n- Always use `uv` for Python commands (e.g., `uv pip install`, `uv run`, `uv venv`)\n\n## Docker\n\n- Always prefer `mise` commands over direct docker builds (e.g., `mise run docker:build` instead of `docker build`)\n\n## Cluster Infrastructure Changes\n\n- If you change gateway deployment infrastructure (e.g., Helm values/templates, gateway image packaging, or deploy logic in `openshell-cli`), update the `debug-openshell-cluster` skill in `.agents/skills/debug-openshell-cluster/SKILL.md` to reflect those changes.\n\n## Skill Maintenance\n\nWhen behavior, commands, or development workflows change, review the related agent skills in the same branch. Use the `sync-agent-infra` skill for the maintenance map and consistency checks.\n\n## Documentation\n\n- When making changes, update the relevant documentation in the `architecture/` directory.\n- When changes affect user-facing behavior, update the relevant published docs pages under `docs/` and navigation in `docs/index.yml`.\n- When changing gateway TOML fields, driver-specific config options, config defaults, or Helm rendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the same branch.\n- `fern/` contains the Fern site config, components, preview workflow inputs, and publish settings.\n- Follow the docs style guide in [docs/CONTRIBUTING.mdx](docs/CONTRIBUTING.mdx): active voice, minimal formatting, no filler introductions, `shell` fences for copyable commands, and no duplicate body H1.\n- Fern PR previews run through `.github/workflows/branch-docs.yml`, and production publish runs through the `publish-fern-docs` job in `.github/workflows/release-tag.yml`.\n- Use the `update-docs` skill to scan recent commits and draft doc updates.\n\n### Architecture Docs\n\n- Architecture docs are short canonical subsystem overviews, not exhaustive implementation notes.\n- Update one of the existing top-level architecture docs before adding a new file.\n- Put useful crate-specific details in the relevant crate `README.md`.\n- Add a new top-level architecture doc only when explicitly requested or when an RFC-level design needs a stable home.\n- Keep architecture docs focused on stable boundaries, data/control flow, invariants, and operational constraints.\n- Remove stale detail instead of preserving it by default.\n- Do not include testing transcripts, historical debugging notes, long source-file inventories, or field-by-field schema references.\n- Put user-facing instructions in `docs/`, broad design proposals in `rfc/`, and temporary plans in ignored `architecture/plans/`.\n\n## Security\n\n- Never commit secrets, API keys, or credentials. If a file looks like it contains secrets (`.env`, `credentials.json`, etc.), do not stage it.\n- Do not run destructive operations (force push, hard reset, database drops) without explicit human confirmation.\n- Scope changes to the issue at hand. Do not make unrelated changes in the same branch.\n","crates/openshell-supervisor-process/src/skills/policy-advisor/SKILL.md":"---\nname: openshell-policy-advisor\ndescription: Use when an OpenShell sandbox returns policy_denied, mentions policy.local, or needs a narrow network policy proposal.\n---\n\n# OpenShell Policy Advisor\n\nWhen a request fails with `policy_denied`, do not treat the denial as final if the user task still needs the request. Read `/etc/openshell/skills/policy_advisor.md`, inspect `http://policy.local/v1/policy/current`, submit the narrowest proposal to `http://policy.local/v1/proposals`, wait on `/v1/proposals/{chunk_id}/wait?timeout=300`, and retry only after approval with `policy_reloaded: true`.\n",".agents/skills/watch-github-actions/SKILL.md":"---\nname: watch-github-actions\ndescription: Watch and monitor GitHub Actions workflow runs using the gh CLI. Use when the user wants to check workflow status, watch a running workflow, view CI/CD jobs, or monitor build progress. Trigger keywords - watch pipeline, pipeline status, CI status, check build, monitor CI, view pipeline, pipeline progress, workflow status, actions status.\n---\n\n# Watch GitHub Actions\n\nMonitor GitHub Actions workflow runs using the `gh` CLI.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Quick Status Check\n\nList recent workflow runs for the current branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nList all recent runs:\n\n```bash\ngh run list\n```\n\n## Watch a Run in Real Time\n\nWatch a workflow run until it completes:\n\n```bash\ngh run watch\n```\n\nWatch a specific run:\n\n```bash\ngh run watch <run-id>\n```\n\nThis will continuously update the status until the run finishes (success, failure, or cancelled).\n\n## View Run Details\n\nView a specific run with job details:\n\n```bash\ngh run view <run-id>\n```\n\nView with full log output:\n\n```bash\ngh run view <run-id> --log\n```\n\nView a failed job's log:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Check Runs for a Specific Branch\n\nCurrent branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nSpecific branch:\n\n```bash\ngh run list --branch main\ngh run list --branch feature-branch\n```\n\n## Check Runs for a PR\n\nList workflow runs associated with a PR:\n\n```bash\n# Get the head branch of the PR, then list runs\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\"\n```\n\nOr view the checks directly on the PR:\n\n```bash\ngh pr checks <pr-number>\n```\n\n## List Recent Runs\n\nList runs for the current project:\n\n```bash\ngh run list\n```\n\nFilter by status:\n\n```bash\ngh run list --status failure\ngh run list --status success\ngh run list --status in_progress\n```\n\nFilter by workflow:\n\n```bash\ngh run list --workflow \"CI\"\n```\n\nJSON output for scripting:\n\n```bash\ngh run list --json databaseId,status,headBranch,url --jq '.[] | {id: .databaseId, status: .status, branch: .headBranch, url: .url}'\n```\n\n## View Job Logs\n\nView logs for a specific run:\n\n```bash\ngh run view <run-id> --log\n```\n\nView only failed job logs:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Wait for Run Completion (Scripting)\n\nWatch and wait for a run to complete:\n\n```bash\nRUN_ID=$(gh run list --branch \"$(git branch --show-current)\" --limit 1 --json databaseId --jq '.[0].databaseId')\ngh run watch \"$RUN_ID\" --exit-status\necho \"Run finished with exit code: $?\"\n```\n\n## Open Run in Browser\n\nOpen the latest run in your default browser:\n\n```bash\ngh run view --web\n```\n\nOpen a specific run:\n\n```bash\ngh run view <run-id> --web\n```\n\n## Rerun Failed Jobs\n\nRerun all failed jobs in a run:\n\n```bash\ngh run rerun <run-id> --failed\n```\n\nRerun an entire run:\n\n```bash\ngh run rerun <run-id>\n```\n\n## Useful Commands Reference\n\n| Command                             | Description                             |\n| ----------------------------------- | --------------------------------------- |\n| `gh run list`                       | List recent workflow runs               |\n| `gh run list --branch <branch>`     | List runs for a specific branch         |\n| `gh run list --status failure`      | List failed runs                        |\n| `gh run watch`                      | Watch latest run until completion       |\n| `gh run watch <run-id>`             | Watch a specific run until completion   |\n| `gh run view <run-id>`              | View run details and job list           |\n| `gh run view <run-id> --log`        | View full run logs                      |\n| `gh run view <run-id> --log-failed` | View only failed job logs               |\n| `gh run view --web`                 | Open run in browser                     |\n| `gh run rerun <run-id>`             | Rerun a workflow run                    |\n| `gh run rerun <run-id> --failed`    | Rerun only failed jobs                  |\n| `gh run cancel <run-id>`            | Cancel a running workflow               |\n| `gh pr checks <pr-number>`          | View PR check statuses                  |\n\n## Common Flags\n\n| Flag               | Description                                    |\n| ------------------- | ---------------------------------------------- |\n| `-b, --branch`     | Specify branch (default: current branch)       |\n| `--status`         | Filter by status (queued, in_progress, etc.)   |\n| `--workflow`       | Filter by workflow name                        |\n| `-L, --limit`      | Maximum number of runs to list                 |\n| `-w, --web`        | Open in browser                                |\n| `--json`           | Output as JSON with specified fields           |\n| `--jq`             | Filter JSON output with jq expression          |\n\n## Example Workflow\n\n1. Push your changes and create/update a PR\n2. Watch the workflow run:\n   ```bash\n   gh run watch\n   ```\n3. If a job fails, view the failed logs:\n   ```bash\n   gh run view <run-id> --log-failed\n   ```\n4. Rerun the failed jobs if needed:\n   ```bash\n   gh run rerun <run-id> --failed\n   ```\n",".agents/skills/update-docs/SKILL.md":"---\nname: update-docs-from-commits\ndescription: Scan recent git commits for changes that affect user-facing behavior, then draft or update the corresponding documentation pages. Use when docs have fallen behind code changes, after a batch of features lands, or when preparing a release. Trigger keywords - update docs, draft docs, docs from commits, sync docs, catch up docs, doc debt, docs behind, docs drift.\n---\n\n# Update Docs from Commits\n\nScan recent git history for commits that affect user-facing behavior and draft documentation updates for each.\n\n## Prerequisites\n\n- You must be in the OpenShell git repository.\n- The published docs tree must exist under `docs/`.\n- Read `docs/CONTRIBUTING.mdx` before writing any content. It contains the current style guide and formatting rules.\n\n## When to Use\n\n- After a batch of features or fixes has landed and docs may be stale.\n- Before a release, to catch any doc gaps.\n- When a contributor asks \"what docs need updating?\"\n\n## Step 1: Identify Relevant Commits\n\nDetermine the commit range. The user may provide one explicitly (e.g., \"since v0.2.0\" or \"last 30 commits\"). If not, default to commits since the head of the main branch.\n\n```bash\n# Commits since a tag\ngit log v0.2.0..HEAD --oneline --no-merges\n\n# Or last 50 commits\ngit log -50 --oneline --no-merges\n```\n\nFilter to commits that are likely to affect docs. Look for these signals:\n\n1. **Commit type**: `feat`, `fix`, `refactor`, `perf` commits often change behavior. `docs` commits are already doc changes. `chore`, `ci`, `test` commits rarely need doc updates.\n2. **Files changed**: Changes to `crates/openshell-cli/`, `python/`, `proto/`, `deploy/`, gateway config parsing, driver config structs, or policy-related code are high-signal.\n3. **Ignore**: Changes limited to `tests/`, `e2e/`, `.github/`, `tasks/`, or internal-only modules.\n\n```bash\n# Show files changed per commit to assess impact\ngit log v0.2.0..HEAD --oneline --no-merges --name-only\n```\n\n## Step 2: Map Commits to Doc Pages\n\nFor each relevant commit, determine which doc page(s) it affects. Use this mapping as a starting point:\n\n| Code area | Likely doc page(s) |\n|---|---|\n| `crates/openshell-cli/` (gateway commands) | `docs/sandboxes/manage-gateways.mdx` |\n| `crates/openshell-cli/` (sandbox commands) | `docs/sandboxes/manage-sandboxes.mdx` |\n| `crates/openshell-cli/` (provider commands) | `docs/sandboxes/manage-providers.mdx` |\n| `crates/openshell-cli/` (new top-level command) | May need a new page or `docs/reference/` entry |\n| `crates/openshell-server/src/config_file.rs` or gateway TOML parsing | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-server/src/cli.rs` gateway config merge/default behavior | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-driver-*/` config structs or driver defaults | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx` |\n| `deploy/helm/openshell/templates/gateway-config.yaml` | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx`, Helm docs if values change |\n| Proxy or policy code | `docs/sandboxes/policies.mdx`, `docs/reference/policy-schema.mdx` |\n| Inference code | `docs/inference/configure.mdx` |\n| `python/` (SDK changes) | `docs/reference/` or `docs/get-started/quickstart.mdx` |\n| `proto/` (API changes) | `docs/reference/` |\n| `deploy/` (Dockerfile, Helm) | `docs/sandboxes/manage-gateways.mdx`, `docs/about/architecture.mdx` |\n| Community sandbox definitions | `docs/sandboxes/community-sandboxes.mdx` |\n\nIf a commit does not map to any existing page but introduces a user-visible concept, flag it as needing a new page.\n\n## Step 3: Read the Commit Details\n\nFor each commit that needs a doc update, read the full diff to understand the change:\n\n```bash\ngit show <commit-hash> --stat\ngit show <commit-hash>\n```\n\nExtract:\n\n- What changed (new flag, renamed command, changed default, new feature).\n- Why it changed (from the commit message body, linked issue, or PR description).\n- Any breaking changes or migration steps.\n\n## Step 4: Read the Current Doc Page\n\nBefore editing, read the full target doc page to understand its current content and structure:\n\n```bash\n# Read the file\n```\n\nIdentify where the new content should go. Follow the page's existing structure.\n\n## Step 5: Draft the Update\n\nWrite the doc update following the rules in `docs/CONTRIBUTING.mdx`. Key reminders:\n\n- **Active voice, present tense, second person.**\n- **No unnecessary bold.** Reserve bold for UI labels and parameter names.\n- **No em dashes** unless used sparingly. Prefer commas or separate sentences.\n- **Start sections with an introductory sentence** that orients the reader.\n- **No superlatives.** Say what the feature does, not how great it is.\n- **Code examples use `shell` language** for copyable commands, with no `$` prompt prefix.\n- **Use `text` fences** for transcripts, logs, or shell sessions that should not be copied verbatim.\n- **Include the SPDX header as YAML comments in frontmatter** if creating a new page.\n- **Match existing Fern frontmatter format** if creating a new page, including `sidebar-title`, `keywords`, and `position` when they are relevant. Use frontmatter `slug` only for folder-discovered pages or absolute URL overrides.\n- **Use `sidebar-title` for short nav labels**. For explicit navigation entries, keep relative `slug` values in `docs/index.yml` instead of page frontmatter.\n- **Keep explicit `page:` entries in `docs/index.yml`**. Fern still requires them. If the page defines `sidebar-title`, set `page:` to that value. Otherwise set `page:` to the page frontmatter `title`.\n- **Use `skip-slug: true` in `docs/index.yml`** when a child page should live at the parent section path.\n- **Use `keywords` as a comma-separated string**.\n- **Do not add a duplicate H1**. Fern renders the page title from frontmatter.\n- **Always write NVIDIA in all caps.** Wrong: Nvidia, nvidia.\n- **Always capitalize OpenShell correctly.** Wrong: openshell, Openshell, openShell.\n- **Do not number section titles.** Wrong: \"Section 1: Deploy a Gateway\" or \"Step 3: Verify.\" Use plain descriptive titles.\n- **No colons in titles.** Wrong: \"Gateways: Deploy and Manage.\" Write \"Deploy and Manage Gateways\" instead.\n- **Use colons only to introduce a list.** Do not use colons as general-purpose punctuation between clauses.\n\nWhen updating an existing page:\n\n- Add content in the logical place within the existing structure.\n- Do not reorganize sections unless the change requires it.\n- Update any cross-references or \"Next Steps\" links if relevant.\n\nWhen creating a new page:\n\n- Follow the frontmatter template from `docs/CONTRIBUTING.mdx`.\n- Add the page to the appropriate section in `docs/index.yml`.\n\n## Step 6: Present the Results\n\nAfter drafting all updates, present a summary to the user:\n\n```\n## Doc Updates from Commits\n\n### Updated pages\n- `docs/sandboxes/manage-gateways.mdx`: Added `--gpu` flag documentation (from commit abc1234).\n- `docs/reference/policy-schema.mdx`: Updated network policy schema for new `tls_inspect` field (from commit def5678).\n\n### New pages needed\n- None (or list any new pages created).\n\n### Commits with no doc impact\n- `chore(deps): bump tokio` (abc1234) — internal dependency, no user-facing change.\n- `test(e2e): add gateway timeout test` (def5678) — test-only change.\n```\n\n## Step 7: Build and Verify\n\nAfter making changes, validate the Fern docs locally:\n\n```bash\nmise run docs\n```\n\nIf a human needs to inspect rendering while iterating, they can also run:\n\n```bash\nmise run docs:serve\n```\n\nCheck for:\n\n- Validation warnings or errors.\n- Broken cross-references.\n- Correct rendering of new content in the PR preview when available.\n\n## Tips\n\n- When in doubt about whether a commit needs a doc update, check if the commit message references a CLI flag, config option, or user-visible behavior.\n- Group related commits that touch the same doc page into a single update rather than making multiple small edits.\n- If a commit is a breaking change, add a note at the top of the relevant section using a Fern `<Warning>` callout.\n- PRs that are purely internal refactors with no behavior change do not need doc updates, even if they touch high-signal directories.\n\n## Example Usage\n\nUser says: \"Catch up the docs for everything merged since v0.2.0.\"\n\n1. Run `git log v0.2.0..HEAD --oneline --no-merges --name-only`.\n2. Filter to `feat`, `fix`, `refactor`, `perf` commits touching user-facing code.\n3. Map each to a doc page.\n4. Read the commit diffs and current doc pages.\n5. Draft updates following the style guide.\n6. Present the summary.\n7. Run `mise run docs` to verify.\n",".agents/skills/build-from-issue/SKILL.md":"---\nname: build-from-issue\ndescription: Given a GitHub issue number, plan and implement the work described in the issue. Supports direct user requests and unattended queue processing through the `agent:*` workflow labels. Includes tests, documentation updates, and PR creation. Trigger keywords - build from issue, implement issue, work on issue, build issue, start issue.\n---\n\n# Build From Issue\n\nPlan, iterate on feedback, and implement work described in a GitHub issue.\n\nThis skill operates as a stateful workflow — it can be run repeatedly against the same issue. Each invocation inspects the issue's labels, plan comment, and conversation history to determine the correct next action.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Invocation and Authorization\n\nThis skill supports two invocation modes:\n\n- **Direct mode:** A user explicitly asks the agent to plan or implement a specific issue. The request itself authorizes the requested phase; the corresponding `agent:*` request label is not required.\n- **Queue mode:** An always-on or unattended agent scans for work without a live user directing it to a specific issue. In this mode, `agent:plan-requested` authorizes planning and `agent:implementation-requested` authorizes implementation.\n\nA direct request authorizes only what it says. A request to review or plan does not authorize implementation. A request to build, implement, or work on an issue authorizes both the planning needed to perform the work and implementation unless the user asks to stop after planning.\n\nThe two request labels remain human-only queue controls. Under **no circumstances** should this skill or any agent apply them, ask to apply them, or suggest automating their application.\n\nDo not refuse a direct user request merely because its request label is absent. If direct work begins on an issue that was not already in the label-driven workflow, do not introduce `agent:in-progress` or `agent:pr-opened` solely for that invocation. If a matching request label is present, preserve the existing label transitions so unattended agents can track the workflow.\n\n## Agent Comment Markers\n\nThis skill uses two distinct markers to identify its comments:\n\n### Plan marker\n\nThe implementation plan lives in a **single comment** that is edited in place as the plan evolves. It is identified by this marker on its first line:\n\n```\n> **🏗️ build-plan**\n```\n\n### Conversation marker\n\nAll other comments (responses to human feedback, status updates, PR announcements) use this marker:\n\n```\n> **🏗️ build-from-issue-agent**\n```\n\nThese markers distinguish agent comments from human comments and from other skills (e.g., `🔒 security-review-agent`, `🔧 security-fix-agent`).\n\n## State Machine Overview\n\nEach invocation follows this decision tree:\n\n```\nFetch issue + comments\n  │\n  ├─ topic:security present?\n  │   → Route to review-security-issue or fix-security-issue; STOP\n  │\n  ├─ Triage incomplete, awaiting information, or awaiting human disposition?\n  │   → Report the blocking state and STOP\n  │\n  ├─ state:accepted and roadmap association both absent?\n  │   → Human has not accepted the issue; STOP\n  │\n  ├─ No plan comment and no direct planning request and agent:plan-requested absent?\n  │   → No request for agent planning; STOP\n  │\n  ├─ No plan comment + direct planning request or agent:plan-requested present?\n  │   → Generate plan via principal-engineer-reviewer\n  │   → Post plan comment\n  │   → Advance labels only for a label-driven invocation\n  │   → Continue if the direct request also authorized implementation; otherwise STOP\n  │\n  ├─ Plan exists + new human comments since last agent response?\n  │   → Respond to each comment (quote context, address feedback)\n  │   → Update the plan comment if feedback requires plan changes\n  │   → STOP\n  │\n  ├─ Plan exists + direct implementation request or 'agent:implementation-requested' label?\n  │   → Run scope check (warn if high complexity)\n  │   → Check for conflicting branches/PRs\n  │   → BUILD (Steps 6–14)\n  │\n  ├─ 'agent:in-progress' label present?\n  │   → Detect existing branch and resume if possible\n  │   → Otherwise report current state\n  │\n  ├─ 'agent:pr-opened' label present?\n  │   → Report that PR already exists, link to it\n  │   → STOP\n  │\n  └─ Plan exists + no new comments + neither a direct implementation request nor 'agent:implementation-requested'?\n      → Report: \"Plan is posted and awaiting review. No new comments to address.\"\n      → STOP\n```\n\n## Step 1: Fetch the Issue\n\nThe user provides an issue ID (e.g., `#42` or `42`). Strip any leading `#` and fetch:\n\n```bash\ngh issue view <id> --json number,title,body,state,labels,author\n```\n\nIf the issue is closed, report that and stop.\n\nIf `topic:security` is present, stop. General build agents must not plan or implement security issues. Route planning/review to `review-security-issue` and authorized remediation to `fix-security-issue`.\n\nStop before planning in any of these states:\n\n- `state:triage-needed`: the issue has not been assessed; use `triage-issue`.\n- `state:needs-info`: triage is waiting for evidence from the reporter.\n- `state:validated` without roadmap placement: triage is complete, but a human has not yet decided whether OpenShell should invest in the work.\n\nNext, require a human acceptance signal: either `state:accepted` or placement on the roadmap. The label records acceptance without requiring scheduling; roadmap placement records acceptance and sequencing. If no plan exists, require either a direct user request for planning or the human-applied `agent:plan-requested` label before generating one. Never add or remove `state:accepted`, either human request label, or the `roadmap` label.\n\n## Step 2: Fetch and Classify Comments\n\nFetch all comments:\n\n```bash\ngh issue view <id> --json comments --jq '.comments[] | {id: .id, body: .body, author: .author.login, createdAt: .createdAt, updatedAt: .updatedAt}'\n```\n\nClassify each comment into one of:\n\n- **Plan comment**: body starts with `> **🏗️ build-plan**`\n- **Agent comment**: body starts with `> **🏗️ build-from-issue-agent**`\n- **Human comment**: everything else (not agent-marked)\n\nRecord the plan comment's `id` (needed for editing via API) and its `updatedAt` timestamp.\n\n## Step 3: Determine Action\n\nUsing the state machine above, determine what to do based on:\n\n1. Whether a plan comment exists\n2. Whether there are human comments newer than the last agent comment (plan or conversation)\n3. Whether this is direct mode and which phase the user requested\n4. Which disposition, roadmap, and agent-workflow labels are present (`state:accepted`, `agent:plan-requested`, `agent:plan-ready`, `agent:implementation-requested`, `agent:in-progress`, `agent:pr-opened`, and the `roadmap` label)\n\nFollow the appropriate branch below.\n\n---\n\n## Branch A: Generate the Plan\n\nIf no plan comment exists, generate one when the user directly requested planning or implementation, or when `agent:plan-requested` is present. Otherwise report that no one has requested agent planning and stop.\n\n### A1: Analyze the Issue with Principal Engineer Reviewer\n\nPass the issue title, description, labels, and any relevant code references to the `principal-engineer-reviewer` sub-agent. Use the Task tool:\n\n```\nTask tool with subagent_type=\"principal-engineer-reviewer\"\n```\n\nIn the prompt, instruct the reviewer to:\n\n1. Read the issue's user story and identify what needs to change in the codebase. Treat reporter diagnostics or solution ideas as optional context, not as authoritative or current analysis.\n2. Map the requirements to existing code — read the relevant source files.\n3. Determine the **issue type** — one of: `feat` (new feature), `fix` (bug fix), `refactor`, `chore`, `perf`, `docs`.\n4. Propose the minimal set of changes that satisfies the requirements.\n5. Sequence the work so each step is independently testable.\n6. Identify what tests are needed (unit, integration, e2e) and where they should live.\n7. Assess **complexity** on a scale:\n   - **Low**: Isolated change, < 3 files, clear path forward\n   - **Medium**: Multiple files/components, some design decisions, but well-scoped\n   - **High**: Cross-cutting changes, architectural decisions needed, significant unknowns\n8. Call out risks, unknowns, and decisions that need stakeholder input.\n9. Assess **gateway config documentation impact** — if the change adds, removes, renames, or changes defaults for gateway TOML keys or driver-specific config options, the plan must include an update to `docs/reference/gateway-config.mdx`. If the change is surfaced through Helm or a compute-driver overview, also include `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment docs.\n10. Assess **LSM compatibility** — if the change touches process identity, `/proc` filesystem access, binary execution, or inter-process visibility, flag whether it will behave differently on hosts running SELinux (enforcing) or AppArmor. In particular, tests that fork+exec into system binaries will fail on SELinux-enforcing hosts due to cross-label `/proc/<pid>/exe` access restrictions.\n\nPerform this investigation against the current branch and current product behavior. If the issue contains earlier diagnostics, verify them rather than relying on them.\n\n### A2: Post the Plan Comment\n\nPost the plan as a comment on the issue. This is the **canonical plan comment** that will be edited in place as the plan evolves.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n**Issue type:** `<feat|fix|refactor|chore|perf|docs>`\n**Complexity:** <Low|Medium|High>\n**Confidence:** <High — clear path | Medium — some unknowns | Low — needs discussion>\n\n### Summary\n<2-3 sentences describing what will be built/changed and the approach>\n\n### Scope\n- `<file1>`: <what changes and why>\n- `<file2>`: <what changes and why>\n- ...\n\n### Implementation Steps\n1. <step 1 — independently testable>\n2. <step 2>\n3. ...\n\n### Test Plan\n- **Unit tests:** <what will be tested and where the tests live>\n- **Integration tests:** <what will be tested, or \"N/A\" with rationale>\n- **E2E tests:** <what will be tested, or \"N/A\" with rationale>\n\n### Risks & Open Questions\n- <risk or unknown that may need human input>\n\n### Documentation Impact\n- <docs expected per AGENTS.md, or \"None expected\">\n\n---\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\n### A3: Mark the Plan Ready in Queue Mode\n\nIf `agent:plan-requested` was present, replace it with `agent:plan-ready`. Do not add `agent:plan-ready` for a direct invocation that was not already using the label workflow.\n\n```bash\ngh issue edit <id> --remove-label \"agent:plan-requested\" --add-label \"agent:plan-ready\"\n```\n\nIf the direct request authorized implementation, continue to Branch C. Otherwise report that the plan has been posted and stop. In queue mode, a human reviews the plan and applies `agent:implementation-requested` before an unattended agent can build.\n\n---\n\n## Branch B: Respond to Feedback\n\nIf a plan exists and there are human comments newer than the last agent response, address them.\n\n### B1: Process Each Unanswered Human Comment\n\nFor each human comment that is newer than the most recent agent comment (plan `updatedAt` or conversation comment `createdAt`):\n\n1. Read the comment.\n2. Quote the relevant portion using `>` blockquote syntax.\n3. Formulate a response based on the codebase and the current plan.\n4. Post a response with the conversation marker.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n> <quoted portion of human's comment>\n\n<response addressing the feedback>\nEOF\n)\"\n```\n\n### B2: Update the Plan if Needed\n\nIf any feedback requires changes to the plan, **edit the existing plan comment** rather than posting a new one. Use the GitHub API with the comment's node ID:\n\n```bash\ngh api graphql -f query='\n  mutation {\n    updateIssueComment(input: {id: \"<comment-node-id>\", body: \"<updated body>\"}) {\n      issueComment { id }\n    }\n  }\n'\n```\n\nOr use the REST API:\n\n```bash\ngh api repos/{owner}/{repo}/issues/comments/<comment-id> -X PATCH -f body=\"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n<... updated plan content ...>\n\n---\n*Revision <N> — <brief description of what changed>*\n*Revision <N-1> — <previous change>*\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\nPreserve the full revision history at the bottom so readers can track how the plan evolved.\n\nReport to the user what feedback was addressed and whether the plan was updated. Stop.\n\n---\n\n## Branch C: Build\n\nProceed with implementation when the plan exists and either the user directly requested implementation or `agent:implementation-requested` is present. An existing `agent:in-progress` or `agent:pr-opened` label still triggers the resume or existing-PR checks below.\n\n### Step 4: Scope Check\n\nRead the plan comment and check the **Complexity** and **Confidence** fields.\n\n- **If Complexity is High or Confidence is Low**, warn the user:\n\n  > \"This issue is rated High complexity / Low confidence. The plan includes open questions that may need human decisions during implementation. Proceeding, but flagging this for your awareness.\"\n\n  Continue — do not hard-stop. The user directly requested implementation or chose to apply `agent:implementation-requested`.\n\n### Step 5: Conflict Detection\n\nBefore creating a branch, check for conflicts:\n\n#### Check for existing branches\n\n```bash\ngit fetch origin\ngit branch -r | grep -i \"<issue-id>\"\n```\n\nIf a remote branch referencing this issue ID exists, report it and ask the user whether to continue on that branch or abort.\n\n#### Check for existing PRs\n\n```bash\ngh pr list --state open --search \"Closes #<issue-id>\" --json number,title,url\n```\n\nIf an open PR already references this issue, report it and stop. Do not create a competing PR.\n\n### Step 6: Create Branch\n\nDetermine the branch prefix from the issue type in the plan:\n\n| Issue type | Branch prefix |\n| --- | --- |\n| `feat` | `feat/` |\n| `fix` | `fix/` |\n| `refactor` | `refactor/` |\n| `chore` | `chore/` |\n| `perf` | `perf/` |\n| `docs` | `docs/` |\n\nGet the current username and create the branch:\n\n```bash\nUSERNAME=$(gh api user --jq '.login')\ngit checkout main\ngit pull origin main\ngit checkout -b <prefix><issue-id>-<short-description>/$USERNAME\n```\n\n### Step 7: Mark Queue Work In Progress\n\nIf `agent:implementation-requested` is present, replace it and `agent:plan-ready` with `agent:in-progress`. In direct mode without a request label, do not add an agent-workflow label.\n\n```bash\ngh issue edit <id> --remove-label \"agent:implementation-requested\" --remove-label \"agent:plan-ready\" --add-label \"agent:in-progress\"\n```\n\n### Step 8: Implement the Changes\n\nFollow the implementation steps from the plan. Principles:\n\n- **Follow the plan**: The plan was reviewed and approved. Stick to it unless you discover something that requires deviation.\n- **Minimal scope**: Only change what the plan calls for. No unrelated refactors.\n- **If you must deviate**: Note the deviation — it will be included in the PR description.\n\nRead the relevant source files before making changes. Implement step by step per the plan's sequence.\n\n### Step 9: Write Tests\n\nWrite tests as specified in the plan's Test Plan section. Follow the project's existing test conventions.\n\n#### Unit tests\n\n- Place alongside existing tests for the module (e.g., `#[cfg(test)]` blocks in Rust, `test_*.py` for Python)\n- Cover the new/changed behavior, edge cases, and error paths\n- Ensure pre-existing behavior still works\n\n#### Integration tests\n\n- Place in the project's existing integration test directories\n- Cover interactions between the changed components\n- Test realistic scenarios including error conditions\n\n#### E2E tests\n\n- Only if the plan calls for them\n- Cover the full user-facing workflow affected by the change\n\n#### Test naming\n\nUse descriptive names that document intent:\n- `test_pagination_returns_correct_page_count`\n- `test_rejects_negative_offset_parameter`\n- `test_retry_succeeds_after_transient_failure`\n\n### Step 10: Verify — Tests, Lint, Pre-commit (Retry Loop)\n\nVerification has two phases: unit tests + pre-commit, then E2E tests (if applicable). Run with up to **3 attempts per phase**.\n\n#### Phase 1: Unit Tests and Pre-commit\n\nOn each attempt:\n\n```bash\n# Run pre-commit checks (linting, formatting, license headers)\nmise run pre-commit\n```\n\n**If verification fails:**\n\n1. Read the error output carefully.\n2. Fix the issues (test failures, lint errors, formatting).\n3. Decrement the retry counter and try again.\n\n**If all 3 attempts fail**, stop and report to the user:\n- What passed and what failed\n- The specific errors from the last attempt\n- That manual intervention is needed\n\nDo not proceed to Phase 2 or PR creation if Phase 1 is not green.\n\n#### Phase 2: E2E Tests (Conditional)\n\n**Trigger**: Run this phase if any files under `e2e/` were added or modified in this build. Check with:\n\n```bash\ngit diff --name-only main -- e2e/\n```\n\nIf there are no changes under `e2e/`, skip this phase entirely.\n\nIf E2E files were modified, run the relevant E2E lane for the driver touched by the change:\n\n```bash\n# Docker-backed gateway smoke E2E\nmise run e2e:docker\n```\n\nUse `mise run e2e:podman`, `mise run e2e:vm`, or a Helm-backed Kubernetes E2E lane when the change targets those drivers.\n\n**E2E retry loop** (up to 3 attempts):\n\n1. Run the selected E2E lane.\n2. If tests fail:\n   - Read the pytest output carefully — identify which tests failed and why.\n   - Distinguish between **test bugs** (the test itself is wrong) and **implementation bugs** (the code under test is wrong).\n   - Fix the failing code or tests.\n   - Decrement the retry counter and try again.\n3. If tests pass, Phase 2 is green.\n\n**If all 3 E2E attempts fail**, stop and report to the user:\n- Which E2E tests are failing\n- The pytest output from the last attempt\n- Whether the failures appear to be test issues or implementation issues\n- That manual intervention is needed\n\nDo not proceed to PR creation if E2E verification is not green.\n\n### Step 11: Update Documentation\n\nReview the documentation requirements in `AGENTS.md` and update any affected\ndocs as part of the implementation. Keep documentation changes scoped to the\nbehavior or subsystem that changed.\n\nIf the implementation changes gateway TOML parsing, `[openshell.gateway]`\nfields, `[openshell.drivers.<name>]` fields, driver config defaults, or Helm\nrendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the\nsame branch. If the change affects user-facing compute-driver setup, also\nupdate `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment\npage.\n\nUse the `sync-agent-infra` skill's maintenance map to identify related skill updates when the implementation changes behavior, commands, or development workflows. Run its full consistency check when the implementation adds, removes, or renames skills or crates; changes workflow relationships or skill coverage; modifies issue or PR templates; or changes agent cross-references. Fix any drift before committing.\n\n### Step 12: Commit and Push\n\nCommit all changes using conventional commit format. The `<type>` comes from the issue type in the plan:\n\n```bash\ngit add <files>\ngit commit -m \"$(cat <<'EOF'\n<type>(<scope>): <short description>\n\nCloses #<issue-id>\n\n<brief explanation of what was implemented>\nEOF\n)\"\n```\n\nPush:\n\n```bash\ngit push -u origin HEAD\n```\n\n### Step 13: Open PR\n\nCreate the PR:\n\n```bash\ngh pr create \\\n  --title \"<type>(<scope>): <short description>\" \\\n  --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Summary\n<1-3 sentences describing what was built and the approach taken>\n\n## Related Issue\nCloses #<issue-id>\n\n## Changes\n- `<file1>`: <what changed and why>\n- `<file2>`: <what changed and why>\n\n### Deviations from Plan\n<any deviations from the approved plan, or \"None — implemented as planned\">\n\n## Testing\n- [x] `mise run pre-commit` passes\n- [x] Unit tests added/updated\n- [x] E2E tests added/updated (if applicable)\n\n**Tests added:**\n- **Unit:** <test file(s) and what they cover>\n- **Integration:** <test file(s) and what they cover, or \"N/A\">\n- **E2E:** <test file(s) and what they cover, or \"N/A\">\n\n## Checklist\n- [x] Follows Conventional Commits\n- [x] Commits are signed off (DCO)\n\n**Documentation updated:**\n- `<doc path>`: <what was updated, or \"None needed\">\nEOF\n)\"\n```\n\n**Display the PR URL** so it's easily clickable:\n\n```\nCreated PR [#<number>](https://github.com/OWNER/REPO/pull/<number>)\n```\n\n### Step 14: Post-Build Cleanup\n\n#### Post summary comment on the issue\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Implementation Complete\n\nPR: [#<pr-number>](https://github.com/OWNER/REPO/pull/<pr-number>)\n\n### What was built\n<1-2 sentence summary>\n\n### Tests\n- Unit: <count> tests added\n- Integration: <count or N/A>\n- E2E: <count or N/A>\n\n### Docs updated\n- <list of updated docs, or \"None needed\">\n\nThe issue will auto-close when the PR is merged.\nEOF\n)\"\n```\n\n#### Post E2E attestation comment on the PR\n\nIf E2E tests were run in Phase 2 of Step 10, post an attestation comment on the **PR** documenting that local E2E tests passed. This is necessary because E2E tests are not yet running in CI — this comment serves as the verification record for reviewers.\n\nCollect the metadata before posting:\n\n```bash\n# Get the commit SHA that was tested\nCOMMIT_SHA=$(git rev-parse HEAD)\n\n# Get the test output summary (last few lines of pytest output)\n# This was captured during the Phase 2 run — include the pass/fail/skip counts\n```\n\nPost the attestation:\n\n```bash\ngh pr comment <pr-number> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## E2E Test Attestation\n\nLocal E2E tests passed. CI does not currently run E2E tests, so this comment serves as the verification record.\n\n| Field | Value |\n|-------|-------|\n| **Commit** | `<commit-sha>` |\n| **Command** | `<selected e2e command>` |\n| **Gateway mode** | `<docker / podman / vm / helm>` |\n| **Result** | ✅ All passed |\n\n### Test Summary\n\n```\n<paste the pytest summary line, e.g.: \"12 passed, 1 skipped in 45.32s\">\n```\n\n### Tests Executed\n- `<test_file.py>::<test_name>` — PASSED\n- `<test_file.py>::<test_name>` — PASSED\n- ...\nEOF\n)\"\n```\n\nInclude **every test** that ran (not just the new ones) so the reviewer can see full coverage. If any tests were skipped, note them and explain why.\n\n#### Update labels\n\nIf `agent:in-progress` is present, replace it with `agent:pr-opened`. Do not add `agent:pr-opened` for an unlabeled direct invocation:\n\n```bash\ngh issue edit <id> --remove-label \"agent:in-progress\" --add-label \"agent:pr-opened\"\n```\n\n#### Report workflow run URL\n\nGet the workflow run URL from the PR so the user can monitor CI:\n\n```bash\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\" --limit 1 --json databaseId,status,url\n```\n\nReport the workflow run URL and suggest the user can use the `watch-github-actions` skill to monitor it.\n\n---\n\n## Branch D: Resume In-Progress Build\n\nIf the `agent:in-progress` label is present, the skill was previously started but may not have completed.\n\n1. Check for an existing branch matching the issue ID:\n   ```bash\n   git branch -r | grep -i \"<issue-id>\"\n   ```\n2. If found, check it out and inspect the state (are there uncommitted changes? committed but not pushed? pushed but no PR?).\n3. Resume from the appropriate step (9, 10, 12, or 13).\n4. If the state is unrecoverable, report to the user and suggest starting fresh. Queue mode requires a human to reapply `agent:implementation-requested`; a new direct implementation request can resume without it.\n\n---\n\n## Useful Commands Reference\n\n| Command | Description |\n| --- | --- |\n| `gh issue view <id> --json number,title,body,state,labels,author` | Fetch full issue metadata |\n| `gh issue view <id> --json comments` | Fetch all comments on an issue |\n| `gh issue comment <id> --body \"...\"` | Post a comment on an issue |\n| `gh api repos/{owner}/{repo}/issues/comments/<id> -X PATCH -f body=\"...\"` | Edit an existing comment |\n| `gh issue edit <id> --add-label \"...\"` | Add labels |\n| `gh issue edit <id> --remove-label \"...\"` | Remove labels |\n| `gh pr list --state open --search \"...\"` | Search for open PRs |\n| `gh pr create --title \"...\" --body \"...\"` | Create a pull request |\n| `gh api user --jq '.login'` | Get current GitHub username |\n| `mise run pre-commit` | Run pre-commit checks (lint, format, license headers) |\n| `mise run e2e:docker` | Run smoke E2E against a standalone Docker-backed gateway |\n| `mise run e2e:podman` | Run smoke E2E against a Podman-backed gateway |\n| `mise run e2e:vm` | Run smoke E2E against the VM compute driver |\n\n## Example Usage\n\n### First run — no plan exists\n\nUser says: \"Plan issue #42\"\n\n1. Fetch issue #42 — title: \"Add pagination to dataset list endpoint\"\n2. Confirm `state:accepted` with no blocking triage state; the user's direct request authorizes planning even if `agent:plan-requested` is absent\n3. Fetch comments — no `🏗️ build-plan` marker found\n4. Pass issue to `principal-engineer-reviewer` for analysis\n5. Reviewer produces a plan: feat type, Medium complexity, 3 implementation steps, unit + integration tests needed\n6. Post the plan comment with the `🏗️ build-plan` marker\n7. Because this direct invocation was unlabeled, leave the `agent:*` workflow labels unchanged\n8. Report to user: \"Plan posted on issue #42. Awaiting review.\"\n\n### Second run — human left feedback\n\nUser says: \"Check on issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find existing plan comment (Revision 1)\n3. Find new human comment: \"Should we also paginate the search endpoint?\"\n4. Post response quoting the question, explaining that search pagination is out of scope for this issue but could be a follow-up\n5. Report to user: \"Responded to feedback on #42. Plan unchanged.\"\n\n### Third run — human revised scope, plan needs update\n\nUser says: \"Check issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find plan + new human comment: \"Actually, let's include search pagination. Updated the issue description.\"\n3. Post response acknowledging the scope change\n4. Edit the plan comment to include search endpoint pagination — Revision 2\n5. Report to user: \"Updated plan to include search pagination (Revision 2).\"\n\n### Fourth run — implementation requested\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists (Revision 2), complexity: Medium, confidence: High\n3. No conflicting branches or PRs\n4. Create branch `feat/42-add-pagination/jmyers`\n5. Leave `agent:*` labels unchanged because this direct invocation was not picked up from the queue\n6. Implement pagination for both endpoints per the plan\n7. Add unit tests for pagination logic, integration tests for both endpoints\n8. `mise run pre-commit` passes on first attempt\n9. E2E tests skipped (no changes under `e2e/`)\n10. Commit, push, create PR with `Closes #42`\n11. Post summary comment on issue with PR link\n12. No agent-workflow label transition is needed\n13. Report PR URL and workflow run status to user\n\n### Run on issue with existing PR\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `agent:pr-opened` label present\n2. Find existing PR #789 linked to the issue\n3. Report: \"PR [#789](...) already exists for issue #42. Nothing to build.\"\n\n### Run on high-complexity issue\n\nUser says: \"Build issue #99\"\n\n1. Fetch issue #99 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists: complexity High, confidence Low, has open questions\n3. Warn user: \"Issue #99 is rated High complexity / Low confidence. Proceeding but flagging for your awareness.\"\n4. Continue with build\n"},"files":{"AGENTS.md":"# Agent Instructions\n\nThis file is the primary instruction surface for agents contributing to OpenShell. It is injected into your context on every interaction — keep that in mind when proposing changes to it.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for build instructions, task reference, project structure, and the full agent skills table.\n\n## Project Identity\n\nOpenShell is built agent-first. We design systems and use agents to implement them — this is not vibe coding. The product provides safe, sandboxed runtimes for autonomous AI agents, and the project itself is built using the same agent-driven workflows it enables.\n\n## Skills\n\nAgent skills live in `.agents/skills/`. Your harness can discover and load them natively — do not rely on this file for a full inventory. The detailed skills table is in [CONTRIBUTING.md](CONTRIBUTING.md) (for humans).\n\n## Workflow Chains\n\nThese pipelines connect skills into end-to-end workflows. Individual skill files don't describe these relationships.\n\n- **Community inflow:** `triage-issue` → human disposition and roadmap placement → `create-spike` when needed → `build-from-issue`\n  - Triage establishes facts and marks technically valid issues `state:validated`. A human signals that the project should pursue the work by applying `state:accepted` or placing the issue on the roadmap. The `agent:*` labels support unattended agents that scan for queued work: a human queues a plan with `agent:plan-requested`, the agent returns `agent:plan-ready`, and a human queues implementation with `agent:implementation-requested`. A direct user request to an agent authorizes the requested phase without those labels.\n- **Internal development:** `create-spike` → human disposition and roadmap placement → `build-from-issue`\n  - Spike explores feasibility and marks its issue `state:validated` when sufficient evidence exists. A human accepts it with `state:accepted` or roadmap placement, or declines it, and optionally queues it through the `agent:*` workflow or directs an agent to it.\n- **Security:** `review-security-issue` → `fix-security-issue`\n  - General build agents must not process `topic:security` issues. For unattended processing, a human queues specialized review with `agent:plan-requested`; review produces a severity assessment and remediation plan; a human queues remediation with `agent:implementation-requested`. Direct requests to the specialized skills do not require those labels.\n- **Policy iteration:** `openshell-cli` → `generate-sandbox-policy`\n  - CLI manages the sandbox lifecycle; policy generation authors the YAML constraints.\n\n## Architecture Overview\n\n| Path | Components | Purpose |\n|------|-----------|---------|\n| `crates/openshell-cli/` | CLI binary | User-facing command-line interface |\n| `crates/openshell-server/` | Gateway server | Control-plane API, sandbox lifecycle, auth boundary |\n| `crates/openshell-sandbox/` | Sandbox runtime | Container supervision, policy-enforced egress routing |\n| `crates/openshell-policy/` | Policy engine | Filesystem, network, process, and inference constraints |\n| `crates/openshell-router/` | Privacy router | Privacy-aware LLM routing |\n| `crates/openshell-bootstrap/` | Gateway metadata | Gateway registration metadata, auth token storage, mTLS bundle storage |\n| `crates/openshell-gateway-interceptors/` | Gateway interceptors | Intercepts and transforms configured gRPC requests at the gateway routing boundary |\n| `crates/openshell-ocsf/` | OCSF logging | OCSF v1.7.0 event types, builders, shorthand/JSONL formatters, tracing layers |\n| `crates/openshell-otel/` | OpenTelemetry support | Shared OTLP trace provider, resource, and tracing-layer construction |\n| `crates/openshell-core/` | Shared core | Common types, configuration, error handling |\n| `crates/openshell-extension-core/` | Extension core | Shared extension identity, JWT claims, bearer-token rotation, and TLS transport primitives |\n| `crates/openshell-sdk/` | Shared client SDK | Async Rust gateway client (gRPC transport, TLS, OIDC refresh, edge tunnel); consumed by CLI, TUI, and `@openshell/sdk` |\n| `crates/openshell-providers/` | Provider management | Credential provider backends |\n| `crates/openshell-tui/` | Terminal UI | Ratatui-based dashboard for monitoring |\n| `crates/openshell-driver-kubernetes-secrets/` | Kubernetes Secrets credential driver | In-process `CredentialDriver` backend for OpenShell-managed K8s Secret storage |\n| `crates/openshell-driver-vault/` | Vault credential driver | In-process `CredentialDriver` backend for Vault-compatible KV storage |\n| `crates/openshell-driver-db-credstore/` | Database credential driver | In-process `CredentialDriver` backend for gateway database credential storage |\n| `crates/openshell-driver-kubernetes/` | Kubernetes compute driver | In-process `ComputeDriver` backend for K8s sandbox pods |\n| `crates/openshell-driver-docker/` | Docker compute driver | In-process `ComputeDriver` backend for local Docker sandbox containers |\n| `crates/openshell-driver-podman/` | Podman compute driver | In-process `ComputeDriver` backend for local Podman sandbox containers |\n| `crates/openshell-driver-vm/` | VM compute driver | Standalone libkrun-backed `ComputeDriver` subprocess (embeds its own rootfs + runtime) |\n| `crates/openshell-prover/` | Policy prover | Policy verification and proof generation |\n| `crates/openshell-server-macros/` | Server macros | Compile-time helpers for gateway RPC authorization |\n| `crates/openshell-supervisor-middleware/` | Middleware runtime | Generic middleware registry, remote service integration, and chain execution |\n| `crates/openshell-supervisor-middleware-builtins/` | Built-in middleware | First-party in-process middleware implementations |\n| `crates/openshell-supervisor-network/` | Network supervisor | Proxying, L7 enforcement, policy evaluation, and inference routing |\n| `crates/openshell-supervisor-process/` | Process supervisor | Process lifecycle, namespace, and bypass monitoring |\n| `crates/openshell-vfio/` | VFIO support | PCI and GPU passthrough preparation and lifecycle |\n| `python/openshell/` | Python SDK | Python bindings and CLI packaging |\n| `sdk/typescript/` | TypeScript SDK | Native Connect client, curated sandbox API, and generated protobuf types |\n| `proto/` | Protobuf definitions | gRPC service contracts |\n| `deploy/` | Docker, Helm, K8s | Dockerfiles, Helm chart, manifests |\n| `docs/` | Published docs | MDX pages, navigation, and content assets |\n| `fern/` | Docs site config | Fern site config, components, and theme assets |\n| `.agents/skills/` | Agent skills | Workflow automation for development |\n| `.agents/agents/` | Agent personas | Sub-agent definitions (e.g., reviewer, doc writer) |\n| `architecture/` | Architecture docs | Design decisions and component documentation |\n\n## Vouch System\n\n- First-time external contributors must be vouched before their PRs are accepted. The `vouch-check` workflow auto-closes PRs from unvouched users.\n- Org members and collaborators bypass the vouch gate automatically.\n- Maintainers vouch users by commenting `/vouch` on a Vouch Request discussion. The `vouch-command` workflow appends the username to `.github/VOUCHED.td`.\n- Skills that create PRs (`create-github-pr`, `build-from-issue`) should note this requirement when operating on behalf of external contributors.\n\n## Issue and PR Conventions\n\n- **Bug reports and feature requests** must include a User Story, Problem Statement, Impact / Why This Matters, and Acceptance Criteria. The impact should explain the consequences of the current behavior, the current workaround, and why that workaround is insufficient. Bug reports additionally require reproduction steps and environment details and may include concise, redacted logs.\n- **Feature requests** must also include a Proposed Design and Alternatives Considered. The design should define the user-facing workflow and externally observable behavior while leaving internal implementation choices open. Agent investigation is optional.\n- **New features** must start as GitHub issues using the feature request template. Open an RFC only after an issue exists; maintainers decide when one is needed and assign RFC numbers from the issue.\n- **Issue triage** establishes technical validity and impact evidence. Agents never decide acceptance, apply `state:accepted`, place issues on the roadmap, or apply `agent:plan-requested` or `agent:implementation-requested`. Humans accept or decline validated work; `state:accepted` or roadmap placement records acceptance, and roadmap association additionally carries sequencing. The request labels queue work for unattended agents; an explicit user instruction can instead authorize an agent to plan or implement a specific issue. OpenShell has no `priority:*` labels.\n- **PRs** must follow the PR template structure: Summary, Related Issue, Changes, Testing, Checklist. Contributors should use their agent to investigate the current code and behavior for accepted issue-backed work, verify any diagnostics already on the issue, understand the change they submit, and report the resulting implementation and verification—not paste an earlier issue-filing diagnostic.\n- **PRs for features, user-visible behavior, public APIs, architecture, or multi-PR efforts** must link an accepted issue. Small docs fixes, mechanical maintenance, and obvious localized bug fixes may state why no issue is required.\n- **PRs from unvouched external contributors** are automatically closed. See the Vouch System section above.\n- **Security vulnerabilities** must NOT be filed as GitHub issues. Follow [SECURITY.md](SECURITY.md).\n- Skills that create issues or PRs (`create-github-issue`, `create-github-pr`, `build-from-issue`) should produce output conforming to these templates.\n\n## Plans\n\n- Store plan documents in `architecture/plans`. This is git ignored so its for easier access for humans. When asked to create Spikes or issues, you can skip to GitHub issues. Only use the plans dir when you aren't writing data somewhere else specific.\n- When asked to write a plan, write it there without asking for the location.\n\n## Sandbox Logging (OCSF)\n\nWhen adding or modifying log emissions in `openshell-sandbox`, determine whether the event should use OCSF structured logging or plain `tracing`.\n\n### When to use OCSF\n\nUse an OCSF builder + `ocsf_emit!()` for events that represent **observable sandbox behavior** visible to operators, security teams, or agents monitoring the sandbox:\n\n- Network decisions (allow, deny, bypass detection)\n- HTTP/L7 enforcement decisions\n- SSH authentication (accepted, denied, nonce replay)\n- Process lifecycle (start, exit, timeout, signal failure)\n- Security findings (unsafe policy, unavailable controls, replay attacks)\n- Configuration changes (policy load/reload, TLS setup, inference routes, settings)\n- Application lifecycle (supervisor start, SSH server ready)\n\n### When to use plain tracing\n\nUse `info!()`, `debug!()`, `warn!()` for **internal operational plumbing** that doesn't represent a security decision or observable state change:\n\n- gRPC connection attempts and retries\n- \"About to do X\" events where the result is logged separately\n- Internal SSH channel state (unknown channel, PTY resize)\n- Zombie process reaping, denial flush telemetry\n- DEBUG/TRACE level diagnostics\n\n### Choosing the OCSF event class\n\n| Event type | Builder | When to use |\n|---|---|---|\n| TCP connections, proxy tunnels, bypass | `NetworkActivityBuilder` | L4 network decisions, proxy operational events |\n| HTTP requests, L7 enforcement | `HttpActivityBuilder` | Per-request method/path decisions |\n| SSH sessions | `SshActivityBuilder` | Authentication, channel operations |\n| Process start/stop | `ProcessActivityBuilder` | Entrypoint lifecycle, signal failures |\n| Security alerts | `DetectionFindingBuilder` | Nonce replay, bypass detection, unsafe policy. Dual-emit with the domain event. |\n| Policy/config changes | `ConfigStateChangeBuilder` | Policy load, Landlock apply, TLS setup, inference routes, settings |\n| Supervisor lifecycle | `AppLifecycleBuilder` | Sandbox start, SSH server ready/failed |\n\n### Severity guidelines\n\n| Severity | When |\n|---|---|\n| `Informational` | Allowed connections, successful operations, config loaded |\n| `Low` | DNS failures, non-fatal operational warnings, LOG rule failures |\n| `Medium` | Denied connections, policy violations, deprecated config |\n| `High` | Security findings (nonce replay, Landlock unavailable) |\n| `Critical` | Process timeout kills |\n\n### Example: adding a new network event\n\n```rust\nuse openshell_ocsf::{\n    ocsf_emit, NetworkActivityBuilder, ActivityId, ActionId,\n    DispositionId, Endpoint, Process, SeverityId, StatusId,\n};\n\nlet event = NetworkActivityBuilder::new(crate::ocsf_ctx())\n    .activity(ActivityId::Open)\n    .action(ActionId::Denied)\n    .disposition(DispositionId::Blocked)\n    .severity(SeverityId::Medium)\n    .status(StatusId::Failure)\n    .dst_endpoint(Endpoint::from_domain(&host, port))\n    .actor_process(Process::new(&binary, pid))\n    .firewall_rule(&policy_name, &engine_type)\n    .message(format!(\"CONNECT denied {host}:{port}\"))\n    .build();\nocsf_emit!(event);\n```\n\n### Key points\n\n- `crate::ocsf_ctx()` returns the process-wide `SandboxContext`. It is always available (falls back to defaults in tests).\n- `ocsf_emit!()` is non-blocking and cannot panic. It stores the event in a thread-local and emits via `tracing::info!()`.\n- The shorthand layer and JSONL layer extract the event from the thread-local. The shorthand format is derived automatically from the builder fields.\n- For security findings, **dual-emit**: one domain event (e.g., `SshActivityBuilder`) AND one `DetectionFindingBuilder` for the same incident.\n- Never log secrets, credentials, or query parameters in OCSF messages. The OCSF JSONL file may be shipped to external systems.\n- The `message` field should be a concise, grep-friendly summary. Details go in builder fields (dst_endpoint, firewall_rule, etc.).\n\n## Sandbox Infra Changes\n\n- If you change sandbox infrastructure, ensure the relevant sandbox e2e path succeeds.\n\n## Network Sockets\n\n- On latency-sensitive TCP streams, disable Nagle's algorithm so small\n  request/response frames don't stall on delayed ACKs. Use\n  `openshell_core::net::set_tcp_nodelay_best_effort` on an accepted or\n  already-connected stream, or `openshell_core::net::connect_tcp_nodelay_best_effort`\n  when dialing.\n- This applies to loopback/localhost TCP too — the delayed-ACK stall is a timer\n  behavior, not wire latency.\n- You should skip it for unix domain sockets (no Nagle). It's not critical for\n  test-only connections, though using it on any non-UDS TCP stream — tests\n  included — is fine and preferred.\n\n## Commits\n\n- Always use [Conventional Commits](https://www.conventionalcommits.org/) format for commit messages\n- Format: `<type>(<scope>): <description>` (scope is optional)\n- Common types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `ci`, `perf`\n- Sign off on each commit for DCO compliance. Use the `--signoff` option to `git commit` to add the `Signed-off-by` footer to ensure the user's configured email address is used.\n- Never mention Claude or any AI agent in commits (no author attribution, no Co-Authored-By, no references in commit messages)\n\n## Pre-commit\n\n- Run `mise run pre-commit` before committing.\n- Install the git hook when working locally: `mise generate git-pre-commit --write --task=pre-commit`\n\n## Testing\n\n- `mise run pre-commit` — Lint, format, license headers. Run before every commit.\n- `mise run test` — Unit test suite. Run after code changes.\n- `mise run e2e` — End-to-end tests against a running gateway. Run for infrastructure, sandbox, or policy changes.\n- `mise run ci` — Full local CI (lint + compile/type checks + tests). Run before opening a PR.\n\n## Go SDK (`sdk/go/`)\n\n- The Go SDK lives in `sdk/go/` with module path `github.com/NVIDIA/OpenShell/sdk/go`.\n- Run `mise run go:ci` for the full SDK CI pipeline (lint, build, test, proto-check, docs-check).\n- Proto bindings are generated with `mise run go:proto:gen` from the `.proto` files in `proto/`.\n- Domain types in `sdk/go/openshell/v1/types/` must not import proto packages.\n- Converters in `sdk/go/openshell/v1/internal/converter/` deep-copy slices and maps at boundaries.\n- Tests use bufconn for in-process gRPC and testify for assertions.\n\n## TypeScript SDK (`sdk/typescript/`)\n\n- Run `mise run sdk:ts:ci` for codegen, proto lint, Biome lint, type checking, unit tests, coverage, and build validation.\n- Proto bindings are generated with `mise run sdk:ts:proto` from the files selected in `sdk/typescript/buf.gen.yaml`.\n- Generated files under `sdk/typescript/src/gen/` are build outputs and must not be committed.\n- Keep the curated API free of generated wire types; expose full generated messages and RPCs through `@nvidia/openshell-sdk/raw`.\n- The release workflow publishes the package to GitHub Packages. Branch checks exercise the publish path with `npm publish --dry-run`.\n\n## Python\n\n- Always use `uv` for Python commands (e.g., `uv pip install`, `uv run`, `uv venv`)\n\n## Docker\n\n- Always prefer `mise` commands over direct docker builds (e.g., `mise run docker:build` instead of `docker build`)\n\n## Cluster Infrastructure Changes\n\n- If you change gateway deployment infrastructure (e.g., Helm values/templates, gateway image packaging, or deploy logic in `openshell-cli`), update the `debug-openshell-cluster` skill in `.agents/skills/debug-openshell-cluster/SKILL.md` to reflect those changes.\n\n## Skill Maintenance\n\nWhen behavior, commands, or development workflows change, review the related agent skills in the same branch. Use the `sync-agent-infra` skill for the maintenance map and consistency checks.\n\n## Documentation\n\n- When making changes, update the relevant documentation in the `architecture/` directory.\n- When changes affect user-facing behavior, update the relevant published docs pages under `docs/` and navigation in `docs/index.yml`.\n- When changing gateway TOML fields, driver-specific config options, config defaults, or Helm rendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the same branch.\n- `fern/` contains the Fern site config, components, preview workflow inputs, and publish settings.\n- Follow the docs style guide in [docs/CONTRIBUTING.mdx](docs/CONTRIBUTING.mdx): active voice, minimal formatting, no filler introductions, `shell` fences for copyable commands, and no duplicate body H1.\n- Fern PR previews run through `.github/workflows/branch-docs.yml`, and production publish runs through the `publish-fern-docs` job in `.github/workflows/release-tag.yml`.\n- Use the `update-docs` skill to scan recent commits and draft doc updates.\n\n### Architecture Docs\n\n- Architecture docs are short canonical subsystem overviews, not exhaustive implementation notes.\n- Update one of the existing top-level architecture docs before adding a new file.\n- Put useful crate-specific details in the relevant crate `README.md`.\n- Add a new top-level architecture doc only when explicitly requested or when an RFC-level design needs a stable home.\n- Keep architecture docs focused on stable boundaries, data/control flow, invariants, and operational constraints.\n- Remove stale detail instead of preserving it by default.\n- Do not include testing transcripts, historical debugging notes, long source-file inventories, or field-by-field schema references.\n- Put user-facing instructions in `docs/`, broad design proposals in `rfc/`, and temporary plans in ignored `architecture/plans/`.\n\n## Security\n\n- Never commit secrets, API keys, or credentials. If a file looks like it contains secrets (`.env`, `credentials.json`, etc.), do not stage it.\n- Do not run destructive operations (force push, hard reset, database drops) without explicit human confirmation.\n- Scope changes to the issue at hand. Do not make unrelated changes in the same branch.\n","crates/openshell-supervisor-process/src/skills/policy-advisor/SKILL.md":"---\nname: openshell-policy-advisor\ndescription: Use when an OpenShell sandbox returns policy_denied, mentions policy.local, or needs a narrow network policy proposal.\n---\n\n# OpenShell Policy Advisor\n\nWhen a request fails with `policy_denied`, do not treat the denial as final if the user task still needs the request. Read `/etc/openshell/skills/policy_advisor.md`, inspect `http://policy.local/v1/policy/current`, submit the narrowest proposal to `http://policy.local/v1/proposals`, wait on `/v1/proposals/{chunk_id}/wait?timeout=300`, and retry only after approval with `policy_reloaded: true`.\n",".agents/skills/watch-github-actions/SKILL.md":"---\nname: watch-github-actions\ndescription: Watch and monitor GitHub Actions workflow runs using the gh CLI. Use when the user wants to check workflow status, watch a running workflow, view CI/CD jobs, or monitor build progress. Trigger keywords - watch pipeline, pipeline status, CI status, check build, monitor CI, view pipeline, pipeline progress, workflow status, actions status.\n---\n\n# Watch GitHub Actions\n\nMonitor GitHub Actions workflow runs using the `gh` CLI.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Quick Status Check\n\nList recent workflow runs for the current branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nList all recent runs:\n\n```bash\ngh run list\n```\n\n## Watch a Run in Real Time\n\nWatch a workflow run until it completes:\n\n```bash\ngh run watch\n```\n\nWatch a specific run:\n\n```bash\ngh run watch <run-id>\n```\n\nThis will continuously update the status until the run finishes (success, failure, or cancelled).\n\n## View Run Details\n\nView a specific run with job details:\n\n```bash\ngh run view <run-id>\n```\n\nView with full log output:\n\n```bash\ngh run view <run-id> --log\n```\n\nView a failed job's log:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Check Runs for a Specific Branch\n\nCurrent branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nSpecific branch:\n\n```bash\ngh run list --branch main\ngh run list --branch feature-branch\n```\n\n## Check Runs for a PR\n\nList workflow runs associated with a PR:\n\n```bash\n# Get the head branch of the PR, then list runs\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\"\n```\n\nOr view the checks directly on the PR:\n\n```bash\ngh pr checks <pr-number>\n```\n\n## List Recent Runs\n\nList runs for the current project:\n\n```bash\ngh run list\n```\n\nFilter by status:\n\n```bash\ngh run list --status failure\ngh run list --status success\ngh run list --status in_progress\n```\n\nFilter by workflow:\n\n```bash\ngh run list --workflow \"CI\"\n```\n\nJSON output for scripting:\n\n```bash\ngh run list --json databaseId,status,headBranch,url --jq '.[] | {id: .databaseId, status: .status, branch: .headBranch, url: .url}'\n```\n\n## View Job Logs\n\nView logs for a specific run:\n\n```bash\ngh run view <run-id> --log\n```\n\nView only failed job logs:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Wait for Run Completion (Scripting)\n\nWatch and wait for a run to complete:\n\n```bash\nRUN_ID=$(gh run list --branch \"$(git branch --show-current)\" --limit 1 --json databaseId --jq '.[0].databaseId')\ngh run watch \"$RUN_ID\" --exit-status\necho \"Run finished with exit code: $?\"\n```\n\n## Open Run in Browser\n\nOpen the latest run in your default browser:\n\n```bash\ngh run view --web\n```\n\nOpen a specific run:\n\n```bash\ngh run view <run-id> --web\n```\n\n## Rerun Failed Jobs\n\nRerun all failed jobs in a run:\n\n```bash\ngh run rerun <run-id> --failed\n```\n\nRerun an entire run:\n\n```bash\ngh run rerun <run-id>\n```\n\n## Useful Commands Reference\n\n| Command                             | Description                             |\n| ----------------------------------- | --------------------------------------- |\n| `gh run list`                       | List recent workflow runs               |\n| `gh run list --branch <branch>`     | List runs for a specific branch         |\n| `gh run list --status failure`      | List failed runs                        |\n| `gh run watch`                      | Watch latest run until completion       |\n| `gh run watch <run-id>`             | Watch a specific run until completion   |\n| `gh run view <run-id>`              | View run details and job list           |\n| `gh run view <run-id> --log`        | View full run logs                      |\n| `gh run view <run-id> --log-failed` | View only failed job logs               |\n| `gh run view --web`                 | Open run in browser                     |\n| `gh run rerun <run-id>`             | Rerun a workflow run                    |\n| `gh run rerun <run-id> --failed`    | Rerun only failed jobs                  |\n| `gh run cancel <run-id>`            | Cancel a running workflow               |\n| `gh pr checks <pr-number>`          | View PR check statuses                  |\n\n## Common Flags\n\n| Flag               | Description                                    |\n| ------------------- | ---------------------------------------------- |\n| `-b, --branch`     | Specify branch (default: current branch)       |\n| `--status`         | Filter by status (queued, in_progress, etc.)   |\n| `--workflow`       | Filter by workflow name                        |\n| `-L, --limit`      | Maximum number of runs to list                 |\n| `-w, --web`        | Open in browser                                |\n| `--json`           | Output as JSON with specified fields           |\n| `--jq`             | Filter JSON output with jq expression          |\n\n## Example Workflow\n\n1. Push your changes and create/update a PR\n2. Watch the workflow run:\n   ```bash\n   gh run watch\n   ```\n3. If a job fails, view the failed logs:\n   ```bash\n   gh run view <run-id> --log-failed\n   ```\n4. Rerun the failed jobs if needed:\n   ```bash\n   gh run rerun <run-id> --failed\n   ```\n",".agents/skills/update-docs/SKILL.md":"---\nname: update-docs-from-commits\ndescription: Scan recent git commits for changes that affect user-facing behavior, then draft or update the corresponding documentation pages. Use when docs have fallen behind code changes, after a batch of features lands, or when preparing a release. Trigger keywords - update docs, draft docs, docs from commits, sync docs, catch up docs, doc debt, docs behind, docs drift.\n---\n\n# Update Docs from Commits\n\nScan recent git history for commits that affect user-facing behavior and draft documentation updates for each.\n\n## Prerequisites\n\n- You must be in the OpenShell git repository.\n- The published docs tree must exist under `docs/`.\n- Read `docs/CONTRIBUTING.mdx` before writing any content. It contains the current style guide and formatting rules.\n\n## When to Use\n\n- After a batch of features or fixes has landed and docs may be stale.\n- Before a release, to catch any doc gaps.\n- When a contributor asks \"what docs need updating?\"\n\n## Step 1: Identify Relevant Commits\n\nDetermine the commit range. The user may provide one explicitly (e.g., \"since v0.2.0\" or \"last 30 commits\"). If not, default to commits since the head of the main branch.\n\n```bash\n# Commits since a tag\ngit log v0.2.0..HEAD --oneline --no-merges\n\n# Or last 50 commits\ngit log -50 --oneline --no-merges\n```\n\nFilter to commits that are likely to affect docs. Look for these signals:\n\n1. **Commit type**: `feat`, `fix`, `refactor`, `perf` commits often change behavior. `docs` commits are already doc changes. `chore`, `ci`, `test` commits rarely need doc updates.\n2. **Files changed**: Changes to `crates/openshell-cli/`, `python/`, `proto/`, `deploy/`, gateway config parsing, driver config structs, or policy-related code are high-signal.\n3. **Ignore**: Changes limited to `tests/`, `e2e/`, `.github/`, `tasks/`, or internal-only modules.\n\n```bash\n# Show files changed per commit to assess impact\ngit log v0.2.0..HEAD --oneline --no-merges --name-only\n```\n\n## Step 2: Map Commits to Doc Pages\n\nFor each relevant commit, determine which doc page(s) it affects. Use this mapping as a starting point:\n\n| Code area | Likely doc page(s) |\n|---|---|\n| `crates/openshell-cli/` (gateway commands) | `docs/sandboxes/manage-gateways.mdx` |\n| `crates/openshell-cli/` (sandbox commands) | `docs/sandboxes/manage-sandboxes.mdx` |\n| `crates/openshell-cli/` (provider commands) | `docs/sandboxes/manage-providers.mdx` |\n| `crates/openshell-cli/` (new top-level command) | May need a new page or `docs/reference/` entry |\n| `crates/openshell-server/src/config_file.rs` or gateway TOML parsing | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-server/src/cli.rs` gateway config merge/default behavior | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-driver-*/` config structs or driver defaults | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx` |\n| `deploy/helm/openshell/templates/gateway-config.yaml` | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx`, Helm docs if values change |\n| Proxy or policy code | `docs/sandboxes/policies.mdx`, `docs/reference/policy-schema.mdx` |\n| Inference code | `docs/inference/configure.mdx` |\n| `python/` (SDK changes) | `docs/reference/` or `docs/get-started/quickstart.mdx` |\n| `proto/` (API changes) | `docs/reference/` |\n| `deploy/` (Dockerfile, Helm) | `docs/sandboxes/manage-gateways.mdx`, `docs/about/architecture.mdx` |\n| Community sandbox definitions | `docs/sandboxes/community-sandboxes.mdx` |\n\nIf a commit does not map to any existing page but introduces a user-visible concept, flag it as needing a new page.\n\n## Step 3: Read the Commit Details\n\nFor each commit that needs a doc update, read the full diff to understand the change:\n\n```bash\ngit show <commit-hash> --stat\ngit show <commit-hash>\n```\n\nExtract:\n\n- What changed (new flag, renamed command, changed default, new feature).\n- Why it changed (from the commit message body, linked issue, or PR description).\n- Any breaking changes or migration steps.\n\n## Step 4: Read the Current Doc Page\n\nBefore editing, read the full target doc page to understand its current content and structure:\n\n```bash\n# Read the file\n```\n\nIdentify where the new content should go. Follow the page's existing structure.\n\n## Step 5: Draft the Update\n\nWrite the doc update following the rules in `docs/CONTRIBUTING.mdx`. Key reminders:\n\n- **Active voice, present tense, second person.**\n- **No unnecessary bold.** Reserve bold for UI labels and parameter names.\n- **No em dashes** unless used sparingly. Prefer commas or separate sentences.\n- **Start sections with an introductory sentence** that orients the reader.\n- **No superlatives.** Say what the feature does, not how great it is.\n- **Code examples use `shell` language** for copyable commands, with no `$` prompt prefix.\n- **Use `text` fences** for transcripts, logs, or shell sessions that should not be copied verbatim.\n- **Include the SPDX header as YAML comments in frontmatter** if creating a new page.\n- **Match existing Fern frontmatter format** if creating a new page, including `sidebar-title`, `keywords`, and `position` when they are relevant. Use frontmatter `slug` only for folder-discovered pages or absolute URL overrides.\n- **Use `sidebar-title` for short nav labels**. For explicit navigation entries, keep relative `slug` values in `docs/index.yml` instead of page frontmatter.\n- **Keep explicit `page:` entries in `docs/index.yml`**. Fern still requires them. If the page defines `sidebar-title`, set `page:` to that value. Otherwise set `page:` to the page frontmatter `title`.\n- **Use `skip-slug: true` in `docs/index.yml`** when a child page should live at the parent section path.\n- **Use `keywords` as a comma-separated string**.\n- **Do not add a duplicate H1**. Fern renders the page title from frontmatter.\n- **Always write NVIDIA in all caps.** Wrong: Nvidia, nvidia.\n- **Always capitalize OpenShell correctly.** Wrong: openshell, Openshell, openShell.\n- **Do not number section titles.** Wrong: \"Section 1: Deploy a Gateway\" or \"Step 3: Verify.\" Use plain descriptive titles.\n- **No colons in titles.** Wrong: \"Gateways: Deploy and Manage.\" Write \"Deploy and Manage Gateways\" instead.\n- **Use colons only to introduce a list.** Do not use colons as general-purpose punctuation between clauses.\n\nWhen updating an existing page:\n\n- Add content in the logical place within the existing structure.\n- Do not reorganize sections unless the change requires it.\n- Update any cross-references or \"Next Steps\" links if relevant.\n\nWhen creating a new page:\n\n- Follow the frontmatter template from `docs/CONTRIBUTING.mdx`.\n- Add the page to the appropriate section in `docs/index.yml`.\n\n## Step 6: Present the Results\n\nAfter drafting all updates, present a summary to the user:\n\n```\n## Doc Updates from Commits\n\n### Updated pages\n- `docs/sandboxes/manage-gateways.mdx`: Added `--gpu` flag documentation (from commit abc1234).\n- `docs/reference/policy-schema.mdx`: Updated network policy schema for new `tls_inspect` field (from commit def5678).\n\n### New pages needed\n- None (or list any new pages created).\n\n### Commits with no doc impact\n- `chore(deps): bump tokio` (abc1234) — internal dependency, no user-facing change.\n- `test(e2e): add gateway timeout test` (def5678) — test-only change.\n```\n\n## Step 7: Build and Verify\n\nAfter making changes, validate the Fern docs locally:\n\n```bash\nmise run docs\n```\n\nIf a human needs to inspect rendering while iterating, they can also run:\n\n```bash\nmise run docs:serve\n```\n\nCheck for:\n\n- Validation warnings or errors.\n- Broken cross-references.\n- Correct rendering of new content in the PR preview when available.\n\n## Tips\n\n- When in doubt about whether a commit needs a doc update, check if the commit message references a CLI flag, config option, or user-visible behavior.\n- Group related commits that touch the same doc page into a single update rather than making multiple small edits.\n- If a commit is a breaking change, add a note at the top of the relevant section using a Fern `<Warning>` callout.\n- PRs that are purely internal refactors with no behavior change do not need doc updates, even if they touch high-signal directories.\n\n## Example Usage\n\nUser says: \"Catch up the docs for everything merged since v0.2.0.\"\n\n1. Run `git log v0.2.0..HEAD --oneline --no-merges --name-only`.\n2. Filter to `feat`, `fix`, `refactor`, `perf` commits touching user-facing code.\n3. Map each to a doc page.\n4. Read the commit diffs and current doc pages.\n5. Draft updates following the style guide.\n6. Present the summary.\n7. Run `mise run docs` to verify.\n",".agents/skills/build-from-issue/SKILL.md":"---\nname: build-from-issue\ndescription: Given a GitHub issue number, plan and implement the work described in the issue. Supports direct user requests and unattended queue processing through the `agent:*` workflow labels. Includes tests, documentation updates, and PR creation. Trigger keywords - build from issue, implement issue, work on issue, build issue, start issue.\n---\n\n# Build From Issue\n\nPlan, iterate on feedback, and implement work described in a GitHub issue.\n\nThis skill operates as a stateful workflow — it can be run repeatedly against the same issue. Each invocation inspects the issue's labels, plan comment, and conversation history to determine the correct next action.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Invocation and Authorization\n\nThis skill supports two invocation modes:\n\n- **Direct mode:** A user explicitly asks the agent to plan or implement a specific issue. The request itself authorizes the requested phase; the corresponding `agent:*` request label is not required.\n- **Queue mode:** An always-on or unattended agent scans for work without a live user directing it to a specific issue. In this mode, `agent:plan-requested` authorizes planning and `agent:implementation-requested` authorizes implementation.\n\nA direct request authorizes only what it says. A request to review or plan does not authorize implementation. A request to build, implement, or work on an issue authorizes both the planning needed to perform the work and implementation unless the user asks to stop after planning.\n\nThe two request labels remain human-only queue controls. Under **no circumstances** should this skill or any agent apply them, ask to apply them, or suggest automating their application.\n\nDo not refuse a direct user request merely because its request label is absent. If direct work begins on an issue that was not already in the label-driven workflow, do not introduce `agent:in-progress` or `agent:pr-opened` solely for that invocation. If a matching request label is present, preserve the existing label transitions so unattended agents can track the workflow.\n\n## Agent Comment Markers\n\nThis skill uses two distinct markers to identify its comments:\n\n### Plan marker\n\nThe implementation plan lives in a **single comment** that is edited in place as the plan evolves. It is identified by this marker on its first line:\n\n```\n> **🏗️ build-plan**\n```\n\n### Conversation marker\n\nAll other comments (responses to human feedback, status updates, PR announcements) use this marker:\n\n```\n> **🏗️ build-from-issue-agent**\n```\n\nThese markers distinguish agent comments from human comments and from other skills (e.g., `🔒 security-review-agent`, `🔧 security-fix-agent`).\n\n## State Machine Overview\n\nEach invocation follows this decision tree:\n\n```\nFetch issue + comments\n  │\n  ├─ topic:security present?\n  │   → Route to review-security-issue or fix-security-issue; STOP\n  │\n  ├─ Triage incomplete, awaiting information, or awaiting human disposition?\n  │   → Report the blocking state and STOP\n  │\n  ├─ state:accepted and roadmap association both absent?\n  │   → Human has not accepted the issue; STOP\n  │\n  ├─ No plan comment and no direct planning request and agent:plan-requested absent?\n  │   → No request for agent planning; STOP\n  │\n  ├─ No plan comment + direct planning request or agent:plan-requested present?\n  │   → Generate plan via principal-engineer-reviewer\n  │   → Post plan comment\n  │   → Advance labels only for a label-driven invocation\n  │   → Continue if the direct request also authorized implementation; otherwise STOP\n  │\n  ├─ Plan exists + new human comments since last agent response?\n  │   → Respond to each comment (quote context, address feedback)\n  │   → Update the plan comment if feedback requires plan changes\n  │   → STOP\n  │\n  ├─ Plan exists + direct implementation request or 'agent:implementation-requested' label?\n  │   → Run scope check (warn if high complexity)\n  │   → Check for conflicting branches/PRs\n  │   → BUILD (Steps 6–14)\n  │\n  ├─ 'agent:in-progress' label present?\n  │   → Detect existing branch and resume if possible\n  │   → Otherwise report current state\n  │\n  ├─ 'agent:pr-opened' label present?\n  │   → Report that PR already exists, link to it\n  │   → STOP\n  │\n  └─ Plan exists + no new comments + neither a direct implementation request nor 'agent:implementation-requested'?\n      → Report: \"Plan is posted and awaiting review. No new comments to address.\"\n      → STOP\n```\n\n## Step 1: Fetch the Issue\n\nThe user provides an issue ID (e.g., `#42` or `42`). Strip any leading `#` and fetch:\n\n```bash\ngh issue view <id> --json number,title,body,state,labels,author\n```\n\nIf the issue is closed, report that and stop.\n\nIf `topic:security` is present, stop. General build agents must not plan or implement security issues. Route planning/review to `review-security-issue` and authorized remediation to `fix-security-issue`.\n\nStop before planning in any of these states:\n\n- `state:triage-needed`: the issue has not been assessed; use `triage-issue`.\n- `state:needs-info`: triage is waiting for evidence from the reporter.\n- `state:validated` without roadmap placement: triage is complete, but a human has not yet decided whether OpenShell should invest in the work.\n\nNext, require a human acceptance signal: either `state:accepted` or placement on the roadmap. The label records acceptance without requiring scheduling; roadmap placement records acceptance and sequencing. If no plan exists, require either a direct user request for planning or the human-applied `agent:plan-requested` label before generating one. Never add or remove `state:accepted`, either human request label, or the `roadmap` label.\n\n## Step 2: Fetch and Classify Comments\n\nFetch all comments:\n\n```bash\ngh issue view <id> --json comments --jq '.comments[] | {id: .id, body: .body, author: .author.login, createdAt: .createdAt, updatedAt: .updatedAt}'\n```\n\nClassify each comment into one of:\n\n- **Plan comment**: body starts with `> **🏗️ build-plan**`\n- **Agent comment**: body starts with `> **🏗️ build-from-issue-agent**`\n- **Human comment**: everything else (not agent-marked)\n\nRecord the plan comment's `id` (needed for editing via API) and its `updatedAt` timestamp.\n\n## Step 3: Determine Action\n\nUsing the state machine above, determine what to do based on:\n\n1. Whether a plan comment exists\n2. Whether there are human comments newer than the last agent comment (plan or conversation)\n3. Whether this is direct mode and which phase the user requested\n4. Which disposition, roadmap, and agent-workflow labels are present (`state:accepted`, `agent:plan-requested`, `agent:plan-ready`, `agent:implementation-requested`, `agent:in-progress`, `agent:pr-opened`, and the `roadmap` label)\n\nFollow the appropriate branch below.\n\n---\n\n## Branch A: Generate the Plan\n\nIf no plan comment exists, generate one when the user directly requested planning or implementation, or when `agent:plan-requested` is present. Otherwise report that no one has requested agent planning and stop.\n\n### A1: Analyze the Issue with Principal Engineer Reviewer\n\nPass the issue title, description, labels, and any relevant code references to the `principal-engineer-reviewer` sub-agent. Use the Task tool:\n\n```\nTask tool with subagent_type=\"principal-engineer-reviewer\"\n```\n\nIn the prompt, instruct the reviewer to:\n\n1. Read the issue's user story and identify what needs to change in the codebase. Treat reporter diagnostics or solution ideas as optional context, not as authoritative or current analysis.\n2. Map the requirements to existing code — read the relevant source files.\n3. Determine the **issue type** — one of: `feat` (new feature), `fix` (bug fix), `refactor`, `chore`, `perf`, `docs`.\n4. Propose the minimal set of changes that satisfies the requirements.\n5. Sequence the work so each step is independently testable.\n6. Identify what tests are needed (unit, integration, e2e) and where they should live.\n7. Assess **complexity** on a scale:\n   - **Low**: Isolated change, < 3 files, clear path forward\n   - **Medium**: Multiple files/components, some design decisions, but well-scoped\n   - **High**: Cross-cutting changes, architectural decisions needed, significant unknowns\n8. Call out risks, unknowns, and decisions that need stakeholder input.\n9. Assess **gateway config documentation impact** — if the change adds, removes, renames, or changes defaults for gateway TOML keys or driver-specific config options, the plan must include an update to `docs/reference/gateway-config.mdx`. If the change is surfaced through Helm or a compute-driver overview, also include `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment docs.\n10. Assess **LSM compatibility** — if the change touches process identity, `/proc` filesystem access, binary execution, or inter-process visibility, flag whether it will behave differently on hosts running SELinux (enforcing) or AppArmor. In particular, tests that fork+exec into system binaries will fail on SELinux-enforcing hosts due to cross-label `/proc/<pid>/exe` access restrictions.\n\nPerform this investigation against the current branch and current product behavior. If the issue contains earlier diagnostics, verify them rather than relying on them.\n\n### A2: Post the Plan Comment\n\nPost the plan as a comment on the issue. This is the **canonical plan comment** that will be edited in place as the plan evolves.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n**Issue type:** `<feat|fix|refactor|chore|perf|docs>`\n**Complexity:** <Low|Medium|High>\n**Confidence:** <High — clear path | Medium — some unknowns | Low — needs discussion>\n\n### Summary\n<2-3 sentences describing what will be built/changed and the approach>\n\n### Scope\n- `<file1>`: <what changes and why>\n- `<file2>`: <what changes and why>\n- ...\n\n### Implementation Steps\n1. <step 1 — independently testable>\n2. <step 2>\n3. ...\n\n### Test Plan\n- **Unit tests:** <what will be tested and where the tests live>\n- **Integration tests:** <what will be tested, or \"N/A\" with rationale>\n- **E2E tests:** <what will be tested, or \"N/A\" with rationale>\n\n### Risks & Open Questions\n- <risk or unknown that may need human input>\n\n### Documentation Impact\n- <docs expected per AGENTS.md, or \"None expected\">\n\n---\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\n### A3: Mark the Plan Ready in Queue Mode\n\nIf `agent:plan-requested` was present, replace it with `agent:plan-ready`. Do not add `agent:plan-ready` for a direct invocation that was not already using the label workflow.\n\n```bash\ngh issue edit <id> --remove-label \"agent:plan-requested\" --add-label \"agent:plan-ready\"\n```\n\nIf the direct request authorized implementation, continue to Branch C. Otherwise report that the plan has been posted and stop. In queue mode, a human reviews the plan and applies `agent:implementation-requested` before an unattended agent can build.\n\n---\n\n## Branch B: Respond to Feedback\n\nIf a plan exists and there are human comments newer than the last agent response, address them.\n\n### B1: Process Each Unanswered Human Comment\n\nFor each human comment that is newer than the most recent agent comment (plan `updatedAt` or conversation comment `createdAt`):\n\n1. Read the comment.\n2. Quote the relevant portion using `>` blockquote syntax.\n3. Formulate a response based on the codebase and the current plan.\n4. Post a response with the conversation marker.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n> <quoted portion of human's comment>\n\n<response addressing the feedback>\nEOF\n)\"\n```\n\n### B2: Update the Plan if Needed\n\nIf any feedback requires changes to the plan, **edit the existing plan comment** rather than posting a new one. Use the GitHub API with the comment's node ID:\n\n```bash\ngh api graphql -f query='\n  mutation {\n    updateIssueComment(input: {id: \"<comment-node-id>\", body: \"<updated body>\"}) {\n      issueComment { id }\n    }\n  }\n'\n```\n\nOr use the REST API:\n\n```bash\ngh api repos/{owner}/{repo}/issues/comments/<comment-id> -X PATCH -f body=\"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n<... updated plan content ...>\n\n---\n*Revision <N> — <brief description of what changed>*\n*Revision <N-1> — <previous change>*\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\nPreserve the full revision history at the bottom so readers can track how the plan evolved.\n\nReport to the user what feedback was addressed and whether the plan was updated. Stop.\n\n---\n\n## Branch C: Build\n\nProceed with implementation when the plan exists and either the user directly requested implementation or `agent:implementation-requested` is present. An existing `agent:in-progress` or `agent:pr-opened` label still triggers the resume or existing-PR checks below.\n\n### Step 4: Scope Check\n\nRead the plan comment and check the **Complexity** and **Confidence** fields.\n\n- **If Complexity is High or Confidence is Low**, warn the user:\n\n  > \"This issue is rated High complexity / Low confidence. The plan includes open questions that may need human decisions during implementation. Proceeding, but flagging this for your awareness.\"\n\n  Continue — do not hard-stop. The user directly requested implementation or chose to apply `agent:implementation-requested`.\n\n### Step 5: Conflict Detection\n\nBefore creating a branch, check for conflicts:\n\n#### Check for existing branches\n\n```bash\ngit fetch origin\ngit branch -r | grep -i \"<issue-id>\"\n```\n\nIf a remote branch referencing this issue ID exists, report it and ask the user whether to continue on that branch or abort.\n\n#### Check for existing PRs\n\n```bash\ngh pr list --state open --search \"Closes #<issue-id>\" --json number,title,url\n```\n\nIf an open PR already references this issue, report it and stop. Do not create a competing PR.\n\n### Step 6: Create Branch\n\nDetermine the branch prefix from the issue type in the plan:\n\n| Issue type | Branch prefix |\n| --- | --- |\n| `feat` | `feat/` |\n| `fix` | `fix/` |\n| `refactor` | `refactor/` |\n| `chore` | `chore/` |\n| `perf` | `perf/` |\n| `docs` | `docs/` |\n\nGet the current username and create the branch:\n\n```bash\nUSERNAME=$(gh api user --jq '.login')\ngit checkout main\ngit pull origin main\ngit checkout -b <prefix><issue-id>-<short-description>/$USERNAME\n```\n\n### Step 7: Mark Queue Work In Progress\n\nIf `agent:implementation-requested` is present, replace it and `agent:plan-ready` with `agent:in-progress`. In direct mode without a request label, do not add an agent-workflow label.\n\n```bash\ngh issue edit <id> --remove-label \"agent:implementation-requested\" --remove-label \"agent:plan-ready\" --add-label \"agent:in-progress\"\n```\n\n### Step 8: Implement the Changes\n\nFollow the implementation steps from the plan. Principles:\n\n- **Follow the plan**: The plan was reviewed and approved. Stick to it unless you discover something that requires deviation.\n- **Minimal scope**: Only change what the plan calls for. No unrelated refactors.\n- **If you must deviate**: Note the deviation — it will be included in the PR description.\n\nRead the relevant source files before making changes. Implement step by step per the plan's sequence.\n\n### Step 9: Write Tests\n\nWrite tests as specified in the plan's Test Plan section. Follow the project's existing test conventions.\n\n#### Unit tests\n\n- Place alongside existing tests for the module (e.g., `#[cfg(test)]` blocks in Rust, `test_*.py` for Python)\n- Cover the new/changed behavior, edge cases, and error paths\n- Ensure pre-existing behavior still works\n\n#### Integration tests\n\n- Place in the project's existing integration test directories\n- Cover interactions between the changed components\n- Test realistic scenarios including error conditions\n\n#### E2E tests\n\n- Only if the plan calls for them\n- Cover the full user-facing workflow affected by the change\n\n#### Test naming\n\nUse descriptive names that document intent:\n- `test_pagination_returns_correct_page_count`\n- `test_rejects_negative_offset_parameter`\n- `test_retry_succeeds_after_transient_failure`\n\n### Step 10: Verify — Tests, Lint, Pre-commit (Retry Loop)\n\nVerification has two phases: unit tests + pre-commit, then E2E tests (if applicable). Run with up to **3 attempts per phase**.\n\n#### Phase 1: Unit Tests and Pre-commit\n\nOn each attempt:\n\n```bash\n# Run pre-commit checks (linting, formatting, license headers)\nmise run pre-commit\n```\n\n**If verification fails:**\n\n1. Read the error output carefully.\n2. Fix the issues (test failures, lint errors, formatting).\n3. Decrement the retry counter and try again.\n\n**If all 3 attempts fail**, stop and report to the user:\n- What passed and what failed\n- The specific errors from the last attempt\n- That manual intervention is needed\n\nDo not proceed to Phase 2 or PR creation if Phase 1 is not green.\n\n#### Phase 2: E2E Tests (Conditional)\n\n**Trigger**: Run this phase if any files under `e2e/` were added or modified in this build. Check with:\n\n```bash\ngit diff --name-only main -- e2e/\n```\n\nIf there are no changes under `e2e/`, skip this phase entirely.\n\nIf E2E files were modified, run the relevant E2E lane for the driver touched by the change:\n\n```bash\n# Docker-backed gateway smoke E2E\nmise run e2e:docker\n```\n\nUse `mise run e2e:podman`, `mise run e2e:vm`, or a Helm-backed Kubernetes E2E lane when the change targets those drivers.\n\n**E2E retry loop** (up to 3 attempts):\n\n1. Run the selected E2E lane.\n2. If tests fail:\n   - Read the pytest output carefully — identify which tests failed and why.\n   - Distinguish between **test bugs** (the test itself is wrong) and **implementation bugs** (the code under test is wrong).\n   - Fix the failing code or tests.\n   - Decrement the retry counter and try again.\n3. If tests pass, Phase 2 is green.\n\n**If all 3 E2E attempts fail**, stop and report to the user:\n- Which E2E tests are failing\n- The pytest output from the last attempt\n- Whether the failures appear to be test issues or implementation issues\n- That manual intervention is needed\n\nDo not proceed to PR creation if E2E verification is not green.\n\n### Step 11: Update Documentation\n\nReview the documentation requirements in `AGENTS.md` and update any affected\ndocs as part of the implementation. Keep documentation changes scoped to the\nbehavior or subsystem that changed.\n\nIf the implementation changes gateway TOML parsing, `[openshell.gateway]`\nfields, `[openshell.drivers.<name>]` fields, driver config defaults, or Helm\nrendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the\nsame branch. If the change affects user-facing compute-driver setup, also\nupdate `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment\npage.\n\nUse the `sync-agent-infra` skill's maintenance map to identify related skill updates when the implementation changes behavior, commands, or development workflows. Run its full consistency check when the implementation adds, removes, or renames skills or crates; changes workflow relationships or skill coverage; modifies issue or PR templates; or changes agent cross-references. Fix any drift before committing.\n\n### Step 12: Commit and Push\n\nCommit all changes using conventional commit format. The `<type>` comes from the issue type in the plan:\n\n```bash\ngit add <files>\ngit commit -m \"$(cat <<'EOF'\n<type>(<scope>): <short description>\n\nCloses #<issue-id>\n\n<brief explanation of what was implemented>\nEOF\n)\"\n```\n\nPush:\n\n```bash\ngit push -u origin HEAD\n```\n\n### Step 13: Open PR\n\nCreate the PR:\n\n```bash\ngh pr create \\\n  --title \"<type>(<scope>): <short description>\" \\\n  --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Summary\n<1-3 sentences describing what was built and the approach taken>\n\n## Related Issue\nCloses #<issue-id>\n\n## Changes\n- `<file1>`: <what changed and why>\n- `<file2>`: <what changed and why>\n\n### Deviations from Plan\n<any deviations from the approved plan, or \"None — implemented as planned\">\n\n## Testing\n- [x] `mise run pre-commit` passes\n- [x] Unit tests added/updated\n- [x] E2E tests added/updated (if applicable)\n\n**Tests added:**\n- **Unit:** <test file(s) and what they cover>\n- **Integration:** <test file(s) and what they cover, or \"N/A\">\n- **E2E:** <test file(s) and what they cover, or \"N/A\">\n\n## Checklist\n- [x] Follows Conventional Commits\n- [x] Commits are signed off (DCO)\n\n**Documentation updated:**\n- `<doc path>`: <what was updated, or \"None needed\">\nEOF\n)\"\n```\n\n**Display the PR URL** so it's easily clickable:\n\n```\nCreated PR [#<number>](https://github.com/OWNER/REPO/pull/<number>)\n```\n\n### Step 14: Post-Build Cleanup\n\n#### Post summary comment on the issue\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Implementation Complete\n\nPR: [#<pr-number>](https://github.com/OWNER/REPO/pull/<pr-number>)\n\n### What was built\n<1-2 sentence summary>\n\n### Tests\n- Unit: <count> tests added\n- Integration: <count or N/A>\n- E2E: <count or N/A>\n\n### Docs updated\n- <list of updated docs, or \"None needed\">\n\nThe issue will auto-close when the PR is merged.\nEOF\n)\"\n```\n\n#### Post E2E attestation comment on the PR\n\nIf E2E tests were run in Phase 2 of Step 10, post an attestation comment on the **PR** documenting that local E2E tests passed. This is necessary because E2E tests are not yet running in CI — this comment serves as the verification record for reviewers.\n\nCollect the metadata before posting:\n\n```bash\n# Get the commit SHA that was tested\nCOMMIT_SHA=$(git rev-parse HEAD)\n\n# Get the test output summary (last few lines of pytest output)\n# This was captured during the Phase 2 run — include the pass/fail/skip counts\n```\n\nPost the attestation:\n\n```bash\ngh pr comment <pr-number> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## E2E Test Attestation\n\nLocal E2E tests passed. CI does not currently run E2E tests, so this comment serves as the verification record.\n\n| Field | Value |\n|-------|-------|\n| **Commit** | `<commit-sha>` |\n| **Command** | `<selected e2e command>` |\n| **Gateway mode** | `<docker / podman / vm / helm>` |\n| **Result** | ✅ All passed |\n\n### Test Summary\n\n```\n<paste the pytest summary line, e.g.: \"12 passed, 1 skipped in 45.32s\">\n```\n\n### Tests Executed\n- `<test_file.py>::<test_name>` — PASSED\n- `<test_file.py>::<test_name>` — PASSED\n- ...\nEOF\n)\"\n```\n\nInclude **every test** that ran (not just the new ones) so the reviewer can see full coverage. If any tests were skipped, note them and explain why.\n\n#### Update labels\n\nIf `agent:in-progress` is present, replace it with `agent:pr-opened`. Do not add `agent:pr-opened` for an unlabeled direct invocation:\n\n```bash\ngh issue edit <id> --remove-label \"agent:in-progress\" --add-label \"agent:pr-opened\"\n```\n\n#### Report workflow run URL\n\nGet the workflow run URL from the PR so the user can monitor CI:\n\n```bash\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\" --limit 1 --json databaseId,status,url\n```\n\nReport the workflow run URL and suggest the user can use the `watch-github-actions` skill to monitor it.\n\n---\n\n## Branch D: Resume In-Progress Build\n\nIf the `agent:in-progress` label is present, the skill was previously started but may not have completed.\n\n1. Check for an existing branch matching the issue ID:\n   ```bash\n   git branch -r | grep -i \"<issue-id>\"\n   ```\n2. If found, check it out and inspect the state (are there uncommitted changes? committed but not pushed? pushed but no PR?).\n3. Resume from the appropriate step (9, 10, 12, or 13).\n4. If the state is unrecoverable, report to the user and suggest starting fresh. Queue mode requires a human to reapply `agent:implementation-requested`; a new direct implementation request can resume without it.\n\n---\n\n## Useful Commands Reference\n\n| Command | Description |\n| --- | --- |\n| `gh issue view <id> --json number,title,body,state,labels,author` | Fetch full issue metadata |\n| `gh issue view <id> --json comments` | Fetch all comments on an issue |\n| `gh issue comment <id> --body \"...\"` | Post a comment on an issue |\n| `gh api repos/{owner}/{repo}/issues/comments/<id> -X PATCH -f body=\"...\"` | Edit an existing comment |\n| `gh issue edit <id> --add-label \"...\"` | Add labels |\n| `gh issue edit <id> --remove-label \"...\"` | Remove labels |\n| `gh pr list --state open --search \"...\"` | Search for open PRs |\n| `gh pr create --title \"...\" --body \"...\"` | Create a pull request |\n| `gh api user --jq '.login'` | Get current GitHub username |\n| `mise run pre-commit` | Run pre-commit checks (lint, format, license headers) |\n| `mise run e2e:docker` | Run smoke E2E against a standalone Docker-backed gateway |\n| `mise run e2e:podman` | Run smoke E2E against a Podman-backed gateway |\n| `mise run e2e:vm` | Run smoke E2E against the VM compute driver |\n\n## Example Usage\n\n### First run — no plan exists\n\nUser says: \"Plan issue #42\"\n\n1. Fetch issue #42 — title: \"Add pagination to dataset list endpoint\"\n2. Confirm `state:accepted` with no blocking triage state; the user's direct request authorizes planning even if `agent:plan-requested` is absent\n3. Fetch comments — no `🏗️ build-plan` marker found\n4. Pass issue to `principal-engineer-reviewer` for analysis\n5. Reviewer produces a plan: feat type, Medium complexity, 3 implementation steps, unit + integration tests needed\n6. Post the plan comment with the `🏗️ build-plan` marker\n7. Because this direct invocation was unlabeled, leave the `agent:*` workflow labels unchanged\n8. Report to user: \"Plan posted on issue #42. Awaiting review.\"\n\n### Second run — human left feedback\n\nUser says: \"Check on issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find existing plan comment (Revision 1)\n3. Find new human comment: \"Should we also paginate the search endpoint?\"\n4. Post response quoting the question, explaining that search pagination is out of scope for this issue but could be a follow-up\n5. Report to user: \"Responded to feedback on #42. Plan unchanged.\"\n\n### Third run — human revised scope, plan needs update\n\nUser says: \"Check issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find plan + new human comment: \"Actually, let's include search pagination. Updated the issue description.\"\n3. Post response acknowledging the scope change\n4. Edit the plan comment to include search endpoint pagination — Revision 2\n5. Report to user: \"Updated plan to include search pagination (Revision 2).\"\n\n### Fourth run — implementation requested\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists (Revision 2), complexity: Medium, confidence: High\n3. No conflicting branches or PRs\n4. Create branch `feat/42-add-pagination/jmyers`\n5. Leave `agent:*` labels unchanged because this direct invocation was not picked up from the queue\n6. Implement pagination for both endpoints per the plan\n7. Add unit tests for pagination logic, integration tests for both endpoints\n8. `mise run pre-commit` passes on first attempt\n9. E2E tests skipped (no changes under `e2e/`)\n10. Commit, push, create PR with `Closes #42`\n11. Post summary comment on issue with PR link\n12. No agent-workflow label transition is needed\n13. Report PR URL and workflow run status to user\n\n### Run on issue with existing PR\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `agent:pr-opened` label present\n2. Find existing PR #789 linked to the issue\n3. Report: \"PR [#789](...) already exists for issue #42. Nothing to build.\"\n\n### Run on high-complexity issue\n\nUser says: \"Build issue #99\"\n\n1. Fetch issue #99 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists: complexity High, confidence Low, has open questions\n3. Warn user: \"Issue #99 is rated High complexity / Low confidence. Proceeding but flagging for your awareness.\"\n4. Continue with build\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Agent Instructions\n\nThis file is the primary instruction surface for agents contributing to OpenShell. It is injected into your context on every interaction — keep that in mind when proposing changes to it.\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for build instructions, task reference, project structure, and the full agent skills table.\n\n## Project Identity\n\nOpenShell is built agent-first. We design systems and use agents to implement them — this is not vibe coding. The product provides safe, sandboxed runtimes for autonomous AI agents, and the project itself is built using the same agent-driven workflows it enables.\n\n## Skills\n\nAgent skills live in `.agents/skills/`. Your harness can discover and load them natively — do not rely on this file for a full inventory. The detailed skills table is in [CONTRIBUTING.md](CONTRIBUTING.md) (for humans).\n\n## Workflow Chains\n\nThese pipelines connect skills into end-to-end workflows. Individual skill files don't describe these relationships.\n\n- **Community inflow:** `triage-issue` → human disposition and roadmap placement → `create-spike` when needed → `build-from-issue`\n  - Triage establishes facts and marks technically valid issues `state:validated`. A human signals that the project should pursue the work by applying `state:accepted` or placing the issue on the roadmap. The `agent:*` labels support unattended agents that scan for queued work: a human queues a plan with `agent:plan-requested`, the agent returns `agent:plan-ready`, and a human queues implementation with `agent:implementation-requested`. A direct user request to an agent authorizes the requested phase without those labels.\n- **Internal development:** `create-spike` → human disposition and roadmap placement → `build-from-issue`\n  - Spike explores feasibility and marks its issue `state:validated` when sufficient evidence exists. A human accepts it with `state:accepted` or roadmap placement, or declines it, and optionally queues it through the `agent:*` workflow or directs an agent to it.\n- **Security:** `review-security-issue` → `fix-security-issue`\n  - General build agents must not process `topic:security` issues. For unattended processing, a human queues specialized review with `agent:plan-requested`; review produces a severity assessment and remediation plan; a human queues remediation with `agent:implementation-requested`. Direct requests to the specialized skills do not require those labels.\n- **Policy iteration:** `openshell-cli` → `generate-sandbox-policy`\n  - CLI manages the sandbox lifecycle; policy generation authors the YAML constraints.\n\n## Architecture Overview\n\n| Path | Components | Purpose |\n|------|-----------|---------|\n| `crates/openshell-cli/` | CLI binary | User-facing command-line interface |\n| `crates/openshell-server/` | Gateway server | Control-plane API, sandbox lifecycle, auth boundary |\n| `crates/openshell-sandbox/` | Sandbox runtime | Container supervision, policy-enforced egress routing |\n| `crates/openshell-policy/` | Policy engine | Filesystem, network, process, and inference constraints |\n| `crates/openshell-router/` | Privacy router | Privacy-aware LLM routing |\n| `crates/openshell-bootstrap/` | Gateway metadata | Gateway registration metadata, auth token storage, mTLS bundle storage |\n| `crates/openshell-gateway-interceptors/` | Gateway interceptors | Intercepts and transforms configured gRPC requests at the gateway routing boundary |\n| `crates/openshell-ocsf/` | OCSF logging | OCSF v1.7.0 event types, builders, shorthand/JSONL formatters, tracing layers |\n| `crates/openshell-otel/` | OpenTelemetry support | Shared OTLP trace provider, resource, and tracing-layer construction |\n| `crates/openshell-core/` | Shared core | Common types, configuration, error handling |\n| `crates/openshell-extension-core/` | Extension core | Shared extension identity, JWT claims, bearer-token rotation, and TLS transport primitives |\n| `crates/openshell-sdk/` | Shared client SDK | Async Rust gateway client (gRPC transport, TLS, OIDC refresh, edge tunnel); consumed by CLI, TUI, and `@openshell/sdk` |\n| `crates/openshell-providers/` | Provider management | Credential provider backends |\n| `crates/openshell-tui/` | Terminal UI | Ratatui-based dashboard for monitoring |\n| `crates/openshell-driver-kubernetes-secrets/` | Kubernetes Secrets credential driver | In-process `CredentialDriver` backend for OpenShell-managed K8s Secret storage |\n| `crates/openshell-driver-vault/` | Vault credential driver | In-process `CredentialDriver` backend for Vault-compatible KV storage |\n| `crates/openshell-driver-db-credstore/` | Database credential driver | In-process `CredentialDriver` backend for gateway database credential storage |\n| `crates/openshell-driver-kubernetes/` | Kubernetes compute driver | In-process `ComputeDriver` backend for K8s sandbox pods |\n| `crates/openshell-driver-docker/` | Docker compute driver | In-process `ComputeDriver` backend for local Docker sandbox containers |\n| `crates/openshell-driver-podman/` | Podman compute driver | In-process `ComputeDriver` backend for local Podman sandbox containers |\n| `crates/openshell-driver-vm/` | VM compute driver | Standalone libkrun-backed `ComputeDriver` subprocess (embeds its own rootfs + runtime) |\n| `crates/openshell-prover/` | Policy prover | Policy verification and proof generation |\n| `crates/openshell-server-macros/` | Server macros | Compile-time helpers for gateway RPC authorization |\n| `crates/openshell-supervisor-middleware/` | Middleware runtime | Generic middleware registry, remote service integration, and chain execution |\n| `crates/openshell-supervisor-middleware-builtins/` | Built-in middleware | First-party in-process middleware implementations |\n| `crates/openshell-supervisor-network/` | Network supervisor | Proxying, L7 enforcement, policy evaluation, and inference routing |\n| `crates/openshell-supervisor-process/` | Process supervisor | Process lifecycle, namespace, and bypass monitoring |\n| `crates/openshell-vfio/` | VFIO support | PCI and GPU passthrough preparation and lifecycle |\n| `python/openshell/` | Python SDK | Python bindings and CLI packaging |\n| `sdk/typescript/` | TypeScript SDK | Native Connect client, curated sandbox API, and generated protobuf types |\n| `proto/` | Protobuf definitions | gRPC service contracts |\n| `deploy/` | Docker, Helm, K8s | Dockerfiles, Helm chart, manifests |\n| `docs/` | Published docs | MDX pages, navigation, and content assets |\n| `fern/` | Docs site config | Fern site config, components, and theme assets |\n| `.agents/skills/` | Agent skills | Workflow automation for development |\n| `.agents/agents/` | Agent personas | Sub-agent definitions (e.g., reviewer, doc writer) |\n| `architecture/` | Architecture docs | Design decisions and component documentation |\n\n## Vouch System\n\n- First-time external contributors must be vouched before their PRs are accepted. The `vouch-check` workflow auto-closes PRs from unvouched users.\n- Org members and collaborators bypass the vouch gate automatically.\n- Maintainers vouch users by commenting `/vouch` on a Vouch Request discussion. The `vouch-command` workflow appends the username to `.github/VOUCHED.td`.\n- Skills that create PRs (`create-github-pr`, `build-from-issue`) should note this requirement when operating on behalf of external contributors.\n\n## Issue and PR Conventions\n\n- **Bug reports and feature requests** must include a User Story, Problem Statement, Impact / Why This Matters, and Acceptance Criteria. The impact should explain the consequences of the current behavior, the current workaround, and why that workaround is insufficient. Bug reports additionally require reproduction steps and environment details and may include concise, redacted logs.\n- **Feature requests** must also include a Proposed Design and Alternatives Considered. The design should define the user-facing workflow and externally observable behavior while leaving internal implementation choices open. Agent investigation is optional.\n- **New features** must start as GitHub issues using the feature request template. Open an RFC only after an issue exists; maintainers decide when one is needed and assign RFC numbers from the issue.\n- **Issue triage** establishes technical validity and impact evidence. Agents never decide acceptance, apply `state:accepted`, place issues on the roadmap, or apply `agent:plan-requested` or `agent:implementation-requested`. Humans accept or decline validated work; `state:accepted` or roadmap placement records acceptance, and roadmap association additionally carries sequencing. The request labels queue work for unattended agents; an explicit user instruction can instead authorize an agent to plan or implement a specific issue. OpenShell has no `priority:*` labels.\n- **PRs** must follow the PR template structure: Summary, Related Issue, Changes, Testing, Checklist. Contributors should use their agent to investigate the current code and behavior for accepted issue-backed work, verify any diagnostics already on the issue, understand the change they submit, and report the resulting implementation and verification—not paste an earlier issue-filing diagnostic.\n- **PRs for features, user-visible behavior, public APIs, architecture, or multi-PR efforts** must link an accepted issue. Small docs fixes, mechanical maintenance, and obvious localized bug fixes may state why no issue is required.\n- **PRs from unvouched external contributors** are automatically closed. See the Vouch System section above.\n- **Security vulnerabilities** must NOT be filed as GitHub issues. Follow [SECURITY.md](SECURITY.md).\n- Skills that create issues or PRs (`create-github-issue`, `create-github-pr`, `build-from-issue`) should produce output conforming to these templates.\n\n## Plans\n\n- Store plan documents in `architecture/plans`. This is git ignored so its for easier access for humans. When asked to create Spikes or issues, you can skip to GitHub issues. Only use the plans dir when you aren't writing data somewhere else specific.\n- When asked to write a plan, write it there without asking for the location.\n\n## Sandbox Logging (OCSF)\n\nWhen adding or modifying log emissions in `openshell-sandbox`, determine whether the event should use OCSF structured logging or plain `tracing`.\n\n### When to use OCSF\n\nUse an OCSF builder + `ocsf_emit!()` for events that represent **observable sandbox behavior** visible to operators, security teams, or agents monitoring the sandbox:\n\n- Network decisions (allow, deny, bypass detection)\n- HTTP/L7 enforcement decisions\n- SSH authentication (accepted, denied, nonce replay)\n- Process lifecycle (start, exit, timeout, signal failure)\n- Security findings (unsafe policy, unavailable controls, replay attacks)\n- Configuration changes (policy load/reload, TLS setup, inference routes, settings)\n- Application lifecycle (supervisor start, SSH server ready)\n\n### When to use plain tracing\n\nUse `info!()`, `debug!()`, `warn!()` for **internal operational plumbing** that doesn't represent a security decision or observable state change:\n\n- gRPC connection attempts and retries\n- \"About to do X\" events where the result is logged separately\n- Internal SSH channel state (unknown channel, PTY resize)\n- Zombie process reaping, denial flush telemetry\n- DEBUG/TRACE level diagnostics\n\n### Choosing the OCSF event class\n\n| Event type | Builder | When to use |\n|---|---|---|\n| TCP connections, proxy tunnels, bypass | `NetworkActivityBuilder` | L4 network decisions, proxy operational events |\n| HTTP requests, L7 enforcement | `HttpActivityBuilder` | Per-request method/path decisions |\n| SSH sessions | `SshActivityBuilder` | Authentication, channel operations |\n| Process start/stop | `ProcessActivityBuilder` | Entrypoint lifecycle, signal failures |\n| Security alerts | `DetectionFindingBuilder` | Nonce replay, bypass detection, unsafe policy. Dual-emit with the domain event. |\n| Policy/config changes | `ConfigStateChangeBuilder` | Policy load, Landlock apply, TLS setup, inference routes, settings |\n| Supervisor lifecycle | `AppLifecycleBuilder` | Sandbox start, SSH server ready/failed |\n\n### Severity guidelines\n\n| Severity | When |\n|---|---|\n| `Informational` | Allowed connections, successful operations, config loaded |\n| `Low` | DNS failures, non-fatal operational warnings, LOG rule failures |\n| `Medium` | Denied connections, policy violations, deprecated config |\n| `High` | Security findings (nonce replay, Landlock unavailable) |\n| `Critical` | Process timeout kills |\n\n### Example: adding a new network event\n\n```rust\nuse openshell_ocsf::{\n    ocsf_emit, NetworkActivityBuilder, ActivityId, ActionId,\n    DispositionId, Endpoint, Process, SeverityId, StatusId,\n};\n\nlet event = NetworkActivityBuilder::new(crate::ocsf_ctx())\n    .activity(ActivityId::Open)\n    .action(ActionId::Denied)\n    .disposition(DispositionId::Blocked)\n    .severity(SeverityId::Medium)\n    .status(StatusId::Failure)\n    .dst_endpoint(Endpoint::from_domain(&host, port))\n    .actor_process(Process::new(&binary, pid))\n    .firewall_rule(&policy_name, &engine_type)\n    .message(format!(\"CONNECT denied {host}:{port}\"))\n    .build();\nocsf_emit!(event);\n```\n\n### Key points\n\n- `crate::ocsf_ctx()` returns the process-wide `SandboxContext`. It is always available (falls back to defaults in tests).\n- `ocsf_emit!()` is non-blocking and cannot panic. It stores the event in a thread-local and emits via `tracing::info!()`.\n- The shorthand layer and JSONL layer extract the event from the thread-local. The shorthand format is derived automatically from the builder fields.\n- For security findings, **dual-emit**: one domain event (e.g., `SshActivityBuilder`) AND one `DetectionFindingBuilder` for the same incident.\n- Never log secrets, credentials, or query parameters in OCSF messages. The OCSF JSONL file may be shipped to external systems.\n- The `message` field should be a concise, grep-friendly summary. Details go in builder fields (dst_endpoint, firewall_rule, etc.).\n\n## Sandbox Infra Changes\n\n- If you change sandbox infrastructure, ensure the relevant sandbox e2e path succeeds.\n\n## Network Sockets\n\n- On latency-sensitive TCP streams, disable Nagle's algorithm so small\n  request/response frames don't stall on delayed ACKs. Use\n  `openshell_core::net::set_tcp_nodelay_best_effort` on an accepted or\n  already-connected stream, or `openshell_core::net::connect_tcp_nodelay_best_effort`\n  when dialing.\n- This applies to loopback/localhost TCP too — the delayed-ACK stall is a timer\n  behavior, not wire latency.\n- You should skip it for unix domain sockets (no Nagle). It's not critical for\n  test-only connections, though using it on any non-UDS TCP stream — tests\n  included — is fine and preferred.\n\n## Commits\n\n- Always use [Conventional Commits](https://www.conventionalcommits.org/) format for commit messages\n- Format: `<type>(<scope>): <description>` (scope is optional)\n- Common types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `ci`, `perf`\n- Sign off on each commit for DCO compliance. Use the `--signoff` option to `git commit` to add the `Signed-off-by` footer to ensure the user's configured email address is used.\n- Never mention Claude or any AI agent in commits (no author attribution, no Co-Authored-By, no references in commit messages)\n\n## Pre-commit\n\n- Run `mise run pre-commit` before committing.\n- Install the git hook when working locally: `mise generate git-pre-commit --write --task=pre-commit`\n\n## Testing\n\n- `mise run pre-commit` — Lint, format, license headers. Run before every commit.\n- `mise run test` — Unit test suite. Run after code changes.\n- `mise run e2e` — End-to-end tests against a running gateway. Run for infrastructure, sandbox, or policy changes.\n- `mise run ci` — Full local CI (lint + compile/type checks + tests). Run before opening a PR.\n\n## Go SDK (`sdk/go/`)\n\n- The Go SDK lives in `sdk/go/` with module path `github.com/NVIDIA/OpenShell/sdk/go`.\n- Run `mise run go:ci` for the full SDK CI pipeline (lint, build, test, proto-check, docs-check).\n- Proto bindings are generated with `mise run go:proto:gen` from the `.proto` files in `proto/`.\n- Domain types in `sdk/go/openshell/v1/types/` must not import proto packages.\n- Converters in `sdk/go/openshell/v1/internal/converter/` deep-copy slices and maps at boundaries.\n- Tests use bufconn for in-process gRPC and testify for assertions.\n\n## TypeScript SDK (`sdk/typescript/`)\n\n- Run `mise run sdk:ts:ci` for codegen, proto lint, Biome lint, type checking, unit tests, coverage, and build validation.\n- Proto bindings are generated with `mise run sdk:ts:proto` from the files selected in `sdk/typescript/buf.gen.yaml`.\n- Generated files under `sdk/typescript/src/gen/` are build outputs and must not be committed.\n- Keep the curated API free of generated wire types; expose full generated messages and RPCs through `@nvidia/openshell-sdk/raw`.\n- The release workflow publishes the package to GitHub Packages. Branch checks exercise the publish path with `npm publish --dry-run`.\n\n## Python\n\n- Always use `uv` for Python commands (e.g., `uv pip install`, `uv run`, `uv venv`)\n\n## Docker\n\n- Always prefer `mise` commands over direct docker builds (e.g., `mise run docker:build` instead of `docker build`)\n\n## Cluster Infrastructure Changes\n\n- If you change gateway deployment infrastructure (e.g., Helm values/templates, gateway image packaging, or deploy logic in `openshell-cli`), update the `debug-openshell-cluster` skill in `.agents/skills/debug-openshell-cluster/SKILL.md` to reflect those changes.\n\n## Skill Maintenance\n\nWhen behavior, commands, or development workflows change, review the related agent skills in the same branch. Use the `sync-agent-infra` skill for the maintenance map and consistency checks.\n\n## Documentation\n\n- When making changes, update the relevant documentation in the `architecture/` directory.\n- When changes affect user-facing behavior, update the relevant published docs pages under `docs/` and navigation in `docs/index.yml`.\n- When changing gateway TOML fields, driver-specific config options, config defaults, or Helm rendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the same branch.\n- `fern/` contains the Fern site config, components, preview workflow inputs, and publish settings.\n- Follow the docs style guide in [docs/CONTRIBUTING.mdx](docs/CONTRIBUTING.mdx): active voice, minimal formatting, no filler introductions, `shell` fences for copyable commands, and no duplicate body H1.\n- Fern PR previews run through `.github/workflows/branch-docs.yml`, and production publish runs through the `publish-fern-docs` job in `.github/workflows/release-tag.yml`.\n- Use the `update-docs` skill to scan recent commits and draft doc updates.\n\n### Architecture Docs\n\n- Architecture docs are short canonical subsystem overviews, not exhaustive implementation notes.\n- Update one of the existing top-level architecture docs before adding a new file.\n- Put useful crate-specific details in the relevant crate `README.md`.\n- Add a new top-level architecture doc only when explicitly requested or when an RFC-level design needs a stable home.\n- Keep architecture docs focused on stable boundaries, data/control flow, invariants, and operational constraints.\n- Remove stale detail instead of preserving it by default.\n- Do not include testing transcripts, historical debugging notes, long source-file inventories, or field-by-field schema references.\n- Put user-facing instructions in `docs/`, broad design proposals in `rfc/`, and temporary plans in ignored `architecture/plans/`.\n\n## Security\n\n- Never commit secrets, API keys, or credentials. If a file looks like it contains secrets (`.env`, `credentials.json`, etc.), do not stage it.\n- Do not run destructive operations (force push, hard reset, database drops) without explicit human confirmation.\n- Scope changes to the issue at hand. Do not make unrelated changes in the same branch.\n","category":"root","tokens":4986},{"name":"SKILL.md","path":"crates/openshell-supervisor-process/src/skills/policy-advisor/SKILL.md","title":"policy-advisor Skill","content":"---\nname: openshell-policy-advisor\ndescription: Use when an OpenShell sandbox returns policy_denied, mentions policy.local, or needs a narrow network policy proposal.\n---\n\n# OpenShell Policy Advisor\n\nWhen a request fails with `policy_denied`, do not treat the denial as final if the user task still needs the request. Read `/etc/openshell/skills/policy_advisor.md`, inspect `http://policy.local/v1/policy/current`, submit the narrowest proposal to `http://policy.local/v1/proposals`, wait on `/v1/proposals/{chunk_id}/wait?timeout=300`, and retry only after approval with `policy_reloaded: true`.\n","category":"crates","tokens":150},{"name":"SKILL.md","path":".agents/skills/watch-github-actions/SKILL.md","title":"watch-github-actions Skill","content":"---\nname: watch-github-actions\ndescription: Watch and monitor GitHub Actions workflow runs using the gh CLI. Use when the user wants to check workflow status, watch a running workflow, view CI/CD jobs, or monitor build progress. Trigger keywords - watch pipeline, pipeline status, CI status, check build, monitor CI, view pipeline, pipeline progress, workflow status, actions status.\n---\n\n# Watch GitHub Actions\n\nMonitor GitHub Actions workflow runs using the `gh` CLI.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Quick Status Check\n\nList recent workflow runs for the current branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nList all recent runs:\n\n```bash\ngh run list\n```\n\n## Watch a Run in Real Time\n\nWatch a workflow run until it completes:\n\n```bash\ngh run watch\n```\n\nWatch a specific run:\n\n```bash\ngh run watch <run-id>\n```\n\nThis will continuously update the status until the run finishes (success, failure, or cancelled).\n\n## View Run Details\n\nView a specific run with job details:\n\n```bash\ngh run view <run-id>\n```\n\nView with full log output:\n\n```bash\ngh run view <run-id> --log\n```\n\nView a failed job's log:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Check Runs for a Specific Branch\n\nCurrent branch:\n\n```bash\ngh run list --branch \"$(git branch --show-current)\"\n```\n\nSpecific branch:\n\n```bash\ngh run list --branch main\ngh run list --branch feature-branch\n```\n\n## Check Runs for a PR\n\nList workflow runs associated with a PR:\n\n```bash\n# Get the head branch of the PR, then list runs\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\"\n```\n\nOr view the checks directly on the PR:\n\n```bash\ngh pr checks <pr-number>\n```\n\n## List Recent Runs\n\nList runs for the current project:\n\n```bash\ngh run list\n```\n\nFilter by status:\n\n```bash\ngh run list --status failure\ngh run list --status success\ngh run list --status in_progress\n```\n\nFilter by workflow:\n\n```bash\ngh run list --workflow \"CI\"\n```\n\nJSON output for scripting:\n\n```bash\ngh run list --json databaseId,status,headBranch,url --jq '.[] | {id: .databaseId, status: .status, branch: .headBranch, url: .url}'\n```\n\n## View Job Logs\n\nView logs for a specific run:\n\n```bash\ngh run view <run-id> --log\n```\n\nView only failed job logs:\n\n```bash\ngh run view <run-id> --log-failed\n```\n\n## Wait for Run Completion (Scripting)\n\nWatch and wait for a run to complete:\n\n```bash\nRUN_ID=$(gh run list --branch \"$(git branch --show-current)\" --limit 1 --json databaseId --jq '.[0].databaseId')\ngh run watch \"$RUN_ID\" --exit-status\necho \"Run finished with exit code: $?\"\n```\n\n## Open Run in Browser\n\nOpen the latest run in your default browser:\n\n```bash\ngh run view --web\n```\n\nOpen a specific run:\n\n```bash\ngh run view <run-id> --web\n```\n\n## Rerun Failed Jobs\n\nRerun all failed jobs in a run:\n\n```bash\ngh run rerun <run-id> --failed\n```\n\nRerun an entire run:\n\n```bash\ngh run rerun <run-id>\n```\n\n## Useful Commands Reference\n\n| Command                             | Description                             |\n| ----------------------------------- | --------------------------------------- |\n| `gh run list`                       | List recent workflow runs               |\n| `gh run list --branch <branch>`     | List runs for a specific branch         |\n| `gh run list --status failure`      | List failed runs                        |\n| `gh run watch`                      | Watch latest run until completion       |\n| `gh run watch <run-id>`             | Watch a specific run until completion   |\n| `gh run view <run-id>`              | View run details and job list           |\n| `gh run view <run-id> --log`        | View full run logs                      |\n| `gh run view <run-id> --log-failed` | View only failed job logs               |\n| `gh run view --web`                 | Open run in browser                     |\n| `gh run rerun <run-id>`             | Rerun a workflow run                    |\n| `gh run rerun <run-id> --failed`    | Rerun only failed jobs                  |\n| `gh run cancel <run-id>`            | Cancel a running workflow               |\n| `gh pr checks <pr-number>`          | View PR check statuses                  |\n\n## Common Flags\n\n| Flag               | Description                                    |\n| ------------------- | ---------------------------------------------- |\n| `-b, --branch`     | Specify branch (default: current branch)       |\n| `--status`         | Filter by status (queued, in_progress, etc.)   |\n| `--workflow`       | Filter by workflow name                        |\n| `-L, --limit`      | Maximum number of runs to list                 |\n| `-w, --web`        | Open in browser                                |\n| `--json`           | Output as JSON with specified fields           |\n| `--jq`             | Filter JSON output with jq expression          |\n\n## Example Workflow\n\n1. Push your changes and create/update a PR\n2. Watch the workflow run:\n   ```bash\n   gh run watch\n   ```\n3. If a job fails, view the failed logs:\n   ```bash\n   gh run view <run-id> --log-failed\n   ```\n4. Rerun the failed jobs if needed:\n   ```bash\n   gh run rerun <run-id> --failed\n   ```\n","category":".agents","tokens":1310},{"name":"SKILL.md","path":".agents/skills/update-docs/SKILL.md","title":"update-docs Skill","content":"---\nname: update-docs-from-commits\ndescription: Scan recent git commits for changes that affect user-facing behavior, then draft or update the corresponding documentation pages. Use when docs have fallen behind code changes, after a batch of features lands, or when preparing a release. Trigger keywords - update docs, draft docs, docs from commits, sync docs, catch up docs, doc debt, docs behind, docs drift.\n---\n\n# Update Docs from Commits\n\nScan recent git history for commits that affect user-facing behavior and draft documentation updates for each.\n\n## Prerequisites\n\n- You must be in the OpenShell git repository.\n- The published docs tree must exist under `docs/`.\n- Read `docs/CONTRIBUTING.mdx` before writing any content. It contains the current style guide and formatting rules.\n\n## When to Use\n\n- After a batch of features or fixes has landed and docs may be stale.\n- Before a release, to catch any doc gaps.\n- When a contributor asks \"what docs need updating?\"\n\n## Step 1: Identify Relevant Commits\n\nDetermine the commit range. The user may provide one explicitly (e.g., \"since v0.2.0\" or \"last 30 commits\"). If not, default to commits since the head of the main branch.\n\n```bash\n# Commits since a tag\ngit log v0.2.0..HEAD --oneline --no-merges\n\n# Or last 50 commits\ngit log -50 --oneline --no-merges\n```\n\nFilter to commits that are likely to affect docs. Look for these signals:\n\n1. **Commit type**: `feat`, `fix`, `refactor`, `perf` commits often change behavior. `docs` commits are already doc changes. `chore`, `ci`, `test` commits rarely need doc updates.\n2. **Files changed**: Changes to `crates/openshell-cli/`, `python/`, `proto/`, `deploy/`, gateway config parsing, driver config structs, or policy-related code are high-signal.\n3. **Ignore**: Changes limited to `tests/`, `e2e/`, `.github/`, `tasks/`, or internal-only modules.\n\n```bash\n# Show files changed per commit to assess impact\ngit log v0.2.0..HEAD --oneline --no-merges --name-only\n```\n\n## Step 2: Map Commits to Doc Pages\n\nFor each relevant commit, determine which doc page(s) it affects. Use this mapping as a starting point:\n\n| Code area | Likely doc page(s) |\n|---|---|\n| `crates/openshell-cli/` (gateway commands) | `docs/sandboxes/manage-gateways.mdx` |\n| `crates/openshell-cli/` (sandbox commands) | `docs/sandboxes/manage-sandboxes.mdx` |\n| `crates/openshell-cli/` (provider commands) | `docs/sandboxes/manage-providers.mdx` |\n| `crates/openshell-cli/` (new top-level command) | May need a new page or `docs/reference/` entry |\n| `crates/openshell-server/src/config_file.rs` or gateway TOML parsing | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-server/src/cli.rs` gateway config merge/default behavior | `docs/reference/gateway-config.mdx` |\n| `crates/openshell-driver-*/` config structs or driver defaults | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx` |\n| `deploy/helm/openshell/templates/gateway-config.yaml` | `docs/reference/gateway-config.mdx`, `docs/reference/sandbox-compute-drivers.mdx`, Helm docs if values change |\n| Proxy or policy code | `docs/sandboxes/policies.mdx`, `docs/reference/policy-schema.mdx` |\n| Inference code | `docs/inference/configure.mdx` |\n| `python/` (SDK changes) | `docs/reference/` or `docs/get-started/quickstart.mdx` |\n| `proto/` (API changes) | `docs/reference/` |\n| `deploy/` (Dockerfile, Helm) | `docs/sandboxes/manage-gateways.mdx`, `docs/about/architecture.mdx` |\n| Community sandbox definitions | `docs/sandboxes/community-sandboxes.mdx` |\n\nIf a commit does not map to any existing page but introduces a user-visible concept, flag it as needing a new page.\n\n## Step 3: Read the Commit Details\n\nFor each commit that needs a doc update, read the full diff to understand the change:\n\n```bash\ngit show <commit-hash> --stat\ngit show <commit-hash>\n```\n\nExtract:\n\n- What changed (new flag, renamed command, changed default, new feature).\n- Why it changed (from the commit message body, linked issue, or PR description).\n- Any breaking changes or migration steps.\n\n## Step 4: Read the Current Doc Page\n\nBefore editing, read the full target doc page to understand its current content and structure:\n\n```bash\n# Read the file\n```\n\nIdentify where the new content should go. Follow the page's existing structure.\n\n## Step 5: Draft the Update\n\nWrite the doc update following the rules in `docs/CONTRIBUTING.mdx`. Key reminders:\n\n- **Active voice, present tense, second person.**\n- **No unnecessary bold.** Reserve bold for UI labels and parameter names.\n- **No em dashes** unless used sparingly. Prefer commas or separate sentences.\n- **Start sections with an introductory sentence** that orients the reader.\n- **No superlatives.** Say what the feature does, not how great it is.\n- **Code examples use `shell` language** for copyable commands, with no `$` prompt prefix.\n- **Use `text` fences** for transcripts, logs, or shell sessions that should not be copied verbatim.\n- **Include the SPDX header as YAML comments in frontmatter** if creating a new page.\n- **Match existing Fern frontmatter format** if creating a new page, including `sidebar-title`, `keywords`, and `position` when they are relevant. Use frontmatter `slug` only for folder-discovered pages or absolute URL overrides.\n- **Use `sidebar-title` for short nav labels**. For explicit navigation entries, keep relative `slug` values in `docs/index.yml` instead of page frontmatter.\n- **Keep explicit `page:` entries in `docs/index.yml`**. Fern still requires them. If the page defines `sidebar-title`, set `page:` to that value. Otherwise set `page:` to the page frontmatter `title`.\n- **Use `skip-slug: true` in `docs/index.yml`** when a child page should live at the parent section path.\n- **Use `keywords` as a comma-separated string**.\n- **Do not add a duplicate H1**. Fern renders the page title from frontmatter.\n- **Always write NVIDIA in all caps.** Wrong: Nvidia, nvidia.\n- **Always capitalize OpenShell correctly.** Wrong: openshell, Openshell, openShell.\n- **Do not number section titles.** Wrong: \"Section 1: Deploy a Gateway\" or \"Step 3: Verify.\" Use plain descriptive titles.\n- **No colons in titles.** Wrong: \"Gateways: Deploy and Manage.\" Write \"Deploy and Manage Gateways\" instead.\n- **Use colons only to introduce a list.** Do not use colons as general-purpose punctuation between clauses.\n\nWhen updating an existing page:\n\n- Add content in the logical place within the existing structure.\n- Do not reorganize sections unless the change requires it.\n- Update any cross-references or \"Next Steps\" links if relevant.\n\nWhen creating a new page:\n\n- Follow the frontmatter template from `docs/CONTRIBUTING.mdx`.\n- Add the page to the appropriate section in `docs/index.yml`.\n\n## Step 6: Present the Results\n\nAfter drafting all updates, present a summary to the user:\n\n```\n## Doc Updates from Commits\n\n### Updated pages\n- `docs/sandboxes/manage-gateways.mdx`: Added `--gpu` flag documentation (from commit abc1234).\n- `docs/reference/policy-schema.mdx`: Updated network policy schema for new `tls_inspect` field (from commit def5678).\n\n### New pages needed\n- None (or list any new pages created).\n\n### Commits with no doc impact\n- `chore(deps): bump tokio` (abc1234) — internal dependency, no user-facing change.\n- `test(e2e): add gateway timeout test` (def5678) — test-only change.\n```\n\n## Step 7: Build and Verify\n\nAfter making changes, validate the Fern docs locally:\n\n```bash\nmise run docs\n```\n\nIf a human needs to inspect rendering while iterating, they can also run:\n\n```bash\nmise run docs:serve\n```\n\nCheck for:\n\n- Validation warnings or errors.\n- Broken cross-references.\n- Correct rendering of new content in the PR preview when available.\n\n## Tips\n\n- When in doubt about whether a commit needs a doc update, check if the commit message references a CLI flag, config option, or user-visible behavior.\n- Group related commits that touch the same doc page into a single update rather than making multiple small edits.\n- If a commit is a breaking change, add a note at the top of the relevant section using a Fern `<Warning>` callout.\n- PRs that are purely internal refactors with no behavior change do not need doc updates, even if they touch high-signal directories.\n\n## Example Usage\n\nUser says: \"Catch up the docs for everything merged since v0.2.0.\"\n\n1. Run `git log v0.2.0..HEAD --oneline --no-merges --name-only`.\n2. Filter to `feat`, `fix`, `refactor`, `perf` commits touching user-facing code.\n3. Map each to a doc page.\n4. Read the commit diffs and current doc pages.\n5. Draft updates following the style guide.\n6. Present the summary.\n7. Run `mise run docs` to verify.\n","category":".agents","tokens":2158},{"name":"SKILL.md","path":".agents/skills/build-from-issue/SKILL.md","title":"build-from-issue Skill","content":"---\nname: build-from-issue\ndescription: Given a GitHub issue number, plan and implement the work described in the issue. Supports direct user requests and unattended queue processing through the `agent:*` workflow labels. Includes tests, documentation updates, and PR creation. Trigger keywords - build from issue, implement issue, work on issue, build issue, start issue.\n---\n\n# Build From Issue\n\nPlan, iterate on feedback, and implement work described in a GitHub issue.\n\nThis skill operates as a stateful workflow — it can be run repeatedly against the same issue. Each invocation inspects the issue's labels, plan comment, and conversation history to determine the correct next action.\n\n## Prerequisites\n\n- The `gh` CLI must be authenticated (`gh auth status`)\n- You must be in a git repository with a GitHub remote\n\n## Invocation and Authorization\n\nThis skill supports two invocation modes:\n\n- **Direct mode:** A user explicitly asks the agent to plan or implement a specific issue. The request itself authorizes the requested phase; the corresponding `agent:*` request label is not required.\n- **Queue mode:** An always-on or unattended agent scans for work without a live user directing it to a specific issue. In this mode, `agent:plan-requested` authorizes planning and `agent:implementation-requested` authorizes implementation.\n\nA direct request authorizes only what it says. A request to review or plan does not authorize implementation. A request to build, implement, or work on an issue authorizes both the planning needed to perform the work and implementation unless the user asks to stop after planning.\n\nThe two request labels remain human-only queue controls. Under **no circumstances** should this skill or any agent apply them, ask to apply them, or suggest automating their application.\n\nDo not refuse a direct user request merely because its request label is absent. If direct work begins on an issue that was not already in the label-driven workflow, do not introduce `agent:in-progress` or `agent:pr-opened` solely for that invocation. If a matching request label is present, preserve the existing label transitions so unattended agents can track the workflow.\n\n## Agent Comment Markers\n\nThis skill uses two distinct markers to identify its comments:\n\n### Plan marker\n\nThe implementation plan lives in a **single comment** that is edited in place as the plan evolves. It is identified by this marker on its first line:\n\n```\n> **🏗️ build-plan**\n```\n\n### Conversation marker\n\nAll other comments (responses to human feedback, status updates, PR announcements) use this marker:\n\n```\n> **🏗️ build-from-issue-agent**\n```\n\nThese markers distinguish agent comments from human comments and from other skills (e.g., `🔒 security-review-agent`, `🔧 security-fix-agent`).\n\n## State Machine Overview\n\nEach invocation follows this decision tree:\n\n```\nFetch issue + comments\n  │\n  ├─ topic:security present?\n  │   → Route to review-security-issue or fix-security-issue; STOP\n  │\n  ├─ Triage incomplete, awaiting information, or awaiting human disposition?\n  │   → Report the blocking state and STOP\n  │\n  ├─ state:accepted and roadmap association both absent?\n  │   → Human has not accepted the issue; STOP\n  │\n  ├─ No plan comment and no direct planning request and agent:plan-requested absent?\n  │   → No request for agent planning; STOP\n  │\n  ├─ No plan comment + direct planning request or agent:plan-requested present?\n  │   → Generate plan via principal-engineer-reviewer\n  │   → Post plan comment\n  │   → Advance labels only for a label-driven invocation\n  │   → Continue if the direct request also authorized implementation; otherwise STOP\n  │\n  ├─ Plan exists + new human comments since last agent response?\n  │   → Respond to each comment (quote context, address feedback)\n  │   → Update the plan comment if feedback requires plan changes\n  │   → STOP\n  │\n  ├─ Plan exists + direct implementation request or 'agent:implementation-requested' label?\n  │   → Run scope check (warn if high complexity)\n  │   → Check for conflicting branches/PRs\n  │   → BUILD (Steps 6–14)\n  │\n  ├─ 'agent:in-progress' label present?\n  │   → Detect existing branch and resume if possible\n  │   → Otherwise report current state\n  │\n  ├─ 'agent:pr-opened' label present?\n  │   → Report that PR already exists, link to it\n  │   → STOP\n  │\n  └─ Plan exists + no new comments + neither a direct implementation request nor 'agent:implementation-requested'?\n      → Report: \"Plan is posted and awaiting review. No new comments to address.\"\n      → STOP\n```\n\n## Step 1: Fetch the Issue\n\nThe user provides an issue ID (e.g., `#42` or `42`). Strip any leading `#` and fetch:\n\n```bash\ngh issue view <id> --json number,title,body,state,labels,author\n```\n\nIf the issue is closed, report that and stop.\n\nIf `topic:security` is present, stop. General build agents must not plan or implement security issues. Route planning/review to `review-security-issue` and authorized remediation to `fix-security-issue`.\n\nStop before planning in any of these states:\n\n- `state:triage-needed`: the issue has not been assessed; use `triage-issue`.\n- `state:needs-info`: triage is waiting for evidence from the reporter.\n- `state:validated` without roadmap placement: triage is complete, but a human has not yet decided whether OpenShell should invest in the work.\n\nNext, require a human acceptance signal: either `state:accepted` or placement on the roadmap. The label records acceptance without requiring scheduling; roadmap placement records acceptance and sequencing. If no plan exists, require either a direct user request for planning or the human-applied `agent:plan-requested` label before generating one. Never add or remove `state:accepted`, either human request label, or the `roadmap` label.\n\n## Step 2: Fetch and Classify Comments\n\nFetch all comments:\n\n```bash\ngh issue view <id> --json comments --jq '.comments[] | {id: .id, body: .body, author: .author.login, createdAt: .createdAt, updatedAt: .updatedAt}'\n```\n\nClassify each comment into one of:\n\n- **Plan comment**: body starts with `> **🏗️ build-plan**`\n- **Agent comment**: body starts with `> **🏗️ build-from-issue-agent**`\n- **Human comment**: everything else (not agent-marked)\n\nRecord the plan comment's `id` (needed for editing via API) and its `updatedAt` timestamp.\n\n## Step 3: Determine Action\n\nUsing the state machine above, determine what to do based on:\n\n1. Whether a plan comment exists\n2. Whether there are human comments newer than the last agent comment (plan or conversation)\n3. Whether this is direct mode and which phase the user requested\n4. Which disposition, roadmap, and agent-workflow labels are present (`state:accepted`, `agent:plan-requested`, `agent:plan-ready`, `agent:implementation-requested`, `agent:in-progress`, `agent:pr-opened`, and the `roadmap` label)\n\nFollow the appropriate branch below.\n\n---\n\n## Branch A: Generate the Plan\n\nIf no plan comment exists, generate one when the user directly requested planning or implementation, or when `agent:plan-requested` is present. Otherwise report that no one has requested agent planning and stop.\n\n### A1: Analyze the Issue with Principal Engineer Reviewer\n\nPass the issue title, description, labels, and any relevant code references to the `principal-engineer-reviewer` sub-agent. Use the Task tool:\n\n```\nTask tool with subagent_type=\"principal-engineer-reviewer\"\n```\n\nIn the prompt, instruct the reviewer to:\n\n1. Read the issue's user story and identify what needs to change in the codebase. Treat reporter diagnostics or solution ideas as optional context, not as authoritative or current analysis.\n2. Map the requirements to existing code — read the relevant source files.\n3. Determine the **issue type** — one of: `feat` (new feature), `fix` (bug fix), `refactor`, `chore`, `perf`, `docs`.\n4. Propose the minimal set of changes that satisfies the requirements.\n5. Sequence the work so each step is independently testable.\n6. Identify what tests are needed (unit, integration, e2e) and where they should live.\n7. Assess **complexity** on a scale:\n   - **Low**: Isolated change, < 3 files, clear path forward\n   - **Medium**: Multiple files/components, some design decisions, but well-scoped\n   - **High**: Cross-cutting changes, architectural decisions needed, significant unknowns\n8. Call out risks, unknowns, and decisions that need stakeholder input.\n9. Assess **gateway config documentation impact** — if the change adds, removes, renames, or changes defaults for gateway TOML keys or driver-specific config options, the plan must include an update to `docs/reference/gateway-config.mdx`. If the change is surfaced through Helm or a compute-driver overview, also include `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment docs.\n10. Assess **LSM compatibility** — if the change touches process identity, `/proc` filesystem access, binary execution, or inter-process visibility, flag whether it will behave differently on hosts running SELinux (enforcing) or AppArmor. In particular, tests that fork+exec into system binaries will fail on SELinux-enforcing hosts due to cross-label `/proc/<pid>/exe` access restrictions.\n\nPerform this investigation against the current branch and current product behavior. If the issue contains earlier diagnostics, verify them rather than relying on them.\n\n### A2: Post the Plan Comment\n\nPost the plan as a comment on the issue. This is the **canonical plan comment** that will be edited in place as the plan evolves.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n**Issue type:** `<feat|fix|refactor|chore|perf|docs>`\n**Complexity:** <Low|Medium|High>\n**Confidence:** <High — clear path | Medium — some unknowns | Low — needs discussion>\n\n### Summary\n<2-3 sentences describing what will be built/changed and the approach>\n\n### Scope\n- `<file1>`: <what changes and why>\n- `<file2>`: <what changes and why>\n- ...\n\n### Implementation Steps\n1. <step 1 — independently testable>\n2. <step 2>\n3. ...\n\n### Test Plan\n- **Unit tests:** <what will be tested and where the tests live>\n- **Integration tests:** <what will be tested, or \"N/A\" with rationale>\n- **E2E tests:** <what will be tested, or \"N/A\" with rationale>\n\n### Risks & Open Questions\n- <risk or unknown that may need human input>\n\n### Documentation Impact\n- <docs expected per AGENTS.md, or \"None expected\">\n\n---\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\n### A3: Mark the Plan Ready in Queue Mode\n\nIf `agent:plan-requested` was present, replace it with `agent:plan-ready`. Do not add `agent:plan-ready` for a direct invocation that was not already using the label workflow.\n\n```bash\ngh issue edit <id> --remove-label \"agent:plan-requested\" --add-label \"agent:plan-ready\"\n```\n\nIf the direct request authorized implementation, continue to Branch C. Otherwise report that the plan has been posted and stop. In queue mode, a human reviews the plan and applies `agent:implementation-requested` before an unattended agent can build.\n\n---\n\n## Branch B: Respond to Feedback\n\nIf a plan exists and there are human comments newer than the last agent response, address them.\n\n### B1: Process Each Unanswered Human Comment\n\nFor each human comment that is newer than the most recent agent comment (plan `updatedAt` or conversation comment `createdAt`):\n\n1. Read the comment.\n2. Quote the relevant portion using `>` blockquote syntax.\n3. Formulate a response based on the codebase and the current plan.\n4. Post a response with the conversation marker.\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n> <quoted portion of human's comment>\n\n<response addressing the feedback>\nEOF\n)\"\n```\n\n### B2: Update the Plan if Needed\n\nIf any feedback requires changes to the plan, **edit the existing plan comment** rather than posting a new one. Use the GitHub API with the comment's node ID:\n\n```bash\ngh api graphql -f query='\n  mutation {\n    updateIssueComment(input: {id: \"<comment-node-id>\", body: \"<updated body>\"}) {\n      issueComment { id }\n    }\n  }\n'\n```\n\nOr use the REST API:\n\n```bash\ngh api repos/{owner}/{repo}/issues/comments/<comment-id> -X PATCH -f body=\"$(cat <<'EOF'\n> **🏗️ build-plan**\n\n## Implementation Plan\n\n<... updated plan content ...>\n\n---\n*Revision <N> — <brief description of what changed>*\n*Revision <N-1> — <previous change>*\n*Revision 1 — initial plan*\nEOF\n)\"\n```\n\nPreserve the full revision history at the bottom so readers can track how the plan evolved.\n\nReport to the user what feedback was addressed and whether the plan was updated. Stop.\n\n---\n\n## Branch C: Build\n\nProceed with implementation when the plan exists and either the user directly requested implementation or `agent:implementation-requested` is present. An existing `agent:in-progress` or `agent:pr-opened` label still triggers the resume or existing-PR checks below.\n\n### Step 4: Scope Check\n\nRead the plan comment and check the **Complexity** and **Confidence** fields.\n\n- **If Complexity is High or Confidence is Low**, warn the user:\n\n  > \"This issue is rated High complexity / Low confidence. The plan includes open questions that may need human decisions during implementation. Proceeding, but flagging this for your awareness.\"\n\n  Continue — do not hard-stop. The user directly requested implementation or chose to apply `agent:implementation-requested`.\n\n### Step 5: Conflict Detection\n\nBefore creating a branch, check for conflicts:\n\n#### Check for existing branches\n\n```bash\ngit fetch origin\ngit branch -r | grep -i \"<issue-id>\"\n```\n\nIf a remote branch referencing this issue ID exists, report it and ask the user whether to continue on that branch or abort.\n\n#### Check for existing PRs\n\n```bash\ngh pr list --state open --search \"Closes #<issue-id>\" --json number,title,url\n```\n\nIf an open PR already references this issue, report it and stop. Do not create a competing PR.\n\n### Step 6: Create Branch\n\nDetermine the branch prefix from the issue type in the plan:\n\n| Issue type | Branch prefix |\n| --- | --- |\n| `feat` | `feat/` |\n| `fix` | `fix/` |\n| `refactor` | `refactor/` |\n| `chore` | `chore/` |\n| `perf` | `perf/` |\n| `docs` | `docs/` |\n\nGet the current username and create the branch:\n\n```bash\nUSERNAME=$(gh api user --jq '.login')\ngit checkout main\ngit pull origin main\ngit checkout -b <prefix><issue-id>-<short-description>/$USERNAME\n```\n\n### Step 7: Mark Queue Work In Progress\n\nIf `agent:implementation-requested` is present, replace it and `agent:plan-ready` with `agent:in-progress`. In direct mode without a request label, do not add an agent-workflow label.\n\n```bash\ngh issue edit <id> --remove-label \"agent:implementation-requested\" --remove-label \"agent:plan-ready\" --add-label \"agent:in-progress\"\n```\n\n### Step 8: Implement the Changes\n\nFollow the implementation steps from the plan. Principles:\n\n- **Follow the plan**: The plan was reviewed and approved. Stick to it unless you discover something that requires deviation.\n- **Minimal scope**: Only change what the plan calls for. No unrelated refactors.\n- **If you must deviate**: Note the deviation — it will be included in the PR description.\n\nRead the relevant source files before making changes. Implement step by step per the plan's sequence.\n\n### Step 9: Write Tests\n\nWrite tests as specified in the plan's Test Plan section. Follow the project's existing test conventions.\n\n#### Unit tests\n\n- Place alongside existing tests for the module (e.g., `#[cfg(test)]` blocks in Rust, `test_*.py` for Python)\n- Cover the new/changed behavior, edge cases, and error paths\n- Ensure pre-existing behavior still works\n\n#### Integration tests\n\n- Place in the project's existing integration test directories\n- Cover interactions between the changed components\n- Test realistic scenarios including error conditions\n\n#### E2E tests\n\n- Only if the plan calls for them\n- Cover the full user-facing workflow affected by the change\n\n#### Test naming\n\nUse descriptive names that document intent:\n- `test_pagination_returns_correct_page_count`\n- `test_rejects_negative_offset_parameter`\n- `test_retry_succeeds_after_transient_failure`\n\n### Step 10: Verify — Tests, Lint, Pre-commit (Retry Loop)\n\nVerification has two phases: unit tests + pre-commit, then E2E tests (if applicable). Run with up to **3 attempts per phase**.\n\n#### Phase 1: Unit Tests and Pre-commit\n\nOn each attempt:\n\n```bash\n# Run pre-commit checks (linting, formatting, license headers)\nmise run pre-commit\n```\n\n**If verification fails:**\n\n1. Read the error output carefully.\n2. Fix the issues (test failures, lint errors, formatting).\n3. Decrement the retry counter and try again.\n\n**If all 3 attempts fail**, stop and report to the user:\n- What passed and what failed\n- The specific errors from the last attempt\n- That manual intervention is needed\n\nDo not proceed to Phase 2 or PR creation if Phase 1 is not green.\n\n#### Phase 2: E2E Tests (Conditional)\n\n**Trigger**: Run this phase if any files under `e2e/` were added or modified in this build. Check with:\n\n```bash\ngit diff --name-only main -- e2e/\n```\n\nIf there are no changes under `e2e/`, skip this phase entirely.\n\nIf E2E files were modified, run the relevant E2E lane for the driver touched by the change:\n\n```bash\n# Docker-backed gateway smoke E2E\nmise run e2e:docker\n```\n\nUse `mise run e2e:podman`, `mise run e2e:vm`, or a Helm-backed Kubernetes E2E lane when the change targets those drivers.\n\n**E2E retry loop** (up to 3 attempts):\n\n1. Run the selected E2E lane.\n2. If tests fail:\n   - Read the pytest output carefully — identify which tests failed and why.\n   - Distinguish between **test bugs** (the test itself is wrong) and **implementation bugs** (the code under test is wrong).\n   - Fix the failing code or tests.\n   - Decrement the retry counter and try again.\n3. If tests pass, Phase 2 is green.\n\n**If all 3 E2E attempts fail**, stop and report to the user:\n- Which E2E tests are failing\n- The pytest output from the last attempt\n- Whether the failures appear to be test issues or implementation issues\n- That manual intervention is needed\n\nDo not proceed to PR creation if E2E verification is not green.\n\n### Step 11: Update Documentation\n\nReview the documentation requirements in `AGENTS.md` and update any affected\ndocs as part of the implementation. Keep documentation changes scoped to the\nbehavior or subsystem that changed.\n\nIf the implementation changes gateway TOML parsing, `[openshell.gateway]`\nfields, `[openshell.drivers.<name>]` fields, driver config defaults, or Helm\nrendering of `gateway.toml`, update `docs/reference/gateway-config.mdx` in the\nsame branch. If the change affects user-facing compute-driver setup, also\nupdate `docs/reference/sandbox-compute-drivers.mdx` or the relevant deployment\npage.\n\nUse the `sync-agent-infra` skill's maintenance map to identify related skill updates when the implementation changes behavior, commands, or development workflows. Run its full consistency check when the implementation adds, removes, or renames skills or crates; changes workflow relationships or skill coverage; modifies issue or PR templates; or changes agent cross-references. Fix any drift before committing.\n\n### Step 12: Commit and Push\n\nCommit all changes using conventional commit format. The `<type>` comes from the issue type in the plan:\n\n```bash\ngit add <files>\ngit commit -m \"$(cat <<'EOF'\n<type>(<scope>): <short description>\n\nCloses #<issue-id>\n\n<brief explanation of what was implemented>\nEOF\n)\"\n```\n\nPush:\n\n```bash\ngit push -u origin HEAD\n```\n\n### Step 13: Open PR\n\nCreate the PR:\n\n```bash\ngh pr create \\\n  --title \"<type>(<scope>): <short description>\" \\\n  --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Summary\n<1-3 sentences describing what was built and the approach taken>\n\n## Related Issue\nCloses #<issue-id>\n\n## Changes\n- `<file1>`: <what changed and why>\n- `<file2>`: <what changed and why>\n\n### Deviations from Plan\n<any deviations from the approved plan, or \"None — implemented as planned\">\n\n## Testing\n- [x] `mise run pre-commit` passes\n- [x] Unit tests added/updated\n- [x] E2E tests added/updated (if applicable)\n\n**Tests added:**\n- **Unit:** <test file(s) and what they cover>\n- **Integration:** <test file(s) and what they cover, or \"N/A\">\n- **E2E:** <test file(s) and what they cover, or \"N/A\">\n\n## Checklist\n- [x] Follows Conventional Commits\n- [x] Commits are signed off (DCO)\n\n**Documentation updated:**\n- `<doc path>`: <what was updated, or \"None needed\">\nEOF\n)\"\n```\n\n**Display the PR URL** so it's easily clickable:\n\n```\nCreated PR [#<number>](https://github.com/OWNER/REPO/pull/<number>)\n```\n\n### Step 14: Post-Build Cleanup\n\n#### Post summary comment on the issue\n\n```bash\ngh issue comment <id> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## Implementation Complete\n\nPR: [#<pr-number>](https://github.com/OWNER/REPO/pull/<pr-number>)\n\n### What was built\n<1-2 sentence summary>\n\n### Tests\n- Unit: <count> tests added\n- Integration: <count or N/A>\n- E2E: <count or N/A>\n\n### Docs updated\n- <list of updated docs, or \"None needed\">\n\nThe issue will auto-close when the PR is merged.\nEOF\n)\"\n```\n\n#### Post E2E attestation comment on the PR\n\nIf E2E tests were run in Phase 2 of Step 10, post an attestation comment on the **PR** documenting that local E2E tests passed. This is necessary because E2E tests are not yet running in CI — this comment serves as the verification record for reviewers.\n\nCollect the metadata before posting:\n\n```bash\n# Get the commit SHA that was tested\nCOMMIT_SHA=$(git rev-parse HEAD)\n\n# Get the test output summary (last few lines of pytest output)\n# This was captured during the Phase 2 run — include the pass/fail/skip counts\n```\n\nPost the attestation:\n\n```bash\ngh pr comment <pr-number> --body \"$(cat <<'EOF'\n> **🏗️ build-from-issue-agent**\n\n## E2E Test Attestation\n\nLocal E2E tests passed. CI does not currently run E2E tests, so this comment serves as the verification record.\n\n| Field | Value |\n|-------|-------|\n| **Commit** | `<commit-sha>` |\n| **Command** | `<selected e2e command>` |\n| **Gateway mode** | `<docker / podman / vm / helm>` |\n| **Result** | ✅ All passed |\n\n### Test Summary\n\n```\n<paste the pytest summary line, e.g.: \"12 passed, 1 skipped in 45.32s\">\n```\n\n### Tests Executed\n- `<test_file.py>::<test_name>` — PASSED\n- `<test_file.py>::<test_name>` — PASSED\n- ...\nEOF\n)\"\n```\n\nInclude **every test** that ran (not just the new ones) so the reviewer can see full coverage. If any tests were skipped, note them and explain why.\n\n#### Update labels\n\nIf `agent:in-progress` is present, replace it with `agent:pr-opened`. Do not add `agent:pr-opened` for an unlabeled direct invocation:\n\n```bash\ngh issue edit <id> --remove-label \"agent:in-progress\" --add-label \"agent:pr-opened\"\n```\n\n#### Report workflow run URL\n\nGet the workflow run URL from the PR so the user can monitor CI:\n\n```bash\nBRANCH=$(gh pr view <pr-number> --json headRefName --jq '.headRefName')\ngh run list --branch \"$BRANCH\" --limit 1 --json databaseId,status,url\n```\n\nReport the workflow run URL and suggest the user can use the `watch-github-actions` skill to monitor it.\n\n---\n\n## Branch D: Resume In-Progress Build\n\nIf the `agent:in-progress` label is present, the skill was previously started but may not have completed.\n\n1. Check for an existing branch matching the issue ID:\n   ```bash\n   git branch -r | grep -i \"<issue-id>\"\n   ```\n2. If found, check it out and inspect the state (are there uncommitted changes? committed but not pushed? pushed but no PR?).\n3. Resume from the appropriate step (9, 10, 12, or 13).\n4. If the state is unrecoverable, report to the user and suggest starting fresh. Queue mode requires a human to reapply `agent:implementation-requested`; a new direct implementation request can resume without it.\n\n---\n\n## Useful Commands Reference\n\n| Command | Description |\n| --- | --- |\n| `gh issue view <id> --json number,title,body,state,labels,author` | Fetch full issue metadata |\n| `gh issue view <id> --json comments` | Fetch all comments on an issue |\n| `gh issue comment <id> --body \"...\"` | Post a comment on an issue |\n| `gh api repos/{owner}/{repo}/issues/comments/<id> -X PATCH -f body=\"...\"` | Edit an existing comment |\n| `gh issue edit <id> --add-label \"...\"` | Add labels |\n| `gh issue edit <id> --remove-label \"...\"` | Remove labels |\n| `gh pr list --state open --search \"...\"` | Search for open PRs |\n| `gh pr create --title \"...\" --body \"...\"` | Create a pull request |\n| `gh api user --jq '.login'` | Get current GitHub username |\n| `mise run pre-commit` | Run pre-commit checks (lint, format, license headers) |\n| `mise run e2e:docker` | Run smoke E2E against a standalone Docker-backed gateway |\n| `mise run e2e:podman` | Run smoke E2E against a Podman-backed gateway |\n| `mise run e2e:vm` | Run smoke E2E against the VM compute driver |\n\n## Example Usage\n\n### First run — no plan exists\n\nUser says: \"Plan issue #42\"\n\n1. Fetch issue #42 — title: \"Add pagination to dataset list endpoint\"\n2. Confirm `state:accepted` with no blocking triage state; the user's direct request authorizes planning even if `agent:plan-requested` is absent\n3. Fetch comments — no `🏗️ build-plan` marker found\n4. Pass issue to `principal-engineer-reviewer` for analysis\n5. Reviewer produces a plan: feat type, Medium complexity, 3 implementation steps, unit + integration tests needed\n6. Post the plan comment with the `🏗️ build-plan` marker\n7. Because this direct invocation was unlabeled, leave the `agent:*` workflow labels unchanged\n8. Report to user: \"Plan posted on issue #42. Awaiting review.\"\n\n### Second run — human left feedback\n\nUser says: \"Check on issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find existing plan comment (Revision 1)\n3. Find new human comment: \"Should we also paginate the search endpoint?\"\n4. Post response quoting the question, explaining that search pagination is out of scope for this issue but could be a follow-up\n5. Report to user: \"Responded to feedback on #42. Plan unchanged.\"\n\n### Third run — human revised scope, plan needs update\n\nUser says: \"Check issue #42\"\n\n1. Fetch issue #42 and comments\n2. Find plan + new human comment: \"Actually, let's include search pagination. Updated the issue description.\"\n3. Post response acknowledging the scope change\n4. Edit the plan comment to include search endpoint pagination — Revision 2\n5. Report to user: \"Updated plan to include search pagination (Revision 2).\"\n\n### Fourth run — implementation requested\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists (Revision 2), complexity: Medium, confidence: High\n3. No conflicting branches or PRs\n4. Create branch `feat/42-add-pagination/jmyers`\n5. Leave `agent:*` labels unchanged because this direct invocation was not picked up from the queue\n6. Implement pagination for both endpoints per the plan\n7. Add unit tests for pagination logic, integration tests for both endpoints\n8. `mise run pre-commit` passes on first attempt\n9. E2E tests skipped (no changes under `e2e/`)\n10. Commit, push, create PR with `Closes #42`\n11. Post summary comment on issue with PR link\n12. No agent-workflow label transition is needed\n13. Report PR URL and workflow run status to user\n\n### Run on issue with existing PR\n\nUser says: \"Build issue #42\"\n\n1. Fetch issue #42 — `agent:pr-opened` label present\n2. Find existing PR #789 linked to the issue\n3. Report: \"PR [#789](...) already exists for issue #42. Nothing to build.\"\n\n### Run on high-complexity issue\n\nUser says: \"Build issue #99\"\n\n1. Fetch issue #99 — `state:accepted` is present; the user's direct request authorizes implementation\n2. Plan exists: complexity High, confidence Low, has open questions\n3. Warn user: \"Issue #99 is rated High complexity / Low confidence. Proceeding but flagging for your awareness.\"\n4. Continue with build\n","category":".agents","tokens":6956}]}