Skip to content

Releases: jeet129/praxis

Release list

Praxis 0.1.0

Choose a tag to compare

@jeet129 jeet129 released this 15 Aug 17:06

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...
Read more