feat(#281): uniform ticket templates + custom-templates/ override#285
Conversation
Add the 5 missing ticket templates and refactor all 7 ticket-creating
skills to read their body from `templates/tickets/<name>.md`, so the
custom-templates/ path-mirroring contract (AgDR-0023) works uniformly
across `/feature`, `/bug`, `/task`, `/migration`, `/idea`, `/spike`,
`/investigation` — not just `/spike` + `/investigation` as before.
- Add templates/tickets/{feature,bug,task,migration,idea}.md (5 new)
- Move templates/{spike,investigation}.md → templates/tickets/
- Refactor 7 SKILL.md files: Pattern A (heredoc-only) → Pattern B
(portfolio_resolve_template tickets/<name>.md) with WARN-on-stderr
heredoc fallback for partial adopter setups
- Update path references in CLAUDE.md, docs/multi-project.md,
workflows/sdlc.md, templates/README.md, custom-templates README,
/investigation tests README + smoke.sh
- Add .claude/hooks/tests/test_ticket_template_resolution.sh
(36 cases covering default resolution, single-fork override,
split-portfolio sibling override, heredoc fallback, mixed-override
scenarios across all 7 ticket types)
- Add AgDR-0031 documenting the refactor decision and the
/update migration step (out of scope, separate ticket)
Closes #281
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review — PR #285 (commit 1166819)
Verdict: APPROVED (via comment — author cannot self-approve) ✅
Summary
Closes the uniformity hole between Pattern A (heredoc-only) and Pattern B (template-file-driven) ticket-creating skills described in #281. All 7 ticket types now resolve their issue body via portfolio_resolve_template tickets/<name>.md, so the AgDR-0023 path-mirroring contract applies uniformly. Well-scoped, well-tested, ships AgDR-0031 capturing the four orthogonal design choices (location / refactor scope / fallback shape / top-level-template move).
Architecture & Design
- No domain/application/infrastructure layering concerns — markdown + bash only
- Path-mirroring contract preserved — resolver unchanged; only the consumer surface broadens
- Single resolution call shape across all 7 skills (
portfolio_resolve_template tickets/<name>.md) — no skill-specific exceptions - AgDR-0031 dimension-by-dimension rationale follows the existing AgDR shape
Code Quality
- Bash test follows
test_portfolio_paths.shconventions (sandbox fixture,make_forkhelper,run_caserunner, per-process cache reset) - Template files use consistent
{{placeholder}}Mustache-style across all 5 new files - Glossary placeholder section added to every ticket template — encourages the PR-quality glossary discipline already enforced on PR bodies (
.claude/rules/pr-quality.md)
Testing
- 36 new test cases across 5 case sets: default resolution ×7, single-fork override ×7, split-portfolio sibling override ×7, missing-template fallback ×7 (resolver + WARN-on-stderr wrapper ×2), mixed-override scenario ×1
- Test verifies the fallback contract end-to-end — both resolver behaviour (empty + nonzero) AND a wrapper that emulates how the consuming SKILL.md reacts (FALLBACK output + WARN on stderr)
- Existing
test_portfolio_paths.sh(38/38) and.claude/skills/investigation/tests/smoke.sh(18/18) still pass after the path move — verified locally
Security
- No secrets, no input-handling code, no auth/crypto surfaces touched
- Test sandboxes use
mktemp -dwithpwd -Pcanonicalisation for macOS compatibility (matches existing pattern intest_portfolio_paths.sh) - No
evalof user-derived input; test snippets are framework-authored heredoc strings
Performance
- N/A — markdown + bash, no hot paths
- Template resolution adds one
portfolio_resolve_templatecall per ticket creation; already cached per-process via_PORTFOLIO_*_CACHEvars
PR Description Quality
- Clear 4-bullet summary
- Ticket linked (
Closes #281) - Testing section names every test that runs + pass counts
- Glossary present with 4 terms (Pattern A vs B, custom-templates path-mirroring, Heredoc fallback,
templates/tickets/subdir)
Technical Decisions (AgDR) — BLOCKING CHECK
- AgDR-0031 at
docs/agdr/AgDR-0031-ticket-template-uniformity.mdwithstatus: accepted, captures all 4 option dimensions, declares the/updatemigration step as Out of Scope (sibling ticket) - Resolution preserves AgDR-0023's contract — no new override semantics, just broader coverage
- No undocumented technical decisions detected in the diff
Handbook Findings
No handbooks under handbooks/architecture/, handbooks/general/, or handbooks/language/<lang>/ triggered by this diff (markdown + bash only — no language-handbook globs match). No custom-handbooks/ resolved.
Observations / Nits
/migrationconsumes two templates (nit). The skill resolvesagdr-migration.md(AgDR side, top-level) ANDtickets/migration.md(ticket body, in the new subdir). Diff captures this implicitly via the two resolver call sites; a one-line callout in AgDR-0031's Decision section would make it explicit. Non-blocking.- AgDR-0017 + AgDR-0027 Artifacts list mentions
templates/{spike,investigation}.md(informational). AgDR-0031 correctly calls these out as intentionally-unchanged historical records — AgDRs document state at decision time. The "current paths are documented intemplates/README.mdandCLAUDE.md" note is the right mitigation. - Backward-compat migration step correctly scoped Out (informational). PR body and AgDR-0031 defer the
/updateflow that detects old top-level overrides to a separate ticket coupling with the existing update-chain ticket. Good scope discipline.
Verdict
APPROVED. Clean, well-tested, well-documented refactor that closes a real adopter-facing UX hole with no behaviour change for adopters who never customise templates. Heredoc-fallback + WARN-on-stderr correctly trades a slightly larger SKILL.md surface for "partial cherry-picks don't break installations" — same trade-off shape as the existing portfolio_validate failure-mode design.
Add the 5 missing ticket templates and refactor all 7 ticket-creating
skills to read their body from `templates/tickets/<name>.md`, so the
custom-templates/ path-mirroring contract (AgDR-0023) works uniformly
across `/feature`, `/bug`, `/task`, `/migration`, `/idea`, `/spike`,
`/investigation` — not just `/spike` + `/investigation` as before.
- Add templates/tickets/{feature,bug,task,migration,idea}.md (5 new)
- Move templates/{spike,investigation}.md → templates/tickets/
- Refactor 7 SKILL.md files: Pattern A (heredoc-only) → Pattern B
(portfolio_resolve_template tickets/<name>.md) with WARN-on-stderr
heredoc fallback for partial adopter setups
- Update path references in CLAUDE.md, docs/multi-project.md,
workflows/sdlc.md, templates/README.md, custom-templates README,
/investigation tests README + smoke.sh
- Add .claude/hooks/tests/test_ticket_template_resolution.sh
(36 cases covering default resolution, single-fork override,
split-portfolio sibling override, heredoc fallback, mixed-override
scenarios across all 7 ticket types)
- Add AgDR-0031 documenting the refactor decision and the
/update migration step (out of scope, separate ticket)
Closes #281
Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
templates/tickets/{feature,bug,task,migration,idea}.md) and move the existing 2 (spike.md,investigation.md) into the sametemplates/tickets/subdir, so every ticket-creating skill has a template file at a mirrored path./feature,/bug,/task,/migration,/idea,/spike,/investigation) to resolve their issue body viaportfolio_resolve_template tickets/<name>.md. Adopter overrides at<private_repo>/custom-templates/tickets/<name>.mdnow win uniformly — closes the silent-override hole described in [Feature] Add missing ticket templates (feature, bug, task, migration, idea) + uniform custom-templates/ override #281.WARN: <path> template missing — using inline fallbackon stderr) preserves the pre-refactor behaviour when the template file is missing — partial adopter setups don't break.AgDR-0031-ticket-template-uniformity.mddocumenting the decision (Pattern A → Pattern B for the 5 older skills, plus thetickets/subdir move for spike + investigation).Testing
bash .claude/hooks/tests/test_ticket_template_resolution.sh— 36 cases covering default-resolution, single-fork override, split-portfolio sibling override, missing-template fallback, and mixed-override scenarios across all 7 ticket types.bash .claude/hooks/tests/test_portfolio_paths.sh— still passes (38/38).bash .claude/skills/investigation/tests/smoke.sh— updated to use the newtemplates/tickets/investigation.mdpath; still passes (18/18).Closes #281
Glossary
portfolio_resolve_template. Before #281: 5 skills on A, 2 on B. After #281: all 7 on B.<private_repo>/custom-templates/<same-path>. #281 makes the contract apply uniformly to every ticket type by giving each one a real framework template file at the mirrored path.portfolio_resolve_template tickets/<name>.mdreturns empty (template file missing — partial cherry-pick, broken install), the SKILL.md falls back to its pre-#281 inline heredoc body and prints a WARN on stderr. Keeps partial upgrades visible without breaking them.templates/tickets/subdirportfolio_resolve_template.🤖 Generated with Claude Code