feat: composer workflow restructure and factory hardening#126
Merged
Conversation
ulascanzorer
approved these changes
Jun 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Task Reference: [MYMR-237]
Reworks the Piyaz composer (Claude-Code-only) into an end-to-end task factory built on the Claude Code Workflow harness: a Piyaz task goes research → plan → implement → CI gate → review → bounded fix loop → opened PR, and, when the operator authorizes it at run start, merge and continue to the next task. The orchestrator is a thin loop; each task's phase sequencing runs in a deterministic per-task workflow off the main-loop context. Crash-safe recovery, a GitHub-feedback rework round-trip, slim per-phase rule extracts, and per-phase model selection keep it reliable and token-frugal.
Per-task Workflow harness (
skills/composer/workflows/compose-task.js, new)skills/composer/SKILL.md) now owns only the interactive seams: pick the task, launch the per-task workflow, resolve gates, run the merge gate, propagate. The token-heavy phase sequencing moved into deterministic JS, so orchestration stops growing the main-loop context.agentTypewith per-phase model / effort / schema and worktree isolation on the implementer, runs the bounded fix loop (≤2 rotations), and returns one validated structured object the orchestrator branches on (DONE/NEEDS_DECISION/BLOCKED).gh pr checksso no opus agent idles; review is dispatched with a verdict schema (no edit to the sharedreview.md).argstolerate object-or-string delivery;projectIdis threaded into every dispatch (the Piyaz MCP is stateless).Merge gate (new authority)
never(default; HOTL owns the merge) /ask-each/auto-on-approve. Merge fires only on anapproveverdict with green CI; on a clean merge composer runsgh pr merge --squash --delete-branchand writesstatus='done'— the one case the orchestrator writes a status transition, authorized by the operator's run-start choice.neverpreserves today's HOTL-owns-merge behavior.Research hardening
Skill, four phase agents, slim extracts
skills/composer/SKILL.mdrewritten as a lean orchestrator: shared STATUS / result vocabulary, todo-anchored loop with digraph, structural stop conditions, red-flags table, run log, and recovery.composer-researcher,composer-planner,composer-implementer, and the sharedreview) load slim per-phase reference extracts underskills/composer/references/instead of force-loading the full Piyaz specs (researcher spec context ~4,950 → ~2,650 words; reviewer ~6,500 → ~900).references/sources.jsonpins the canonical sources by hash.Reliability, recovery, rework
.piyaz/composer-<project>.md; recovery after compaction via the workflowrunId(resumeFromRunId) plus Piyaz status — Piyaz authoritative on status, the log on history and merge policy.isolation: worktree); default-branch derivation replaces hardcodedmain; merge-forward before PR and each fix rotation; branch-collision and foreign-commit handling; claim ownership with branch-evidence fallback./piyaz:composer rework <taskRef|pr-url>): reviewer-led intake fetches unresolved GitHub review threads (GraphQL, outdated-anchor re-location), re-verifies against HEAD, and feeds the fix loop with a fresh 2-rotation budget.--pipelined): lookahead 1, 7-row brief-invalidation table, kill switch after two consecutive invalidations.App and tooling
lib/context/format.tsnow renders acceptance-criterion ids, closing a bug where the researcher's documented by-id AC rewrite appended duplicates (TDD'd intests/context/format.test.ts; 5 golden snapshots regenerated).scripts/check-plugins.tsgains two CI gates:@-include target resolution across every plugin, and canonical hash pins for the composer extracts (any edit to a pinned Piyaz reference fails CI until the extracts are reviewed and the pin refreshed viabun run sync:plugins).biome.jsoncexcludesplugins/**/workflows/**: the harness script uses top-levelreturn/await, legal only under the harness async wrapper, which biome cannot parse. Local-formatter-only; no packaging effect.Type of change
Testing
bun run check:plugins(mirror sync,@-include resolution, extract pins),bun run format:check, andbun run check:versionpass.lib/context/format.tsAC-id fix is TDD-backed (tests/context/format.test.ts); 5 context snapshots regenerated (bun test tests/context).compose-task.jsvia the Workflow tool against a throwaway draft task (plannableOnly, research → plan); confirmedDONE / outcome=plannedand thedraft → plannedwrite landing in Piyaz. The runs surfaced and fixed three real defects (args-as-string, missingprojectId, haiku research too weak for the role).The 20-scenario regression suite (
tests/plugins/composer-scenarios.md) was rewritten to the workflow architecture and cross-checked against the implementation (0 contradictions in a three-lens audit).Notes for reviewer
agent()dispatch primitive (proven by the research → plan live run), not yet by a full end-to-end run — that is deferred to a real project. Review those stages from the code.compose-task.jsships to users: the plugin installs viagit-subdir(the wholeplugins/claude-codesubdir), the file is git-tracked, andplugin.jsonhas nofilesallowlist; it resolves at${CLAUDE_PLUGIN_ROOT}/skills/composer/workflows/compose-task.js.doneauthority is the only orchestrator status write; it is gated on anapproveverdict, green CI, and an authorizing run-start policy.decompose-*agents still force-load full specs; the rework GraphQL intake reads the first 100 review threads (no pagination yet); a caller-id MCP surface forassigneeIds-based claims.