Skip to content

LT-22723: Add evidence framework for screenshots in PRs and Jira - #1099

Closed
johnml1135 wants to merge 3 commits into
jira-issue-skillfrom
jira-issue-evidence
Closed

LT-22723: Add evidence framework for screenshots in PRs and Jira#1099
johnml1135 wants to merge 3 commits into
jira-issue-skillfrom
jira-issue-evidence

Conversation

@johnml1135

@johnml1135 johnml1135 commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Draft on purpose — see "why this is a draft" below. Stacked on #1098; review that first.

A visible change should ship with a picture. The repo already does the hard half — headless Skia capture for Avalonia, MCP capture for WinForms, an Output/ManualEvidence/<TICKET>/ convention — but nothing trimmed an image, captioned it, or carried it into a PR body or a ticket. This adds that last mile, and a Jira attachment script to go with it.

Start here: .claude/references/evidence.md. Everything else points at it.

Where to look:

  • The rule the rest hangs on: the test is the evidence, the screenshot is the courtesy. A control-level headless capture is not a screenshot of the product. Every image now states which it is, because a caption that omits it lets a reader believe a feature shipped when nothing writes the code path at runtime yet.
  • Three publish routes, tried in order and reported: native gh --attach, gh image where a session cookie is reachable, and — when neither is available — handing the file to the author to drag in. Images are never committed to the repo, and no side branch is created to host them: that puts binaries in history permanently to solve a problem lasting one review.
  • jira_add_attachment drives client.session directly because AtlassianClient.post sends JSON only, while multipart needs the XSRF header and Content-Type cleared. It is the one piece of executable code in either branch.
  • The permission gate: a screenshot of a live project is a data disclosure exactly as a project file is. Agent-captured WinForms evidence comes from throwaway projects only.
  • No new dependency. gh image was installed, tested and removed. It needs a full-account GitHub session cookie, so it is documented as an optional route and never required.

Deliberately not here: nothing for CI. The official --attach flag excludes Actions tokens, so an unattended run has no upload path and is told to say so rather than invent one.

Verification: jira_add_attachment is proven end to end — LT-22723 carries attachment 154621, a 6,895-byte synthetic PNG that Jira accepted and generated a thumbnail for. Its validation paths return correct errors for a missing file, an empty file and a missing issue key. gitlint clean. No build.ps1 or test.ps1 run: one standalone Python module, no compiled code.

Next: hold this until gh --attach ships, or say so and I will undraft it now — it does not depend on the release.


Why this is a draft

drogers0/gh-image#56 tracks GitHub shipping native image upload in the gh CLI (github/roadmap#1324): a repeatable --attach flag on six commands, preview built, 8 PRs open, targeted for the end of August 2026. Locally gh 2.83.1 has no --attach on pr create, pr comment or issue create.

The branch does not depend on that landing — the probe falls through to the other two routes — so the draft status is a preference about when the documentation reads correctly, not a blocker. Two constraints on the official flag are worth knowing now: it needs write access, and it excludes Actions tokens, so CI can never use it.

Decisions, and why

Jira gets native attachments; GitHub gets a probe. Jira has a real attachment API, so a 30-line script solves it permanently and the file outlives any branch. GitHub has no token-authenticated attachment endpoint at all, which is why three routes exist instead of one.

gh image is documented, not adopted. It works by driving the web UI's own upload flow with a user_session cookie — full account access, bypassing 2FA, and dependent on undocumented endpoints (/upload/policies/assets). Fine as a route a developer opts into; wrong as a dependency a team skill requires. The skill also forbids running gh image extract-token in an agent session, because it prints that credential to stdout and stdout becomes conversation context.

Curation is a named step, not an afterthought. The trigger was a real capture: 520×180 with content in the top quarter, which at thumbnail size — the size it is first seen at in both GitHub and Jira — reads as an empty box. Trim to content, caption with what to look at, label provenance.

Evidence

The attachment path is genuinely exercised, not merely compiled. LT-22723 carries the upload; the response returned a content URL and a generated thumbnail URL, which is Jira confirming it accepted the bytes as an image.

The three routes were tested, not assumed. gh 2.83.1 was checked for --attach on three commands (absent). gh image v1.3.0 was installed and gh image check-token returned session token is empty, consistent with Chrome 127+ App-Bound Encryption defeating cookie extraction on Windows. The extension was then removed; nothing on this branch requires it.

An earlier draft proposed a never-merged orphan evidence branch hosting screenshots behind sha-pinned raw URLs. It was cut before review: speculative, unbuilt, and it traded permanent repo weight for a one-review problem.


This change is Reviewable

@johnml1135
johnml1135 force-pushed the jira-issue-evidence branch 2 times, most recently from 02caff5 to 51079cb Compare August 21, 2026 14:58
A visible change should ship with a picture, and the repo already has
the hard half: headless Skia capture for Avalonia, MCP capture for
WinForms, and an Output/ManualEvidence naming convention. What was
missing is the last mile -- trimming, captioning, provenance labelling,
and any route at all from a PNG to a PR body or a ticket.

The rule evidence.md turns on is that the test is the evidence and the
screenshot is the courtesy. A control-level headless capture is not a
screenshot of the product, and every image now says which it is.

Publishing probes three routes and reports the one it used: native gh
attach once it ships, gh image where a session cookie is reachable, and
an orphan evidence branch with sha-pinned raw URLs otherwise. Only the
third works under an Actions token, which is why it stays.

jira_add_attachment uploads to Jira. It drives client.session directly
because AtlassianClient.post sends JSON only, while multipart needs the
XSRF header and no Content-Type. Its validation paths are exercised; the
upload path has not yet been run against a live issue.

A screenshot of a live project is a data disclosure exactly as a project
file is, so the permission gate covers both.

Co-Authored-By: Claude Opus 5 <[email protected]>
johnml1135 and others added 2 commits August 21, 2026 11:41
evidence.md sits in .claude/references/ and pointed at
fieldworks-avalonia-ui/references/visual-snapshot-testing.md as if it
were a sibling. The file is under .claude/skills/, so the pointer
resolved from nowhere. Made absolute from the repo root.

Co-Authored-By: Claude Opus 5 <[email protected]>
The third upload route proposed creating a never-merged orphan branch to
host screenshots and referencing them by sha-pinned raw URL. It was
speculative, nothing had been built, and it solved a problem lasting one
review by putting binaries in history permanently.

Route three is now the honest one: when no upload path is available, say
which was tried and hand the file to the author to drag in. The skill
also states plainly that images are not committed to the repository and
no side branch is created to host them.

Refs LT-22723
@johnml1135

Copy link
Copy Markdown
Contributor Author

Consolidated into #1100, which now targets main and carries all eleven commits from this branch, #1098 and #1102. Nothing is lost -- the commit boundaries survive in history. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant