Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ summary: Chronological history of repository and skill changes.

# Changelog

## 2026-07-21 — Completed carve-changesets skill and verification suite
## 2026-07-21 — Completed carve-changesets and integrated ticket publication

- fix: fail closed on invalid carved handoffs
- feat: integrate carved ticket publication
(`54c67f7cd7ace3269eee4fe628f974b090a4d699`)
- refactor: derive the eval action vocabulary from expectations
(`e30b5f1021538d673eb931b2978287cfd21ae4ae`)
- fix: require the two-part source freshness override
(`eb8612300d75d1483995677d75f54fe1a32b60d7`)
- test: complete the carve-changesets verification suite
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ Current reusable agent skills:
explicitly authorized completion policy
- `skills/implement-ticket` — implement exactly one standalone ticket or named
epic child through isolated execution and initial repository-owned review,
delegate the published PR lifecycle to `babysit-pr`, then verify tracker,
mainline, and cleanup outcomes; this is the canonical owner of generic
single-ticket execution rules consumed by `implement-epic`
publish one ordinary PR through `babysit-pr` or an explicitly authorized
carved stack through `carve-changesets`, then verify tracker, mainline, and
cleanup outcomes; this is the canonical owner of generic single-ticket
execution rules consumed by `implement-epic`
- `skills/implement-epic` — traverse live GitHub or Linear epic graphs and
delegate each selected child to `implement-ticket`, then refresh graph state
and verify separately authorized epic closeout
Expand All @@ -40,8 +41,12 @@ The composed implementation dependency chain is:
implement-epic
└── implement-ticket
├── review-code-change # initial candidate review
└── babysit-pr # published PR lifecycle
└── review-code-change # after a head-changing fix
├── babysit-pr # ordinary single-PR lifecycle
│ └── review-code-change # after a head-changing fix
└── carve-changesets # authority-gated oversized path
├── review-code-change # each exact changeset
└── babysit-pr # each changeset PR lifecycle
└── review-code-change # after a head-changing fix

carve-changesets
├── review-code-change # direct per-changeset review
Expand Down
67 changes: 44 additions & 23 deletions skills/implement-epic/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ Orchestrate the live work graph. Delegate each selected child to
## Require the ticket skill

Before an epic run, verify that `implement-ticket` is available, readable, and
supports `ready_pr`, `merged`, `blocked`, and `requires_epic` terminal results.
Return `blocked` before mutation when the dependency or result contract is
missing or untrustworthy. Do not substitute a generic implementation agent,
inline a copy of the ticket workflow, or weaken any gate.
supports `ready_pr`, `ready_prs`, `merged`, `blocked`, and `requires_epic`
terminal results. Return `blocked` before mutation when the dependency or result
contract is missing or untrustworthy. Do not substitute a generic implementation
agent, inline a copy of the ticket workflow, or weaken any gate.

`implement-ticket` owns ticket readiness, isolated implementation, validation,
`review-code-change`, PR state, remote gates, merge, tracker transition, per-PR
cleanup, and terminal evidence. Do not invoke individual review lenses or
`review-code-change` directly from this skill.
`review-code-change`, publication-path selection, PR or stack state, remote
gates, merge, tracker transition, per-candidate cleanup, and terminal evidence.
Do not invoke individual review lenses, `review-code-change`, `babysit-pr`, or
`carve-changesets` directly from this skill.

## Require compatible runtime capabilities

Expand All @@ -38,11 +39,12 @@ A compatible agentic runtime must be able to:
taking ownership of local review.

The portable dependency chain is `implement-epic` → `implement-ticket` →
(`review-code-change`, `babysit-pr`), with `babysit-pr` → `review-code-change`
after a head-changing fix. Verify `implement-ticket` directly and require its
result to prove that its own dependencies and applicable capabilities were
available. Do not make this skill invoke `review-code-change` or `babysit-pr`
itself.
(`review-code-change`, `babysit-pr`, `carve-changesets`), with
`carve-changesets` → `babysit-pr` per changeset and `babysit-pr` →
`review-code-change` after a head-changing fix. Verify `implement-ticket`
directly and require its result to prove that its own dependencies and
applicable capabilities were available. Do not make this skill invoke
`review-code-change`, `babysit-pr`, or `carve-changesets` itself.

Stop before child mutation with an explicit limitation when an applicable
capability or dependency is unavailable. Product-specific discovery metadata
Expand Down Expand Up @@ -76,13 +78,17 @@ Before selecting work, discover or receive and verify:
- serial execution by default, with parallel execution only when explicitly
authorized and proven non-overlapping; and
- authority for child execution, merge, manual transitions, graph edits,
follow-up creation, branch deletion, parent closeout, deployment, production
follow-up creation, decomposition of an oversized coherent candidate into a
stacked chain, branch deletion, parent closeout, deployment, production
mutation, and destructive operations.

Pass authority into `implement-ticket` without expansion. Ready-PR authority
does not imply merge. Child merge authority does not imply parent closeout.
Words such as `finish`, `complete`, or `end to end` do not independently grant
merge, graph mutation, deployment, or closeout authority.
Pass authority into `implement-ticket` without expansion. The
`decompose oversized candidates into stacked changesets` grant is off by default
and must be passed through verbatim; this skill gains no decomposition
mechanics. Ready-PR authority does not imply merge. Child merge authority does
not imply parent closeout. Words such as `finish`, `complete`, or `end to end`
do not independently grant decomposition, merge, graph mutation, deployment, or
closeout authority.

Use this source order:

Expand Down Expand Up @@ -120,6 +126,13 @@ outcome exists in its authoritative repository, artifact registry, tracker, or
environment. Treat canceled or not-planned blockers with missing required
outcomes as unresolved.

Prevent predictable oversizing here. When the live ticket already describes
independently valuable and trackable parts too large for one child, route it to
tracker-level decomposition before invoking `implement-ticket`; do not use
`carve-changesets` to compensate for a known non-PR-sized child. The carved
publication path is reserved for one coherent child whose completed
implementation turns out materially larger than the live guardrails predicted.

When multiple children are ready, prefer contracts and additive foundations
before consumers or cutovers, then prefer the child that unlocks the most
downstream work without widening scope. Do not absorb a missing sibling outcome
Expand All @@ -133,7 +146,8 @@ Invoke `implement-ticket` once with a concise handoff containing:
- parent outcome and only the dependency/sibling evidence needed for safe
independent shipping;
- repository, PR host, base, and named specifications;
- completion policy and every granted or withheld authority; and
- completion policy and every granted or withheld authority;
- the explicit decomposition grant or its explicit absence; and
- any epic-level rollout or merge-order constraint that qualifies the child.

The primary context may follow `implement-ticket` directly. A delegated worker,
Expand All @@ -153,8 +167,15 @@ transition, and cleanup evidence are internally consistent and match live state.
current-candidate non-merge gate with only merge withheld. Do not count the
child complete or unblock dependents that require merge. Continue only with
another independently ready child when the requested scope permits it.
- `ready_prs`: verify the reported PR count, ordered predecessor-base topology,
final-only closing syntax, per-PR candidate and non-merge gate evidence, and
whole-chain equivalence with the ticket candidate. Do not count the child
complete or unblock dependents that require merge.
- `merged`: verify mainline and tracker evidence, then refresh the complete live
graph before any selection or completion claim.
graph before any selection or completion claim. For a stacked child, also
verify `all_merged`, every PR merge and propagation step, and full-chain
representation on the base. Do not reproduce decomposition or propagation
mechanics while verifying the result.
- `blocked`: preserve the exact reason and partial artifacts. Never count it as
complete. Select another independently ready child only when the requested
scope permits; otherwise stop for the missing decision, outcome, or
Expand Down Expand Up @@ -206,7 +227,7 @@ Difficulty, ordinary CI wait time, or unrelated ready children are not blockers.
## Report the epic result

Report the requested scope, each invoked ticket and its terminal state, merged
and ready PRs, refreshed graph state, serial critical-path and parallel-ready
work, parent acceptance and closeout evidence, intentionally deferred work, and
one concrete next action. Never report a child or parent complete from stale or
unverified evidence.
and ready PRs or stacks, refreshed graph state, serial critical-path and
parallel-ready work, parent acceptance and closeout evidence, intentionally
deferred work, and one concrete next action. Never report a child or parent
complete from stale or unverified evidence.
6 changes: 6 additions & 0 deletions skills/implement-epic/evals/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,11 @@
"request": "Continue epic G-270 across three independently selected children.",
"graph": "Each child is selected only when independently ready; implement-ticket owns all direct dependencies.",
"ticket_results": ["G-271 ready_pr at the complete non-merge gate", "G-272 merged with verified mainline and transition evidence", "G-273 blocked with preserved artifacts"]
},
{
"id": "verify-stacked-child-result",
"request": "Continue epic G-280 after authorized child G-281 returns a three-PR carved result.",
"graph": "G-282 is blocked until G-281 is fully merged.",
"ticket_results": ["G-281 reports all_merged with three ordered PRs, per-PR gate evidence, propagation evidence, and full-chain representation on main"]
}
]
5 changes: 5 additions & 0 deletions skills/implement-epic/evals/expectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,10 @@
"case_id": "transitive-babysit-results",
"workflow_state": "mixed_ticket_results",
"required_actions": ["consume ready_pr merged and blocked unchanged", "do not invoke babysit-pr directly", "do not count ready_pr or blocked as merged", "refresh graph only after verified merged"]
},
{
"case_id": "verify-stacked-child-result",
"workflow_state": "stack_child_verified",
"required_actions": ["verify stack topology and every PR gate", "verify all_merged and full-chain representation on base", "do not invoke carve-changesets directly", "refresh graph before considering G-282"]
}
]
6 changes: 4 additions & 2 deletions skills/implement-epic/references/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ not-planned blockers with missing outcomes as unresolved.

After a returned `merged` result, verify the GitHub issue transition and reread
the complete parent/sub-issue/blocker graph before selecting another child or
claiming completion. A `ready_pr` result does not satisfy a dependency that
requires merge.
claiming completion. A `ready_pr` or `ready_prs` result does not satisfy a
dependency that requires merge. For a stacked `merged` result, verify the
reported topology, every PR merge, and full-chain representation on the base
without taking ownership of decomposition mechanics.

When duplicate implementation paths exist, do not choose a competing path; pass
the canonical ownership evidence into `implement-ticket` or return `blocked`
Expand Down
6 changes: 4 additions & 2 deletions skills/implement-epic/references/linear.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ prerequisite outcomes. Treat canceled or not-planned blockers with missing
outcomes as unresolved.

After `implement-ticket` returns `merged`, verify the expected Linear transition
and reread the complete epic relationship state. Do not treat `ready_pr` as a
completed child or unblock a dependent that requires merge.
and reread the complete epic relationship state. For a stacked result, also
verify every PR merge and full-chain representation on the base. Do not treat
`ready_pr` or `ready_prs` as a completed child or unblock a dependent that
requires merge.

## Separate tracker and PR host

Expand Down
17 changes: 14 additions & 3 deletions skills/implement-epic/scripts/tests/test_orchestration_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,26 @@ def test_product_neutral_runtime_contract(self):
def test_dependency_chain_is_stable_and_acyclic(self):
self.assertIn(
"`implement-epic` → `implement-ticket` → "
"(`review-code-change`, `babysit-pr`)",
"(`review-code-change`, `babysit-pr`, `carve-changesets`)",
self.contract,
)
self.assertIn(
"Do not make this skill invoke `review-code-change` or `babysit-pr` itself",
"Do not make this skill invoke `review-code-change`, `babysit-pr`, or "
"`carve-changesets` itself",
self.contract,
)
self.assertIn("never recursively invoke this skill", self.contract)

def test_child_terminal_states_are_stable(self):
for state in ("ready_pr", "merged", "blocked", "requires_epic"):
for state in ("ready_pr", "ready_prs", "merged", "blocked", "requires_epic"):
self.assertIn(f"`{state}`", self.contract)

def test_epic_only_passes_authority_and_verifies_stack_results(self):
self.assertIn("off by default", self.contract)
self.assertIn("ordered predecessor-base topology", self.contract)
self.assertIn("full-chain representation on the base", self.contract)
self.assertIn("gains no decomposition mechanics", self.contract)

def test_epic_does_not_own_lens_mechanics(self):
self.assertNotIn("review-solution-simplicity", self.contract)
self.assertNotIn("review-correctness", self.contract)
Expand Down Expand Up @@ -107,6 +114,10 @@ def test_eval_expectations_preserve_critical_boundaries(self):
"missing-asynchronous-wait",
):
self.assertEqual("blocked", self.expectations[case_id]["workflow_state"])
self.assertEqual(
"stack_child_verified",
self.expectations["verify-stacked-child-result"]["workflow_state"],
)


if __name__ == "__main__":
Expand Down
Loading
Loading