All notable changes to weft are documented here. Format follows Keep a Changelog, and the project adheres to Semantic Versioning.
weft doctor(/wf-doctor) — template currency. Reports whether a working copy (project-local or user-global) has drifted from the plugin-bundled canonical it was derived from — the one staleness git can't see, since the copies live in different trees. Compares by content hash (key-order/whitespace independent), so only real semantic drift is flagged. Also reports whether the plugin's own git clone is behind upstream (no network; HEAD vs the already-fetched@{u}). Read-only, no persisted state.--jsonfor machine output.weft analyze(/wf-analyze) — per-template run insight. Reads the event log into a per-template rollup: step durations (median/p90 from pairedwf.step_changeddeltas), loop counts, guard-block counts, abandonment + stall counts, slowest step, plus a recurring-friction section joined fromworkflow-qa.jsonl(byworkflow_id). Turns the event log from a record into a feedback loop.wf.guard_blockedevents. The guard engine appends awf.guard_blockedevent (workflow_id,step_id,step_name,pattern,command,tool) when it blocks a tool call — previously blocks were silent, so "does this guard ever fire?" was unanswerable from the log. Matching logic unchanged.wf.stalledannotation + real session-id capture. SessionStart writes the live session id to a per-project<weft_dir>/.session-id(read bycli.pyas a fallback), fixing events logged withsession_id="unknown"; a running workflow idle longer thanWEFT_STALL_HOURS(default 12) gets a pure-annotationwf.stalledevent (state untouched).- Context surfacing in
context.md.generate_context_mdrenders the current step'sdescription, a computedNext action:line (gated onrunning/waiting), and two optional per-step fields —suggest(commands that fit the step) andinsights(💡 hard-won findings) — so the right command and the why-it-bites surface when a step goes active and survive compaction. wf.step_changedpaired start+end events._advance_to_nextnow emits awf.step_changedevent withto_status="running"when each step begins. Auto-skipped optional+requires_skill steps now also emit awf.step_changedwithto_status="skipped".step_loop_backemits the target step'swf.step_changed(pending->running) alongside the existingwf.loop_iterationevent. Dashboards reading events.jsonl can now compute true per-step duration (paired transition deltas) and per-iteration loop timing. Test updated: feature workflow expects 2 * step_count - 1wf.step_changedevents.wf.failedterminal event. When a step'son_fail=blockpolicy lands the workflow infailedstate,step_failemits awf.failedevent withworkflow_id,blocked_at_step,reason,policy. Previously, blocked workflows had no terminal marker so downstream aggregators couldn't compute duration or distinguish "running" from "blocked-and-abandoned".scripts/wf.py— interactive TUI over weft workflows. Curses-based: list view (running workflows + PR/CI status), detail view (per-workflow step + recent events), templates view (discovery). Falls back to the staticwf-monitor.pytable when stdout is not a TTY or invoked with--list/--json/--templates. Reads per-project.claude/weft/state.json + workflow-context.jsonand per-ticket subdirectories. Read-only.scripts/wf-monitor.py— read-only viewer producing a plain-text aligned table over workflows + GitHub PR status. Standalone for scripting (wf-monitor.py --json | jq) or as the data layer behind the TUI.pyproject.tomlwithweftconsole script entry point.CONTRIBUTING.mdand GitHub issue templates.- CI workflow running pytest on push and pull requests.
- User-global templates tier —
~/.weft/templates/*.json(override withWEFT_USER_TEMPLATES_DIR). Discovery order: project-local > user-global > plugin-bundled. - README sections: "Custom templates" (three tiers), "Why not just use TODOs?" (positioning), "Requirements".
- README GIFs (5 total): pitch (agentic chain — preview + start), walkthrough (first-run lifecycle), compose (heredoc → save-template → preview → start), extend (author SKILL.md + reference it from a template), audit (query + raw jsonl + rebuild from events). All recorded with asciinema → agg from the real
weftCLI; reproducible scripts indocs/demos/. - README sections: "Compose your own workflow", "Extend with your own skills", "Auditable by design".
.claude-plugin/marketplace.jsonso/plugin marketplace add dioptx/weftworks.docs/demo.md— annotated end-to-end walkthrough captured from a real workflow run.Makefilewithinstall,test,lint,cleantargets for one-command contributor onboarding.
insightsstep field is now actually populated.generate_context_mdrendered per-stepinsights(💡 lines) and the field was documented, butstart_workflow/rebuild_from_eventsnever copied it from the template into step state — so it silently rendered nothing. Both build sites now carryinsights, matching the existingsuggest-style optional fields. (suggesthas the same latent gap; wire it the same way if a template ever uses it.)
- Date-based
workflow_idnow carries second resolution (name-YYYYMMDD-HHMMSS, wasname-YYYYMMDD). Two same-day runs of one template in one project no longer share an id, so/wf-analyzecounts them as distinct workflows instead of conflating their step timings. PR-scoped ids (name-pr<N>) are unchanged — they stay stable by design./wf-analyzealready groups by thenamefield inwf.started, not by parsing the id, so the format change is backward-compatible for analytics. - README: corrected license, version, install instructions (was a fictional
claude plugin installsyntax — now uses real/plugin marketplace addflow), skill count (10→11, addedwf-compose), and feature-workflow step count (12→11). .claude-plugin/plugin.jsonbumped to0.3.0to match shipped feature set.
templates/publish-repo.json— was specific to the maintainer's portfolio publishing setup (hardcoded paths, repo names, deploy targets). Deployment-specific templates belong in user-global or project-local tiers, not bundled with the plugin.
0.3.0 — 2026-04-10
- Looping constructs in template schema and state machine: steps can declare
loop_back_to,max_iterations,exit_condition. - New transitions
loop-continueandloop-donewithwf.loop_iterationevents handled byrebuild_from_events. - Projections now surface loop count, skill directives, and exit conditions.
- New
/wf-composeskill — reads conversation context, scans the skill registry, and proposes v2 templates with loops + skill blocks (ASCII diagram preview before approval). feature-workflow.jsonupgraded to schema v2: manual review-cycle replaced with an enforced 3-step loop (review → apply-fixes → run-tests).- 12 new tests covering loop lifecycle, rebuild, and behavioral mandate 10. Suite at 187 tests.
- Renamed default feature template to
feature-workflow(previously namespaced to a private workflow).
0.2.0 — 2026-04-09
publish-repoworkflow template — 10-step pipeline ending in a dry-run gate.- Two new template-management skills:
/wf-new-template,/wf-edit-template. - MIT
LICENSEfile. pyrightconfig.jsonfor editor type-resolution.
- Default feature template renamed to remove a private namespace prefix (now
feature-workflow). - Plugin cache refreshed via version bump for new skills to surface.
/wf-rebuildnow preserves step definitions andcurrent_step./wf-rebuildinferscurrent_stepcorrectly for completed and aborted workflows.
0.1.0 — 2026-04-08
- First public cut of weft: deterministic workflow tracking for Claude Code.
- Event-sourced state machine with append-only JSON log under
.claude/weft/. - Built-in templates:
generic(3 steps) andfeature-workflow(12 steps). - Eight smart skills:
/wf-start,/wf-step,/wf-status,/wf-abort,/wf-preview,/wf-rebuild,/wf-dashboard,/ev-query. - Guard engine enforcing per-step
allowed-toolsandblocked-commandsviaPreToolUse. - Stop gate refusing session exit while steps are incomplete.
- Compaction-safe
PreCompacthook writing acontext.mdprojection. - Live curses-based dashboard.
- pytest suite covering event store, state machine, hooks, CLI, and behaviors.