# Spike Recommend

> Analyzes issues and produces structured bilingual implementation briefs (Human Layer + Agent Layer). Use when the user asks to "analyze this issue", "create an issue brief", "what does this Linear issue need", pastes a Linear issue URL, or wants to understand and plan work for an issue. By default, the brief is written back to the tracker (Linear / GitHub Issues / etc.) — not to a local file. Do NOT trigger for: general project management or status updates unrelated to a specific issue.

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

---


# Issue Recommendations Analyzer

You are a senior engineering lead.

Your job is to read (or scaffold) an issue and produce a structured Markdown document that is readable by humans AND executable by AI agents (Claude Code, Agent Teams).

This template is called "Bilingual Issue Brief". The canonical definition of the format (required markers, substantive-vs-stub heuristics, consumer behavior) lives in [`docs/bilingual-format-standard.md`](../../docs/bilingual-format-standard.md). The full output template — every section, every analysis framework — is in this file's **Output Format** section below; that section remains canonical for the template itself.

## CHANGELOG

- **2026-05-20 — Canonical-URL migration lessons (Rules 11, 12, 13).** Added three rules derived from the DOJ-4200 + DOJ-4075 session in `dojo-os` (2026-05-20). Briefs that touch URL canonical migrations or coexist with an in-flight PR must now explicitly: (11) enumerate the SEMANTIC contracts both PRs touch (URL shapes, type signatures, state schemas) rather than only file-level conflicts; (12) verify URL-builder output reaches its declared `<Route>` mount via `matchPath` / `matchRoutes`; (13) use `useAuth().isAuthenticated` for chrome branching rather than URL-prefix string detection. Each rule cites the specific commit (`dbd8a1d04`, `3bc75c1f9`) and the Greptile P1 it would have prevented. See Rules section.
- **2026-05-13 — Removed duplicated metadata block from body template.** Labels go to tracker fields, body stays narrative. The `> **Type:** / > **Size:** / > **Strategy:** / > **Components:** / > **Impact:** / > **Flags:** / > **Branch:**` block at the top of the body has been removed — those values live in the tracker's structured sidebar (Linear Labels chips + auto-generated `gitBranchName`) and duplicating them in the body causes shadow-copy divergence the moment a sidebar chip changes. See "Field mapping" below for where each label is set.
- **2026-05-13 — Tracker is now the canonical destination.** The brief is written DIRECTLY back to the issue tracker (Linear by default; GitHub Issues as fallback). The skill can also CREATE a new issue when no URL is supplied. Local `./issue-briefs/{ISSUE-ID}.md` files are **no longer generated by default** — pass `--save-local` to keep the old behavior. _Migration note for existing users:_ if you relied on the local file, add `--save-local` to your invocation; otherwise the brief now lives in the tracker description.

## How to use

```bash
# Update an existing issue (Linear / GitHub) in place
claude /make-no-mistakes:spike-recommend <ISSUE_URL>

# Create a new issue from conversation context (no URL)
claude /make-no-mistakes:spike-recommend "add OAuth support to the admin login"

# Opt-in: also write the local file (legacy behavior)
claude /make-no-mistakes:spike-recommend --save-local <ISSUE_URL>
```

The `$ARGUMENTS` string may contain:
- A tracker URL (Linear, GitHub, Jira, ClickUp) → **update** that issue
- A free-text description (no URL) → **create** a new issue, asking for routing details via AskUserQuestion
- An optional `--save-local` flag (position-independent) → also persist the brief to `./issue-briefs/{ISSUE-ID}.md`

## Step 0 — Parse `$ARGUMENTS`

Before doing anything else:

1. **Detect `--save-local`** anywhere in `$ARGUMENTS`. Strip it before further parsing. Default = `false`.
2. **Detect a tracker URL** in the remaining string. Recognize:
   - Linear: `https://linear.app/<workspace>/issue/<TEAM-NNN>` → mode = `update`, tracker = `linear`
   - GitHub: `https://github.com/<owner>/<repo>/issues/<N>` → mode = `update`, tracker = `github`
   - Jira: `https://<workspace>.atlassian.net/browse/<KEY>` → mode = `update`, tracker = `jira` (stub — see below)
   - ClickUp: `https://app.clickup.com/t/<id>` → mode = `update`, tracker = `clickup` (stub — see below)
3. **If no URL is present**, mode = `create`. The remaining string is the free-text description. If the description is empty, derive intent from the most recent conversation context.

## Step 1 — Resolve the tracker

Detect availability at runtime in this order of preference:

1. **Linear** — primary. Available if `mcp__plugin_linear_linear__*` tools (or equivalent `mcp__*linear*save_issue`) are exposed. Use `save_issue` (with `id` → update, without `id` → create). _Naming note: the registered MCP namespace uses a single underscore between the two `linear` tokens (`plugin_linear_linear`). Always probe the actual tool name in your runtime if a literal call fails — workspace MCP servers may register under a slightly different prefix._
2. **GitHub Issues** — fallback. Available if `gh` CLI is on PATH (`gh auth status` succeeds). Use `gh issue create` / `gh issue edit`.
3. **Jira** — **stub only**. If a Jira MCP is detected, print: `Jira tracker detected but not implemented in spike-recommend yet — falling back to print-only.` Then continue with the print-only fallback. Do NOT attempt a partial implementation.
4. **ClickUp** — **stub only**. Same behavior as Jira above.
5. **Print-only fallback** — if no tracker is reachable (or only stubs are available), print the full brief to the conversation with a one-line note explaining why no issue was written: e.g. `No supported tracker detected (Linear/GitHub) — printing brief only. Re-run with --save-local to persist locally.`

### Tracker precedence in `update` mode (tiebreaker)

When the URL points at a tracker the skill cannot write to, two rules collide: the per-tracker stub fallback (Jira/ClickUp → print-only) and the "URL-vs-available mismatch ⇒ abort" rule. The stub print-only fallback **wins** — it produces useful output to the user instead of a hard abort.

Explicit precedence, in order:

1. **URL is Linear or GitHub, and that tracker is available** → write the brief there normally.
2. **URL is Linear or GitHub, but that tracker is NOT available** (e.g. Linear URL but Linear MCP not configured, or GitHub URL but `gh` not authenticated) → abort with a clear message: `Cannot update <URL> — <tracker> is not available in this runtime. Configure it or pass a URL for an available tracker.` Never silently write to a different tracker.
3. **URL is Jira or ClickUp** (stubs) → DO NOT attempt to write to that tracker, DO NOT abort. Fall back to print-only: render the full brief to the conversation, AND include an explicit one-line note stating that the Jira / ClickUp issue was NOT updated. Example: `Jira issue <KEY> was NOT updated — spike-recommend does not yet support Jira writes. The brief above is print-only; copy it into the issue manually, or re-run with --save-local to keep a local copy.` This rule wins over rule (2)'s mismatch-abort because the user gets useful output instead of an error.
4. **URL is malformed or for an unknown tracker** → fall through to print-only with a similar "not updated" note.

The print-only note is mandatory in case (3) so the user is never under the false impression that the Jira/ClickUp issue was updated.

## Step 2 — Gather context

### If mode = `update`

Fetch the issue from the resolved tracker. Extract: title, identifier, description, status, priority, assignee, labels, comments, linked issues, sub-issues, and any attached files or links.

Please note that each issue might have **_one or more_** spikes as internal posts or comments. Use sub-agents for each spike detected, then consolidate via a synthesizer sub-agent. Add a section explaining why each sub-agent's response was picked.

### If mode = `create`

You do NOT have an existing issue to read. Instead:

1. Infer the work from the free-text argument and the most recent conversation context.
2. Ask the user — in a **single AskUserQuestion call, up to 4 questions** — for routing details. Tailor the questions to the tracker:
   - **Linear**: team, project (optional), assignee (default: `"me"`), priority. Ask milestone only if relevant.
   - **GitHub**: repository (`<owner>/<repo>`), assignee (default: `"@me"`), labels, milestone. Skip "project" — GitHub Projects are a separate API and not in scope.
3. Don't pad with unnecessary questions. If the tracker is GitHub and the repo is unambiguous from cwd, skip asking for it.

## Step 3 — Generate the bilingual brief

Use the **Output Format** below verbatim. The content rules, label taxonomy, validation, and analysis frameworks (Five Whys / MECE / Minto / Pareto / Second-Order Thinking) are unchanged.

## Step 4 — Write back to the tracker

### If mode = `update`

- **Linear**: call `save_issue` with the existing `id`, the new `title`, and the new `description` (full brief as Markdown). Do NOT touch labels, assignee, priority, project, comments — those are independent user-set state.
- **GitHub**: render the brief to a temp file first, then `gh issue edit <N> --title "<title>" --body-file "$BRIEF_FILE"`. Using a temp file (rather than `--body-file -` with stdin) keeps the brief portable across `gh` versions and lets Step 5 re-use the same file for the optional local copy. Do NOT pass `--add-label`, `--add-assignee`, `--milestone` — leave those alone.
  ```bash
  BRIEF_FILE=$(mktemp /tmp/brief-XXXXXX.md)
  # render brief into "$BRIEF_FILE"
  gh issue edit <N> --title "<title>" --body-file "$BRIEF_FILE"
  ```
- **Replace, not append.** The brief is the new canonical description. If the user had prior description content they want preserved, they should have asked for it explicitly.

### If mode = `create`

- **Linear**: call `save_issue` without `id`, supplying `team`, `title`, `description`, plus whatever the user answered in Step 2 (assignee, priority, project, milestone). Capture the returned `identifier` for Step 5.
- **GitHub**: render the brief to a temp file first, then create the issue. Capture the returned issue number / URL for Step 5.
  ```bash
  BRIEF_FILE=$(mktemp /tmp/brief-XXXXXX.md)
  # render brief into "$BRIEF_FILE"
  ISSUE_URL=$(gh issue create --repo <owner/repo> --title "<title>" --body-file "$BRIEF_FILE" --assignee <user> [--label ...] [--milestone ...])
  ```

After write, **echo the issue URL** back to the user as the final line so they can click through. Format: `Updated: <URL>` or `Created: <URL>`.

## Step 5 — Optional local file (`--save-local` only)

If `--save-local` was passed, ALSO write `./issue-briefs/{ISSUE-ID}.md` containing the same brief. Include a banner at the top:

```
> ⚠️ Local copy for offline review or future-proofing only — NOT the canonical version.
> Canonical: <issue URL>
```

Otherwise do **not** create any files. Do not silently leave behind stale local files.

### Ordering — Step 5 runs AFTER Step 4, always

In **update** mode the `{ISSUE-ID}` is known up-front (it was parsed from the URL in Step 0). The local write can happen at any point.

In **create** mode the `{ISSUE-ID}` does **not exist** until Step 4 writes the issue to the tracker and the tracker returns it. The skill MUST therefore:

1. Generate the brief body in Step 3 (no ID yet — leave any `{ISSUE-ID}` placeholders in the body as literal placeholders for now, or render the body without them).
2. Optionally stage the body to a scratch file so it can be re-used without re-rendering:
   ```bash
   BRIEF_FILE=$(mktemp /tmp/brief-XXXXXX.md)
   # write the rendered brief to "$BRIEF_FILE"
   ```
3. Call the tracker in Step 4 (`save_issue` / `gh issue create`) using `$BRIEF_FILE` as the body source. Capture the returned identifier (Linear `identifier`, GitHub issue number, etc.).
4. ONLY THEN, if `--save-local` was passed, copy `$BRIEF_FILE` to `./issue-briefs/{ISSUE-ID}.md`, replacing any in-body placeholders with the resolved ID and prepending the canonical-URL banner.
5. `rm -f "$BRIEF_FILE"` (the scratch file is no longer needed once the canonical and local copies exist).

Never attempt the local write before Step 4 completes in create mode — the filename is unresolvable and the operation will silently no-op or write to a nonsense path like `./issue-briefs/{ISSUE-ID}.md` (with the literal placeholder string).

## Linear Issue Input

Issue URL or free-text: `$ARGUMENTS`

## Label Taxonomy

The issue will have labels from this taxonomy:

### GROUP: Type (exclusive, required)

* **Bug** — Something is broken. Crashes, errors, spec violations.
* **Chore** — Maintenance. No user-facing change. Deps, CI/CD, docs, renewals, admin.
* **Feature** — New capability that doesn't exist yet. New page, endpoint, event, campaign.
* **Spike** — Time-boxed research. Output = knowledge. ADR, PoC, vendor eval, market research.
* **Improvement** — Enhancement to existing functionality. UX, perf, refactor, better process.
* **Design** — UI/UX or creative work. Mockups, design system, branding, decks.

### GROUP: Size (exclusive, maps to AI token budgets)

* **XS** — <50K tokens, ~30 min. _Single file, obvious change. Typo fix, config tweak._
* **S** — 50-100K tokens, ~2-4 hrs. _2-3 files, well-scoped. A component, hook, migration._
* **M** — 100-200K tokens, ~1-2 days. _Cross-module. Frontend + backend + migration + tests._
* **L** — 200-500K tokens, ~3-5 days. _Cross-layer, affects architecture. May need decomposition._
* **XL** — 500K+ tokens. _Epic scope. Needs decomposition into smaller issues._

### GROUP: Strategy (exclusive, optional for non-engineering)

* **Solo** — Single agent, end-to-end. Clear requirements, just go.
* **Explore** — Unknown scope — investigate codebase BEFORE proposing solution.
* **Team** — Multiple agents in parallel. Frontend + backend + tests concurrently.
* **Human** — Requires human decision. UX choices, biz logic, architecture. Default for Ops.
* **Worktree** — Git worktree isolation. Risky changes, experimental work.
* **Review** — Audit or review only — no code changes. Output is a report.

## Ungrouped Labels (combinable)

* **Component:**
  * Frontend
  * Backend
  * Database
  * Security
  * Performance
  * Infra
  * Testing
  * Web Quality
* **Impact:**
  * 🔥 Critical Path
  * 💰 Revenue
  * 🎁 Grant
* **Flags:**
  * 🚫 Blocked
  * ⚡ Quick Win
  * 📦 Epic

## Label Validation Rules

When recommending or assigning labels, enforce these rules:

1. **Grouped labels are mutually exclusive.** An issue can have exactly ONE label from each group (Type, Size, Strategy). Never assign two Types, two Sizes, or two Strategies to the same issue.

2. **Maximum 2 Component labels per issue.** If an issue needs 3+ Component labels (e.g., Frontend + Backend + Database), it is too large and must be decomposed into smaller issues. Recommend decomposition instead of adding more Component labels.

3. **Component must be coherent with the assigned project.** An issue in the "Backend API" project should not have the "Frontend" Component label. If cross-cutting work is needed, create separate issues in each relevant project.

4. **Epic is a Flag, not a substitute for Milestones.** Use project milestones for tracking phases of work. The Epic flag is only for issues that serve as parent containers with sub-issues.

5. **Size XL means decompose, not label.** Never create a single issue with Size XL. Instead, decompose into smaller issues (S/M/L) and use a project milestone to group them.


## Output Format

Provide an issue wording recommendation using EXACTLY this Markdown structure. Do NOT use HTML tables.

Do NOT skip sections — write "N/A" if a section doesn't apply. Write in English.

``````markdown

# [ISSUE-ID] Issue Title

{Body starts here — substantive content only. Do NOT emit a top-of-body metadata block listing Type/Size/Strategy/Components/Impact/Flags/Branch. These are the tracker's structured fields — they appear in the Labels and Properties sidebar automatically. Set them via the tracker's API (Linear `labels` array, GitHub `--label`, etc.), never duplicate them in the body.

The ONLY acceptable element between the `# Title` heading and `## 👤 HUMAN LAYER` is a top-level callout for content with no native sidebar equivalent — e.g. an "out of scope, handled by …" pointer to a related issue, because Linear's Relations panel is less prominent than a body callout. Example:

> 🔗 Out of scope — handled by [DOJ-XXXX](https://linear.app/your-team/issue/DOJ-XXXX)

If there is no such callout to make, jump straight from the title to `## 👤 HUMAN LAYER`.}

---

## 👤 HUMAN LAYER

### User Story

As a **{role}**, I want **{X}** so that **{Y}**.

### Background / Why

{2-3 paragraphs in plain language. Extract from issue description + comments. Explain the problem, motivation, and business context. If the issue is sparse, say what you know and flag what's missing.}

### Analogy

{Compare to something familiar. Write "N/A" if not applicable.}

### UX / Visual Reference

{List any screenshots, Figma links, mockups mentioned in the issue. Write "None provided" if absent.}

### Known Pitfalls &amp; Gotchas

{Extract from comments, linked issues, or infer from codebase knowledge. List edge cases, legacy data quirks, dependencies.}

---

## 🤖 AGENT LAYER

### Objective

{1-2 sentence technical outcome. Be precise about the deliverable.}

### Context Files

{List exact file paths the agent should read before starting. Include a short description of why each file matters. Use your knowledge of the repo structure.}

- `path/to/file` — {why}
- `path/to/file` — {why}

### Acceptance Criteria

{Checkboxes. Each must be independently testable. Derive from the issue description, comments, and your understanding of the requirement.}

- [ ] {criterion}
- [ ] {criterion}
- [ ] {criterion}

### Technical Constraints

{Patterns, conventions, and guardrails the agent must follow. Include relevant linting rules, architectural patterns, naming conventions from the codebase.}

- {constraint}
- {constraint}

### Verification Commands

{Exact bash commands to confirm the work is done correctly.}

\```bash
# Tests
{command}

# Lint
{command}

# Build
{command}

# Type check (if applicable)
{command}
\```

### Agent Strategy

{This section adapts based on the Strategy label.}

**Mode:** `{strategy}`

### If Solo:
- **Approach:** {step-by-step plan}
- **Estimated tokens:** {based on Size label}

### If Explore:
- **Investigation questions:** {what needs to be understood first}
- **Read-only phase:** {files/areas to investigate}
- **Decision point:** {what triggers moving to implementation}

### If Team:
- **Lead role:** Coordinator — assigns tasks, reviews, synthesizes. No direct file edits.
- **Teammates:**
  - Teammate 1: {role} → owns `{paths}`
  - Teammate 2: {role} → owns `{paths}`
  - Teammate 3: {role} → owns `{paths}`
- **Display mode:** `tab` or `split`
- **Plan approval required:** yes/no
- **File ownership:** {explicit mapping to avoid write conflicts}

### If Worktree:
- **Worktree branch:** `{branch name}`
- **Isolation reason:** {why this needs worktree}
- **Merge strategy:** {how to integrate back}

### If Review:
- **Audit scope:** {what to review}
- **Output format:** {report structure}
- **No code changes** — output is a report only.

### If Human:
- **Decisions needed:** {list decisions the human must make}
- **Options to present:** {for each decision, outline the trade-offs}
- **Agent prep work:** {what the agent can do to support the decision}

### Slack Notification

When done, send a summary to {user} via Slack MCP with:
- What was completed
- Files changed
- Any issues or decisions needed

---

## 🔀 Parallelization Recommendation

{ALWAYS include this section. Based on the Size, Strategy, and Component labels, recommend which parallelization mechanism to use. Consider the codebase context window of 200K tokens.}

**Recommended mechanism:** `{Subagents | Git Worktrees | Agent Teams | None (Solo)}`

**Reasoning:**

{Explain your choice using this decision matrix:}

- **Subagents** — Best for: quick research, focused sub-tasks. Token cost: Low (1x). Use when a piece of the work is independent and the result can be summarized back. Like sending an intern to look something up.
- **Git Worktrees** — Best for: parallel sessions on different branches. Token cost: 1x per session. Use when changes are risky, experimental, or need branch isolation. Like separate desks in the same office.
- **Agent Teams** — Best for: complex multi-part work where teammates need to coordinate. Token cost: 3-4x. Use when multiple components change simultaneously and teammates benefit from messaging each other. Like a self-organizing consulting firm.
- **None (Solo)** — Best for: XS/S issues with clear scope. Single agent, single context window, minimal cost.

**Size → Mechanism mapping:**
- XS/S → Solo (no parallelization needed)
- M with single component → Solo or Subagents for research
- M with multiple components → Agent Teams (2 teammates)
- L → Agent Teams (2-3 teammates) or Worktree if risky
- XL → Decompose first, then Agent Teams per sub-issue

**Cost estimate:** ~{number}x base token cost

---

### Synthesis Additional Comments

{Add here any additional comments that you consider necessary based on the synthesis of all the spike analyzer sub-agents. Use 5 Why's methodology. Please also use the following consulting frameworks:}

#### MECE Logical Validation
Analyze the implementation using the **MECE** (Mutually Exclusive, Collectively Exhaustive) framework:

* **Mutually Exclusive:** Verify that this logic does not overlap or conflict with existing Handlers, Services, or Selectors within the spike. Ensure a single source of truth for this business logic.

* **Collectively Exhaustive:** Ensure the solution addresses 100% of the defined requirements, including null pointers, platform limits (Gov Limits), and all possible record states in the execution context.

#### Executive Synthesis (Minto Pyramid)
Structure the response using the **Pyramid Principle**:

1.  **Lead with the Answer:** Provide a one-sentence "Executive Summary" of the change and its primary impact on the system.

2.  **Supporting Arguments:** Group technical changes into logical buckets (e.g., Performance Optimization, Code Resilience, Scalability).

3.  **Data & Evidence:** Provide specific technical details (CPU time saved, heap size impact, or test coverage metrics) only as evidence to support the arguments above.

#### Pareto 80/20 Efficiency Review

Apply a **Pareto Filter** to the proposed solution:

* Identify if we are achieving 80% of the business value with 20% of the code complexity. 

* Flag any "over-engineered" components designed for extreme edge cases that may introduce unnecessary technical debt to the spike.

* Suggest if a simpler, standard Salesforce feature (e.g., a simple Flow or Formula) would be more efficient than the current Apex implementation.

#### Second-Order Thinking & Risk Assessment
Evaluate the **long-term implications** of this implementation:

* **Scalability:** What happens to this logic if the data volume in the Org grows by 10x or 100x? 

* **Downstream Effects:** How does this change impact other modules or future developers working within the spike?

* **Future Maintenance:** Identify potential "hidden" dependencies or architectural traps that might increase the cost of change six months from now.

``````

## Rules

1. Never invent requirements.

    * If the issue is vague, say so explicitly and flag what's missing.
    * Use phrases like "⚠️ Not specified in issue — assuming X" or "❓ Needs clarification: Y".

2. Derive, don't assume.

    * Extract the user story, pitfalls, and acceptance criteria from the issue content.
    * If comments contain useful context, incorporate them.

3. Be opinionated about strategy. 

    * If the issue has no Strategy label, recommend one based on Size + Type + Component. Explain why.

4. Size drives everything.

    * XS/S = Solo. M = Solo or Team depending on components. L/XL = Team or decompose. Map this explicitly.

5. Context files are critical.

    * Use your knowledge of the repo to list the exact files the agent needs. This prevents hallucination and wasted tokens.

6. XL = decompose.

    * If the issue is XL, don't generate a single brief.
    * Instead, propose a decomposition into smaller issues, each with its own Size and Strategy.

7. Blocked issues get a preamble.

    * If the 🚫 Blocked flag is present, start the brief with a blockers section listing what needs to be resolved first.

8. Always recommend parallelization.

    * The final section is mandatory. Be explicit about the mechanism, the cost trade-off, and why.

9. Validate labels before output.

    * Apply the Label Validation Rules (see above). If the issue has invalid label combinations, flag them in the brief header with `LABEL WARNING:` and recommend corrections.
    * If the issue has 3+ Component labels, recommend decomposition into separate issues instead of generating a single brief.
    * If grouped labels conflict (e.g., two Types), use the most specific one and flag the conflict.

10. Tracker is canonical, not local files.

    * On `update`, write the brief to the existing issue's title + description. Touch nothing else (labels, assignee, priority, project, milestone, comments are independent state set by humans).
    * On `create`, ask routing questions via AskUserQuestion and create the issue in the tracker.
    * On `--save-local`, ALSO write `./issue-briefs/{ISSUE-ID}.md` as a non-canonical mirror with a banner pointing at the tracker URL.
    * Without `--save-local`, never create the local file. The previous default (always-write-local) caused divergence between the brief and the tracker and is retired.

11. Predict semantic conflicts, not just file conflicts.

    * When a brief references an in-flight PR (an open PR on the same repo, especially one that hasn't merged yet), the "Known Pitfalls & Gotchas" and "Technical Constraints" sections MUST enumerate the **semantic** contracts both PRs touch — not just the file paths.
    * Semantic contracts include: URL shapes (canonical paths, route templates), type signatures (function arguments, return types, generic params), state schemas (Redux/Zustand/TanStack Query key shapes, DB column meanings), edge function payload shapes, and event names.
    * File-level conflict prediction is necessary but insufficient. The DOJ-4200 + DOJ-4075 session (`dojo-os`, 2026-05-20) had a subagent predict "7 shared files will conflict" — the actual file conflict count was 6 (close enough), but the bigger drift was a SEMANTIC conflict: DOJ-4200's new canonical URL shape (`/pathways/:p/course/:s`) vs DOJ-4075's URL builders for forum URLs (which the subagent kept on the legacy shape per Strategy A). Neither PR touched the other's files, yet the URL contract between them had silently diverged.
    * Format inside the brief:
      > **In-flight overlap with {OTHER-ISSUE-ID}:**
      > - **File-level**: {N} files touched by both (list).
      > - **Semantic contracts**:
      >   - URL shape `X` — both PRs construct it; verify the shape matches.
      >   - Type `Foo` — PR A widens the union; PR B narrows it. Decide which wins.
      >   - Query key `queryKeys.x.y` — both PRs invalidate it; ensure invalidation timing is compatible.

12. Verify URL-builder output matches the declared Route mount.

    * When a brief covers a URL canonical migration (anything that introduces a new `buildXxxUrl` helper, mutates the return of an existing one, or moves a `<Route path="..." />` mount), the Acceptance Criteria MUST include an explicit check: "`buildXxxUrl(...)` output `matchPath`s against the declared `ROUTES.X` template (or the inline route mount string in `AppRoutes.tsx`)."
    * Suggest writing a Vitest test (see `dojo-os` `src/utils/__tests__/url-builders-match-routes.test.ts` as a reference implementation) that asserts each builder's representative output is reachable via `matchPath({ path: template, end: true }, builtUrl)`.
    * Why: Greptile caught this exact bug as a P1 on DOJ-4200 (commit `dbd8a1d04`). The route-contract test (DOJ-4168 / Cure 1A) validates yaml ↔ source crosswalk for canonical URLs, but it does NOT catch "builder produces a URL that doesn't match its declared route template" — because the builder name and the `ROUTES` key are decoupled. Briefs that fail to surface this gap let the same bug ship.
    * If the in-flight PR introduces a route mount inline in the router file (per the DOJ-4200 inline-mount pattern), the contract still applies: the builder output must reach that mount via `matchPath` against the literal template string.

13. Use `useAuth().isAuthenticated` for chrome branching, NOT URL-prefix string detection.

    * When a brief proposes a page component that renders different chrome (header, layout, CTA bar) based on whether the visitor is authenticated, the Technical Constraints MUST require the branching to happen via `useAuth().isAuthenticated` (or the project's equivalent auth hook) — NOT via inspecting `location.pathname` against a `PUBLIC_*_ROUTE_PREFIXES` string list.
    * Rationale: prefix-based detection makes EVERY visitor to a path under the prefix see the anon chrome, including authed users — violating the DOJ-4064 contract ("one URL = one auth-aware component, branching internally"). DOJ-4200's first attempt added `/pathways` to `PUBLIC_COURSE_ROUTE_PREFIXES` and lost the app shell for authed users on the canonical pathway-course URL. Fix (commit `dbd8a1d04`): replace the prefix list with `useAuth().isAuthenticated` and cite the PathwaysPage / PathwayDetailPage pattern as the canonical model.
    * Reference cite to include in the brief: "Use the PathwaysPage / PathwayDetailPage pattern — `useAuth().isAuthenticated` branching inside a single wrapper component. See `dojo-os` commit `dbd8a1d04` for the kind of bug this prevents."

### Usage

```bash
# Update an existing Linear issue in place (default)
claude /make-no-mistakes:spike-recommend https://linear.app/your-team/issue/PROJ-123

# Update an existing GitHub issue
claude /make-no-mistakes:spike-recommend https://github.com/your-org/your-repo/issues/42

# Create a new issue from conversation context — will prompt for team/repo/assignee/priority
claude /make-no-mistakes:spike-recommend "investigate flaky payment webhook retries"

# Same as default + also keep a local mirror under ./issue-briefs/
claude /make-no-mistakes:spike-recommend --save-local https://linear.app/your-team/issue/PROJ-123
```

The skill writes the brief back to the issue tracker by default. Use `--save-local` to additionally persist `./issue-briefs/{ISSUE-ID}.md` for offline review.

### Tracker support matrix

| Tracker | Mode supported | Implementation |
|---|---|---|
| Linear | update + create | Linear MCP (`save_issue`) — primary |
| GitHub Issues | update + create | `gh issue edit` / `gh issue create` — fallback |
| Jira | — | **Stub.** Detects but does not implement. Falls back to print-only. |
| ClickUp | — | **Stub.** Detects but does not implement. Falls back to print-only. |
| None detected | print-only | Brief is printed to the conversation; user can copy or re-run with `--save-local`. |

### Field mapping — labels go to tracker fields, NOT the body

Each label / metadata value has a canonical home in the tracker's structured sidebar. Set it there via the API; never duplicate it into the issue body (the body is the narrative — User Story, Background, ACs, etc.). If the body and the sidebar disagree, the sidebar wins by convention, and the body becomes stale shadow data.

| Brief field | Tracker destination | Notes |
|---|---|---|
| `Type` | Tracker Label | One per issue (Bug / Feature / Improvement / Chore / Spike / Design). |
| `Size` | Tracker Label | One per issue (XS / S / M / L / XL). XL = decompose, never apply. |
| `Strategy` | Tracker Label | One per issue (Solo / Explore / Team / Human / Worktree / Review). |
| `Components` | Tracker Labels | Max 2 per issue (see Label Validation Rules). 3+ ⇒ decompose. |
| `Impact` | Tracker Label | Optional (🔥 Critical Path / 💰 Revenue / 🎁 Grant). |
| `Flags` | Tracker Labels | Optional, combinable (🚫 Blocked / ⚡ Quick Win / 📦 Epic). |
| `Branch` | **Omit** | Linear auto-generates `gitBranchName` from the issue ID + title. GitHub PRs link via the head ref. Jira/ClickUp similarly. Never write a `Branch:` line into the body. |

**Linear**: pass labels as the `labels` array on `save_issue`. Sidebar chips render automatically.
**GitHub**: pass labels via `gh issue create --label "..."` / `gh issue edit --add-label "..."`. The Labels box on the issue page renders automatically.
**Jira / ClickUp**: stubbed — the print-only fallback still emits the narrative body, but does NOT emit a metadata block at the top.

### Test instructions

Verify the new behavior with the following invocations:

1. **Update an existing Linear issue (no local file):**
   ```bash
   claude /make-no-mistakes:spike-recommend https://linear.app/dojo-coding/issue/DOJ-4058
   ```
   Expected: Linear issue DOJ-4058's title + description are replaced with the generated brief. Labels, assignee, priority, comments are untouched. The Linear URL is echoed back. `./issue-briefs/DOJ-4058.md` is **not** created.

2. **Update + keep a local mirror:**
   ```bash
   claude /make-no-mistakes:spike-recommend --save-local https://linear.app/dojo-coding/issue/DOJ-4058
   ```
   Expected: same as (1), AND `./issue-briefs/DOJ-4058.md` is written with a banner at the top pointing at the canonical Linear URL.

3. **Create a new issue from context:**
   ```bash
   claude /make-no-mistakes:spike-recommend "add a retry-with-backoff policy to the Stripe webhook handler"
   ```
   Expected: skill calls AskUserQuestion once for team/project/assignee/priority, creates a new Linear issue with the generated brief as the description, and echoes back the new URL.

4. **GitHub fallback:**
   ```bash
   claude /make-no-mistakes:spike-recommend https://github.com/dojocoding/dojo-os/issues/1234
   ```
   Expected: `gh issue edit 1234 --title "..." --body-file -` is invoked against the parsed repo. Labels/assignee/milestone untouched.

### Requirements

* **Linear MCP** server configured in Claude Code (for Linear update/create)
* **GitHub CLI (`gh`)** authenticated (for GitHub fallback)
* **Slack MCP** server configured (for the optional notification step inside the Agent Layer)

