-
Notifications
You must be signed in to change notification settings - Fork 479
Description
Description
The project previously shipped a basic create-issue Claude Code skill at .claude/skills/create-issue/ (added in #34465). This was a 232-line, CREATE-only workflow with significant gaps:
- No team caching — always prompted for team assignment
- Feature label defaulted to
dotCMS : Content Managementwhen no match was found - Did not set the native GitHub Issue Type after creation
- Did not set Project testing assign #7 Technology field via GraphQL
- Did not support sub-issues, relationships, or any query/update operations
Over multiple sessions the skill has been substantially reworked into a multi-mode AI-agent-native skill called dotcms-github-issues. The new skill (589 lines + 3 reference files) currently lives at the user level (~/.claude/skills/dotcms-github-issues/) for testing. This task is to move it into the project repository and ship the accompanying slash command stubs.
What changed vs the original skill
| Capability | Old create-issue (232 lines) |
New dotcms-github-issues (589 lines) |
|---|---|---|
| Modes | CREATE only | CREATE · UPDATE · QUERY · FIND |
| Team assignment | Always prompted | Cached default; asks only when no cache |
| Native GitHub Issue Type | Not set | Set via REST PATCH immediately after creation |
| Project #7 Technology field | Not set | Set via GraphQL mutation |
| Sub-issues / relationships | Not supported | Sub-issue REST endpoint + cross-reference comments |
| Feature label fallback | Defaulted to dotCMS : Content Management |
Asks when ambiguous; no incorrect default applied |
| Sprint / iteration queries | Not supported | Full per-team sprint awareness — current and historical (see below) |
| Reference files | feature-labels.md only |
feature-labels.md · github-apis.md · project-fields.md |
| Team selection UX | Single flat prompt | Cascading Stage 1 / Stage 2 + free-text fallback |
Type : label |
Not applied | Derived from template + description keywords |
UPDATE mode |
— | Fetches state, shows validation table, applies changes |
QUERY mode |
— | Returns title, labels, native type, project fields, sub-issues |
FIND mode |
— | Sprint/backlog queries per team with velocity summary |
Sprint and iteration awareness (FIND mode)
The FIND mode can answer "what is the team working on this sprint?" and "what did the team complete last sprint?" for any sprint-based team. This required solving several non-obvious problems.
Per-team iteration fields
Each sprint team has a dedicated ProjectV2IterationField ID in Project #7 — separate from the shared Status and Technology fields. These IDs are catalogued in references/project-fields.md:
| Team | Sprint field ID |
|---|---|
| Falcon | PVTIF_lADOAA9Wz84AKDq_zgcwTUQ |
| Maintenance | PVTIF_lADOAA9Wz84AKDq_zgIGutk |
| Scout | PVTIF_lADOAA9Wz84AKDq_zgdo3T0 |
| Platform | PVTIF_lADOAA9Wz84AKDq_zgj83DM |
Kanban-only teams (Enablement, Modernization, UX) have no iteration field. The skill detects this and falls back to Status-field queries automatically.
Querying current and previous sprints
To find the active sprint title, the skill queries the team's iteration field for its iterations (active) list. To find the previous sprint, it queries completedIterations on the same field and selects the most recent entry by startDate. Both lookups use GraphQL against Project #7 directly — no hardcoded sprint names.
Once the sprint title is known, issues are filtered by matching the iterationValue.title field value on each issue's project item.
Critical pagination fix
The naive approach of querying node(id: projectId).items(first: 100) returns the oldest 100 project items — for a team like Scout with 1,600+ issues, recently closed sprint items are completely absent. The same problem affects gh issue list: it returns the oldest 100 by default regardless of label filter.
The fix uses repository.issues with orderBy: {field: UPDATED_AT, direction: DESC} and states: [OPEN, CLOSED], ensuring recently-updated issues (including Done items closed during the sprint) appear at the top of the result set within the 100-item cursor window. This was validated against Scout Sprint 4 (Feb 11–24, 2026) which had 5 Done items — all 5 were returned correctly after the fix.
jq reliability
Two silent failure modes were discovered and documented:
- The
!=operator is shell-expanded in bash heredoc jq expressions; use chainedselect()calls instead - Reusing an
--argname (e.g.--arg sprint) as an internalas $sprintbinding causes a silent variable collision; use a distinct internal name (e.g.as $iterTitle)
Null-safety is also required: when a project item exists but has no iteration value, .fieldValues.nodes[] must be guarded with // [] to avoid a runtime error.
Slash commands
Four command stubs in .claude/commands/ route to the correct mode — already added in this session:
| Command | Mode |
|---|---|
/create-issue |
CREATE |
/update-issue |
UPDATE |
/query-issue |
QUERY |
/find-issues |
FIND |
Acceptance Criteria
-
dotcms-github-issues/skill directory (SKILL.md + all three reference files) moved into.claude/skills/in the project repo -
.claude/commands/directory contains all four command stubs:create-issue.md,update-issue.md,query-issue.md,find-issues.md - Old
.claude/skills/create-issue/directory confirmed removed - CREATE mode verified: issue created with correct labels, native type set, Technology field set in Project testing assign #7
- UPDATE mode verified: fetches current state, shows validation table, applies changes
- QUERY mode verified: returns title, labels, native type, project fields, sub-issues
- FIND mode verified: current sprint query and previous sprint query both return correct results for a sprint team (e.g. Scout)
- FIND mode verified: kanban team query (e.g. Enablement) falls back to Status-based results correctly
- All four commands tested in a fresh Claude Code session from the project directory
Metadata
Metadata
Assignees
Type
Projects
Status