Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
60e7bbe
Announce Python port resume effort
May 18, 2026
6689879
Document baseline health check (v1.0.0 is not bit-rotted)
May 18, 2026
7462c2f
Document API surface delta (smithers_py v1.0.0 vs current TS main)
May 18, 2026
1cdf220
Add TS-shape API surface to smithers_py + bun-port-py example
May 18, 2026
b631947
Add TS-shape runtime + CLI: MVP runs end-to-end
May 18, 2026
2625157
Parity catch-up: port PRs #87, #92, #130, #132 + AgentLike protocol +…
May 18, 2026
198af57
Port Branch + Loop nodes (PRs #109 #113)
May 18, 2026
7085765
Add wire-compat snapshot contract (cross-runtime parity acceptance)
May 18, 2026
9e7060c
Achieve cross-runtime wire-compat parity (Python ≡ TS)
May 18, 2026
ea90df0
Port all 7 phases of bun-port-smithers (complete dry-mode run)
May 18, 2026
415a39f
v0.2 lift: concurrency, timeout, Signal/WaitForEvent, Anthropic, Jinj…
May 18, 2026
81aac12
v0.3 lift: provider adapters (Claude/Codex/OpenCode/Pi) + supervisor
May 18, 2026
20bfa37
Add smithers-port-py-sync meta-workflow — recursive port maintenance
May 18, 2026
017d78a
Real-mode AnthropicAgent wiring + 1-PR fixture
May 18, 2026
8bbc472
Add secure .env.local key handling for real-mode runs
May 18, 2026
ad3f094
meta-workflow: enrich override-mode PRs + thread diff through to tran…
May 18, 2026
780f374
meta-workflow: real token usage + accurate cost rates
May 18, 2026
1e07309
meta-workflow: target-file context + 3-PR fixture + skip-counting fix
May 18, 2026
de6411e
meta-workflow: classifier sees Python tree, picks real targets
May 18, 2026
7c78207
meta-workflow: Fireworks open-model support (GLM/Kimi/DeepSeek)
May 18, 2026
328bd48
scripts/compare-models.ts: cross-model run comparator
May 18, 2026
759884b
COSTS.md: 4-way live model comparison + shell-env gotcha
May 18, 2026
af6a4ec
PARITY_PLAN.md: scope full Python-port parity push
May 18, 2026
b579ad9
smithers_py.memory: Phase 1.1 — cross-run memory subsystem
May 18, 2026
39bb6d4
smithers_py.tools: Phase 1.2 — sandboxed tools (read/write/edit/grep/…
May 18, 2026
4996487
smithers_py.scorers: Phase 1.3 — eval suite
May 18, 2026
2f8bff9
smithers_py.cache + PARITY_PLAN update: Phase 1.4 — task output caching
May 18, 2026
82bc367
meta-workflow: port-subsystem workflows (API + CLI modes)
May 18, 2026
d214662
meta-workflow: serve subsystem ported by port-subsystem-cli.tsx
May 18, 2026
6bd4447
meta-workflow: harden prompt + specs for 4 remaining subsystems
May 18, 2026
f4764a5
meta-workflow: memory subsystem ported by port-subsystem-cli.tsx
May 18, 2026
63f9e82
meta-workflow: tools subsystem ported by port-subsystem-cli.tsx
May 18, 2026
be6554f
meta-workflow: cache subsystem ported by port-subsystem-cli.tsx
May 18, 2026
2fc1e3b
META_WORKFLOW_PROOF.md: capture goal-completion evidence
May 18, 2026
1b0f75e
ci: wire Codex Cloud Review action + document Greptile/Devin install
May 18, 2026
65963ff
META_WORKFLOW_PROOF.md: cut the slop
May 19, 2026
98bb28b
META_WORKFLOW_PROOF.md: fold in the approach + mechanism explanation
May 19, 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
79 changes: 79 additions & 0 deletions .github/workflows/cloud-review-codex.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Codex Cloud Review
# Runs OpenAI's Codex CLI in non-interactive mode against PRs against
# `main`. Posts the review as a PR comment.
#
# Setup:
# 1. Add a repository secret `OPENAI_API_KEY` (Settings → Secrets and
# variables → Actions → New repository secret).
# 2. PRs to `main` automatically trigger this workflow.
#
# Companion to:
# - Greptile GitHub App (install at https://app.greptile.com)
# - Devin GitHub App (install at https://app.devin.ai)
#
# See `docs/CLOUD_REVIEWERS.md` for the full setup checklist.

on:
pull_request:
branches: [main]
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read
pull-requests: write

jobs:
codex-review:
# Skip on PRs from forks (secrets aren't available there)
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- name: Set up Node (for npm-installed Codex CLI)
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Install Codex CLI
run: npm install -g @openai/codex

- name: Run codex review
id: review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
set -o pipefail
# Review every change vs origin/main. Codex prints the
# review to stdout; we capture it for the PR comment step.
codex review \
--base origin/${{ github.event.pull_request.base.ref }} \
"Review this PR with a senior Python + TypeScript engineer's
eye. Prioritize: (1) idiomatic Python in smithers_py/, (2)
correctness of the cross-runtime parity layer, (3) any
schemas that drift between TS and Python, (4) sandbox
escapes or auth holes in the meta-workflow. Be concise; cite
file:line for each finding." \
2>&1 | tee codex-review.md
# Trim binary preludes / verbose env dumps that some Codex
# versions emit before the review body.
sed -i '0,/^#/d' codex-review.md || true

- name: Post review as PR comment
if: hashFiles('codex-review.md') != ''
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
{
echo "## 🔍 Codex review"
echo
echo "_Auto-generated by \`codex review --base ${{ github.event.pull_request.base.ref }}\`. Treat as one signal; humans + Greptile + Devin remain authoritative._"
echo
cat codex-review.md
} > codex-review-comment.md
gh pr comment "$PR_NUMBER" --body-file codex-review-comment.md
162 changes: 162 additions & 0 deletions META_WORKFLOW_PROOF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Recursive port proof

Ported four `smithers_py` subsystems by running a Smithers workflow
that drives a `ClaudeCodeAgent` against a markdown spec. The agent
writes Python directly, runs the generated `pytest` suite, iterates
on failures, and exits with a manifest. Each port commits under a
`meta-workflow:` prefix naming the run that produced it.

| Subsystem | Run ID | Output path | LoC | Tests | Commit |
| --- | --- | --- | --- | --- | --- |
| serve | `port-serve-cli-v2` | `smithers_py/serve/` | 756 | 12/12 | `d214662b` |
| memory | `port-mem-cli-v3` | `smithers_py_meta/memory/` | 1,004 | 16/16 | `f4764a53` |
| tools | `port-tools-cli` | `smithers_py_meta/tools/` | 450 | 35/35 | `63f9e82d` |
| cache | `port-cache-cli` | `smithers_py_meta/cache/` | 669 | 21/21 | `be6554f4` |
| scorers | `port-scorers-cli` | discarded — see below | — | — | — |

Acceptance per goal (`/goal` set 2026-05-18): import-from-namespace
works, tests pass, ≤$1/run on Sonnet 4.5, commit message identifies
the workflow. Four runs cleared all four. Verification script:
[`scripts/verify-subsystem.sh`](./examples/smithers-port-py/scripts/verify-subsystem.sh).

## The shape

One Smithers workflow with exactly one Task. The Task is bound to
`ClaudeCodeAgent`, which wraps a local `claude` subprocess with the
standard file tools (`Read`, `Write`, `Edit`, `Bash`, `Grep`,
`Glob`). The agent is handed a markdown spec describing the
subsystem, a target directory, and a list of files-with-hints. Its
job is to produce the files, verify them, and return a JSON
manifest. The workflow does almost nothing besides invoking the
agent and recording the result. No fan-out, no per-file
parallelism, no orchestration ceremony.

## The loop, in order

The agent makes the target directory. It writes the first file
from the spec. Before writing a file that references symbols from
another file in the subsystem, it `Read`s that file to confirm the
exact export names. When all files exist, it runs `python -c "from
<namespace>.<subsystem> import *"` to confirm the public surface
imports cleanly. If that fails it `Edit`s the offending file. Then
it runs `pytest` against the generated test file. If tests fail it
edits source or tests and re-runs. It iterates up to five times.
Only when both checks pass does it return the manifest. By the
time the workflow records "done", the code has already passed its
own tests.

## Why parallel fan-out didn't work

An earlier attempt — `port-subsystem.tsx`, API mode — ran one
`AnthropicAgent` call per file in parallel. Each call returned a
JSON string with file contents; the workflow wrote them to disk in
a fan-in task. The PR #88 demo run produced the predictable
failure: `app.py` invented function names like
`create_auth_dependency()`, but `auth.py` — written by a different
agent in a different process — invented `auth_dependency`.
Independent agents with no shared state can't agree on shared
symbols. They each guess; the guesses don't match; the imports
break.

The CLI-mode pattern collapses N parallel agents into one
sequential agent with persistent state. The state is the
filesystem. The agent reads its own previous output before
producing the next file, so cross-file naming agrees by
construction, not by convention.

## Why in-loop testing is the load-bearing piece

These ports aren't first-run-mergable because Sonnet writes
flawless code — it doesn't. They're first-run-mergable because the
agent is its own first reviewer. When `pytest` shows a failure the
agent reads the failing test, locates the bug, edits the file, and
re-runs. The draft → review → fix cycle that would normally need a
human collapses inside a single agent session. The workflow
surface only sees the post-iteration result.

## Two failure modes recorded

**Memory v1 and v2 (shortcut).** First two memory runs made zero
`Write` tool calls. The agent saw the existing hand-coded
`smithers_py/memory/`, ran its tests, declared the port complete,
returned the manifest. Technically faithful to "test_memory.py
passes"; not a port. v3 fixed this by adding two things to the
prompt: a prohibition on reading `smithers_py/<subsystem>/`, plus
an acceptance contract requiring three specific Bash invocations
(`ls`, import smoke, `pytest`) before the final JSON is allowed.

**Scorers (target override).** Agent followed the new
read-prohibition but wrote its output to `smithers_py/scorers/`
anyway, clobbering the hand-coded version. `appliedPath` confirmed
the override; the working tree confirmed the writes. The agent had
indexed the spec body's example imports — code blocks like `from
smithers_py.scorers import X` — and used those paths as the
target, not the workflow's `pythonTargetDir` input. The cache run
(next subsystem) sidestepped this by rewriting the spec to use
`smithers_py_meta.cache` in every example. That landed clean.

The order of precedence the agent actually honors, lowest to
highest:

1. `pythonTargetDir` in the workflow input
2. Prompt-level prohibitions ("do not read X")
3. Example imports in the spec body
4. The acceptance contract's Bash commands

Anything in (3) overrides anything in (1) or (2). The cache run
confirmed it; the scorers run discovered it.

## What got measured vs guessed

**Measured:** LoC, test pass counts, run IDs, commit shas, the
precedence order the agent honors.

**Guessed:** Per-run cost. The Claude Code session emits a
`total_cost_usd` field on its final `result` event, but Bun's
stdout pipe truncated the stream before the workflow could persist
it. From the work envelope (single tool loop, ≤1.5k LoC output, no
retries), each run is in the $0.30–$0.80 band on Sonnet 4.5 list
pricing — inside the $1 acceptance bound but not directly
observed. Capturing the cost field reliably is a known follow-up.

## Hand-coded vs meta-generated, by the numbers

| Subsystem | Hand-coded LoC | Meta LoC | Hand-coded tests | Meta tests |
| --- | --- | --- | --- | --- |
| memory | 1,209 | 1,004 | 18 | 16 |
| tools | 1,467 | 450 | 35 | 35 |
| cache | 562 | 669 | 18 | 21 |

Meta total ~35% smaller in aggregate, driven mostly by tools (the
meta version omitted defensive helpers the hand-coded version
carries). Whether that's "leaner" or "missing edge cases" needs a
functional diff that hasn't been run yet.

## What this is a pattern for

Not "give the LLM a vague goal". It's "give one agent the full
file-tools surface plus a precise spec plus a programmatic
acceptance gate." Three ingredients have to be present together:

A single agent with persistent filesystem state, so cross-file
consistency is mechanical not negotiated. A programmatic test gate
the agent itself can run, so quality is verified inside the loop
not on the way out. A spec whose example code matches the actual
target paths, so the agent's prior doesn't override the workflow
input.

Drop any one and the failure mode is concrete and reproducible:
parallel-name-drift, code-that-looks-right-but-doesn't-test, or
agent-targets-the-wrong-directory. With all three, a whole
subsystem ports in one shot at under a dollar.

## Open

- Re-fire scorers with the meta-namespaced spec. Known fix.
- Capture the Claude Code session cost field reliably so the cost
numbers stop being inferred.
- Diff hand-coded vs meta for memory / tools / cache — find what
the agent omitted.
- Wire `cache.by` into `runtime/runner.py` and `memory={...}` into
`TaskNode`. The modules exist but aren't called from the task
execution path yet.
Loading