Skip to content

[AI-62] feat: Add filing-jira-tickets skill to bitwarden-atlassian-tools - #189

Merged
SaintPatrck merged 4 commits into
mainfrom
feat/jira-write-tools-skill
Aug 14, 2026
Merged

[AI-62] feat: Add filing-jira-tickets skill to bitwarden-atlassian-tools#189
SaintPatrck merged 4 commits into
mainfrom
feat/jira-write-tools-skill

Conversation

@SaintPatrck

Copy link
Copy Markdown
Contributor

🎟️ Tracking

AI-62

📔 Objective

Adds the filing-jira-tickets skill to bitwarden-atlassian-tools: it reads a project's create screen before drafting, places acceptance criteria in whatever field the project provides (or the description if it has none), previews each ticket in plain language and takes approval before any live write, then wires and verifies dependency links.

@SaintPatrck SaintPatrck added the ai-review Request a Claude code review label Aug 4, 2026
@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude Configuration Validation — PR #189

Scope: plugins/bitwarden-atlassian-tools v2.5.0 → v2.6.0, adding the filing-jira-tickets skill.

Verdict: No critical issues. Structure, versioning, changelog, MCP config, and security all pass. Three content-quality findings in the new skill will produce avoidable tool-call failures at runtime and are worth fixing before merge; the rest is documentation hygiene.

Section Result
1. Plugin validation (plugin-validator) Pass — 0 critical, 1 major, 7 warnings
2. Skill review (skill-reviewer) Needs improvement — 0 critical, 3 major, 4 minor
3. Config & security review Pass — no config files changed by this PR; no secrets

1. Plugin Validation

Validated plugins/bitwarden-atlassian-tools end to end. All structural checks pass.

Verified clean:

  • Version consistency at 2.6.0 across all four required locations: .claude-plugin/marketplace.json:51, plugins/bitwarden-atlassian-tools/.claude-plugin/plugin.json:3, root README.md:12. No agents/ directory exists, so the AGENT.md leg of the version-bump rule does not apply. 2.5.0 → 2.6.0 is the correct MINOR bump for a backward-compatible new skill.
  • CHANGELOG## [2.6.0] - 2026-08-04 with an ### Added section, Keep a Changelog compliant, ordering correct.
  • Manifestname present, kebab-case, matches the directory name and the marketplace name/source; valid semver; author, description, keywords well-formed; no unknown fields. marketplace.json, plugin.json, and .mcp.json all parse.
  • Components — no commands, agents, or hooks (those checks are N/A). 3 skills, all structurally valid with name matching directory and valid YAML.
  • MCP server — 1 server (bitwarden-atlassian), type stdio with a command; no HTTP/WS URLs, so the HTTPS/WSS rule is not engaged. Uses ${CLAUDE_PLUGIN_ROOT} correctly and passes all credentials by env-var reference.
  • Tool-name accuracy — every tool the new skill names (get_create_fields, create_issue, link_issues, get_issue) exists in the registered set.
  • Behavioral claims match the implementationdryRun defaults to true (validation.ts:287); blockerKey/blockedKey are real parameters with internal inward/outward mapping (link-issues.ts:176-186); link_issues genuinely self-verifies (link-issues.ts:73-96); get_issue genuinely has no links section, so SKILL.md:60 is accurate; the 404 wording at SKILL.md:23 matches get-create-fields.ts:118-126 including the "cannot tell which" ambiguity. README.md:176's write-token claim matches src/index.ts:43.
  • File organization — README, CHANGELOG present; no node_modules, .DS_Store, or stray artifacts.

Major — error, fix before merge

plugins/bitwarden-atlassian-tools/skills/filing-jira-tickets/SKILL.md:34 — "Required fields. Supply every one Step 1 reported" is unqualified, but create_issue rejects six keys inside fields: project, issuetype, summary, description, parent, labels (mcp/bitwarden-atlassian-mcp-server/src/utils/validation.ts:227-234, RESERVED_FIELD_KEYS, enforced at :279-281). Those are exactly the fields Jira's createmeta reports as required for most types, and get_create_fields renders every field.required entry (get-create-fields.ts:79,94). A model following Step 2 literally on the most common path therefore hits a validation rejection.

Remediation: add to line 34 that those six keys are owned by the named parameters (project, issueType, summary, descriptionParagraphs, parentKey, labels) and must never be repeated inside fields. The rejection message is self-explanatory so the model can usually recover, but the failed call is avoidable.

Warnings — should fix

  1. SKILL.md:33 — the skill asserts a project-wide fact it cannot know: "that field is plain text, so embedded line breaks render fine." That is verified only for PM's customfield_10192 (src/utils/adf-build.ts:6-8 scopes the claim to PM explicitly). Line 18 of the same file says SM also exposes a criteria field, and its schema type is established nowhere. If any project's criteria field is rich-text/ADF, passing a Gherkin string through fields yields a Jira 400 with no recovery path — Step 3's advice at line 50 ("re-read Step 1") returns the same field id.
    Remediation: get_create_fields already answers this — get-create-fields.ts:57 renders type ${field.schema?.type ?? "unknown"} for every field. Instruct: send a string only when Step 1 reported the criteria field's type as string; if it reports doc/rich text, fall back to the descriptionParagraphs path already described in the same bullet.
  2. SKILL.md:32,45 — the skill says "parent" in prose but never names the actual parameter, parentKey (create-issue.ts:188). Combined with parent being a rejected fields key, a model that guesses parent fails. Name parentKey explicitly.
  3. SKILL.md:58Blocks gets its parameters documented (blockerKey/blockedKey, line 59) but Relates does not; they are firstKey/secondKey (link-issues.ts:187-195). Add: "Relates takes firstKey and secondKey; the relationship is symmetric, so order does not matter."
  4. plugins/bitwarden-atlassian-tools/CHANGELOG.md:8 — dated 2026-08-04; today is 2026-08-14. Bump to the intended release date.
  5. .claude-plugin/marketplace.json:52 and plugins/bitwarden-atlassian-tools/.claude-plugin/plugin.json:4 — both descriptions still read "deep Jira issue research skill" and were not updated for the new filing capability, though this PR touches both files. Discoverability only.
  6. plugins/bitwarden-atlassian-tools/README.md:153-176 — the Skills section documents researching-jira-issues and the new filing-jira-tickets, but assessing-jira-issue-relevance (shipped in 2.4.0) is documented nowhere. Pre-existing gap; this PR is a natural place to close it.
  7. plugins/bitwarden-atlassian-tools/README.md:143-149 (pre-existing, not modified by this PR) — documents the MCP tool prefix as mcp__bitwarden-atlassian__<tool>, which contradicts the prefix both skills actually pre-authorize: mcp__plugin_bitwarden-atlassian-tools_bitwarden-atlassian__ (skills/filing-jira-tickets/SKILL.md:5, skills/assessing-jira-issue-relevance/SKILL.md:4). Anyone copying the README form into an allowed-tools list gets no pre-approval and silent permission prompts. Informational, since the PR does not touch these lines.

2. Skill Review — filing-jira-tickets

Rating: Needs improvement (sound and safe; the triggering path is the load-bearing concern).

62 lines, 976 words, four numbered steps each closed by an explicit Completion criterion. Well within the 500-line limit. Valid YAML frontmatter with name (kebab-case, matches directory) and description present. No broken file references, no hardcoded credentials.

Strengths: every factual claim about MCP tool parameters and behavior verified correct against the server source, including the non-obvious one that get_issue returns no links section. Per-step completion criteria make the workflow auditable. Failure modes are placed at the point of failure (line 23 on 404s, line 50 on field-name errors, line 60 on unverifiable links) rather than collected in an appendix. The 404-ambiguity handling correctly refuses to guess between "bad key" and "no permission" and stops. Writing style is predominantly imperative, as it should be.

Major — should fix

  1. SKILL.md:3-4 — trigger phrases live in when_to_use, not description. Line 3's description is a pure capability statement with no user-facing trigger phrasings. All of them — "file a bug for this", "create a story for this work", "open a spike", "link these two tickets", "wire the blocked-by relationship" — plus the negative boundary against researching-jira-issues, sit in when_to_use on line 4. when_to_use is not documented Claude Code skill frontmatter; it is a house convention used by 18 of 56 SKILL.md files in this repo, so it is not invalid, but it is unverified as load-bearing for skill selection. Notably, both sibling skills in this same plugin put their triggers in description (researching-jira-issues/SKILL.md:3, assessing-jira-issue-relevance/SKILL.md:3), so this skill competes for selection against two better-armed siblings.
    Remediation: fold the triggers and the boundary into description; keep when_to_use if convention requires, but make it redundant rather than load-bearing. Suggested form:

    This skill should be used when the user is ready to create or link Jira work items — "file a bug for this", "create a story for this work", "open a spike", "file these tickets", "link these two tickets", "wire the blocked-by relationship" — or when another skill hands off drafted tickets to create. Reads the target project's create screen first so no field layout is assumed, previews every payload before writing, and verifies dependency links. Not for reading or researching existing issues (use researching-jira-issues) or for editing existing tickets.

  2. SKILL.md:34 — reserved fields keys. Same finding as section 1's major issue; see the remediation there.
  3. SKILL.md:33 — the plain-text assumption. Same finding as section 1 warning 1; branch on the schema.type that get_create_fields already reports.

Minor

  1. SKILL.md:5,31allowed-tools lists Read and get_create_fields only, but line 31 instructs "check one [sibling ticket] if you are unsure", which needs get_issue or search_issues. Since this repo treats allowed-tools as pre-approval rather than restriction (commit 3525ac8, "Drop AskUserQuestion from allowed-tools; it needs no pre-approval"), the effect is an avoidable permission prompt on a read-only lookup, not a failure. Conversely, Read is granted but no step in the skill reads a local file — unearned scope. Add get_issue; drop Read unless there is an intended use.
  2. SKILL.md:5 — omitting create_issue/link_issues from allowed-tools is correct and deliberate under the pre-approval reading: it forces a permission prompt on every live write, reinforcing line 14's approval-first design with a harness-level gate. But that intent is written down nowhere, so the next person to "fix" the list will not find the reason. Document it near line 12: "create_issue and link_issues are deliberately absent from allowed-tools so every live write raises a permission prompt. Do not add them."
  3. Skill directory — no examples/, unlike both sibling skills (researching-jira-issues/examples/, assessing-jira-issue-relevance/examples/). This skill has the most format-sensitive output in the plugin: Gherkin as a single string in a custom field versus one-Gherkin-line-per-descriptionParagraphs-entry, a branch described in prose only. Add examples/filed_ticket_workflow.md with one worked example per branch (a PM ticket with a criteria field, a QA ticket without), each showing the get_create_fields output, the resulting payload, and the user-facing preview.
  4. SKILL.md:33 — a ~110-word bullet carrying two mutually exclusive branches, the densest and most consequential passage in the file. Split into two sub-bullets once the example file exists to carry the payloads. At 976 words the skill has room.
  5. SKILL.md:18 — hardcoded live Jira config ("PM and SM expose an Acceptance criteria field; QA, VULN, and PLT do not. VULN has no Story type. PLT's only creatable type is Platform Initiative") sits immediately before "Never assume a field id...". The tension is intentional, but nobody will update this line when an admin adds a field. Mark it dated and illustrative: "As of 2026-08, for example: ... — but always confirm with get_create_fields."
  6. SKILL.md:23 — a 60-word run-on covering two distinct causes plus a resolution procedure. Consider breaking after "the tool cannot tell which."

Word count: 976, just under the 1,000-3,000 target. This reads as lean-and-complete rather than thin, so the right response is adding examples/ (finding 6), not padding SKILL.md. Progressive disclosure: adequate at this length; no references/ split warranted.


3. Configuration & Security Review

Config files: not applicable to this PR

No CLAUDE.md or .claude/ files changed. Verified per rule 2 rather than assumed: .claude-pr/ exists and holds .claude/CLAUDE.md, .claude/settings.json, and .husky/pre-commit; diff -r against the working-tree copies reports no differences, and git diff origin/main...HEAD lists no path under .claude/, no root CLAUDE.md, no .mcp.json, and no .husky change. The PR's six changed files are all under plugins/, .claude-plugin/, and the root README.md, which rule 2 leaves untouched and which were read from the working tree as normal.

Security scan: pass

  • No committed secrets. Pattern scan across the full PR diff for API keys, tokens, passwords, bearer values, private-key headers, and Atlassian/GitHub/OpenAI token prefixes returned nothing.
  • No hardcoded credentials. All five credentials reach the MCP server by env-var reference in .mcp.json ("${ATLASSIAN_JIRA_WRITE_TOKEN}" form). README credential lines are placeholders (your-jira-write-scoped-token).
  • No settings.local.json tracked in git (git ls-files count: 0).
  • Permission scoping.claude/settings.json is unchanged by this PR, so no permission review applies. Within the new skill, allowed-tools scoping is conservative to a fault: it grants one read-only MCP tool and deliberately withholds both write tools so live creates prompt. That is least-privilege done right; findings 2.4 and 2.5 above are about completeness and documentation, not over-grant.
  • No dangerous command auto-approvals. The new skill declares no Bash(...) permissions.
  • No malformed component definitions. The one new component is a skill with valid frontmatter; no agent, command, or hook definitions were added or changed.

Prompt-engineering quality

Covered in section 2. The one security-adjacent quality note: the skill's safety story (approval before every create, dry-run default, no write tools pre-approved) is coherent and matches the implementation, but rests on an allowed-tools-as-pre-approval assumption that the file never states — see finding 2.5.


Check that could not run

pnpm run lint (prettier + cspell) could not be executed in this environment: pnpm is not installed, and npx is blocked by the repo's devEngines.packageManager pin. Formatting was verified manually instead — all JSON parses, and the root README.md:12 table edit is a same-width in-place change so the table stays prettier-stable. Gherkin is a new-ish term in SKILL.md and does not appear in .cspell.json; confirm the lint.yml CI job passes.


Summary of required actions

Errors (must fix):

  • SKILL.md:34 — document that project, issuetype, summary, description, parent, labels must not be passed inside fields; they have named parameters.

Warnings (should fix, in priority order):

  1. SKILL.md:3 — move trigger phrases and the sibling-skill boundary into description.
  2. SKILL.md:33 — branch on the criteria field's schema.type instead of assuming plain text.
  3. SKILL.md:5 — add get_issue to allowed-tools, drop unused Read, and document why the write tools are deliberately excluded.
  4. SKILL.md:32,45,58 — name parentKey, firstKey, and secondKey explicitly.
  5. Add examples/filed_ticket_workflow.md covering both acceptance-criteria branches.
  6. CHANGELOG.md:8 — update the date; refresh the two manifest descriptions; add assessing-jira-issue-relevance to the plugin README.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Re-reviewed the filing-jira-tickets skill after the latest three commits (link-verification fallback rework, Gherkin criteria split across descriptionParagraphs, create-screen failure wording, and the get_issue/AskUserQuestion removals from allowed-tools). Cross-checked every tool contract the skill relies on against the MCP server source: get_create_fields 404 handling matches the skill's "missing project or missing create permission" wording, link_issues does read the link back and report verification itself, the get_issue tool's rendered output genuinely has no links section, dryRun defaults to true on both write tools, and create_issue merges fields keyed by Jira field id while each descriptionParagraphs entry becomes its own ADF paragraph. The 2.5.0 → 2.6.0 minor bump is applied consistently across marketplace.json, plugin.json, the root README catalog, and the changelog, with the plugin README documenting the new skill; no agents exist in this plugin, so no AGENT.md bump is needed.

No new findings. The two prior threads (allowed-tools scope and the plain-text criteria field) were settled by the maintainer and are not re-raised.

@SaintPatrck
SaintPatrck marked this pull request as ready for review August 4, 2026 20:12
@SaintPatrck
SaintPatrck requested a review from a team as a code owner August 4, 2026 20:12
prograhamming
prograhamming previously approved these changes Aug 12, 2026
@SaintPatrck
SaintPatrck disabled auto-merge August 14, 2026 15:32
Base automatically changed from feat/jira-write-tools-mcp to main August 14, 2026 15:33
Drives the create_issue/link_issues/get_create_fields MCP tools end to
end: reads a project's create screen before drafting so no project's
field layout is assumed, previews each payload in plain language and
takes approval before any live write, then wires and verifies
dependency links.
Stop routing the link-verification fallback through get_issue, whose
output has no links section to check. Split Gherkin criteria across
descriptionParagraphs entries when there is no criteria field, since
a single paragraph has no line-break node and would render as one
run-on line. Reflect that a failed create screen read can mean either
a missing project or missing permission, matching what
get_create_fields actually reports. Drop get_issue from allowed-tools
now that nothing in the skill calls it.
@SaintPatrck
SaintPatrck merged commit 681b977 into main Aug 14, 2026
12 checks passed
@SaintPatrck
SaintPatrck deleted the feat/jira-write-tools-skill branch August 14, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants