$npx -y skills add multica-ai/multica --skill multica-working-on-issuesUse when working on a Multica issue after the runtime has provided the trigger context — to apply the product contracts the runtime brief does not encode: how PR linking differs from close intent, how to read a linked PR's real state via the pull-requests CLI, which metadata keys
| 1 | # Working on Multica issues |
| 2 | |
| 3 | Product contracts the runtime brief does not fully encode: PR linking vs close |
| 4 | intent, reading linked-PR state, metadata keys, status side effects, and |
| 5 | sub-issue enqueue behavior. |
| 6 | |
| 7 | For building mention links, load `multica-mentioning` instead — not this skill. |
| 8 | |
| 9 | Every contract below is traced to source in |
| 10 | `references/working-on-issues-source-map.md`. |
| 11 | |
| 12 | ## PR linking and close intent are two distinct contracts |
| 13 | |
| 14 | The GitHub webhook runs two separate scans over an incoming PR. They are not the |
| 15 | same gate and they read different fields. |
| 16 | |
| 17 | **Linking** scans the PR **title, body, OR branch** for a routable issue key |
| 18 | (`PREFIX-NUMBER`, e.g. `MUL-2759`). Each match writes an issue ↔ PR link row. |
| 19 | This is the link that `multica issue pull-requests` reads back — but see the |
| 20 | reference-only rule below: a key that appears **only** as a bare mention in the |
| 21 | body is linked yet hidden from that list. |
| 22 | |
| 23 | ```text |
| 24 | MUL-2759: add built-in issue working skill # title prefix → links, shown |
| 25 | agent/matt/mul-2759-working-on-issues # branch ref → links, shown |
| 26 | ``` |
| 27 | |
| 28 | **Close intent** is stricter and is a separate scan over **title or body only — |
| 29 | never the branch**. It fires only for a key placed immediately after a closing |
| 30 | keyword (`Closes` / `Fixes` / `Resolves`, optional `:` then whitespace). That |
| 31 | adjacency is what sets the link row's close-intent flag, the gate that |
| 32 | auto-advances the issue to `done` when the PR merges. |
| 33 | |
| 34 | ```text |
| 35 | Closes MUL-2759 # links AND records close intent |
| 36 | Fixes MUL-2759 |
| 37 | Resolves MUL-2759 |
| 38 | Fix login MUL-2759 # links only — keyword not adjacent |
| 39 | ``` |
| 40 | |
| 41 | Consequence: a bare title prefix or a branch reference links the PR but does not |
| 42 | close the issue on merge. A closing keyword immediately adjacent to the issue key |
| 43 | records close intent; on merge, that close intent can move the linked issue to |
| 44 | `done`. |
| 45 | |
| 46 | **Reference-only links (hidden from the PR list).** A key that appears **only** |
| 47 | as a bare mention in the body — no closing keyword, and not in the title or |
| 48 | branch — still writes a link row, but the row is flagged `reference_only` and |
| 49 | **excluded from `multica issue pull-requests`** (and the issue's right-side PR |
| 50 | list in the UI). This keeps passing mentions like `Related MUL-2759` or |
| 51 | `Follow up in MUL-2759` from surfacing an unrelated PR as if it were working on |
| 52 | that issue. To make a PR show up for an issue, put the key in the title, the |
| 53 | branch, or after a closing keyword in the body — not as a loose body reference. |
| 54 | |
| 55 | ```text |
| 56 | Closes MUL-2759 in the body # links and shown |
| 57 | Related to MUL-2759 in the body (no title/branch) # links but reference_only → hidden |
| 58 | ``` |
| 59 | |
| 60 | ### Default for code-changing issue work |
| 61 | |
| 62 | When an issue run changes code in a checked-out GitHub repo, the default handoff |
| 63 | is to open or update a PR before posting the final Multica issue comment, unless |
| 64 | the user explicitly asked for a local-only change or no PR. This is a default, not |
| 65 | an unconditional command: if no code changed, say no PR is needed; if PR creation |
| 66 | is blocked by auth, failing tests, or missing remote state, report that blocker |
| 67 | instead of pretending the run is complete. |
| 68 | |
| 69 | Use a routable issue key in the PR title, body, or branch so the webhook can link |
| 70 | the PR back to the issue. If the PR should close the issue on merge, put the key |
| 71 | immediately after a closing keyword in the title or body, for example: |
| 72 | |
| 73 | ```text |
| 74 | MUL-2759: fix login redirect # links only |
| 75 | Closes MUL-2759 # links and records close intent |
| 76 | ``` |
| 77 | |
| 78 | In the final issue comment, include the PR URL when a PR exists. If the task did |
| 79 | not produce a PR because no code changed or the user asked not to create one, say |
| 80 | that explicitly. |
| 81 | |
| 82 | ## Reading a linked PR's real state |
| 83 | |
| 84 | When a step depends on PR state, query Multica's link table — do not infer it |
| 85 | from branch names, GitHub search, memory, or `pr_url` metadata (which can be |
| 86 | stale). |
| 87 | |
| 88 | ```bash |
| 89 | multica issue pull-requests <issue-id> --output json |
| 90 | ``` |
| 91 | |
| 92 | Returns `{"pull_requests": [...]}`. Each element exposes: |
| 93 | |
| 94 | - `number`, `html_url`, `title` |
| 95 | - `state` — the PR lifecycle as a **single enum**, one of `merged`, `closed`, |
| 96 | `draft`, `open`. There is no separate `draft` or `merged` boolean in the |
| 97 | response; the server folds them into `state` (merged wins, then closed, then |
| 98 | draft, else open). |
| 99 | - `merged_at` — non-null once merged; a second confirmat |