Repository navigation
Add /crow-cascade-epic: run an epic as a dependency-gated cascade (CROW-1312) - #1313
Conversation
…OW-1312) A new bundled skill packages the cascade process we have been running by hand (most recently corveil-cloud-terraform#618 → T1–T8). It reads an epic, layers its sub-tickets into dependency waves, and launches one Crow work session per ticket of the current wave through crow-workspace/setup.sh. Launches run one at a time with a list-worktrees check (the #1301 race). A background watcher releases the next wave only once every PR in the current wave has merged. Each coder prompt carries the cascade contract: one PR scoped to its ticket with Closes #N, the human reviewer requested (default dgershman), no self-approval, and the gate's label rule. --gate human leaves crow:merge off and the reviewer merges by hand. --gate auto adds it via crow add-merge-label. When the flag is omitted, auto is chosen only if the base branch requires an approving review and the auto-merge watcher is on. cascade.sh is the deterministic half: - plan: Kahn wave layering, cycle and unknown-dependency checks - status: merge state from closedByPullRequestsReferences plus the session's registered PR, contract drift, and the resume point - watch: exit 0 when the wave has merged, 10 to re-arm, 3 when blocked Progress is always read live, so re-running the skill resumes without launching a ticket twice. The Scaffolder installs the skill and script on every launch, and settings.json pre-approves the script. The drift guard keeps skills/ and Resources/ byte-identical and requires the policy text. cascade_test.sh (61 checks, fake gh/crow) runs in make parity and CI. 🐦⬛ Generated with Claude Code, orchestrated by Crow Co-Authored-By: Claude <[REDACTED_EMAIL]> Crow-Session: 3D47A57F-2215-482F-879E-2593E521624F
dgershman
left a comment
There was a problem hiding this comment.
Code & Security Review
Critical Issues
Red — watch reports an open wave complete when jq is 1.6.
skills/crow-cascade-epic/cascade.sh uses jq 1.7 object shorthand ({id, label, …}) in the plan summary (cascade.sh:120) and in STATUS_JQ (cascade.sh:189, cascade.sh:231, cascade.sh:242). command -v jq on this machine is jq 1.6 (/usr/local/bin/jq), which fails to compile those filters, so status writes no JSON. cmd_watch then evaluates jq -e '.waves[0].complete' on that empty output (cascade.sh:346). jq 1.6 exits 0 for empty input, and the script takes the complete branch.
Reproduced by running bash skills/crow-cascade-epic/cascade_test.sh with that jq: 43 checks failed, and watch --wave 3 --interval 0 --timeout 0 exited 0 with WAVE 3 COMPLETE — that was the last wave while wave 3 was still open. The same suite is 61/61 under /usr/bin/jq 1.7.1-apple. CI can stay green because its jq is new enough; a Mac whose PATH selects Homebrew jq 1.6 will release the next wave without a merge. The Resources template is the same script.
Ship filters jq 1.6 can compile, or exit 2 from preflight when jq is older than 1.7. Also require a status object with "status":"ok" before the complete branch — on jq 1.6 the -e exit code alone does not mean the wave finished.
Architecture / Existing Patterns
- Existing pathway:
/crow-workspace'ssetup.sh. This skill sequences that script one ticket at a time (with thelist-worktreescheck) and leaves worktree creation, naming, and prompts on that path. That matches the #1301 registration race the skill is written around.
Security Review
Strengths:
cascade.shonly reads GitHub, through GraphQL variables, and Crow (list-sessions/list-links). Issue comments andgh pr editstay off the pre-approved allow list.- An omitted
--gatestayshumanunless a required approving review is visible and the auto-merge watcher is on. - Author self-approval is still flagged in the
statusJSON.
Concerns:
- The Red finding is the one that breaks the gate: the wrong
jqreleases the next wave with nothing merged. - The Yellow finding drops the human-gate alert (
crow:mergebefore a human approval) from the stream the Manager is told to act on.
Code Quality
Yellow — the watch stream never emits ⚠ contract: lines. cascade.sh:338-342 walks .drift[] and then reads .wave and .id off that string. Reproduced on jq 1.7 with an open PR that has crow:merge and no reviewer request: status listed both drift findings, and watch printed Cannot index string with string "id" plus the state line only, then exited 0. cascade_test.sh:224 asserts the state line and never a contract line, so the suite stays green. SKILL.md:249 tells the Manager to act on those lines, including removing a premature crow:merge. Capture the ticket ($t.wave, $t.id) before iterating drift, and assert a contract line in the watch test.
Green — a merged PR satisfies the ticket while another PR is still open. classify returns merged as soon as any linked PR is merged (cascade.sh:201), and the “more than one PR” drift counts only OPEN pulls. Reproduced: PR #11 merged and PR #12 still open with crow:merge left the wave complete: true. The state table treats that merge as enough; a drift line for a leftover open PR would be the tighter rule if a second PR should hold the wave.
swift build completed. cascade_test.sh is 61/61 on jq 1.7.1 and 18/61 on jq 1.6, with the false wave release above.
Summary Table
| Color | Meaning | Verdict effect |
|---|---|---|
| Red | Must fix | Request changes |
| Yellow | Should fix | Request changes |
| Green | Consider | Approve allowed |
Recommendation: Request Changes — driven by 1 Red, 1 Yellow, 1 Green findings.
Addresses the PR #1313 review. Red: jq 1.6 treats `label` as a keyword, so the bare `{id, label, …}` keys and `.label` reads failed to compile. `status` then printed nothing, and jq 1.6's `-e` exits 0 on empty input, so `watch` released an unmerged wave. - Quote the key everywhere (`"label": ."label"`, `$t."label"`). The suite now passes 77/77 under both jq 1.6 and 1.7.1 (it was 18/61 under 1.6). - Fail closed. `status` emits an error object and exits 2 when its filter can't run. `watch` requires `"status":"ok"` before it trusts `complete` and exits 2 otherwise, so it never releases a wave it could not read. - Preflight rejects jq older than 1.6. - CI runs the suite a second time under a pinned, checksum-verified jq 1.6. Yellow: the watch stream walked `.drift[]` and then read `.wave`/`.id` off the string, so it never printed a `⚠ contract:` line. It now binds the ticket first. A new test asserts the contract lines appear in the stream. Green: when a ticket already has a merged PR, another PR left open is reported as drift. It doesn't hold the wave, because the ticket is done, but the stray PR could still merge later. 🐦⬛ Generated with Claude Code, orchestrated by Crow Co-Authored-By: Claude <[REDACTED_EMAIL]> Crow-Session: 3D47A57F-2215-482F-879E-2593E521624F
|
Thanks. All three findings are addressed in a716c32. Red (jq 1.6). The cause was narrower than the object shorthand itself:
Yellow (contract lines). The stream now binds the ticket before iterating Green (merged + still-open PR). I went with a drift line and kept the ticket satisfied, rather than holding the wave. Once the ticket's PR has merged, its dependents can build on it. If the stray PR held the wave, it could stall the cascade indefinitely for work that isn't a dependency. It's now reported as |
dgershman
left a comment
There was a problem hiding this comment.
Code & Security Review
The previous round's jq 1.6 false release and the dropped ⚠ contract: lines are fixed. On this machine's jq 1.6 (/usr/local/bin/jq), bash skills/crow-cascade-epic/cascade_test.sh is 77/77, including the fail-closed watch (exit 2, no COMPLETE) and both contract lines. shellcheck is clean, scripts/check-workspace-custom-instructions.sh passes, and swift build completes.
Critical Issues
None.
Architecture / Existing Patterns
- Existing pathway:
/crow-workspace'ssetup.sh, run one ticket at a time with thelist-worktreescheck. Wave layering and the merge watch are new and live incascade.sh. The skill leaves worktree creation, naming, and prompts onsetup.sh, and it keeps a wave off/crow-batch-workspacebecause of the #1301 registration race. That shape fits.
Security Review
Strengths:
- GitHub reads go through GraphQL variables (
-F). Plan fields are not eval'd. - An omitted
--gatestayshumanunless a required approving review is visible and the auto-merge watcher is on. - Issue comments and
gh pr editstay off the pre-approved allow list. - A status filter jq cannot run becomes
{"status":"error"}.watchrequires"status":"ok"before it can release a wave. That path exits 2 on jq 1.6.
Concerns:
- The Yellow below: contract drift, including
crow:mergebefore a human approval, is computed from one session's links, so an open PR on the active session can be invisible while the wave is reported complete.
Code Quality
Yellow — PR links come from a different session than the one status reports. collect_ticket takes the first non-explore work session in list-sessions order (skills/crow-cascade-epic/cascade.sh:175). session_for prefers a session that is not completed or archived (skills/crow-cascade-epic/cascade.sh:248-251). Sessions are appended, so the first row is the oldest.
Reproduced with a fake gh/crow: a completed session linked to merged PR #11, and a later active session linked to open PR #12 (crow:merge, no reviewer, and not a closing reference on the issue). status returned state: merged, complete: true, drift: [], and session.id of the active session, with only PR #11 in prs. The leftover-open-PR line and the human-gate crow:merge check both miss a PR registered only on the later session. Collect links from every matching work session, or from the same session session_for returns.
Yellow — re-running the skill does not advance a GitLab ticket. cascade.sh queries only GitHub issue URLs (skills/crow-cascade-epic/cascade.sh:149-169). A GitLab URL stays no_pr. Once that ticket has a work session, to_launch is empty and complete stays false. Reproduced: status for https://gitlab.com/o/r/-/issues/1 with an active session was {state: no_pr, satisfied: false, complete: false, to_launch: []}. skills/crow-cascade-epic/SKILL.md:432 tells the Manager to check glab mr view and re-run the skill to advance. That re-run calls the same status, and the wave does not move. Point this limitation at --wave after the MR is confirmed, and say a GitLab merge does not release the wave.
Green — a merged PR still satisfies the ticket while another open PR is drift, and the wave still releases. That matches the rationale on the last review: dependents can build on the merged PR. The single-issue case is covered by the leftover-open-PR checks in skills/crow-cascade-epic/cascade_test.sh. The Yellow above is the case where that drift line is never produced.
Green — on jq 1.6, jq -e still exits 0 for a blank line (printf '\n' | jq -e '.status == "ok"' → 0). The watch guard holds because collect_status prints an error object when the filter fails; the suite's "watch never releases a wave it could not read" check passes on this jq 1.6. Comparing the printed status token, rather than relying on -e alone, would keep a blank line from looking like success.
Summary Table
| Color | Meaning | Verdict effect |
|---|---|---|
| Red | Must fix | Request changes |
| Yellow | Should fix | Request changes |
| Green | Consider | Approve allowed |
Recommendation: Request Changes — driven by 0 Red, 2 Yellow, 2 Green findings.
Addresses the second PR #1313 review. Yellow: collect_ticket read PR links only from the first matching work session (the oldest), while status reported the active one. A PR registered only on a later session was invisible, and so was its drift (the leftover-open-PR line, crow:merge before approval). Links now come from every non-explore work session on the ticket. Yellow: re-running the skill can't advance past a change that lands as a GitLab MR, because cascade.sh reads only GitHub. SKILL.md no longer says a re-run advances it. It says a GitLab merge doesn't release the wave: confirm the MR with glab, check that status shows every other ticket satisfied, then advance with --wave n+1. --wave skips the whole wave. Green: jq 1.6's `-e` exits 0 on empty or blank input. That was a real false release: a status filter that printed a blank line let watch release the wave, and an empty plan file passed the object check. Every `jq -e` in cascade.sh is now jq_true, which compares the printed value to `true`. New tests cover empty and blank plan files, a blank status line, and the two-session case. The suite is 89/89 under jq 1.6 and 1.7.1; against the previous commit it fails 10 checks under 1.6, including the false release. 🐦⬛ Generated with Claude Code, orchestrated by Crow Co-Authored-By: Claude <[REDACTED_EMAIL]> Crow-Session: 3D47A57F-2215-482F-879E-2593E521624F
|
All four findings are addressed in 826a9e6.
The suite is 89/89 under jq 1.6 and 1.7.1. Against the previous commit, the new checks fail 3 under 1.7.1 and 10 under 1.6. |
dgershman
left a comment
There was a problem hiding this comment.
Code & Security Review
The last round's jq 1.6 false release and the single-session link read are fixed. On this machine's jq 1.6 (/usr/local/bin/jq), bash skills/crow-cascade-epic/cascade_test.sh is 89/89, including the fail-closed watch. shellcheck is clean on cascade.sh, cascade_test.sh, and scripts/check-workspace-custom-instructions.sh (that guard passes). swift build completes.
Critical Issues
None.
Architecture / Existing Patterns
- Existing pathway:
/crow-workspace'ssetup.sh, one ticket at a time, with thelist-worktreescheck. Wave layering and the merge watch are new and live incascade.sh. The skill does not create worktrees itself, and it keeps a wave off/crow-batch-workspacebecause of the #1301 registration race. That shape fits.
Security Review
Strengths:
- GitHub reads go through GraphQL variables (
-F/-f). Plan fields are not interpolated into the query. - A status filter jq cannot run becomes
{"status":"error"}.watchrequires"status":"ok"before it can release a wave. That path exits 2 on jq 1.6. - Issue comments and
gh pr editstay off the pre-approved allow list.cascade.shonly reads GitHub and Crow. - An omitted
--gatestayshumanunless a required approving review is visible and the auto-merge watcher is on.
Concerns:
- Green — who merged is not part of the gate.
crow:mergeand self-approval drift are computed only on open PRs. AMERGEDPR satisfies the ticket, including one the author merged. On the human gate that is the unprotected-branch case the skill is written for. The skill defines the gate as "the PR merged" and keeps no-self-merge in the coder prompt. That enforcement gap is the author's call.
Code Quality
Yellow — a failed crow list-sessions looks like "no sessions", so to_launch starts the ticket again.
collect_status stores any list-sessions failure as an empty list and still returns "status":"ok" (skills/crow-cascade-epic/cascade.sh:321-322):
sessions=$("$CROW_BIN" list-sessions 2>/dev/null | jq -c '.sessions // []' 2>/dev/null) || sessions='[]'
[[ -n "$sessions" ]] || sessions='[]'to_launch then treats session == null plus no_pr or pr_closed as launchable (skills/crow-cascade-epic/cascade.sh:310-313). The ticket error stays null: this path never records that Crow could not be read. skills/crow-cascade-epic/SKILL.md:412 says a re-run skips any ticket that already has a work session.
Reproduced with CROW_BIN exiting 1 and an open issue that has no PRs: status returned {"status":"ok","to_launch":["o/r#10"]} and error: null. Phase 5 launches to_launch. A socket timeout while the coder is still working and has not opened a PR yet starts a second session. The jq-filter failure beside this is fail-closed; this one is not. A non-zero list-sessions should be a status error (watch exit 2), not an empty session list. Cover that in cascade_test.sh.
Green — pr_closed is relaunched only when no session row remains. A completed session plus a closed-unmerged PR stays out of to_launch, so the wave waits until that session is gone. The idempotency section already says any session blocks a second launch. The state table's "launchable again" is the case with no session left; one clarifying phrase would stop a re-run from looking stuck.
Summary Table
| Color | Meaning | Verdict effect |
|---|---|---|
| Red | Must fix | Request changes |
| Yellow | Should fix | Request changes |
| Green | Consider | Approve allowed |
Recommendation: Request Changes — driven by 0 Red, 1 Yellow, 2 Green findings.
…2 review) Addresses the third PR #1313 review. Yellow: a failed `crow list-sessions` was stored as an empty session list, so status came back "ok" with every in-flight ticket in to_launch. A socket timeout could have started a second coder on a ticket still being worked. Now a non-zero exit, or output that isn't a session list, is a status error: status exits 2 with no to_launch, and watch exits 2 without releasing anything. Green: who merged is now partly part of the gate. On the human gate, a merged PR with no approval from anyone but its author is reported as drift. It is checked by approval, not by mergedBy: on #618, GitHub records the author as the merger of every PR (#636, #640, #644), because Crow's auto-merge ran under that account after the reviewer approved. The drift doesn't hold the wave, since the change has already landed. SKILL.md tells the Manager to raise it with the operator (revert?). The live #618 status still reports no drift. Green: the pr_closed row now says the ticket is relaunched only once no work session remains, and how to restart it. Suite: 102/102 under jq 1.6 and 1.7.1. Against the previous commit, 10 checks fail, including the reviewer's repro (a ticket offered for launch while Crow was unreachable). 🐦⬛ Generated with Claude Code, orchestrated by Crow Co-Authored-By: Claude <[REDACTED_EMAIL]> Crow-Session: 3D47A57F-2215-482F-879E-2593E521624F
|
All three findings are addressed in 294bc27.
The suite is 102/102 under jq 1.6 and 1.7.1. |
dgershman
left a comment
There was a problem hiding this comment.
Code & Security Review
The last round's fail-closed list-sessions path holds. On this machine's jq 1.6 (/usr/local/bin/jq), bash skills/crow-cascade-epic/cascade_test.sh is 102/102. swift build completed. CI is green (Build & Test, Catalog & Parity Gates, Shell Lint).
Critical Issues
None.
Architecture / Existing Patterns
-
Existing pathway:
/crow-workspace'ssetup.sh, one ticket at a time, with thelist-worktreescheck. Wave layering and the merge watch live incascade.sh. That shape fits. -
Yellow — human-gate approval is read from
latestReviews, which drops a review that still stands. Crow already treats approval asreviewDecisionfirst and only then falls back tolatestReviews, because a re-request removes the review fromlatestReviewswhile the verdict remains (Packages/CrowEngine/Sources/CrowEngine/PRStatusController.swift:481,Packages/CrowCore/Sources/CrowCore/Models/PRStatus.swift:165).skills/crow-cascade-epic/cascade.sh:150selectslatestReviews, andcascade.sh:225keeps a login only when that node isAPPROVED. The fragment does not selectreviewDecisionorlatestOpinionatedReviews.Reproduced with a fixture in the shape of merged corveil/crow#1261:
reviewDecisionisAPPROVED,latestOpinionatedReviewsis dhilgaertnerAPPROVED,latestReviewsis empty, and a review request for dhilgaertner is still pending.statusreturnedstate: merged,satisfied: true, and driftPR #1261 merged without an approval from anyone but its author (human gate).skills/crow-cascade-epic/SKILL.md:385tells the Manager to report that unreviewed code is on the default branch. Count approvals fromlatestOpinionatedReviews(still exclude the author). The Resources template is the same script.
Security Review
Strengths:
- GitHub reads go through GraphQL variables. Plan fields are not eval'd.
- A missing or unreadable
crow list-sessionsis{"status":"error"}.watchrequires"status":"ok"before it can release a wave. - Issue comments and
gh pr editstay off the pre-approved allow list. - An omitted
--gatestayshumanunless a required approving review is visible and the auto-merge watcher is on.
Concerns:
- The Yellow above pages the operator that a merged PR had no human approval when the approval is only missing from
latestReviews.
Code Quality
Yellow — the "who added crow:merge" command does not run as written. skills/crow-cascade-epic/SKILL.md:380 (and Resources/crow-cascade-epic-SKILL.md.template) puts the jq filter in a table cell, so the pipes are backslash-escaped: [.[] \| select(...)] \| last \| .actor.login. Reproduced: jq rejects \| with unexpected INVALID_CHARACTER and exits 3. That command is how the Manager decides whether a premature crow:merge was the coder's (remove it) or the reviewer's (leave it). Put the filter in a fenced block so the pipes are real.
Green — a merged PR with no non-author approval still satisfies the ticket and releases the wave. The skill states that on purpose: the change has landed, and holding dependents would not undo it. Who clicked merge stays out of the gate.
Summary Table
| Color | Meaning | Verdict effect |
|---|---|---|
| Red | Must fix | Request changes |
| Yellow | Should fix | Request changes |
| Green | Consider | Approve allowed |
Recommendation: Request Changes — driven by 0 Red, 2 Yellow, 1 Green findings.
…OW-1312 review) Addresses the fourth PR #1313 review. Yellow: approvals came only from latestReviews, which GitHub hides once the reviewer is re-requested, even though the approval still stands (the case PRStatus.swift already handles). A merged PR like #1261 (latestReviews empty, latestOpinionatedReviews APPROVED, a re-request pending) was reported as "merged without an approval from anyone but its author", which would have told the operator unreviewed code had landed. The fragment now also selects latestOpinionatedReviews, and approved_by and reviewed_by read both lists. The author is still excluded. The same fix clears a false crow:merge-before-approval warning on open PRs. Yellow: the "who added crow:merge" command sat in a SKILL.md table cell, so its pipes were `\|` and jq rejected it (the Manager reads the file raw). It is now in a fenced block and runs as written. The guard script now rejects any `\|` in either copy of the skill. Suite: 104/104 under jq 1.6 and 1.7.1. The two #1261-shaped checks fail against the previous commit. The live #618 status is unchanged: ok, complete, no drift. 🐦⬛ Generated with Claude Code, orchestrated by Crow Co-Authored-By: Claude <[REDACTED_EMAIL]> Crow-Session: 3D47A57F-2215-482F-879E-2593E521624F
|
Both Yellows are addressed in 649f842.
The suite is 104/104 under jq 1.6 and 1.7.1. The live #618 status is unchanged: ok, complete, no drift. |
dgershman
left a comment
There was a problem hiding this comment.
Code & Security Review
The last round's two findings are fixed. On this machine's jq 1.6, bash skills/crow-cascade-epic/cascade_test.sh is 104/104. shellcheck is clean on cascade.sh, cascade_test.sh, and scripts/check-workspace-custom-instructions.sh (that guard passes). swift build completed.
Critical Issues
None.
Architecture / Existing Patterns
- Existing pathway:
/crow-workspace'ssetup.sh, one ticket at a time. This commit extends the status query's review fragment. Crow's own PR status readsreviewDecisionfirst (Packages/CrowEngine/Sources/CrowEngine/PRStatusController.swift:481). The cascade also needs the approver's login, soskills/crow-cascade-epic/cascade.sh:227unionslatestReviewswithlatestOpinionatedReviews— the list GitHub keeps after a re-request. Live corveil/crow#1261 isreviewDecision: APPROVED,latestReviewsempty, andlatestOpinionatedReviewsholding the approval.skills/crow-cascade-epic/cascade_test.shcovers that shape, including acrow:mergePR whose only approval sits inlatestOpinionatedReviews.
Security Review
Strengths:
- GitHub reads go through GraphQL variables. Plan fields are not eval'd.
- A missing
crow list-sessions, or a status filter jq cannot run, is{"status":"error"}.watchrequires"status":"ok"before it can release a wave. - Issue comments and
gh pr editstay off the pre-approved allow list. - An omitted
--gatestayshumanunless a required approving review is visible and the auto-merge watcher is on.
Concerns:
None.
Code Quality
The "who added crow:merge" lookup in skills/crow-cascade-epic/SKILL.md:390 is a fenced command, so the pipes are real. The same filter returns the actor under jq 1.6. scripts/check-workspace-custom-instructions.sh rejects a table-escaped pipe in either copy of the skill.
Summary Table
| Color | Meaning | Verdict effect |
|---|---|---|
| Red | Must fix | Request changes |
| Yellow | Should fix | Request changes |
| Green | Consider | Approve allowed |
Recommendation: Approve — driven by 0 Red, 0 Yellow, 0 Green findings.
Closes #1312
Summary
Adds
/crow-cascade-epic <epic-url>, a new bundled Crow skill. It packages the dependency-gated epic cascade we have been running by hand (most recently the NAT-removal epic corveil-cloud-terraform#618 → T1–T8) into a repeatable skill:blocked_bylinks,Depends onlines in child bodies, and the epic's own wave list.cascade.sh planruns Kahn's algorithm and rejects cycles, unknown dependencies, and missing fields. Against the real feat(web): skeleton-load the left pane before list-sessions #618 it reproduces the hand-built T1 · T2/T3 · T4/T5/T6 · T7 · T8.crow-workspace/setup.shand does no setup of its own. Tickets are launched one at a time, and each launch is followed by acrow list-worktreescheck (plus a re-check 5s later). This is the add-worktree registration lost under rapid session creation (setup.sh dies at launch_agent: "no registered worktree with a branch") #1301 constraint: Stop the store-reload poll from dropping just-registered worktrees (CROW-1301) #1308 fixed that race, but the skill can't tell whichcrowdbuild is running, and a wave is only a few tickets.Closes #Nand the default branch as base. It requests the human reviewer (--reviewer, defaultdgershman) and never self-approves. Then the gate rule:--gate human: nocrow:merge. The reviewer merges by hand.--gate auto:crow add-merge-label, so Crow's auto-merge watcher merges on green.autoonly if the base branch's ruleset requires an approving review and the auto-merge watcher is on. Otherwisehuman.cascade.sh watchruns as a background Bash task and exits0only when every ticket in the wave has a merged PR, or was closed as completed by a human. Exit10means re-arm;3means blocked (a ticket closed as not-planned).closedByPullRequestsReferences, plus the PR the coder registered on its session) and from Crow (list-sessionsmatched byticket_url). A re-run lands on the right wave and never launches a ticket twice. The per-ticket contract comment carries a marker, so it posts only once.statusandwatchalso report contract drift on open PRs:crow:mergeadded before any human approval (human gate). An approver adding it afterward is fine; fix: sync main into web UI parity (clears #594 conflicts) #636 on feat(web): skeleton-load the left pane before list-sessions #618 did exactly that.crow:merge(auto gate).Changes
skills/crow-cascade-epic/SKILL.md: the orchestrator. It has flags--gate,--reviewer,--wave,--dry-run,--explore, and--no-comment. It includes the coder-prompt contract for both gates and the per-ticket comment, drift handling, explore mode, resume rules, and a worked example of the feat(web): skeleton-load the left pane before list-sessions #618 cascade from end to end.skills/crow-cascade-epic/cascade.sh: the deterministic half, withplan,status, andwatch. It is bash 3.2-safe and needsjq.skills/crow-cascade-epic/cascade_test.sh: 61 checks against fakegh/crow. They cover wave layering and validation, every ticket state, every drift rule, the resume point /start_wave, and eachwatchexit code. It runs inmake parityand in the CI parity job.Resources/crow-cascade-epic-{SKILL.md,cascade.sh}.template: byte-identical twins for installed builds.Scaffolder.swift: installs both files on every launch (the script as0755), adds the two loaders, and adds the fallback allow rules.settings.json: pre-approvescascade.sh, both thebash …and direct forms. Comment posting and PR edits still prompt.scripts/check-workspace-custom-instructions.sh: frontmatter check, a byte-identity check across both halves of the skill and the script, and required policy text (both gates, reviewer, no self-approval,setup.shdelegation, sequential creation). The new diff check doesn't abort underpipefailbefore it reports.LaunchScaffoldTests: expects the new files and asserts that both skill scripts are executable.CLAUDE.md(and its template),docs/configuration.md,docs/getting-started.md, andCHANGELOG.md.Testing
bash skills/crow-cascade-epic/cascade_test.sh: 61/61 pass. Mutating the classification,to_launch, and human-gate drift rules makes it fail (6, 2, and 1 failures).planproduced the five waves above.statusread all eight tickets asmergedthrough PRs fix: sync main into web UI parity (clears #594 conflicts) #636, fix(terminal): stop resize clobber by coalescing + deduping fits #638–Support drag-and-drop images into agent chats (parity with Cursor/Claude Code TUI) #644, withcomplete: true.watch --wave 4exited0withWAVE 4 COMPLETE — release wave 5: T8 …#626.shellcheckis clean oncascade.sh,cascade_test.sh, and the guard script.bash scripts/check-workspace-custom-instructions.shpasses. A drifted template or a removed policy line fails it.make daemonbuilds.LaunchScaffoldTestspasses 5/5, including the newskillScriptsAreExecutable. The Scaffolder suites in CrowEngine pass 35/35, andCLIDocsTestspasses 7/7.make paritypasses, now with thecascade_test.shstep.Limitations
cascade.shyet; the skill says to checkglab mr viewand re-run.plan/status/watchrun above.🤖 Generated with Claude Code