mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-15 23:32:46 +00:00
Replace fabro's hand-written agent loop with pebble's `CodingAgent` and delete the `fabro-agent` crate. Workflow: `PebbleBackend` builds one agent per stage over `RunSandbox`, binds the stage's hooks as tool middleware, the interviewer as the human-input provider, and a durable `EventSink` that writes every agent event through the run event log before the agent goes on. Full-fidelity threads continue across stages through `export`/`resume_from_export`. Model failover takes the session record after the failed prompt and continues it on the next route with `ResumeMode::UseModel`, so no tool effect repeats. The steering hub targets pebble's control handle, with a steering lease holding completion open while a human is paired. Events: `EventBody::Agent` carries pebble's `CodingAgentEvent` envelope; the per-variant bodies, the transcript projection, and the fabro-only context-window, tool-summary, and skill types are gone in favor of pebble's. The OpenAPI schemas, generated Rust and TypeScript clients, and web readers follow. Ask Fabro: the session runs a `CodingAgent` under a read-only permission policy and a system prompt transform. Its conversation lives in a new `run_session_records` table and resumes on the recorded model with the event cursor advanced past the run log. `fabro exec` builds the same agent over a local sandbox with pebble's permission middleware and an interactive approval service. The catalog fills in `metadata.agent.profile` for operator providers that declare none, so pebble's lookup is the one resolution path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
193 lines
7.5 KiB
YAML
193 lines
7.5 KiB
YAML
name: Rust
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- "lib/apps/**"
|
|
- "lib/components/**"
|
|
- "lib/foundation/**"
|
|
- "test/**"
|
|
- "Cargo.toml"
|
|
- "Cargo.lock"
|
|
- ".cargo/**"
|
|
- ".config/**"
|
|
- "bin/dev/**"
|
|
- "docs/public/reference/cli.mdx"
|
|
- "docs/public/reference/user-configuration.mdx"
|
|
- "openapi/**"
|
|
- ".github/workflows/rust.yml"
|
|
pull_request:
|
|
branches: [main]
|
|
paths:
|
|
- "lib/apps/**"
|
|
- "lib/components/**"
|
|
- "lib/foundation/**"
|
|
- "test/**"
|
|
- "Cargo.toml"
|
|
- "Cargo.lock"
|
|
- ".cargo/**"
|
|
- ".config/**"
|
|
- "bin/dev/**"
|
|
- "docs/public/reference/cli.mdx"
|
|
- "docs/public/reference/user-configuration.mdx"
|
|
- "openapi/**"
|
|
- ".github/workflows/rust.yml"
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
permissions: {}
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
CARGO_NET_RETRY: "10"
|
|
|
|
jobs:
|
|
fmt:
|
|
name: Format
|
|
runs-on: ubuntu-24.04-x86-32-cores
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: nightly-2026-04-14
|
|
components: rustfmt
|
|
- run: cargo +nightly-2026-04-14 fmt --check --all
|
|
|
|
clippy:
|
|
name: Clippy
|
|
runs-on: ubuntu-24.04-x86-32-cores
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: nightly-2026-04-14
|
|
components: clippy
|
|
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
|
with:
|
|
cache-on-failure: true
|
|
- name: Verify legacy auth identity removal
|
|
run: |
|
|
if git grep -nE 'AuthMode::Disabled|RunAuthMethod|RunSubjectProvenance|\bActorRef\b|\bActorKind\b|AuthenticatedSubject|AuthenticatedService|AuthorizeRunScoped|AuthorizeRunBlob|AuthorizeStageArtifact|AuthorizeCommandLog|auth_method\s*==\s*"disabled"' \
|
|
-- lib/apps lib/components lib/foundation apps lib/packages docs/public/api-reference/fabro-api.yaml; then
|
|
echo "::error::Legacy auth identities remain in the repository"
|
|
exit 1
|
|
else
|
|
status=$?
|
|
if [ "$status" -ne 1 ]; then
|
|
exit "$status"
|
|
fi
|
|
fi
|
|
- run: cargo +nightly-2026-04-14 clippy --locked --workspace --all-targets -- -D warnings
|
|
|
|
generated-docs:
|
|
name: Generated Docs
|
|
runs-on: ubuntu-24.04-x86-32-cores
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: 1.97.1
|
|
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
|
with:
|
|
cache-on-failure: true
|
|
- run: cargo --locked dev docs check
|
|
|
|
test:
|
|
name: Test (Linux)
|
|
runs-on: ubuntu-24.04-x86-32-cores
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: 1.97.1
|
|
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
|
with:
|
|
cache-on-failure: true
|
|
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
|
|
- run: cargo nextest run --locked --workspace --status-level slow --profile ci
|
|
# Twin-mode e2e suites. These are hermetic (in-process twin provider, no
|
|
# secrets): FABRO_TEST_MODE defaults to twin, so live-only tests
|
|
# self-skip. Scoped to the packages whose ignored tests are fully green
|
|
# in twin mode; widen as the remaining suites are fixed up for CI.
|
|
# Must not use the e2e nextest profile here: NEXTEST_PROFILE=e2e implies
|
|
# strict mode, which fails (rather than skips) live tests without keys.
|
|
- run: cargo nextest run --locked --workspace --status-level slow --profile ci --run-ignored only -E 'package(fabro-llm)'
|
|
|
|
sandbox-plugins:
|
|
name: Sandbox plugins (stdio)
|
|
runs-on: ubuntu-24.04-x86-32-cores
|
|
permissions:
|
|
contents: read
|
|
env:
|
|
# The plugin scenarios skip when an executable or daemon is missing;
|
|
# in CI a skip is a failure.
|
|
FABRO_REQUIRE_SANDBOX_PLUGINS: "1"
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: 1.97.1
|
|
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
|
with:
|
|
cache-on-failure: true
|
|
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
|
|
- run: docker pull buildpack-deps:noble
|
|
# The driver's own Host and Docker executables, installed at the rev the
|
|
# workspace pins so the plugins and the in-process providers are one
|
|
# build; the CLI scenarios find them on PATH and launch them over stdio.
|
|
- name: Install the sandbox-driver plugin executables
|
|
run: |
|
|
rev="$(sed -n 's/^sandbox-driver = { git = "[^"]*", rev = "\([0-9a-f]*\)" }$/\1/p' Cargo.toml)"
|
|
test -n "$rev"
|
|
cargo install --locked --git https://github.com/lithoscomputer/sandbox-driver --rev "$rev" sandbox-driver-host sandbox-driver-docker
|
|
# Host and Docker served as plugins through the workflow scenarios. The
|
|
# scenarios are e2e tests (ignored by default); the key-free ones run
|
|
# here, the LLM-backed ones self-skip without credentials.
|
|
- run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-cli --test it -E 'test(/host_plugin_|docker_plugin_/)'
|
|
# The stdio plugin proof (not ignored: it skips without the executable,
|
|
# which the environment above forbids) and the driver-backed Docker
|
|
# integration tests.
|
|
- run: cargo nextest run --locked --profile ci --status-level slow -p fabro-sandbox --test plugin_provider
|
|
- run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-sandbox --test docker_streaming
|
|
- run: cargo nextest run --locked --profile ci --status-level slow --run-ignored only -p fabro-workflow --test it -E 'test(asset_collection_docker_sandbox)'
|
|
|
|
test-macos:
|
|
name: Test (macOS)
|
|
if: github.event_name == 'workflow_dispatch'
|
|
runs-on: macos-15
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
|
with:
|
|
toolchain: 1.97.1
|
|
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
|
with:
|
|
cache-on-failure: true
|
|
- uses: taiki-e/install-action@773334c0e05d7e699e4d78234494308223f3a2cf # nextest
|
|
- run: cargo nextest run --locked --workspace --status-level slow --profile ci
|