Skip to content

Releases: denniyahh/devflow

v2.12.0

Choose a tag to compare

@denniyahh denniyahh released this 02 Sep 21:46
v2.12.0
71a5192

Unattended auto-mode hardening (Phase 45). Makes --mode auto launchable and safe out of the box:
a configurable git-flow trunk so a phase worktree can fork from a personal .planning/-tracking
branch instead of hardcoded develop, a self-dogfood staleness check scoped to actual Cargo
workspace members, and a shared unattended-decision policy for the Code stage.

Added

  • configurable base branch (base_branch in devflow.toml, or DEVFLOW_BASE_BRANCH), resolved
    once and shared by the worktree fork point, the merge target, and every later process
    (advance/resume/the monitor/ship evidence) that needs to agree on the same trunk
  • affects_compiled_binary scoped to Cargo workspace members plus root build files (including
    .cargo/config.toml) for DevFlow's own self-dogfood check, so .planning/spikes/ no longer
    trips a false stale-build block; every other project DevFlow drives keeps its prior repo-wide rule
  • a shared CODE_STAGE_POLICY instructing the agent to evaluate unattended decision checkpoints
    on merit and record its reasoning, delivered to both agent-family Code-stage renderers on the
    first pass

Fixed

  • the base-branch substitution's blast radius: cleanup_merged could delete the built-in develop/
    main trunks under a configured base, and the resolved base was not persisted, so a later
    resume in a fresh shell silently fell back to develop for the worktree base, the idle-timeout
    commit evidence, and the Ship merge-evidence check — each fixed to consult the run's own recorded
    base
  • a devflow.toml that fails to parse no longer silently falls back to the default trunk; the
    base-branch resolver's fail-hard contract now covers a bad file, not only a bad value

Known gap

  • the unattended-decision policy does not yet reach the Claude/OpenCode loop-back Code prompt
    (fix_prompt's FullExecute arm), so a run that fails Validate and retries under that path gets
    no policy while the Codex/Pi equivalent does. Confirmed in shipped source by an internal review
    and two independent external reviews; accepted as this release's terminal state for that one path
    rather than reopening the plan — tracked as backlog 999.115 and 999.116.

v2.11.0

Choose a tag to compare

@denniyahh denniyahh released this 28 Aug 00:32
v2.11.0
df63642

Codex end-to-end verification (Phase 44). Proves devflow resume --phase N --agent codex
end-to-end through a real phase run and closes every gap the run and its reviews surfaced.

Added

  • devflow resume --phase N --agent <AGENT> handoff: preflights the candidate driver against the
    full generic preflight bundle before persisting the new agent
  • per-phase cron-instruction lifecycle, with TOCTOU-safe deletion under concurrent consumers
  • Hermes resume schedules as runnable UTC instants via a real hermes cron create invocation

Fixed

  • quoting bug in the composite Hermes cron command string that broke (and, for a path containing
    an apostrophe, made exploitable) project paths containing shell metacharacters
  • consume_cron_instructions_preserves_unreadable_legacy_record asserted a chmod 0o000 guarantee
    that root — the container pre-push gate's default user — bypasses; now skips under root instead
    of failing

v2.10.0

Choose a tag to compare

@denniyahh denniyahh released this 25 Aug 00:53
v2.10.0
42f88c2

OpenCode driver completion (Phase 43). Completes the under-built AgentDriver for OpenCode: a
real headless launch, JSONL event-stream completion/verdict parsing, and fail-closed health and
subagent-dispatch capability probes.

Added

  • OpenCode headless launch (opencode run --auto --format json) and Layer-1 JSONL marker parsing
  • OpenCode error-event and torn-tail precedence in completion/verdict detection
  • fail-closed credential health check for OpenCode
  • fail-closed subagent-dispatch capability probe for OpenCode

Fixed

  • close 4 fail-closed gaps in OpenCode health/capability probes found in Ship-stage review
  • correct stale cargo install OpenCode doctor hint

Changed

  • workspace isolation, conventional commits hook, and release tooling
  • automate sync branch and PR workflow for sync-main-to-develop

v2.9.0 - Hermes driver

Choose a tag to compare

@denniyahh denniyahh released this 22 Aug 10:54
v2.9.0
30ccc89

2.9.0 — 2026-08-21

Added

  • unlock unattended auto mode for Antigravity after dogfood validation
  • implement Hermes driver, doctor probe, and transport tests

Fixed

  • address review findings for Hermes driver, cadence docs, and delegation parser

Changed

  • ship phase 42 — PR #137
  • cargo fmt formatting adjustments
  • add security threat model audit
  • update code review and verification artifacts
  • update generated docs
  • record raw adversarial review transcripts from Claude, Codex, and DeepSeek
  • document multi-model adversarial review findings and action items
  • add verification and UAT evidence for Phase 42
  • create phase plan
  • record phase 42 context session
  • capture phase context

v2.8.0 — Antigravity driver + test hygiene and dogfood validation

Choose a tag to compare

@denniyahh denniyahh released this 22 Aug 10:54
v2.8.0
81119c1

2.8.0 — 2026-08-21

Antigravity driver + test hygiene and dogfood validation (milestone v2.8.0). DevFlow adds the
AntigravityDriver for headless CLI automation (agy), closes the test monitor-leak hygiene
defect, and fixes container git worktree verification.

What's new

  • Antigravity CLI Driver (Phase 41). Operator can select --agent antigravity. Spawns agy
    headless via --input-format stream-json --output-format stream-json --print-timeout 60m.
    Includes agent-aware transport handling (event-key first turn, top-level result marker close
    predicate), agent-aware canary trust, and explicit ERROR-envelope failure parsing.
  • Unattended Safety Policy (Phase 41). --mode auto is refused for Antigravity in preflight
    (C2 gate) until dogfooded through a supervised run.
  • Test Monitor Hygiene (HYG-01 / Phase 41). Integration tests in phase7_cli bind
    MonitorReapGuard to settled state, with a suite registry and audit ensuring zero orphaned
    monitor processes across test runs.
  • Container Parity for Git Worktrees (HYG-02 / Phase 41). scripts/check-in-container.sh
    bind-mounts worktree .git files and commondir paths to pass cleanly under container root.
  • Pi Supervised Dogfood Run (Phase 40). Full supervised Define→Validate run completed
    through --agent pi (closing 999.85 stale comments).

v2.7.0 — Pi end-to-end + driver contract completion

Choose a tag to compare

@denniyahh denniyahh released this 18 Aug 19:00
v2.7.0
d135d87

2.7.0 — 2026-08-18

Pi end-to-end (milestone v2.7.0). DevFlow finishes the AgentDriver migration and drives Pi
through the full pipeline. Phase 37.1 (research) returned a VIABLE verdict for the
@bacnh85/pi-subagent extension; Phase 38 removed the legacy AgentAdapter surface and wired
InteractivityMode; Phase 39 landed the Pi pipeline (provider-aware health, Legacy launch,
subagent dispatch).

What's new

  • The legacy AgentAdapter surface is gone (999.106 / Phase 38). AgentAdapter, DriverShim,
    adapter_for, and the four legacy *Agent structs are removed; every call site resolves through
    driver_for(kind) -> Box<dyn AgentDriver>. Claude's launch argv stays byte-identical (zero
    regression).
  • InteractivityMode is consumed (Phase 38). A driver-driven Define/Plan gate replaces the
    hardcoded AgentKind::Codex Define check.
  • Two Codex-parser defects fixed (999.107 / Phase 38). Terminal turn.failed now takes
    precedence over an earlier success marker; non-UTF-8 / hostile writable-root paths are refused
    rather than lossily converted to U+FFFD.
  • Pi health probes the active provider (Phase 39). PiDriver::health reads settings.json's
    defaultProvider (falling back to Pi's --provider default) instead of a hardcoded google or
    "any ready models.json provider" — fixing both a false-reject of standard installs and a
    false-green of a provider the launch never uses.
  • Pi is pinned to MonitorLaunch::Legacy (Phase 39). A regression test asserts the
    claude_stream_launch_enabled(Pi) precondition, so Pi can never land on the PipeOwning path
    whose stdin wire protocol deadlocks it.
  • Pi subagent dispatch is detected, not faked (Phase 39). Capability detection matches the
    vetted @bacnh85/pi-subagent package specifically (not *subagent*), and a captured session
    transcript proves the live dispatch (parent toolCall: subagent → nested subagent bash
    DEVFLOW_RESULT) completes under Legacy with no drain gate.

Deferred (recorded, not shipped here)

  • 999.94 — unattended decision checkpoint takes the first option blindly.
  • Isolated-context (process-spawning) Pi dispatch — needs a --no-approve child-argv patch.

v2.6.0 — multi-agent adapter migration

Choose a tag to compare

@denniyahh denniyahh released this 17 Aug 01:48
v2.6.0
6d54b2d

The multi-agent adapter migration (milestone v2.6.0). DevFlow stops rendering one shared
/gsd-* prompt for every agent and moves to a modular AgentDriver contract, where each agent
owns its prompt rendering, command building, completion parsing, and health. This fixes Codex
(which received GSD slash commands as literal shell strings) and registers Pi as a fourth,
selectable agent.

What's new

  • Pi is a fourth, selectable agent (Phase 36). AgentKind::Pi + PiAgent with a
    pi auth check-backed health check that distinguishes "installed" from "headless-capable"
    (never env-var sniffing). Pi launches with --no-approve--approve would trust
    project-local extensions that execute unsandboxed.
  • The release path signs deterministically (999.104 / Phase 36). scripts/cut-release.sh
    fails loudly before tag -s when devflow.releaseSigningKey is unset or unreadable, instead of
    silently signing with whatever user.signingkey defaults to. The capability-only
    signing-viability probe is removed; the pre-push fingerprint hook — the only check that
    distinguishes the maintainer key from the agent key — is retained.
  • release --check catches a forgotten version bump (999.96 / Phase 36). A new row compares
    CHANGELOG.md's top heading to the workspace version and reports NOT viable with direction.
  • A modular AgentDriver contract replaces AgentAdapter (Phase 37). Each driver owns its
    prompt rendering, command building, completion parsing, health, and interactivity declaration,
    instead of that logic being scattered across prompt.rs, agents/*.rs, agent_result.rs, and
    preflight.rs.
  • Codex is fixed (999.31 / Phase 37). The StageIntent de-Claude-ification removes the
    literal /gsd-* slash commands from every stage prompt; Codex now receives a workflow-file
    reference and the verified non-interactive approval flag (-a never, the global form).
  • Pi is the second native driver (Phase 37). Pi runs on -p print mode with the same
    de-Claude-ified prompt; its end-to-end run (JSON unwrapper + monitor CloseRule) is a
    follow-on (37.1/38).
  • A shared conformance suite (test_contract()) (Phase 37). Every driver must pass it; a
    deliberately-broken driver must fail it. InteractivityMode and DriverHealth are declared at
    the driver layer.

Deferred (recorded, not shipped here)

  • AgentAdapter removal + InteractivityMode consumption (999.106).
  • Codex parser success-before-failure + writable-root serialization (999.107, pre-existing).
  • Pi end-to-end (JSON unwrapper + CloseRule) — 37.1/38.

v2.4.0 — Resume Unattended Dogfooding

Choose a tag to compare

@denniyahh denniyahh released this 06 Aug 12:16
v2.4.0
c5fe44b

Phase 33 (loop-back correctness for multi-wave Validate↔Code cycles) and phase 34 (stream-json
coverage, the Validate trust boundary, and Layer 0 in worktree mode). Together they close the
structural defects blocking unattended, multi-wave devflow start runs found during the phase
29 dogfood run and phase 31 planning, so unattended dogfooding can safely resume.

The headline is the Validate trust boundary (999.74): an agent that self-reports status: failed
alongside verdict: pass used to have that verdict grafted onto an otherwise-derived Success
result and advance to Ship unattended. reconcile_layer0_verdict now consults Layer 1's own status
before transplanting its verdict, and classify_validate_outcome was rewritten as an exhaustive
match naming all seven AgentStatus variants — an eighth is now a compile error, not a silent join.
The exploit was reproduced against the real cascade before the fix, with a matched positive control
proving the fix isn't indiscriminate.

What's new

  • The Code↔Validate loop no longer false-gates on healthy work (999.66).
    consecutive_failures is measured from a persisted commit-count baseline instead of an unreset
    counter, so a healthy 3+ wave phase no longer false-gates at wave 3 while a genuinely stuck loop
    still reaches MAX_CONSECUTIVE_FAILURES.
  • Loop-back fix selection reads the worktree (999.65). select_loop_back_fix reads
    {N}-VERIFICATION.md from the phase's worktree instead of the main checkout, making
    FixType::GapsOnly reachable on the Validate path in worktree mode for the first time.
  • All five stream-json stages joined the launch path on real evidence (999.73). Widened beyond
    Stage::Code against committed, PII-scrubbed production captures with per-stage drain analysis,
    not a flag flip. The capture campaign refuted its own premise — zero background_tasks_changed
    events across 1063 events despite 8 concurrent sub-agent dispatches — filed as a known gap rather
    than absorbed; see Known Issues.
  • Layer 0 external verification works in worktree mode (999.76). Declaration discovery now
    reads the execution root, so a correctly-declared external_verify probe set no longer silently
    never executes — the plan-28-03 checkpoint auto-decide path is fixed at the same call site.

Fixed

  • Self-reported status: failed paired with verdict: pass could reach Ship unattended via the
    Layer 0 verdict graft (999.74). Closed by gating the graft on Layer 1's own status.
  • The Validate classifier's status-position wildcard could discard a non-Success status silently;
    now every AgentStatus variant is named explicitly.

Known Issues

  • The drain gate has not been observed to see sub-agent concurrency on Claude CLI 2.1.222 — the
    safety mechanism the widened stream-json stages' unattended behavior depends on. Tracked as 999.83.
  • One call site in the worktree-mode checkpoint fix has no regression test. The fix is correct
    by direct source read and by two root-sensitivity tests on the function it calls, but no test
    drives the call site itself: reverting its argument leaves the full test suite green. Tracked as
    999.84.
  • Two in-source comments (idle_timeout_result and a test-module comment) describe a mechanism
    this release's own fixes replaced.
    Their conclusions are still correct; their stated reasoning
    is not. Tracked as 999.85.

v2.3.0 — closes the 999.64 arc

Choose a tag to compare

@denniyahh denniyahh released this 04 Aug 04:54
v2.3.0
dc844b5

Phase 30 (the stream-json parser and the feasibility gate) and phase 31 (the
launch path itself). Together they close the 999.64 arc: a DevFlow-driven
phase containing a multi-plan wave now completes that wave without orphaning
delegated work — the failure that had blocked every attempt at an unattended
run through this project's history. Phase 29 remains unmerged and is not in
this release.

The headline is phase 31: the Claude adapter's detached sh monitor is
replaced by a pipe-owning Rust monitor, and the adapter always launches with
--input-format stream-json --output-format stream-json, prompt delivered on
stdin rather than argv. Holding stdin open past the first turn is what lets a
background helper agent's completion actually reach the parent session — the
notification had nowhere to arrive before this. Verified with a live two-plan
acceptance run, not just integration tests: both plans produced a SUMMARY.md
and both merged, crossing the exact point where a prior attempt (phase 29)
orphaned both executors of a two-plan wave.

What's new

  • Idle timeout. A stage that goes quiet for longer than a configurable,
    floor-clamped window now fails loudly with a distinct AgentStatus::IdleTimeout,
    naming the agent's commits and rolling nothing back — instead of hanging
    indefinitely or having a later signal misread as an unrelated failure.
    DEVFLOW_CLAUDE_IDLE_TIMEOUT_SECS raises the window above its floor; it can
    never be set lower.
  • Startup delivery canary. Before a stream-json launch, DevFlow now
    confirms the background-notification path actually works with one throwaway
    task, and refuses to run rather than silently degrading if it doesn't.
  • --legacy-claude-launch (and DEVFLOW_CLAUDE_LEGACY_LAUNCH) — an
    explicit, off-by-default escape hatch back to the pre-31 launch path, loud on
    every use, with no automatic fallback.
  • Exit-code arbitration: a stream-derived Success can no longer stand against
    a contradicting non-zero process exit code.

Fixed

Two defects from this release's own peer code review, neither reachable by the
acceptance run because it only exercised healthy paths: an idle timeout could
fire and overwrite a stage that had already completed successfully, and a
single non-UTF-8 byte in agent output could silently truncate the capture.
Both are covered by mutation-tested regression tests.

v2.2.0 — Checkpoint Answer Return Path, Hermetic Git Invocation

Choose a tag to compare

@denniyahh denniyahh released this 02 Aug 12:30
v2.2.0
828550c

Phase 27 (hermetic git invocation) and phase 28 (the checkpoint answer return
path). Phase 26 remains unmerged and is not in this release.

The headline is phase 28: a gate="blocking-human" checkpoint used to be a dead
end for any DevFlow-driven run. The agent stopped, asked a question, and no path
existed by which an answer could reach it — every retry spawned a fresh process
that asked the identical question again. A plan that correctly gated an
irreversible decision became a plan that could never finish unattended.

⚠ Behavior change: human-blocking checkpoints are now resolved by the agent

This is unconditional and there is no flag or config toggle to disable it.
When a stage halts at a task declared gate="blocking-human", DevFlow now
relaunches the exact exited Claude session with an instruction to decide the
checkpoint itself, and records what it decided.

This deliberately overrides checkpoints.md rule 6 (blocking-human is never
auto-approved, in any mode). It was adopted because DevFlow has no usable
notification or response channel — the only push mechanism is an
operator-supplied DEVFLOW_GATE_NOTIFY_CMD that is a silent no-op when unset,
and the only pull mechanism is running devflow status by hand. A "wait for a
human" default would not degrade gracefully; it would hang. Given that, a flag
implying a working "off" state would have been misleading.

What bounds it: the path is reachable only for a checkpoint that the
operator's own approved plan declared — the authorizing check is a static scan
of the phase's PLAN.md files, which an agent cannot influence at runtime, and
it is evaluated strictly before any agent-controlled signal. Resumes are capped
(MAX_CHECKPOINT_RESUMES), and exhaustion falls through to the existing
never-silent gate. Every auto-decision writes a checkpoint_auto_decided event
to .devflow/events.jsonl naming the session, the instruction, and the policy —
with no human in the loop beforehand, that record is the only way anyone learns
after the fact what the agent decided.

Fixed

  • A blocking-human checkpoint no longer strands a headless run (999.57). DevFlow statically scans the stage's plans for a declared human-blocking task before launching, confirms from captured stdout that one actually fired, and resolves it by resuming the exact exited session rather than spawning a fresh one — no CONTEXT/RESEARCH re-read, no re-running completed tasks
  • The checkpoint confirmation reader now matches what a real run actually emits. The reader was built against a rendering predicted by reading the emitting source, and shipped with that caveat recorded rather than hidden. A live end-to-end run then showed the executor renders the value as a markdown code span — **Gate:** `blocking-human` — and the matcher, which trimmed only * and whitespace, terminated on the backtick and produced an empty token. Genuine checkpoints fell through to the generic gate. The unit suite could not catch it: every fixture was built from the same prediction. Regression tests are now transcribed from the live capture. The reader's documented safe-direction property held throughout — a false negative degrades to the never-silent gate, so nothing was ever silently authorized
  • devflow resume no longer discards an unfired --until cap (999.60). The stop-marker clear was unconditional, so a cap the operator set that had not yet fired was silently dropped and the pipeline ran past the stage they named — observed live during phase 27's own dogfood run, which advanced into Ship unguarded. The clear is now gated on the pipeline having actually stopped
  • The Define stage no longer invokes an interactive interview headlessly (999.59). When CONTEXT.md was absent, Define issued /gsd-discuss-phase, which hangs on AskUserQuestion under claude -p with no operator present. The branch is deleted rather than flag-gated: whether to run an interview is decided before devflow start is ever invoked, so there is no runtime accommodation to make
  • All 41 production git invocations are hermetic (phase 27). Every Command::new("git") in production code now routes through git_command/hermetic_command, including two indirect sh → cargo → git edges and monitor.rs's spawn of the coding agent itself — the highest-consequence site, and one that was not in the original grep scope. Under a hostile GIT_DIR the suite went from 37 deliberately-failing tests to 0

Added

  • yes_ship is settable in devflow.toml (and via DEVFLOW_YES_SHIP), in addition to the existing --yes-ship flag. The flag ORs with the config value rather than replacing it, so passing it always wins. A run whose authorization came from config prints a line naming devflow.toml as the source — a standing default, but never a silent one
  • checkpoint_auto_decided events in .devflow/events.jsonl, emitted before the relaunch spawns so a crash mid-relaunch still leaves the decision recorded
  • devflow-core public API: verify::phase_plan_files, verify::phase_has_blocking_human_checkpoint, agent_result::{claude_session_id, session_id_from_capture, blocking_human_checkpoint_reported, checkpoint_reported_in_capture}, config::yes_ship, and State::{session_id, checkpoint_resumes}

Changed

  • State is now #[non_exhaustive]. Downstream crates must construct it through State::new and assign fields afterward, rather than by struct literal. Deserialization is unaffected — every #[serde(default)] field still loads state written by older binaries. State gains a field roughly every phase that introduces a run-scoped concept; without this, each addition is a semver-breaking change for any consumer using a literal. Paying that cost once here makes every future field additive
  • --yes-ship may now come from configuration, deliberately reversing the phase 23 decision that made it per-run only "so a standing unattended auto-merge can never become the silent default." That decision's own stated cost applies: relaxing this is easy, re-tightening it after operators depend on the persisted setting is not. The never-silent notice above is the compensating control. What did not change: the Ship gate still fires and still records an explicit, attributed approval rather than being bypassed
  • session_id is read only from the result envelope's top-level key, never from the agent-authored DEVFLOW_RESULT marker, and is deliberately not a deserialized field on AgentResult — otherwise an agent could nominate which session DevFlow resumes into