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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions .github/claude-code-pr-draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
## Summary

Add an experimental `claude-code` agent kit that runs Claude inside an acq
microVM using a configured OpenAI-shaped model provider, including USAi.

- Pinned SHA-256-verified Claude native binaries for Linux x64 and ARM64.
- Private authenticated, session-local LiteLLM bridge from Anthropic Messages
to OpenAI Chat Completions, with hash-locked wheel-only dependencies.
- Unprivileged installation, including pip bootstrap for guests without ensurepip.
- Claude-owned model catalog and explicit canonical-name substitutions; no
separate Paseo catalog projection or global user-config rewrite.
- Host TUI access and optional browser access through the separate Paseo kit.
- README warning: browser picker lists more choices than the configured
OpenAI-shaped model provider supports; tracked at getpaseo/paseo#8321.

Also consolidate repository CI into a four-kit matrix plus a Claude Python 3.12
lane, reusing pinned upstream Patterns validators rather than importing the
Patterns skill/index toolchain. Shared checks cover lint/format, ShellCheck,
contracts, local doc links and executable modes, tests, dependency audits,
unsafe-shell patterns, and secrets. CI uses read-only permissions, SHA-pinned
actions and checksum-pinned Gitleaks; no model credentials or VM execution.

## Verification

- Local `make check` passed with the pinned Patterns checkout and verified
Gitleaks executable; all four kits validated and the provider bundle validated.
- Claude offline suite: 27 passed / 3 explicitly gated live skips.
- Actual relocated Claude live/unit/lifecycle suite: 30 passed, with four
upstream Pydantic deprecation warnings.
- Actual CLI text, file tool/result continuation and real SDK canonical
Sonnet 5.5 model switch were exercised through USAi.
- Operator observed ARM64 MSB 0.7.7 installation, provider-root presence,
browser access, and Sonnet 5/5.5 calls from the acq Quickstart checkout.
- Independent adversarial review performed; reproducibility findings addressed.

GitHub Actions execution and local Python 3.12 execution remain unverified in
this session. Native x64 execution, backend mount enforcement, actual browser
permission/disconnect paths, and enterprise CA-specific validation remain live
gates. Offline x64 CI does not prove the native x64 Claude executable works.
See `claude-code/docs/verification.md` for history and limitations.

## Security and licensing

No credentials are stored in the kit, generated model settings, or CI.
Model routing comes from acq's backend-owned provider input; the proxy never
accepts client-supplied provider routing. Claude child environments have projected
provider credentials stripped, but this is defense in depth, not same-user
process isolation. The kit publishes no model API port and enables no permission
bypass. Optional Paseo browser exposure retains its separate trust boundary.

Kit provenance from the local CC0 Patterns worktree is recorded in `NOTICE`;
distribution uses this repository's MIT license. Claude Code remains proprietary,
and downloaded dependencies retain their own licenses.

## Rollback

Remove the kit reference and recreate the disposable test sandbox without it.
Existing Claude user settings and transcripts are not overwritten. Revert the
repository change to restore the former CI layout if needed.

## AI assistance

Implementation, tests, documentation, and independent reviews were AI-assisted.
The human operator performed the reported macOS/MSB/browser checks. Human review
is required before production use. No compliance or ATO assertion is made.
126 changes: 55 additions & 71 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,89 +9,73 @@ permissions:
contents: read

jobs:
test-and-validate:
kits:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
kit: [opencode-go-provider, pi-coding-agent, first-mate-skill, claude-code]
python: ["3.14"]
include:
- kit: claude-code
python: "3.12"
steps:
- name: Check out this repository
uses: actions/checkout@v4

- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: ${{ matrix.python }}
- name: Set up Node.js
uses: actions/setup-node@v4
if: matrix.kit == 'opencode-go-provider' || matrix.kit == 'pi-coding-agent'
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"
- name: Run kit's offline tests
env:
KIT: ${{ matrix.kit }}
run: python scripts/run-kit-tests.py "$KIT" --install

- name: Install kit test dependencies
working-directory: opencode-go-provider
run: npm ci

- name: Run kit tests
working-directory: opencode-go-provider
run: npm test

- name: Install pi agent-kit test dependencies
working-directory: pi-coding-agent
run: npm ci

- name: Run pi agent-kit tests
working-directory: pi-coding-agent
run: npm test

- name: Run pi agent-kit offline verification
run: bash pi-coding-agent/scripts/verify

- name: Run first-mate skill-kit offline verification
run: bash first-mate-skill/scripts/verify

- name: Set up Python
uses: actions/setup-python@v5
shared:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
python-version: "3.12"

- name: Install validator dependencies
run: python -m pip install --disable-pip-version-check jsonschema==4.26.0 PyYAML==6.0.3

- name: Check out the pinned patterns release
uses: actions/checkout@v4
persist-credentials: false
fetch-depth: 0
- name: Check out pinned Patterns validators
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
repository: GSA-TTS/agentic-coding-patterns
# Pinned to the release this kit was authored and validated against.
# Update deliberately together with the validator.
ref: a290d5d80737fc739e7ec139da0eeaf438631631
path: .patterns

- name: Validate agent-kit and skill-kit specs with the patterns validator (when present)
shell: bash
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.14"
- name: Install hash-locked shared tools
run: |
set -euo pipefail
validator=".patterns/integrations/isolation/acq-kits/validate-kits.py"
schema=".patterns/schemas/kit-hybrid-v1.schema.json"
if [ ! -f "$validator" ] || [ ! -f "$schema" ]; then
echo "Pinned patterns checkout predates the neutral kit validator;"
echo "the vendored kit-hybrid-v1 schema test in npm test is authoritative."
exit 0
fi
work="$(mktemp -d)"
mkdir -p "$work/schemas" "$work/integrations/isolation/acq-kits"
cp "$schema" "$work/schemas/"
printf 'schemaVersion: "acq-kits-registry/v1"\nkits:\n' \
> "$work/integrations/isolation/acq-kits/kits.yaml"
for name in pi-coding-agent first-mate-skill; do
kit="$work/integrations/isolation/acq-kits/$name"
mkdir -p "$kit"
cp "$name/spec.yaml" "$name/README.md" "$kit/"
cp -R "$name/files" "$kit/files"
printf ' %s:\n backends: [sbx, msb]\n parity: CI validation entry.\n' "$name" \
>> "$work/integrations/isolation/acq-kits/kits.yaml"
done
python "$validator" --root "$work" --strict

- name: Validate provider input with a patched credential binding
python -m venv .tmp/ci-venv
.tmp/ci-venv/bin/python -m pip install --disable-pip-version-check --require-hashes --only-binary=:all: -r requirements-dev.lock
- name: Lint, format, infrastructure tests, and all kit contracts
run: |
make lint validate
.tmp/ci-venv/bin/python -m pytest scripts/tests -q
- name: Install checksum-pinned Gitleaks (no action token or license)
shell: bash
run: |
set -euo pipefail
mkdir -p .tmp
python -c 'import json; source = ".patterns/integrations/isolation/schemas/provider-credential-bindings.json"; bindings = json.load(open(source, encoding="utf-8")); bindings["providers"]["opencode-go"] = "OPENCODE_GO_API_KEY"; json.dump(bindings, open(".tmp/provider-credential-bindings.json", "w", encoding="utf-8"), indent=2)'
python .patterns/scripts/validate_provider_input_contract.py \
--schema-dir .patterns/integrations/isolation/schemas \
--credential-bindings .tmp/provider-credential-bindings.json \
--bundle opencode-go-provider/provider-input.json
mkdir -p .tmp/gitleaks
curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 --max-time 120 \
https://github.com/gitleaks/gitleaks/releases/download/v8.24.3/gitleaks_8.24.3_linux_x64.tar.gz \
-o .tmp/gitleaks/archive.tar.gz
echo '9991e0b2903da4c8f6122b5c3186448b927a5da4deef1fe45271c3793f4ee29c .tmp/gitleaks/archive.tar.gz' | sha256sum --check
tar -xzf .tmp/gitleaks/archive.tar.gz -C .tmp/gitleaks gitleaks
- name: Dependency audit, unsafe shell, and secrets scans
run: make security GITLEAKS="$PWD/.tmp/gitleaks/gitleaks"
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ tests/output/
.patterns/
.tmp/

# Python validation artifacts
__pycache__/
.pytest_cache/
.ruff_cache/

# OS noise
.DS_Store
Thumbs.db
Expand Down
35 changes: 35 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
PYTHON ?= python3
VENV ?= .tmp/ci-venv
PY := $(VENV)/bin/python
PATTERNS ?= .patterns
LINT_PATHS := scripts/validate-kits.py scripts/run-kit-tests.py scripts/tests claude-code/files claude-code/tests claude-code/scripts/test claude-code/scripts/verify
GITLEAKS ?= gitleaks

.PHONY: setup check lint test validate security
setup:
@if command -v uv >/dev/null 2>&1; then uv venv --python $(PYTHON) --seed $(VENV); else $(PYTHON) -m venv $(VENV); fi
$(PY) -m pip install --disable-pip-version-check --require-hashes --only-binary=:all: -r requirements-dev.lock
npm --prefix opencode-go-provider ci --ignore-scripts --no-audit --no-fund
npm --prefix pi-coding-agent ci --ignore-scripts --no-audit --no-fund

check: lint validate test security

lint:
$(PY) -m ruff check $(LINT_PATHS)
$(PY) -m ruff format --check $(LINT_PATHS)
shellcheck claude-code/files/home/.local/bin/claude

validate:
$(PY) scripts/validate-kits.py --patterns $(PATTERNS)

test:
$(PY) -m pytest scripts/tests -q
$(PY) scripts/run-kit-tests.py all

security:
$(PY) -m pip_audit --strict --require-hashes --disable-pip -r requirements-dev.lock
$(PY) -m pip_audit --strict --require-hashes --disable-pip -r claude-code/files/home/claude-code/requirements.lock
$(PY) $(PATTERNS)/scripts/scan_unsafe_shell.py claude-code
$(GITLEAKS) dir --redact --no-banner --log-level warn claude-code
$(GITLEAKS) dir --redact --no-banner --log-level warn scripts
$(GITLEAKS) git --redact --no-banner --log-level warn .
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ An agent kit is a `hybrid/v1` mixin that:

| Kit | Kind | Provides | Status |
| --- | --- | --- | --- |
| [`claude-code/`](claude-code/) | Agent | Pinned Claude Code + private Messages-to-Chat-Completions proxy for a configured OpenAI-shaped model provider | **Experimental** — operator-verified on ARM64 MSB; x64 execution pending; browser model picker overstates availability |
| [`opencode-go-provider/`](opencode-go-provider/) | Provider | OpenCode Go (`openai-compatible`) facts and a 19-model neutral catalog | **Preview** — blocked on the acq credential-binding addition |
| [`pi-coding-agent/`](pi-coding-agent/) | Agent | Pinned pi CLI + `~/.pi/agent/models.json` renderer | **Preview** — live verification pending acq PR 611 |
| [`first-mate-skill/`](first-mate-skill/) | Skill | The `paseo-first-mate` Agent Skill and two helper scripts, dropped into `~/.agents/skills` | Offline-verified; no live sandbox run |
Expand Down Expand Up @@ -113,6 +114,23 @@ first-mate-skill/ skill kit

New kits follow the same directory contract and get a row in the table above.

### Executable scripts on shared mounts

Shared host/microVM mounts can report filesystem permissions differently from
Git's recorded modes. Validation checks both declared executable payloads and
Git index entries for executable scripts, including normalizers and test/verify
entrypoints. An executable script must be staged with mode `100755`; checking
only `test -x` locally does not prove a fresh CI checkout will be executable.
For an intended executable, stage it and run
`git update-index --chmod=+x <script>`. Do not mark every file executable or
automatically change `core.fileMode` on mounts that do not preserve modes.
Validation reports mismatches and never changes permissions or the index.

The Claude Code kit can compose with the separate Patterns Paseo kit for browser
access. It does not include Paseo or write Paseo's model catalog. Its README
explains the [upstream picker limitation](https://github.com/getpaseo/paseo/issues/8321)
and which displayed choices can actually run through the configured provider.

## Using kits

Provider input is materialized **at sandbox create time only**. `acq kit apply`
Expand Down Expand Up @@ -163,6 +181,31 @@ reads the variable by name.

## Validating a kit

### Shared repository checks

All root directories containing `spec.yaml` are discovered by shared tooling.
CI runs a matrix over the four kits rather than repeating install/test steps;
Claude also runs on Python 3.12 and 3.14. Tests never receive model credentials
and do not launch VMs. The pinned Patterns checkout supplies contract validation,
not runtime kit configuration.

For local verification, prepare a checkout of Patterns at
`a290d5d80737fc739e7ec139da0eeaf438631631` in `.patterns` (or set the Make
variable `PATTERNS` to an existing checkout at that commit). Then run:

```bash
make setup
make check
```

`make setup` creates an isolated development environment and installs locked
Python tools and existing Node kit dependencies. `make check` runs scoped lint,
formatting, ShellCheck, all-kit contract validation, local documentation-link
and normalizer-mode checks, each kit's offline tests, dependency audits,
unsafe-shell checks, and secret scans. A missing validator or wrong
Patterns pin fails closed. Gitleaks, ShellCheck, and Node must be available; see the Makefile
for paths and overrides. Opt-in live Claude tests are separate from this command.

Provider kits are validated with the host-time contract validator from
`agentic-coding-patterns`:

Expand Down
11 changes: 11 additions & 0 deletions claude-code/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Claude Code kit provenance

This kit was initially developed with AI assistance in a local worktree of
GSA-TTS/agentic-coding-patterns, whose repository dedication is CC0-1.0.
It is distributed here under the repository's MIT license. No proprietary
Claude executable or third-party package source is vendored in this kit.

Claude Code is downloaded at installation time from Anthropic's distribution
and remains governed by Anthropic's terms. LiteLLM and other downloaded runtime
dependencies retain their respective licenses; the repository license does
not relicense those dependencies.
Loading
Loading