Sync GitHub issues to match a plan's structure (umbrellas + step issues), with rich bodies optimized for fresh-context LLM work. Detects letter-named phases, sub-phase notation, table-row step formats. Use after plan changes or to bring issue bodies up to current build-doc richness.
Scanned 9/3/2026
Install to Claude Code
npx -y skills add aberson/skill-mesh --skill repo-sync --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Repo Sync?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/aberson-repo-sync)More formats (shields.io, HTML) on the badges page.
---
name: repo-sync
description: Sync GitHub issues to match a plan's structure (umbrellas + step issues), with rich bodies optimized for fresh-context LLM work. Detects letter-named phases, sub-phase notation, table-row step formats. Use after plan changes or to bring issue bodies up to current build-doc richness.
user-invocable: true
---
# Repo Sync
Bidirectional sync between a plan document and GitHub issues. Creates,
updates, closes, and **enriches** issues so GitHub mirrors the plan's
structure and any fresh-context LLM picking up a step has enough context
in the issue body to start work.
## Principle: optimize for LLM effectiveness, not human-noise reduction
Issue bodies should be substantive. A fresh-context model reading
`gh issue view #N` should understand:
- What to build (not just a name)
- Where in the codebase (specific files)
- How to know it's done (concrete acceptance)
- What it depends on (prior issues, blocked-by relationships)
- Build-phase flags (reviewers, isolation, **`--ui` when frontend is touched**)
- Where the canonical design lives (build doc + section anchor)
- **Whether the step can run in parallel with neighbors** (declared explicitly,
not left for the operator to infer)
Lean bodies (just "What to build" and a footer) tax every future
session that picks up that issue. Treat enrichment as a first-class
output, not optional polish. Issue count and inbox tidiness are
human-experience costs the operator is fine paying — don't optimize for
them at the expense of the LLM-context-effectiveness above.
## Operator preference (HEAVY) — autonomous + bundled UI + parallel
This skill propagates the operator's strong workflow preference through every
issue it writes. Three dials, applied to every step body:
1. **Autonomous build readiness.** Step bodies must contain enough acceptance
detail (`Done when`) for `/build-step` to verify PASS without asking the
operator a follow-up. Bodies that force a human ping mid-build are a
regression. When enriching, prioritize concrete acceptance over prose.
2. **UI-bundle declaration.** If a step's `Files` touch `frontend/`, change a
`/api/...` shape consumed by the dashboard, or modify WebSocket payloads,
the issue body's `Flags (recommended)` line MUST include `--ui` and the
`Done when` MUST reference UI evidence (Playwright screenshot, dashboard
smoke, or any project-specific UI/dashboard smoke commands defined in
the project's `CLAUDE.md`). Code-only acceptance on frontend-touching
work is the gap repo-sync is here to close — flag any existing issue
that violates this and propose enrichment.
3. **Parallelism declared explicitly.** If a step has no `Depends on` and
shares no `Files` with another open step in the same phase, the body MUST
note `**Parallel-safe with:** #M` (and the reciprocal noted on #M too).
Sequential is fine, but `none — strictly sequential` MUST carry a one-line
justification (e.g. "Step N+1 imports this module"); a bare
"strictly sequential" without a reason is a defect — the parallelism
choice must be visible in the issue, not hidden in the operator's head.
These dials are applied during CREATE, ENRICH, and UPDATE — not just on first
write. A pre-existing rich body that lacks the UI-bundle declaration on a
frontend-touching step still counts as needing ENRICH.
## When to use
- Plan steps were added, removed, or reworded after issues were created
- Existing issues have lean bodies that need richer context (`--enrich`)
- Cutting issues for a new phase from its build doc
- User says: "sync issues", "update GitHub issues", "enrich step issues",
"issues are out of date"
## When NOT to use
- Closing a single issue after a step completes — just `gh issue close N`
- Bulk-closing issues from a deleted plan (use `gh issue list ... | xargs gh issue close`)
---
## Prerequisites
Run the plan pipeline in order. `/repo-sync` is step 4 of 5:
1. `/plan-init` or `/plan-feature` — produce `plan.md`.
2. `/plan-review` — gap-check before sync.
3. `/plan-wrap` — clean-context check before sync.
4. `/repo-sync` — mint or update issues from the plan.
5. `/build-phase` — execute the steps.
Skipping `/plan-review` or `/plan-wrap` before sync is the
**N+1 rework trap**: one plan edit becomes N+1 edits — the plan
file plus every step issue body that needs the same fix.
`/repo-sync` mints fresh-context-LLM-targeted issue bodies
straight from the plan, so plan-only ambiguities (undefined IDs,
unexplained acronyms, lingering TBDs) bake into every issue.
For an autonomous pre-flight that runs the chain unattended,
use `/plan-expedite --plan <path>` — it chains
`plan-review --autofix → plan-wrap --autofix → repo-sync →
session-wrap` in one shot.
Canonical workspace-level statement of the chain lives in
`dev/.claude/rules/plan-and-issue-flow.md` § Order.
---
## Arguments
| Arg | Required | Default | Description |
|---|---|---|---|
| `--plan` | yes | -- | Path to plan/build-doc (e.g. `documentation/plans/phase-d-build-plan.md`) |
| `--phase` | no | inferred | Phase identifier (B, D, E, 6, 7, F, G, G.2, 9, etc.) — letters and numbers both supported. Inferred from filename if omitted. |
| `--scope` | no | both | `umbrella`, `steps`, or `both` |
| `--enrich` | no | false | Update existing-issue bodies if richer content is now in the plan |
| `--dry-run` | no | false | Print issue-change preview and exit without applying — for validation before commit |
---
## Phase identifier conventions
Phases can be:
- Numeric: `Phase 0`, `Phase 1`, ..., `Phase 9` — common for substrate/operational tracks
- Letter: `Phase A`, `Phase B`, `Phase D`, ..., `Phase G` — common for capability tracks
- Sub-phase: `Phase G.1`, `Phase G.2`, `Phase G.3` — for multi-step phases that fork
Numbering gaps are allowed and intentional (e.g. project skipped Phase C
during a merge; project may skip Phase 8 to align with pre-existing
issue titles). The skill honors the plan as-written — does NOT try to
fill gaps.
Step numbering within a phase uses dot notation in the build doc
(e.g. `D.1`, `D.2`, `7.1`, `G.2.1`) but issue titles use the friendlier
`Phase X Step N:` form.
Issue title patterns the skill recognizes:
- Umbrella: `Phase X — <name>` (e.g. `Phase D — Build-order z-statistic`)
- Step: `Phase X Step N: <name>` (e.g. `Phase D Step 1: Audit reward_rules.json`)
- Sub-phase umbrella: `Phase X.M: <name>` (e.g. `Phase G.2: Zerg bot`)
- Sub-phase step: `Phase X.M Step N: <name>`
## Step-detection formats supported in plan docs
The skill scans the plan for any of:
- `### Step N: <name>` — heading style
- `### Phase X Step N: <name>` — explicit phase heading
- `#### Step N: <name>` — sub-heading style
- `- **Step N:** <name>` — list style
- `| X.N | <description> |` — table row in a Scope / Build-steps section
For table-row format, the description is the step title; richer body
content must be pulled from explicit per-step subsections OR the doc is
flagged as lean (see "Doc richness check").
---
## Flow
### Step 0 — Pre-flight: resolve and verify target repo
`gh` resolves the target repo from cwd by walking up to the nearest
`.git/`. The `dev/` workspace root is itself a git repo with its own
remote (`<your-org>/coding-root`), so running `gh` from `dev/` silently
lands on `<your-org>/coding-root` instead of the intended project
subdirectory. Resolve and echo the repo before any mutating call:
```bash
cd <absolute-project-dir>
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
echo "Target repo: $REPO"
```
Confirm the printed `Target repo:` matches the intended project. If it
does not, stop — the cwd is wrong.
For every subsequent `gh` call in the run, pass `-R <owner>/<repo>`
defensively so cwd-resolution cannot drift mid-run:
```bash
gh -R <your-org>/Alpha4Gate issue create ...
gh -R <your-org>/Alpha4Gate issue list ...
```
Equivalent fix: `cd` into the project subdirectory before invoking
`gh` (e.g., `cd Alpha4Gate && gh ...`). The `-R` flag is preferred
because it survives mid-run cwd changes.
### Step 1 — Read the plan and infer phase
Read `--plan`. If `--phase` not specified, infer from filename
(`phase-d-build-plan.md` → `D`; `phase-9-build-plan.md` → `9`;
`improve-bot-evolve-plan.md` → check `# Phase X ...` H1 in content).
Extract:
- **Umbrella metadata:** title (from `# <H1>`), goal, prerequisites,
effort, kill criterion, validation
- **Step list:** every step matching one of the supported formats
For each step, capture from per-step subsections if present:
- `Problem` / `What to build`
- `Files` / `Files to modify` / `Files touched`
- `Existing context`
- `Done when` / `Acceptance`
- `Flags` (build-step flags like `--reviewers code --isolation worktree`)
- `Depends on`
- `Produces`
If steps are table-only (sparse), flag this and run the richness check
(below).
### Step 2 — Doc richness check (the LLM-effectiveness gate)
For each step, count populated rich-fields out of 6:
{Files, Done when, Flags, Existing context, Produces, Depends on}.
- **Rich step:** ≥ 3 fields populated
- **Lean step:** ≤ 2 fields populated
If >50% of steps are lean:
```text
WARNING: <plan> has N of M lean steps (only title + description).
Issues created from lean steps will be lean too. Every fresh-context
LLM session that opens those issues will need to drill into the build
doc or source code for context the issue body should have.
Per the LLM-effectiveness principle (memory:
feedback_optimize_for_llm_over_human_noise.md), the recommendation is:
1. Enrich the build doc first with per-step Files / Done when /
Flags / Existing context sections.
2. Then re-run this skill (or run with --enrich for an existing
issue set).
Continuing — issue bodies will reflect the plan's current shape.
Operator can re-run /repo-sync after enriching the plan if higher-
fidelity issues are needed.
```
Surfacing this cost is mandatory; the warning is a printed observability
note that proceeds automatically without prompting. The operator can
re-run `/repo-sync` after enriching the plan when richer issues are
needed — but no halt mid-sync.
### Step 3 — Fetch existing GitHub issues
```bash
# jq requires POSIX classes — no \d / \w / \s / \. (see Common mistakes § Perl-style regex escapes)
gh issue list --state all --limit 200 --json number,title,body,state \
--jq '.[] | select(.title | test("^Phase [A-Z0-9]+([.][0-9]+)?( Step [0-9]+)?:|^Phase [A-Z0-9]+([.][0-9]+)? — "))'
```
This regex matches both umbrella titles (`Phase X — ...`) and step
titles (`Phase X Step N: ...`) across numeric, letter, and sub-phase
numbering. Falls through to the legacy `(Phase \d+ )?Step \d+:` if the
new pattern returns nothing (back-compat).
#### 3.1 — Cross-plan collision check
When a repo holds issues from multiple plans, step keys
(`Phase X Step N`) collide and a new plan's step may match a
stale issue belonging to an unrelated, possibly closed prior
plan.
The disambiguator is the body footer `/repo-sync` writes.
There are TWO footer shapes — both encode the source-plan
path and the parser must recognize both. In the rendered
issue body the plan path is a markdown link (square-bracket
label wrapping the path, parenthesis URL `../blob/<default-branch>/`
plus that same path) so the path is clickable from the
GitHub issue — never a code-spanned path followed by a
parenthetical "linked to" phrase.
- Create path (see Body template — step):
`*Synced from `<plan>` by /repo-sync at <git-short-sha>*`
(with `<plan>` rendered as the markdown link described above).
- Enrich / update path (see Update / enrich):
`*Enriched by /repo-sync from <build-doc-path> @
<git-short-sha>*`
Long-lived issues that have been re-synced carry the second
shape; the parser must match both or every previously
enriched issue falls through as "footer missing" — exactly
the issues most likely to be cross-plan-colliding.
Regex shapes the parser must match:
- Create: `Synced from \[(.*?)\]`
- Enrich: `Enriched by /repo-sync from (.+?)( @ |$)`
Algorithm: for each issue that matched a plan step in the
Step 3 fetch above, parse the footer's plan path from the
issue body — from EITHER `Synced from [<plan>]` OR
`Enriched by /repo-sync from <build-doc-path>`. If that plan
path differs from the current `--plan` argument's path,
classify the match as a CROSS-PLAN COLLISION (the issue
belongs to a different plan; the step key collision is
incidental).
Action: emit a `WARN: cross-plan collision` line in the
Step 5 preview output for each collision. **No halt** —
autonomous default still executes; the operator sees the
warning in the preview but the run proceeds without
prompting. Collided issues are excluded from ENRICH /
REOPEN candidate lists (treat as stale w.r.t. this plan).
Example warning line in the preview:
```text
WARN: cross-plan collision — issue #123 "Phase D Step 3: foo"
plan footer: documentation/old-plan.md
--plan arg: docs/archived-plans/repo-sync-improvements-plan.md
classify as: stale (do not ENRICH, do not REOPEN)
```
Footer-absent issues (legacy or hand-authored) cannot be
classified by this check; fall through to the existing
title-prefix match behavior. Add `(footer missing)` to the
preview note so the operator knows the check could not run
on that issue.
**Always-surface contract.** The rendered Step 3.1 output
MUST state the two recognized footer shapes explicitly —
even when no existing issues were matched in Step 3. This
makes the parser's footer-aware classification visible and
auditable in every run, not only runs that exercise it.
Required Step 3.1 header line in the rendered output:
```text
Footer shapes recognized:
Create: Synced from [<plan>](...)
Enrich: Enriched by /repo-sync from <build-doc-path> @ <sha>
```
When no issues were matched, follow with `(no existing
issues to classify)`. When issues exist, list each with its
footer plan path or `(footer missing)` per the algorithm
above. Either way, neither footer shape is omitted from the
output, so enriched-path issues are never silently treated
as `footer missing`.
### Step 4 — Match and diff
Match plan entries to existing issues by title prefix:
- Umbrella: `Phase X — <anything>` matches plan's H1 phase
- Step: `Phase X Step N: <anything>` matches plan step `X.N` or `Step N`
within the phase
Classify into buckets:
| Bucket | Condition | Default action |
|---|---|---|
| **CREATE umbrella** | Plan has phase, no umbrella issue | Create with full body |
| **CREATE step** | Plan step has no matching issue | Create with rich body |
| **ENRICH** | Issue exists, body is lean (≤2 sections), plan now has richer content | Update body (auto if `--enrich` OR if plan has clear new fields) |
| **UPDATE** | Issue exists but title or body changed substantively | Update |
| **CLOSE** | Issue exists, plan step removed | Close with comment |
| **NO-OP** | Issue exists, body is rich, no plan change | Skip |
### Step 5 — Preview
Print all proposed changes grouped by phase:
```text
repo-sync: documentation/plans/phase-d-build-plan.md (Phase D)
Build doc richness: 3/8 steps rich, 5/8 lean
CREATE umbrella Phase D — Build-order z-statistic (reward refactor)
CREATE step Phase D Step 1: Audit reward_rules.json (rich body)
CREATE step Phase D Step 2: Define z schema (rich body)
CREATE step Phase D Step 3: build_order_reward.py (lean — Files missing)
ENRICH Phase D Step 5 (#168) — body lacks Done when + Files
UPDATE Phase D Step 7 (#170) — title changed
CLOSE (none)
NO-OP (none)
```
If `--dry-run` was specified, stop here and print:
```text
Dry-run complete. No changes applied.
```
Otherwise, proceed directly to Step 6 — print `Applying changes now...`
and execute. **Do not prompt for confirmation.** The preview is the
operator's read-out, not a halt point; autonomous orchestration
(`/build-phase`, `/plan-expedite`) depends on this.
#### --dry-run flag
When `/repo-sync --dry-run` is invoked, the preview above is printed but
no changes are applied. The skill exits cleanly with the message
`Dry-run complete. No changes applied.` Use this to validate plan→issue
mapping before committing to a sync.
### Step 6 — Execute (one tool call per gh action)
Process in this order:
1. Umbrella issues first (so step issues can reference them)
2. Step issue creates
3. Step issue enrichments + updates
4. Closes last
Each `gh issue create/edit/close` is its own Bash tool invocation, OR a
loop in one Bash with explicit per-iteration error handling. Do NOT
batch with `&&` — one failure must not break the chain.
#### Body delivery — always use `--body-file`
All `gh issue create/edit` calls in this skill MUST deliver bodies via `--body-file <path>`, never inline `--body "$(cat <<EOF ... EOF)"`. The inline heredoc form silently truncates or parser-tangles bodies that contain nested quote levels (code spans, quoted text, tables) — see `dev/.claude/rules/windows-shell.md` § gh / jq.
Use a Windows-safe temp path:
- Bash: `$LOCALAPPDATA/Temp/` (the Windows per-user temp dir, not `/tmp`)
- PowerShell: `$env:TEMP`
POSIX `/tmp/` is invisible to `gh.exe` on Windows (different temp roots).
The Create / Update / Close templates below all assume this delivery method.
#### Body template — umbrella
```markdown
**Umbrella:** #<master-plan-umbrella-issue-if-exists>
**Blocked by:** Phase <prerequisite-phase-if-any>
**Build doc:** `<build-doc-path>` (linked to `../blob/<default-branch>/<build-doc-path>`)
**Track:** <track-from-plan>
## Goal
<goal paragraph from plan>
## Work (N steps)
- [ ] **#<step-1-issue>** Step 1: <name>
- [ ] **#<step-2-issue>** Step 2: <name>
...
(Step issue numbers populated after step creates — re-edit umbrella in Step 7.)
## Acceptance
<validation / acceptance from plan>
## Effort
<effort estimate from plan>
## Kill criterion
<kill criterion from plan>
```
#### Body template — step
```markdown
## Build step N of M — Phase <X> (umbrella #<umbrella-issue>)
**Build doc:** `<build-doc-path>` (linked to `../blob/<default-branch>/<build-doc-path>`) §<section> Step <X.N>
### What to build
<full description from plan, not abbreviated>
### Existing context
<from plan's "Existing context" section if present, scoped to this step>
<otherwise: omit (will be flagged in summary)>
### Files to modify/create
<file list from plan if present>
<otherwise: omit (flagged in summary)>
### Done when
<acceptance from plan, specific not generic>
<otherwise: "All tests green, mypy strict + ruff clean. See umbrella for phase-level gate.">
### Flags (recommended)
<build-step flags from plan if present, e.g. `--reviewers code --isolation worktree`>
<if step touches frontend/, /api/ shapes, or WebSocket payloads: ALSO include `--ui`>
### Depends on
<previous step issue # if known, or "none">
### Parallel-safe with
<list any open step issue # in the same phase that shares no Files and no
Depends-on with this step. When no such peers exist, write
`none — strictly sequential (<one-line justification>)`. The justification
is REQUIRED — bare "strictly sequential" without a reason hides the
choice from the operator. Acceptable justifications: "Step N+1 imports
this module", "shares <Files entry> with #X", "soak gate after Step N
must finish first". When the plan is lean (no Depends on, no Files
declared), default to listing peers as parallel-safe rather than
collapsing to strictly sequential.>
### Produces
<list from plan if present>
### Operator workflow notes (autonomous + UI-bundle + parallel)
- This step is intended to run end-to-end via `/build-step` without
mid-iteration check-ins; the `Done when` above is the verification gate.
- If `--ui` is in the Flags line above, UI evidence (Playwright screenshot,
or any project-specific UI/dashboard smoke commands defined in the
project's `CLAUDE.md`) is part of acceptance, not a follow-up.
- Parallel-safe pairs above can be dispatched in parallel worktrees by
`/build-phase`.
---
*Synced from `<plan>` (linked to `../blob/<default-branch>/<plan>`) by /repo-sync at <git-short-sha>*
```
The footer with the source path + SHA helps a future LLM verify whether
the issue body is current vs the build doc.
Sections without source content can be omitted, but **issues missing
>2 of {Existing context, Files, Done when, Flags, Produces} are flagged
in the summary** as candidates for follow-up enrichment.
#### Update / enrich
```bash
# Windows-safe temp path; POSIX /tmp/ is invisible to gh.exe.
BODY_FILE="$LOCALAPPDATA/Temp/repo-sync-issue-$NUMBER.md"
cat > "$BODY_FILE" << 'BODYEOF'
<full new body following template>
---
*Enriched by /repo-sync from <build-doc-path> @ <git-short-sha>*
BODYEOF
gh issue edit <NUMBER> --title "<title>" --body-file "$BODY_FILE"
rm "$BODY_FILE"
```
#### Close
```bash
gh issue close <NUMBER> --comment "Closed by /repo-sync — step removed from plan."
```
### Step 7 — Re-edit umbrellas with step references
After step issues are created, edit each phase's umbrella issue to
include the **Work** checklist with actual issue numbers:
```markdown
## Work (N steps)
- [ ] **#164** Step 1: Audit reward_rules.json
- [ ] **#165** Step 2: Define z schema
...
```
This creates bidirectional cross-refs that an LLM can follow either
direction. Without this, the umbrella has stale `<step-1-issue>`
placeholders or a generic `(steps will be cut by /repo-sync)` note,
which forces the LLM to do a separate `gh issue list` to find them.
### Step 8 — Report
The final line of the report MUST surface this skill's plan-pipeline
position — `step 4 of 5: after /plan-review + /plan-wrap, before
/build-phase` — so the operator and any fresh-context downstream LLM
see at a glance what runs next. The breadcrumb is non-optional.
```text
repo-sync complete for Phase D (umbrella #114)
Plan pipeline: /plan-review + /plan-wrap → /repo-sync (step 4 of 5) → /build-phase
Created: 1 umbrella, 8 step issues (#164–#171)
Enriched: 0
Updated: 0
Closed: 0
Body richness: 3/8 issues fully rich; 5/8 missing Files/Existing-context
Cross-refs: umbrella #114 updated with step issue links
Recommendation: build-doc step richness was lean (5/8). Consider
enriching documentation/plans/phase-d-build-plan.md with explicit
per-step Files / Done when / Existing context sections, then
re-run with --enrich to bring issues to richer state.
```
If new issues were created, the operator (or the orchestrator)
backfills the plan's `**Issue:**` lines so `/build-phase` can post
progress updates — e.g., via the pattern below. The skill itself
does not back-propagate; surfacing the pattern is enough for the
operator to run once after sync.
Copy-paste bulk-fill snippet (Python). Adapt the `ISSUE_MAP` from
the sync output's "Created" / "Enriched" mapping:
```python
# Backfill **Issue:** #N lines after /repo-sync.
# Save the sync output's "Created" or "Enriched" mapping as
# {step_number: issue_number}, e.g.:
ISSUE_MAP = {
1: 164, # Step 1 -> issue #164
2: 165,
# ...
}
import re, pathlib
# REPLACE <plan-file> with your plan's actual filename,
# e.g. "documentation/phase-rs-plan.md".
plan = pathlib.Path("documentation/<plan-file>")
text = plan.read_text(encoding="utf-8")
for step_n, issue_n in ISSUE_MAP.items():
# Match Step N heading, then the immediately-following
# **Issue:** line (which may be #N, TBD, or empty).
# No re.DOTALL: `.` does not match newlines, so `.*?\n`
# stays within a single line and the bullet-eater group
# matches only consecutive single-line bullets. If a step
# is missing its **Issue:** bullet entirely, the pattern
# fails to match for that step and the script safely skips
# it (no cross-step contamination).
pattern = (
rf"(### Step {step_n}:.*?\n(?:- \*\*[^*]+\*\*.*?\n)*?"
rf"- \*\*Issue:\*\* )(#\d+|TBD|)"
)
text = re.sub(pattern, rf"\g<1>#{issue_n}", text)
plan.write_text(text, encoding="utf-8")
```
Verification — after a fully-populated backfill, the following
returns empty (no remaining `TBD` or blank `**Issue:**` values).
REPLACE `<plan-file>` with your plan's actual filename:
```bash
grep -nE "Issue:\*\*\s*(TBD\s*$|#\s*$|$)" documentation/<plan-file>
```
This pattern is one instance of the broader bulk-placeholder-fill
discipline (see `feedback_bulk_placeholder_fills.md`). Background
and rationale in investigation
`docs/investigations/skill-deep-dives/repo-sync/03-issue-blank-lines-kill-build-phase.md`.
---
## Matching rules (extended)
Issue matching is prefix-based on the step key. The skill normalizes:
- Whitespace
- Phase notation: `Phase D` ≡ `Phase D` (no normalization across letter/digit; B != 2; D != 4)
- Sub-phase: `Phase G.2 Step 1` matches plan `G.2.1` or `Step 1` within phase G.2
Manually renamed issue titles still match as long as the step prefix
(`Phase X Step N` or `Phase X.M Step N`) is preserved.
---
## Edge cases
- **Cross-plan step-key collision:** Step keys collide when a
repo holds issues from multiple plans (`Phase D Step 3`
exists in plan A and plan B). The Step 3.1 check (see Flow)
flags these via the body footer's plan path. Workaround for
new plans that share step keys with closed prior plans:
bypass `/repo-sync` for the new plan and create issues
manually with namespaced titles (`<feature> — Phase X Step
N: <name>`); those manual issues will not be re-matched by
future runs. See investigation
`docs/investigations/skill-deep-dives/repo-sync/01-step-key-collision.md`.
- **Closed issue, step still in plan:** Show as `REOPEN?` in preview. Require explicit confirmation.
- **Multiple issues match same step key:** Warn and skip — user must resolve manually.
- **Plan has no umbrella H1, just steps:** Skip umbrella creation; only step issues.
- **No steps found:** Error: `No steps found in <path>. Expected "### Step N:", "### Phase X Step N:", or "| X.N | ... |" table row.`
- **No GitHub repo:** See Step 0 — Pre-flight. The resolve command halts early if no repo is found.
- **Numbering gaps:** If plan jumps from Phase 7 to Phase 9 (intentional), don't try to create Phase 8. Honor the plan as written.
- **Existing umbrella, plan adds new steps:** Create new step issues + re-edit umbrella to add their links.
- **Step issue exists but lean, build doc still lean:** ENRICH would be a no-op. Recommend doc enrichment in summary; do not edit issue.
---
## Common mistakes
**Batching gh calls in one shell command**
- Fix: One `gh issue create/edit/close` per call, separate Bash tool invocations OR a loop in one Bash with explicit per-iteration error handling.
**Halting mid-sync for confirmation**
- Fix: Preview-then-execute is the default; no `(y/n)` prompt. Operators who want preview-only behavior pass `--dry-run`. Autonomous orchestrators (`/build-phase`, `/plan-expedite`) depend on this — a mid-sync halt breaks them.
**Matching by issue number instead of title prefix**
- Fix: Issue numbers change. Always match by the step-key prefix in the title.
**Using Perl-style regex escapes in `--jq` filters**
- Fix: jq's regex engine does NOT accept `\d`, `\w`, `\s`, `\.`
(and most other Perl-style shorthand). It silently rejects
the filter or returns empty matches — failing the
classification, which then surfaces as duplicate-issue
CREATEs in Step 5 preview. Use POSIX classes or literal
character sets:
| Avoid | Use |
|---|---|
| `\d` | `[0-9]` |
| `\w` | `[a-zA-Z0-9_]` |
| `\s` | `[ \t\n\r]` (POSIX whitespace; or the named class with single-bracket pairs the engine supports) |
| `\.` | `[.]` |
Prefer regex-free forms when the prefix is fixed:
`startswith("Phase D")` beats `test("^Phase D")` and
sidesteps the escape limit entirely.
Reference: `feedback_jq_regex_escape_limits.md` and
investigation `docs/investigations/skill-deep-dives/repo-sync/13-jq-regex-escaping.md`.
PowerShell-specific quoting issues for `gh -q` are
documented in `dev/.claude/rules/windows-shell.md` § gh / jq.
**Lean bodies on creation**
- Fix: Run the doc richness check first. If steps are lean, propose enriching the build doc before creating issues. Don't normalize lean issues as the steady state.
**Forgetting umbrella back-references**
- Fix: After creating step issues, edit the umbrella to include the **Work** checklist with issue numbers. Bidirectional links matter.
**Ignoring sub-phase notation**
- Fix: Phase G.2 is its own phase, not "Phase G". Match titles accordingly.
**Skipping the doc-richness warning**
- Fix: A lean issue taxes future LLM sessions every time someone opens it. Surface this cost explicitly; default to enriching the doc first.
**Treating issue creation as one-shot**
- Fix: `--enrich` exists because issues drift behind build docs over time. Re-run the skill after each plan revision.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!