[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6X7MGXG2DRHCGAS1RBA5HS9":3,"skill-same:01M6X7MGXG2DRHCGAS1RBA5HS9":117},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":50,"linkOnly":51,"markdownContent":52,"markdownBody":53,"frontMatter":54,"refName":77,"commitSha":78,"skillDirectory":79,"forksCount":80,"repositoryHtmlUrl":81,"repositoryHomepageUrl":82,"ownerHtmlUrl":83,"ownerBlogUrl":82,"ownerDescription":84,"updatedAt":85,"install":86,"resources":98},"01M6X7MGXG2DRHCGAS1RBA5HS9","refine-ticket",null,"Refine a Jira\u002FLinear ticket before planning — 'refine ticket', 'tighten AC on PROJ-123', 'ist das Ticket klar?'; rewritten ticket, risks, persona voices, close-prompt.","event4u-app\u002Fagent-config","event4u-app","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F199339632?v=4","01M6X5TWBNCQCE1VDKT4E9KF7N","event4u.app","01M6X5TWF4HRM266RG2Q5VVH1X",19,"MIT","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49],"refine ticket","ticket","refine","modeling","senior","ac","handler","subprocess","close","professional","scope","critical","jira","ai-agent","engineer","threat","never","command","persona","threat-modeling","product","2026-11-10 10:12:30",false,"---\nmodel_tier: inherit\nname: \"refine-ticket\"\ndescription: \"Refine a Jira\u002FLinear ticket before planning — 'refine ticket', 'tighten AC on PROJ-123', 'ist das Ticket klar?'; rewritten ticket, risks, persona voices, close-prompt.\"\npersonas:\n  - developer\n  - senior-engineer\n  - product-owner\n  - stakeholder\n  - critical-challenger\n  - ai-agent\ndomain: product\nscope:\n  write: []\n  verification_reason: \"execution.handler is internal, so this skill spawns no subprocess — writes happen through the agent's declared allowed_tools. No command can prove a scope the skill never executes.\"\nexecution:\n  type: assisted\n  handler: internal\n  allowed_tools: []\nworkspaces:\n  - product\npacks:\n  - product-basic\nrequires_skills:\n  - validate-feature-fit\n  - threat-modeling\ntrust:\n  level: professional\ninstall:\n  removable: true\n---\n\n# Refine Ticket\n\n> Move a ticket from \"raw idea\" to \"implementation-ready\" in one run.\n> Produces a rewritten ticket, Top-5 risks, and persona voices.\n> Orchestrates `validate-feature-fit` and `threat-modeling` as sub-skills\n> — never duplicates their logic. Output is copy-paste ready; the user\n> decides write-back.\n\n## When to use\n\n- The user hands over a Jira \u002F Linear ticket key, URL, branch name, or\n  pasted ticket text and asks for a sanity check before planning.\n- A ticket looks too vague, too broad, or smells wrong.\n- Before `\u002Ffeature-plan` or `\u002Ffeature-explore` on a ticket-anchored scope.\n- The user says \"tighten the AC\", \"poke holes in this ticket\",\n  \"is this ready to plan?\", \"ist das Ticket klar genug?\",\n  \"verbessere das Ticket\".\n\n## When NOT to use (near-misses)\n\n| Phrasing | Route to |\n|---|---|\n| \"plan this feature\" | `\u002Ffeature-plan` (downstream) |\n| \"estimate this ticket\" | `\u002Festimate-ticket` (sibling, Phase 4) |\n| \"is this a duplicate feature?\" | `validate-feature-fit` (sub-skill) |\n| \"threat-model this change\" | `threat-modeling` (sub-skill) |\n| \"investigate this bug\" | `\u002Fbug-investigate` (bug-focused) |\n\n`\u002Frefine-ticket` **orchestrates** these — it does not replace them.\n\n## Language strategy\n\nThe refined output's prose language is picked once, up front, and\napplied to every section (refined description, risks, persona voices,\norchestration notes, close-prompt). Fallback order — first hit wins:\n\n1. **User-message language.** If the latest user message is in\n   German, the entire output is German; if English, English; etc.\n   This honours the global `language-and-tone` iron law.\n2. **Ticket body language.** When the user's message is ambiguous\n   (one-word `\u002Frefine-ticket PROJ-123`), mirror the language the\n   ticket is written in — detected from the summary + description.\n3. **`.agent-settings.yml` default.** If both are silent or unclear,\n   fall back to the project default in `.agent-settings.yml`\n   (`personal.language` or equivalent). If that is also missing,\n   default to English.\n\nQuoted identifiers (ticket keys, file paths, command names, code\nsnippets) stay in their native form. Only the prose mirrors the\nselected language.\n\n## Inputs (four equivalent paths)\n\nReuses the `jira-ticket` command's loader. Accepts:\n\n1. **Ticket key** — `\u002Frefine-ticket PROJ-123`\n2. **Branch detection** — `\u002Frefine-ticket` with no arg; `agent-config git:convention ticket`\n   on the current branch ([`commit-subject`](..\u002Fgit-workflow\u002Freferences\u002Fcommit-subject.md) § Reading the ticket)\n3. **Pasted text** — `\u002Frefine-ticket` followed by a markdown block\n4. **URL** — `\u002Frefine-ticket https:\u002F\u002Facme.atlassian.net\u002Fbrowse\u002FPROJ-123`\n\nIf none resolve to a ticket, fall back to conversational discovery\n(`feature-explore`-style): ask one focused question, then continue.\n\n## Procedure\n\n### 1. Load ticket\n\nDelegate to `jira-ticket` §1-3:\n- Extract ticket ID (branch \u002F URL \u002F arg).\n- Fetch via Jira API (`GET \u002Fissue\u002F{id}`) — summary, description,\n  issue type, priority, status, comments, linked issues.\n- Scan description + comments for Sentry URLs; pull stacktrace \u002F\n  tags when present.\n\nIf pasted text: skip API, parse markdown, extract title + AC\nbullets + body.\n\n**Auto-fetch parent (Phase F4).** Before detection, check the\nissue type and fold parent context in:\n\n```ts\nimport { issuetype_needs_parent, fold_parent_context } from 'scripts\u002Frefine_ticket_detect.js';\n\nif (issuetype_needs_parent(ticket.issuetype)) {\n    const parentKey = ticket.parent_key;        \u002F\u002F from `fields.parent.key`\n    const parent = fetch_jira_issue(parentKey); \u002F\u002F +1 API call\n    ticketBody = fold_parent_context(ticketBody, parent.body, parentKey);\n}\n```\n\nRules:\n- Applies to `Story` and `Sub-task` (and their Linear \u002F Shortcut\n  equivalents). `Task` \u002F `Bug` \u002F `Epic` skip the auto-fetch unless a\n  `parent` link field is already populated — in that case the agent\n  folds explicitly without the issuetype guard.\n- `fold_parent_context()` is idempotent; folding twice with the same\n  parent does not duplicate the block.\n- When the parent fetch fails (404, permission, network), skip the\n  fold and append a line to orchestration notes:\n  *\"Parent `\u003Ckey>` not reachable — AC may lack upstream context.\"*\n\nParent AC lines surfaced this way must be cited verbatim in the\nrefined output's *Open questions* section so the user sees which\nconstraints come from the parent.\n\n### 2. Inspect ticket + detect orchestration triggers\n\nCheck the loaded ticket for clarity signals before orchestrating:\n- Does the summary match the description body?\n- Are AC bullets concrete (observable \u002F testable) or vague (\"works well\")?\n- Is the scope one feature, or multiple tangled together?\n- Any sentence that references an existing module name, feature flag, or domain concept?\n\n**Cross-source discrepancy scan** (per [`cross-source-consistency`](..\u002F..\u002Frules\u002Fcross-source-consistency.md)): the ticket is rarely a single source. Compare every source against the others and surface any conflict as an *Open question* — never resolve it silently:\n- **text ↔ attachment** — does the ticket text agree with every attached mockup \u002F screenshot \u002F diagram? (Canonical miss: text says \"birthdays **today**\", the mockup shows a birthday from two days ago.) If an attachment cannot be read, say so — do not assume it agrees.\n- **silent-but-needed** — is the spec silent on a clearly-needed behavior (weekend\u002Fholiday shift, empty state, error path, timezone, permissions)? Surface it and ask before it becomes an implementation assumption — an inferred behavior is a scope expansion, not a given.\n- **intra-ticket** — do the AC, description, and comments contradict each other?\n\nFold every discrepancy into the refined output's *Open questions* section (one batched list), never a second prompt. Full taxonomy + scan procedure: [`cross-source-consistency-mechanics`](..\u002F..\u002F..\u002Fdocs\u002Fguidelines\u002Fagent-infra\u002Fcross-source-consistency-mechanics.md).\n\nThen run the deterministic detection helper — do **not** re-derive trigger\nlogic in prose:\n\n```bash\n.\u002Fagent-config refine-ticket:detect \u003Cticket-body-file>\n# or, inside the skill run (scripts\u002Frefine_ticket_detect.ts):\n#   import { detect, load_map } from 'scripts\u002Frefine_ticket_detect.js';\n#   const decision = detect(ticketBody, load_map(), process.cwd());\n```\n\nThe helper consumes [`detection-map.yml`](detection-map.yml) (co-located\nin this skill folder) and returns:\n\n- `validate-feature-fit` — fires when ≥ 2 distinct feature-area keywords\n  appear in the body (see `sub_skills.validate-feature-fit.keywords`).\n- `threat-modeling` — fires on any auth \u002F webhook \u002F upload \u002F queue \u002F\n  secret \u002F tenant \u002F admin \u002F PII \u002F payment keyword, or a `CVE-YYYY-N`\n  regex match.\n- `repo_aware` — on when `.git\u002F`, `agents\u002Fsettings\u002Fcontexts\u002F`, `composer.json`,\n  or `package.json` is present in the cwd; off otherwise.\n- When `repo_aware=True`, `decision.repo_context` is populated by\n  `gather_repo_context()`:\n  - `recent_branches` — up to 20 most recent local branches (naming\n    convention signal).\n  - `recent_commits` — up to 30 most recent commit subjects (active\n    modules + verb conventions).\n  - `context_docs` — every `agents\u002Fsettings\u002Fcontexts\u002F*.md` filename (domain\n    vocabulary).\n- Outside a repo the context is empty — the skill produces the same\n  output shape, minus repo-specific citations (graceful degrade).\n\nUse `repo_context.recent_branches` to anchor the \"Refined ticket\" title\nnaming (e.g. `feat\u002F` vs `fix\u002F` vs `refactor\u002F` prefix), and\n`repo_context.context_docs` to cite domain vocabulary in the Top-5\nrisks instead of inventing terms.\n\nThe match lists and `require_count` thresholds are owned by\n`detection-map.yml` — edit the map, not this skill (DE + EN fixtures,\nrepo-aware + graceful-degrade coverage are regression-locked in this\npackage's own test suite).\n\n### 3. Orchestrate\n\nFor every `SubSkillDecision` with `fired=True`, invoke the named sub-skill\nwith the ticket body as input:\n\n- `validate-feature-fit` → returns duplicate \u002F scope-creep findings\n- `threat-modeling` → returns trust boundaries + abuse cases\n\n**Cite, don't copy** — the output references findings by sub-skill name and\nfile:line where applicable. If a sub-skill reports zero findings, emit\n`fired → clean` in the orchestration section. Skipped sub-skills appear\nas `skipped (no trigger match)` — never silently omitted.\n\nEach fired finding must map to at least one entry in the Top-5 risks\nsection; orchestration that does not influence the risks is waste.\n\n### 4. Apply personas\n\nLoad the persona set from frontmatter (Core-6 default). Each persona\nreviews the ticket through its lens and produces one paragraph:\n\n- **Developer** — implementability, unknowns, test seams\n- **Senior Engineer** — architectural fit, blast radius, hidden deps\n- **Product Owner** — value, user story integrity, AC completeness\n- **Stakeholder** — deadline fit, business impact, comms plan\n- **Critical Challenger** — devil's advocate; what's wrong with this?\n- **AI Agent** — automation hooks, tool boundaries, clarity for agents\n\nOptional: `--personas=+qa` adds the QA persona (edge cases, regression\nrisk, test matrix).\n\nOptional: `--user-type=\u003Cid>` loads one user-type from `user-types\u002F\u003Cid>.md`\nand adds an end-user simulation lens to the persona stack (e.g.\n`--user-type=galabau-field-crew`). User-types compose orthogonally with\npersonas — persona = methodology \u002F role lens; user-type = end-user \u002F field\nlens. v1 is CLI-only (no skill-level default; no frontmatter list). The\nuser-type voice renders as one paragraph in *Persona voices* labelled\n`**User: \u003Clabel>**`, citing Daily Workflow, Vocabulary, Operational\nConstraints, and Ticket Red Flags from the loaded user-type. Contract:\n[`docs\u002Fcontracts\u002Fuser-type-schema.md`](..\u002F..\u002F..\u002Fdocs\u002Fcontracts\u002Fuser-type-schema.md).\n\n### 5. Synthesize + close-prompt\n\nProduce the three-section output (template below). After rendering,\nemit the close-prompt (below). Do **not** write to Jira. Do **not**\nopen a planning doc.\n\n## Output template\n\nFrozen per Q25.\n\n````markdown\n## Refined ticket\n\n**Title:** \u003Crewritten title>\n\n\u003Crewritten description — tightened AC, explicit out-of-scope,\nopen questions surfaced>\n\n## Top-5 risks\n\n1. \u003Crisk> — \u003Cmitigation \u002F deferral>\n2. \u003Crisk> — \u003Cmitigation \u002F deferral>\n3. \u003Crisk> — \u003Cmitigation \u002F deferral>\n4. \u003Crisk> — \u003Cmitigation \u002F deferral>\n5. \u003Crisk> — \u003Cmitigation \u002F deferral>\n\n## Persona voices\n\n- **Developer** — \u003Cone paragraph>\n- **Senior Engineer** — \u003Cone paragraph>\n- **Product Owner** — \u003Cone paragraph>\n- **Stakeholder** — \u003Cone paragraph>\n- **Critical Challenger** — \u003Cone paragraph>\n- **AI Agent** — \u003Cone paragraph>\n- **[qa]** — *(only when `--personas=+qa`)* \u003Cone paragraph>\n- **User: \u003Clabel>** — *(only when `--user-type=\u003Cid>`)* \u003Cone paragraph\n  citing Daily Workflow \u002F Vocabulary \u002F Operational Constraints \u002F\n  Ticket Red Flags from the loaded user-type>\n\n## Orchestration notes\n\n- `validate-feature-fit` — \u003Cfired \u002F skipped; key findings or \"clean\">\n- `threat-modeling` — \u003Cfired \u002F skipped; key findings or \"clean\">\n- Repo-aware — \u003Con \u002F off; contexts loaded>\n````\n\nThe \"Refined ticket\" section is wrapped in a **copyable Markdown box**\nso the user can grab it verbatim.\n\n## Self-review (3-scan checklist)\n\nRun these three scans on the rendered output before the close-prompt. Each is a fast pass; failure blocks emission and forces a fix.\n\n1. **Spec coverage** — every AC bullet and constraint from the original ticket (and every parent-AC line surfaced via `fold_parent_context`) is reflected in the rewritten ticket, the Top-5 risks, or the *Open questions* section. Nothing from the input vanishes silently.\n2. **Placeholder \u002F TODO scan** — no `\u003Cplaceholder>`, `TODO`, `FIXME`, `tbd`, `???`, `XXX` strings remain. The angle-bracket placeholders in the template (`\u003Crewritten title>`, `\u003Crisk>`, `\u003Cone paragraph>`) must be replaced with concrete prose before the close-prompt fires.\n3. **Type \u002F shape consistency** — every module, file, route, or domain term cited in the rewritten ticket and Top-5 risks matches `repo_context.context_docs` and `recent_branches` vocabulary. Invented terms are flagged in *Open questions* or replaced with the project's actual term.\n\nSelf-review is mechanical (gaps, leftovers, naming drift); persona voices and orchestration outputs handle reasoning critique. Both run; neither replaces the other.\n\nSource: adapted from an external reference.\n\n## Close-prompt (mandatory final step)\n\n**Probe write access first (Phase F6).** Before rendering, do a\ncheap upfront check:\n\n```ts\nimport { render_close_prompt } from 'scripts\u002Frefine_ticket_detect.js';\n\nlet write: boolean | null;\ntry {\n    const me = jira_get('\u002Fmyself');                 \u002F\u002F existence → auth works\n    const meta = jira_get(`\u002Fissue\u002F${key}\u002Feditmeta`); \u002F\u002F fields → write access\n    write = Boolean(meta.fields);\n} catch {\n    write = null;                                    \u002F\u002F probe itself failed\n}\n\nconsole.log(render_close_prompt(write));\n```\n\nBehaviour:\n\n| Probe result | Prompt shape |\n|---|---|\n| Write access present (`True`) | Full three-option prompt (comment \u002F replace \u002F nothing) |\n| Read-only (`False`) | Single option: *\"Copy-paste — no write access to this project\"* |\n| Probe failed (`None`) | Full three-option prompt; skill degrades to copy-paste on selection (v1 fallback) |\n\nPer user interaction rules, accept number or free text. `editmeta`\nis cheap and cacheable; cache the result per Jira project key for\nthe session, re-probe on project change.\n\n## Rubric pass (optional, surfacing-only)\n\nAfter refinement, run\n[`judge-artifact-completeness`](..\u002Fjudge-artifact-completeness\u002FSKILL.md)\nwith rubric `ticket-quality-score` to verify DoR readiness — acceptance\ncriteria, test plan, risk, and estimate. Invoke when the user asks for a\nDoR check — not automatically on every refinement.\n\n## Output format\n\n1. **Refined ticket** section with rewritten title + description, wrapped in a copyable markdown block.\n2. **Top-5 risks** as a numbered list, each item paired with a mitigation or deferral.\n3. **Persona voices** — one paragraph per persona from the active set; no skipped personas without explicit reason.\n4. **Orchestration notes** naming every sub-skill that fired or was skipped, with a one-line reason.\n5. **Close-prompt** with exactly three numbered options (comment \u002F replace \u002F nothing); no fourth option in v1.\n\n## Gotcha\n\n- The model tends to invent risks that sound plausible but aren't anchored in the ticket text. Every risk in Top-5 must cite a phrase, AC bullet, or sub-skill finding — no hypotheticals.\n- Persona voices degrade into generic platitudes when the ticket is already tight. If a persona has nothing real to flag, write one sentence stating that — do not pad.\n- Sub-skills (`validate-feature-fit`, `threat-modeling`) cost tokens; orchestrate only when the trigger matrix actually matches, not defensively on every run.\n- Branch-detection takes the first `ticket` that `git:convention ticket` prints; chained keys (e.g. `feat\u002FPROJ-1-and-PROJ-2`) pick the first and note the rest.\n\n## Do NOT\n\n- Do NOT write back to Jira in v1 — output is copyable markdown; write-back is user-gated via the close-prompt.\n- Do NOT chain into `\u002Festimate-ticket` or `\u002Ffeature-plan` automatically — separate invocations by design (Q5 decision).\n- Do NOT duplicate logic from `validate-feature-fit` or `threat-modeling` — orchestrate by reference, cite findings, don't re-derive them.\n- Do NOT skip the close-prompt, even when the ticket looks fine and the user seems eager to move on — the prompt is the contract.\n- Do NOT emit persona voices outside the active set; if the user passed `--personas=+qa`, add QA, otherwise do not.\n- Do NOT emit a user-type voice unless `--user-type=\u003Cid>` was passed; loading a user-type proactively (e.g. \"this ticket smells like field-crew\") is forbidden — the axis is CLI-only in v1.\n\n## See also\n\n- [`jira-ticket`](..\u002F..\u002Fcommands\u002Fjira-ticket.md) — ticket loader\n- [`validate-feature-fit`](..\u002Fvalidate-feature-fit\u002FSKILL.md) — orchestrated sub-skill\n- [`threat-modeling`](..\u002Fthreat-modeling\u002FSKILL.md) — orchestrated sub-skill\n- [`feature-explore`](..\u002F..\u002Fcommands\u002Ffeature\u002Fexplore.md) — upstream idea capture; hints at `\u002Frefine-ticket` when input looks like a ticket\n- [`feature-plan`](..\u002F..\u002Fcommands\u002Ffeature\u002Fplan.md) — downstream planning\n- [`adversarial-review`](..\u002Fadversarial-review\u002FSKILL.md) — same `critical-challenger` persona, different stage (post-plan)\n- [`artifact-drafting-protocol`](..\u002F..\u002Frules\u002Fartifact-drafting-protocol.md) — this skill was drafted under it\n","# Refine Ticket\n\n> Move a ticket from \"raw idea\" to \"implementation-ready\" in one run.\n> Produces a rewritten ticket, Top-5 risks, and persona voices.\n> Orchestrates `validate-feature-fit` and `threat-modeling` as sub-skills\n> — never duplicates their logic. Output is copy-paste ready; the user\n> decides write-back.\n\n## When to use\n\n- The user hands over a Jira \u002F Linear ticket key, URL, branch name, or\n  pasted ticket text and asks for a sanity check before planning.\n- A ticket looks too vague, too broad, or smells wrong.\n- Before `\u002Ffeature-plan` or `\u002Ffeature-explore` on a ticket-anchored scope.\n- The user says \"tighten the AC\", \"poke holes in this ticket\",\n  \"is this ready to plan?\", \"ist das Ticket klar genug?\",\n  \"verbessere das Ticket\".\n\n## When NOT to use (near-misses)\n\n| Phrasing | Route to |\n|---|---|\n| \"plan this feature\" | `\u002Ffeature-plan` (downstream) |\n| \"estimate this ticket\" | `\u002Festimate-ticket` (sibling, Phase 4) |\n| \"is this a duplicate feature?\" | `validate-feature-fit` (sub-skill) |\n| \"threat-model this change\" | `threat-modeling` (sub-skill) |\n| \"investigate this bug\" | `\u002Fbug-investigate` (bug-focused) |\n\n`\u002Frefine-ticket` **orchestrates** these — it does not replace them.\n\n## Language strategy\n\nThe refined output's prose language is picked once, up front, and\napplied to every section (refined description, risks, persona voices,\norchestration notes, close-prompt). Fallback order — first hit wins:\n\n1. **User-message language.** If the latest user message is in\n   German, the entire output is German; if English, English; etc.\n   This honours the global `language-and-tone` iron law.\n2. **Ticket body language.** When the user's message is ambiguous\n   (one-word `\u002Frefine-ticket PROJ-123`), mirror the language the\n   ticket is written in — detected from the summary + description.\n3. **`.agent-settings.yml` default.** If both are silent or unclear,\n   fall back to the project default in `.agent-settings.yml`\n   (`personal.language` or equivalent). If that is also missing,\n   default to English.\n\nQuoted identifiers (ticket keys, file paths, command names, code\nsnippets) stay in their native form. Only the prose mirrors the\nselected language.\n\n## Inputs (four equivalent paths)\n\nReuses the `jira-ticket` command's loader. Accepts:\n\n1. **Ticket key** — `\u002Frefine-ticket PROJ-123`\n2. **Branch detection** — `\u002Frefine-ticket` with no arg; `agent-config git:convention ticket`\n   on the current branch ([`commit-subject`](..\u002Fgit-workflow\u002Freferences\u002Fcommit-subject.md) § Reading the ticket)\n3. **Pasted text** — `\u002Frefine-ticket` followed by a markdown block\n4. **URL** — `\u002Frefine-ticket https:\u002F\u002Facme.atlassian.net\u002Fbrowse\u002FPROJ-123`\n\nIf none resolve to a ticket, fall back to conversational discovery\n(`feature-explore`-style): ask one focused question, then continue.\n\n## Procedure\n\n### 1. Load ticket\n\nDelegate to `jira-ticket` §1-3:\n- Extract ticket ID (branch \u002F URL \u002F arg).\n- Fetch via Jira API (`GET \u002Fissue\u002F{id}`) — summary, description,\n  issue type, priority, status, comments, linked issues.\n- Scan description + comments for Sentry URLs; pull stacktrace \u002F\n  tags when present.\n\nIf pasted text: skip API, parse markdown, extract title + AC\nbullets + body.\n\n**Auto-fetch parent (Phase F4).** Before detection, check the\nissue type and fold parent context in:\n\n```ts\nimport { issuetype_needs_parent, fold_parent_context } from 'scripts\u002Frefine_ticket_detect.js';\n\nif (issuetype_needs_parent(ticket.issuetype)) {\n    const parentKey = ticket.parent_key;        \u002F\u002F from `fields.parent.key`\n    const parent = fetch_jira_issue(parentKey); \u002F\u002F +1 API call\n    ticketBody = fold_parent_context(ticketBody, parent.body, parentKey);\n}\n```\n\nRules:\n- Applies to `Story` and `Sub-task` (and their Linear \u002F Shortcut\n  equivalents). `Task` \u002F `Bug` \u002F `Epic` skip the auto-fetch unless a\n  `parent` link field is already populated — in that case the agent\n  folds explicitly without the issuetype guard.\n- `fold_parent_context()` is idempotent; folding twice with the same\n  parent does not duplicate the block.\n- When the parent fetch fails (404, permission, network), skip the\n  fold and append a line to orchestration notes:\n  *\"Parent `\u003Ckey>` not reachable — AC may lack upstream context.\"*\n\nParent AC lines surfaced this way must be cited verbatim in the\nrefined output's *Open questions* section so the user sees which\nconstraints come from the parent.\n\n### 2. Inspect ticket + detect orchestration triggers\n\nCheck the loaded ticket for clarity signals before orchestrating:\n- Does the summary match the description body?\n- Are AC bullets concrete (observable \u002F testable) or vague (\"works well\")?\n- Is the scope one feature, or multiple tangled together?\n- Any sentence that references an existing module name, feature flag, or domain concept?\n\n**Cross-source discrepancy scan** (per [`cross-source-consistency`](..\u002F..\u002Frules\u002Fcross-source-consistency.md)): the ticket is rarely a single source. Compare every source against the others and surface any conflict as an *Open question* — never resolve it silently:\n- **text ↔ attachment** — does the ticket text agree with every attached mockup \u002F screenshot \u002F diagram? (Canonical miss: text says \"birthdays **today**\", the mockup shows a birthday from two days ago.) If an attachment cannot be read, say so — do not assume it agrees.\n- **silent-but-needed** — is the spec silent on a clearly-needed behavior (weekend\u002Fholiday shift, empty state, error path, timezone, permissions)? Surface it and ask before it becomes an implementation assumption — an inferred behavior is a scope expansion, not a given.\n- **intra-ticket** — do the AC, description, and comments contradict each other?\n\nFold every discrepancy into the refined output's *Open questions* section (one batched list), never a second prompt. Full taxonomy + scan procedure: [`cross-source-consistency-mechanics`](..\u002F..\u002F..\u002Fdocs\u002Fguidelines\u002Fagent-infra\u002Fcross-source-consistency-mechanics.md).\n\nThen run the deterministic detection helper — do **not** re-derive trigger\nlogic in prose:\n\n```bash\n.\u002Fagent-config refine-ticket:detect \u003Cticket-body-file>\n# or, inside the skill run (scripts\u002Frefine_ticket_detect.ts):\n#   import { detect, load_map } from 'scripts\u002Frefine_ticket_detect.js';\n#   const decision = detect(ticketBody, load_map(), process.cwd());\n```\n\nThe helper consumes [`detection-map.yml`](detection-map.yml) (co-located\nin this skill folder) and returns:\n\n- `validate-feature-fit` — fires when ≥ 2 distinct feature-area keywords\n  appear in the body (see `sub_skills.validate-feature-fit.keywords`).\n- `threat-modeling` — fires on any auth \u002F webhook \u002F upload \u002F queue \u002F\n  secret \u002F tenant \u002F admin \u002F PII \u002F payment keyword, or a `CVE-YYYY-N`\n  regex match.\n- `repo_aware` — on when `.git\u002F`, `agents\u002Fsettings\u002Fcontexts\u002F`, `composer.json`,\n  or `package.json` is present in the cwd; off otherwise.\n- When `repo_aware=True`, `decision.repo_context` is populated by\n  `gather_repo_context()`:\n  - `recent_branches` — up to 20 most recent local branches (naming\n    convention signal).\n  - `recent_commits` — up to 30 most recent commit subjects (active\n    modules + verb conventions).\n  - `context_docs` — every `agents\u002Fsettings\u002Fcontexts\u002F*.md` filename (domain\n    vocabulary).\n- Outside a repo the context is empty — the skill produces the same\n  output shape, minus repo-specific citations (graceful degrade).\n\nUse `repo_context.recent_branches` to anchor the \"Refined ticket\" title\nnaming (e.g. `feat\u002F` vs `fix\u002F` vs `refactor\u002F` prefix), and\n`repo_context.context_docs` to cite domain vocabulary in the Top-5\nrisks instead of inventing terms.\n\nThe match lists and `require_count` thresholds are owned by\n`detection-map.yml` — edit the map, not this skill (DE + EN fixtures,\nrepo-aware + graceful-degrade coverage are regression-locked in this\npackage's own test suite).\n\n### 3. Orchestrate\n\nFor every `SubSkillDecision` with `fired=True`, invoke the named sub-skill\nwith the ticket body as input:\n\n- `validate-feature-fit` → returns duplicate \u002F scope-creep findings\n- `threat-modeling` → returns trust boundaries + abuse cases\n\n**Cite, don't copy** — the output references findings by sub-skill name and\nfile:line where applicable. If a sub-skill reports zero findings, emit\n`fired → clean` in the orchestration section. Skipped sub-skills appear\nas `skipped (no trigger match)` — never silently omitted.\n\nEach fired finding must map to at least one entry in the Top-5 risks\nsection; orchestration that does not influence the risks is waste.\n\n### 4. Apply personas\n\nLoad the persona set from frontmatter (Core-6 default). Each persona\nreviews the ticket through its lens and produces one paragraph:\n\n- **Developer** — implementability, unknowns, test seams\n- **Senior Engineer** — architectural fit, blast radius, hidden deps\n- **Product Owner** — value, user story integrity, AC completeness\n- **Stakeholder** — deadline fit, business impact, comms plan\n- **Critical Challenger** — devil's advocate; what's wrong with this?\n- **AI Agent** — automation hooks, tool boundaries, clarity for agents\n\nOptional: `--personas=+qa` adds the QA persona (edge cases, regression\nrisk, test matrix).\n\nOptional: `--user-type=\u003Cid>` loads one user-type from `user-types\u002F\u003Cid>.md`\nand adds an end-user simulation lens to the persona stack (e.g.\n`--user-type=galabau-field-crew`). User-types compose orthogonally with\npersonas — persona = methodology \u002F role lens; user-type = end-user \u002F field\nlens. v1 is CLI-only (no skill-level default; no frontmatter list). The\nuser-type voice renders as one paragraph in *Persona voices* labelled\n`**User: \u003Clabel>**`, citing Daily Workflow, Vocabulary, Operational\nConstraints, and Ticket Red Flags from the loaded user-type. Contract:\n[`docs\u002Fcontracts\u002Fuser-type-schema.md`](..\u002F..\u002F..\u002Fdocs\u002Fcontracts\u002Fuser-type-schema.md).\n\n### 5. Synthesize + close-prompt\n\nProduce the three-section output (template below). After rendering,\nemit the close-prompt (below). Do **not** write to Jira. Do **not**\nopen a planning doc.\n\n## Output template\n\nFrozen per Q25.\n\n````markdown\n## Refined ticket\n\n**Title:** \u003Crewritten title>\n\n\u003Crewritten description — tightened AC, explicit out-of-scope,\nopen questions surfaced>\n\n## Top-5 risks\n\n1. \u003Crisk> — \u003Cmitigation \u002F deferral>\n2. \u003Crisk> — \u003Cmitigation \u002F deferral>\n3. \u003Crisk> — \u003Cmitigation \u002F deferral>\n4. \u003Crisk> — \u003Cmitigation \u002F deferral>\n5. \u003Crisk> — \u003Cmitigation \u002F deferral>\n\n## Persona voices\n\n- **Developer** — \u003Cone paragraph>\n- **Senior Engineer** — \u003Cone paragraph>\n- **Product Owner** — \u003Cone paragraph>\n- **Stakeholder** — \u003Cone paragraph>\n- **Critical Challenger** — \u003Cone paragraph>\n- **AI Agent** — \u003Cone paragraph>\n- **[qa]** — *(only when `--personas=+qa`)* \u003Cone paragraph>\n- **User: \u003Clabel>** — *(only when `--user-type=\u003Cid>`)* \u003Cone paragraph\n  citing Daily Workflow \u002F Vocabulary \u002F Operational Constraints \u002F\n  Ticket Red Flags from the loaded user-type>\n\n## Orchestration notes\n\n- `validate-feature-fit` — \u003Cfired \u002F skipped; key findings or \"clean\">\n- `threat-modeling` — \u003Cfired \u002F skipped; key findings or \"clean\">\n- Repo-aware — \u003Con \u002F off; contexts loaded>\n````\n\nThe \"Refined ticket\" section is wrapped in a **copyable Markdown box**\nso the user can grab it verbatim.\n\n## Self-review (3-scan checklist)\n\nRun these three scans on the rendered output before the close-prompt. Each is a fast pass; failure blocks emission and forces a fix.\n\n1. **Spec coverage** — every AC bullet and constraint from the original ticket (and every parent-AC line surfaced via `fold_parent_context`) is reflected in the rewritten ticket, the Top-5 risks, or the *Open questions* section. Nothing from the input vanishes silently.\n2. **Placeholder \u002F TODO scan** — no `\u003Cplaceholder>`, `TODO`, `FIXME`, `tbd`, `???`, `XXX` strings remain. The angle-bracket placeholders in the template (`\u003Crewritten title>`, `\u003Crisk>`, `\u003Cone paragraph>`) must be replaced with concrete prose before the close-prompt fires.\n3. **Type \u002F shape consistency** — every module, file, route, or domain term cited in the rewritten ticket and Top-5 risks matches `repo_context.context_docs` and `recent_branches` vocabulary. Invented terms are flagged in *Open questions* or replaced with the project's actual term.\n\nSelf-review is mechanical (gaps, leftovers, naming drift); persona voices and orchestration outputs handle reasoning critique. Both run; neither replaces the other.\n\nSource: adapted from an external reference.\n\n## Close-prompt (mandatory final step)\n\n**Probe write access first (Phase F6).** Before rendering, do a\ncheap upfront check:\n\n```ts\nimport { render_close_prompt } from 'scripts\u002Frefine_ticket_detect.js';\n\nlet write: boolean | null;\ntry {\n    const me = jira_get('\u002Fmyself');                 \u002F\u002F existence → auth works\n    const meta = jira_get(`\u002Fissue\u002F${key}\u002Feditmeta`); \u002F\u002F fields → write access\n    write = Boolean(meta.fields);\n} catch {\n    write = null;                                    \u002F\u002F probe itself failed\n}\n\nconsole.log(render_close_prompt(write));\n```\n\nBehaviour:\n\n| Probe result | Prompt shape |\n|---|---|\n| Write access present (`True`) | Full three-option prompt (comment \u002F replace \u002F nothing) |\n| Read-only (`False`) | Single option: *\"Copy-paste — no write access to this project\"* |\n| Probe failed (`None`) | Full three-option prompt; skill degrades to copy-paste on selection (v1 fallback) |\n\nPer user interaction rules, accept number or free text. `editmeta`\nis cheap and cacheable; cache the result per Jira project key for\nthe session, re-probe on project change.\n\n## Rubric pass (optional, surfacing-only)\n\nAfter refinement, run\n[`judge-artifact-completeness`](..\u002Fjudge-artifact-completeness\u002FSKILL.md)\nwith rubric `ticket-quality-score` to verify DoR readiness — acceptance\ncriteria, test plan, risk, and estimate. Invoke when the user asks for a\nDoR check — not automatically on every refinement.\n\n## Output format\n\n1. **Refined ticket** section with rewritten title + description, wrapped in a copyable markdown block.\n2. **Top-5 risks** as a numbered list, each item paired with a mitigation or deferral.\n3. **Persona voices** — one paragraph per persona from the active set; no skipped personas without explicit reason.\n4. **Orchestration notes** naming every sub-skill that fired or was skipped, with a one-line reason.\n5. **Close-prompt** with exactly three numbered options (comment \u002F replace \u002F nothing); no fourth option in v1.\n\n## Gotcha\n\n- The model tends to invent risks that sound plausible but aren't anchored in the ticket text. Every risk in Top-5 must cite a phrase, AC bullet, or sub-skill finding — no hypotheticals.\n- Persona voices degrade into generic platitudes when the ticket is already tight. If a persona has nothing real to flag, write one sentence stating that — do not pad.\n- Sub-skills (`validate-feature-fit`, `threat-modeling`) cost tokens; orchestrate only when the trigger matrix actually matches, not defensively on every run.\n- Branch-detection takes the first `ticket` that `git:convention ticket` prints; chained keys (e.g. `feat\u002FPROJ-1-and-PROJ-2`) pick the first and note the rest.\n\n## Do NOT\n\n- Do NOT write back to Jira in v1 — output is copyable markdown; write-back is user-gated via the close-prompt.\n- Do NOT chain into `\u002Festimate-ticket` or `\u002Ffeature-plan` automatically — separate invocations by design (Q5 decision).\n- Do NOT duplicate logic from `validate-feature-fit` or `threat-modeling` — orchestrate by reference, cite findings, don't re-derive them.\n- Do NOT skip the close-prompt, even when the ticket looks fine and the user seems eager to move on — the prompt is the contract.\n- Do NOT emit persona voices outside the active set; if the user passed `--personas=+qa`, add QA, otherwise do not.\n- Do NOT emit a user-type voice unless `--user-type=\u003Cid>` was passed; loading a user-type proactively (e.g. \"this ticket smells like field-crew\") is forbidden — the axis is CLI-only in v1.\n\n## See also\n\n- [`jira-ticket`](..\u002F..\u002Fcommands\u002Fjira-ticket.md) — ticket loader\n- [`validate-feature-fit`](..\u002Fvalidate-feature-fit\u002FSKILL.md) — orchestrated sub-skill\n- [`threat-modeling`](..\u002Fthreat-modeling\u002FSKILL.md) — orchestrated sub-skill\n- [`feature-explore`](..\u002F..\u002Fcommands\u002Ffeature\u002Fexplore.md) — upstream idea capture; hints at `\u002Frefine-ticket` when input looks like a ticket\n- [`feature-plan`](..\u002F..\u002Fcommands\u002Ffeature\u002Fplan.md) — downstream planning\n- [`adversarial-review`](..\u002Fadversarial-review\u002FSKILL.md) — same `critical-challenger` persona, different stage (post-plan)\n- [`artifact-drafting-protocol`](..\u002F..\u002Frules\u002Fartifact-drafting-protocol.md) — this skill was drafted under it\n",{"name":5,"packs":55,"scope":57,"trust":60,"domain":49,"install":61,"personas":63,"execution":69,"model_tier":73,"workspaces":74,"description":7,"requires_skills":75},[56],"product-basic",{"write":58,"verification_reason":59},[],"execution.handler is internal, so this skill spawns no subprocess — writes happen through the agent's declared allowed_tools. No command can prove a scope the skill never executes.",{"level":38},{"removable":62},true,[64,65,66,67,68,42],"developer","senior-engineer","product-owner","stakeholder","critical-challenger",{"type":70,"handler":71,"allowed_tools":72},"assisted","internal",[],"inherit",[49],[76,48],"validate-feature-fit","main","12bd765ce1d800501d45dfb8232102793af01290","src\u002Fskills\u002Frefine-ticket",1,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config","https:\u002F\u002Fevent4u.app","https:\u002F\u002Fgithub.com\u002Fevent4u-app","Your events in your hand","2026-11-11 22:25:41",{"source":8,"skillName":5,"commands":87,"prompt":97,"zipAvailable":62},[88,91,94],{"tool":89,"command":90},"npx","npx skills add event4u-app\u002Fagent-config --skill refine-ticket",{"tool":92,"command":93},"bunx","bunx skills add event4u-app\u002Fagent-config --skill refine-ticket",{"tool":95,"command":96},"pnpm","pnpm dlx skills add event4u-app\u002Fagent-config --skill refine-ticket","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002FSKILL.md",[99,105,109,113],{"path":100,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":103,"sourceHtmlUrl":104},"detection-map.yml","REFERENCE","参考文档",3694,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002Fdetection-map.yml",{"path":106,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":107,"sourceHtmlUrl":108},"evals\u002Fevals.json",738,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002Fevals\u002Fevals.json",{"path":110,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":111,"sourceHtmlUrl":112},"evals\u002Foutput-schema.yml",536,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002Fevals\u002Foutput-schema.yml",{"path":114,"resourceType":101,"resourceTypeDesc":102,"sizeBytes":115,"sourceHtmlUrl":116},"evals\u002Ftriggers.json",1376,"https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Fsrc\u002Fskills\u002Frefine-ticket\u002Fevals\u002Ftriggers.json",[118,132,144,156,168,178],{"skillNo":119,"name":120,"nameZh":6,"description":121,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":125,"publishedAt":50},"01M6X84PK96XBPENXH66JCTSD1","unknown-key-fixture","Declares a key the schema does not know.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Funknown-key\u002FSKILL.md",[124],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[126,127,128,129,130,131],"unknown key fixture","Unknown key","fixture","unknown","schema","package",{"skillNo":133,"name":134,"nameZh":6,"description":135,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":136,"categories":137,"keywords":139,"publishedAt":50},"01M6X84HW7NAHZ7GZMQ9RXK1XJ","portable-fixture","Declares only semantics the MCP-lite carrier transports whole.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Fportable\u002FSKILL.md",[138],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[128,140,141,43,142,131,143],"portable","portable fixture","only","MCP",{"skillNo":145,"name":146,"nameZh":6,"description":147,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":148,"categories":149,"keywords":151,"publishedAt":50},"01M6X84F29FE0RGGZ1ZTFGZTX2","non-portable-fixture","Declares a runtime semantic the carrier drops.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Fscripts\u002Ffixtures\u002Fbody-portable\u002Fnon-portable\u002FSKILL.md",[150],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[141,152,140,128,153,154,155,131],"non portable fixture","semantic","high","runtime",{"skillNo":157,"name":158,"nameZh":6,"description":159,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":160,"categories":161,"keywords":163,"publishedAt":50},"01M6X848F706PT9MDCX75JKJ6B","candidate-zero-width","A candidate whose prose carries an invisible joiner.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fzero-width-injection\u002FSKILL.md",[162],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[164,165,166,167],"candidate zero width","candidate","ZeRO","prose",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":175,"publishedAt":50},"01M6X841SSC2T31VDF41SA6DG1","candidate-disclosure-suppression","A candidate whose prose tells the agent to withhold from the user.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fdisclosure-suppression\u002FSKILL.md",[174],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[176,165,167,177],"candidate disclosure suppression","user",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":185,"publishedAt":50},"01M6X83TFS5AGPBPVTQNWP0BB3","candidate-dangerous-frontmatter","A candidate claiming an unscoped tool grant and a permission bypass.","https:\u002F\u002Fgithub.com\u002Fevent4u-app\u002Fagent-config\u002Fblob\u002Fmain\u002Ftests\u002Ffixtures\u002Fskill-scout-candidates\u002Fdangerous-frontmatter\u002FSKILL.md",[184],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[186,165,187,188,189,190],"candidate dangerous frontmatter","frontmatter","shell","permission","tool"]