Skip to content

v0.4.1

Choose a tag to compare

@mikeroySoft mikeroySoft released this 17 Oct 03:57
· 76 commits to main since this release
Immutable release. Only release title and notes can be modified.
51f9e03

Compared against 0.4.0 (9a83868). Released channel stable points at v0.4.1. Patch bump: the closed-loop groundwork — every escalation carries a mechanical code, OMP worker transcripts persist per ticket, factory watch files the factory's own runtime failures as bugs, factory score rates sessions from those transcripts, and a release gate tier runs only on tags.

  • Worker transcripts and escalation codes (#241): OMP workers run with --session-dir .factory/transcripts/<n>/, and the attempt row's transcript names the session file (null for other workers or --no-session). escalate() takes a required code from dispatch.ESCALATION_CODES (gate_failed, worker_stuck, budget, ci_failed, review_revise, approval_drift, …) journaled beside the prose reason; factory stats and human_touch_metrics report the trailing week escalations_by_code, and handoff routing reads the code.
  • Review and manager rounds default to 3 (#231).
  • factory score [--last N] [--dry-run] (#234): scores every finished ticket's worker attempts from the OMP transcripts the dispatcher keeps per ticket and journals one score row per attempt (tool_calls, edits, retries, gate_first_pass, efficiency, compliance, judge_model). Counts come from the session JSONL alone; compliance is a 0–1 LLM-as-judge score through the triage model transport, judging the ticket's Scope and Exit gate against the worker's final message and handoff (the worktree copy, or the retained accepted result once the worktree is removed), that is null, never guessed, when the model is unreachable or does not answer with a number in range. Scored attempts are skipped on later runs, a missing transcript journals skipped: "missing", and a run reads at most 50 attempts and 2 MB per transcript. learn still reads log tails; wiring it to scores is a later ticket.
  • Post-ship monitor (#232): factory watch reads local evidence only — lifecycle exit rows with mechanism_failure (or unknown with worker_exit:*/check_timeout), this repository's failed factory-* user units, and dashboard --runtime-json source errors — and files one bug,needs-triage issue per new failure fingerprint (sha256 of kind/stage/reason-or-unit, 12 hex) with the triggering rows, the newest attempt log tail, the observation excerpt and the reproducing command; filings are journaled as watch rows, never refiled while open, refiled once closed and recurring, at most 5 per pass; --dry-run makes no gh call. factory install runs it from the pass unit's ExecStopPost=, so it runs after a crashed dispatch too and reads that crash from $SERVICE_RESULT.
  • Add-only protected paths (#228): [gate].add_only_paths globs (read from the base ref's .factory.toml, like protected_paths) let a worker add a file or append lines to an existing one without an override; a deletion, rename, mode change, binary change or any removed or changed line (git diff --numstat deleted lines > 0) fails protected-paths with the offending diff and escalates as worker removed or changed existing tests. This repository moves tests/** from protected_paths to add_only_paths; .factory.toml, **/acceptance/**, review prompts and TRACKING stay fully protected and factory-protected-override still bypasses both. factory learn's CURATE allowlist includes the base ref's add_only_paths, so a regression test under tests/** is still accepted.
  • Named human actions (#227): factory/actions.py defines requeue_agent, resolve_and_close and add_needs_triage once — input schema, preconditions, and the decisions request each compiles to. The Ops Attention Re-queue, Close and new Send-to-triage buttons post {repository, action, args} to /api/decisions/prepare, and factory mcp gains factory_prepare_action / factory_apply_action; both paths run the same validation and return the same structured refusal (unknown_action, invalid_args, precondition_failed, routing_refused). requeue_agent and add_needs_triage refuse upstream sync: issues (covers #169). Proposals, journal rows (now including a prepared row) and receipts record caller (dashboard or mcp) and the named action.
  • Release gate tier (#236): [[gate.check]] accepts when = "release"; any when outside attempt/pr/release is a config error naming gate.check[<i>].when. Release checks are reported SKIP (release tier) by the attempt gate and by --tier pr; factory gate --tier release runs only them (no built-ins, no pr or attempt checks) and titles its report Gate report (release tier). factory init's ci.yml gains a release job that installs factory and runs factory gate --tier release on push of a v* tag (the gate job is unchanged), and factory doctor warns (release gate workflow) when .factory.toml has release checks but no workflow runs --tier release.