Skip to content

Praxis 0.1.0

Latest

Choose a tag to compare

@jeet129 jeet129 released this 15 Aug 17:06
· 2 commits to main since this release

Changelog

All notable changes to Praxis are documented in this file.

The format is based on Keep a Changelog,
and this project adheres, loosely, to Semantic Versioning
loosely because the library is pre-1.0; some interfaces may still shift between
minor versions until it stabilizes.


Unreleased

Fixed

  • Governance gate count corrected across current-state docs. README (counts table + "What's inside" + architecture diagram + project tree), INSTALLATION.md, PLAYBOOK.md, and docs/{operating-model,quickstart,getting-started,claude-code-setup}.md said "17 gates (6 core + 11 conditional)", but governance/governance.yaml defines 18 — the ideation_refinement_approval conditional gate (end of ideation-refinement-loop.yaml) was never counted, while plugin.json / .claude-plugin/marketplace.json already said 18. All current-state docs now read 18 (6 core + 12 conditional). Root cause: build-registry.py syncs skill/agent/workflow/command counts but not gate counts, so this drift was invisible to CI; the durable fix (teaching the registry to own the gate count) is noted for a follow-up.
  • Full-platform prod-readiness audit (3 parallel reviews: docs currency, ADLC coverage, harness parity). P0s fixed: commands/slice.md contradicted the two-tier delegation canon (told delivery-lead to spawn specialists directly; agents/delivery-lead.md and the Codex praxis-slice both say Lead Developer dispatches, delivery-lead only as fallback) AND never had lead-developer produce the task ledger — breaking the /slice/drive handoff on Claude; the Codex adaptive-model-routing overlay was stale (delivery-lead still listed deep/high vs the canonical standard/medium rebalance; false "identical to every harness" claim; unclosed code fence swallowing two sections; missing routing-examples reference). Parity: added praxis-factory-record (the one missing Codex command; validator now requires it); Codex delivery-lead + lead-developer TOML developer_instructions now carry the core constraints (two-tier delegation, single-writer, drive-mode runner/in-session split, ledger-at-slice-open); the mirror's hooks.json plugin-root var gets a ${CLAUDE_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-}} fallback chain; using-praxis now states the per-spawn model: mechanic is Claude-only (Codex applies routing via regenerated profiles) and names the Codex command surface. Docs: counts corrected everywhere (91 skills / 12 commands / 5-11-1 tiers) across README/INSTALLATION/PLAYBOOK/quickstart/getting-started + 4 harness docs; PLAYBOOK §2.3 no longer calls the plugin "future" (plugin-first install, both harnesses); getting-started leads with plugin install; CONTRIBUTING documents resolve-model/test-routing-parity/governance-overrides/setup-claude-agents; autonomous-drive doc states in-session drive loops continuously; telemetry doc covers the Codex Stop upsert; plugin-builds documents the fail-on-orphan build. Coverage verdict recorded: strong across methodology/brownfield/incidents/UX/routing/data-ML; named gaps (product experimentation + outcome analytics, dynamic security validation/DAST-pentest, evaluative usability testing) deferred as candidate new skills.
  • Drive no longer stops after one task in-session on EITHER harness (root cause, shared agent). agents/delivery-lead.md's Drive mode said "when invoked via /drive or scripts/praxis-drive.sh, execute exactly ONE iteration and exit — the harness re-invokes you." That contract only holds for the unattended runner; under in-session /drive nothing re-invokes it, so the run died after a single task (observed on both Codex and Claude Code). Drive mode now splits the two invocation paths explicitly — runner: one iteration then exit; in-session: complete an iteration then immediately begin the next (or return so the orchestrator can), continuing through the slice drain and into the next ledger — and adds a hard rule: ending a drive run after one completed task with no non-negotiable stop and no stop_after boundary reached is a protocol violation, not "correct one-iteration behavior." commands/drive.md now tells the in-session orchestrator it is the loop and must not report-and-wait.
  • Codex in-session $praxis-drive now loops like Claude's /drive instead of stopping after one task. The Codex skill's header said "You do NOT loop internally" over the whole skill and its in-session step said "one iteration at a time … reporting the outcome each time", so the orchestrator did a single delivery-lead iteration and paused — even under stop_after: gate, where it should continue through the slice drain (code/security/QA review + closure) to the next real stop. "One iteration then exit, no internal loop" is correct ONLY for a delivery-lead invoked by the unattended runner (which re-invokes per iteration); it must not apply to the in-session orchestrator. The skill now scopes that discipline to the runner path and instructs the in-session path to iterate continuously within the session until a non-negotiable stop or the stop_after boundary, explicitly noting per-slice reviews are drain, not governance gates. Matches commands/drive.md (Claude) and skills/autonomous-drive §"stop_after semantics". The unattended runner (praxis-drive.sh --harness codex) already looped deterministically and is the reliable path for whole-slice/workflow drive.
  • workflow-drive no longer crashes on machine-checkable decision_node steps (external review, P1). A decision_node runs no agent, so it left the USAGE_* vars unset — but the telemetry append reads them bare (not ${x:-null}), so under set -u the runner aborted with USAGE_INPUT_TOKENS: unbound variable right after evaluating the step (exactly on the new status_field ideation path). The decision_node branch (and the sub_ledger parse-fail branch) now initialize all USAGE_* + ITER_EFFORT to null, matching the sub_ledger success branch. Verified: a status_field decision_node reaches done (pass) / writes an outcome: failed record with route_back (fail), no unbound-variable abort in either case.
  • Pre-commit now rebuilds the Codex mirror on hook-only changes (external review, P2). hooks/ is packaged by build-codex-plugin.sh but was absent from .githooks/pre-commit TRIGGERS, so a change to only hooks/tap.sh or hooks/hooks.json could commit without regenerating plugins/praxis-codex/hooks/. Added hooks/ to TRIGGERS.
  • Codex drive routing is now actually enforced (external review, P1). The drive runner resolved routing per harness by assuming map was always the model map — but for Codex map is model_reasoning_effort, so Codex iterations recorded iteration_model: "low" (mislabeled effort) and applied nothing (model_flag: null). The runner now resolves the two axes by FIELD NAME (model → model axis, *effort* → effort axis) generically for every harness, skips auto values, and Codex effort is applied as codex exec -c model_reasoning_effort=<level> (model as -m, omitted while the model map is auto). Verified: Codex deep-tier iteration emits -c model_reasoning_effort=high as clean argv, telemetry iteration_effort: high / iteration_model: null; Claude unchanged (--model opus --effort high). autonomy.yaml codex harness gains model_flag: -m, effort_flag: -c, effort_arg_prefix.
  • Codex end-of-session token capture is now wired to the right event (external review, P1). Codex has no SessionEnd (its turn-scoped Stop is the analog, verified against the Codex hooks reference); the packaged plugin registered only SessionEnd, so Codex captured nothing. tap.sh now handles SessionEnd|Stop through one handler; the mirror's hooks.json drops the unsupported SessionEnd and adds Stop; the Stop path emits a valid {} on stdout (Codex requires JSON output for Stop and would treat plain text as invalid — and a bare {} avoids an accidental decision: block continuation). Token capture is now an UPSERT keyed by session id, so a turn-scoped Stop firing more than once refreshes the running total in place instead of double-counting. validate-codex-plugin.sh now rejects any Codex-unsupported hook event name and requires Stop.
  • Generated Codex mirror no longer silently retains stale files (external review, P2). build-codex-plugin.sh replaced the "orphans may linger" fallback: it refreshes every file in place, then reconciles OUT against the exact set it produced and REMOVES anything left over; if a stale file cannot be removed it FAILS (exit 4) rather than publish a dirty public package. validate-codex-plugin.sh already fails on mirror drift.
  • Fallback gates reconciled with governance (external review, P2). A fallback_gate is a human review BOUNDARY (predicate not machine-checkable at runtime), distinct from a governance-matrix gate; validate-workflows.py no longer warns that fallback_gate names are "missing from governance.yaml" (only kind: gate names are cross-checked), and references/phase-gates.md §2 states the distinction. Check-kind regexes are now inline-comment tolerant (matching the runner, which strips comments).
  • Ideation convergence is now genuinely machine-checked (external review, P2). convergence_check persists a deterministic verdict (recommended_disposition, computed from "no findings ≥ major AND next-pass value cosmetic/low") to .project/working/ideation-convergence.yaml, and loop_decision reads it via check: status_field instead of a fallback_gate — so governance.yaml's "machine-checked" description is now true rather than aspirational.

Added

  • /intake ($praxis-intake) — a single steady-state front door for new requirements, so you never pick a workflow by hand. The requirements-intake discipline (triage size + blast radius + owner, sequence, route) already existed as a skill but had no command, which forced manual routing per story/epic. /intake fronts it: drop any new story/ticket/change and it logs to .project/working/inbox.md, right-sizes, and routes to the lightest safe path (small ready story → slice + /drive; touches existing behavior → impact-analysis first; epic/cross-cutting → discover + architect + project-phasing; unproven → spike; P0/P1 → expedited-change), preventing FIFO churn and impulse coding. Wired for all harnesses (Claude/Gemini command files + Codex command skill), registry counts auto-updated (11→12 commands), and the using-praxis router + docs/drive-first-playbook.md steady-state section now point at it.

  • Drive and no-drive now route identically (single source of truth). Previously a spawn's model came from the drive runner (which read the effective table) in drive, but from the baked agent profile (plugin default) in no-drive — so a project override only affected drive. Now one rule governs every spawn: resolve(tier, harness) against the effective table (.project/governance/model-routing.yaml first, plugin default fallback), with force_tier applied. New scripts/resolve-model.py is the shared resolver; adaptive-model-routing / delivery-lead / using-praxis now resolve through it and pass the model at spawn (Claude Code's per-invocation model: beats frontmatter); scripts/setup-claude-agents.sh (+ apply-model-routing.py --claude-out) materializes project-local .claude/agents/*.md that shadow the plugin so the static fallback is override-correct too. scripts/test-routing-parity.sh asserts the resolver and the drive runner agree for every tier on both harnesses and that an override moves both together. Fixed a latent bug the parity test caught: the drive runner ignored overrides.force_tier — it now honors it, matching the resolver and the governance intent ("force every agent to that tier").

  • Project routing overrides now reach the Codex subagent profiles. Previously the .codex/agents/*.toml were generated from the PLUGIN's model-routing.yaml at build time, so a project-level .project/governance/model-routing.yaml override (which the drive loop already honors at runtime) never affected the static subagent profiles — you'd have had to hardcode models in the plugin defaults. Now apply-model-routing.py takes --routing / --project-dir (read the project override, falling back to the plugin default) and --codex-out DIR (write the resolved model / model_reasoning_effort into a target .codex/agents/, leaving the plugin's own files untouched), and $praxis-setup-subagents runs it on install/refresh. Set model_map (pin models) or map (effort) in your project override and re-run setup-subagents to propagate — no plugin edits. Default model_map: auto still writes no model line (subagents inherit the Codex session model). Re-running also refreshes stale effort values (the reason a standard-tier agent could still show high after a tier rebalance).

  • Governance-override drift detection + non-destructive refresh. .project/governance/{model-routing,autonomy}.yaml are seeded once and win over the plugin's copies (so per-engagement tuning survives updates) — which meant new default keys from a plugin update (e.g. the codex effort_flag/effort_arg_prefix that enable per-iteration reasoning-effort routing) never reached an existing project. Now: the SessionStart hook detects the drift (plugin has keys your copy lacks) and prints a warning with the exact fix command; scripts/refresh-governance-overrides.sh [--apply] reports the drift and, on --apply, merges the new keys in while KEEPING your tuned values (backs up first; changed defaults are surfaced for review, never silently overwritten); scripts/governance-overrides.py is the zero-dep diff/merge engine. governance.yaml stays plugin-owned (read from the plugin, not a project override) so gate-topology changes propagate automatically. Docs: docs/codex-setup.md refresh checklist + INSTALLATION.md §6.

  • triage skill (experimental): on-demand discovery scan (git activity, failing tests/CI, tech-debt register, TODO drift, dependency alerts, doc-vs-code drift) that writes a classified inbox (.project/operational/triage/.md) splitting findings into auto-fixable-with-machine-verify vs needs-human vs informational. Zero standing cost — invoked, never scheduled; the scheduled heartbeat stays roadmap-only. Optionally seeds a slice ledger for /drive on explicit ask.

  • Routing v2 (simplified, single tier axis — lane axis deliberately rejected as redundant): each capability tier now resolves to model AND reasoning effort, not just model. Claude gets per-iteration --effort (verified flag: low|medium|high|xhigh|max) alongside --model, and effort: in agent frontmatter — enabling the cheaper cost lever (deep thinking on a standard model instead of a model-family jump). Codex agent TOMLs gain optional model alongside model_reasoning_effort, and drive telemetry captures Codex reasoning_output_tokens separately (verified end-to-end: input=50/cache_read=30/reasoning=42). model: auto / model_map: auto supported = omit the flag/key and use harness default; concrete models stay the library default so per-iteration cost tiering does not regress; project overrides pin per engagement. drive.jsonl gains iteration_effort + reasoning_output_tokens; routing-decision template gains resolved_effort + decision_source. Docs updated (model-routing, adaptive-model-routing, llm-cost-optimization, telemetry, factory-metrics-schema).

  • Workflow-drive — the top-level loop over workflow steps. scripts/praxis-drive.sh --workflow (opt-in, default off) loops a workflow's steps rather than a slice's tasks, reading .project/working/workflow-state.yaml; each step runs on its own phase-tier model — universal per-step model routing that now covers the orchestrator itself, not just specialists. Autonomy zone is C -> D only (implementation through release); discovery/architecture (A/B) stay human-gated, and kind: gate steps plus any non-machine-checkable boundary always stop for a human regardless of the autonomy dial. Schema and step kinds: references/phase-gates.md; protocol: skills/autonomous-drive's "Workflow-drive" section; operator docs: docs/autonomous-drive.md, docs/operating-model.md.

  • Phase-exit predicate hardening. Every workflow decision_node / phase-exit boundary must now resolve to a machine-checkable check (command | artifact_exists | artifact_contains | verdict_file) or declare an explicit fallback_gate for judgment-call boundaries; scripts/validate-workflows.py fails any decision node that does neither — closing the "LLM silently asserts a phase exit" gap. See references/phase-gates.md §2.

  • delivery-planner now emits the workflow-step ledger (.project/working/workflow-state.yaml, one entry per phase/gate/decision-node) alongside the workflow instance it already produced — this is the artifact workflow-drive consumes.

  • Added the ideation_refinement_approval governance gate, closing a pre-existing dangling reference (workflows/ideation-refinement-loop.yaml named the gate before governance/governance.yaml defined it).

  • Routed the router: drive iterations now run on the model the TASK's tier resolves to (new per-harness model_flag in autonomy.yaml: --model for claude, -m for gemini, TOML-profile for codex; recorded as iteration_model in drive.jsonl) — a light-tier task's whole iteration, including delivery-lead protocol execution, runs on the light model. delivery-lead's static tier corrected deep -> standard (measured evidence: routing sessions were the largest deep-tier cost center); deep is now an escalation for re-plans/ambiguous decision nodes/judgment-heavy gates, never a resting state — routing table, per-agent assignments (5 deep / 11 standard / 1 light), and docs/model-routing.md updated.

  • Session discipline codified in PLAYBOOK (7.0): one slice, one session — clear after the slice-close checkpoint (never mid-slice; /compact at task boundaries for long slices); rationale: chosen compaction points beat lossy auto-compaction, fresh context beats quality dilution, and session-per-slice makes tokens.jsonl read directly as cost-per-slice.

  • Artifact-class token hygiene named per surface (generic AOP rule made rationalization-proof): qa-engineer suite-run hygiene (quiet reporters, log capture, summary + failing extracts; coverage summaries only), platform-sre pipeline/deploy/IaC-plan log hygiene, static analysis to file with top-N consumption in /audit (all copies), code-reviewer exclusion of generated/lock artifacts from ingestion (consistency-check instead), and testing-strategy now mandates quiet reporters as the test-plan default with verbose re-runs on demand.

  • Live per-invocation token capture: SubagentStop hook computes the transcript usage DELTA since the last cursor position and writes it to agent-spawns.jsonl attributed to the finishing agent (event: invocation_usage; concurrent spawns honestly share a delta); factory-routing-report.py renders a 'Real tokens per agent' table; cursor cleaned at SessionEnd. Cost is now visible DURING runs, not only at session end.

  • Evidence-first token optimizations with explicit quality guards: hand-off reply contract (<=15-line structured replies, artifacts on disk — blockers/deviations/uncertainty are MANDATORY fields, never compressed away), read discipline (grep-to-locate before Read; reviewers work diff+context; reading deeper is always permitted when judgment requires — only mechanical over-reading is targeted), cache-aware spawn-prompt ordering (stable prefix first, volatile state last; drive's constant prompt documented as deliberate cache design), and diff-scoped review guard in code-reviewer with 'review depth is never budget-capped' stated verbatim.

  • Token attribution ladder completed: sidechain-aware per-agent-invocation attribution in factory-token-report.py (main-vs-sidechain split, invocation segments with best-effort agent identity), task started_at/completed_at timestamps in the ledger (stamped on status change, drive and interactive alike) enabling window-attributed per-task tokens in interactive sessions — clearly labeled approximation vs drive.jsonl's exact per-task measurement; attribution ladder documented (session exact > drive task exact > sidechain measured > interactive window approximation).

  • Token telemetry made universal: SessionEnd hook now sums each session's own Claude Code transcript into .project/telemetry/tokens.jsonl (deterministic, every session — interactive or driven); factory-token-report.py treats hook records as authoritative with transcript mining as gap-fill; ceremony honored at pre-merge review in ANY mode (delivery-lead general discipline, not drive-only); tool-output hygiene promoted to a universal AOP rule in using-praxis.

  • Real token telemetry: praxis-drive.sh captures actual usage + total_cost_usd from headless JSON output into drive.jsonl; new scripts/factory-token-report.py mines Claude Code session transcripts for per-session/model/day/slice token totals with a proxy-calibration table; factory-routing-report.py surfaces real tokens/USD per drive run and its prose-dispatch parser now counts routing-frontmatter files (PortiQ validation: 0 -> 13 dispatches).

  • Verify-output hygiene: verify commands authored quiet, full output captured to .project/working/verify-.log, model consumes exit code + failure extract only (loop-contracts, autonomous-drive, lead-developer) — tool-result token sink closed.

  • Adaptive ceremony: task ledgers carry ceremony: full|expedited|spike scored at slice open (reversibility x blast radius x production exposure; security-bearing surfaces force full), drive drains gates accordingly (expedited = single blocker-only review + mandatory retro; spike = report artifact, never merges); engagement switches in governance/autonomy.yaml; governance gates unaffected.

  • Honest harness test-status published everywhere support is claimed: tested end-to-end on real engagements = Claude Code + Codex; adapters shipped and structurally validated but under test = Gemini CLI, Cursor, OpenCode, Copilot, Kiro, Antigravity. Publishing-readiness sweep synced all counts (90/17/9/11/17) and telemetry descriptions across README, INSTALLATION, PLAYBOOK, and every docs page.

  • Telemetry redesigned around checkpoint records — the universal aggregation point at EVERY closure boundary (gate, phase end, slice close, loop convergence, disposition, workflow end), covering discovery/architecture/ideation/release phases that have no slice: structured episodic entries (agents_dispatched, skills_consumed, artifacts, cost_proxy, human touchpoints) written by delivery-lead at the AOP Document step; new scripts/factory-usage-report.py mines checkpoints + packets/ledgers/routing/commands/sessions into per-skill/agent/workflow usage analytics; hooks/tap.sh slimmed (retired the ~5%-capture per-Read and preload stub files and per-session stub files — sessions now one JSONL line each); factory-frequency/aging marked legacy; factory-evaluation and docs/telemetry.md updated to the mined-artifacts model. Zero incremental token cost: analytics ride on artifacts the workflow already produces.

  • Brownfield parity for governance seeding: /audit (all copies + Codex praxis-audit) gains a Day-0 setup step — initialize the .project tree, seed .project/governance/ overrides, and ask the same routing/autonomy tuning question as /start, with a brownfield-specific suggestion of stop_after: slice until characterization-test coverage is trusted.

  • Governance overrides now seed automatically: the SessionStart hook copies model-routing.yaml + autonomy.yaml into .project/governance/ on first session (project copies win, survive plugin updates), and /start (all harnesses incl. Codex praxis-start) asks the user once whether to keep default adaptive routing/autonomy or tune force_tier / cost_weights / stop_after / run_budget for the engagement — answers applied to project copies only. build-registry.py now also maintains the /start count line.

  • Per-project governance overrides: .project/governance/model-routing.yaml and .project/governance/autonomy.yaml now win over the plugin-shipped copies (consumed by praxis-drive.sh, factory-routing-report.py, and delivery-lead's runtime routing) — engagements can tune force_tier / cost_weights / stop_after / budgets without editing the installed plugin; documented in docs/model-routing.md.

  • UI-quality enforcement wired end-to-end: visual_review branch in the pre-merge gate of implementation-slice.yaml (ux-designer reviews implementation screenshots against the design plan/tokens/frontend-design calibration; fires only on UI-bearing slices; blockers feed the same fix loop), UX hand-off now emits design_tokens + design_plan, FE/mobile branches capture ui_screenshots as evidence, task ledgers gain a visual_review gate key and token-lint in FE task verify, ux-designer produces .project/semantic/design-brief.md at first engagement, and delivery-planner gains a design_fidelity flag.

  • frontend-design skill (experimental): harness-portable visual-design craft adapted from Anthropic's open frontend-design skill — subject-grounded direction, two-pass plan-then-critique process, anti-generic calibration (the three AI-default looks), interface-copy rules, and a free-first design-tooling fallback chain (Figma MCP -> community/Penpot -> Stitch/v0 free tiers -> token-themed shadcn baseline -> text-only floor). Consumed by frontend-developer, mobile-developer, and ux-designer.

  • Three new workflows + six conditional governance gates. workflows/expedited-change.yaml
    (P0/P1 incident or critical-security-patch fast path: compressed gates now —
    scope containment, blocker-only combined review, rollback readiness —
    gated by expedited_change_approval, repaid by a MANDATORY retroactive
    full review + blameless postmortem + tech-debt entries, gated by
    expedited_change_retro); workflows/spike.yaml (time-boxed feasibility
    exploration; a bounded build-to-learn loop with no review gate on the
    throwaway code, gated only at disposition — spike_disposition
    archive or promote the report into discovery; spike code never merges);
    workflows/modernization.yaml (strangler-fig legacy replacement: deep
    comprehension + seam identification, target architecture + migration
    strategy sign-off at modernization_strategy_sign_off, a per-seam
    increment loop with characterization tests + implementation-slice
    sub-workflow + parallel-run comparison telemetry gated at
    parallel_run_verification, then a gated legacy decommission phase at
    legacy_decommission_approval). Total: 9 workflows, 17 gates (6 core +
    11 conditional). Plus a "Workflow composition policy" section in
    skills/using-praxis/SKILL.md and a workflow-selection table in
    skills/delivery-planner/SKILL.md: a scenario earns a new workflow file
    only when its gate topology differs, otherwise it's planner
    parameterization of an existing template — the anti-sprawl rule that
    keeps workflow-count creep a factory-evaluation decay signal alongside
    skill-count creep.

  • Autonomous drive mode. scripts/praxis-drive.sh — a Ralph-style outer
    runner that re-invokes a fresh-context harness against the task ledger
    until a stop condition fires (exit codes: 0 natural, 3 stalled, 4
    budget, 5 blocked); the autonomy dial (stop_after in
    governance/autonomy.yaml, the three non-negotiable stops, the
    first-slice-of-phase rule) plus run budgets and stall detection; loop
    contracts and the task ledger schema (references/loop-contracts.md,
    .project/working/slice-<id>-tasks.yaml); the skills/autonomous-drive
    delivery-lead protocol; the /drive command; drive telemetry at
    .project/telemetry/drive.jsonl plus a drive section in
    scripts/factory-routing-report.py; slice-close async summaries at
    .project/telemetry/summaries/; new operator docs
    docs/autonomous-drive.md and docs/operating-model.md.

  • Cost/routing telemetry completed: hooks/tap.sh now writes deterministic spawn/completion events (with model and token fields when available) to .project/telemetry/agent-spawns.jsonl; scripts/factory-routing-report.py aggregates structured telemetry, prose routing logs, and usage records into a per-slice routing/cost report (cost proxy via cost_weights in governance/model-routing.yaml); JSONL schemas documented in references/factory-metrics-schema.md.

  • Documentation overhaul: new docs/quickstart.md (5-minute path), docs/telemetry.md, docs/model-routing.md; README docs index; per-tool verify-your-install checklists; CONTRIBUTING validator/generated-surfaces/skill-authoring guides.

  • Pre-commit hook now reminds the committer to double-check documentation when core artifacts change without any doc change (non-blocking).

  • Four new skills (state: experimental): feature-flags-progressive-delivery, schema-migration, caching-strategy, developer-experience.

  • Abstract capability tiers. Agents now declare a harness-agnostic capability_tier
    (deep | standard | light) in frontmatter instead of a concrete model name.
    governance/model-routing.yaml is the single file that maps tiers to concrete
    models per harness (Claude Code, Codex, Gemini CLI); scripts/apply-model-routing.py
    applies the mapping and rewrites agents/*.md frontmatter and
    codex-plugin-assets/codex-agents/*.toml accordingly (--check mode for CI).

  • Runtime ±1-tier adaptive routing. delivery-lead scores each sub-agent spawn
    against the adaptive-model-routing rubric and may shift the agent's default tier
    up or down by one step; on gate failure it promotes one tier and retries once before
    escalating to the human. Every routing decision is logged to
    .project/telemetry/model-routing.jsonl for cost/quality analysis.

  • definition-of-done skill — a shared, explicit checklist agents apply before
    declaring a slice, phase, or release complete.

  • mobile-developer agent — a new specialist role for mobile-stack implementation
    work, following the existing Tier-2 specialist pattern (backend/frontend/data/ml).

  • Registry + validator scripts and CI — scripts that build and check the
    agent/skill/workflow registry (scripts/build-registry.py --check), wired into CI
    so skill/agent/workflow counts and cross-references stay accurate without manual
    bookkeeping.

  • 10 new reference files — filled in from the highest-priority items tracked in
    references/MISSING-INVENTORY.md.

  • Repo governance docsCHANGELOG.md (this file), SECURITY.md, ROADMAP.md.

Fixed

  • External-review blockers (workflow-drive, all 4 + validator gaps): nested block-form exit.args now parse (parse_steps_block rewritten); new status_field check kind reads a dotted field from a file and compares to expect (phase-gates §2); failed workflow exits now stamp status=failed + completed_at + raise stop_flags instead of leaving steps stuck in_progress; decision_node steps with a machine check are evaluated (not auto-stopped); 12 decision_nodes that used check:command with no runnable cmd (silent false-pass) converted to fallback_gate with the expr kept for interactive evaluation; validate-workflows now fails any check:command lacking a cmd/command arg (the false-pass class) and accepts status_field; build-codex-plugin falls back to overwrite-in-place when deletes are blocked (fixes stale mirror); validate-codex-plugin fails on missing phase-gates.md or a praxis-drive.sh/autonomous-drive/loop-contracts mirror drift.

  • validate-codex-plugin.sh now respects TMPDIR (falls back to a repo-local scratch file) instead of hardcoding /tmp — the validator no longer fails on sandboxes where /tmp is locked; CI unaffected.

  • Ledger status vocabulary enforced end-to-end (real defect: LD authored status: pending, runner silently drained): the runner now hard-stops (exit 5) on unknown status tokens naming them with the fix; interactive-only tasks (verify: null) are skipped by the runner but surfaced at drain instead of ignored; vocabulary declared CLOSED in loop-contracts and lead-developer with the pending trap called out; tier-assignment ownership clarified (LD proposes per-task tier at authoring from agent defaults + fast-paths; dispatcher applies final +-1 at spawn and logs). Also fixed the residual --model-reasoning-effort flag-override mention in the Codex routing overlay.

  • Codex telemetry parity (external review, all 7 findings verified true): pre-commit now runs apply-model-routing --check before the codex build; hooks/ packaged into the Codex plugin with a hooks manifest key (generated, not hand-edited); tap.sh is harness-aware (generic PLUGIN_ROOT, TAP_TOOL detection incl. codex, dual transcript stores ~/.claude/projects + ~/.codex/sessions, tolerant usage shapes incl. turn.completed with cached_input_tokens mapping); drive runner gains a codex-json usage parser (codex exec --json event stream) with json_output_flag/usage_parse wired in the codex harness config; fabricated codex --agent CLI syntax replaced with documented .codex/agents/ profile behavior; validate-codex-plugin.sh enforces all of the above; codex-setup.md gains the post-update refresh checklist (reinstall, setup-subagents with overwrite, hook trust, drive token verification).

  • Routing-log schema drift: resolved_model is now a REQUIRED field in the routing decision template (deterministic — chosen_tier mapped through the governance harness map, never guessed); reports key on tiers so older records stay valid. Token-capture failures are now observable: the SessionEnd hook writes a token_capture_skipped breadcrumb to sessions.jsonl (transcript not found / jq missing / no transcript store) instead of silently producing nothing.

  • Drive runner discoverability: /drive (all copies) and the drive docs now explain that praxis-drive.sh ships inside the PLUGIN, with concrete resolution per install type (find ~/.claude/plugins for marketplace installs, ./scripts/ for install.sh, clone path for --plugin-dir) and a clear 'not found = plugin predates drive mode, update it' hint — previously all references used a bare relative path that only worked for file installs.

  • tap.sh no longer requires jq for SessionStart/SessionEnd: governance seeding and session logging now run without jq (degraded session id), and only tool-event parsing bails when jq is absent — a missing jq previously killed the entire hook layer silently.

  • Routing-decision logging made resilient: delivery-lead now embeds the tier decision (agent/default_tier/chosen_tier/score/reason) in every routing-*.md frontmatter as part of the routing-transparency discipline it demonstrably follows, with the model-routing.jsonl append folded into the same step; factory-routing-report.py recovers frontmatter decisions as decided records when the JSONL is missing; session-start hook pre-creates .project/telemetry/ so appends cannot fail on a missing directory.

  • Visual review propagated to ALL harness surfaces after double-check: greenfield-saas's inline review cluster (visual_review step + FE branch screenshots + frontend-design skill), Codex praxis-slice command skill, /slice command in all four copies, autonomous-drive drain step, definition-of-done (now nine gates incl. visual review), using-praxis slice chain, output-skill-map telemetry patterns, and screenshot-capture duty in frontend/mobile developer agents. Found and fixed real drift: .claude/commands/{slice,release}.md had fallen behind the canonical commands/ copies — now synced, and CI gains a command-copy drift check so it cannot recur. Brownfield-enhancement and modernization inherit visual review via the implementation-slice sub-workflow.

  • Cleared remaining line-budget warnings: Codex adaptive-model-routing overlay slimmed 369 -> 298 (examples/tables to references/), using-praxis 330 -> 299 (gate-topology and agent-mapping tables to references/); validate-skills.sh now counts capability: command adapter skills separately from the 70-90 knowledge-skill health band.

  • Delegation-chain contradiction resolved: canonical two-tier model is now unambiguous — Lead Developer (not Delivery Lead) dispatches specialists per the ledger DAG and validates integration; Delivery Lead resumes at review gates. Harness fallback documented for environments that cannot nest agent spawns. Parallelism rule made explicit everywhere (delivery-lead, lead-developer, implementation-slice.yaml, loop-contracts, Codex praxis-slice): dependencies are on contract artifacts, not on sibling implementations — FE/test start when the contract lands.

  • Drive runner stop summary no longer over-counts iterations by one; scenario operational playbook added at docs/scenarios.md; README value prop, badges, and counts brought fully current; PLAYBOOK/quickstart counts and command lists synced (11 commands incl. /drive).

  • Second external review (8 findings): restored executable bits on all scripts/hooks (now CI-checked); unified the last stale routing-log path in using-praxis; fixed install.sh Cursor rule filename; added the 3 missing Gemini command TOMLs (review, refine-idea, factory-record — Gemini now has all 10); using-praxis routing tree/table now covers /refine-idea, /review, /factory-record and describes Markdown commands; /start counts corrected and now auto-routes to the next phase instead of prompting; CI now rebuilds and freshness-checks the Codex package, verifies exec bits, telemetry-path consistency, and installer path references; gate count (11) now derived from governance.yaml by build-registry.py and corrected in both manifests.

Changed

  • External-review fixes: .claude/commands/ now carries all 10 Markdown commands and install.sh/INSTALLATION.md describe the .md command format; routing telemetry unified on .project/telemetry/model-routing.jsonl; ideation-refinement-loop artifact state made explicit (loop_state.current_artifact / previous_artifact with a state_update step); Codex adaptive-model-routing overlay aligned with capability tiers (6 high / 10 medium / 1 low, generated — not hand-edited); added Codex praxis-refine-idea command skill; validate-codex-plugin.sh now requires mobile-developer; build-registry.py also maintains slash-command counts and README/install.sh count phrases; trailing whitespace cleaned.

  • Library-wide progressive-disclosure pass: every SKILL.md now <=300 lines; embedded templates, worked examples, and long code blocks moved to per-skill references/ files (19 skills slimmed this round).

  • Reliability-cluster ownership boundaries clarified: resilience-patterns (in-process fault handling), distributed-systems-patterns (cross-service coordination; now owns outbox/saga), reliability-dr (availability architecture), chaos-engineering (verification practice).

  • Skill slimming — trimmed several SKILL.md bundles to reduce redundancy and
    keep the library under its own bloat thresholds (see PLAYBOOK.md §10,
    "library is starting to feel bloated").

  • README.md and PLAYBOOK.md updated to describe capability-tier routing in place
    of the previous Opus/Sonnet-hardcoded language, and to be explicit that YAML
    workflows are declarative specs interpreted by delivery-lead, not a deterministic
    execution engine.

  • scripts/build-codex-plugin.sh — generated Codex package README now warns
    explicitly that the generated output is not the place to make edits.


0.1.0 — initial library

The first public release of Praxis: a tool-portable AI-delivery platform — skills,
role agents, workflows, and governance gates for end-to-end software delivery with
AI coding agents.

Added

  • Role-agent library covering delivery lead, product/discovery, architecture
    (+ architecture challenger), UX, backend/frontend/data/ML specialists, code
    review, security review, QA, tech writing, platform/SRE, and system-steward
    roles.
  • SKILL.md library spanning foundation, lifecycle, discovery, architecture, UX,
    stack packs, quality + security, build + deploy, ops, data, ML, agentic-AI,
    and maintenance disciplines — each with an anti-rationalization table and a
    verification checklist.
  • Named workflow compositions: greenfield-api-service, greenfield-saas,
    brownfield-enhancement, implementation-slice, production-release.
  • Governance gate set (governance/governance.yaml) with evidence packs and an
    approver matrix, including requirements_freeze, architecture_sign_off,
    production_go_live, responsible_ai_review, and steward_promotion.
  • Adaptive model-routing skill (5-signal scoring rubric).
  • Telemetry stack: hooks/tap.sh PostToolUse tap + factory-record.sh +
    factory-aging.sh + factory-frequency.sh.
  • Multi-tool install paths: Claude Code plugin-dir, Codex plugin marketplace,
    file-based install for 8 supported AI coding tools.
  • Six-type project memory taxonomy under .project/.
  • Cross-cutting reference library plus references/MISSING-INVENTORY.md tracking
    the remaining backlog.