| name | release-notes |
| description | Jira-driven release-notes drafting. Reads a Value Increment (or any ticket) from exported markdown, optionally grounds in PR diffs, renders a dynatrace-docs release-notes body, runs a light dt-style-checker gate, and writes a persistent draft to paste into Jira's release-notes field. Activated when the user prompt starts with "release-notes:".
|
| allowed-tools | view, edit, create, bash, glob, grep, task, ask_user |
Draft release notes for the Jira ticket: the argument (text following the release-notes: trigger)
release-notes: produces a customer-facing release-notes draft for a Jira
Value Increment (or any ticket) from pre-exported markdown in the user's Obsidian vault.
It optionally grounds the prose in merged PR diffs, renders the dynatrace-docs authored
release-notes body (a {{#context}} label + ### title + prose — no {{#internal-note}},
no Jira IDs, no PR links; the docs automation adds the metadata wrapper), runs a light
style gate, and writes the draft to a persistent destination for the user to paste into
Jira's release-notes field.
For full feature documentation use document:; for Epic drafting use epics:.
This command makes zero external API calls and never writes into the docs repo
(release-notes pages there are generated by Jira-driven automation).
Phase 0 — Load
-
Resolve the Jira input via the shared front-end. Execute
~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/jira-input-resolution.md against
the argument (text following the release-notes: trigger). release-notes: is jira-driven only: expect
mode: jira-driven with jira_key, jira_export_root (the ticket export
dir — $VAULT_PATH/jira-products/<KEY> for a JiraID, or the passed
directory), and source. The front-end owns the $VAULT_PATH /
jira-products validation and Fallbacks A/B. Carry jira_key,
jira_export_root, and focus_key forward.
If the front-end returns mode: direct (no Jira input), stop with
RELEASE_NOTES_NEEDS_JIRA: release-notes: needs a Jira key or an imported-Jira directory. —
this command has no direct-prompt behavior.
Phase 1 — Clarification
Rule: Ask, don't guess. Group questions; use choices arrays; the last choice MUST be "Other… (describe)".
-
Diff grounding (default OFF — Jira content is usually enough for release notes):
choices: ["Jira content only (Recommended)", "Also ground in merged PR diffs (you'll pick repos)", "Cancel", "Other… (describe)"]
If "ground in PR diffs", additionally ask the two sub-questions below.
-
Repos search base ($REPOS_PATH) (only if diff grounding is ON). Read ${REPOS_PATH:-/workspace}; may be a colon-separated list. Ask:
choices: ["Use $REPOS_PATH (default /workspace) (Recommended)", "Use a different path (you'll be prompted)", "Cancel", "Other… (describe)"]
Clones are located in Phase 4 by matching git remote against each PR's repo slug — not by assuming a <base>/<slug> directory name.
-
PR status filter (only if diff grounding is ON):
choices: ["MERGED only (Recommended)", "All PRs (MERGED + OPEN + DECLINED)", "Specific list (you'll be prompted)", "Other… (describe)"]
-
Output destination. Always write to a file (console-pasted markdown
loses formatting in Jira). Resolve the default by $VAULT_PATH:
choices: ["Write to <default file> (Recommended)", "Write to a different absolute path (you'll be prompted)", "Print to screen only", "Skip writing", "Other… (describe)"]
Print-to-screen and Skip remain available but are never the default. The
default is persistent (host-mounted; survives container restart, unlike
/tmp). NEVER offer or accept a path inside a docs repo or under
jira-products/.
-
Style check (default ON when the dt-style-guide plugin is installed):
choices: ["Run dt-style-checker then apply safe fixes (Recommended)", "Run dt-style-checker, report only (no auto-fix)", "Skip style check", "Other… (describe)"]
Also display: resolved jira_export_root, jira_key (plus $VAULT_PATH when set), $REPOS_PATH (or "N/A — Jira-only"), and the resolved destination.
Phase 1.5 — Classify
Load and follow the model-routing policy at ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/model-routing.md, then classify the task. Release-notes drafting is MODERATE (bounded prose synthesis from a single ticket; no Opus planning or review gate). State the classification and a one-sentence reason.
Phase 2 — Worthiness check + plan/approval
-
Worthiness. After Phase 3 reads the ticket (or by reading the VI frontmatter now), check relevant_for_release_notes and release_versions. If relevant_for_release_notes != "Yes" AND release_versions is empty/absent, warn and ask:
choices: ["Proceed anyway (Recommended)", "Cancel", "Other… (describe)"]
-
Plan. Present: resolved jira_key, destination, diff-grounding on/off (+ $REPOS_PATH and repos to scan when on), release versions detected, style-check choice. Ask:
choices: ["Approve & continue (Recommended)", "Revise plan", "Cancel"]
Phase 3 — Read Jira
Invoke jira-reader. Use depth: vi-only when diff grounding is OFF; depth: full when ON (to collect PR URLs from the hierarchy's ## Pull Requests sections).
→ task(agent_type: "dev-workflows:jira-reader"):
"Return the structured handoff for this brief:
jira_export_root: [resolved jira_export_root]
jira_key: [resolved jira_key]
depth: [vi-only | full]"
When focus_key is set (explicit <VI> <Epic>), scope the Phase 6 render input
to the focus Epic's subtree — the focus Epic plus its linked descendants — so the
release note covers that Epic's user-facing changes rather than the whole VI. This
scopes only what Phase 6 renders; it does not mutate the stored handoff that other
phases read. When focus_key is null, the draft covers the whole ticket/VI exactly as
today.
If status: NOT_FOUND / EMPTY, surface ["Re-enter key", "Cancel"]. On OK, parse release_versions from the VI frontmatter into a list (e.g. "Managed (344), SaaS (344)" → ["Managed (344)", "SaaS (344)"]).
Phase 4 — Resolve repos (only if diff grounding is ON)
Build a slug→clone map: for each top-level directory under each entry of $REPOS_PATH, run timeout 5 git -C <dir> remote get-url origin 2>/dev/null, strip a trailing .git, and take the URL's last path segment as the clone's slug. Resolve each in-scope PR repo slug against the map: one match → use it; multiple → auto-prefer basename ending -repo, then _repo/_fast, then alphabetically last; zero matches → escalate:
choices: ["Skip and continue without its PRs", "I'll clone it — wait", "Cancel", "Specify a different absolute path for this repo", "Other… (describe)"]
Phase 5 — Diff summarisation (only if diff grounding is ON)
Spawn diff-summarizer in batches of up to 4 concurrent agents per Agent message, passing each resolved absolute repo_path plus repo_url_slug and the PRs filtered to that repo. Collect the outputs into a diff_summaries array.
Phase 6 — Render the draft
→ task(agent_type: "dev-workflows:release-notes-writer"):
"Render the release-notes draft for this brief:
jira_reader_handoff: [the Phase 3 handoff — scoped to the focus Epic's subtree when focus_key is set]
diff_summaries: [the Phase 5 array, or omit when diff grounding was off]
release_versions: [parsed list, or [] ]
context_label_hint: [user hint if any, else null]
change_type_hint: [user-supplied Change Type and/or deprecation signal if any, else null]
model_routing: [the block from Phase 1.5]
code_repos: [the Phase-4 resolved {slug, path} map when diff grounding is on; omit otherwise]"
If status: PARTIAL, surface each gaps entry with recommended_action: "ask user" and let the user supply the label/prose or accept a <!-- TODO --> marker.
For a field: change_type gap (low-confidence classification), present the writer's
proposed value and let the user confirm or override:
choices: ["<proposed value> (Recommended)", "Breaking change", "New technology support", "Bug fix", "not applicable", "Other… (describe)"]
Apply the chosen value to release_notes_block.change_type (and thus the draft's leading Change type: line).
For a field: deprecation_eol gap (a deprecation was detected but the required
end-of-life date is unclear), ask the user:
choices: ["Enter the end-of-life date (you'll be prompted; end-of-support optional)", "Leave the <!-- TODO: end-of-life date --> marker in the draft", "This isn't a deprecation — drop the note", "Other… (describe)"]
On a supplied date, replace the <!-- TODO: end-of-life date --> placeholder with the
end-of-life date (and end-of-support date when given), formatted per the dt-style-guide
(e.g. November 30, 2026).
When release-notes-writer returns gaps[] entries that have jira_phrasing and source_phrasing (source-truth discrepancies), present the discrepancy table and per-claim prompt as in document: (Jira mode) Phase 5.8:
- Show the analysis table (claim, Jira phrasing, source phrasing, location).
- Ask:
choices: ["Decide per discrepancy (Recommended)", "Document ALL as actual (code)", "Document ALL as intended (Jira)", "Skip ALL and report (drafts a bug report)", "Cancel", "Other… (describe)"]
- Apply the decision to the draft prose:
document-as-code → use source phrasing; document-as-spec → use Jira phrasing (no marker in release notes prose — the gap is recorded only in the gaps file); skip-and-report → omit the claim.
- For
document-as-spec or skip-and-report: resolve bug_report_destination the same way as the release-notes destination — $VAULT_PATH set → the find "$VAULT_PATH/Projects" -maxdepth 5 -type d -name "<jira_key>*" project folder; $VAULT_PATH unset → <parent-of-jira_export_root>/. Write/append <bug_report_destination>/<jira_key>-implementation-gaps.md using the §7.5 format from ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/source-truth.md, setting Spec phrasing: to (no spec) (this flow has no spec).
Pass code_repos (the Phase-4 resolved map) to the writer when diff-grounding is on.
Phase 7 — Style gate (optional)
If the user chose a style check AND the dt-style-guide plugin is installed:
→ task(agent_type: "dt-style-guide:dt-style-checker") on the combined_rendered draft (write it to the destination first when the destination is a file, or pass it inline). If violations are returned and the user chose auto-fix:
→ task(agent_type: "dt-style-guide:dt-doc-fixer") to apply safe fixes.
If dt-style-guide is not installed, skip this phase and note "style check skipped — dt-style-guide not installed" in the report.
Phase 8 — Write + report
-
Write the combined_rendered draft to the resolved destination:
file:<path> → write it. If the file exists, ask: ["Overwrite", "Write to <path>.new", "Print to screen instead", "Skip"].
stdout → include the full draft in the report under ### Release-notes draft.
skip → do not write.
NEVER write into a docs repo.
-
Report:
## Release-notes draft — <jira_key>
- Destination: <path | stdout | skipped>
- Release versions: <list, or "none declared">
- Change type: <Breaking change | New technology support | Bug fix | not applicable>
- Deprecation: <EOL <date> (end-of-support <date | —>) | none>
- Diff grounding: <on (repos: …) | off>
- Style check: <applied N safe fixes | report only (M findings) | skipped (dt-style-guide absent)>
- Reminder: paste this into the ticket's Jira release-notes field — the docs automation adds the {{#internal-note}} metadata and emits it into dynatrace-docs.
### Next step
[leaf/closure per `~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/next-phase-offer.md` — guidance only, never auto-invoked: the release note is drafted. If earlier pipeline phases remain, continue — hand to PA → `create-ard: <VI>` or PE → `epics: <VI>`; if the change is already built and documented, the VI is fully processed.]
### Context hygiene
Write the resume pointer at `<VI-dir>/dev-workflows/resume.md` (per `session-hygiene.md` §1). Then:
- **Release note drafted and the VI fully processed?** → nothing to suggest — you're done.
- **A PA/PE phase still pending for this VI (e.g. `create-ard:`, `epics:`), even yourself?** → run **`/clear`** before switching roles.
- Consider **`/rename <VI-ID>-<slug>-pm`** to relocate this session later.
Guidance only — see `~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/session-hygiene.md`.
Phase 9 — Emit follow-up tasks
Terminal phase — runs AFTER the Phase 8 report is composed; NEVER interrupts an
earlier phase. Persist the run's manual-step follow-ups by citing
~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/followup-emission.md and executing its steps
inline.
- Collect the qualifying follow-ups: the mandatory manual publish step
("paste this release-notes draft into the ticket's Jira release-notes field")
and any implementation-gap signals surfaced during the run.
- Filter them with the reference's §6 qualifying predicate.
- Resolve the write target via the §4 ladder using
jira_key and source;
render + place tasks and verbose notes per §1–§3; dedupe per §5. The task
references the draft file written in Phase 8 rather than duplicating it.
- Preview + confirm per §7 (
approve-all | select | cancel), then write.
ADDITIVE — the follow-ups also remain in the Phase 8 report. This phase NEVER
fails the run, NEVER commits, NEVER makes an external API call, and NEVER writes
into a docs repo or the current working directory.
Phase 10 — Session maintenance & feedback
Terminal phase — runs AFTER the Phase 8 report and the Phase 9 follow-up phase;
NEVER interrupts an earlier phase. release-notes: has no built-in maintenance
agent, so this phase invokes impl-maintenance on the Sonnet detection chain
and then persists the plugin-facing slice of its report as session feedback.
- Invoke
impl-maintenance (task(agent_type: "dev-workflows:impl-maintenance", model: <detection chain — claude-sonnet-4.6, fallback claude-sonnet-4.5/gpt-5.4>)):
"Analyse this session and return a Lessons Learned report.
Session handoff:
- Command run: release-notes:
- What was done: [one-paragraph summary of the release-notes draft produced]
- Key events: [source-truth discrepancies, PARTIAL renders, style-check failures, ambiguous destinations — or 'none']
- Workarounds used: [manual steps not automated by the workflow — or 'none']
- Review verdict: N/A (light gate only, no Opus review)
- Test result: N/A (no tests in release-notes:)
- Project root: [the resolved jira_export_root or the destination directory]"
- Persist plugin feedback (automatic). Project the report's plugin-facing
slice into the specs repo by citing
~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/feedback-emission.md and calling its
emit-auto entry point (§6). Pass the Lessons Learned report,
command: release-notes:, the run's jira_key and source, and
plugin_version (read from
~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/.plugin/plugin.json). emit-auto renders only
the report's Command workflow improvements, New agents / skills, and
plugin Reference docs sections plus the Key observations that
triggered them (§4) — never target-project copilot-instructions.md/hook advice — as
origin: auto entries, dedupes by stable id (§3), resolves the target via
the §2 specs-first ladder, and writes silently.
- Surface the persisted path (or "no plugin-facing signal — nothing
persisted") as this phase's only output.
ADDITIVE — this phase NEVER fails the run, NEVER commits, NEVER makes an external
API call, and NEVER writes into a docs repo or the current working directory.
Invariants (always enforced)
- ALWAYS
emit-block (per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/feedback-emission.md) before escalating a halt caused by a plugin / skill / command / reference gap (a capability the run needed but the plugin lacked) — so a run abandoned at the block still records it. NEVER for a work-quality review BLOCK or an environment / user halt (repo-missing, dirty-tree, jira-not-found, cancellation).
- ZERO external API calls — PR URLs are identifiers only; all resolution is local
git.
jira-reader is read-only.
- The draft contains NO Jira IDs/keys, NO PR links, and NO
{{#internal-note}} block.
- The draft LEADS with a
Change type: line (one of Breaking change / New technology support / Bug fix / not applicable) above a type-aware Summary; when the change deprecates something the Summary carries a deprecation note (end-of-life date required, end-of-support optional). The Change Type label never appears inside the Summary body, and no title or Summary prose names the release version. The pipeline-consumed Summary body is otherwise unchanged.
- NEVER write into a docs repo; the default destination is persistent (never
/tmp).
- ALWAYS use
choices arrays; the last choice is always "Other… (describe)".
- Light gate only — no Opus review, no tests, no branch, no commit.
- ALWAYS end the Phase 8 report with a
### Next step recommendation (per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/next-phase-offer.md) — guidance only, never auto-invoked; the pipeline leaf (adaptive: continue any pending PA/PE phase, else the VI is fully processed).
- ALWAYS end the Phase 8 report with a
### Context hygiene block per ~/.copilot/installed-plugins/ihudak-copilot-plugins/dev-workflows/skills/_shared/session-hygiene.md — prepare-first (resume.md), then a leaf-aware suggestion (done → nothing; pending role → /clear) + /rename <VI-ID>-<slug>-pm; guidance only, never auto-run.