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
120 changes: 120 additions & 0 deletions .agents/skills/improving-by-trial/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
name: improving-by-trial
description: Improve this repository's plugins by trial — run fresh, isolated agents that get only a user's sentence and this repository's link, collect where they got stuck, fix what belongs here, file what belongs elsewhere, and repeat until the trial passes. Use when asked to trial, dogfood, test the onboarding or a plugin end to end, run a fresh agent against the plugins, or iterate on trial findings before a release.
---

# Improving the plugins by trial

A trial is a fresh agent with nothing but a user's sentence and a link. It shows what the skills
fail to say. The gate cannot show that: every check passes while an agent still guesses.

## 1. Build a sandbox from this checkout

```console
task trial:sandbox NAME=<name>
```

This creates `/var/tmp/b10x-trials-$USER/<name>/` (the Taskfile's `TRIALS`) with its own `home/`, a `b10x` built from this
checkout, and an `env` file. The `env` file sets `HOME` to the sandbox and `B10X_MARKETPLACE` to
this checkout, so `b10x init` installs the plugins as they are in the working tree, before any
release. It also unsets `ANTHROPIC_API_KEY`, `TMPDIR` and `TMPPREFIX`. Put the fixture the trial
needs (a small service, a `TODO.md`, an OpenAPI document) under `work/`, and commit it there with
`git` when the trial needs history or a remote.

To trial the released version instead, remove `home/.local/bin/b10x` and unset `B10X_MARKETPLACE`
in `env`; the agent then follows `SETUP.md` from the release.

## 2. Run it headless, never as a sub-agent

```console
task trial:run NAME=<name> PROMPT='<the user sentence>' [DIR=<subdirectory of work>]
```

The task copies the operator's credentials in (mode 600), runs `claude -p` with the sandbox's
`env`, `--strict-mcp-config` (no MCP server, including the account's claude.ai connectors) and
stream-json output into `run.jsonl`, and deletes the credentials when it finishes.

**Never run a trial as a sub-agent of the working session.** A sub-agent gets the session's own
agents and plugins whatever `HOME` its shell uses. In trial 3 the aep critics that ran were this
machine's, not the plugin's under test.

The prompt is what a user would type, plus the link when the trial is about finding the
repository. Ask the agent to end by listing the skills and agents it used, quoting any text that
confused it, and pasting the final command output verbatim. Give it no other hints.

## 3. Only an isolated run counts

`trial:run` ends with:

```console
agentplugins-check trial-isolation <sandbox>/run.jsonl --sandbox <sandbox> --version <version>
```

It fails when a plugin loaded from outside the sandbox home and the checkout, when a plugin is not
in the sandbox's own registry as it was before the run, when a plugin is not at the version under
test, or when an agent or skill came from a plugin the sandbox did not load. A failing run is
discarded, not interpreted.

**A sandbox under the home directory is not isolated.** Claude Code reads `CLAUDE.md`,
`.claude/CLAUDE.md` and `.claude/settings*.json` in every directory above its working directory. In
trial 3, sandboxes under `~/.cache` loaded the operator's `~/.claude/CLAUDE.md` (one agent followed
its commit rules) and a `.claude/settings.local.json` an earlier trial left in `~/.cache`, which
enabled `aep@b10x`. `trial:sandbox` refuses to build below any of those files; that is why `TRIALS`
is outside `$HOME`. Neither leak shows in the `init` event, so the placement is the only guard. An upgrade trial seeds older plugins on
purpose: run it with `SEEDED=true`, so plugins must match what the sandbox was seeded with.

## 4. Read the run

From `run.jsonl`:

| collect | how |
|---|---|
| tool calls | count of `tool_use` blocks |
| stuck points | every refusal and error in `tool_result`s, verbatim |
| guesses | what the final report says it inferred or could not find |
| waste | calls repeated, files read twice, commands that failed and were retried unchanged |
| the outcome | the verbatim `validate` / `generate` / plan output it pasted |

Before writing a finding into a skill, reproduce each claimed behaviour with the released CLI. A
trial agent's explanation of a refusal is a hypothesis.

## 5. Triage every finding to one owner

| the cause | where the fix goes |
|---|---|
| a skill, agent, `SETUP.md`, the catalog or the `b10x` CLI | here: fix it on a branch, with a test for CLI behaviour |
| a product CLI or language (`ess`, `aep`, `worktree`) | an issue in that repository, created through the bot (`AGENTS.md`); the skill here documents the workaround until it is fixed |
| both | both: the workaround here, the issue there, each naming the other |

The issue body has the trial name, the exact command and output, the expected behaviour, the
workaround the skill now documents, and ends with the line *Found by an agentplugins trial*. That
line is the ledger: the bot may not label issues (403), so the list is a body search.

```console
gh search issues --owner beyond10x --state open --match body "Found by an agentplugins trial"
```

Check that list before each round, and delete a workaround from the skills once its issue is
fixed and released.

## 6. Fix, gate, re-run

1. Fix on a managed worktree branch.
2. Run `task check`, and `agentplugins-check tools` when a CLI command or the ESS example changed.
3. Rebuild the sandbox (`task trial:sandbox`) and re-run the trial that found the problem. It
passes when the finding does not recur. New findings go back to step 5.
4. Release when every trial of the round passes.

Each round has 3 ESS trials (a new specification; a retrofit of an existing service; generate plus
a synthesized suite), and 1 trial each for aep planning, worktree, and onboarding or upgrade.
Change the domain each round so the agents cannot copy the previous answer from the skills.

## 7. Clean up

`trial:run` deletes the credentials it copied. When the round is released, check that no
credentials are left in any sandbox and remove the sandboxes:

```console
ls /var/tmp/b10x-trials-$USER/*/home/.claude/.credentials.json
rm -rf /var/tmp/b10x-trials-$USER/<name>
```
1 change: 1 addition & 0 deletions .claude/skills/improving-by-trial
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CLIs. Serves O2 (decisions as data) and O3 (any harness).
| `evals/` | eval corpus ([`evals/README.md`](evals/README.md)) |
| `website/` | public docs; must pass `task site-build` |
| `SETUP.md` | agent bootstrap, published as a release asset |
| `.agents/skills/improving-by-trial/` | how plugins are improved: isolated headless trials (`task trial:sandbox`, `task trial:run`), triage, fix, re-run |

## Rules

Expand All @@ -27,6 +28,8 @@ CLIs. Serves O2 (decisions as data) and O3 (any harness).
- Retired names appear only where the gate allows them (`CHANGELOG.md`, `changes/`,
`.engineering/`, `catalog.json`, `crates/b10x/`, the checker's own table).
- Anything executable is Rust.
- Trial findings for another repository become an issue there, ending *Found by an agentplugins
trial*; the skill here documents the workaround until it is fixed ([`improving-by-trial`](.agents/skills/improving-by-trial/SKILL.md)).

## Gate

Expand Down
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,51 @@
# Changelog

## [0.14.3] — 2026-09-25

From trial 3: five fresh agents on 0.14.2 (an ESS specification from nothing, an ESS retrofit of an
existing service, an ESS pipeline through generate and a synthesized suite, AEP planning over a
`TODO.md`, worktree onboarding) plus a migration of a seeded older install.

- `ess:specifying`: lifecycle state names start upper-case; `ess-inputs.yaml` is documented and
recommended once anything is generated, since a directory without it is read whole;
`generate --out <dir>` writes its own `schema/` or `openapi/` below `<dir>`; an entity invariant
needs a view holding every state and publishing the fields it reads, or `synthesize` refuses the
check. The syntax example gains that view: it synthesized with 3 refusals, now 12 scenarios and 0.
- The syntax reference says how to write rules the trials hit: a limit read from stored state, and
no double booking (a per-slot lifecycle, or `UNMAPPED:`). A time range is ordered by an `Integer`
length; comparing two `Timestamp`s validates and then fails `synthesize`, and `Duration` does not
compare with a number.
- `ess:retrofitting`: `ess infra import openapi` reads OpenAPI 3.1 only; `aep plan reverse openapi`
accepts 3.0. Its description named the retired `specify` and `coverage` skills.
- `ess:testing-conformance`: what the built-in targets `interpreted`, `oracle-fixture` and `billing`
are, why a new domain reports nothing useful against them, and `synthesize --target go|typescript`
to hold a real implementation to the suite.
- `aep:planning`: the `--protocols` and `--profile` values for `reverse init`; body files live in a
git-ignored directory of the repository, not `$TMPDIR`; a critic's empty findings fence is recorded as
`[]`, which the store accepts, since it refuses the empty fence. Two references to `ess skill`, which no longer exists, now name
`b10x skill ess:specifying`.
- `aep:migrating`: `reverse init` creates the store in every case; a backlog item that introduces a
new noun gets its ESS domain before its stories. Provenance says whose revisions it counts.
- `b10x:init` and `aep:init` offer `ess` with `aep`.
- The design and parallel-safety critics name the same two remedies for a shared file (an ordering
edge, or splitting the file) instead of asking for opposite changes in consecutive rounds.
- `worktree:init`: where to get a profile and where it goes; `doctor --check` exits 0 with
`profiles=0`; cleanup needs a remote. `worktree:managing-worktrees`: switch to a branch before the
first commit.
- `b10x:routing` routes ESS and worktree work to their skills instead of to `ess skill`.
- `b10x upgrade` installs the replacement of a legacy plugin it removes; it used to remove it and
only note the replacement as missing. A legacy `local` install is not reinstalled at `local` when
the user scope covers it. A plan names Beyond10x plugins on a host it does not cover. `b10x check` no longer says nothing is set up
when only a legacy plugin is installed.
- `agentplugins-check tools` also synthesizes and generates the ESS syntax example.
- `agentplugins-check` parses its arguments with clap; new `trial-isolation` checks that a headless
trial loaded only the plugins its sandbox installed, at the version under test, and no MCP server.
Sandboxes live outside `$HOME` (`/var/tmp/b10x-trials-$USER`): below it, a trial loaded the
operator's `CLAUDE.md` and a settings file an earlier trial left behind. `task trial:sandbox` and
`task trial:run`, and the repository skill `improving-by-trial`, describe the loop.
- The README lists every plugin's skills and agents, linked to their files; the gate keeps it
exact. The retired-name sweep covers `ess skill` and the `beyond10x/ess` marketplace.

## [0.14.2] — 2026-09-24

From trial 2, in which fresh agents given only a sentence and this repository's link onboarded
Expand Down
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/agentplugins-check", "crates/b10x"]

[workspace.package]
version = "0.14.2"
version = "0.14.3"
edition = "2021"
rust-version = "1.85"
license = "Apache-2.0"
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,23 @@ Codex: `codex plugin marketplace add beyond10x/agentplugins` — then install wh
| [`connectors`](website/docs/plugins/connectors.md) | integrations | `/plugin install connectors@b10x` | `codex plugin add connectors@b10x` |
| [`b10x`](website/docs/plugins/b10x.md) | setup, upgrades, routing | `/plugin install b10x@b10x` | `codex plugin add b10x@b10x` |

What each plugin ships:

<!-- plugin-tree:start -->
- [`ess`](plugins/ess/) · [docs](website/docs/plugins/ess.md)
- skills: [`init`](plugins/ess/skills/init/SKILL.md) · [`upgrade`](plugins/ess/skills/upgrade/SKILL.md) · [`retrofitting`](plugins/ess/skills/retrofitting/SKILL.md) · [`specifying`](plugins/ess/skills/specifying/SKILL.md) · [`testing-conformance`](plugins/ess/skills/testing-conformance/SKILL.md)
- agents: [`author`](plugins/ess/agents/author.md) · [`conformance`](plugins/ess/agents/conformance.md) · [`retrofitter`](plugins/ess/agents/retrofitter.md)
- [`aep`](plugins/aep/) · [docs](website/docs/plugins/aep.md)
- skills: [`init`](plugins/aep/skills/init/SKILL.md) · [`upgrade`](plugins/aep/skills/upgrade/SKILL.md) · [`implementing`](plugins/aep/skills/implementing/SKILL.md) · [`migrating`](plugins/aep/skills/migrating/SKILL.md) · [`planning`](plugins/aep/skills/planning/SKILL.md)
- agents: [`adversary`](plugins/aep/agents/adversary.md) · [`decomposer`](plugins/aep/agents/decomposer.md) · [`implementor`](plugins/aep/agents/implementor.md) · [`plan-critic-acceptance`](plugins/aep/agents/plan-critic-acceptance.md) · [`plan-critic-design`](plugins/aep/agents/plan-critic-design.md) · [`plan-critic-parallel-safety`](plugins/aep/agents/plan-critic-parallel-safety.md) · [`plan-critic-scope`](plugins/aep/agents/plan-critic-scope.md) · [`plan-reviewer`](plugins/aep/agents/plan-reviewer.md) · [`reverse-engineer`](plugins/aep/agents/reverse-engineer.md) · [`security-reviewer`](plugins/aep/agents/security-reviewer.md) · [`story-scoper`](plugins/aep/agents/story-scoper.md)
- [`worktree`](plugins/worktree/) · [docs](website/docs/plugins/worktree.md)
- skills: [`init`](plugins/worktree/skills/init/SKILL.md) · [`upgrade`](plugins/worktree/skills/upgrade/SKILL.md) · [`managing-worktrees`](plugins/worktree/skills/managing-worktrees/SKILL.md)
- [`connectors`](plugins/connectors/) · [docs](website/docs/plugins/connectors.md)
- skills: [`init`](plugins/connectors/skills/init/SKILL.md) · [`upgrade`](plugins/connectors/skills/upgrade/SKILL.md) · [`integrating`](plugins/connectors/skills/integrating/SKILL.md)
- [`b10x`](plugins/b10x/) · [docs](website/docs/plugins/b10x.md)
- skills: [`init`](plugins/b10x/skills/init/SKILL.md) · [`upgrade`](plugins/b10x/skills/upgrade/SKILL.md) · [`authoring-plugins`](plugins/b10x/skills/authoring-plugins/SKILL.md) · [`routing`](plugins/b10x/skills/routing/SKILL.md)
<!-- plugin-tree:end -->

Most plugins drive a CLI of the same name. To have an agent install plugins and matching CLIs, and
migrate older installs, tell it: *"Set up Beyond10x: follow
https://github.com/beyond10x/agentplugins/releases/latest/download/SETUP.md"*.
Expand Down
70 changes: 70 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
version: '3'

vars:
# Outside the home directory: Claude Code reads CLAUDE.md, .claude/CLAUDE.md and .claude/settings*.json
# in every directory above its working directory, so a sandbox under $HOME inherits the operator's.
TRIALS: '/var/tmp/b10x-trials-{{.USER}}'

tasks:
check:
desc: Run the complete offline repository gate.
Expand All @@ -17,6 +22,71 @@ tasks:
cmds:
- cargo run --quiet --locked --bin agentplugins-check -- evals

trial:sandbox:
desc: "Create a clean trial sandbox for this checkout: task trial:sandbox NAME=<name> (see .agents/skills/improving-by-trial)."
requires:
vars: [NAME]
vars:
T: '{{.TRIALS}}/{{.NAME}}'
cmds:
# Claude Code also reads `.claude/settings*.json` in the directories above its working
# directory; one there enables plugins in every sandbox below it.
- |
d='{{.T}}'
while [ "$d" != / ]; do
d="$(dirname "$d")"
for f in "$d/CLAUDE.md" "$d/.claude/CLAUDE.md" "$d/.claude/settings.json" "$d/.claude/settings.local.json"; do
if [ -e "$f" ]; then
echo "refusing: $f would load into every sandbox below it; set TRIALS elsewhere"
exit 1
fi
done
done
- rm -rf '{{.T}}'
- mkdir -p -m 700 '{{.TRIALS}}'
- mkdir -p '{{.T}}/home/.local/bin' '{{.T}}/work' '{{.T}}/tools'
- for t in claude codex; do p="$(command -v $t)" && ln -sf "$(readlink -f "$p")" '{{.T}}/tools/'$t; done; true
- for t in cargo rustc rustup; do ln -sf "$HOME/.cargo/bin/$t" '{{.T}}/tools/'$t; done
- echo '{}' > '{{.T}}/home/.claude.json'
- nice -n 19 env CARGO_BUILD_JOBS=4 cargo build --quiet --locked -p b10x
- cp "${CARGO_TARGET_DIR:-target}/debug/b10x" '{{.T}}/home/.local/bin/b10x'
- |
{
echo "export HOME='{{.T}}/home'"
echo "export PATH='{{.T}}/home/.local/bin:{{.T}}/home/.cargo/bin:{{.T}}/tools:/usr/bin:/bin'"
echo "export RUSTUP_HOME='$HOME/.rustup' CARGO_HOME='$HOME/.cargo' CARGO_BUILD_JOBS=4"
echo "export B10X_MARKETPLACE='{{.ROOT_DIR}}'"
echo "export GIT_AUTHOR_NAME=trial GIT_AUTHOR_EMAIL=trial@example.invalid GIT_COMMITTER_NAME=trial GIT_COMMITTER_EMAIL=trial@example.invalid"
echo "unset ANTHROPIC_API_KEY TMPDIR TMPPREFIX"
} > '{{.T}}/env'
- echo '{{.T}}'

trial:run:
desc: "Run one headless trial in a sandbox and check its isolation: task trial:run NAME=<name> PROMPT='…' [DIR=<subdir of work>] [SEEDED=true for an upgrade trial]."
requires:
vars: [NAME, PROMPT]
vars:
T: '{{.TRIALS}}/{{.NAME}}'
DIR: '{{.DIR | default ""}}'
SEEDED: '{{if eq (.SEEDED | default "") "true"}}--seeded{{end}}'
VERSION:
sh: sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -1
cmds:
- cp '{{.T}}/home/.claude/plugins/installed_plugins.json' '{{.T}}/registry-at-start.json'
- install -m 600 "$HOME/.claude/.credentials.json" '{{.T}}/home/.claude/.credentials.json'
- defer: rm -f '{{.T}}/home/.claude/.credentials.json'
- |
(. '{{.T}}/env' && mkdir -p '{{.T}}/work/{{.DIR}}' && cd '{{.T}}/work/{{.DIR}}' &&
timeout 2400 claude -p "$PROMPT" --permission-mode acceptEdits \
--allowedTools 'Bash(b10x:*)' 'Bash(ess:*)' 'Bash(aep:*)' 'Bash(worktree:*)' 'Bash(git:*)' \
'Bash(mkdir:*)' 'Bash(ls:*)' 'Bash(cat:*)' 'Bash(find:*)' 'Bash(curl:*)' 'Bash(tar:*)' \
'Bash(sha256sum:*)' 'Bash(mv:*)' 'Bash(chmod:*)' Read Write Edit Glob Grep Skill Task Agent \
--strict-mcp-config --output-format stream-json --verbose > '{{.T}}/run.jsonl' 2> '{{.T}}/run.err'
echo "EXIT=$?" >> '{{.T}}/run.err')
- cargo run --quiet --locked --bin agentplugins-check -- trial-isolation '{{.T}}/run.jsonl' --sandbox '{{.T}}' --marketplace '{{.ROOT_DIR}}' --version '{{.VERSION}}' {{.SEEDED}}
env:
PROMPT: '{{.PROMPT}}'

site-build:
desc: Install and build the public Docusaurus documentation (network).
cmds:
Expand Down
1 change: 1 addition & 0 deletions crates/agentplugins-check/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ repository.workspace = true
authors.workspace = true

[dependencies]
clap.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_yaml.workspace = true
Expand Down
Loading
Loading