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
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: CI

on:
push:
branches: [main]
pull_request:

permissions:
Expand All @@ -12,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
python: ["3.9", "3.13"]
runs-on: ${{ matrix.os }}
timeout-minutes: 20
Expand All @@ -24,8 +25,11 @@ jobs:
- name: Pack validation
run: python scripts/workflow.py check
- name: Runtime tests
if: success() || failure()
run: python scripts/test_session.py
- name: Installer tests
if: success() || failure()
run: python scripts/test_workflow.py
- name: Golden path integration tests (stub worker)
if: success() || failure()
run: python scripts/test_relay.py
19 changes: 18 additions & 1 deletion PROJECT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Do not publish credentials, local runtime state, or personal logs.

## Documentation map

- Plan: docs/plans/multi-provider.md (multi-provider relay).
- Plan: docs/plans/relay-hardening.md (3.1.1); previous: docs/plans/multi-provider.md.
- Handover: HANDOVER.md.
- Installation: docs/INSTALL.md; usage: docs/USAGE.md.
- Maintenance and checks: docs/MAINTAINING.md.
Expand All @@ -19,6 +19,23 @@ Do not publish credentials, local runtime state, or personal logs.
- Multi-provider relay (3.1.0): skill `agent-relay` and runtime `delegate`; see docs/plans/multi-provider.md.
- On another computer, follow docs/CONTINUING.md, then use session-start.

## AI providers

Decided by the user on 2026-10-15: every available provider except the
Claude (Pricefx) work account. Agents ask before changing this table.
Providers not listed (for example Cursor, Grok or OpenCode, currently
disabled in T3) are refused until the user adds them.

<!-- estafeta:providers:start -->
| Provider | Allowed | Models | Notes |
| --- | --- | --- | --- |
| claude | orchestrate, consult, review, write | any | Personal account: T3 instance `claudeAgent`, Claude Code, `claude -p` |
| claude-pricefx | none | - | Work account (T3 instance `claude-pricefx`): not for this project |
| codex | orchestrate, consult, review, write | any | T3 tasks and `codex exec` (local login) |
| antigravity | orchestrate, consult, review, write | any | T3 tasks; Gemini models without an API key |
| gemini | consult, review, write | any | `gemini -p`; needs a paid API key, none on this host yet |
<!-- estafeta:providers:end -->

## Run and verify

Python 3.9+ and Git are required.
Expand Down
10 changes: 8 additions & 2 deletions docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,14 @@ transfer it together with its evidence.

- **Solo (default):** one writer per checkout. A new chat supersedes the earlier
chats in the same checkout and takes over their phase claims and preview
servers. A chat closed without session-end therefore blocks nothing. A chat that
is still running a check is detected as alive, and the takeover is refused.
servers, so a chat closed without session-end blocks nothing for long.
- **No takeover of live chats.** A new chat does not take over a chat that
may still be working: one running a check, one that acted in the last 30
minutes, or one with open delegations. It joins in parallel and says so.
This matters in hosts such as T3 Code, where several threads share one
folder.
- **Idle threshold.** `SESSION_WORKFLOW_TAKEOVER_IDLE_MINUTES` changes the 30
minutes.
- **Parallel:** tell a chat, in any language, that another agent works in the
same folder ("work in parallel", «работаем параллельно», «pracujeme
paralelně», «並行して作業する»), and it begins with `--parallel`. The agent goes
Expand Down
115 changes: 115 additions & 0 deletions docs/plans/relay-hardening.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Relay hardening and provider policy plan (3.2.0)

- Context: [PROJECT.md](../../PROJECT.md); previous workstream:
[multi-provider](multi-provider.md).
- Goal and acceptance: close the gaps that 3.1.0 left as "Not verified":
- live `codex exec` and Gemini transports;
- the Gemini/Antigravity route;
- native Linux and Windows;
- a third review round on the round 2 fixes.

Each gap ends verified, or as a documented limitation with a concrete
reason.
- Scope and non-goals: CI, tests, runtime fixes found by the new evidence,
adapter corrections, validation record and a 3.1.1 release. Not in scope:
new delegation modes or a benchmark run.
- Execution: authorized by the user on 2026-10-15.
- Installing `@openai/codex` and `@google/gemini-cli` globally (npm prefix
`~/.local`).
- Paid runs: live `codex exec`, live Antigravity through T3, and a third
Codex review round, with re-review of its fixes if needed.
- Pushes to a stacked branch with its own PR on top of #3.
- Constraints: same as the 3.1.0 plan. Store no secrets, never use
sandbox-bypass flags, and keep state schema 2.
- Base: `agent-relay-3.1.0` @ 5b3fb8a (PR #3, open). Branch
`relay-hardening-3.1.1`.

## Decisions

| ID | Question and recommendation | Answer or open impact | Date |
| --- | --- | --- | --- |
| H1 | Linux | Closed by PR #3 CI: ubuntu-latest with Python 3.9 and 3.13 passed all four suites. Record it; no extra work. | 2026-10-15 |
| H2 | Windows without a Windows machine | Add a windows-latest job to CI and iterate by pushing to this branch. Mark POSIX-only tests as skipped with their reason. Fix real runtime defects. | 2026-10-15 |
| H3 | Gemini route | Verify Antigravity live through T3 host tasks. `gemini -p` gets an install and failure-mode check only: personal Gemini logins were retired, and the user chose no API key. | 2026-10-15 |
| H4 | CI double runs | Trigger `push` only for main; pull requests cover branches. | 2026-10-15 |
| H5 | Scope grew (user, 2026-10-15) | One release, 3.2.0, that adds three things: orchestrator hosts beyond T3, a project provider policy with a first-use question, and a guard against taking over a live session. | 2026-10-15 |
| H6 | Provider policy enforcement | The runtime enforces it. PROJECT.md holds a marked "AI providers" table; `delegate start` refuses until it exists, and refuses providers or modes it does not allow. session-start asks the user on first use. | 2026-10-15 |
| H7 | Live session takeover | Observed: a separate T3 thread's solo session-start superseded the live orchestrator and inherited its claims. Solo `begin` now supersedes only sessions that have been idle for 30 minutes (configurable) and hold no open delegations; otherwise it joins in parallel and warns. | 2026-10-15 |

## Phases

### R1: Windows and CI

- Scope: `.github/workflows/ci.yml`, `scripts/test_*.py`, `scripts/golden/`,
the runtime if Windows exposes defects.
- Acceptance: the windows-latest job passes all suites. Every skipped test
names its POSIX-only reason. Branch pushes no longer run CI twice.
- Checks: `unit-session`, `unit-workflow`, `golden-relay`, `pack-check`,
`ci-windows` (recorded GitHub run).

### R2: Live Codex CLI

- Scope: `skills/agent-relay/references/adapters.md`, VALIDATION.md.
- Acceptance: `codex exec` as a supervised `delegate` worker passes
consult-cli and write-worktree with `--live-verify` in disposable fixtures.
The adapter commands match `codex exec --help` 0.162.1.
- Checks: `live-codex-cli`.

### R3: Gemini and Antigravity

- Scope: adapters, VALIDATION.md.
- Acceptance:
- Antigravity (gemini-3.8-flash-high) through T3 passes a consult and a
delegated write with `--live-verify`.
- The `gemini -p` adapter matches `gemini --help` 0.64.0.
- Its unauthenticated failure is recorded by `delegate` as an exited worker
and a `malformed` result, never as success.
- Checks: `live-antigravity`, `gemini-cli-failure`.

### R4: Review round 3

- Scope: whatever its findings touch.
- Acceptance: a Codex review of the round 2 fixes and this whole update
(R1-R3, R6-R8) returns APPROVE, or each finding is fixed with a test and the
fix delta is re-reviewed.
- Checks: `live-review-3`, plus the suites.

### R6: Provider policy and first-use question

- Scope: runtime (policy parser and `delegate start` gate; `delegate
providers` shows the policy), session-start, agent-relay, session-guide,
the project-context template, tests, golden scenarios and the live driver.
- Acceptance:
- On first use in a project, session-start asks which providers, modes and
models are allowed, offering detected CLIs and host options, and writes
the marked table in PROJECT.md.
- Delegation is refused without it, and for anything it does not allow.
- Checks: `unit-session`, `golden-relay`, `pack-check`.

### R7: Takeover guard

- Scope: `begin` in the runtime, the contract, USAGE.md, tests.
- Acceptance: a solo begin joins in parallel, instead of superseding, when an
earlier session in this checkout was active within the idle threshold or
has open delegations. Idle sessions are still taken over.
- Checks: `unit-session`, `golden-relay`.

### R8: Orchestrator hosts beyond T3

- Scope: adapters ("Orchestrator hosts"), a live orchestrator driver, and
VALIDATION.md.
- Acceptance: live runs, each verified with `--live-verify`:
- Codex (`codex exec` with project-local skills) orchestrates a Claude
worker;
- Claude Code (`claude -p`) orchestrates a Codex worker;
- Claude Code delegates to its own native subagent.

Sandbox requirements per host are documented.
- Checks: `live-orchestrators`.

### R5: Release 3.2.0

- Scope: versions, README limits, VALIDATION.md, handover, PR.
- Acceptance: 3.2.0 is consistent everywhere, and the "Not verified" list
holds only items with a concrete reason.
- Checks: `pack-check`, `unit-workflow`, `unit-session`, `golden-relay`.
29 changes: 29 additions & 0 deletions packs/session-workflow/VALIDATION.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# Validation - estafeta 3.1.0

## Relay hardening, 3.1.1 (2026-10-15)

This release closes the gaps that 3.1.0 left unverified.

**Live transports.** All were run with `scripts/golden/live_cli.py` or T3
host tasks in disposable fixtures, then checked with `test_relay.py
--live-verify`.

| Transport | Model | consult-cli | write-worktree |
| --- | --- | --- | --- |
| `codex exec` 0.162.1, CLI | gpt-6.1-sol | PASS | PASS: sandboxed writer in a worktree, no discrepancies, integrated recheck passed |
| Antigravity, T3 host task | gemini-3.8-flash-high | PASS | PASS: writer recorded its session and check, no discrepancies, integrated recheck passed |
| `gemini -p` 0.64.0, CLI | none: no API key | failure mode only | not run |

Without a key, `gemini -p` exits with code 41 and prints its error as JSON on
stderr. `delegate` records the worker as exited and the result as
`malformed`, with that exit code and stderr, never as success. A real Gemini
CLI answer needs a paid API key, which this host does not have; Gemini models
are verified through Antigravity instead.

Observations from these runs, now in the adapters:

- **Codex.** The user's `~/.codex/config.toml` defaulted to
`danger-full-access`, so the adapter's explicit `--sandbox` is mandatory.
- **Gemini.** In an untrusted folder it lowers the approval mode, so a headless
writer would be read-only.
- **Antigravity.** Its writer wrapped the result block in a fenced code
block; `collect` accepted it.

## Cross-provider relay, 3.1.0 (2026-10-15)

macOS, Python 3.9.6, orchestrator Claude Opus 5.5 in T3 Code.
Expand Down
2 changes: 2 additions & 0 deletions packs/session-workflow/shared/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,7 @@ To finish a phase, batch these steps:
| `stale_revision` | `status`, reconcile, retry with the new revision |
| `busy` | The lock was held for 10 seconds: retry once, then report |
| `handover_after_end` | The session already ended: fix the file, rerun only `handover --output` |
| `provider_policy: missing` | First use: ask the user which AI providers this project allows and record the PROJECT.md table (session-start step 5) |
| `providers_unset`, `provider_not_allowed` | Delegation outside the project's AI providers table: ask the user; never edit the table on your own |
| Stopped session holds claims | After the user confirms it is gone: `release --session OLD --expect-revision R --confirm-stopped --reason "..." --by ID` |
| Interrupted check stays `running` | After verifying it stopped: `check abandon --session ID --id CHECK --confirm-stopped --evidence "..."` |
27 changes: 24 additions & 3 deletions packs/session-workflow/shared/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,20 @@ from its own machine and path; elsewhere it gets `session_foreign`.

Solo `begin`, the default, ends earlier sessions recorded in this checkout, or
in a checkout path that no longer exists on this machine. It moves their claims
and runtimes to the new session. A session that is still running a check blocks
this with `session_alive`.
and runtimes to the new session, and their open delegations once the state is
saved. A session that is still running a check blocks this with
`session_alive`.

A session in this checkout that acted within
`SESSION_WORKFLOW_TAKEOVER_IDLE_MINUTES` (default 30), or that has open
delegations, may belong to a live thread. A solo `begin` then joins in
parallel, takes over nothing and warns.

Activity is measured from the runtime's own records:

- the session's begin and checkpoints;
- its events and checks;
- its delegations.

`begin --parallel` puts the checkout in parallel mode, which marks every
active session there as parallel. While any parallel session is active in a
Expand Down Expand Up @@ -116,13 +128,22 @@ recorded PID. On Windows the supervisor ends the process tree through

| Command | Purpose |
| --- | --- |
| `delegate providers` | Read-only: provider CLIs on PATH and their versions |
| `delegate providers` | Read-only: provider CLIs on PATH, their versions and the project's AI providers table |
| `delegate start --session ID --name N --provider P --mode consult\|review\|write --packet F [--model M] [--phase P --worker-session W] [--workspace DIR] [--timeout S] -- CMD...` | Record a delegation and run a CLI worker as a supervised runtime `relay-N` |
| `delegate start ... --host-ref REF` (no command) | Record a host-native child task, such as a T3 task ID |
| `delegate status [--session ID] [--name N]` | Read-only: records, worker runtime, writer facts and result |
| `delegate collect --session ID --name N [--from FILE] [--confirm-stopped]` | Parse the worker's final RELAY-RESULT block from `--from`, `reply.txt` or the CLI worker's stdout |
| `delegate cancel --session ID --name N [--confirm-stopped]` | Stop a CLI worker, or close a host task you already cancelled |

- **Provider policy.** `delegate start` requires the marked AI providers table
in the context document (PROJECT.md), between
`<!-- estafeta:providers:start -->` and `<!-- estafeta:providers:end -->`.
- Each row gives the provider ID, its allowed modes (`consult`, `review`,
`write`, plus the informational `orchestrate`, or `none`) and its models
(`any` or IDs).
- Without the table the error is `providers_unset`, and `status`/`begin`
report `provider_policy: missing`. A provider, mode or model outside it
gives `provider_not_allowed`.
- Records live in `delegations/<name>/` under the state directory: the packet,
`record.json` and `result.json` with SHA-256 hashes. `state.json` and its
schema do not change, so a 3.0 runtime can still take part as a worker.
Expand Down
Loading
Loading