@xera-ai/skills 0.11.6 → 0.12.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 +23 -0
- package/package.json +1 -1
- package/xera-explore.md +179 -0
- package/xera-report.md +1 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @xera-ai/skills
|
|
2
2
|
|
|
3
|
+
## 0.12.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#100](https://github.com/xera-ai/xera/pull/100) [`40a1488`](https://github.com/xera-ai/xera/commit/40a1488a7f0e5bbf697361a250977c680aca0dd3) Thanks [@thanhtrinity](https://github.com/thanhtrinity)! - core,cli,skills: strict config schema + remove unwired `testOutdated` config docs
|
|
8
|
+
|
|
9
|
+
- `XeraConfigSchema` is now `strictObject` and rejects unknown top-level keys instead of silently stripping them. This surfaces config typos and aspirational keys (e.g. `testOutdated`, `report`) at parse time with a clear Zod error ([#94](https://github.com/xera-ai/xera/issues/94)).
|
|
10
|
+
- Docs (`CONFIGURATION.md`, `TROUBLESHOOTING.md`) and the `/xera-report` skill no longer reference the unwired `testOutdated.threshold` / `report.testOutdatedNotify` keys; those tuning hooks are tracked for a future release.
|
|
11
|
+
- Followup to [#95](https://github.com/xera-ai/xera/issues/95) / [#92](https://github.com/xera-ai/xera/issues/92): the http-only `.env.example` template comment now references `.env` (the canonical filename) instead of `.env.local`.
|
|
12
|
+
|
|
13
|
+
## 0.12.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- [#86](https://github.com/xera-ai/xera/pull/86) [`7ba0b72`](https://github.com/xera-ai/xera/commit/7ba0b723dc43faa4a5046c9c992c023d3003b360) Thanks [@thanhtrinity](https://github.com/thanhtrinity)! - skills: add /xera-explore (experimental) — opt-in adversarial scenario generator beyond AC
|
|
18
|
+
|
|
19
|
+
Introduces `/xera-explore <TICKET>`, a QA-internal skill that proposes 5-10 adversarial Gherkin scenarios beyond the ticket's acceptance criteria (negative paths, boundaries, races, a11y, security smells, etc.). Output lands in `.xera/<TICKET>/explore.feature` (separate from `test.feature`) tagged `@adversarial` for selective execution. The skill is opt-in and NOT auto-chained from `/xera-run`.
|
|
20
|
+
|
|
21
|
+
- New prompt: `adversarial-scenarios.md` v0.1.0 — 8-category heuristic checklist, concrete-value rule, NONCE-wrapped untrusted input handling.
|
|
22
|
+
- New skill: `xera-explore.md` — interactive UX with two QA checkpoints (category focus + concrete concern hint, then per-proposal acceptance).
|
|
23
|
+
- New binaries: `explore-prepare`, `explore-finalize`.
|
|
24
|
+
- Status: experimental. No golden-eval coverage yet; no `xera.config.ts.explore` knobs yet (both deferred). Graph event emission deferred to next release.
|
|
25
|
+
|
|
3
26
|
## 0.11.6
|
|
4
27
|
|
|
5
28
|
## 0.11.5
|
package/package.json
CHANGED
package/xera-explore.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xera-explore
|
|
3
|
+
description: Generative — propose ADVERSARIAL Gherkin scenarios beyond the ticket's acceptance criteria (negative paths, boundaries, races, a11y, security smells). QA-internal; not part of /xera-run. Use when you want AI to brainstorm "what could go wrong" tests for a ticket. Available v0.9+ (experimental).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user invoked `/xera-explore <TICKET>`. If no key, ask.
|
|
7
|
+
|
|
8
|
+
This skill is **opt-in and QA-internal**. `/xera-run` does NOT auto-trigger it. Output lands in `.xera/<TICKET>/explore.feature` (separate from `test.feature`) so PO review of AC-driven scenarios is not disturbed.
|
|
9
|
+
|
|
10
|
+
**Status: experimental.** The prompt has no golden-eval coverage yet (v0.9.0). Treat AI output as a brainstorming partner, not a source of truth — QA must review every proposal.
|
|
11
|
+
|
|
12
|
+
## Step 1 — Verify project + ticket
|
|
13
|
+
|
|
14
|
+
Confirm `xera.config.ts` exists in cwd. If not, say `xera.config.ts not found — run this inside a xera project.` and STOP.
|
|
15
|
+
|
|
16
|
+
Verify `.xera/{{TICKET}}/story.md` exists. If not, say `No story.md for {{TICKET}}. Run /xera-fetch {{TICKET}} first.` and STOP.
|
|
17
|
+
|
|
18
|
+
## Step 2 — Ask the user for focus (UX checkpoint)
|
|
19
|
+
|
|
20
|
+
Before running the prompt, ask the user **two questions** in sequence:
|
|
21
|
+
|
|
22
|
+
**Q1.** Print:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
What adversarial categories should I focus on for {{TICKET}}?
|
|
26
|
+
|
|
27
|
+
[1] negative — invalid/malformed input (default ON)
|
|
28
|
+
[2] boundary — empty/max-length/unicode/precision edges (default ON)
|
|
29
|
+
[3] state-combination — role × flag × prior-action combinations
|
|
30
|
+
[4] race — double-submit, concurrent, network drop mid-action
|
|
31
|
+
[5] error-recovery — 5xx, timeout, session expiry, browser back/forward
|
|
32
|
+
[6] a11y — keyboard nav, screen reader, focus management
|
|
33
|
+
[7] security-smell — XSS, IDOR, open redirect, auth bypass
|
|
34
|
+
[8] non-functional — i18n, perf budget, viewport, reduced motion
|
|
35
|
+
|
|
36
|
+
Reply with: numbers (e.g. "1,2,4,7"), "all", or "default" (= 1,2,4,7 — the 4 most universally relevant).
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Wait for the user's answer. Default to `1,2,4,7` if they reply "default" or with an empty input. Reject invalid numbers with a one-line error and re-ask.
|
|
40
|
+
|
|
41
|
+
For HTTP adapter tickets (`meta.json.adapter === "http"`), strike `a11y` from the list and adjust default to `1,2,4,5,7`.
|
|
42
|
+
|
|
43
|
+
**Q2.** Print:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
Any specific concern to investigate? (e.g. "double-charge under flaky network", "RTL languages break the cart UI")
|
|
47
|
+
Reply with a one-liner, or press Enter to skip.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Capture the free-text reply (may be empty). This becomes `userHint` passed to the prompt.
|
|
51
|
+
|
|
52
|
+
## Step 3 — Prepare context
|
|
53
|
+
|
|
54
|
+
Run:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bun run xera:explore-prepare {{TICKET}} \
|
|
58
|
+
--categories "<comma-separated-slugs-from-Q1>" \
|
|
59
|
+
--user-hint "<reply-from-Q2-or-empty>"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Exit codes:
|
|
63
|
+
- `0` — context written to `.xera/{{TICKET}}/adversarial-input.json`
|
|
64
|
+
- `1` — invalid flags (shouldn't happen; you pass through user input)
|
|
65
|
+
- `2` — ticket has no story / not a xera project; surface stderr and STOP
|
|
66
|
+
|
|
67
|
+
The binary assembles: story, AC, existing `test.feature` (if present), existing `spec.ts` (if present), adapter, the chosen categories, and the user hint.
|
|
68
|
+
|
|
69
|
+
## Step 4 — Invoke the adversarial-scenarios prompt
|
|
70
|
+
|
|
71
|
+
Mint a fresh per-invocation nonce:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bun -e "console.log('XR_' + crypto.randomUUID().replace(/-/g,'').slice(0,12))"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Capture the single-line output as the nonce.
|
|
78
|
+
|
|
79
|
+
Read `.xera/{{TICKET}}/adversarial-input.json` and `node_modules/@xera-ai/prompts/adversarial-scenarios.md`. Generate proposals following that prompt's rules. Wrap the input JSON between two identical `<NONCE>` tags (using the real nonce, NOT the literal `<NONCE>`) before feeding it to your generation context.
|
|
80
|
+
|
|
81
|
+
Write the prompt output to `.xera/{{TICKET}}/adversarial-proposals.json`. Schema:
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"proposals": [
|
|
86
|
+
{
|
|
87
|
+
"id": "A1",
|
|
88
|
+
"ticketId": "{{TICKET}}",
|
|
89
|
+
"category": "negative | boundary | state-combination | race | error-recovery | a11y | security-smell | non-functional",
|
|
90
|
+
"severity": "low | medium | high",
|
|
91
|
+
"title": "...",
|
|
92
|
+
"rationale": "...",
|
|
93
|
+
"gherkin": "Scenario: ...\n Given ...\n When ...\n Then ..."
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Step 5 — Present proposals to user (UX checkpoint)
|
|
100
|
+
|
|
101
|
+
Read the proposals and print them grouped by severity descending, with category badge. Example:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
8 adversarial scenarios proposed for {{TICKET}}:
|
|
105
|
+
|
|
106
|
+
[HIGH] severity
|
|
107
|
+
[A1] race · "Double-click Apple Pay does not double-charge"
|
|
108
|
+
Why: AC does not mention idempotency; spec.ts has no waitFor on button disable.
|
|
109
|
+
Preview: Given user is on /checkout · When user clicks "Apple Pay" twice within 200ms · Then exactly one payment is captured
|
|
110
|
+
|
|
111
|
+
[A2] security-smell · "Comment field rejects script injection"
|
|
112
|
+
Why: AC doesn't mention sanitization; comment field is reflected on order confirmation.
|
|
113
|
+
Preview: When user enters "<script>alert(1)</script>" as comment · Then the rendered comment shows literal text
|
|
114
|
+
|
|
115
|
+
[MEDIUM] severity
|
|
116
|
+
[A3] negative · "Email field rejects malformed addresses"
|
|
117
|
+
...
|
|
118
|
+
|
|
119
|
+
[LOW] severity
|
|
120
|
+
[A8] non-functional · "Order summary survives 1000 line items"
|
|
121
|
+
...
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Ask the user:
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
Pick proposals to accept [comma-separated IDs / all / high-only / none]:
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- **none** — STOP. Mention `.xera/{{TICKET}}/adversarial-proposals.json` is preserved for later review.
|
|
131
|
+
- **all** — accept every proposal.
|
|
132
|
+
- **high-only** — accept only `severity === "high"`.
|
|
133
|
+
- **comma-separated IDs** (e.g. `A1, A3, A7`) — accept the named subset. Reject unknown IDs with a one-line error and re-ask.
|
|
134
|
+
|
|
135
|
+
## Step 6 — Finalize accepted proposals
|
|
136
|
+
|
|
137
|
+
Run:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
bun run xera:explore-finalize {{TICKET}} --accept "<comma-separated-ids-or-all-or-high-only>"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The binary appends accepted scenarios to `.xera/{{TICKET}}/explore.feature`, tagged `@adversarial` (and a second tag matching the category, e.g. `@adversarial-race`). If `explore.feature` does not exist, the binary creates it with a Feature header copied from `test.feature` (or a synthesized one if no `test.feature` yet).
|
|
144
|
+
|
|
145
|
+
Exit codes:
|
|
146
|
+
- `0` — written
|
|
147
|
+
- `1` — invalid flags / no IDs matched
|
|
148
|
+
- `2` — proposals file missing (Step 4 didn't produce output)
|
|
149
|
+
- `4` — internal write error
|
|
150
|
+
|
|
151
|
+
## Step 7 — Next-step summary
|
|
152
|
+
|
|
153
|
+
Print:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
Wrote N adversarial scenarios to .xera/{{TICKET}}/explore.feature.
|
|
157
|
+
|
|
158
|
+
Review the file, edit as needed, then either:
|
|
159
|
+
(a) merge into test.feature and run /xera-script {{TICKET}} to generate spec
|
|
160
|
+
(b) keep explore.feature separate and run via: bun run xera:exec {{TICKET}} --grep "@adversarial"
|
|
161
|
+
(when /xera-script grows multi-feature support — currently spec covers test.feature only,
|
|
162
|
+
so option (a) is the only end-to-end path)
|
|
163
|
+
|
|
164
|
+
The raw proposals are at .xera/{{TICKET}}/adversarial-proposals.json if you want to revisit.
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Edge cases
|
|
168
|
+
|
|
169
|
+
- User picks 0 categories in Q1 → STOP with a friendly note ("no categories selected, nothing to explore").
|
|
170
|
+
- Prompt returns `{ "proposals": [] }` (degenerate input or attempted injection) → tell the user the prompt returned no proposals and STOP. Do NOT retry without further input from the user.
|
|
171
|
+
- `adversarial-proposals.json` already exists from a prior run → ask `Overwrite existing proposals from prior /xera-explore run? (y/N)` before Step 4. If no, skip Step 4 and jump straight to Step 5 with the existing file.
|
|
172
|
+
- `explore.feature` already exists → the finalize binary appends; it does NOT overwrite. If the user wants a clean slate, instruct them to delete the file manually before re-running.
|
|
173
|
+
|
|
174
|
+
## What this skill does NOT do
|
|
175
|
+
|
|
176
|
+
- It does NOT modify `test.feature`. AC-driven scenarios are sacred.
|
|
177
|
+
- It does NOT generate `spec.ts`. That's `/xera-script`'s job. Merge `explore.feature` into `test.feature` first.
|
|
178
|
+
- It does NOT auto-run tests. Use `/xera-exec` after merging.
|
|
179
|
+
- It does NOT record graph events in v0.9.0 (deferred to v0.9.1 once the schema is finalized).
|
package/xera-report.md
CHANGED
|
@@ -193,10 +193,7 @@ In the current QA's session, only show a summary line:
|
|
|
193
193
|
3 impact tickets notified (ABC-100, ABC-145, ABC-178). No action required from you.
|
|
194
194
|
```
|
|
195
195
|
|
|
196
|
-
**
|
|
197
|
-
- `'jira-subtask'` (default) — post sub-task as above
|
|
198
|
-
- `'comment'` — post comment instead
|
|
199
|
-
- `'console-only'` — only print to terminal, no Jira write
|
|
196
|
+
**Routing:** Currently always posts a `jira-subtask`. Alternative routings (`comment`, `console-only`) are tracked for a future release.
|
|
200
197
|
|
|
201
198
|
## Step 11 — Dispute capture (v0.6.1, optional)
|
|
202
199
|
|