@codyswann/lisa 2.11.1 → 2.13.0

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/package.json CHANGED
@@ -79,7 +79,7 @@
79
79
  "lodash": ">=4.18.1"
80
80
  },
81
81
  "name": "@codyswann/lisa",
82
- "version": "2.11.1",
82
+ "version": "2.13.0",
83
83
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
84
84
  "main": "dist/index.js",
85
85
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -34,7 +34,23 @@ Call `mcp__atlassian__getJiraIssue` for the target ticket. Extract and preserve:
34
34
  - Full description (preserve formatting)
35
35
  - Acceptance criteria section if separately structured
36
36
  - **Validation Journey** section if present (pass verbatim to downstream)
37
- - Attachments list (names + URLs, do not download unless needed)
37
+ - Attachments list capture `id`, `filename`, `mimeType`, `size`, and `content` URL for each. Do not download unless a downstream task needs the bytes (see "Downloading attachments" below).
38
+
39
+ #### Downloading attachments (opt-in)
40
+
41
+ The Atlassian MCP exposes attachment metadata but no binary-fetch tool ([JRACLOUD-97830](https://jira.atlassian.com/browse/JRACLOUD-97830), [ECO-1265](https://jira.atlassian.com/browse/ECO-1265)). Fetch attachment bytes only when a downstream task explicitly needs them — e.g., a design-fidelity check on an image, log-file analysis, PDF text extraction. For everything else, keep the URL reference and move on.
42
+
43
+ ```bash
44
+ bash .claude/skills/jira-read-ticket/scripts/download-attachment.sh <id-or-content-url> <output-path>
45
+ ```
46
+
47
+ Requires `JIRA_SERVER`, `JIRA_LOGIN`, and `JIRA_API_TOKEN` in the environment (same contract as `jira-evidence`). If those are not set the helper exits with code 2 and a clear remediation message — record the URL only and continue.
48
+
49
+ After download, branch on `mimeType`:
50
+ - `image/*` — pass the local path to image-aware downstream tools
51
+ - `text/*`, `application/json`, `application/xml`, `application/x-yaml` — read inline as text
52
+ - `application/pdf` — extract text via downstream tooling if needed
53
+ - everything else — record path only; do not attempt to inline binary content
38
54
 
39
55
  ### Comments
40
56
 
@@ -121,7 +137,7 @@ Produce a single structured output that the caller can pass verbatim to downstre
121
137
  <chronological comments, flagged items called out>
122
138
 
123
139
  ### Attachments
124
- <list>
140
+ <list with id, filename, mimeType, size, content URL — note any that were downloaded and their local paths>
125
141
 
126
142
  ## Remote Links
127
143
  ### Pull Requests (<count>)
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env bash
2
+ # download-attachment.sh — Download a JIRA attachment to a local file.
3
+ #
4
+ # Usage:
5
+ # bash download-attachment.sh <ATTACHMENT_ID_OR_URL> <OUTPUT_PATH>
6
+ #
7
+ # Why this helper exists:
8
+ # The Atlassian MCP server (mcp__atlassian__*) returns attachment metadata
9
+ # (id, filename, mimeType, size, content URL) on getJiraIssue but provides
10
+ # no tool to fetch the binary content. This script closes the gap by
11
+ # hitting the Jira REST API directly with Basic auth, mirroring the
12
+ # env-var contract already used by jira-evidence/scripts/post-evidence.sh.
13
+ #
14
+ # See https://jira.atlassian.com/browse/JRACLOUD-97830 for the upstream
15
+ # gap; remove this helper once Atlassian ships a download tool in the MCP.
16
+ #
17
+ # Required env vars:
18
+ # JIRA_SERVER - https://<your-tenant>.atlassian.net
19
+ # JIRA_LOGIN - login email
20
+ # JIRA_API_TOKEN - API token (https://id.atlassian.com/manage-profile/security/api-tokens)
21
+ #
22
+ # Exit codes:
23
+ # 0 success
24
+ # 1 download failed (HTTP error)
25
+ # 2 missing required env var
26
+ # 3 invalid arguments
27
+
28
+ set -euo pipefail
29
+
30
+ if [[ $# -lt 2 ]]; then
31
+ echo "Usage: download-attachment.sh <ATTACHMENT_ID_OR_URL> <OUTPUT_PATH>" >&2
32
+ exit 3
33
+ fi
34
+ ID_OR_URL="$1"
35
+ OUTPUT_PATH="$2"
36
+
37
+ # Resolve credentials: prefer env, fall back to jira-cli config for server/login.
38
+ JIRA_CONFIG="${HOME}/.config/.jira/.config.yml"
39
+ if [[ -z "${JIRA_SERVER:-}" && -f "$JIRA_CONFIG" ]]; then
40
+ JIRA_SERVER=$(grep '^server:' "$JIRA_CONFIG" | awk '{print $2}')
41
+ fi
42
+ if [[ -z "${JIRA_LOGIN:-}" && -f "$JIRA_CONFIG" ]]; then
43
+ JIRA_LOGIN=$(grep '^login:' "$JIRA_CONFIG" | awk '{print $2}')
44
+ fi
45
+
46
+ for VAR in JIRA_SERVER JIRA_LOGIN JIRA_API_TOKEN; do
47
+ if [[ -z "${!VAR:-}" ]]; then
48
+ echo "ERROR: $VAR is not set." >&2
49
+ echo "Required env vars: JIRA_SERVER, JIRA_LOGIN, JIRA_API_TOKEN." >&2
50
+ echo "Generate an API token: https://id.atlassian.com/manage-profile/security/api-tokens" >&2
51
+ exit 2
52
+ fi
53
+ done
54
+
55
+ OUTPUT_DIR=$(dirname "$OUTPUT_PATH")
56
+ if [[ ! -d "$OUTPUT_DIR" ]]; then
57
+ echo "ERROR: Output directory does not exist: $OUTPUT_DIR" >&2
58
+ exit 3
59
+ fi
60
+
61
+ if [[ "$ID_OR_URL" == http*://* ]]; then
62
+ ATTACHMENT_URL="$ID_OR_URL"
63
+ else
64
+ ATTACHMENT_URL="${JIRA_SERVER%/}/rest/api/3/attachment/content/$ID_OR_URL"
65
+ fi
66
+
67
+ JIRA_AUTH=$(printf '%s' "$JIRA_LOGIN:$JIRA_API_TOKEN" | base64 | tr -d '\n')
68
+
69
+ # Atlassian responds 302 to a signed URL on media.atlassian.com that has its
70
+ # own auth and rejects Basic. Two-step: capture Location, then GET unauthed.
71
+ HEADERS_FILE=$(mktemp)
72
+ trap 'rm -f "$HEADERS_FILE"' EXIT
73
+
74
+ HTTP_CODE=$(curl -sS -o /dev/null -w '%{http_code}' \
75
+ --max-redirs 0 \
76
+ -D "$HEADERS_FILE" \
77
+ -H "Authorization: Basic $JIRA_AUTH" \
78
+ -H "Accept: */*" \
79
+ "$ATTACHMENT_URL" || true)
80
+
81
+ case "$HTTP_CODE" in
82
+ 302|303|307)
83
+ SIGNED_URL=$(awk '/^[Ll]ocation:/{sub(/^[Ll]ocation:[ \t]*/,""); sub(/\r$/,""); print; exit}' "$HEADERS_FILE")
84
+ if [[ -z "$SIGNED_URL" ]]; then
85
+ echo "ERROR: Got HTTP $HTTP_CODE but no Location header in response." >&2
86
+ exit 1
87
+ fi
88
+ curl -sSf -o "$OUTPUT_PATH" "$SIGNED_URL" || { echo "ERROR: Download from signed URL failed." >&2; exit 1; }
89
+ ;;
90
+ 200)
91
+ curl -sSf -o "$OUTPUT_PATH" \
92
+ -H "Authorization: Basic $JIRA_AUTH" \
93
+ -H "Accept: */*" \
94
+ "$ATTACHMENT_URL" || { echo "ERROR: Direct download from $ATTACHMENT_URL failed." >&2; exit 1; }
95
+ ;;
96
+ 401|403)
97
+ echo "ERROR: Authentication failed (HTTP $HTTP_CODE). Verify JIRA_LOGIN and JIRA_API_TOKEN." >&2
98
+ exit 1
99
+ ;;
100
+ 404)
101
+ echo "ERROR: Attachment not found at $ATTACHMENT_URL (HTTP 404). Verify the ID and your access." >&2
102
+ exit 1
103
+ ;;
104
+ *)
105
+ echo "ERROR: Unexpected HTTP $HTTP_CODE from $ATTACHMENT_URL" >&2
106
+ exit 1
107
+ ;;
108
+ esac
109
+
110
+ echo " ✓ Downloaded -> $OUTPUT_PATH"
@@ -24,3 +24,26 @@ See the `config-resolution` rule for configuration and dispatch table.
24
24
 
25
25
  - The GitHub `pr-assets` release lives on the implementation repo (the one with the PR), regardless of which tracker hosts the ticket/issue. All vendor skills upload there.
26
26
  - Never post evidence to a different ticket than the one named — `$ARGUMENTS` is the source of truth.
27
+
28
+ ## UI Evidence Checklist (when work is UI-visible)
29
+
30
+ Apply this when authoring `evidence/comment.md` (and `evidence/comment.txt` for JIRA wiki markup) for any ticket whose work touches a user-facing surface — bug fix, new component, new flow, UX polish, design implementation. Skip the checklist for non-UI work (API, infra, migrations, etc.); the plain-text evidence path is fine there.
31
+
32
+ The checklist is tracker-agnostic — the same shape works on JIRA, GitHub Issues, and Linear. Vendor skills only own the post/transition mechanics; the comment body is your responsibility.
33
+
34
+ 1. **AI disclosure at the top.** Lead with "Update from Claude (AI agent, not a human)" and address the reporter / QA / PM by name.
35
+ 2. **Own any prior mistake explicitly.** If an earlier triage or build pass got something wrong, say so up front. Don't bury it.
36
+ 3. **Numbered step-by-step walk** of what you actually did in the browser/app, in plain language a non-engineer can follow:
37
+ - Exact env (URL, viewport size — e.g. `402×874` for an iOS-sized mobile flow)
38
+ - Login creds shape — e.g. `(000) 000-0002` + OTP `555555`
39
+ - Exact record/player name, exact button labels as they appear on screen
40
+ - Full happy-path **and** any non-obvious edge state worth showing (empty state, loading, post-completion)
41
+ 4. **One screenshot per step**, captured live via Playwright MCP at the matching viewport. Upload via `gh release upload pr-assets <files> --clobber` and reference each one as a **plain URL** in the comment body — *not* `![alt](url)` markdown embeds. Plain URLs render as smartlinks/auto-embeds across all three trackers and stay individually viewable; markdown embeds collapse on JIRA when there are ≥2.
42
+ 5. **"What this shows" section.** Tailor to ticket type:
43
+ - **Bug repro:** state plainly whether the bug reproduces or not, and the most likely 1–2 reasons their retest still failed (different env, native app vs. web, stuck backend row, etc.).
44
+ - **Feature/UX completion:** state plainly which acceptance criteria each screenshot covers, and call out any deferred or out-of-scope surface explicitly so QA/PM doesn't have to infer.
45
+ 6. **"What would help me confirm" (bug) / "How to QA" (feature) section.** Concrete actionable retest steps with the exact selection criteria (e.g., "pick a record whose Status column shows `—`, not `Processing` or `Pending Review`").
46
+ 7. **Explicit invitation to be corrected.** End with a line like *"If any of the steps I listed are different from what you expected / actually did, please tell me explicitly which step I got wrong."* Non-optional — small differences (which record, which device, exact tap order, expected behavior) change everything, and naming the door open short-circuits ticket bounce-loops.
47
+ 8. **Workflow transition** is the vendor skill's job, not yours — it'll move the ticket per the configured tracker (JIRA: Reassign to reporter for bug repro / move to Awaiting QA for feature; GitHub: relabel `status:code-review` or equivalent; Linear: equivalent state). You don't transition manually.
48
+
49
+ **Why this format:** It (a) gives the reporter a frame-by-frame they can compare against, (b) avoids the JIRA image-collapse failure mode while still working everywhere else, (c) names the most plausible discrepancies up front so the loop short-circuits, (d) explicitly opens the door to being corrected so tickets don't bounce on assumed alignment. The same mechanics that resolve a stuck bug ticket also give QA an unambiguous handoff for a freshly-built feature.
@@ -29,7 +29,7 @@ Execute the **Verify** flow as defined in the `intent-routing` rule (loaded via
29
29
  4. **Review loop** — handle CodeRabbit / human review comments via `lisa:pull-request-review`
30
30
  5. **Merge** when CI is green
31
31
  6. **Remote verification** — invoke the `lisa:monitor` skill against the target environment to confirm the deploy actually works (health endpoints, recent logs/errors, Validation Journey replay if defined). If remote verification surfaces a behavioral gap that the existing codified tests do not guard, invoke `codify-verification` to add coverage and open a follow-up PR.
32
- 7. **Evidence** — post results to the originating ticket via `lisa:tracker-evidence` (vendor-neutral; dispatches to `lisa:jira-evidence`, `lisa:github-evidence`, or `lisa:linear-evidence` per `.lisa.config.json` `tracker`), including the list of codified tests added on this branch.
32
+ 7. **Evidence** — post results to the originating ticket via `lisa:tracker-evidence` (vendor-neutral; dispatches to `lisa:jira-evidence`, `lisa:github-evidence`, or `lisa:linear-evidence` per `.lisa.config.json` `tracker`), including the list of codified tests added on this branch. **If the work is UI-visible** (any verification step ran in a browser, or the change touches a user-facing surface), author `evidence/comment.md` per the **UI Evidence Checklist** in `lisa:tracker-evidence` — numbered live-session steps, one Playwright-MCP screenshot per step uploaded to the GitHub `pr-assets` release as plain URLs, and an explicit invitation to be corrected.
33
33
 
34
34
  The rule contains the canonical step sequence. Change it there, propagate everywhere.
35
35
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.11.1",
3
+ "version": "2.13.0",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -34,7 +34,23 @@ Call `mcp__atlassian__getJiraIssue` for the target ticket. Extract and preserve:
34
34
  - Full description (preserve formatting)
35
35
  - Acceptance criteria section if separately structured
36
36
  - **Validation Journey** section if present (pass verbatim to downstream)
37
- - Attachments list (names + URLs, do not download unless needed)
37
+ - Attachments list capture `id`, `filename`, `mimeType`, `size`, and `content` URL for each. Do not download unless a downstream task needs the bytes (see "Downloading attachments" below).
38
+
39
+ #### Downloading attachments (opt-in)
40
+
41
+ The Atlassian MCP exposes attachment metadata but no binary-fetch tool ([JRACLOUD-97830](https://jira.atlassian.com/browse/JRACLOUD-97830), [ECO-1265](https://jira.atlassian.com/browse/ECO-1265)). Fetch attachment bytes only when a downstream task explicitly needs them — e.g., a design-fidelity check on an image, log-file analysis, PDF text extraction. For everything else, keep the URL reference and move on.
42
+
43
+ ```bash
44
+ bash .claude/skills/jira-read-ticket/scripts/download-attachment.sh <id-or-content-url> <output-path>
45
+ ```
46
+
47
+ Requires `JIRA_SERVER`, `JIRA_LOGIN`, and `JIRA_API_TOKEN` in the environment (same contract as `jira-evidence`). If those are not set the helper exits with code 2 and a clear remediation message — record the URL only and continue.
48
+
49
+ After download, branch on `mimeType`:
50
+ - `image/*` — pass the local path to image-aware downstream tools
51
+ - `text/*`, `application/json`, `application/xml`, `application/x-yaml` — read inline as text
52
+ - `application/pdf` — extract text via downstream tooling if needed
53
+ - everything else — record path only; do not attempt to inline binary content
38
54
 
39
55
  ### Comments
40
56
 
@@ -121,7 +137,7 @@ Produce a single structured output that the caller can pass verbatim to downstre
121
137
  <chronological comments, flagged items called out>
122
138
 
123
139
  ### Attachments
124
- <list>
140
+ <list with id, filename, mimeType, size, content URL — note any that were downloaded and their local paths>
125
141
 
126
142
  ## Remote Links
127
143
  ### Pull Requests (<count>)
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env bash
2
+ # download-attachment.sh — Download a JIRA attachment to a local file.
3
+ #
4
+ # Usage:
5
+ # bash download-attachment.sh <ATTACHMENT_ID_OR_URL> <OUTPUT_PATH>
6
+ #
7
+ # Why this helper exists:
8
+ # The Atlassian MCP server (mcp__atlassian__*) returns attachment metadata
9
+ # (id, filename, mimeType, size, content URL) on getJiraIssue but provides
10
+ # no tool to fetch the binary content. This script closes the gap by
11
+ # hitting the Jira REST API directly with Basic auth, mirroring the
12
+ # env-var contract already used by jira-evidence/scripts/post-evidence.sh.
13
+ #
14
+ # See https://jira.atlassian.com/browse/JRACLOUD-97830 for the upstream
15
+ # gap; remove this helper once Atlassian ships a download tool in the MCP.
16
+ #
17
+ # Required env vars:
18
+ # JIRA_SERVER - https://<your-tenant>.atlassian.net
19
+ # JIRA_LOGIN - login email
20
+ # JIRA_API_TOKEN - API token (https://id.atlassian.com/manage-profile/security/api-tokens)
21
+ #
22
+ # Exit codes:
23
+ # 0 success
24
+ # 1 download failed (HTTP error)
25
+ # 2 missing required env var
26
+ # 3 invalid arguments
27
+
28
+ set -euo pipefail
29
+
30
+ if [[ $# -lt 2 ]]; then
31
+ echo "Usage: download-attachment.sh <ATTACHMENT_ID_OR_URL> <OUTPUT_PATH>" >&2
32
+ exit 3
33
+ fi
34
+ ID_OR_URL="$1"
35
+ OUTPUT_PATH="$2"
36
+
37
+ # Resolve credentials: prefer env, fall back to jira-cli config for server/login.
38
+ JIRA_CONFIG="${HOME}/.config/.jira/.config.yml"
39
+ if [[ -z "${JIRA_SERVER:-}" && -f "$JIRA_CONFIG" ]]; then
40
+ JIRA_SERVER=$(grep '^server:' "$JIRA_CONFIG" | awk '{print $2}')
41
+ fi
42
+ if [[ -z "${JIRA_LOGIN:-}" && -f "$JIRA_CONFIG" ]]; then
43
+ JIRA_LOGIN=$(grep '^login:' "$JIRA_CONFIG" | awk '{print $2}')
44
+ fi
45
+
46
+ for VAR in JIRA_SERVER JIRA_LOGIN JIRA_API_TOKEN; do
47
+ if [[ -z "${!VAR:-}" ]]; then
48
+ echo "ERROR: $VAR is not set." >&2
49
+ echo "Required env vars: JIRA_SERVER, JIRA_LOGIN, JIRA_API_TOKEN." >&2
50
+ echo "Generate an API token: https://id.atlassian.com/manage-profile/security/api-tokens" >&2
51
+ exit 2
52
+ fi
53
+ done
54
+
55
+ OUTPUT_DIR=$(dirname "$OUTPUT_PATH")
56
+ if [[ ! -d "$OUTPUT_DIR" ]]; then
57
+ echo "ERROR: Output directory does not exist: $OUTPUT_DIR" >&2
58
+ exit 3
59
+ fi
60
+
61
+ if [[ "$ID_OR_URL" == http*://* ]]; then
62
+ ATTACHMENT_URL="$ID_OR_URL"
63
+ else
64
+ ATTACHMENT_URL="${JIRA_SERVER%/}/rest/api/3/attachment/content/$ID_OR_URL"
65
+ fi
66
+
67
+ JIRA_AUTH=$(printf '%s' "$JIRA_LOGIN:$JIRA_API_TOKEN" | base64 | tr -d '\n')
68
+
69
+ # Atlassian responds 302 to a signed URL on media.atlassian.com that has its
70
+ # own auth and rejects Basic. Two-step: capture Location, then GET unauthed.
71
+ HEADERS_FILE=$(mktemp)
72
+ trap 'rm -f "$HEADERS_FILE"' EXIT
73
+
74
+ HTTP_CODE=$(curl -sS -o /dev/null -w '%{http_code}' \
75
+ --max-redirs 0 \
76
+ -D "$HEADERS_FILE" \
77
+ -H "Authorization: Basic $JIRA_AUTH" \
78
+ -H "Accept: */*" \
79
+ "$ATTACHMENT_URL" || true)
80
+
81
+ case "$HTTP_CODE" in
82
+ 302|303|307)
83
+ SIGNED_URL=$(awk '/^[Ll]ocation:/{sub(/^[Ll]ocation:[ \t]*/,""); sub(/\r$/,""); print; exit}' "$HEADERS_FILE")
84
+ if [[ -z "$SIGNED_URL" ]]; then
85
+ echo "ERROR: Got HTTP $HTTP_CODE but no Location header in response." >&2
86
+ exit 1
87
+ fi
88
+ curl -sSf -o "$OUTPUT_PATH" "$SIGNED_URL" || { echo "ERROR: Download from signed URL failed." >&2; exit 1; }
89
+ ;;
90
+ 200)
91
+ curl -sSf -o "$OUTPUT_PATH" \
92
+ -H "Authorization: Basic $JIRA_AUTH" \
93
+ -H "Accept: */*" \
94
+ "$ATTACHMENT_URL" || { echo "ERROR: Direct download from $ATTACHMENT_URL failed." >&2; exit 1; }
95
+ ;;
96
+ 401|403)
97
+ echo "ERROR: Authentication failed (HTTP $HTTP_CODE). Verify JIRA_LOGIN and JIRA_API_TOKEN." >&2
98
+ exit 1
99
+ ;;
100
+ 404)
101
+ echo "ERROR: Attachment not found at $ATTACHMENT_URL (HTTP 404). Verify the ID and your access." >&2
102
+ exit 1
103
+ ;;
104
+ *)
105
+ echo "ERROR: Unexpected HTTP $HTTP_CODE from $ATTACHMENT_URL" >&2
106
+ exit 1
107
+ ;;
108
+ esac
109
+
110
+ echo " ✓ Downloaded -> $OUTPUT_PATH"
@@ -24,3 +24,26 @@ See the `config-resolution` rule for configuration and dispatch table.
24
24
 
25
25
  - The GitHub `pr-assets` release lives on the implementation repo (the one with the PR), regardless of which tracker hosts the ticket/issue. All vendor skills upload there.
26
26
  - Never post evidence to a different ticket than the one named — `$ARGUMENTS` is the source of truth.
27
+
28
+ ## UI Evidence Checklist (when work is UI-visible)
29
+
30
+ Apply this when authoring `evidence/comment.md` (and `evidence/comment.txt` for JIRA wiki markup) for any ticket whose work touches a user-facing surface — bug fix, new component, new flow, UX polish, design implementation. Skip the checklist for non-UI work (API, infra, migrations, etc.); the plain-text evidence path is fine there.
31
+
32
+ The checklist is tracker-agnostic — the same shape works on JIRA, GitHub Issues, and Linear. Vendor skills only own the post/transition mechanics; the comment body is your responsibility.
33
+
34
+ 1. **AI disclosure at the top.** Lead with "Update from Claude (AI agent, not a human)" and address the reporter / QA / PM by name.
35
+ 2. **Own any prior mistake explicitly.** If an earlier triage or build pass got something wrong, say so up front. Don't bury it.
36
+ 3. **Numbered step-by-step walk** of what you actually did in the browser/app, in plain language a non-engineer can follow:
37
+ - Exact env (URL, viewport size — e.g. `402×874` for an iOS-sized mobile flow)
38
+ - Login creds shape — e.g. `(000) 000-0002` + OTP `555555`
39
+ - Exact record/player name, exact button labels as they appear on screen
40
+ - Full happy-path **and** any non-obvious edge state worth showing (empty state, loading, post-completion)
41
+ 4. **One screenshot per step**, captured live via Playwright MCP at the matching viewport. Upload via `gh release upload pr-assets <files> --clobber` and reference each one as a **plain URL** in the comment body — *not* `![alt](url)` markdown embeds. Plain URLs render as smartlinks/auto-embeds across all three trackers and stay individually viewable; markdown embeds collapse on JIRA when there are ≥2.
42
+ 5. **"What this shows" section.** Tailor to ticket type:
43
+ - **Bug repro:** state plainly whether the bug reproduces or not, and the most likely 1–2 reasons their retest still failed (different env, native app vs. web, stuck backend row, etc.).
44
+ - **Feature/UX completion:** state plainly which acceptance criteria each screenshot covers, and call out any deferred or out-of-scope surface explicitly so QA/PM doesn't have to infer.
45
+ 6. **"What would help me confirm" (bug) / "How to QA" (feature) section.** Concrete actionable retest steps with the exact selection criteria (e.g., "pick a record whose Status column shows `—`, not `Processing` or `Pending Review`").
46
+ 7. **Explicit invitation to be corrected.** End with a line like *"If any of the steps I listed are different from what you expected / actually did, please tell me explicitly which step I got wrong."* Non-optional — small differences (which record, which device, exact tap order, expected behavior) change everything, and naming the door open short-circuits ticket bounce-loops.
47
+ 8. **Workflow transition** is the vendor skill's job, not yours — it'll move the ticket per the configured tracker (JIRA: Reassign to reporter for bug repro / move to Awaiting QA for feature; GitHub: relabel `status:code-review` or equivalent; Linear: equivalent state). You don't transition manually.
48
+
49
+ **Why this format:** It (a) gives the reporter a frame-by-frame they can compare against, (b) avoids the JIRA image-collapse failure mode while still working everywhere else, (c) names the most plausible discrepancies up front so the loop short-circuits, (d) explicitly opens the door to being corrected so tickets don't bounce on assumed alignment. The same mechanics that resolve a stuck bug ticket also give QA an unambiguous handoff for a freshly-built feature.
@@ -29,7 +29,7 @@ Execute the **Verify** flow as defined in the `intent-routing` rule (loaded via
29
29
  4. **Review loop** — handle CodeRabbit / human review comments via `lisa:pull-request-review`
30
30
  5. **Merge** when CI is green
31
31
  6. **Remote verification** — invoke the `lisa:monitor` skill against the target environment to confirm the deploy actually works (health endpoints, recent logs/errors, Validation Journey replay if defined). If remote verification surfaces a behavioral gap that the existing codified tests do not guard, invoke `codify-verification` to add coverage and open a follow-up PR.
32
- 7. **Evidence** — post results to the originating ticket via `lisa:tracker-evidence` (vendor-neutral; dispatches to `lisa:jira-evidence`, `lisa:github-evidence`, or `lisa:linear-evidence` per `.lisa.config.json` `tracker`), including the list of codified tests added on this branch.
32
+ 7. **Evidence** — post results to the originating ticket via `lisa:tracker-evidence` (vendor-neutral; dispatches to `lisa:jira-evidence`, `lisa:github-evidence`, or `lisa:linear-evidence` per `.lisa.config.json` `tracker`), including the list of codified tests added on this branch. **If the work is UI-visible** (any verification step ran in a browser, or the change touches a user-facing surface), author `evidence/comment.md` per the **UI Evidence Checklist** in `lisa:tracker-evidence` — numbered live-session steps, one Playwright-MCP screenshot per step uploaded to the GitHub `pr-assets` release as plain URLs, and an explicit invitation to be corrected.
33
33
 
34
34
  The rule contains the canonical step sequence. Change it there, propagate everywhere.
35
35