# Issue Workflow

> XnaFiddle's process for turning a GitHub issue into a merged PR — read the issue + its comments, load matching skills, invoke the right agent, branch, build-verify, and open the PR immediately. Load when the user references a GitHub issue (a URL or

- Skill: `vchelaru/issue-workflow` (Agent Skill)
- Install (CLI): `npx skillmds@latest add vchelaru/issue-workflow`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vchelaru/issue-workflow/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: vchelaru (https://skillmd.com/u/vchelaru)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vchelaru/issue-workflow

---


# Issue Workflow

The flow when the user points at a GitHub issue (URL or `#N`) and asks to fix or implement it.
This grows organically — add a step or a gotcha when one actually bites; keep it lean.

## 1. Read the issue AND its comments first

Run BOTH `gh issue view <n>` (title + body) and `gh issue view <n> --comments`. Plain `view`
omits the discussion thread, and comments routinely narrow scope, add files to touch, or settle
open questions raised in the body. Read both before touching code.

## 2. Load matching skills, then invoke the agent

- Load every skill whose trigger matches the area the issue touches (see `CLAUDE.md` → *Skills*).
  If none fit, **say so briefly** and continue — don't silently skip the check.
- Announce and invoke the matching agent from `.claude/agents/` ("Invoking coder agent…") and
  re-read its file at the start of the task; long sessions drift (see `CLAUDE.md` → *Agent Workflow*).

## 3. Branch — never commit issue work to `main`

Create a branch off `main` first (`feat/…`, `fix/…`).

## 4. Build to verify

`dotnet build XnaFiddle.BlazorGL/XnaFiddle.BlazorGL.csproj`

**Stale-submodule gotcha:** the build can fail with dozens of
`CS0579: Duplicate '…AssemblyInfo' attribute` errors, all pathed under `Submodules/KniSB/**`.
These are leftover `obj`/`bin` from earlier multi-TFM builds (net45 / netstandard2.0) being
globbed into the net10.0 build — **not** your change. Clear them and rebuild:

```
find Submodules/KniSB -type d \( -name obj -o -name bin \) -prune -exec rm -rf {} +
```

This removes only generated artifacts; the submodule pointer and tracked source are untouched
(it also cleans the dirty `M Submodules/KniSB` working-tree state those artifacts cause).

## 5. Set up manual testing — prioritize testing and speed

If the change needs manual testing in the running app (most UI/behavior changes do), get the
user testing as fast as possible:

1. **Open the solution first**, before writing anything: `Start-Process "XnaFiddle.sln"` (PowerShell).
   Launch it up front so Visual Studio loads in the background while you write the steps — don't
   make the user wait on your prose before the IDE is even opening.
   **Exception — mobile testing:** if the fix must be verified on a phone (touch UI, mobile layout,
   anything Android/iOS-specific), do **not** open the `.sln`, and do **not** suggest USB /
   `chrome://inspect` debugging — that route was whack-a-mole and the user abandoned it. Instead
   have them serve over the LAN and hit it from the phone: `dotnet run --project XnaFiddle.BlazorGL
   --urls "http://0.0.0.0:60441"`, then open `http://<machine-LAN-ip>:60441` on the phone (same
   Wi-Fi). Use plain **HTTP** (avoids the dev-cert-trust problem); it's fine unless the specific
   test needs a secure context (clipboard / CacheStorage). Find the LAN IP with `Get-NetIPAddress
   -AddressFamily IPv4` (the Wi-Fi one, not the `172.x` WSL vEthernet). The user has a **permanent
   Windows Firewall rule** for inbound 60441, so the phone connects without any setup — do **not**
   mention firewall, connection troubleshooting, or Incognito in the handoff; that's all handled on
   their end. Just give them the URL and the marker color (below).
2. **Then write concise, numbered manual steps** — what to run, what to click, and what correct
   behavior looks like (and the failure mode the fix addresses, so the user knows what they're
   confirming).

Skip this step only when the change is genuinely untestable by hand (pure refactor, build-only,
or covered entirely by unit tests) — say so briefly instead.

### Build marker — prove the phone is running the new build (not a stale cache)

Over plain HTTP the phone caches `index.html` **and** the compiled DLLs, and mobile Chrome has no
easy hard-reload — so a normal reload can silently serve the *previous* build and make a working
fix look broken. We've burned test cycles on exactly this. So on **every build handed off for
mobile testing**, bump a **deterministic** visual marker and tell the user the value up front:

- The marker is the **main splitter color**, driven by `var SPLITTER_COLOR` in `index.html`
  (painted onto `#splitter` by `applyLayout`). It lives in the **JS** on purpose — that's the
  cache-prone file — so a stale page shows the *previous* color.
- **The ordered palette** (never reuse the immediately-previous one; the user must be able to name
  the color at a glance): orange `#e8830c` → magenta `#d6336c` → green `#2f9e44` → purple `#7048e8`
  → teal `#0ca678` → red `#e03131` → amber `#f59f00` → (wrap). Advancing is a *pick*, not randomness
  — state the name **and** hex in your reply so the user confirms the served build.
- **"Last used" is recorded right here, not recovered from git.** Read the `LAST MARKER` line just
  below, advance to the *next* palette entry after it, and — as part of the same commit that bumps
  `SPLITTER_COLOR` — update that line to the color you just picked. This is the source of truth:

      LAST MARKER: purple #7048e8

  Why a committed pointer line and not a git-history search: the shipped `SPLITTER_COLOR` is
  bump-then-reset (magenta on the branch, back to `#007acc` before merge), so its **net diff is
  zero** — a squash-merge would collapse it and erase every trace of which color was used, and even
  a pickaxe (`git log -S/-G`) only works while the un-squashed branch commits stay reachable. This
  pointer line has a **persistent net change** (magenta → green), so it survives *any* merge
  strategy and is readable at a glance with no `git log` archaeology. Keep the two in lockstep: the
  same commit bumps `SPLITTER_COLOR` *and* this line.
- **The color is the only thing to tell the user in the handoff.** State the name **and** hex; that
  is enough for them to confirm the served build is fresh (wrong color = stale cache, not a failed
  fix). They manage their own clean-fetch flow — don't instruct them on Incognito or reloading.
- **Before the PR merges, reset `SPLITTER_COLOR` to the canonical accent `#007acc`** so `main`
  doesn't ship a random marker color.

## 6. Open the PR as soon as the work is finished

Don't wait for manual-test sign-off — CI runs in parallel with the user's testing. Commit →
`git push -u origin <branch>` → `gh pr create`. Put `Closes #<n>` in the PR body so the merge
auto-closes the issue. This is the standing workflow; open the PR without per-task approval.

## 7. Bundle incidental skill-file improvements

Skill tweaks made while working the issue go in the **same** PR, unless something obvious says
otherwise. These small increments are how the skills — including this one — grow.

## 8. Report the PR URL back to the user.

