Implement Ticket
SkillDev toolsEnd-to-end implementation pipeline for a GitHub issue in actual-mcp-server: gate the ticket to 10/10, implement it, validate, code-review it, and either fix findings inline or spin them into their own tickets, then commit + bump + push to develop. Use this whenever the user asks to implement, build out, do, work, or ship a ticket or issue by number, e.g. "implement ticket 167", "implement #178", "do issue 142", "build out ticket 90", or "/implement-ticket 178", even if they do not name every step. Do NOT use it for merely reading, triaging, gating, or reviewing a ticket without implementing it, or for code changes that are not tied to a specific issue number.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Implement Ticket skill
What this skill tells your AI
The instructions your AI receives, as published by agigante80/actual-mcp-server in .claude/skills/implement-ticket/SKILL.md and read by ahel’s review.
A repeatable pipeline that takes a GitHub issue number and carries it from
"ready to build" to "merged on develop", with adversarial review and automatic
follow-up ticketing baked in. It chains tools we already have (the ticket-gate
agent, the project validation sequence, /code-review, /local-env) so a
single instruction does what a careful engineer would do across an afternoon.
When this runs
Trigger on any request to implement a specific issue by number. Extract the
issue number from the prompt. If no number is present, ask for one before
starting. Everything happens on develop; never touch main (see CLAUDE.md).
Inputs and state to track
TICKET: the issue number under implementation.DEPTH: recursion depth, starts at0for the user-invoked ticket. Spinning off and auto-implementing a discovered ticket increments it. The cap is2.SEEN: the set of ticket numbers this run has already started, so a follow-up ticket can never re-enter a ticket already in progress (loop guard).
Hold these in a TodoWrite list so progress survives a long run.
The pipeline
Run the phases in order. A phase that cannot pass after its bounded retries stops the run with a clear report rather than limping forward.
Order depends on ticket type. For a bug, behaviour-change, or external /
fork-harvested ticket, run Phase 0 (Reproduce) BEFORE Phase 1 (Gate): gating,
security-reviewing, and synthesising a ticket that turns out to be a phantom is
wasted work, so prove it reproduces first and gate only what survives. For
greenfield features, docs, and chore/CI tickets (nothing to reproduce), skip
Phase 0 and start at Phase 1.
Phase 0: Reproduce first (bug, behaviour-change, and external/fork tickets)
Run this FIRST, ahead of the gate, when the ticket is labelled bug, proposes a
change to existing observable behaviour, OR is external / community /
fork-harvested. Skip it only for greenfield features with nothing to reproduce,
docs, and chore/CI tickets (say so in the report, then start at Phase 1).
An incoming ticket is a HYPOTHESIS, not ground truth. External and spec-derived tickets are routinely wrong: stale (the bug was fixed since), mis-scoped (only part of it is real), or mis-severity. Prove the reported behaviour against the CURRENT code before spending any effort gating or building it, so you never gate, security-review, and "fix" a phantom.
- Reproduce against current code, preferring the live
/local-env(it has caught several mischaracterised tickets, four already-fixed fork/spec phantoms among them, that unit-level reasoning alone would have missed). Write a focused failing check that demonstrates the reported behaviour and capture its red result. That check is the start of the regression test, it is not throwaway. - Branch on the outcome, and report which happened with evidence:
- Reproduces as described -> proceed to Phase 1 (gate), then implement. The red check is the test that must go green.
- Does not reproduce -> STOP. Do not gate, do not implement. Recharacterise
or close the ticket (with the evidence), the way the
payee_rules_get, #211 "already fixed / not a crash", and #194 "already implemented" findings were handled. - Reproduces differently (different severity, scope, or symptom) -> rewrite the ticket body to match reality (re-title, re-label, fix the symptom) before gating.
- Surfaces an out-of-scope sibling bug (as reproducing #194 surfaced #212) -> file a gate-ready ticket for it; do not expand this ticket's scope.
- Tier the rigor by source: external / community / fork-harvested tickets get the full treatment plus the mandatory security review; internal trivial changes can be lighter. When unsure, do more.
A behaviour change is not done until a check that was red is green. Carry the red check into Phase 2 (make it pass) and Phase 3 (it runs in the suite). If the fix changes observable behaviour, sweep every affected test, tool description, and doc in Phase 2, not just the line you changed.
Phase 1: Gate to 10/10
Gate only a ticket that survived Phase 0 (or one that skipped it: a greenfield feature, docs, or chore). The ticket must score 10/10 from every gate agent before any code is written, so the spec is unambiguous and testable.
- Run the gate:
Agenttool,subagent_type: ticket-gate, prompt = the issue number. - If the result is BLOCKED, this is fully automated (no confirmation): edit the
issue body with
gh issue edit <n> --body-file <file>to resolve each named gap, then re-run the gate. Per the re-run rule only the failed agents are re-scored. Make a real engineering decision for design-ambiguity blockers (pick the better option and justify it in the body), do not just restate the ticket. - Cap at 4 gate rounds. If it still is not 10/10, stop and report what remains.
Writing the body files: the gh sandbox cannot read /tmp, so write body files
into the repo root as a dot-file (e.g. ./.ticket-<n>-body.md) and delete them
after the gh call.
Phase 2: Implement
Treat the now-10/10 ticket body as the spec. Read it in full plus CLAUDE.md, and
follow the project's conventions exactly (amounts in integer cents, dates as
YYYY-MM-DD, withActualApi around every Actual call, createTool for new
tools, Zod from CommonSchemas). Prefer delegating to the project subagents
when the work is in their domain: tool-author for a brand-new MCP tool, qa
for test-heavy work, actual-api for @actual-app/api behaviour questions.
Write the tests the ticket specifies (positive and negative) and wire new unit
tests into the test:unit-js chain in package.json. Update the docs the
ticket and CLAUDE.md's "Documentation Sync" table call for.
Phase 3: Fast validation
Run the mandatory pre-commit sequence; all must be green before review:
npm run build
npm run verify-tools # confirm the expected tool count
npm run test:unit-js
npm run test:adapter
npm audit --audit-level=moderate # no NEW vulnerabilities
test:adapter and unit tests need Actual env vars set; export the dummy values
the CI uses (ACTUAL_SERVER_URL=http://localhost:5006,
ACTUAL_PASSWORD=dummy, ACTUAL_BUDGET_SYNC_ID=00000000-0000-0000-0000-000000000000).
A red phase here means fix and re-run, do not proceed.
Phase 4: Code review
Stage the changes (git add -A the implemented files) so the full diff,
including new files, is in scope, then run the /code-review skill at high
effort on the working diff. Collect the verified findings.
Phase 5: Triage findings (the inline-vs-ticket decision)
For each verified finding, decide with the scope-and-risk rubric:
-
Fix inline when it is within this ticket's scope AND low-risk: typos, small logic corrections, a missing guard or null check, a test or doc gap. After inline fixes, return to Phase 3 (re-validate) then Phase 4 (re-review). Loop until a review pass is clean. Cap at 3 review-fix loops; if findings keep appearing, stop and report.
-
Spin off a ticket when it is out of scope, a separate pre-existing bug, or a larger design change (a new abstraction, touching files outside this ticket). Create it with
gh issue createusing the bug or feature template (include the<!-- template-version: 3 -->marker and an area label so it is gate-ready), and cross-reference the current ticket.Then, if
DEPTH < 2and the new ticket number is not inSEEN: auto-implement it now by recursing into this same pipeline withDEPTH + 1and the new number added toSEEN. When that nested run returns, resume the current ticket. IfDEPTH == 2(cap reached) or the ticket is already inSEEN, do NOT recurse: leave the new ticket open, note it in the final report, and continue.
A finding being "major" is not automatically a reason to stop the current ticket: only the findings that are genuinely about THIS ticket's code block its completion. An out-of-scope discovery becomes a tracked ticket and does not gate the current work.
Phase 6: Live validation
Once review is clean, run /local-env full (which runs
bash scripts/deploy-and-test.sh full). This rebuilds the image from the working
tree and exercises the real server. It must pass. Skip the optional
--bank-sync unless the ticket is about bank sync. If the live run reveals a
real regression, treat it as a Phase 5 finding (fix inline or ticket) and loop.
Phase 7: Finalize on develop
When validation and review are both clean:
- Commit the implementation to
developwith a descriptive Conventional-Commit message that references the ticket ((#<n>)), ending with the standardCo-Authored-Bytrailer. - Bump the patch version:
npm run version:bump -- patch. It edits VERSION, package.json, and the doc markers (never edit those markers by hand), and prints the git commands. Commit the bump aschore(release): bump version to X.Y.Z. (CI-only or dev-dependency-only changes do not bump the product version; say so in the report.) git push origin develop.
Phase 8: Confirm CI is green (close the loop)
Local validation is NOT CI validation. The GitHub Actions pipeline runs steps
the local suite does not (workflow linting, multi-arch docker builds, the
docker-e2e tool-count check) and runs in a different environment (different Node,
different system tools such as shellcheck), so green-local can still be red-CI.
This phase exists because a real run once pushed a green-local change that failed
CI on every push and it was not noticed for a whole batch.
After the push, find the CI run for the pushed commit and wait for it to finish:
git rev-parse HEAD # the pushed SHA
gh run list --branch develop --limit 3 # find the CI/CD Pipeline run for that SHA
gh run view <run-id> # poll until status is completed
- If the run concludes success, the ticket is done.
- If any job fails, treat it as a Phase 5 finding: read
gh run view <id> --log-failed, then fix inline if in-scope and low-risk (re-validate, re-push, re-confirm CI), or spin off a gate-ready ticket for an out-of-scope failure. A red CI run is NOT a completed ticket, even when every local gate passed. Reproduce the failing CI step locally with the SAME tool versions CI uses before claiming a fix.
Stop here. Do not merge to main, do not tag, do not release. Report the commit
hashes, the new version, the CI run conclusion (with the run id), and any
follow-up tickets created (with their numbers and whether they were
auto-implemented or left open).
Guardrails
- A ticket is a hypothesis, not ground truth. For bug, behaviour-change, and external/fork tickets, reproduce against current code first (Phase 0), BEFORE the gate, so a phantom is never gated or built. If it does not reproduce, recharacterise or close it. If it reproduces differently, rewrite then gate. Never fix from the report alone.
- Red before green. A behaviour change is not done until a check that was red is green, and the fix sweeps every affected test, tool description, and doc.
- develop only. Never push to
main, never tag, never release. That stays a separate, explicit human step. - No em or en dashes anywhere (CLAUDE.md hard rule): not in commits, issue bodies, comments, code, or docs. Restructure with a colon, comma, parentheses, "to" for ranges, or two sentences. A PreToolUse hook enforces this; self-check regardless.
- Recursion is depth-capped at 2 and loop-guarded by
SEEN, so a chain of discovered tickets cannot run away. - Bounded retries on every loop: 4 gate rounds, 3 review-fix loops. Exceeding a cap stops the run with a report, it does not spin.
- Honest reporting. If a phase fails or is skipped, say so with the evidence. Never claim green without the command output.
- A ticket is not done until CI is green. Local validation passing is
necessary but not sufficient; always confirm the GitHub Actions run for the
pushed commit concluded
success(Phase 8). Never report a ticket complete on a red or unchecked CI run.
Failure and resumption
If the run stops at any phase (cap exceeded, unfixable failure, gate stuck), report exactly where it stopped, what is committed vs uncommitted, what tickets were created, and the single next action. The user can re-invoke the skill on the same ticket to resume; earlier phases that already passed (a 10/10 gate, a green build) can be confirmed quickly rather than redone from scratch.
Signals
- GitHub stars
- 54
- Forks
- 19
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
implement-ticket- Source
- github.com/agigante80/actual-mcp-server