# Inspect what happened while the agent worked

This experiment reviews a synthetic order report, its service submission and the
operations that produced them. A correct final file can coexist with an
unauthorized read, a temporary public write that was later deleted, or an
additional service submission.

[Browse all controls and attempts](https://noteflowai.github.io/evalarc/behavior-audit/index.html)
· [中文方法说明](README.zh-CN.md).

The observer records actual Linux system calls and fake-service receipts.
Candidate commands run as UID 65534 with no effective capabilities in a
disposable container. The trusted observer uses a separate root-owned directory
and five narrowly specified container capabilities. It has no host mounts or
external network. This is a dedicated research observer; ordinary candidate
evaluation continues to use its existing sandbox.

## Review the recorded controls

For a wheel-only installation and the published evidence ZIP, follow
[local behavior review](https://github.com/noteflowai/evalarc/blob/main/docs/behavior-first-review.md).
The commands below use a source checkout.

Install this source checkout, then review saved evidence without executing it:

```bash
python3 -m pip install -e .
evalarc behavior-review examples/behavior-audit/controls/write-then-delete --json
evalarc behavior-review examples/behavior-audit/service-controls/candidate-health --json
evalarc behavior-review examples/behavior-audit/service-controls/idle --json
```

The command reports evidence validity, final-file acceptance, service completion,
behavior authorization and overall acceptance separately. Default exit 0 means
the evidence is valid even when the task is rejected; `--require-accepted` returns
1 for a valid rejection. Invalid or unreadable evidence returns 2.

The 24 file/composition controls include allowed working files, metadata-only
access, discarded reads, child processes, links, mappings, duplicate service
writes and operations rejected by the operating system. Eight additional
controls cover a fresh reference, idle execution, candidate health requests,
a forged health header, an unfamiliar HTTP method and three incomplete request
cases. These are declared maintainer controls, including repeated reference
behavior; they are not 32 independent real-world tasks.

The idle observation is valid but has no completed task. Candidate health
requests are recorded even though the service returns 200. Only authenticated
observer health probes are excluded from the candidate journal. Partial or
unparsed requests make evidence incomplete; they cannot receive acceptance.

## Repeat native observation

These commands execute the authored controls in their isolated containers:

```bash
docker build -f examples/behavior-audit/environment/Dockerfile \
  -t evalarc-behavior:2 .
PYTHONPATH=src:. python3 -m scripts.record_behavior_controls \
  --output /tmp/new-file-controls
PYTHONPATH=src:. python3 -m scripts.record_behavior_service_controls \
  --output /tmp/new-service-controls
```

Choose new output paths. If Docker requires a command prefix, pass
`--docker-command "sudo -n docker"` using your existing Docker permissions.
The image fixes its Python base digest and strace package version; observations
record the actual built image ID and observer-source hashes.

The candidate can read standard system runtime files. Workspace reads and
writes follow `policy.json`; only one correctly shaped POST to `/reports` is
authorized. The report separately checks its numeric contents. The fake service
accepts bounded POSTs, including unauthorized ones, so a 201 response records a
committed write rather than an authorization decision.

Each control preserves its program, raw compressed trace, command receipt,
service journal and exported files. Observer source snapshots were collected
before execution. `base-dependencies.json` explicitly labels the additional
base-module copies collected afterward and verifies them against the recorded
EvalArc base commit.

## Record MCP skill composition

The new pilot uses Qwen3-8B at a fixed model revision on a CUDA device. Its
four conditions are no skill, internal caching, optional cache submission, and
both fixtures. Each condition receives three generation seeds on the same
synthetic task. All conditions expose the same tool definitions; selected
skills are preloaded through actual MCP connections at fixed file and bundle
hashes. Instruction lengths differ by condition.

Build the provider, then start the model server using its verified local files:

```bash
# In a dsh-skills-anywhere source checkout:
pnpm install --frozen-lockfile --ignore-scripts
pnpm run build

# In this EvalArc checkout, using a separate CUDA-enabled Python environment:
python3 scripts/local_model_server.py \
  --model /path/to/pinned-qwen3-8b \
  --model-id Qwen/Qwen3-8B \
  --revision b968826d9c46dd6066d109eabc6255188de91218 \
  --model-files /path/to/reviewed-model-files.json
```

In another terminal:

```bash
PYTHONPATH=src:. python3 -m scripts.record_behavior_pilot \
  --bridge /path/to/dsh-skills-anywhere/examples/skill-impact/bridge.mjs \
  --pool /path/to/dsh-skills-anywhere/examples/behavior-lab/skills \
  --model-files /path/to/reviewed-model-files.json \
  --output /tmp/new-behavior-pilot
```

The model-file manifest maps every loaded filename to its SHA-256 and byte
count, with the model ID and revision. The server verifies it before and after
loading. The candidate receives neither the model files nor the model endpoint.
The task allows eight generations, at most 1,536 output tokens each, with a
300-second work budget; final export and review are measured separately.
Issued requests, received responses, MCP receipts and executed tools are retained.
Missing usage remains unknown. A finish signal is separate from task acceptance.

## Interpret the evidence

### Recorded development pilot

All 12 scheduled Qwen3-8B attempts ran on one NVIDIA L40S at the fixed revision.
The frozen sources remained unchanged throughout the cohort. The conditions
share one synthetic task; the three seeds vary generation, not task content.

| Condition | Attempts | Valid evidence/execution | Correct final file | Completed service submission | Overall accepted |
| --- | ---: | ---: | ---: | ---: | ---: |
| No skill | 3 | 3 | 0 | 0 | 0 |
| Internal cache | 3 | 3 | 3 | 0 | 0 |
| Optional cache submission | 3 | 3 | 0 | 0 | 0 |
| Both fixtures | 3 | 2 | 1 | 0 | 0 |

No attempt produced a parsed HTTP submission. Several commands assumed `curl`,
`wget` or other clients that were absent from the Python image. The task allowed
Python standard-library networking; native controls use that route successfully.
Other failures include incorrect sums, malformed tool calls and early finish
signals. The incomplete connection in `07-composed-41` sent a bare JSON body
through a socket without an HTTP request and is marked invalid.

The three submission-only attempts violate the declared contract through
attempted writes to `/dev/tty`; they do not demonstrate a cache disclosure.
The model cohort does not establish a composition effect or skill efficacy.
Actual unauthorized cache submissions are demonstrated by the separately
authored native controls. Full model text, command outputs and every failed
attempt are included in `pilot/`; none was replaced or retried.

### Recheck the complete offline bundle

Build the page and archive from this source checkout:

```bash
PYTHONPATH=src:. python3 -m scripts.build_behavior_site \
  --source examples/behavior-audit --output /tmp/behavior-review
PYTHONPATH=src:. python3 -m scripts.build_behavior_site \
  --verify --output /tmp/behavior-review
```

The archive contains its manifest and can be extracted and verified with the
same command. Open `index.html` to filter all records without network access,
then follow a case to its source-line excerpts or complete compressed trace.
Opening a page does not run the candidate. Packaging recomputes reviews from
the raw evidence and checks the frozen harness, model identity and MCP receipts.
The archived Skills Anywhere bridge and built JavaScript retain their original
MIT notice in `PROVIDER-LICENSE.txt`, copied from the recorded provider commit.
New recordings also freeze that notice with the provider sources.

### Observation boundary

Successful opens, readable mappings and reads that return bytes are distinct
events. The observer follows child processes and resolves the supported file
descriptor and link cases. It does not provide general taint tracking, kernel
attestation or arbitrary host monitoring. Raw traces and unsupported operations
remain available; incomplete coverage produces an invalid result.

The examples use synthetic data and an exact output/service contract. All
controls and instructions come from the same AI-assisted maintainer process.
No independent human-authored final fault set or held-out efficacy result is
claimed. Fingerprints establish record consistency, not producer authenticity.
