# Lisa Tracker Evidence

> Vendor-neutral wrapper for posting verification evidence. Reads the required `tracker` from .lisa.config.json and dispatches to lisa-jira-evidence, lisa-github-evidence, or lisa-linear-evidence. Uploads evidence to the GitHub `pr-assets` release, updates the PR description, posts a comment on the originating ticket/issue, and leaves workflow transitions to the tracker-specific lifecycle owner.

- Skill: `codyswanngt/lisa-tracker-evidence` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add codyswanngt/lisa-tracker-evidence`
- Raw SKILL.md: https://api.skillmd.com/api/skills/codyswanngt/lisa-tracker-evidence/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: codyswanngt (https://skillmd.com/u/codyswanngt)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/codyswanngt/lisa-tracker-evidence

---


# Tracker Evidence: $ARGUMENTS

Thin dispatcher. Resolves the configured destination tracker and delegates to the matching vendor evidence skill.

See the `config-resolution` rule for configuration and dispatch table.

## Workflow

1. Resolve tracker config (same logic as `lisa-tracker-write`).
2. Missing / empty → stop and report `"No tracker configured in .lisa.config.json. Run /lisa:setup:jira, /lisa:setup:github, or /lisa:setup:linear first."`
3. Before dispatching, update the generated evidence artifact through `lisa-usage-accounting` so the comment body / PR evidence section carries a direct `lisa-verify` usage entry in the canonical `## Lisa Usage` section. If the originating work item's parentage or child refs are already known, prefer `record_and_rollup` so ancestor totals refresh in the same write; otherwise still write the direct entry, and if trustworthy runtime usage is unavailable, write `source: unavailable` with nullable token/cost fields instead of skipping the row.
4. Dispatch:
   - `jira` → invoke `lisa-jira-evidence` with `$ARGUMENTS` verbatim. Arg shape: `<TICKET_ID> <EVIDENCE_DIR> <PR_NUMBER>`.
   - `github` → invoke `lisa-github-evidence` with `$ARGUMENTS` verbatim. Arg shape: `<ISSUE_REF> <EVIDENCE_DIR> <PR_NUMBER>` where `ISSUE_REF` is `org/repo#<number>` or a GitHub issue URL.
   - `linear` → invoke `lisa-linear-evidence` with `$ARGUMENTS` verbatim. Arg shape: `<IDENTIFIER> <EVIDENCE_DIR>` where `IDENTIFIER` is a Linear Issue identifier (e.g., `ENG-123`).
   - Anything else → stop and report `"Unknown tracker '<value>' in .lisa.config.json. Expected 'jira', 'github', or 'linear'."`
5. Pass through the vendor skill's output.

## Rules

- 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.
- Never post evidence to a different ticket than the one named — `$ARGUMENTS` is the source of truth.
- Never invent a verify-specific usage footer. Evidence artifact usage must flow through `lisa-usage-accounting`, preserve the canonical `## Lisa Usage` section, and surface `source: unavailable` explicitly when the runtime cannot provide trustworthy numbers.
- **Evidence-manifest gate (leaf work units).** Before dispatching to a vendor skill that transitions the ticket, confirm `EVIDENCE_DIR` contains a non-empty artifact **of the declared type** for every typed `[EVIDENCE: <artifact-type>: <name>]` marker declared in the ticket's Validation Journey — a `screenshot` marker needs an actual image, an `http-transcript` marker needs the request + response text, a `perf-trace` marker needs measured numbers; a prose claim satisfies nothing. If any declared marker has no captured artifact, an empty one, or one whose content/extension does not match its declared type, stop and report the offending markers by name instead of posting — a leaf work unit (Bug / Task / Sub-task / Improvement) may not advance to its review/Done state with an unsatisfied manifest (see the "Per-Work-Unit Evidence Contract" in the `verification` rule). Epics / Stories / Spikes, and leaf units without a Validation Journey, are exempt.
- **Claim↔boundary binding (S14 upgrade).** Satisfying the manifest by *type* is not enough: each `[EVIDENCE: <artifact-type>: <name>]` marker is also cited for a **claim**, and the marker's artifact type must **reach the boundary that claim declares** per the `claim-evidence-mapping` rule's taxonomy. A `browser` claim (user-visible UI behavior) is reached by `screenshot` / `recording` and never by a unit `test-run-log`; an `http-api` claim needs an `http-transcript`; a `deploy-health` claim needs a `deploy-log` and no pre-deploy artifact. On a mismatch, report the offending marker **by name** together with the claim, its boundary, and the **required evidence kinds** for that boundary — e.g. `[EVIDENCE: test-run-log: unit-suite] cited for claim AC-2 [boundary browser] — required evidence kinds: screenshot, recording`. Swapping in a marker of a reaching kind with a real captured artifact satisfies the gate. **Advisory-first:** until `verification.gate.enforceBoundaries` is `true` in `.lisa.config.json` (the same ratchet flag the Stop-hook gate reads, default `false`), a boundary mismatch is reported to the operator but does not block the post; once ratcheted on it refuses the post exactly like a missing or wrong-type artifact. Missing/empty/wrong-type artifacts keep refusing the post regardless of the flag.
- **The "Not established" section is required.** Before posting, confirm `evidence/comment.md` (and `comment.txt` where the vendor uses it) contains a `## Not established` heading and that the verdict carries `not_established_reviewed: true`. The heading is **never omitted and never blank**: with nothing outstanding it still renders `None outstanding — reviewed`; otherwise it lists, in plain operator language, each thing the verification did not prove — boundaries not exercised, environments not tested, behavior consciously out of scope. A comment with no such heading, a heading with nothing under it, or a verdict whose `not_established_reviewed` flag is absent is **refused**: stop and report the missing Not-established review instead of posting. (The list may be empty; the flag may never be omitted.) Definition and exemplars live in the `claim-evidence-mapping` rule; this generalizes `lisa-improve-harness`'s required, never-empty `Known limits` field.
- **Artifact identity is required, with values (S14 extension).** Before posting, confirm the comment body carries a `## Artifact identity` heading populated with **values, not placeholders**: the `repository`, the `head_sha` the verification observed, the `environment`, and for each committed artifact its `sha256` digest and `captured_at`. Then check both identity failures. **`artifact_mismatch`** — an evidence entry whose recorded `artifact_head_sha` differs from the verdict's `artifact.head_sha`: refuse the post and report the offending evidence id together with **both SHAs** (the one the artifact was captured at and the one the verdict claims), e.g. `EV-2 captured at 4f1c9ab but artifact.head_sha is 9de0c31`. **`evidence_digest_mismatch`** — recompute the `sha256` of each committed evidence file on read; if the bytes no longer match the recorded digest (or the file is absent), stop and report the evidence id by name. Never summarize either as "verification failed" — name the field, the ids, and both SHAs so a non-engineer can read it at the gate. **Advisory-first:** until `verification.gate.enforceBoundaries` is `true` in `.lisa.config.json`, an identity failure is reported to the operator but does not block the post; once ratcheted on it refuses the post exactly like a missing artifact. Definition: the `claim-evidence-mapping` rule.
- **Merge-race reconciliation (at completion, not at post).** The evidence's pinned `head_sha` is reconciled against the merged head using the ancestry + deploy-run definition of "what shipped" that `lisa-drive-pr-to-merge` already owns — cite that skill, never re-implement or restate its checks here. Pre-merge evidence counts for the merge commit only when its head is a parent of the merge, ancestry alone never justifies reporting shipped, and on a mismatch verification re-runs against the merged head before completion is declared.
- **Evidence references are not manifest entries.** Extract obligations using the exact `[EVIDENCE:` prefix (and the legacy local `[SCREENSHOT:` form). Exclude both the canonical `[EVIDENCE-REF: <work-item-ref> | <artifact-type>: <kebab-case-name>]` and the Lisa 2.223.0 legacy alias `[EVIDENCE-REF: <tracker-ref>: <artifact-type>: <kebab-case-name>]` from artifact lookup, missing-artifact reporting, and duplicate-name checks: either belongs to another work item and cannot satisfy this item's S14 gate. A runtime-changing leaf with references but no local claiming marker must be rejected before dispatch.

## UI Evidence Checklist (when work is UI-visible)

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.

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.

1. **AI disclosure at the top.** Lead with "Update from Claude (AI agent, not a human)" and address the reporter / QA / PM by name.
2. **Own any prior mistake explicitly.** If an earlier triage or build pass got something wrong, say so up front. Don't bury it.
3. **Numbered step-by-step walk** of what you actually did in the browser/app, in plain language a non-engineer can follow:
   - Exact env (URL, viewport size — e.g. `402×874` for an iOS-sized mobile flow)
   - Login creds shape — e.g. `(000) 000-0002` + OTP `555555`
   - Exact record/player name, exact button labels as they appear on screen
   - Full happy-path **and** any non-obvious edge state worth showing (empty state, loading, post-completion)
4. **One screenshot per step**, captured live through the interactive browser controller at the matching viewport. The controller may be an in-app Browser/Chrome tool, interactive Playwright control, CDP, computer use, or an equivalent; do not require one named backend. 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.
5. **"What this shows" section.** Tailor to ticket type:
   - **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.).
   - **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.
6. **"Artifact identity" and "Not established" sections (both required).** Right after "What this shows":
   - `## Artifact identity` — what the evidence was collected against, as **values, not placeholders**: the repository, the `head_sha` the verification observed, the `environment`, and per artifact its `sha256` digest and `captured_at`. A heading rendered with `<unknown>` in place of a SHA is not identity.
   - `## Not established` — **never omitted, never blank.** List in plain language what this verification did *not* prove: boundaries not exercised (e.g. "the persisted order row was never queried"), environments not tested (e.g. "checked on desktop Chrome only — not mobile Safari"), and behavior consciously out of scope (e.g. "refunds were not touched or tested"). Name the specific thing, not a category. With nothing outstanding, the heading still renders a single line: `None outstanding — reviewed`. Never state a quality check as proof of behavior — "unit tests pass" belongs here as a limit, not above as evidence.
7. **"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`").
8. **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.
9. **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 the configured review status when one exists, otherwise leave it in `claimed`; GitHub: direct `claimed` → configured `done` after a successful build; Linear: equivalent state). You don't transition manually.

**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.

