Releases: Consiliency/agent-harness
Release list
phase-loop-runtime v0.7.14
phase-loop-runtime v0.7.14
This release publishes the accumulated post-v0.7.13 runtime work and the fleet advisor-board defaults from #643.
Advisor-board defaults
- Claude Fable 5 (
claude-fable-5) - GPT-5.6 Sol (
gpt-5.6-sol) - Grok 4.6 (
grok-4.6) - Gemini 3.7 Flash (
gemini-3.7-flash) - President availability order: Fable, Sol, Grok, Gemini
- President fallback advances only on typed
president_unavailable - Native harness execution remains the default for native legs; nonnative legs retain their TUI-adapter boundary
Release evidence
- Source release PR: #649
- Release merge commit:
0c4d3a89054efa80a1f7663bd65e70d0f547c76e - Trusted-publish workflow:
32783112944 - Exact prebuilt-wheel Gate A and trusted PyPI publish: success
- PyPI wheel SHA-256:
08ec0e61c91b95ccd822a6c6dafc47f607455c594ea1d8a253c7c0b1f7ab4fa7 - PyPI sdist SHA-256:
d6731f120f694c8046eb5a1d77ad49d68e356edad672c41790ef4c72b5583c37 - Fresh public-PyPI install verified as
phase-loop-runtime==0.7.14
agent-harness v0.7.13
Native Windows import-safety repair for #327.
- phase-loop CLI entrypoint now imports on native Windows
- POSIX PTY execution fails closed as claude_tui_unsupported_platform when unavailable
- Claude remains subscription-TUI-only with no API or native Task fallback
- full multi-Python and clean-room wheel gates passed
v0.7.12 was not published: tag/version validation rejected it before build or upload.
v0.7.11 — governed advisor research and model routing
What's Changed
- docs(roadmap): post-0.7.10 backlog phase roadmap v9 by @ViperJuice in #258
- fix(profiles): decouple grok max-effort-planner eligibility via planner_max_class (#231) by @ViperJuice in #263
- fix(runner): goal-coverage + verification gate parity on dispatch & delegated paths (#244, #245) by @ViperJuice in #262
- fix(reconcile): fail-closed breakglass SL-2 gates on malformed/non-absolute event paths (#238) by @ViperJuice in #267
- fix(broker/coordinator): IF-0-BRK-1 byte-identity + N1–N7 publish→merge TOCTOU hardening (#250) by @ViperJuice in #268
- fix(verification-evidence): whole-artifact seal + source-redaction of diagnostics (#243) by @ViperJuice in #270
- feat(closeout): FAV #91 visual-avatar visible-render evidence gate (declared-signal trigger, #272) by @ViperJuice in #274
- docs(design): FAB #191 reviewed-byte delta-review design (v2, supersedes #271) by @ViperJuice in #275
- feat(fab): Lane A — provenance schema + hash chain + trust root (#191) by @ViperJuice in #277
- feat(fab): Lane B — canonical bytes + equivalence + hostile-git (#191) by @ViperJuice in #278
- feat(fab): Lane C — delta chain + carry-forward + escalation + boundary manifest (#191) by @ViperJuice in #280
- feat(fab): Lane D — gate-status + agent-review-gate + authenticity + promotion re-gate (dormant) (#191) by @ViperJuice in #281
- feat(fab): activation 1/3 — promotion re-assertion at the live merge path (#191) by @ViperJuice in #282
- .github/workflows: Migrate workflows to Blacksmith runners by @blacksmith-sh[bot] in #284
- feat(FAB): activate producer + forge-resistance trust root (piece 2, #191) by @ViperJuice in #283
- feat(FAB): activate merge-time re-gate via durable admission bridge (piece 3a, #191) by @ViperJuice in #285
- feat(FAB): delta-chain authentication — lift the block, per-round forge resistance (piece 3b-gate, #191) by @ViperJuice in #286
- feat(FAB): delta-review shortcut consumer + atomic re-admission (piece 3b-consumer, #191) by @ViperJuice in #287
- feat(FAB): #265 merge-queue queue-bound re-assertion (last FAB milestone item) by @ViperJuice in #295
- feat(model-tiers): fleet-wide ultra/heavy/regular/lite taxonomy — Opus 5 heavy, Gemini 3.6, tier-enforced routing by @ViperJuice in #309
- chore(plans): true up plan bookkeeping — tier design DELIVERED, convergence-v1 partially executed by @ViperJuice in #314
- docs(plans): add agent-harness#310 rollout plans by @ViperJuice in #315
- feat: reconcile role-aware model defaults by @ViperJuice in #317
- feat: apply governed repair model escalation by @ViperJuice in #318
- feat: default advisor boards to Gemini 3.6 Flash by @ViperJuice in #320
- feat: enforce Claude subscription TUI for agent-harness#310 by @ViperJuice in #321
- feat: add governed advisor research by @ViperJuice in #323
New Contributors
- @blacksmith-sh[bot] made their first contribution in #284
Full Changelog: v0.7.10...v0.7.11
v0.7.10
verification.json records the phase alias on the train re-verify path (#236)
Follow-up to #235 (ah#85b), which threaded the live run alias into run_verification
on the execute path. The train re-verify path (train_runner._live_reverify) also calls
run_verification but passed no phase_alias, so verification.json fell back to
current_phase → 'unknown' even though a phase alias was already resolved in scope. It
now threads the resolved (reconcile-recomputed) phase, so a re-verify records the actual
phase rather than 'unknown'. (#236)
Panel/advisor-board: a codex review is no longer mislabeled DEGRADED for discussing auth (#252)
_classify_leg scanned a leg's full transcript for auth-error signatures; because the
codex leg's log_text includes its stdout+stderr (codex echoes its own review onto
stderr), a clean, conforming codex review whose prose merely discusses "unauthorized" /
"rate limit exceeded" (routine in security/auth reviews) was forced to DEGRADED and the
operator told to discard a valid review. A conforming review-mode rc==0 verdict is
now classified OK before the auth scan (its terminal-verdict predicate is one a
de-authed CLI can't fake). Advisory mode keeps auth-scan-first (its weaker length
predicate could otherwise fail open on a real banner), preserving the #63 behavior.
Fail-closed for genuine auth failures is unchanged. (#252)
Dual-declared run-family options survive before the subcommand (#233)
Follow-up to the argparse copy-back clobber fixed in #84/#232. Those PRs added
default=argparse.SUPPRESS to the common subparser args (_add_common_subparser_args),
but the same clobber still hit options that are dual-declared (top-level and on the
run/resume/dry-run subparser) outside that helper. So phase-loop --force-replan run
silently dropped to False, phase-loop --allow-cross-phase-dirty REASON run to None,
and likewise --rotate-executors, --rotation-mode, --rotation-on-policy-pin (the last
two also clobbered the top-level "phase"/"skip" defaults to None, masked at the call
site by or "phase"/or "skip"), --full-phase, and --no-deprecation-hints. Each
subparser copy now carries default=argparse.SUPPRESS (identical to #232's pattern), so a
value parsed before the subcommand survives in both option positions. The top-level parser
still declares each option with its concrete default, so the attribute is never absent from
the final namespace. CLI-only fix. (#233)
Planner skills emit and reference goal IDs — goal-ID Increment 2 (#211)
The planner skills now produce roadmaps/plans that use the decidable goal-coverage
mechanism shipped in Increment 1 (#247), so it applies to real roadmaps, not just
fixtures. All four harnesses' phase-roadmap-builder emit each exit-criterion led by a
stable goal ID — - [ ] EC-<ALIAS>-<N> — <assertion> — with the convention documented
(all-or-none per phase, unique + alias-scoped, gaps allowed, never reuse/renumber a
deleted ID). All four harnesses' plan-phase and plan-detailed author acceptance
items that reference the roadmap goal by its EC-<ALIAS>-<N> ID and name the
proving command, instead of restating (and drifting from) the goal text — so validation
always checks the plan against the original goal and a plan can never silently weaken
it. validate_plan_doc.py gains a (P) warn: when the anchored roadmap phase declares
goal IDs, every declared ID should be referenced by an acceptance item and every
reference should resolve (no dangling); legacy phases with no goal IDs get no finding.
Opt-in and non-breaking: existing specs/phase-plans-v*.md roadmaps are untouched and
stay not_applicable until re-authored; a phase that declares no goal IDs uses the
prior testable-assertion authoring. No runtime code change (Increment 1 ships the
mechanism); the skills bundle is regenerated and byte-parity is green. (#211)
Broker reconciles publish scope with the branch's actual content (#202)
publish_committed_branch publishes the whole committed branch by (repo, branch, head_sha), and the admission's approval digest covers the coordinator-supplied
owned_paths — but the broker never checked that those owned_paths actually
matched what the branch changed. The broker now re-derives the branch's diff vs its
declared base itself (origin/<base>...head_sha, three-dot — the same derivation
the #201 coordinator uses) and refuses to publish when the admitted owned_paths do
not cover what the branch actually changed, catching drift or coordinator bugs
where the declared scope diverges from the real branch content. Every outcome fails
closed before any push, and each is a proven no-effect (no_effect_terminal_proven
— the push is never reached) distinguished only by its detail string: a changed path
outside the admitted scope → owned-scope-exceeded:<paths>; a non-empty owned_paths
with an empty branch diff → owned-scope-empty-diff (also catches a gamed base==head
ref); a git-diff failure → owned-scope-diff-failed. A #202 reject has zero mutation
ambiguity (nothing was pushed), so it is not outcome_ambiguous_blocked — which is
permanent and poisons the repo's broker epoch, a blast radius a purely-local read-only
git failure must not trigger. no_effect_terminal_proven is also the only valid
provider_call_in_flight → reject transition (rejected_before_start is reachable only
pre-intent, and the service records intent before the adapter runs). Directory
owned_paths entries cover files beneath them, so an over-specified scope never
false-rejects.
Scope note: base is a coordinator-supplied ref name (not the digest-bound
base_sha), so this reconciles against the declared base — it closes accidental
drift and coordinator bugs, not a coordinator that deliberately games the base ref
(binding base into the approval digest would be the stronger, separate step). Only
the run_train prebuilt coordinator path reaches this check today, and it runs in the
node workspace where origin/<base> is already present, so there is no added fetch or
regression. BrokerRequest gains a base field (default main);
publish_from_worktree gains a matching base parameter; the run_train prebuilt
path threads the same _DEFAULT_BASE its owned-paths were derived from. Follow-up
hardening from the #201 panel (codex + grok). (#202)
codex review-leg cannot write the reviewed live tree (#177)
The product-loop review action's codex leg was built with --sandbox danger-full-access (or --dangerously-bypass-approvals-and-sandbox) against the
live worktree — the same as write actions — so a codex review leg could mutate the
reviewed tree. The review action now points codex at a staged copy instead of
the live repo (matching the agy review leg), the airtight barrier for
IF-0-SANDBOX-1 (build_codex_command gains a read_only flag;
build_codex_launch_spec threads read_only=(action == "review"); all winning over
bypass_approvals):
--cd <staged copy>— the review leg's working directory is a throwaway,
gitignore-aware copy of the tree (via the same_stage_review_treeagy uses),
materialized at launch and cleaned afterward. codex cannot reach the live tree at
all, regardless of which config layer (user / system / enterprise) declares an
out-of-sandbox MCP server. This is the primary guarantee.--sandbox read-onlyand--ignore-user-configare kept as defense in depth
(block shell writes; drop user-config MCP; auth still resolves viaCODEX_HOME;
--model/model_reasoning_effortare passed explicitly so the run is hermetic),
and--skip-git-repo-checkbecause the staged copy carries no.git.
A cross-vendor review blocked an earlier flag-only fix (--sandbox read-only +
--ignore-user-config) as an overclaim: MCP tools run outside codex's shell
sandbox (openai/codex#4152) and can be declared in config layers --ignore-user-config
does not drop, so only the staged copy makes the guarantee airtight. This brings the
codex review leg to the IF-0-SANDBOX-1 bar the other vendors already meet (agy =
staged copy, grok = read-only --tools allow-list, claude = plan/read-only), with a
filesystem-level write-proof test.
The shared review-stage cleanup was also hardened (benefiting the agy leg too): the
launch-time cleanup now removes the exact copy paths the materializer created,
rather than inferring ownership from an --add-dir/--cd argv basename — so an
execute run against a live repo that happens to be named pl-review-stage-* can
never be deleted. Stage materialization now self-cleans if the copy or a later
launch-time resolution step (e.g. output-schema materialization) fails, closing a leak
window since staging runs before the launch cleanup finally.
(#177)
Goal-ID single source of truth — Increment 1 (#211)
Redefines #211 from a fuzzy text-diff audit (proven undecidable) into a decidable
goal-coverage check by removing the duplication between a roadmap's goals and a
plan's restatement of them. Roadmap phase exit-criteria may now carry stable
EC-<ALIAS>-<N> goal IDs (mirroring the IF-0-<ALIAS>-<N> gate scheme);
roadmap_lint reconciles them (alias-scoped, unique, all-or-none per phase, gaps
allowed so a deleted criterion never forces a renumber that would silently re-bind a
downstream reference). Phase.exit_criteria stays list[str] (API-compatible); IDs
are exposed via an additive accessor.
A plan's ## Acceptance Criteria items reference the goal IDs (item-leading:
- [ ] EC-P1-1 — proven by <test>) instead of restating the goal. The new
goal_coverage.check_goal_coverage verifies — by pure set membership, no
word-matching — that every declared goal ID is referenced by ≥1 acceptance i...
v0.7.9 — planner producer-dependency fix (#182)
[0.7.9] - 2026-07-14
Planning — validator enforces the producer-dependency contract (fail-fast)
validate_plan_doc.pynow errors when a lane consumes an interface provided by
another in-plan lane it does not depend on directly (a new(O)check). Previously
the plan validator passed such a plan (check F only traced that the interface was
provided somewhere) and the phase-loop lane IR then failed closed at execute time
withmissing_producer_dependency— so a reviewed, signed plan could pass its
canonical validator and design panel, then become non-executable at the
approval/baseline gate.(O)delegates to the runtimephase_loop_runtime.plan_ir
(the single source of truth) rather than reimplementing the parse/identity, so
planning-time and execution-time enforce the same contract by construction — no
interface-normalization or lane-parser divergence (verified: 0 divergences across all
22 committed plans). When the runtime is not importable at plan time,(O)skips (the
execute-time lane IR still enforces the contract). (agent-harness#182)
v0.7.8 — convergence run-train live path from the shipped CLI
[0.7.8] - 2026-07-13
Convergence — the run-train live path now works from the shipped CLI
Completes the broker live-path the SPECPKGMIN pilot surfaced as unusable from the
shipped CLI. Together these make phase-loop run-train actually open draft PRs. The
routing broker keeps a per-repo, per-train admission/evidence store so one node's
ambiguous outcome fail-closes only that repo, never siblings or unrelated trains
(broker root keyed by the roadmap's resolved-path hash).
gh pr createis now a complete non-interactive argv (fix). The broker's
GitHubBrokerAdapterissuedgh pr create --draftwith no--title/--body,
which aborts when gh is not attached to a tty ("must provide --title and --body")
— the branch pushed but no PR opened (outcome_ambiguous_blocked). It now derives
a title from the branch HEAD commit subject, passes the request'spr_bodyas
--body, pins--head <branch>, and appends--draftfor draft requests.
(agent-harness#207)build_routing_broker_client— one broker client serves a MULTI-repo train
(new).build_github_broker_clientbinds onerepo_pathat construction, so a
single client could only serve one repo; a cross-reporun_trainmis-bound
git -C <wrong-repo>on node 2+. The routing client binds a fresh
GitHubBrokerAdapterperBrokerRequest.repo(the node's resolved workspace) AND
keeps a per-repo admission + evidence store underbroker_root/<repo-slug>.
Per-repo stores are load-bearing for safety, not just routing:epoch_blockedis a
global scan over a store and an ambiguous terminal is durable + permanent and can be
tripped by a benign transient (e.g. a one-offls-remote/ghnetwork hiccup →
remote-read-failed/pr-unconfirmed), so a shared store would let one repo's
transient permanently fail-close every other repo. Per-repo stores scope the
fail-closed epoch to exactly the repo whose mutation became ambiguous.
(agent-harness#206)run-trainCLI now wires a broker-authoritative coordinator (fix).
_run_train_commandbuilds aCoordinatorRuntimecarrying the routing broker and
passes it torun_train. Previously the CLI passed no runtime, so every publish
fail-closedbroker_requiredand the train opened ZERO PRs. The broker root is
namespaced per train by the roadmap's resolved-path hash
(<ledger-dir>/broker/<path-hash>) — so two distinct roadmap files, even
same-stemmed and even under one explicit--ledger-dir, get distinct broker roots
and an ambiguous outcome in one train never fail-closes a different train. (Keying on
the stable path rather than the content digest keeps a resumed train on its own epoch
across roadmap edits.) (agent-harness#205)
SPECPKGMIN
- Harness dogfood of the
consiliency-spec-ingestwheel + GP interchange seam.
An env-gated (SPEC_ROOT/GP_ROOT/HARNESS_ROOT) cross-repo integration test that
builds + installs the wheel, runsevaluate(...), and checks the GP interchange
seam; bounds every child process with a timeout. (agent-harness#204)
v0.7.7 — prebuilt-node broker-dispatch in run_train
run-train — prebuilt node publish mode (broker-mediated)
- Land already-committed cross-repo branch work without re-executing the phase.
Train roadmap nodes accept a new**Mode:**attribute:execute(default,
unchanged — runs the per-reporun_loopthen publishes) orprebuilt, which
publishes an already-committed, independently-verified branch WITHOUT any
executor dispatch. A prebuilt node preflights as CLEAN and strictly ahead of
origin/main(clean-but-not-ahead is a preflight error → zero PRs), skips
run_loopand upstream injection entirely, and derives the PR's owned paths from
the committed diff (git diff --name-only origin/main...HEAD). - The prebuilt publish is routed through the credential broker — the same
broker-mediated, exact-head-verifiedpublish_committed_branch/githubpath
execute nodes use (prebuilt=True,broker_client/admissionfrom the
broker-authoritativeCoordinatorRuntime). It pushes the existing branch (by
name, no--force) and opens a draft PR with no new commit. Without a
broker the publish fails closed (broker_required); a prebuilt node never does
a direct push. - Per-node workspace override for arbitrary paths/volumes. Nodes may declare a
**Workspace:** <abs-path>attribute, andrun-traingains a repeatable
--workspace <repo>=<path>flag. Resolution precedence:--workspaceflag >
**Workspace:**attribute ><workspace-root>/<repo>(the unchanged default). - Guardrails. An unknown
**Mode:**value is rejected at parse time with a
coded, node-named(T-G)error (zero PRs). P4 governed merge for prebuilt nodes
is out of scope this release: a prebuilt node under--governedis rejected up
front (zero PRs) rather than emitting a misleading re-verify failure — open the
drafts without--governedand merge the prebuilt PRs manually. Execute-mode
behavior is byte-unchanged; all train invariants (INV-1..7 + merge-SHA
false-green killer) remain green.
v0.7.6 — live-enable publish_committed_branch/github broker verb
Convergence
- Enable live
publish_committed_branch/githubverb (broker-mediated,
exact-head-verified, fail-closed); other verbs remain gated. Flip the single
publish_committed_branch/githubprovider contract toSUPPORTED
(convergence/provider_contracts.py) and add an opt-in
convergence.broker.build_github_broker_client(repo_path, *, broker_root, run=…)
helper that wiresLinearizableAdmissionStore+BrokerEvidenceStore+
GitHubBrokerAdapter+BrokerServicefor a broker-authoritative
CoordinatorRuntime. Every other verb×provider (merge, release, package,
publish, and all non-github providers) staysHUMAN_EXECUTEDand is refused
before start; legacy trains (no coordinator runtime) publish unchanged.
v0.7.5 — convergence coordinator + credential broker (verb-gated skeleton)
Convergence: crash-safe cross-repo coordinator + credential broker (verb-gated skeleton)
- Panel-ratified convergence coordinator (
phase_loop_runtime/convergence/**): frozen contracts
(event schema, result envelope, provider completion-contract matrix + terminal-outcome state machine,
broker verb/admission, reconciliation authority-split, resource-isolation predicate, shared
admission/fencing binding), an append-only event log + exact-state reconciliation, bounded
codex/claude/outside-agent adapters, advisor-seat lifecycle, and transcript-free status. - Single credential-capable broker epoch (
convergence/broker/**): linearizable admission,
terminal effect/no-effect evidence with permanent fail-closed onoutcome_ambiguous_blocked
(no timeout/override escape), canonical(repo,branch,head_sha)idempotency, and
publish_committed_branchwith real exact-published-head verification (git ls-remote+
gh pr list --json headRefOid; any read-failure/mismatch fails closed, never fabricates success). - Adversarial fault suite (crash/partition/stale-worker/delayed-commit/mixed-version/exact-head/
outside-agent-adversarial) proving crash-safety + fail-closed behaviour before any enablement. - Live automation stays DISABLED: every provider verb is classified
HUMAN_EXECUTED, so the broker
refuses all mutations. This ships the live-capable, verb-gated enforcement skeleton; flipping verbs
toSUPPORTED(live GitHub mutation) is a separate, explicitly-authorized step. - Fixes: untrack + gitignore
.dev-skills/handoffs(tracking broke governed closeouts with
dirty_worktree_conflict).
v0.7.4 — run-train actionable roadmap-format diagnostics (agent-harness#60)
[0.7.4] - 2026-07-13
run-train — actionable roadmap-format diagnostics (agent-harness#60)
- Named, coded parse diagnostics for train roadmaps.
parse_train_roadmap
now surfaces the offending node/heading on malformed input instead of failing
opaquely: a malformed**Channel:**descriptor is prefixed with itsnode_id;
a duplicate### Node:block is caught by a new coded(T-F)check before
the topo pass (previously mis-reported as a spurious(T-D)cycle with an empty
node list); and an empty<repo>/<plan-path>component is rejected at parse,
naming the heading. Both parse-time raises are caught at the CLI boundary with a
clean message and zero PRs opened; the duplicate fix is bound to INV-3. The
child-launch/dispatch half was already correct (dispatch locks are keyed per
(repo, roadmap)) and is unchanged; all train invariants (INV-1..6, merge-SHA
false-green killer) remain intact.
Advisor board — heartbeat-aware liveness for the claude/Fable PTY leg (agent-harness#188)
- Reviewer-progress heartbeat, not cosmetic animation. The self-PTY Claude TUI
leg (_run_claude_tui_session) now resets its stall clock only on GENUINE reviewer
progress — novel de-animated terminal text, review-file growth, or transcript
growth. The TUI's animated "thinking" status line (rotating verb + per-second
elapsed counter) and a Node CLI's incidental libuv/GC CPU no longer count as
liveness. This closes a regression where a genuinely-wedged Fable leg (blocked in
ep_poll, ~2s CPU, no output) animated forever and hung ~17 min with no reclaim. - Typed stalled leg. A reclaimed wedge is surfaced as
DEGRADED
(claude_tui_stalled), so the board names the liveness reclaim while the completed
seats are preserved. No fixed model-response timeout is injected when the caller did
not request one — the hard deadline stays the generous_MAXbackstop and the real
kill is heartbeat extinction. - Regression coverage. New PTY-subprocess tests prove a silent-but-animating,
CPU-trickling leg is reclaimed within the stall window; a slow-but-progressing leg
is not killed; and no fixed short timeout is injected on the default path.