feat(tools-triage-flow): ticket triage flow — thin workflow + tools-triage skill - #334
feat(tools-triage-flow): ticket triage flow — thin workflow + tools-triage skill#334sergepr wants to merge 11 commits into
Conversation
…tool-issue creation Adds the triage-flow workflow (intake, requirements elicitation via comments, posted assessment, and linked target-project issue creation on completion), its jira-write skill (write-capable Jira counterpart to data-collection's read-only binding), and the supporting MCP/config wiring: - instructions/r3/core/workflows/triage-flow*.md: orchestrator + 6 phases (intake, elicitation, publish-questions, completion-check, assess, create-tool-issue) - instructions/r3/core/skills/jira-write/: write-capable skill (post comment, transition, reassign, create issue, link issues), content-level gated via dangerous-actions - agents/jira-triage.config.json + agents/jira-mcp-auth-header.sh: deployment config and MCP auth header helper - .mcp.json: registers the jira-service-account MCP server - .gitignore: ignore the local (untracked) jira-triage.secrets.json the auth helper reads Source-only: intentionally excludes the plugins/* regeneration and marketplace/plugin.json version bumps produced by rosettify-plugins for #332/#333 — that build output is regenerated by CI, not carried in source PRs. Also excludes the unrelated rosettify-plugins lightweight-profile test fix that had been bundled into #332. Supersedes #332 and #333.
Rosetta Triage ReviewSummary: Adds This touches Findings:
Caveats:
Suggestions:
Questions:
Automated triage by Rosetta agent |
Per the automated Rosetta prompt-authoring review on #334: - Reword the three direct references to data-collection's internal issue-vendor-binding.md file to intent-level phrasing ("USE SKILL data-collection..."), per pa-hardening's cross-skill isolation rule (no naming another skill's references/ files directly). - Refresh all 6 phase files' subagent_required_model lists from R2-era IDs to the current R3 canonical sets already used by sibling workflows: the opus tier matches requirements-authoring-flow.md's own requirements-engineer/architect phases; the bounded/executor tier matches init-workspace-flow.md's discovery phase. - Trim triage-flow.md's and jira-write/SKILL.md's frontmatter descriptions to fit the schema's token budget (both were ~2x over). - Document in jira-write's POC-SCOPE-OVERRIDE note that the confirmation-gate bypass is skill-wide, not per-operation: transition and reassign inherit the same unattended bypass under confirmation_gate_override even though this build only exercises comment/create/link. Not addressed here (left for human review, per the same automated report): the dangerous-actions step-skipping claim's licensing, and the vendor-neutral-framing leak into jira-write/SKILL.md's core_concepts — both need a judgment call rather than a mechanical fix.
|
Pushed a follow-up commit (211efec) addressing the automated Rosetta triage review:
Left open for review, since they need a judgment call rather than a mechanical fix:
|
…override framing Per the automated Rosetta triage review on #334 (2 remaining findings not addressed in 211efec, left for review since they seemed like judgment calls at the time): - core_concepts and dangerous_actions_gate said "Jira account" / "Jira ticket" despite the file's own stated principle one paragraph earlier ("never hardcode a specific tool name"). Reworded both to "Issue Tracker", matching data-collection's convention (the skill this file is modeled on) and jira-write-vendor-binding.md's own capability-generic prose. The skill's name, directory, and file paths stay Jira-specific on purpose (this build is a Jira-only POC, consistent with jira-triage.config.json / jira-mcp-auth-header.sh / the jira-service-account MCP registration) — only the two body-prose mentions were the actual inconsistency. - The POC-SCOPE-OVERRIDE paragraph claimed "the content-level blast-radius check (steps 1-4) still runs" as if dangerous-actions licenses partial application of its own 5-step process; it doesn't — dangerous-actions defines one linear process, and this is (per a repo search) the only place in instructions/r3 that overrides its step 5 / hitl's "dangerous actions ALWAYS require explicit approval" rule. Reworded so the content-level check is framed as this build's own choice to keep it, not something dangerous-actions sanctions running standalone. The underlying policy question — whether unattended writes to a live Jira ticket are acceptable — is unchanged and still belongs to human review; this only fixes the wording's claim of license it didn't have. No config keys, frontmatter names, intake_contract shape, or INVOKE SUBAGENT/APPLY PHASE syntax touched — prose only, same category as 211efec.
|
Pushed a second follow-up commit (ddf7fad) closing out the remaining 2 findings from the automated Rosetta triage review that 211efec left open for review:
On the underlying design question that wording change doesn't resolve — why unattended writes to a live ticket at all: triage-flow's whole mechanism is the comment round-trip — phase 4 posts Open Questions derived from the elicitation phase's Requirements.md, and the requester waits for the ticket reporter's reply in a comment, not an interactive prompt in this session. Gating every one of those on a human confirmation here would defeat the flow's actual design (a tick-based, asynchronous loop meant to run unattended between CI dispatches), not just add friction to it. The bypass is also narrower than it looks: scoped to comment/create/link only (transition/reassign are unused by this build, explicitly out of scope), every write is manually revertible except All 6 findings from the automated review are now addressed across 211efec + ddf7fad. |
|
Maybe you can intro what and why this flow was implemented?
|
…skill, rename from triage-flow
The flow shipped as 7 files under workflows/: a 216-line triage-flow.md plus
6 phase files. That inverted Rosetta's layering — docs/schemas/workflow.md
requires the workflow file to stay "small and short, skills already define how
things work", yet triage-flow.md carried <intake_contract>,
<write_artifact_contract>, <idempotency> and a 42-line <state_and_resumption>.
The flow owned no skill at all: deleting the shared jira-write skill earlier
inlined its knowledge into the workflow instead of into a flow-owned skill.
It also polluted the command surface. All 6 phase files were emitted flat into
every target's command folder (plugins/core-claude/workflows/,
core-cursor/commands/, core-copilot/commands/) and nested under
core-codex/.agents/skills/triage-flow/phases/. Their user-invocable: false
frontmatter carried through verbatim, but Cursor and Copilot command frontmatter
has no such key, so /triage-flow-intake and its five siblings were reachable
there as user commands.
Changes:
- New skill instructions/r3/core/skills/tools-triage/ (11 files): SKILL.md
(role, cross-stage invariants, stage flow, reference router), README.md per
the <skill_authoring> spec, 6 references/tt-*.md (intake contract ·
elicitation and completion · write artifacts · assessment rubrics ·
tool-issue binding · state and idempotency), 3 assets/tt-* (state skeleton,
assessment skeleton, the three op JSON shapes).
- workflows/tools-triage-flow.md: 216 -> 149 lines. Keeps prerequisites,
<subagent_policy>, 6 phase blocks with their subagent/role/
subagent_required_model/must-be-subagent attributes token-for-token,
<out_of_scope>, and a sequencing-and-evidence checklist. No contract, rubric,
constant, state shape, or op JSON remains in it.
- The 6 triage-flow-*.md phase files are deleted.
- Renamed from triage-flow to tools-triage-flow, skill named tools-triage. The
flow is deployment-specific (hardcoded TOOL project, TSSM: custom fields,
Grid Dynamics tool reasoning) while triage-flow was a generic name in a
shared namespace, and this repo already uses "triage" for PR/issue triage
(.github/workflows/repo-triage.yml). The prefix also stops the skill reading
as a general-purpose shared skill. Cheap now: nothing calls /triage-flow yet.
- Registered tools-triage in docs/definitions/skills.md and tools-triage-flow
in docs/definitions/workflows.md — the flow was never registered there.
- agents/IMPLEMENTATION.md entry rewritten; plugins regenerated (7 targets).
Behavior-neutral apart from the rename: every rule, rubric, constant,
POC-SCOPE-OVERRIDE marker and state field was relocated, not redefined. The
invocation contract { ticket_key, reason?, ticket_details, artifacts_dir? } and
all runtime artifact names are unchanged.
Verification: plans/triage-flow-skill-extraction/ carries a 151-row invariant
inventory built before anything moved, with each row traced to its new home;
108 automated needle checks across the 11 destination files, re-run after the
rename with zero misses. One deviation and one honest miss are recorded there:
the workflow does not deep-link into the skill (the closed alias grammar
forbids it — SKILL FILE never carries a skill name), and POC-SCOPE-OVERRIDE
occurrences dropped 14 -> 8 because per-phase restatements of the same compose
override were consolidated into the contract of record.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The PR carried 116 changed files for what is one workflow. 93 of those were
generated plugins/** output — the same authored set copied into 7 agent targets
— but the authored surface was still larger than it needed to be at 12 files,
and runtime-loaded lines had grown 668 -> 779 (+17%) even though the workflow
itself shrank 216 -> 149.
Folded the 3 assets/ files into the reference that owns each and removed the
assets/ folder, then merged the 6 references into 3 by natural grouping. Each
original file became a named section, so nothing lost its identity:
- tt-intake-and-state.md <intake_contract> · <state_and_idempotency>
· <flow_state_template>
- tt-elicitation-and-assessment.md <elicitation_and_completion>
· <assessment_rubrics> · <assessment_template>
- tt-writes-and-tool-issue.md <write_artifacts>
· <write_artifact_templates> · <tool_issue_binding>
Cross-references that pointed at another file now point at a section in the
same file. SKILL.md's routing list went 6 entries -> 3 and its <templates>
section was dropped, since the shapes live inside the references now; README.md's
routing map and invariants updated to match.
Net: authored 12 -> 6 files, skill lines 826 -> 685 (the merge also removed
~140 lines of per-file headers and duplicated pointers), generated plugins/**
93 -> 42 files.
No behavior change: 90 needle checks re-run against the merged destinations with
zero misses, no dangling in-file section pointers, POC-SCOPE-OVERRIDE occurrences
unchanged at 8, plugins regenerated clean across 7 targets with no stale tt-* or
assets/ artifacts left behind.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…thored files)
Chosen after the previous consolidation: take the authored surface down to its
minimum with a skill still in place. The three reference files are now three
stage sections inside SKILL.md, and references/ is gone.
SKILL.md (646 lines): <role> -> <when_to_use_skill> -> <core_concepts> (five
cross-stage invariants, stage flow, section map) -> <intake_and_state> ->
<elicitation_and_assessment> -> <writes_and_tool_issue> -> <validation_checklist>
-> <pitfalls>. Every former file became a named section and every former nested
section kept its own tag, checklist and pitfalls, so nothing lost its identity.
APPLY SKILL FILE pointers became in-file section pointers ("<write_artifacts>
below", "<state_and_idempotency> above"); no SKILL FILE alias remains, since
there are no sub-files to address. README.md rewritten for the single-file shape:
the routing list is a section map, the tt-* filename invariant is replaced by
"section tags are the routing surface", and the load cost is stated plainly.
Authored surface: 3 files — workflows/tools-triage-flow.md (149),
skills/tools-triage/SKILL.md (646), skills/tools-triage/README.md (44,
maintainer doc, never loaded at runtime). Generated plugins/** drops to 21 files.
The trade, recorded in README.md: activating the skill loads all 646 lines, with
no partial loading. The reversal path is written down — split the stage sections
back into references/ and turn the section map into a routing list — if the file
grows much further.
No behavior change: 90 needle checks against the merged destinations with zero
misses, XML tags balanced in the expected top-level order, no dangling in-file
pointers, POC-SCOPE-OVERRIDE occurrences unchanged at 8, plugins regenerated
clean across 7 targets with no stale references/ or assets/ left behind.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…-writes/ Rosetta instructions describe an Issue Tracker, not a vendor. Eleven "Jira" occurrences remained in the shipped artifacts, in three classes: - Prose (4), reworded to Issue Tracker: "Jira-shaped intent" in SKILL.md and README.md, "reads like a Jira task" in SKILL.md's pitfalls, and phase 4's role="Bounded Jira comment publisher" in the workflow. That role attribute is one of the phase attributes otherwise held token-for-token (inventory row W-39) — changed deliberately here, not by drift. - The artifact directory (6), renamed jira-writes/ -> issue-writes/ across SKILL.md, the workflow, README.md and agents/IMPLEMENTATION.md. Delivered path is <artifacts_dir>/<TICKET-KEY>/issue-writes/<NNN>-<op>.json. Cheap now because the executor that reads these artifacts is unbuilt, cross-repo work; once it exists the path is a contract. Open item that cannot be verified from this repo: if tools-harness-intake already references jira-writes/, it needs the same rename. - One kept deliberately (1): the pitfall naming agents/jira-triage.config.json, a config file deleted earlier in this branch. A historical identifier, not a vendor claim — the warning works because it names the exact file an agent primed on the old design would hunt for. The op names inside the artifacts (add_comment, create_issue, link_issues), target_issue_key, and the state-file fields were already vendor-neutral. The target constants (TOOL, Story, Action item, TSSM: Tool / TSSM: Project) stay — they are the deployment's real values, not vendor terminology. Plugins regenerated across 7 targets; the only "jira" string left in any generated copy is the intentional config-file pitfall. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds
tools-triage-flow, a flow that triages one issue-tracker ticket per invocation for GD Tools' AI SDLC pipeline (TSSM ticket triage): it elicits requirements from the ticket through comment round-trips, posts a triage assessment, then creates and links a Story in the targetTOOLproject. It is delivered as a thin workflow plus one flow-owned skill,tools-triage.This is the Rosetta-side half of a two-repo flow. The trigger (a Jira webhook / CI dispatch) and the PR publishing live in
tools-harness-intakeandgriddynamics/tools-aisdlc-knowledgebase. Wiring those to actually call/tools-triage-flowand to execute the write artifacts it produces is separate, deliberately out-of-scope follow-up work — see Deferred below.Why the flow looks the way it does
It has no live connection to the Issue Tracker, by design. The caller composes whatever it knows about the ticket into free text and passes it in; the flow never reads anything itself. Every write it decides to make is composed into a JSON artifact on disk for a later executor to run — it never sends one. Two consequences reviewers should hold onto:
"pending — see <artifact path>"sentinel. A plausible-looking identifier anywhere in this flow would be a fabrication, and the next invocation would trust it.link_issuesneeds a real target-project key, which does not exist until someone executes the create artifact and that result reaches a later invocation's input. This is handled as an expected resumable state (create composed, link pending), not a failure.It is deployment-specific, not a general-purpose Rosetta flow. The target project key
TOOL, issue typeStory, theTSSM: Tool/TSSM: Projectcustom fields, and the Grid Dynamics tool-impact reasoning are hardcoded constants for this deployment. There is no config file anywhere in this build.Architecture: thin workflow + one flow-owned skill
The flow originally shipped as 7 files under
workflows/— a 216-linetriage-flow.mdplus 6 phase files — which inverted Rosetta's layering.docs/schemas/workflow.mdrequires the workflow file to stay "small and short, skills already define how things work", yet the workflow carried<intake_contract>,<write_artifact_contract>,<idempotency>and a 42-line<state_and_resumption>. The flow owned no skill at all: deleting the sharedjira-writeskill earlier in this branch inlined its knowledge into the workflow rather than into a flow-owned skill.It also polluted the command surface: all 6 phase files were emitted flat into every target's command folder (
plugins/core-claude/workflows/,core-cursor/commands/,core-copilot/commands/) and nested undercore-codex/.agents/skills/triage-flow/phases/. Theiruser-invocable: falsefrontmatter carried through verbatim, but Cursor and Copilot command frontmatter has no such key — so/triage-flow-intakeand its five siblings were reachable there as user commands.Final shape, following the
coding-agents-prompting-flow+coding-agents-prompt-authoringpattern already established in this repo:3 authored files. Single-file skill: no
references/, noassets/. Sections point at each other by tag (`<write_artifacts>` below,`<state_and_idempotency>` above), and each carries its own checklist, pitfalls, and the shape of the file it produces. The trade — recorded inREADME.mdalong with the reversal path — is that activating the skill loads all 646 lines, with no partial loading.The workflow keeps only orchestration: phase sequence, per-phase
subagent/role/subagent_required_model/must-be-subagent, state ownership, scope boundary, and a sequencing-and-evidence checklist. It names the skill and the topic per phase and lets the skill route — it does not deep-link intoreferences/, because the closed alias grammar forbids it (SKILL FILEnever carries a skill name; skill-folder isolation is grammar-enforced).Why one skill rather than two or six. A separate write-mechanics skill would recreate the independently-discoverable shared Jira skill that
jira-write's deletion was meant to end. Six per-phase skills would burn the shared ~1K-token skill-description budget for a single-caller flow.tools-triageis flow-owned:tools-triage-flowis its only caller, and nothing in it is written for reuse elsewhere.Why the
tools-prefix.triage-flowwas a generic name in a shared namespace for a deployment-specific flow, and this repo already uses "triage" for PR/issue triage (.github/workflows/repo-triage.yml). The prefix marks both artifacts as one self-contained unit, stops the skill reading as general-purpose, and leavestriage-flowfree for a real generic triage flow. A skill may not take the flow's own name — Codex and Antigravity convert the workflow into a skill of that exact name, sotools-triage(skill) andtools-triage-flow(flow) are deliberately distinct and coexist in those targets.Input / output
{ ticket_key, reason?, ticket_details, artifacts_dir? }, supplied directly by the caller.ticket_detailsis free text with no fixed schema — no file read, no config read, no live fetch.artifacts_dirdefaults toagents/TEMP.<artifacts_dir>/<TICKET-KEY>/:<TICKET-KEY>-REQUIREMENTS.md,<TICKET-KEY>-TRIAGE-ASSESSMENT.md,<TICKET-KEY>-TRIAGE-FLOW-STATE.md, and oneissue-writes/<NNN>-<op>.jsonper composed write (op ∈ add_comment, create_issue, link_issues). Executing those against the real tracker is a separate, cross-repo step.ticket_detailsversuslast_processed_ticket_details_hash. Deliberately coarser than a comment-ID diff — free text carries no comment IDs — so its worst case is an unnecessary elicitation re-run on a no-op text change, never a missed update.POC-scope overrides — please review these explicitly
Two documented simplifications weaken normal Rosetta gates. Both are flagged in-file with a
POC-SCOPE-OVERRIDE:marker naming exactly what they substitute for, and both are prose, not config — removing the paragraph restores the gate.tt-write-artifacts.md): skipsdangerous-actionsstep 5 andhitl's always-require-approval rule for all three compose operations — unattended at compose time by design, matching the unattended-CI posture. Thedangerous-actionscontent gate itself still runs, once per artifact. The override governs only whether an artifact is written to disk; it says nothing about whether executing it later is safe.create_issueis the one exception it does not cover: because a created issue can never be deleted, that compose must state which duplicate-prevention check ran and what it found, or it is refused.tt-elicitation-and-completion.md): "Open Questions empty" alone flips the requirement units to Approved, standing in forhitl's explicit affirmative-sentence approval. The flow's human gate lives downstream, in the consumer of its artifacts (harness-intake's PR review), not in Jira ticket state.sensitive-dataredaction is not relaxed: intake redactsticket_detailsitself before anything downstream sees it, and evidence is cited by type/count/location only, never the masked value.Deferred (seams only, do not implement here)
Real cron/webhook trigger · sub-hourly cadence · any risk-based gating on the assessment levels · local eligibility re-checking · service-account credential swap · changes to
tools-harness-intake· post-creation management of the created issue · a comment announcing it · executing the composed artifacts and feeding results back. One known residual gap: this flow cannot live-validate custom-field option values or link-type names before composing — that validation belongs to whatever executes the artifacts.Verification
plans/triage-flow-skill-extraction/carries a 151-row invariant inventory built before any content moved, with every normative rule, constant, rubric level, state field, and regression-preventing negation traced to its new home. Its destination-key table maps each row to the file and section it now lives in.triage-flow*orticket-triage*artifacts remain; exactly onetools-triage-flowcommand and onetools-triageskill per target, one INDEX entry each.data-collectionshows zero diff from its pre-branch state; nojira-writereferences remain anywhere.Two things recorded honestly rather than smoothed over, both in
content-map-verification.md§S6: the workflow deviates from the plan by not deep-linking into the skill (the alias grammar forbids it), andPOC-SCOPE-OVERRIDEoccurrences dropped 14 → 8 because per-phase restatements of the same compose override were consolidated into the contract of record — both distinct overrides survive with full framing.Vendor neutrality
The instructions describe an Issue Tracker, not a vendor. Prose mentions of Jira are gone, and the artifact directory is
issue-writes/, notjira-writes/. The op names (add_comment,create_issue,link_issues),target_issue_key, and the state-file fields were already neutral. The target constants (TOOL,Story,Action item,TSSM: Tool/TSSM: Project) stay — those are the deployment's real values, not vendor terminology.One
jirastring is kept on purpose: a pitfall namingagents/jira-triage.config.json, a config file deleted earlier in this branch. It works precisely because it names the exact file an agent primed on the old design would hunt for.tools-harness-intakealready referencesjira-writes/, it needs the same rename. The path was safe to change here only because the executor that reads these artifacts does not exist yet.PR size
44 changed files, of which 30 are generated
plugins/**output:npx rosettify-pluginscopies every authored file into all 7 agent targets (claude, cursor, cursor-standalone, copilot, copilot-standalone, codex, antigravity), and those outputs are tracked in this repo. The authored surface is 3 files underinstructions/r3/core/, plus 8 plan/verification docs and 3 one-line registry entries (docs/definitions/skills.md,workflows.md,agents/IMPLEMENTATION.md).Worth knowing when reading the commit history: the skill was first authored as 11 files (6 references + 3 assets + SKILL.md + README), consolidated to 5, then inlined to 2. The second and third commits are pure file merges with no behavior change — the needle sweep was re-run after each, always zero misses.
Review guide
Start with
content-map-verification.md— each row names a rule and where it lives. Thenskills/tools-triage/SKILL.md: it is the entire behavioral surface now.workflows/tools-triage-flow.mdis orchestration only. Design history for the earlier decoupling work is inplans/triage-jira-decoupling/HANDOFF.md.