kvasanova/loomwork
SDD lifecycle glue for superpowers + compound-engineering: status-frontmatter convention, drift audit, pre-merge close-out, and strategy/close-out hook gates. One loom, one status surface.
Changelog
All notable changes to loomwork are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.4.1] - 2026-09-17
Added
-
skills/split-agents-md/SKILL.mdsplits one oversized agent guidance file into a tool-agnosticAGENTS.mdplus thin host files that import or reference it. The skill is manual-only — its frontmatter description says so at the trigger surface, so it never fires on its own. It carries the classification procedure that decides what is shared knowledge and what is host mechanics, and it moves any marker-guarded block intoAGENTS.mdsoscripts/init.mjskeeps finding exactly one block to update.A host file holding nothing but the import is still written when the host cannot read
AGENTS.mdnatively. Claude Code is such a host: dropping itsCLAUDE.mdas "import-only" would leave it with no shared guidance at all. Only a host that readsAGENTS.mdon its own — Codex — gets no file.The skill commits only when the user asks. The classification calls are the kind a human wants to review before they land in history.
0.4.0 - 2026-09-16
loomwork becomes a portable Agent Plugins package. Codex can install and run it natively, and the lifecycle gates fire on explicit Codex skill prompts. Claude Code and Cursor are unchanged as supported runtimes.
This release also fixes a bug that made the gates fail silently: they matched
with echo "$x" | grep -q under set -euo pipefail, where grep -q exits on
its first match and the resulting write failure, combined with || exit 0,
turned the gate into a no-op — exit 0, no output, strategy never injected. It
read exactly like a gate that chose not to fire. Reproducing it needs a newline
after the trigger and a tail past the 64KB pipe buffer; a 200KB prompt dropped
the injection 10/10. The Cursor mirrors carried the same defect, where it
mattered more, because beforeSubmitPrompt receives the raw user prompt and an
ordinary pasted log was enough to disable the gate.
Added
- Root
plugin.jsonon the Agent Plugins 1.0 schema, selecting the Codex hook registration throughextensions["com.openai"]..claude-plugin/plugin.jsonremains as the Claude compatibility manifest, and a test keeps the two identities aligned. hooks/codex-hooks.jsonregisters both gates onUserPromptSubmit. Codex observes explicit$superpowers:...prompts only — implicit skill selection produces no signal the gates can identify.skills/init/SKILL.mdexposes the initializer asloomwork:init, so initialization no longer requires the Claude-only slash command.
Changed
- The shared gates accept both payload shapes — Claude
PostToolUseand CodexUserPromptSubmit— and echo the incoming event name back inhookSpecificOutput. - Root resolution is ordered. A non-empty
CLAUDE_PROJECT_DIRis used exactly as given; otherwise the payload's.cwdwalks up to the nearest.gitor.loomwork.json, since Codex may start in a subdirectory, falling back to the raw.cwdso uninitialized repositories still get nudged..gitis tested with-e, so a worktree's.gitfile counts. - The audit and init skills resolve their CLIs relative to the installed
SKILL.mdinstead of requiring a plugin-root environment variable. - A fresh consumer repository now receives
AGENTS.md, notCLAUDE.md. An existingAGENTS.mdstill wins, an existingCLAUDE.mdis still supported, and marker-block idempotency is unchanged. - The strategy gate is spill-aware under Codex. Output past
additionalContextLimit(2500) is truncated and saved to a file, so the message no longer claims the whole strategy is inline; it points at the saved hook-output file when the host truncated. The Cursor mirror keeps the original wording on purpose — Cursor sets no limit and never spills.
Fixed
- Gate matching no longer uses a pipeline. All matching moved to bash
=~against an unquoted pattern variable, withshopt -s nocasematchpreserving the case-insensitivitygrep -qiEprovided in the Cursor gates. Semantics were diffed against the original patterns across representative inputs with zero divergence. hooks/close-out-gate.shno longer reads/.loomwork.jsonwhen no root resolves. It exits silently, matchinghooks/strategy-gate.sh.- Tests no longer leak an ambient
CLAUDE_PROJECT_DIR, which would have made every payload-.cwdtest pass vacuously.
0.3.0 - 2026-08-21
STRATEGY.md belongs to compound-engineering:ce-strategy. loomwork reads it,
points at it, and reminds people to run ce-strategy — it does not define the
file's shape and does not write to it. Close-out had been appending one
## Milestones bullet per merge, creating that section when absent, and bumping
last_updated on every ship, which is the content ce-strategy documents as
optional and skip-by-default. This release removes every loomwork write path to
the file.
Changed
loomwork:close-outStep 3b is a decision, not a write. It asks whether the ship introduced an externally visible milestone, changed what an investment area covers, retired a direction, or shifted the target problem. A yes routes to ace-strategyrun on the feature branch so the update rides the same PR; a no touches nothing. Nolast_updatedbump, no Milestones append, no Tracks or## Not working onedit.- Doctrine restated in
references/PLAYBOOK.mdandREADME.md, with the governing rule recorded so future changes to loomwork's handling of the strategy file can be tested against it.
Added
- Missing-file nudge in both hook gates.
hooks/strategy-gate.shandtemplates/cursor/loomwork-strategy-gate.shpreviously exited silently when no strategy file existed, giving no reminder at the moment grounding matters. Both now inject a one-sentence pointer toce-strategy, each through its own output envelope. The gates check existence only, never shape; behavior when the file exists is unchanged.
Removed
templates/STRATEGY.md— a loomwork-authored variant of ce's template that drifted independently from it.- Strategy-file seeding in
/loomwork:init.initReponow reports the file as missing and namesce-strategyinstead of creating one. An existing strategy file is still left byte-identical, and no already-initialized repo loses content — accumulated## Milestonesentries are left in place.
Fixed
loomwork:close-outStep 5 rangit add docs/... STRATEGY.md, which aborts withfatal: pathspec 'STRATEGY.md' did not match any files(exit 128) when the file is absent, so the commit on the next line never ran. Now guarded on existence. Reachable in practice as of this release, since init no longer seeds the file.hooks/strategy-gate.shresolved its root as${CLAUDE_PROJECT_DIR:-$PWD}and could act on an unrelated directory's strategy file. It now requires a resolvedCLAUDE_PROJECT_DIR, matching the Cursor gate.
0.2.1 - 2026-08-02
Fixed
- Cursor hook commands now invoke gate scripts via explicit
bash .cursor/hooks/loomwork-*.shinstead of the bare path — the bare path let Cursor/Windows open the.shas an editor tab instead of executing it, stealing focus and letting stray keystrokes corrupt shebangs. - Reworded the strategy gate's injected prefix (Claude Code + Cursor) so agents are told the content is already inlined and not to Read/open the strategy file or any loomwork hook script.
/loomwork:initmigrates legacy bare-command.cursor/hooks.jsonentries in place on re-run instead of appending duplicate gates.
0.2.0 - 2026-08-02
First working release. 0.1.0 was a skeleton; everything below is what turned it
into a usable plugin.
Added
- SDD drift audit engine —
scripts/sdd-audit.mjsplusscripts/lib/, ported from weavereads, with unit tests. Flags stale spec status, missing plan DONE banners, and missing/stale verified dates. loomwork:auditskill — runs the drift linter over the SDD docs dirs.loomwork:close-outskill — pre-merge close-out that commits and pushes to the feature branch, so the close-out lands in the same PR./loomwork:initcommand — backed by an idempotentscripts/init.mjsscaffolder that lays down the SDD docs dirs, a STRATEGY.md seed, Cursor hooks, and the CLAUDE.md block.- Hook gates —
hooks/strategy-gate.shandhooks/close-out-gate.sh, wired through the plugin'shooks.json. - Cursor hook templates — dual-event support for
beforeSubmitPromptandpostToolUse, with TDD tests. - Repo templates —
templates/STRATEGY.mdandtemplates/claude-md-block.md. - Configuration —
.loomwork.jsonloading with repo-root walk-up resolution, configurable paths, and a CLI entry point. - Docs — playbook doctrine and README.
Fixed
- Force LF line endings via
.gitattributes; bash scripts break on CRLF. - Resolve
ghinvocations against the correct working directory.