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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ summary: Chronological history of repository and skill changes.

# Changelog

## 2026-07-20 — Composed ticket and PR execution

- fix: execute result-blind forward evaluations in fresh contexts
- feat: delegate the `implement-ticket` PR lifecycle to `babysit-pr`
(`d5838d49587ab34a00973441a870cd525cfcd773`)

## 2026-07-20 — Repository-owned PR babysitting

- fix: bind each watcher lock to an immutable repository and pull request target
(`3666b3d5beb9182b3dab221d2489a7acf23323b7`)
- fix: validate the locked PR state path before any snapshot read or write
(`322a83c6b31d5668e6648df8f0fabe3732c3e74f`)
- fix: serialize every watcher state mutation through one repository/PR lock
Expand Down
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ Current reusable agent skills:
current-head CI, feedback, repository-owned re-review, mergeability, and an
explicitly authorized completion policy
- `skills/implement-ticket` — implement exactly one standalone ticket or named
epic child through isolated execution, repository-owned review, PR gates, and
authorized merge and cleanup; this is the canonical owner of generic
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`
- `skills/implement-epic` — traverse live GitHub or Linear epic graphs and
delegate each selected child to `implement-ticket`, then refresh graph state
Expand All @@ -37,15 +38,11 @@ The composed implementation dependency chain is:
```text
implement-epic
└── implement-ticket
└── review-code-change

babysit-pr
└── review-code-change (after a head change or when current evidence is absent)
├── review-code-change # initial candidate review
└── babysit-pr # published PR lifecycle
└── review-code-change # after a head-changing fix
```

Integrating `babysit-pr` into `implement-ticket` is tracked separately so the
standalone skill can be reviewed and merged first.

Compatible runtimes may provide named subagents or equivalent isolated
implementation and review contexts. OpenAI-facing files under `agents/` are
optional discovery metadata, not part of the skills' portable contracts.
Expand All @@ -66,6 +63,7 @@ just test-review-suite
just test-babysit-pr
just test-implement-ticket
just test-implement-epic
just eval-implement-ticket
```

Validate a review packet and result together:
Expand All @@ -78,8 +76,16 @@ Run deterministic local evals without an agent runtime:

```bash
just eval-prepare-changesets
just eval-implement-ticket
```

The ticket-composition evaluator starts a fresh process for each raw-artifact
case, with fixture identity and grader expectations withheld. Its bundled
reference executor validates the portable skill contract deterministically. To
forward-evaluate another compatible agent runtime, pass its stdin/stdout JSON
adapter through `scripts/evals/run_forward.py --executor` and retain captured
observations with `--output-dir`.

## Prerequisites

- Python 3.11+
Expand Down
3 changes: 3 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ test-babysit-pr:
test-implement-ticket:
python3 -m unittest discover -s {{skills_dir}}/implement-ticket/scripts/tests -p 'test_*.py'

eval-implement-ticket:
python3 {{skills_dir}}/implement-ticket/scripts/evals/run_forward.py

test-implement-epic:
python3 -m unittest discover -s {{skills_dir}}/implement-epic/scripts/tests -p 'test_*.py'

Expand Down
15 changes: 9 additions & 6 deletions skills/implement-epic/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ 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`. Verify `implement-ticket` directly and require its result
to prove that its own review dependency and applicable capabilities were
available. Do not make this skill invoke `review-code-change` itself.
(`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.

Stop before child mutation with an explicit limitation when an applicable
capability or dependency is unavailable. Product-specific discovery metadata
Expand Down Expand Up @@ -147,9 +149,10 @@ Do not trust a reported result until ticket identity, repository, base,
branch/worktree, candidate, PR, validation, review, remote-gate, merge,
transition, and cleanup evidence are internally consistent and match live state.

- `ready_pr`: record the candidate and remaining gates. 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_pr`: verify the candidate is open, mergeable, and at the complete
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.
- `merged`: verify mainline and tracker evidence, then refresh the complete live
graph before any selection or completion claim.
- `blocked`: preserve the exact reason and partial artifacts. Never count it as
Expand Down
6 changes: 6 additions & 0 deletions skills/implement-epic/evals/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,5 +101,11 @@
"request": "Implement epic G-260 through child merges.",
"graph": "G-261 is open and ready, with asynchronous CI and review gates required by its ticket workflow.",
"runtime_profile": "The runtime cannot poll, wait, or resume after asynchronous child gates."
},
{
"id": "transitive-babysit-results",
"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"]
}
]
5 changes: 5 additions & 0 deletions skills/implement-epic/evals/results.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,10 @@
"case_id": "missing-asynchronous-wait",
"workflow_state": "blocked",
"required_actions": ["name asynchronous wait as unavailable", "perform no child mutation", "do not pretend ticket or remote gates passed"]
},
{
"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"]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_product_neutral_runtime_contract(self):
self.contract,
)
self.assertIn(
"`implement-epic` → `implement-ticket` → `review-code-change`",
"`implement-epic` → `implement-ticket` → (`review-code-change`, `babysit-pr`)",
self.contract,
)
self.assertIn("retain task state", self.contract)
Expand Down Expand Up @@ -90,6 +90,10 @@ def test_epic_does_not_own_review_or_ticket_mechanics(self):
self.assertNotIn("review-code-simplicity", self.contract)
self.assertNotIn("fix/re-review cycles", self.contract)
self.assertNotIn("per-PR cleanup", self.closeout)
self.assertIn(
"Do not make this skill invoke `review-code-change` or `babysit-pr` itself",
self.contract,
)

def test_graph_selection_and_refresh_use_live_native_state(self):
self.assertIn(
Expand Down Expand Up @@ -168,6 +172,7 @@ def test_forward_cases_cover_composed_contract(self):
"missing-review-dependency-through-ticket",
"missing-isolation-capability",
"missing-asynchronous-wait",
"transitive-babysit-results",
}
self.assertEqual(required, set(self.cases))
self.assertEqual(required, set(self.results))
Expand Down Expand Up @@ -198,6 +203,14 @@ def test_forward_results_preserve_critical_boundaries(self):
"missing-asynchronous-wait",
):
self.assertEqual("blocked", self.results[case_id]["workflow_state"])
self.assertEqual(
"mixed_ticket_results",
self.results["transitive-babysit-results"]["workflow_state"],
)
self.assertIn(
"do not invoke babysit-pr directly",
self.results["transitive-babysit-results"]["required_actions"],
)


if __name__ == "__main__":
Expand Down
88 changes: 59 additions & 29 deletions skills/implement-ticket/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: implement-ticket
description: Implement exactly one standalone GitHub or Linear ticket, or one named child of a larger epic, through an isolated branch and pull request. Use when an agent should resolve live ticket and dependency context, enforce readiness and authority boundaries, implement and validate one coherent change, invoke the repository-owned review-code-change skill in a fresh read-only context, handle current-head remote gates, and optionally merge and clean up when explicitly authorized. Detect whole-epic requests before mutation and route them toward implement-epic without creating a circular skill dependency.
description: Implement exactly one standalone GitHub or Linear ticket, or one named child of a larger epic, through an isolated branch and pull request. Use when an agent should resolve live ticket and dependency context, enforce readiness and authority boundaries, implement and validate one coherent change, run an initial repository-owned review, delegate the published PR lifecycle to babysit-pr, and verify tracker, mainline, and cleanup outcomes. Detect whole-epic requests before mutation and route them toward implement-epic without creating a circular skill dependency.
---

# Implement Ticket
Expand All @@ -10,10 +10,11 @@ claiming a parent epic is complete. Treat live tracker and repository evidence
as execution state; use old plans or summaries only for orientation.

Treat this skill as the canonical owner of generic single-ticket readiness,
implementation, review, PR, merge, base-drift, feedback, tracker-transition,
cleanup, and terminal-reporting rules. `implement-epic` consumes this contract
for each selected child. Do not copy these rules back into epic orchestration or
create a third shared workflow abstraction.
implementation, initial review, PR publication, tracker transition, mainline
verification, cleanup, and terminal reporting. Delegate the post-publication PR
lifecycle to repository-owned `babysit-pr`. `implement-epic` consumes this
contract for each selected child. Do not copy either skill's rules back into
epic orchestration or create a third shared workflow abstraction.

## Load the applicable references

Expand All @@ -23,6 +24,8 @@ create a third shared workflow abstraction.
parent, dependency, or status state.
- Always read [review and merge gates](references/review-and-merge-gates.md)
before publishing the pull request.
- Always read [the babysit-pr handoff](references/babysit-pr-handoff.md) before
creating implementation state and again before transferring PR ownership.
- Always read [cleanup and result](references/cleanup-and-result.md) before a
merge or terminal handoff.

Expand All @@ -34,8 +37,9 @@ same-numbered issue from the PR host for the real tracker ticket.

A compatible agentic runtime must be able to:

- load `implement-ticket` and repository-owned `review-code-change` by stable
skill name or an equivalent repository-owned dependency mechanism;
- load `implement-ticket`, repository-owned `review-code-change`, and
repository-owned `babysit-pr` by stable skill name or an equivalent
repository-owned dependency mechanism;
- read repository instructions, tracker state, and structured relationships;
- inspect and create isolated branch/worktree state;
- edit files, run commands, commit, push, and manage PRs when authorized;
Expand Down Expand Up @@ -95,11 +99,27 @@ manual transition. State that consequence before publication or merge. Do not
use automatic closing syntax when its effect conflicts with the resolved
completion policy.

Before implementation can produce a reviewed PR, verify that
`review-code-change` is available and readable by stable name or an equivalent
repository-owned dependency mechanism. It is the only local adversarial-review
dependency. Return `blocked` before mutation when it is unavailable; do not
substitute a third-party skill, generic self-review, or unreviewed path.
After applying the whole-epic scope guard, and before creating a branch,
worktree, or other implementation state for a ticket, verify that both
`review-code-change` and `babysit-pr` are available and readable by stable name
or an equivalent repository-owned dependency mechanism. Return `blocked` before
mutation when either is unavailable. Do not substitute a third-party reviewer,
generic self-review, private PR loop, runtime download, or stranded unmonitored
PR path. A whole-epic `requires_epic` result occurs before these ticket-only
dependencies are invoked.

The dependency graph is deliberately acyclic:

```text
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` must never invoke `implement-ticket`. Do not re-enter this skill
while consuming a babysitter result.

## Establish source-of-truth precedence

Expand Down Expand Up @@ -244,20 +264,29 @@ cycles by default.

Treat a missing dependency, malformed result, `blocked` verdict, reviewer
mutation, or unavailable required evidence as a failed local gate. The review
suite stays read-only; this skill owns accepted fixes, GitHub replies, thread
resolution, commits, pushes, merge, and cleanup within granted authority.

### 6. Apply current-candidate remote and merge gates

Do not equate CI success, stale approval, or zero threads with a clean review.
Require every applicable local, CI, human, connector, comment, formal-review,
and thread gate for the current candidate. Follow the risk-based base-drift
rules in the gate reference.

When merge is authorized and every gate passes, merge using the repository's
approved method. Verify remote merge state, mainline representation, and the
owning tracker's ticket transition before cleanup. For an epic child, reread the
affected native dependency relationships after that transition and report newly
suite stays read-only. This skill owns accepted fixes, commits, and pushes
during the initial review loop. Post-publication fixes, replies, thread
resolution, pushes, and merge belong to `babysit-pr` after explicit ownership
transfer; cleanup remains here.

### 6. Delegate the published PR lifecycle

Follow [the babysit-pr handoff](references/babysit-pr-handoff.md). After the
initial review loop is clean, reread the live PR, build the verified handoff,
and transfer exclusive mutation ownership to `babysit-pr` or follow it in the
same exclusive context. Do not maintain a second CI, feedback, base-drift,
post-fix review, or merge loop here.

Map `ready PR only` to `ready_to_merge`. Map both merge policies to
`merge_when_ready`. Normal ticket execution never uses `watch_until_closed`.
Ordinary pending CI or review time is not a blocker; retain task ownership and
continue until the mapped policy reaches a terminal result or a genuine
user-help-required condition occurs.

Validate the returned identity and evidence against live GitHub state. After an
authorized merge, independently verify remote merge state, mainline
representation, and the owning tracker's ticket transition before cleanup. For
an epic child, reread affected native dependency relationships and report newly
unblocked work without selecting or mutating it. Never close or verify a parent
epic from this skill.

Expand All @@ -281,9 +310,10 @@ sibling work is not a blocker.
Follow [cleanup and result](references/cleanup-and-result.md). Return exactly
one terminal state:

- `ready_pr`: the one-ticket PR exists at the reported candidate; state every
remaining remote or authority gate, and confirm this run owns or was
explicitly handed ownership of the candidate;
- `ready_pr`: the one-ticket PR is open and mergeable at the reported candidate,
every applicable current-candidate non-merge gate has passed, merge was
withheld, and this run owns or was explicitly handed ownership of the
candidate;
- `merged`: the PR is verified on the base, the ticket transition is verified,
and authorized cleanup is complete or precisely limited;
- `blocked`: give one concrete blocking reason and next action, preserving any
Expand Down
4 changes: 2 additions & 2 deletions skills/implement-ticket/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface:
display_name: "Implement Ticket"
short_description: "Implement one ticket through a reviewed PR"
default_prompt: "Use $implement-ticket to implement this ticket through the authorized validation, review, PR, and merge gates."
short_description: "Implement and babysit one ticket PR"
default_prompt: "Use $implement-ticket to implement this ticket, run its initial review, delegate the published PR to babysit-pr, and verify the authorized result."
6 changes: 3 additions & 3 deletions skills/implement-ticket/evals/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"request": "Implement GitHub issue G-21.",
"tracker_state": "Open standalone PR-sized ticket with complete requirements, no blockers, and no existing implementation.",
"authority": "ready_pr_only",
"runtime_profile": "Repository-owned skills and named subagents are available.",
"capabilities": ["stable_skill_loading", "structured_tracker_relationships", "isolated_worktree", "command_execution", "github_pr", "named_read_only_reviewer", "asynchronous_wait", "thread_aware_feedback"]
"runtime_profile": "Repository-owned review-code-change and babysit-pr plus named isolated contexts are available.",
"capabilities": ["stable_skill_loading", "review_code_change", "babysit_pr", "structured_tracker_relationships", "isolated_worktree", "command_execution", "github_pr", "named_read_only_reviewer", "asynchronous_wait", "thread_aware_feedback"]
},
{
"id": "authorized-merge-cleanup",
Expand Down Expand Up @@ -50,7 +50,7 @@
"id": "clean-local-review-remote-pending",
"request": "Implement GitHub issue G-28 to a ready PR.",
"authority": "ready_pr_only",
"candidate_state": "Local validation and review are clean; required current-head human and connector approvals remain pending; zero threads are unresolved."
"candidate_state": "Initial validation and review are clean; babysit-pr waits through pending human and connector approvals until both become current for the unchanged head."
},
{
"id": "unrelated-base-drift-retained",
Expand Down
Loading
Loading