Ouroboros PM Interview
Q00/ouroboros
Runs a guided product-manager interview that classifies each question automatically and produces a Product Requirements Document.
A skill your agent uses when the user types /piyaz:composer, /piyaz:composer <taskRef, or /piyaz:composer rework <taskRef|pr-url, or asks to run the next Piyaz task end-to-end, ship the backlog…
The automated check flagged lines worth reading first. See the safety section below.
$ npx skills add FrkAk/piyaz --skill composer -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install FrkAk/piyaz composer --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/claude-code/skills/composer .claude/skills/composer && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .claude/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composerType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add FrkAk/piyaz --skill composer -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install FrkAk/piyaz composer --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/claude-code/skills/composer .agents/skills/composer && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .agents/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add FrkAk/piyaz --skill composer -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install FrkAk/piyaz composer --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/claude-code/skills/composer .cursor/skills/composer && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .cursor/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/FrkAk/piyaz.git --path plugins/claude-code/skills/composer--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add FrkAk/piyaz --skill composer -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install FrkAk/piyaz composer --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/claude-code/skills/composer .gemini/skills/composer && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .gemini/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install FrkAk/piyaz composerInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add FrkAk/piyaz --skill composer -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/claude-code/skills/composer .github/skills/composer && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .github/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add FrkAk/piyaz --skill composer -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install FrkAk/piyaz composer --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/FrkAk/piyaz.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/claude-code/skills/composer .opencode/skills/composer && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "composer" agent skill from https://github.com/FrkAk/piyaz/tree/main/plugins/claude-code/skills/composer into .opencode/skills/composer/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "composer", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
composerA skill your agent uses when the user types /piyaz:composer, /piyaz:composer <taskRef, or /piyaz:composer rework <taskRef|pr-url, or asks to run the next Piyaz task end-to-end, ship the backlog…
Composer is an agent skill from FrkAk/piyaz. Use when the user types /piyaz:composer, /piyaz:composer <taskRef, or /piyaz:composer rework <taskRef|pr-url, or asks to run the next Piyaz task end-to-end, ship the backlog, compose through the ready queue, or loop through Piyaz tasks until done. Composer researches, refines, plans, implements, reviews, and fixes each task in a loop until the PR is ready, and merges and continues when the user authorizes it. Do NOT invoke for one-off task lookups, status checks, hand-refinement of one task, or interactive…
Its SKILL.md is about 8.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including reference files (for example `references/implementer-rules.md`, `references/planner-rules.md` and `references/researcher-rules.md`).
It sits in Product & Project Management. It works with Model Context Protocol. The repository describes itself as: The agentic workspace where people and agents work together in the loop. The licence is AGPL-3.0.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit a0d97a4. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
gitghFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git and gh, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Composer loads about 8.6k tokens when it runs, and up to ~20k if it reads all its reference files. Until then it costs about 159 tokens; SKILL.md has 4,239 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found patterns that need a careful read before installing.
ical-path yes/no, one-sentence reason). Do not wait for approval; the user interrupts if they disagree.Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from FrkAk/piyaz at commit a0d97a4, republished under its AGPL-3.0 licence (© FrkAk). 4,239 words, ~8,593 tokens.
.claude/skills/composer/SKILL.md (or your agent's skills folder). This skill also uses 6 other files; get the full folder from GitHub.Composer is a Piyaz task orchestrator. Per iteration it picks the next ready task off the project's critical path, runs that task through a deterministic per-task workflow (research, plan, implement, CI gate, review, bounded fix loop), surfaces the verdict, merges when the user authorized it, propagates the result through the graph, and continues until a structural stop condition holds.
The orchestrator (this skill, running in the main loop) owns only the interactive seams: pick the task, resolve gates, run the merge gate, propagate. The token-heavy phase sequencing runs inside the workflow, off the orchestrator's context, dispatching the phase agents in fresh windows with per-phase model and effort. This is the design's main token discipline: orchestration is JavaScript, not main-loop reasoning over a transcript that grows with every phase.
Composer is glue. The heavy lifting (task selection, refinement, the Completion Protocol, propagation) lives in the piyaz skill (skills/piyaz/SKILL.md); composer reuses those flows rather than duplicating them.
/piyaz:composer: backlog mode. Pick the highest-value ready task each iteration; continue until a stop condition holds./piyaz:composer <taskRef>: single-task mode. Same pipeline applied to one task; exits after the iteration completes./piyaz:composer rework <taskRef|pr-url>: rework mode. HOTL requested changes on GitHub instead of merging; composer rounds that feedback back through the fix loop./piyaz:composer --pipelined: backlog mode with research-ahead (latency-only, costs tokens). Off by default; see Pipelined research-ahead.No argument means backlog mode; rework plus an argument means rework mode; anything else is single-task.
The canonical piyaz rules load with this skill. Downstream citations (conventions §1, artifacts §3, lifecycle §3) refer to this loaded text.
@skills/piyaz/references/conventions.md @skills/piyaz/references/artifacts.md @skills/piyaz/references/lifecycle.md @skills/piyaz/references/resilience.md
Each iteration's task runs through skills/composer/workflows/compose-task.js, launched with the Workflow tool:
Workflow({
scriptPath: "${CLAUDE_PLUGIN_ROOT}/skills/composer/workflows/compose-task.js",
args: { taskRef, taskId, projectId, categories, tagVocabulary,
pickEstimate, pickPriority, workType, tags,
mode, plannableOnly, resumeFrom, priorBrief, gateAnswers,
fixFindings, prUrl, priorFailure, estimate, flags, fable },
})If ${CLAUDE_PLUGIN_ROOT} does not resolve in the tool argument, substitute the absolute path of this plugin's root. The workflow runs in the background; the orchestrator is suspended until it returns, so it spends no context tokens while phases run.
The workflow dispatches the phase agents by agentType, each with explicit model/effort/schema, the implementer with isolation:'worktree'. It runs research+plan → implement → ci-gate → review → [fix-loop ≤2 rotations], with a fixed-interval CI poll (60s, bounded) and a CI-pending re-poll path that re-reviews without burning a fix rotation, then returns one structured result. It does not merge, propagate, or touch edges; those are the orchestrator's seams. The phase contracts live in the agent files; do not duplicate them here.
| Phase | agentType | Writes to Piyaz | Workflow captures |
|---|---|---|---|
| 1+2. Research+Plan (merged) | piyaz:composer-researcher under an orchestrator authority grant | refinement fields (description, acceptanceCriteria, tags, category, priority, estimate, decisions) plus implementationPlan; status='planned' on draft → planned only | brief, status, gatePhase, flags, confidence, refined estimate/work-type, proposed rewrites, section/step counts, open questions |
| 3. Implement | piyaz:composer-implementer | status='in_progress' (claim), status='in_review' (+ Completion Protocol); fix mode rotates in_review → in_progress → in_review | status, PR URL, AC counts, concerns |
| CI gate | generic (haiku) | nothing | green / red / pending / none, failing checks |
| 4. Review | piyaz:review (dispatched with a verdict schema) | nothing (read-only) | verdict, blocking findings |
The workflow returns exactly one of three shapes. Branch on result.status, not on prose:
status | Meaning | Orchestrator reaction |
|---|---|---|
DONE | Task ran to in_review (or planned for a plannable-only pick) | Surface the verdict, run the Merge gate, propagate |
NEEDS_DECISION | The merged research+plan phase gated; result.gate carries the trigger and result.phase names the raising half (research or plan) | Resolve via Gates, then relaunch the workflow with the answer |
BLOCKED | A phase could not complete; result.phase and result.reason say which and why | Failure handling |
A DONE result also carries: outcome (in_review|planned), verdict, prUrl, ciState, acSatisfied/acTotal, rotations, escalated (true when a block verdict or an exhausted fix budget left findings unaddressed), blockingFindings, concerns. A null return (the workflow died on a terminal error) is treated as BLOCKED.
Once per session, before the first iteration:
piyaz_workspace action='projects' and note the identifier; pass it (or a taskRef) on every call — there is no server-side selection. Single-task mode: also piyaz_search query='<taskRef>' to confirm the task and its current status.piyaz_get view='meta'. Keep the categories and tag vocabulary for the workflow's research args; drop the status counts.piyaz_search project='<identifier>' status=['in_progress'] for tasks already claimed. Surface possible stale claims from dead sessions in the first pick rationale.the AskUserQuestion tool: never (default; HOTL owns the merge), ask-each (confirm per PR), or auto-on-approve (merge automatically on an approve verdict with green CI, and auto-remove safe worktrees at run end). Record the choice; it holds for the whole run. When AskUserQuestion is unavailable (headless), default to never.mkdir -p .piyaz and guard the gitignore (grep -qxF '.piyaz/' .gitignore 2>/dev/null || printf '\n.piyaz/\n' >> .gitignore). If .piyaz/composer-<projectIdentifier>.md exists and ends with RUN_END, archive it to .piyaz/archive/composer-<projectIdentifier>-<date>.md and start fresh; if it exists without a RUN_END, that is a resume signal — see Recovering after compaction first. When the unfinished log's RUN_START mode= differs from this invocation, append RUN_END reason=superseded-by-<mode>, archive, and start fresh. Then append RUN_START mode=<...> mergePolicy=<...> project=<identifier>.Then start iterating. There is nothing to install and nothing to confirm beyond the merge policy.
At the start of each iteration, materialize these todos and mark them off (the todo list is your compaction anchor): pick, launch workflow, handle result, surface verdict, merge gate, propagate.
digraph composer_iteration {
"Pick next task" [shape=box];
"Ready or plannable task?" [shape=diamond];
"STOP: backlog drained" [shape=doublecircle];
"Launch compose-task workflow" [shape=box];
"Result status?" [shape=diamond];
"Resolve gate with user" [shape=box];
"Continue this task?" [shape=diamond];
"STOP: iteration ends (single-task)" [shape=doublecircle];
"Failure handling" [shape=box];
"outcome = planned?" [shape=diamond];
"Surface verdict" [shape=box];
"Merge gate (per policy)" [shape=box];
"Propagate" [shape=box];
"Single-task mode?" [shape=diamond];
"STOP: iteration complete" [shape=doublecircle];
"Pick next task" -> "Ready or plannable task?";
"Ready or plannable task?" -> "STOP: backlog drained" [label="no"];
"Ready or plannable task?" -> "Launch compose-task workflow" [label="yes"];
"Launch compose-task workflow" -> "Result status?";
"Result status?" -> "outcome = planned?" [label="DONE"];
"Result status?" -> "Resolve gate with user" [label="NEEDS_DECISION"];
"Result status?" -> "Failure handling" [label="BLOCKED / null"];
"Resolve gate with user" -> "Continue this task?";
"Continue this task?" -> "Launch compose-task workflow" [label="yes: relaunch with answers"];
"Continue this task?" -> "Pick next task" [label="no (backlog)"];
"Continue this task?" -> "STOP: iteration ends (single-task)" [label="no (single-task)"];
"outcome = planned?" -> "Single-task mode?" [label="yes (plannable-only)"];
"outcome = planned?" -> "Surface verdict" [label="no"];
"Surface verdict" -> "Merge gate (per policy)";
"Merge gate (per policy)" -> "Propagate";
"Propagate" -> "Single-task mode?";
"Single-task mode?" -> "STOP: iteration complete" [label="yes"];
"Single-task mode?" -> "Pick next task" [label="no"];
"Failure handling" -> "Single-task mode?";
}Pick. Backlog: piyaz_map view='ready' ∩ view='critical_path'; rank by priority (urgent > core > normal > backlog), tie-break by lowest estimate. Fall back to the highest-priority ready task when the intersection is empty, then to piyaz_map view='plannable' when ready is empty (plannable picks route through research + plan only; mark the pick plannable-only). Single-task: the named task; if done or cancelled, report and stop; if already claimed, see Failure handling (jump to the in-flight phase, never restart). Emit a one-paragraph pick rationale (taskRef, priority, estimate, critical-path yes/no, one-sentence reason). Do not wait for approval; the user interrupts if they disagree.
Gather pick facts and launch. Build the workflow args from the pick and bootstrap: taskRef, taskId (the UUID, carried for cross-referencing; refs are first-class in tool calls — conventions §4), projectId, categories, tagVocabulary, pickEstimate, pickPriority, workType and tags (from the task row), mode, plannableOnly. Write PICK then WORKFLOW task=<ref> runId=<id> to the run log, then launch the workflow and await the result.
Handle the result. NEEDS_DECISION → Gates. BLOCKED/null → Failure handling. DONE with outcome=planned (plannable-only) → end the iteration (TASK_END outcome=planned); backlog returns to the pick, single-task reports and stops. DONE with outcome=in_review → step 4.
Surface + merge + propagate. Quote the final verdict block verbatim (VERDICT to the run log). Run the Merge gate. Then propagate per lifecycle §3: piyaz_map view='neighbors' task='<taskRef>', piyaz_map view='downstream' task='<taskRef>'; update or retire edge notes the work invalidated (edge-note shape: artifacts §3). Propagation depth: full when the PR was merged or the verdict was approve; otherwise provisional, each note prefixed Provisional pending HOTL on PR #<n>:. Surface newly-unblocked tasks in the next pick rationale. Write PROPAGATED, then TASK_END outcome=in_review rotations=<n>.
Loop. Single-task: report the outcome and stop. Backlog: next iteration, no pause.
A NEEDS_DECISION result means the merged research+plan phase needs a user decision before the task can proceed. result.phase names the raising half (research or plan, from the agent's gatePhase) and result.gate carries the trigger. Resolve with the AskUserQuestion tool, then relaunch the workflow:
oversize-task flag): offer to dispatch piyaz:decompose-task or skip the task. Composer never splits a task itself. On decompose, dispatch the decompose agent and end the iteration; the children land in the backlog.result.gate.proposedRewrites non-empty): show original vs proposed per field with the rationale; offer accept / deny. On accept, apply via piyaz_edit and relaunch the workflow fresh (no resumeFrom) so research re-grounds on the rewritten task. On deny, end the iteration (backlog picks next; single-task stops).external-input-required, or any plan-phase open question): surface the open questions, wait for answers, then relaunch — research gate relaunches fresh with gateAnswers; a plan gate relaunches with resumeFrom='plan', priorBrief=result.brief, and gateAnswers, so research is not redone (the merged phase plans from the prior brief).Headless gate fallback: when AskUserQuestion is unavailable (errors or hangs), a NEEDS_DECISION resolves to skip-the-task: append a GATE line carrying the unasked question and the skip, write TASK_END outcome=skipped, end the iteration (backlog picks next; single-task stops). Never fabricate an answer; skipping is the reversible default (resilience §11).
The merge gate runs after a DONE result with outcome=in_review, governed by the run's merge policy. It fires only when result.verdict === 'approve' AND result.ciState === 'green'; a request-changes, block, escalated, red, or pending result is never merged.
never (default): do not merge. HOTL owns the merge and the in_review → done transition, exactly as without this feature. Propagate provisionally unless the verdict was approve.ask-each: ask the AskUserQuestion tool whether to merge this PR. On yes, merge as below. On no (or headless), leave it for HOTL.auto-on-approve: merge without asking.To merge: gh pr merge <url> --squash --delete-branch (squash is the default; follow the repo's configured default method when it differs). On a clean merge, write the task done — this is the one case the orchestrator writes a status transition, authorized by the run-start merge policy.
The merge is a status flip only; it does not touch the executionRecord. The implementer's record already describes what shipped and is the durable record. A HOTL merge leaves it untouched, so auto-on-approve leaves it untouched too; that keeps the two paths identical. The PR reference resolves through task_links, and method=squash lives in the run log.
piyaz_edit task='<taskRef>' operations=[{op:'set', field:'status', value:'done'}]Then propagate fully (the work landed) and write MERGE task=<ref> pr=<url> method=squash to the run log. Drop the merged worktree before the next pick: locate the .claude/worktrees/wf_* entry whose branch matches the PR's headRefName (git worktree list --porcelain) and run git worktree remove <path> + git branch -D <branch> (no --force; if git refuses on a dirty or locked tree, surface it and leave it for Worktree cleanup at run end). A failed merge (conflict, protected branch, merge-queue required) is not a task failure: report it, leave the task at in_review for HOTL, and continue.
The workflow self-selects each phase's model and effort from the pick facts and the research stage's refined estimate/work-type/flags. The orchestrator does not pass models; it passes the pick facts. The table the workflow applies:
| Phase | est 1–2 | est 3 | est 5 | est 8–13 / unset |
|---|---|---|---|---|
| Research+Plan | opus | opus | opus | opus |
| Implementer | sonnet (also docs/test/chore) | sonnet if docs/test/chore, else opus | opus | opus |
| CI gate | haiku | haiku | haiku | haiku |
| Reviewer | opus | opus | opus | opus — never downgrade |
Research and plan correctness are load-bearing: a mis-refined task or a vague plan wastes far more downstream tokens than a cheaper model saves, so the merged phase never runs below opus. (CI polling is mechanical, so the cheap haiku tier holds there only.)
Guardrails force opus and higher effort on the research+plan and implement dispatches regardless of estimate when any holds: a security/safety/compliance tag; estimate 8, 13, or missing; a fix-mode rotation; any retry or partial-success recovery; priority='urgent'; or a risk-bearing research flag (security-boundary-uncovered, version-drift-major, dep-mismatch). These are encoded in compose-task.js; this table is the human-readable mirror.
Fable sits above opus and upgrades the guardrail-fired dispatches. When args.fable is not 'off', the research+plan, implement, and fix dispatches select fable instead of opus when a guardrail fires on estimate 8+, a risk tag or flag, or priorFailure; the final fix rotation always takes the top tier. A failed fable dispatch (no account access, terminal error) falls back to opus and disables fable for the rest of the run. Pass fable:'off' when the user declines the tier; the reviewer stays opus and the CI gate stays haiku either way.
The run log is composer's crash-safe memory: an append-only event log at .piyaz/composer-<projectIdentifier>.md, one active file per project. The conversation can compact; the log does not. Counters derive by grep over events after the latest RUN_START: this run's iterations = PICK lines; failed attempts on task X = FAIL task=X lines.
One timestamped line per event, key=value pairs; multi-line payloads (blocking findings, gate questions and answers, failure summaries) follow as > continuation lines. The vocabulary:
| Event | Written when |
|---|---|
RUN_START | bootstrap completes (mode=backlog|single|rework mergePolicy=<...> project=<identifier>) |
PICK | step 1 emits the pick rationale |
WORKFLOW | immediately after launching the workflow (task=<ref> runId=<wf-id>) |
GATE | a NEEDS_DECISION resolves — user answer or headless skip; question and answer as continuations |
VERDICT | the workflow returns DONE (verdict=<v> rotations=<n> ci=<state> escalated=<bool>; blocking findings as continuations) |
MERGE | the merge gate merges a PR (task=<ref> pr=<url> method=squash) |
ESCALATE | a block or rotations-exhausted result goes to HOTL |
PROPAGATED | propagation completes (edges=<n> unblocked=<refs>) |
BRIEF | a --pipelined prefetch brief lands (task=<B-ref> baselinedAt=<A-ref>; brief verbatim as continuations) |
FAIL | the workflow returns BLOCKED (failure summary as continuation) |
TASK_END | the iteration ends (outcome=in_review|planned|stuck|skipped rotations=<n>) |
RESUME | recovery appends this after reading the log |
RUN_END | any stop condition (reason=<...> picked=<n> shipped=<n> merged=<n> stuck=<n> skipped=<n>) |
Per-phase events and fix rotations live inside the workflow's own journal, not the run log; the WORKFLOW runId line is the bridge to it. If .piyaz/ is not writable, fall back to any writable directory and name the chosen path in the first report; if no local write is possible, run without the log and say so — the run loses crash recovery, not correctness.
Pull-based: the backend has no webhooks, and task_links is the only PR record. The user invokes rework when GitHub review feedback exists; composer fetches it, re-anchors it, and runs the fix loop on it.
task.links filtered to kind='pull_request'; given a PR URL, resolve the task from the [<taskRef>] bracket (verify the link row agrees). Prefer the newest open PR when several exist.piyaz:review with Target task: <taskRef>. PR URL: <url>. Mode: rework-intake. The intake re-verifies the human feedback against current HEAD and returns a verdict.request-changes: launch the workflow with resumeFrom='fix', prUrl=<url>, and fixFindings=<the human items with fresh file:line citations>. The fix loop uses a fresh rotation budget of 2 for this rework invocation (the workflow's rotation counter starts at zero per launch). The fix loop dispatches the implementer in fix mode, which accepts an in_progress entry (HOTL may flip in_review → in_progress to signal rework).BLOCKED (PR merged/closed, task done/cancelled): report and stop.TASK_END. The run log records RUN_START mode=rework.Only under --pipelined, only in backlog mode, lookahead 1. The win is latency (~15–25%), not tokens; when in doubt, run without it.
resumeFrom='research' with a research-only early return is not built in; instead dispatch piyaz:composer-researcher directly with worktree isolation and run_in_background). Never prefetch while A's workflow is still running.in_review unblocks nothing, so the ready set already excludes A's dependents.BRIEF event with the brief verbatim. The prefetch is not a PICK; B's PICK lands when B's iteration starts, so recovery's last-PICK-without-TASK_END rule still finds A. Pass the brief into B's workflow launch as priorBrief with resumeFrom='plan' only when the invalidation table below clears it.planned → in_progress → in_review motion. B is never planned, claimed, or implemented early. A prefetch failure consumes no budget; drop it and research B normally.Brief invalidation. After propagation(A), evaluate in order; the first matching row wins:
| # | Signal after propagation(A) | Action |
|---|---|---|
| 1 | A depends_on edge B→(non-done task) was created | Re-pick; brief is stale |
| 2 | B's description was updated | Re-research (relaunch fresh) |
| 3 | Edge notes into B name files/patterns in the brief's Files to touch | Re-research |
| 4 | A's files ∩ B brief's Files to touch ≠ ∅ | Re-research with the A PR pointer in gateAnswers |
| 5 | A re-pick returns C outranking B on priority class | Re-pick to C; a tie proceeds with B |
| 6 | Pure informational note updates, no overlap | Proceed with the brief |
| 7 | None of the above | Proceed |
Kill switch: after two consecutive invalidations, disable prefetch for the rest of the run and say so.
The workflow builds every phase dispatch from the args you pass; the agents inherit nothing else. Keep args to the pick facts in Step details — never pass orchestrator transcript, prior-iteration summaries, full meta payloads, or piyaz reference text. The agents load their own rule extracts and fetch task context from Piyaz themselves. Oversized dispatches make agents worse, not better.
BLOCKED/null from the workflow is a failed attempt, with exceptions:
done or cancelled is not a failure — HOTL resolved it underneath the run. Run Surface + merge + propagate if it has not run, consume no budget, move on.BLOCKED — environmental: <error> (gh auth, rate limits, network) is an environment problem; surface it verbatim, consume no budget, resume the same workflow (via resumeFrom) once the user confirms the fix.BLOCKED from the plan phase prefixed foundation-unsound means the planner judged the research foundation wrong; relaunch the workflow fresh once to re-research, then treat a second failure normally.For every other BLOCKED:
FAIL); never write it to decisions (artifacts §1: CHOICE + WHY, not process metadata).priorFailure set; otherwise, or on a second failure, write TASK_END outcome=stuck and move to the next pick. Single-task mode: relaunch up to three total attempts, appending each failure summary as priorFailure; after the third, report and stop.Partial success and orphaned PRs are handled inside the implementer's pre-flight (it resumes the Completion Protocol against an existing branch/PR rather than re-implementing). When a single-task pick is already in_progress or in_review, launch the workflow with resumeFrom='implement' (in_progress) or resumeFrom='fix' with the existing prUrl (in_review); the implementer's pre-flight does the rest.
Stop and report in plain language (there are no magic stop phrases) when one holds:
ready and plannable are both empty. The run-end report (below) lists every unfinished task with its rationale, so nothing strands silently.These six are exhaustive. Every stop produces one run-end report. It appends RUN_END with its reason and the grep-derived counters, lists each unfinished task the loop left behind (in_progress, draft, or in_review awaiting HOTL) with its status, last completed phase, and one-line failure rationale, and surfaces the worktrees from Worktree cleanup at run end in the same report rather than a second adjacent block. For each unfinished task the report offers HOTL the choice to retry it or cancel it with a rationale; composer never cancels autonomously. Then it offers to archive the log. The headless default is inform-only on worktrees and unfinished tasks, and archive on the log.
The workflow dispatches the implementer and every fix rotation with isolation:'worktree' (compose-task.js), so each task leaves a git worktree under .claude/worktrees/wf_<runId>-<n> plus its local branch. The harness auto-removes a worktree only when it is unchanged; the implementer always commits, so a worktree outlives its task. The merge gate removes each merged task's worktree eagerly (gh pr merge --delete-branch drops only the remote branch — the local removal is composer's), so what reaches run end is the unmerged remainder: PR-backed worktrees awaiting HOTL, orphans, and — under never — every worktree. Composer never silently mutates the filesystem (HOTL owns destructive local actions), so at every stop — after RUN_END, before the archive offer — it surfaces what it left behind and cleans up per the run's merge policy.
git worktree list --porcelain; keep only paths under .claude/worktrees/wf_*. The wf_<runId> prefix is the discriminator that proves the workflow created the worktree — never the primary checkout or a user-made one. Capture each path and its branch refs/heads/<name>.gh pr list --state open --json number,headRefName,url. A worktree whose branch equals an open PR's headRefName is PR-backed (may be at in_review awaiting HOTL); every other is safe (its branch backs no open PR — merged, or an orphan worktree-wf_* branch). If gh is unavailable or errors, treat every worktree as PR-backed and inform only.git worktree remove <path> (no --force; surface git's refusal on a dirty or locked tree and leave it).git branch -D <branch> — -D not -d is intentional; orphan worktree-wf_* branches never merge upstream, so -d refuses them. For a PR-backed branch this drops only the local ref; the PR, its remote branch, and git fetch recovery survive.git worktree prune.auto-on-approve: auto-remove the safe bucket — the git worktree remove + git branch -D pair per worktree, then one git worktree prune — no prompt; the run-start delegation that authorized auto-merge covers it. PR-backed worktrees are surfaced (step 3), never auto-removed.never / ask-each: ask once with the AskUserQuestion tool — remove safe / remove all incl. PR-backed (explicit opt-in) / leave all. Remove only the pick, PR-backed only under the include option.Read the run log first: .piyaz/composer-<projectIdentifier>.md. The last PICK/WORKFLOW without a matching TASK_END is the in-flight task. Piyaz wins on status — re-read the task row and never trust the log over the server. The log wins on history — the merge policy (RUN_START mergePolicy=), gate answers, verdict history, and the workflow runId.
To resume the in-flight task:
WORKFLOW runId=<id> line with no VERDICT/TASK_END after it means the workflow may still be journaled. Resume it with Workflow({ scriptPath, resumeFromRunId: '<id>' }) — completed phases return from cache, only the unfinished phase re-runs. Stop the prior run first if it is somehow still live.resumeFrom. draft without a plan → fresh; planned → resumeFrom='implement' (or iteration end for a plannable-only pick); in_progress → resumeFrom='implement' (the implementer pre-flight resumes partial work); in_review → resumeFrom='fix' with the PR URL; done → HOTL or the merge gate already resolved it, run propagation if no PROPAGATED line exists.Append a RESUME line, then continue. Rebuild the backlog skip set from this run's TASK_END outcome=stuck/skipped lines. When the log is missing (different machine, sandbox), fall back to the status mapping alone; single-task mode re-invoked per task remains the lowest-risk shape for runs likely to span compaction.
| Temptation | Reality |
|---|---|
Write status "so no other agent grabs the task" | Every transition belongs to a phase agent: planner draft→planned; implementer planned→in_progress→in_review plus fix rotations. The orchestrator writes only propagation edges — and done, but only when the merge gate merged the PR under an authorizing merge policy. |
| Merge without the policy authorizing it, or merge a non-approve / non-green PR | The merge gate fires only on approve + green CI, only under ask-each (with a yes) or auto-on-approve. never means HOTL merges. |
| Dispatch a phase agent yourself instead of launching the workflow | The orchestrator never dispatches phase agents directly (rework intake is the one exception). The workflow owns research → review; the orchestrator owns the seams. |
| Skip research or planning to "get the claim in faster" | The phase order is fixed inside the workflow; the orchestrator cannot reorder it. |
| Split an oversize task yourself | Oversize routes to piyaz:decompose-task, and only after the user gate. |
Treat a request-changes or block verdict as a failed attempt | A careful verdict is a successful review. The workflow's fix loop or HOTL owns the response; the failure budget is untouched. |
| Pause between tasks to ask "should I continue?" | Continuous execution. The six stop conditions are the only exits; gates fire only on NEEDS_DECISION. |
Pad args with transcript, meta, or spec text | Pick facts only. Pollution makes agents worse. |
Not a decomposer (oversize routes out). Not a hand-refiner (that is the piyaz skill, used directly). It IS, when the user authorizes it, the merge gate. The workflow is the execution engine; the run log and the workflow journal are the resilience primitives; per-task re-invocation remains the recommendation for very long runs.
skills/composer/workflows/compose-task.js: the per-task pipeline the orchestrator launches.skills/piyaz/SKILL.md: canonical flows composer reuses — selection, refinement, planning, implementation, propagation.agents/composer-researcher.md, agents/composer-planner.md, agents/composer-implementer.md, agents/review.md: the phase contracts and their structured returns. The workflow's merged research+plan phase runs on the researcher; the planner stays for direct dispatch.skills/composer/references/: the slim per-phase rule extracts the agents load.agents/decompose-task.md: the oversize-delegation target.© FrkAk, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 6 other files (references) in plugins/claude-code/skills/composer of FrkAk/piyaz.
Open the folder on GitHubat commit a0d97a4
Composer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Composer this skillFrkAk/piyaz | 194 | — | ~8.6k | Automated safety check: Warn | AGPL-3.0 | |
| Ouroboros PM InterviewQ00/ouroboros | 6.2k | — | ~5.7k | Automated safety check: Pass | MIT | |
| Jira Natural Language Interfacejjmartres/opencode | 133 | 3 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Load Contextvishalmdi/ai-native-pm-os | 108 | — | ~562 | Automated safety check: Pass | None | |
| User Testing ValidatorIntelligent-Internet/zenith | 338 | — | ~1.8k | Automated safety check: Pass | Apache-2.0 | |
| Cas Supervisor Checklistcodingagentsystem/cas | 176 | — | ~349 | Automated safety check: Pass | MIT |
Q00/ouroboros
Runs a guided product-manager interview that classifies each question automatically and produces a Product Requirements Document.
jjmartres/opencode
Lets an agent view, create, update and transition Jira issues in natural language, automatically choosing between the jira CLI and Atlassian MCP tools.
vishalmdi/ai-native-pm-os
Loads all PM context files and prepares Claude for a productive session.
Intelligent-Internet/zenith
Real-surface validation coordinator for engineering validation assignments.
codingagentsystem/cas
Quick startup checklist for factory supervisors. An agent skill from codingagentsystem/cas.
alirezarezvani/claude-skills
A skill your agent uses when coordinating project-delivery work across the 8 project-management sub-skills — sprint/velocity analytics, portfolio health, Jira/JQL, Confluence, Atlassian admin…
FrkAk/piyaz
A skill your agent uses when the user has a net-new software project idea that needs shaping into a brief before tasks can be created.
FrkAk/piyaz
A skill your agent uses when the user wants to add a new feature, capability, or cluster of work to an existing active Piyaz project.
FrkAk/piyaz
A skill your agent uses when an existing task in an active Piyaz project carries scope larger than 13 points worth of work (composer's research brief raised the oversize-task flag, or the user…
FrkAk/piyaz
A skill your agent uses when the user wants to plan, decompose, track, or resume a multi-task project: scoping a new idea, importing or onboarding an existing repo or workspace, asking what to work…
FrkAk/piyaz
A skill your agent uses when a Piyaz project exists with a description but few or no tasks, and the user wants it broken into an implementable graph (project-level decomposition).
FrkAk/piyaz
A skill your agent uses when the current repo has existing code but no Piyaz project that matches it, and the user wants to adopt Piyaz on day N.
Works with
A skill your agent uses when the user types /piyaz:composer, /piyaz:composer <taskRef, or /piyaz:composer rework <taskRef|pr-url, or asks to run the next Piyaz task end-to-end, ship the backlog…. Composer is an agent skill from FrkAk/piyaz. Use when the user types /piyaz:composer, /piyaz:composer <taskRef, or /piyaz:composer rework <taskRef|pr-url, or asks to run the next Piyaz task end-to-end, ship the backlog, compose through the ready queue, or loop through Piyaz tasks until done.
Composer fits situations like: the user types /piyaz:composer; /piyaz:composer <taskRef; /piyaz:composer rework <taskRef|pr-url; asks to run the next Piyaz task end-to-end.
Run `npx skills add FrkAk/piyaz --skill composer -a claude-code`. Or copy the skill folder (plugins/claude-code/skills/composer in FrkAk/piyaz) into .claude/skills/composer in your project. Claude Code loads it when a task matches its description.
Run `npx skills add FrkAk/piyaz --skill composer -a codex`. Or copy the skill folder (plugins/claude-code/skills/composer in FrkAk/piyaz) into .agents/skills/composer in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add FrkAk/piyaz --skill composer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/composer, .gemini/skills/composer, .github/skills/composer and .opencode/skills/composer in your project.
Going by SKILL.md and its folder, Composer needs JavaScript for the scripts in its folder and the command-line tools its instructions call (git and gh). Our summary lists: Node.js.
SKILL.md contains no URLs. Its commands use git and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md flagged 1 warning(s): tells the agent its actions are pre-authorized / not to stop for confirmation. Read the flagged lines before installing; the check is not a guarantee either way.
Composer is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.6k tokens (SKILL.md is roughly 34k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 11k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Composer: Ouroboros PM Interview (Q00/ouroboros, 6.2k stars), Jira Natural Language Interface (jjmartres/opencode, 133 stars), Load Context (vishalmdi/ai-native-pm-os, 108 stars) and User Testing Validator (Intelligent-Internet/zenith, 338 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
FrkAk (a GitHub user) maintains it in FrkAk/piyaz, which has 194 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on September 29, 2026.
Source: FrkAk/piyaz on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.