Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
406784b
feat: add fail-closed host-side execution observer export
bateau84 Oct 2, 2026
813d684
test: probe actual Code Mode boundaries with isolated deterministic p…
bateau84 Oct 2, 2026
22cecdf
test: report observed hook gaps without promoting diagnostic data
bateau84 Oct 2, 2026
16394ac
test: record all hook events to rule out filtered terminal gaps
bateau84 Oct 2, 2026
19f31aa
feat: add a pinned downstream Code Mode observation patch
bateau84 Oct 2, 2026
58c5d72
feat: connect runtime observations through an isolated capture profile
bateau84 Oct 3, 2026
a72db40
fix: restrict protected Code Mode networking and carry transport iden…
bateau84 Oct 3, 2026
c162941
feat: bind protected collection to verified launch snapshots
bateau84 Oct 3, 2026
9153cc3
docs: record protected connection evidence and Loom integration handoff
bateau84 Oct 3, 2026
a84260c
fix: seal protected collection with independent supervisor receipt
bateau84 Oct 3, 2026
17877f6
fix(ci): assert old-image rejection without failing healthy checks
bateau84 Oct 3, 2026
d34fa82
fix: retain truthful incomplete capture counts
bateau84 Oct 3, 2026
b6536ad
fix(ci): isolate experimental image publication
bateau84 Oct 3, 2026
ce7bd9e
fix: reject persistent image volumes before launch
bateau84 Oct 3, 2026
584795f
fix: enforce capture limits and version accounting
bateau84 Oct 3, 2026
e4b9c9d
feat(runtime): preserve eval:live host semantics
bateau84 Oct 3, 2026
8ac6377
test(runtime): align probe with image-owned observation seam
bateau84 Oct 3, 2026
3005bcd
test(runtime): separate native and inner observation controls
bateau84 Oct 3, 2026
a92473b
docs: record normal-invoke feasibility evidence
bateau84 Oct 3, 2026
4e0c71c
fix(runtime): observe native terminals at session boundary
bateau84 Oct 3, 2026
b2f8fcf
fix(runtime): match session-publisher patch anchor
bateau84 Oct 3, 2026
587161e
docs(runtime): define Loom normal-invoke observation contract
bateau84 Oct 3, 2026
8af99cc
docs: distinguish legacy observer candidate from eval:live seam
bateau84 Oct 3, 2026
171bf07
test(runtime): exercise real delegated sessions under invoke
bateau84 Oct 3, 2026
6bb753f
feat(provenance): prepare trusted signing and close delegated ancestr…
bateau84 Oct 3, 2026
9dd22c8
fix(review): isolate probe seeds and cover full workflow job IDs
bateau84 Oct 3, 2026
79da4e9
fix(review): require approved rebuild before Cosign signing
bateau84 Oct 3, 2026
37eea75
test(workflow): distinguish input name from pull-request trigger
bateau84 Oct 3, 2026
8ffece5
fix(review): cover invoke changes and fail cleanup closed
bateau84 Oct 3, 2026
a6ced1b
fix(review): make signer executable and cleanup ownership explicit
bateau84 Oct 3, 2026
2a1f299
feat: project evidence safely before runner output and clipping
bateau84 Oct 3, 2026
d2ce384
fix(review): protect abbreviated safety options and reconcile create …
bateau84 Oct 4, 2026
aee6708
feat(runtime): add disposable OpenCode state bootstrap
bateau84 Oct 4, 2026
20e5bbf
test(runtime): discriminate disposable bootstrap from RSP admission
bateau84 Oct 4, 2026
ee502d4
fix(runtime): attest the current OpenCode session schema
bateau84 Oct 4, 2026
78b9868
fix(safety): validate disposable state as protocol structure
bateau84 Oct 4, 2026
1942e48
fix(review): close remaining safety and signing gaps
bateau84 Oct 4, 2026
108c526
fix(safety): preserve fixed event status under incomplete policy
bateau84 Oct 4, 2026
946930f
fix(observer): reject embedded key encodings in forwarded env
bateau84 Oct 4, 2026
6266c8a
fix(runtime): reserve disposable state controls
bateau84 Oct 4, 2026
57b37c9
fix(safety): honor explicit disposable config roots
bateau84 Oct 4, 2026
d9600d8
fix(runtime): isolate expected-plugin preflight from disposable DB
bateau84 Oct 4, 2026
3e19187
test(runtime): expose synthetic disposable plugin-preflight failures
bateau84 Oct 4, 2026
a4d17a7
test(runtime): supply agent for expected-plugin disposable probe
bateau84 Oct 4, 2026
6cb2c70
test(safety): assert plugin activation at the correct boundary
bateau84 Oct 4, 2026
f04b183
fix(handoff): align env inventory and runtime probe triggers
bateau84 Oct 4, 2026
9245670
fix(safety): make projection absence and event omission total
bateau84 Oct 4, 2026
e8c62b6
fix(safety): make fallback projections validator-complete
bateau84 Oct 4, 2026
86860e3
fix(safety): bind package initializer into image provenance
bateau84 Oct 4, 2026
9474bec
test(signing): catch single-backslash escaped substitutions
bateau84 Oct 4, 2026
dda191b
test(workflow): fail closed on quoted jobs and cover new workflows
bateau84 Oct 4, 2026
03339e5
fix(test): parse only top-level workflow job keys
bateau84 Oct 4, 2026
bfebab2
fix(safety): accept Podman image config IDs without weakening preflight
bateau84 Oct 5, 2026
ff61143
fix(runtime): separate Code Mode dispatch from observer enablement
bateau84 Oct 5, 2026
2940ae4
fix(safety): rebase RSP image onto corrected eval.5 runtime
bateau84 Oct 5, 2026
4ba6169
fix(safety): omit unsupported escaped credential keys
bateau84 Oct 5, 2026
441f4f3
test(safety): cover deep escaped credential keys
bateau84 Oct 5, 2026
00b489b
test(safety): exercise deep-key omission at runner boundary
bateau84 Oct 5, 2026
002aba9
test(safety): exercise deep key through preserved tool input
bateau84 Oct 5, 2026
37cebb6
fix(evidence): omit recoverable deep credential representations
bateau84 Oct 5, 2026
8933b64
test: add evidence regression coverage
bateau84 Oct 5, 2026
d1a5b2a
test: scope deep representation sink assertion
bateau84 Oct 5, 2026
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
130 changes: 130 additions & 0 deletions .github/workflows/evidence-safety.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: Evidence safety boundaries

on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- container/**
- runner/**
- bin/opencode-eval-runner
- evidence-safety/**
- tests/test_evidence_safety*.py
- tests/integration/run_evidence_safety_probe.py
- tests/integration/run_podman_preflight_probe.py
- .github/workflows/evidence-safety.yml

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
build:
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Test source and build a separate opt-in image
run: |
mkdir evidence-safety-results
python3 -m unittest discover -s tests -p 'test_*.py' 2>&1 | tee evidence-safety-results/tests.txt
python3 -m py_compile container/*.py runner/*.py tests/integration/run_evidence_safety_probe.py tests/integration/run_podman_preflight_probe.py
git rev-parse HEAD > evidence-safety-results/source-commit.txt
sha256sum container/__init__.py container/evidence_safety.py container/invoke.py runner/safe_invoke.py runner/cli.py bin/opencode-eval-runner > evidence-safety-results/code.sha256
docker build -f evidence-safety/Containerfile \
--build-arg RUNNER_REVISION="$(git rev-parse HEAD)" \
--build-arg PACKAGE_INIT_SHA256="$(sha256sum container/__init__.py | cut -d' ' -f1)" \
--build-arg SAFETY_MODULE_SHA256="$(sha256sum container/evidence_safety.py | cut -d' ' -f1)" \
--build-arg INVOKE_SHA256="$(sha256sum container/invoke.py | cut -d' ' -f1)" \
-t evidence-safety:test .
docker save -o image.tar evidence-safety:test
git archive --format=tar HEAD > evidence-safety-results/source.tar
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: safety-image-${{ github.run_id }}-${{ github.run_attempt }}
path: image.tar
compression-level: 0
if-no-files-found: error
retention-days: 1
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
if: always()
with:
name: safety-source-${{ github.run_id }}-${{ github.run_attempt }}
path: evidence-safety-results/
if-no-files-found: error
retention-days: 14

publish:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
packages: write
outputs:
reference: ${{ steps.image.outputs.reference }}
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: safety-image-${{ github.run_id }}-${{ github.run_attempt }}
path: image-data
- name: Publish image bytes without executing the workload
id: image
env:
REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
[[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]
mkdir publication
docker load --input image-data/image.tar
printf '%s' "$REGISTRY_TOKEN" | docker login ghcr.io --username "$GITHUB_ACTOR" --password-stdin
trap 'docker logout ghcr.io' EXIT
tag="ghcr.io/bateau84/opencode-eval-runner:evidence-safety-${HEAD_SHA:0:12}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
docker tag evidence-safety:test "$tag"
docker push "$tag"
image="$(docker image inspect "$tag" --format '{{index .RepoDigests 0}}')"
[[ "$image" =~ ^ghcr\.io/bateau84/opencode-eval-runner@sha256:[0-9a-f]{64}$ ]]
printf '%s\n' "$image" > publication/image.txt
printf 'reference=%s\n' "$image" >> "$GITHUB_OUTPUT"
docker image inspect "$image" > publication/image-inspect.json
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: safety-publication-${{ github.run_id }}-${{ github.run_attempt }}
path: publication/
if-no-files-found: error
retention-days: 14

verify:
needs: [build, publish]
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- name: Exercise actual pre-output boundaries without real inference
env:
IMAGE: ${{ needs.publish.outputs.reference }}
run: |
docker pull "$IMAGE"
python3 tests/integration/run_evidence_safety_probe.py --image "$IMAGE" --output evidence-safety-results
podman --version
python3 tests/integration/run_podman_preflight_probe.py --image "$IMAGE" --output evidence-safety-results
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
if: always()
with:
name: safety-connection-${{ github.event.pull_request.head.sha }}-${{ github.run_attempt }}
path: evidence-safety-results/
if-no-files-found: error
retention-days: 14
186 changes: 186 additions & 0 deletions .github/workflows/local-runtime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
name: Normal-invoke runtime observation seam

on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- runtime-patches/**
- runner/cli.py
- runner/observer.py
- container/**
- bin/opencode-eval-runner
- tests/integration/run_capture_probe.py
- tests/integration/capture_probe.ts
- tests/test_workflow_boundaries.py
- .github/workflows/local-runtime.yml

permissions:
contents: read

defaults:
run:
shell: bash

jobs:
build:
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
repository: anomalyco/opencode
ref: cd9a14a6b688d4021bee381dfd39d2cef9c0f862
path: .runtime-source
persist-credentials: false
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: 1.4.2
- name: Apply exact downstream source patch
run: |
mkdir -p local-runtime-results
python3 -m py_compile runtime-patches/*.py
python3 runtime-patches/apply.py .runtime-source
git -C .runtime-source add -N packages/core/src/codemode/local-observation.ts packages/core/test/local-observation.test.ts
git -C .runtime-source diff --binary > local-runtime-results/runtime.patch
git rev-parse HEAD > local-runtime-results/runner-revision.txt
sha256sum runtime-patches/*.py runtime-patches/*.ts runtime-patches/Containerfile > local-runtime-results/patch-inputs.sha256
- name: Install pinned runtime dependencies
working-directory: .runtime-source
run: bun install --frozen-lockfile
- name: Test normal host-semantics observation source
run: |
root="$(mktemp -d "$RUNNER_TEMP/local-runtime-test.XXXXXX")"
mkdir -p "$root"/{home,config,data,state,cache,run}
HOME="$root/home" XDG_CONFIG_HOME="$root/config" XDG_DATA_HOME="$root/data" \
XDG_STATE_HOME="$root/state" XDG_CACHE_HOME="$root/cache" XDG_RUNTIME_DIR="$root/run" \
OPENCODE_DISABLE_AUTOUPDATE=1 bun test --cwd .runtime-source/packages/core --timeout 20000 test/local-observation.test.ts \
2>&1 | tee local-runtime-results/source-tests.txt
rm -rf "$root"
- name: Build the existing CLI with the local patch
working-directory: .runtime-source
env:
OPENCODE_VERSION: 2.0.18-eval.5
OPENCODE_CHANNEL: latest
run: |
bun run packages/cli/script/build.ts --skip-install --target=opencode-linux-x64 \
2>&1 | tee "$GITHUB_WORKSPACE/local-runtime-results/build.txt"
cp packages/cli/dist/cli-linux-x64/bin/opencode "$GITHUB_WORKSPACE/local-runtime-results/opencode"
sha256sum "$GITHUB_WORKSPACE/local-runtime-results/opencode" > "$GITHUB_WORKSPACE/local-runtime-results/binary.sha256"
- name: Build experimental image without replacing defaults
run: |
docker build -f runtime-patches/Containerfile \
--build-arg RUNNER_REVISION="$(git rev-parse HEAD)" \
-t local-observation:test local-runtime-results
- name: Save image data without publication credentials
run: docker save -o images.tar local-observation:test
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
if: always()
with:
name: runtime-build-evidence-${{ github.run_id }}-${{ github.run_attempt }}
path: |
local-runtime-results/**
!local-runtime-results/opencode
if-no-files-found: error
retention-days: 14
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: runtime-image-data-${{ github.run_id }}-${{ github.run_attempt }}
path: images.tar
compression-level: 0
if-no-files-found: error
retention-days: 1

publish:
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
packages: write
outputs:
reference: ${{ steps.image.outputs.reference }}
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: runtime-image-data-${{ github.run_id }}-${{ github.run_attempt }}
path: image-data
# No repository checkout or executable workload in the publication job.
- name: Publish fixed destination from image archive data
id: image
env:
REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
[[ "$HEAD_SHA" =~ ^[0-9a-f]{40}$ ]]
mkdir publication
docker load --input image-data/images.tar
printf '%s' "$REGISTRY_TOKEN" | docker login ghcr.io --username "$GITHUB_ACTOR" --password-stdin
trap 'docker logout ghcr.io' EXIT
tag="ghcr.io/bateau84/opencode-eval-runner:observer-pr41-${HEAD_SHA:0:12}-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
docker tag local-observation:test "$tag"
docker push "$tag" | tee publication/publish.txt
image="$(docker image inspect "$tag" --format '{{index .RepoDigests 0}}')"
[[ "$image" =~ ^ghcr\.io/bateau84/opencode-eval-runner@sha256:[0-9a-f]{64}$ ]]
printf '%s\n' "$image" > publication/image.txt
printf 'reference=%s\n' "$image" >> "$GITHUB_OUTPUT"
docker image inspect "$image" > publication/image-inspect.json
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: runtime-publication-${{ github.run_id }}-${{ github.run_attempt }}
path: publication/
retention-days: 14
if-no-files-found: error

verify:
needs: [build, publish]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: runtime-build-evidence-${{ github.run_id }}-${{ github.run_attempt }}
path: local-runtime-results
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: runtime-publication-${{ github.run_id }}-${{ github.run_attempt }}
path: local-runtime-results
- name: Probe published runtime without publication credentials
env:
LOCAL_IMAGE: ${{ needs.publish.outputs.reference }}
run: |
docker pull "$LOCAL_IMAGE"
python3 runtime-patches/run_image_probe.py --image "$LOCAL_IMAGE" --output local-runtime-results/probe
- name: Preserve Loom eval:live invoke contract
env:
LOCAL_IMAGE: ${{ needs.publish.outputs.reference }}
run: |
python3 runtime-patches/run_eval_live_compat_probe.py \
--image "$LOCAL_IMAGE" \
--output local-runtime-results/eval-live-compat
- name: Exercise real delegated Session identity and permission enforcement
env:
LOCAL_IMAGE: ${{ needs.publish.outputs.reference }}
run: |
python3 runtime-patches/run_delegated_session_probe.py \
--image "$LOCAL_IMAGE" \
--output local-runtime-results/delegated-session
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
if: always()
with:
name: local-runtime-${{ github.event.pull_request.head.sha }}-${{ github.run_attempt }}
path: local-runtime-results/
if-no-files-found: error
retention-days: 14
45 changes: 45 additions & 0 deletions .github/workflows/observer-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Observer boundary integration

on:
pull_request:
paths:
- 'tests/integration/**'
- 'runner/observer.py'
- 'tests/test_capture_probe.py'
- '.github/workflows/observer-integration.yml'

permissions:
contents: read

jobs:
capture-boundary:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false

- name: Verify probe syntax and record checkout
run: |
python3 -m py_compile tests/integration/run_capture_probe.py
git rev-parse HEAD

- name: Pull unchanged immutable OpenCode 2.0.18 image
run: docker pull ghcr.io/bateau84/opencode-eval-runner@sha256:68ef7322c75aede0e8cc76d0e3531e8b82dd417bbb5e5100264a89eab7fe8627

- name: Verify old-image rejection (negative control)
run: python3 tests/integration/run_capture_probe.py --expect-unsupported-baseline --output capture-probe-results
# All 12 checks must pass on the pinned old image; unexpected eligibility
# or any diagnostic failure is still a job failure. Capture stays BLOCKED.
# Positive capture is tested separately by Protected runtime channel.

- name: Preserve diagnostic evidence even on blocked capture
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: capture-boundary-${{ github.event.pull_request.head.sha }}
path: capture-probe-results/
if-no-files-found: error
retention-days: 14
Loading
Loading