@xera-ai/skills 0.15.5 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,42 @@
1
1
  # @xera-ai/skills
2
2
 
3
+ ## 0.16.1
4
+
5
+ ## 0.16.0
6
+
7
+ ### Minor Changes
8
+
9
+ - [#146](https://github.com/xera-ai/xera/pull/146) [`5990dde`](https://github.com/xera-ai/xera/commit/5990dde002d3a9a9dfc6b095fba9666f831bd5de) Thanks [@thanhtrinity](https://github.com/thanhtrinity)! - feat: support GitHub Issues as an alternative issue tracker
10
+
11
+ Adds a tracker-agnostic `IssueProvider` abstraction so projects can use
12
+ either Jira (existing default) or GitHub Issues. The GitHub backend uses
13
+ the GitHub MCP when available and falls back to the `gh` CLI — no token
14
+ env vars are required.
15
+
16
+ Configure via `xera.config.ts`:
17
+
18
+ ```ts
19
+ export default defineConfig({
20
+ github: { repo: "owner/repo" }, // instead of `jira: { ... }`
21
+ // ...rest unchanged
22
+ });
23
+ ```
24
+
25
+ `xera init` adds a `--tracker github` flag (and an interactive prompt) so
26
+ scaffolds can target GitHub Issues from day one. GitHub ticket keys take
27
+ the form `GH-<number>` (e.g. `/xera-fetch GH-42`).
28
+
29
+ `xera doctor` checks `gh auth status` when the github tracker is configured
30
+ and the GitHub MCP is not in use, so auth issues surface before pipeline
31
+ runs. `xera-report` posts comments via `mcp__github__add_issue_comment` or
32
+ falls back to `gh issue comment`. `xera-promote` is tracker-agnostic.
33
+
34
+ Backwards-compatible: existing Jira configs are unchanged.
35
+
36
+ ### Patch Changes
37
+
38
+ - [#151](https://github.com/xera-ai/xera/pull/151) [`f3d8906`](https://github.com/xera-ai/xera/commit/f3d8906403ec362cd75ffe13a09730494819cc5d) Thanks [@thanhtrinity](https://github.com/thanhtrinity)! - unblock /xera-run on first invocation ([#149](https://github.com/xera-ai/xera/issues/149)) (auto-generated from [#151](https://github.com/xera-ai/xera/issues/151))
39
+
3
40
  ## 0.15.5
4
41
 
5
42
  ## 0.15.4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xera-ai/skills",
3
- "version": "0.15.5",
3
+ "version": "0.16.1",
4
4
  "files": [
5
5
  "*.md",
6
6
  "version.json"
package/xera-feature.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: xera-feature
3
- description: Generate or regenerate the Gherkin test.feature file for a Jira ticket. Use when QA wants AI to produce Gherkin scenarios from the fetched user story.
3
+ description: Generate or regenerate the Gherkin test.feature file for a ticket (Jira or GitHub). Use when QA wants AI to produce Gherkin scenarios from the fetched user story.
4
4
  ---
5
5
 
6
6
  You are running inside a project repo configured for xera. The user has invoked `/xera-feature <TICKET>`.
package/xera-fetch.md CHANGED
@@ -1,20 +1,26 @@
1
1
  ---
2
2
  name: xera-fetch
3
- description: Fetch a Jira ticket and write its user story to .xera/<TICKET>/story.md. Use when QA wants to start working on a ticket without yet generating tests.
3
+ description: Fetch a Jira or GitHub issue and write its user story to .xera/<TICKET>/story.md. Use when QA wants to start working on a ticket without yet generating tests.
4
4
  ---
5
5
 
6
6
  You are running inside a project repo configured for xera. The user has invoked `/xera-fetch <TICKET>`.
7
7
 
8
- If the user did not provide a ticket key, ask: "Which Jira ticket key?" and wait. The key must look like `PROJ-123`.
8
+ Determine the configured issue provider by reading `xera.config.ts`:
9
+ - If `github.repo` is set → GitHub provider. Ticket keys look like `GH-123` (the number maps to the configured `owner/repo` issue).
10
+ - Else if `jira` is set → Jira provider. Ticket keys look like `PROJ-123`.
11
+
12
+ If the user did not provide a ticket key, ask: "Which ticket key?" and wait. Show the expected shape for the configured provider.
9
13
 
10
14
  1. Check whether `.xera/{{TICKET}}/story.md` already exists.
11
15
  - If yes, read its first line to confirm the ticket key matches.
12
- - If the file exists and the user did not explicitly ask to re-fetch, ask: "story.md exists for {{TICKET}}. Re-fetch from Jira and overwrite? (y/N)". Default to no.
16
+ - If the file exists and the user did not explicitly ask to re-fetch, ask: "story.md exists for {{TICKET}}. Re-fetch and overwrite? (y/N)". Default to no.
17
+
18
+ 2. Detect the issue-provider backend:
13
19
 
14
- 2. Detect Jira backend:
20
+ **Jira provider:**
15
21
  - If an Atlassian MCP tool is available in this session (a tool whose name starts with `mcp__atlassian__` or `mcp__plugin_engineering_atlassian__`), use it:
16
22
  a. Call `getJiraIssue` (or equivalent) with the ticket key.
17
- b. Map the response into the shape `xera-internal fetch` expects: `{ key, summary, story, acceptanceCriteria?, attachments, raw }`.
23
+ b. Map the response into the shape `xera-internal fetch` expects: `{ key, summary, story, acceptanceCriteria?, attachments }`.
18
24
  - `story` is the value of the field named in `xera.config.ts.jira.fields.story`.
19
25
  - `acceptanceCriteria` is the value of `jira.fields.acceptanceCriteria` if set.
20
26
  - `attachments` is the array of attachments, each mapped to `{ filename, url }`.
@@ -22,6 +28,15 @@ If the user did not provide a ticket key, ask: "Which Jira ticket key?" and wait
22
28
  d. Set the environment variable `XERA_MCP_JIRA=1` for the next subprocess call.
23
29
  - Else: use the REST backend implicitly via `JIRA_EMAIL` + `JIRA_API_TOKEN` from `.env`.
24
30
 
31
+ **GitHub provider:**
32
+ - The github issue number is the digits after `GH-` (e.g. `GH-42` → issue `42` in the repo named by `github.repo`).
33
+ - If a GitHub MCP tool is available in this session (a tool whose name starts with `mcp__github__`), use it:
34
+ a. Call `mcp__github__get_issue` (or equivalent) with `owner`, `repo` (from `github.repo`), and `issue_number`.
35
+ b. Map the response into the shape `xera-internal fetch` expects: `{ key, summary, story, attachments }`, where `key` is `GH-<number>`, `summary` is the issue title, and `story` is the issue body. GitHub issues have no separate AC field — leave `acceptanceCriteria` unset; step 4 below will body-extract.
36
+ c. Write that JSON to `$TMPDIR/xera-mcp-github/{{TICKET}}.json` (create the dir if missing).
37
+ d. Set `XERA_MCP_GITHUB=1` for the next subprocess call.
38
+ - Else: rely on the `gh` CLI. `xera-internal fetch` will invoke `gh issue view <number> --repo <owner/repo> --json …`. Confirm the user is authenticated by running `gh auth status` once if you have any doubt; surface a fix if not.
39
+
25
40
  3. Run: `bun run xera:fetch {{TICKET}}`
26
41
  - Exit 0 → continue.
27
42
  - Exit 1 → user/config error. Read stderr, show the user the fix instructions, STOP.
package/xera-report.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: xera-report
3
- description: Classify the latest run, draft a Jira comment, and post it. Use after `/xera-exec` when QA wants the diagnosis and Jira update.
3
+ description: Classify the latest run, draft a comment for the configured issue tracker (Jira or GitHub), and post it. Use after `/xera-exec` when QA wants the diagnosis and the tracker update.
4
4
  ---
5
5
 
6
6
  You are running `/xera-report <TICKET>` (or `/xera-report --no-heal <TICKET>` to skip the heal sub-flow described in step 4a; or you were dispatched to this step by `/xera-run`). If no ticket key is provided, ask the user.
@@ -158,15 +158,16 @@ After the heal sub-flow finishes (whether it applied, refused, or errored), cont
158
158
  bun run xera:report {{TICKET}} --input=.xera/{{TICKET}}/classifier-input.json
159
159
  ```
160
160
 
161
- The `xera:report` subcommand reads `outdated-decisions.json` (if present) and may upgrade scenario classifications to `TEST_OUTDATED`. It aggregates per-scenario classifications into an overall verdict, updates `status.json` with history, and writes `jira-comment.draft.md`. If exit code is non-zero, surface the error to the user; do not proceed to post.
161
+ The `xera:report` subcommand reads `outdated-decisions.json` (if present) and may upgrade scenario classifications to `TEST_OUTDATED`. It aggregates per-scenario classifications into an overall verdict, updates `status.json` with history, and writes `comment.draft.md`. If exit code is non-zero, surface the error to the user; do not proceed to post.
162
162
 
163
- 6. **Show the draft.** Read `.xera/{{TICKET}}/jira-comment.draft.md`. Display its content to the user verbatim. Ask: "Post to Jira? (Y/n)" (default: Y, unless `meta.json.source === "local"` for SAMPLE tickets — then never post).
163
+ 6. **Show the draft.** Read `.xera/{{TICKET}}/comment.draft.md`. Display its content to the user verbatim. Ask: "Post to the tracker? (Y/n)" (default: Y, unless `meta.json.source === "local"` for SAMPLE tickets — then never post).
164
164
 
165
- 7. **Post.** If user says yes (or `xera-run` is in auto mode with `postToJira: true`):
166
- - If an Atlassian MCP tool is available in this session (e.g., `mcp__atlassian__addCommentToJiraIssue` or `mcp__plugin_engineering_atlassian__addCommentToJiraIssue`), call it with `{{TICKET}}` and the draft contents. Capture the comment id.
167
- - Else run `bun run xera:post {{TICKET}}` (uses REST credentials from `.env`).
165
+ 7. **Post.** If user says yes (or `xera-run` is in auto mode with `reporting.postComment: true` — also accepts the legacy alias `postToJira`):
166
+ - Determine the configured tracker from `xera.config.ts` (`jira:` vs `github:`).
167
+ - **Jira tracker:** if an Atlassian MCP tool is available in this session (e.g., `mcp__atlassian__addCommentToJiraIssue` or `mcp__plugin_engineering_atlassian__addCommentToJiraIssue`), call it with `{{TICKET}}` and the draft contents. Capture the comment id. Otherwise run `bun run xera:post {{TICKET}}` (uses REST credentials from `.env`).
168
+ - **GitHub tracker:** if a GitHub MCP tool such as `mcp__github__add_issue_comment` is available, call it with `owner`/`repo` from `xera.config.ts.github.repo` and the issue number (the digits after `GH-`). Otherwise run `bun run xera:post {{TICKET}}` — the helper shells out to `gh issue comment` and surfaces the resulting comment URL.
168
169
 
169
- 8. **Summarize** to the user: overall classification, scenario pass/fail counts, the reproduce command (`bunx xera-internal exec {{TICKET}} --replay=<runId>`), and the Jira comment URL if available.
170
+ 8. **Summarize** to the user: overall classification, scenario pass/fail counts, the reproduce command (`bunx xera-internal exec {{TICKET}} --replay=<runId>`), and the posted comment URL if available (Jira link or GitHub issue-comment anchor depending on the tracker).
170
171
 
171
172
  ## Step 9 — Record graph classification events (v0.6)
172
173
 
@@ -178,7 +179,10 @@ Non-fatal. Note: TEST_OUTDATED detection ships in v0.6.1 — for v0.6.0 this jus
178
179
 
179
180
  ## Step 10 — Notify ticket owner when TEST_OUTDATED detected (v0.6.1)
180
181
 
181
- For every scenario classified as `TEST_OUTDATED` in `outdated-decisions.json`, find the **original ticket** that owns the scenario (from graph: `xera:graph-query --ticket <SCENARIO_OWNER_TICKET> --format json`). Then post a Jira sub-task on that ticket via the existing Jira backend (the same code path `/xera-fetch` uses to read tickets — re-use the configured backend per `xera.config.ts.jira`):
182
+ For every scenario classified as `TEST_OUTDATED` in `outdated-decisions.json`, find the **original ticket** that owns the scenario (from graph: `xera:graph-query --ticket <SCENARIO_OWNER_TICKET> --format json`). Then notify the original ticket's owner via the configured issue tracker:
183
+
184
+ - **Jira tracker:** post a sub-task on the original ticket (re-use the same backend `/xera-fetch` uses — `xera.config.ts.jira`).
185
+ - **GitHub tracker:** GitHub has no sub-tasks. Post a comment on the original issue and `@`-mention the assignee instead (use `mcp__github__add_issue_comment` if available, else `bun run xera:post <ORIGINAL_TICKET>` after writing the comment body into `.xera/<ORIGINAL_TICKET>/comment.draft.md`).
182
186
 
183
187
  Body template:
184
188
 
package/xera-run.md CHANGED
@@ -1,22 +1,24 @@
1
1
  ---
2
2
  name: xera-run
3
- description: Run the full xera pipeline for a Jira ticket end-to-end — fetch story, generate Gherkin, generate Playwright spec, execute, diagnose, post to Jira. Use when QA wants to test a ticket from scratch.
3
+ description: Run the full xera pipeline for a ticket end-to-end — fetch story, generate Gherkin, generate Playwright spec, execute, diagnose, post a comment to the configured issue tracker (Jira or GitHub). Use when QA wants to test a ticket from scratch.
4
4
  ---
5
5
 
6
6
  The user invoked `/xera-run <TICKET>`. If no key, ask.
7
7
 
8
8
  This skill orchestrates the other six skills with quality gates between each step. If any step fails non-recoverably, STOP and surface the cause.
9
9
 
10
- ## Step 0 — Health gate
10
+ ## Step 0 — Health gate (environment only)
11
11
 
12
- Run: `bunx xera doctor --strict {{TICKET}}`
12
+ Run: `bunx xera doctor --strict`
13
13
  If non-zero exit → STOP. Show the output verbatim. Suggest the user fix env and re-run.
14
14
 
15
+ This runs the environment-level checks (bun, `xera.config.ts`, baseUrl reachability, auth files, OpenAPI, `.env`, editor skill layout). The ticket-specific gate runs as Step 1.6 after fetch, since `.xera/{{TICKET}}/` legitimately does not exist on the very first invocation of `/xera-run`.
16
+
15
17
  ## Step 1 — Fetch
16
18
 
17
19
  Follow the same instructions as `xera-fetch.md`, but never prompt the user about re-fetching here.
18
20
 
19
- **Sub-steps 1–3 of xera-fetch (Jira call → write `story.md` + `meta.json`)**: skip if `story.md` exists AND `meta.json` shows a `story_hash` < 24 hours old. Otherwise refresh.
21
+ **Sub-steps 1–3 of xera-fetch (tracker call → write `story.md` + `meta.json`)**: skip if `story.md` exists AND `meta.json` shows a `story_hash` < 24 hours old. Otherwise refresh.
20
22
 
21
23
  **Sub-step 4 of xera-fetch (cognitive AC body-extraction)**: re-run whenever `story.md` frontmatter shows `acceptanceCriteriaSource: none` AND `acceptanceCriteria:` block is empty — even when sub-steps 1–3 were skipped. The extraction is cheap and idempotent (writes back to the same frontmatter). Skipping it permanently is what causes projects with AC-in-body workflow to have empty AC across the graph.
22
24
 
@@ -51,6 +53,14 @@ This means the auto-trigger is effectively a "high-risk alarm" rather than a per
51
53
 
52
54
  Non-fatal: if `xera:impact-prepare` itself exits abnormally, log the warning but continue to Step 2 — graph features are advisory, not gating.
53
55
 
56
+ ## Step 1.6 — Ticket health gate
57
+
58
+ Run: `bunx xera doctor --strict {{TICKET}}`
59
+
60
+ This re-runs doctor with the ticket arg now that `/xera-fetch` has materialized `.xera/{{TICKET}}/` (story.md, meta.json, graph-input.json). Checks include: artifact dir present, `graph-input.json` parses with a valid `modifiesAreas` array, and `story.md` frontmatter has acceptanceCriteria (or an actionable hint if not).
61
+
62
+ If non-zero exit → STOP. Show the output verbatim. The most common failures are recoverable in-place (re-run a single substep of `/xera-fetch`); pick the hint that matches the failing check.
63
+
54
64
  ## Step 2 — Feature
55
65
 
56
66
  Follow `xera-feature.md`. If `feature_generated_from_story_hash !== story_hash`, regenerate. If unchanged AND spec.ts exists, skip feature generation entirely.
@@ -69,8 +79,8 @@ Run `bun run xera:normalize {{TICKET}}`. This writes `normalized.json` AND emits
69
79
 
70
80
  ## Step 6 — Diagnose + report + post
71
81
 
72
- Follow `xera-report.md` from step 3 onwards. If the user is the SAMPLE-001 ticket (meta.source === "local"), do NOT post to Jira and do NOT prompt about posting — only print the drafted comment.
82
+ Follow `xera-report.md` from step 3 onwards. If the user is the SAMPLE-001 ticket (meta.source === "local"), do NOT post a comment and do NOT prompt about posting — only print the drafted comment.
73
83
 
74
84
  ## Step 7 — Summary
75
85
 
76
- Print a single-paragraph summary covering: overall result, classification, per-scenario counts, link to Jira comment (if posted), and the reproduce command (`bunx xera-internal exec {{TICKET}} --replay=<runId>`).
86
+ Print a single-paragraph summary covering: overall result, classification, per-scenario counts, link to the posted comment (if posted — Jira link or GitHub issue-comment anchor), and the reproduce command (`bunx xera-internal exec {{TICKET}} --replay=<runId>`).