github-sync

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GitHub Sync — BMAD to GitHub Projects v2

GitHub 同步 — BMAD 到 GitHub Projects v2

Bidirectional sync between BMAD planning artifacts (epics, stories, sprint plan) stored as markdown files and GitHub Projects v2 for visual project tracking.
Quick navigation
  • gh
    CLI commands, GraphQL queries →
    references/gh-commands.md
  • Issue body template, field mapping, labels, milestones →
    references/content-mapping.md
  • Config file format →
    references/config-schema.md
  • Artifact parser script →
    scripts/parse-artifacts.py

用于可视化项目跟踪的,以markdown文件形式存储的BMAD规划工件(epics、stories、sprint计划)与GitHub Projects v2之间的双向同步。
快速导航
  • gh
    CLI命令、GraphQL查询 →
    references/gh-commands.md
  • Issue主体模板、字段映射、标签、里程碑 →
    references/content-mapping.md
  • 配置文件格式 →
    references/config-schema.md
  • 工件解析脚本 →
    scripts/parse-artifacts.py

Four Rules (Never Break These)

四条规则(绝对不能违反)

  1. Never sync automatically. Every mutating operation (create issues, update fields, modify files) requires generating a sync report first, presenting it to the user, and waiting for explicit approval before executing. The user must see exactly what will change.
  2. Field-level source of truth. Each field has one owner — either BMAD files or GitHub. During sync, the owner side always wins. Never overwrite the owner's data.
    • BMAD owns: story body, acceptance criteria, tasks, sprint assignment, epic grouping, dependencies
    • GitHub owns: status, dev assignment, task checkbox completion, story points, priority
  3. Idempotent operations. Running the same sync twice produces the same result. Link-back identifiers (H1 title links in story files,
    gh_item_url
    in planning frontmatter) prevent duplicate creation. Always check for existing sync state before creating.
  4. Never auto-parse issue bodies with a script. Issue body generation requires reading each story file directly with the Read tool and crafting the body manually following the template in
    references/content-mapping.md
    . Auto-parsing scripts fail silently in subtle ways: they strip task lists when formatting assumptions are wrong, gut dev notes by removing code blocks, and produce empty section headers. One bad push contaminates all 27 issues at once. Read the file. Write the body. No shortcuts.

  1. 永远不要自动同步。 每一项变更操作(创建issue、更新字段、修改文件)都需要先生成同步报告,展示给用户,并在执行前等待用户明确批准。用户必须清楚看到所有即将发生的变更。
  2. 字段级可信来源。 每个字段都有唯一的责任方——要么是BMAD文件,要么是GitHub。同步过程中,责任方的内容始终优先级最高,永远不要覆盖责任方的数据。
    • BMAD负责: story主体、验收标准、任务、sprint分配、epic分组、依赖关系
    • GitHub负责: 状态、开发人员分配、任务复选框完成状态、story点数、优先级
  3. 幂等操作。 两次运行相同的同步操作会产生相同的结果。回链标识符(story文件中的H1标题链接、规划前置元数据中的
    gh_item_url
    )可防止重复创建。创建前请始终检查现有同步状态。
  4. 永远不要用脚本自动解析issue主体。 生成issue主体需要直接使用Read工具读取每个story文件,并按照
    references/content-mapping.md
    中的模板手动编写主体。自动解析脚本会出现难以察觉的静默失败:当格式假设错误时会删除任务列表,移除代码块导致开发笔记丢失,还会生成空的章节标题。一次错误的推送会一次性污染所有27个issue。 读取文件,编写主体,不要走捷径。

Flow Detection

流程检测

User SaysWorkflowConfig Required?
"set up github project", "onboard", "initialize github"OnboardingNo (creates config)
"push to github", "sync push", "create issues"PushYes
"pull from github", "sync pull", "update from github"PullYes
"sync status", "what's out of sync"Status CheckYes
If no
.github-sync.yaml
exists at project root, always route to Onboarding first.

用户输入内容工作流是否需要配置?
"set up github project", "onboard", "initialize github"接入初始化不需要(会自动创建配置)
"push to github", "sync push", "create issues"推送需要
"pull from github", "sync pull", "update from github"拉取需要
"sync status", "what's out of sync"状态检查需要
如果项目根目录下不存在
.github-sync.yaml
时,始终优先路由到接入初始化流程。

Prerequisite Check (Run Before Every Workflow)

前置条件检查(每个工作流运行前执行)

Before any workflow, verify these in order. Stop at first failure.
Step 1: gh --version
        → If missing: "Install GitHub CLI: https://cli.github.com/"

Step 2: gh auth status
        → If not authenticated: "Run: gh auth login"

Step 3: gh auth status (check for "project" in scopes)
        → If missing: "Run: gh auth refresh -s project"

Step 4: (For push/pull/status only) Check .github-sync.yaml exists
        → If missing: "Run onboarding first: say 'set up github project'"

运行任何工作流之前,按顺序验证以下条件。遇到第一个失败项就停止。
Step 1: gh --version
        → 若未安装:"Install GitHub CLI: https://cli.github.com/"

Step 2: gh auth status
        → 若未认证:"Run: gh auth login"

Step 3: gh auth status (check for "project" in scopes
        → 若缺少权限:"Run: gh auth refresh -s project"

Step 4: (仅推送/拉取/状态检查时执行) 检查`.github-sync.yaml`是否存在
        → 若不存在:"Run onboarding first: say 'set up github project'"

Onboarding Workflow

接入初始化工作流

This is the first-time setup. It creates or connects to a GitHub Project, creates custom fields, labels, and phase-based milestones.
这是首次设置流程,会创建或关联GitHub Project,创建自定义字段、标签和基于阶段的里程碑。

Step 1: Detect BMAD Artifacts

步骤1:检测BMAD工件

Run the parser to discover what exists:
bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan \
  --stories-dir .artifacts/implementation-artifacts
Also check that these files exist:
  • .artifacts/planning-artifacts/epics.md
  • .artifacts/planning-artifacts/sprint-plan.md
Note: The artifacts path
.artifacts/
may differ per project. Check the actual directory structure — some projects use
_bmad-output/
. Confirm the correct paths with the user and use them throughout. Update
paths.*
in the config accordingly.
Report the count: "Found N story files, M epics, K sprints."
运行解析器发现现有内容:
bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan \
  --stories-dir .artifacts/implementation-artifacts
同时检查以下文件是否存在:
  • .artifacts/planning-artifacts/epics.md
  • .artifacts/planning-artifacts/sprint-plan.md
注意: 工件路径
.artifacts/
可能因项目不同而有差异。检查实际目录结构——部分项目使用
_bmad-output/
。请与用户确认正确路径并全程使用,同时相应更新配置中的
paths.*
项。
上报统计结果:"Found N story files, M epics, K sprints."

Step 2: Gather GitHub Details

步骤2:收集GitHub信息

Auto-detect the current repo:
bash
gh repo view --json owner,name --jq '.owner.login + "/" + .name'
List existing projects and ask the user whether to use one or create new:
bash
gh project list --owner {owner} --format json
Present detected owner/repo and existing projects. Ask for confirmation before proceeding.
自动检测当前仓库:
bash
gh repo view --json owner,name --jq '.owner.login + "/" + .name'
列出现有项目,询问用户是使用现有项目还是创建新项目:
bash
gh project list --owner {owner} --format json
展示检测到的所有者/仓库和现有项目,继续前请先征求用户确认。

Step 3: Parse Epic and Sprint Data

步骤3:解析Epic和Sprint数据

Read
references/content-mapping.md
now
— sections 7 (Label Scheme), 8 (Milestone Scheme), and 12 (Epic Derivation). You need these to build an accurate onboarding report.
Then parse the actual artifacts:
bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode epics \
  --file .artifacts/planning-artifacts/epics.md

python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode sprints \
  --file .artifacts/planning-artifacts/sprint-plan.md
立即读取
references/content-mapping.md
——第7节(标签方案)、第8节(里程碑方案)和第12节(Epic推导)。你需要这些内容来生成准确的初始化报告。
然后解析实际工件:
bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode epics \
  --file .artifacts/planning-artifacts/epics.md

python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode sprints \
  --file .artifacts/planning-artifacts/sprint-plan.md

Step 4: Generate Onboarding Report

步骤4:生成初始化报告

Present a report showing everything that WILL be created:
=== GITHUB SYNC — ONBOARDING REPORT ===

Repository: {owner}/{repo}
Project: #{N} "{title}" (existing) OR new project "{title}"

Will create/verify:
  Custom fields (7):
    - Story ID      (TEXT)
    - Epic          (SINGLE_SELECT: 12 options, rainbow colors)
    - Sprint        (SINGLE_SELECT: Sprint 01–12, rainbow colors + sprint goal descriptions)
    - Dev           (SINGLE_SELECT: All, Dev 1, Dev 2, Dev 3, Dev 1+2)
    - Sprint Start  (DATE)
    - Sprint End    (DATE)
    - Story Points  (NUMBER)
  Built-in fields to set:
    - Start date    (DATE, pre-existing)   ← same dates as Sprint Start
    - Target date   (DATE, pre-existing)   ← same dates as Sprint End
    - Status        (single-select, pre-existing)
  {N} labels:
    - Epic labels (one per epic, e.g., epic:1-foundation ... epic:12-testing)
    - Phase labels (e.g., phase:poc, phase:hardening)
    - Layer labels (optional, project-specific architecture layers)
  {K} milestones (phase-based, NOT per-sprint):
    - PoC              (due: {sprint_6_end})    Sprints 1–6
    - Production Hardening (due: {sprint_12_end}) Sprints 7–12

Note: No "Phase" custom field — the milestone covers phase membership.

Proceed with onboarding? [Y/N]
HALT HERE. Wait for user approval.
展示报告,列出所有即将创建的内容:
=== GITHUB SYNC — ONBOARDING REPORT ===

Repository: {owner}/{repo}
Project: #{N} "{title}" (existing) OR new project "{title}"

Will create/verify:
  Custom fields (7):
    - Story ID      (TEXT)
    - Epic          (SINGLE_SELECT: 12 options, rainbow colors)
    - Sprint        (SINGLE_SELECT: Sprint 01–12, rainbow colors + sprint goal descriptions)
    - Dev           (SINGLE_SELECT: All, Dev 1, Dev 2, Dev 3, Dev 1+2)
    - Sprint Start  (DATE)
    - Sprint End    (DATE)
    - Story Points  (NUMBER)
  Built-in fields to set:
    - Start date    (DATE, pre-existing)   ← same dates as Sprint Start
    - Target date   (DATE, pre-existing)   ← same dates as Sprint End
    - Status        (single-select, pre-existing)
  {N} labels:
    - Epic labels (one per epic, e.g., epic:1-foundation ... epic:12-testing)
    - Phase labels (e.g., phase:poc, phase:hardening)
    - Layer labels (optional, project-specific architecture layers)
  {K} milestones (phase-based, NOT per-sprint):
    - PoC              (due: {sprint_6_end})    Sprints 1–6
    - Production Hardening (due: {sprint_12_end}) Sprints 7–12

Note: No "Phase" custom field — the milestone covers phase membership.

Proceed with onboarding? [Y/N]
在此暂停,等待用户批准。

Step 5: Execute Setup

步骤5:执行设置

Read
references/gh-commands.md
now
— you need the exact commands for every operation below.
If approved, execute in this order:
  1. Create or connect GitHub Project (section 2) — if using existing, just get its node ID
  2. Create custom fields (section 3) — Story ID, Epic, Sprint, Dev, Sprint Start, Sprint End, Story Points
  3. Query all field IDs (section 4) — including the pre-existing Start date, Target date, Status fields
  4. Apply rainbow colors + sprint goal descriptions to Sprint and Epic fields (section 13)
    • Sprint options: cycle RED→ORANGE→YELLOW→GREEN→BLUE→PURPLE→PINK, repeat
    • Sprint description = sprint objective from sprint-plan.md
    • Epic options: RED→ORANGE→YELLOW→GREEN→BLUE→PURPLE→PINK→RED→ORANGE→YELLOW→GREEN→BLUE
  5. Create labels (section 5) — 17 labels total
  6. Create phase-based milestones (section 6) — PoC and Production Hardening
Critical: After calling
updateProjectV2Field
to set colors/descriptions, the single-select option IDs CHANGE (the mutation replaces the options list). Always re-query option IDs after calling this mutation and use the new IDs in the config.
立即读取
references/gh-commands.md
——你需要以下所有操作的准确命令。
如果获得批准,按以下顺序执行:
  1. 创建或关联GitHub Project(第2节)——如果使用现有项目,仅获取其节点ID
  2. 创建自定义字段(第3节)——Story ID、Epic、Sprint、Dev、Sprint Start、Sprint End、Story Points
  3. 查询所有字段ID(第4节)——包括预存在的Start date、Target date、Status字段
  4. 为Sprint和Epic字段应用彩虹色+sprint目标描述(第13节)
    • Sprint选项:按红→橙→黄→绿→蓝→紫→粉循环
    • Sprint描述 = sprint-plan.md中的sprint目标
    • Epic选项:红→橙→黄→绿→蓝→紫→粉→红→橙→黄→绿→蓝
  5. 创建标签(第5节)——共17个标签
  6. 创建基于阶段的里程碑(第6节)——PoC和Production Hardening
关键提示: 调用
updateProjectV2Field
设置颜色/描述后,单选选项ID会发生变化(该变更操作会替换选项列表)。调用此变更操作后请始终重新查询选项ID,并在配置中使用新ID。

Step 6: Write Config

步骤6:写入配置

Read
references/config-schema.md
now
— you need the exact YAML format.
Create
.github-sync.yaml
at project root with all populated IDs following that schema. Note: No
phase
field in
field_ids
or
option_ids
— Phase was replaced by milestones.
立即读取
references/config-schema.md
——你需要准确的YAML格式。
在项目根目录创建
.github-sync.yaml
,按照该schema填充所有ID。注意:
field_ids
option_ids
中没有
phase
字段——阶段已由里程碑替代。

Step 7: Report Completion

步骤7:上报完成结果

Onboarding complete!
  Project: https://github.com/orgs/{owner}/projects/{number}
  Config: .github-sync.yaml

Next: Run "push stories to github" to create issues.

Onboarding complete!
  Project: https://github.com/orgs/{owner}/projects/{number}
  Config: .github-sync.yaml

Next: Run "push stories to github" to create issues.

Push Workflow (Files → GitHub)

推送工作流(文件 → GitHub)

Pushes BMAD story files to GitHub as issues, adds them to the project, sets all fields, sets date fields, and establishes relationships.
将BMAD story文件作为issue推送到GitHub,添加到项目中,设置所有字段、日期字段并建立关联关系。

Step 1: Load Config

步骤1:加载配置

Read
.github-sync.yaml
. Verify all field IDs are populated. If any are empty, re-query field IDs from GitHub (the IDs may have been lost).
读取
.github-sync.yaml
,验证所有字段ID均已填充。如果有任何ID为空,重新从GitHub查询字段ID(ID可能丢失)。

Step 2: Scan Stories

步骤2:扫描Stories

bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan \
  --stories-dir .artifacts/implementation-artifacts
For each story, determine create vs edit mode:
  • H1 is plain
    # Story X.X: Title
    (no link) → CREATE
  • H1 contains
    # [Story X.X: Title](url)
    → UPDATE (already synced)
bash
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan \
  --stories-dir .artifacts/implementation-artifacts
对于每个story,判断是创建还是编辑模式:
  • H1是纯文本
    # Story X.X: Title
    (无链接)→ 创建
  • H1包含
    # [Story X.X: Title](url)
    → 更新(已同步过)

Step 3: Handle Partial Sync (Optional)

步骤3:处理部分同步(可选)

If the user specified a filter (e.g., "push stories 1.1 1.2", "push epic 1", "push sprint 2"), filter the story list before proceeding. If no filter, push all stories.
如果用户指定了筛选条件(例如"push stories 1.1 1.2"、"push epic 1"、"push sprint 2"),在继续前筛选story列表。如果没有筛选条件,推送所有stories。

Step 4: Read Story Files and Build Issue Content

步骤4:读取Story文件并构建Issue内容

⚠️ Rule 4 applies here: Read each file with the Read tool. Build bodies manually. No scripts.
For each story:
  1. Read the file using the Read tool
  2. Read
    references/content-mapping.md
    — sections 1–4 and 9 for the exact format
  3. Build the issue body following the template:
    • User story blockquote
    • AC as one-line Then-clause summaries (checkboxes)
    • Full task list (Task 2+ only — exclude agent-only tasks by reading content, not by position)
    • Dependencies with
      #N
      GitHub issue numbers
    • Collapsible dev notes: tables, config snippets, architecture patterns — NOT code skeletons, NOT ASCII trees, NOT "What NOT to Do" lists, NOT references
  4. Look up sprint/dev/epic from sprint-plan.md (NOT from the story file body)
⚠️ 此处适用规则4:使用Read工具读取每个文件,手动构建主体,不要使用脚本。
对于每个story:
  1. 使用Read工具读取文件
  2. 读取
    references/content-mapping.md
    ——第1-4节和第9节获取准确格式
  3. 按照模板构建issue主体:
    • 用户故事引用块
    • 验收标准作为单行Then子句摘要(复选框形式)
    • 完整任务列表(仅任务2及以后——通过内容读取排除仅Agent使用的任务,不要按位置判断)
    • 依赖关系,附带
      #N
      格式的GitHub issue编号
    • 可折叠的开发笔记:表格、配置片段、架构模式——不要包含代码骨架、ASCII树、"禁止操作"列表、参考内容
  4. 从sprint-plan.md查询sprint/开发人员/epic(不要从story文件主体获取)

Step 5: Generate Sync Report

步骤5:生成同步报告

=== GITHUB SYNC — PUSH REPORT ===
Generated: {timestamp}

--- CREATES ({count} new issues) ---

  [CREATE] {story_id} {short_title}
           File: {story_file_path}
           Epic: {epic_label} | Sprint: {sprint} | Dev: {dev} | Phase: {phase}
           Labels: epic:{N}-{name}, phase:{phase}
           Milestone: {PoC | Production Hardening}

--- UPDATES ({count} existing issues) ---

  [UPDATE] {story_id} {short_title} (#{issue_number})
           Changes: body updated

--- SKIPPED ({count} items) ---

  [SKIP] {story_id} {short_title} — already synced, no local changes

--- SUMMARY ---
Creates: {N} | Updates: {N} | Skips: {N}

Proceed? [Y/N]
HALT HERE. Wait for user approval.
=== GITHUB SYNC — PUSH REPORT ===
Generated: {timestamp}

--- CREATES ({count} new issues) ---

  [CREATE] {story_id} {short_title}
           File: {story_file_path}
           Epic: {epic_label} | Sprint: {sprint} | Dev: {dev} | Phase: {phase}
           Labels: epic:{N}-{name}, phase:{phase}
           Milestone: {PoC | Production Hardening}

--- UPDATES ({count} existing issues) ---

  [UPDATE] {story_id} {short_title} (#{issue_number})
           Changes: body updated

--- SKIPPED ({count} items) ---

  [SKIP] {story_id} {short_title} — already synced, no local changes

--- SUMMARY ---
Creates: {N} | Updates: {N} | Skips: {N}

Proceed? [Y/N]
在此暂停,等待用户批准。

Step 6: Execute Push

步骤6:执行推送

If approved, for each CREATE:
  1. Write issue body to a temp file (
    /tmp/issue-{story_id}.md
    )
  2. gh issue create --title "..." --body-file /tmp/... --label "epic:X-name" --label "phase:poc" --milestone "{PoC|Production Hardening}"
  3. Extract issue URL from output
  4. gh project item-add {project_number} --owner {owner} --url {issue_url} --format json
  5. Extract item ID from JSON output
  6. Set all project fields using
    gh project item-edit
    :
    • Story ID (text)
    • Epic (single-select option)
    • Sprint (single-select option, e.g., "Sprint 01")
    • Dev (single-select option)
    • Sprint Start (date from sprint-plan.md)
    • Sprint End (date from sprint-plan.md)
    • Status (Backlog)
    • Start date (same date as Sprint Start — pre-existing field)
    • Target date (same date as Sprint End — pre-existing field)
  7. Write link-back to local file: replace H1 with
    # [Story X.X: Title](issue_url)
For each UPDATE:
  1. Write updated body to temp file
  2. gh issue edit {number} --body-file /tmp/... --milestone "{phase_milestone}"
  3. Update project fields if sprint/epic changed
如果获得批准,对每个创建项:
  1. 将issue主体写入临时文件(
    /tmp/issue-{story_id}.md
  2. gh issue create --title "..." --body-file /tmp/... --label "epic:X-name" --label "phase:poc" --milestone "{PoC|Production Hardening}"
  3. 从输出中提取issue URL
  4. gh project item-add {project_number} --owner {owner} --url {issue_url} --format json
  5. 从JSON输出中提取项目ID
  6. 使用
    gh project item-edit
    设置所有项目字段:
    • Story ID(文本)
    • Epic(单选选项)
    • Sprint(单选选项,例如"Sprint 01")
    • Dev(单选选项)
    • Sprint Start(来自sprint-plan.md的日期)
    • Sprint End(来自sprint-plan.md的日期)
    • Status(Backlog)
    • Start date(与Sprint Start相同日期——预存字段)
    • Target date(与Sprint End相同日期——预存字段)
  7. 写入回链到本地文件:将H1替换为
    # [Story X.X: Title](issue_url)
对每个更新项:
  1. 将更新后的主体写入临时文件
  2. gh issue edit {number} --body-file /tmp/... --milestone "{phase_milestone}"
  3. 如果sprint/epic发生变化则更新项目字段

Step 7: Set Up Relationships

步骤7:设置关联关系

After all issues are created, establish GitHub native relationships.
Read
references/gh-commands.md
section 12
for the exact GraphQL mutations.
所有issue创建完成后,建立GitHub原生关联关系。
读取`references/gh-commands.md第12节获取准确的GraphQL变更语句。

7a. Epic tracking issues as parents

7a. Epic跟踪issue作为父项

Create one epic tracking issue per epic (if not already created). See
references/content-mapping.md
section 10 for the body template. Then for each story, set its epic tracking issue as its parent:
graphql
mutation {
  addSubIssue(input: {
    issueId: "{epic_tracking_issue_node_id}"
    subIssueId: "{story_issue_node_id}"
    replaceParent: true
  }) {
    issue { number }
    subIssue { number }
  }
}
每个epic创建一个epic跟踪issue(如果尚未创建)。参考
references/content-mapping.md
第10节获取主体模板。然后对每个story,将其epic跟踪issue设置为其父项:
graphql
mutation {
  addSubIssue(input: {
    issueId: "{epic_tracking_issue_node_id}"
    subIssueId: "{story_issue_node_id}"
    replaceParent: true
  }) {
    issue { number }
    subIssue { number }
  }
}

7b. Blocked-by dependencies

7b. 阻塞依赖关系

Read the dependency table from
sprint-plan.md
(the
Dependencies
column in each sprint's story table). For each dependency
A → B
(story A depends on story B):
graphql
mutation {
  addBlockedBy(input: {
    issueId: "{story_A_node_id}"
    blockingIssueId: "{story_B_node_id}"
  }) {
    issue { number }
    blockingIssue { number }
  }
}
Always source dependencies from sprint-plan.md, not from story file bodies. The sprint plan is the authoritative dependency record.
Get issue node IDs via:
bash
gh api graphql -f query='
  query {
    repository(owner:"{owner}", name:"{repo}") {
      issues(first:50, orderBy:{field:CREATED_AT, direction:ASC}) {
        nodes { number id title }
      }
    }
  }
'
sprint-plan.md
读取依赖表(每个sprint的story表中的
Dependencies
列)。对每个依赖
A → B
(story A依赖story B):
graphql
mutation {
  addBlockedBy(input: {
    issueId: "{story_A_node_id}"
    blockingIssueId: "{story_B_node_id}"
  }) {
    issue { number }
    blockingIssue { number }
  }
}
始终从sprint-plan.md获取依赖关系,不要从story文件主体获取。 sprint计划是权威的依赖记录。
通过以下方式获取issue节点ID:
bash
gh api graphql -f query='
  query {
    repository(owner:"{owner}", name:"{repo}") {
      issues(first:50, orderBy:{field:CREATED_AT, direction:ASC}) {
        nodes { number id title }
      }
    }
  }
'

Step 8: Report Completion

步骤8:上报完成结果

Push complete!
  Created: {N} issues
  Updated: {N} issues
  Skipped: {N} items
  Relationships set: {N} parent, {M} blocked-by

Config updated: last_synced = {timestamp}

Push complete!
  Created: {N} issues
  Updated: {N} issues
  Skipped: {N} items
  Relationships set: {N} parent, {M} blocked-by

Config updated: last_synced = {timestamp}

Pull Workflow (GitHub → Files)

拉取工作流(GitHub → 文件)

Pulls status, assignees, and task completion from GitHub back into local BMAD files.
将状态、负责人和任务完成情况从GitHub拉取回本地BMAD文件。

Step 1: Load Config and Query GitHub

步骤1:加载配置并查询GitHub

Read
.github-sync.yaml
. Then read
references/gh-commands.md
section 9
to get the full GraphQL items query. Execute it to fetch all project items.
读取
.github-sync.yaml
,然后读取
references/gh-commands.md
第9节
获取完整的GraphQL项目项查询语句。执行查询获取所有项目项。

Step 2: Match Items to Local Files

步骤2:匹配项目项与本地文件

For each GitHub item that has a "Story ID" field value:
  1. Find the matching local story file (by story ID → filename pattern)
  2. Compare GitHub state with local file state:
    • Status: GitHub status vs local
      Status:
      line
    • Assignee: GitHub assignee vs local dev mapping
    • Task checkboxes: GitHub issue body checkboxes vs local file checkboxes
对每个有"Story ID"字段值的GitHub项:
  1. 找到匹配的本地story文件(通过story ID → 文件名模式)
  2. 比较GitHub状态与本地文件状态:
    • 状态:GitHub状态 vs 本地
      Status:
    • 负责人:GitHub负责人 vs 本地开发人员映射
    • 任务复选框:GitHub issue主体复选框 vs 本地文件复选框

Step 3: Generate Sync Report

步骤3:生成同步报告

=== GITHUB SYNC — PULL REPORT ===
Generated: {timestamp}

--- FILE UPDATES ({count} items) ---

  [UPDATE] {story_filename}.md
           Status: ready-for-dev → done (from GitHub #{issue_number})
           Assignee: (none) → @{username}

--- NO CHANGES ({count} items) ---

  [OK] {story_filename}.md — in sync

--- GITHUB-ONLY ({count} items) ---

  [WARN] GitHub #{N} "{title}" — no matching local file

--- SUMMARY ---
File updates: {N} | No changes: {N} | Warnings: {N}

Proceed? [Y/N]
HALT HERE. Wait for user approval.
=== GITHUB SYNC — PULL REPORT ===
Generated: {timestamp}

--- FILE UPDATES ({count} items) ---

  [UPDATE] {story_filename}.md
           Status: ready-for-dev → done (from GitHub #{issue_number})
           Assignee: (none) → @{username}

--- NO CHANGES ({count} items) ---

  [OK] {story_filename}.md — in sync

--- GITHUB-ONLY ({count} items) ---

  [WARN] GitHub #{N} "{title}" — no matching local file

--- SUMMARY ---
File updates: {N} | No changes: {N} | Warnings: {N}

Proceed? [Y/N]
在此暂停,等待用户批准。

Step 4: Execute Pull

步骤4:执行拉取

If approved, for each file update:
  1. Read the story file
  2. Update the
    Status:
    line with the mapped BMAD status
  3. Write the file back
  4. Update config
    last_synced

如果获得批准,对每个文件更新项:
  1. 读取story文件
  2. 用映射后的BMAD状态更新
    Status:
  3. 写回文件
  4. 更新配置的
    last_synced

Status Check (Read-Only)

状态检查(只读)

Compare local files with GitHub state without making any changes. No approval needed.
bash
undefined
比较本地文件与GitHub状态,不做任何变更,无需批准。
bash
undefined

Scan local files

扫描本地文件

python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan
--stories-dir .artifacts/implementation-artifacts
python3 .agents/skills/github-sync/scripts/parse-artifacts.py --mode scan
--stories-dir .artifacts/implementation-artifacts

Query GitHub items (full field values)

查询GitHub项目项(完整字段值)

Use GraphQL query from references/gh-commands.md section 9

使用references/gh-commands.md第9节的GraphQL查询


Output a comparison table:
=== GITHUB SYNC — STATUS ===
StoryLocal StatusGitHub StatusSprintSynced?Issue
1.1ready-for-devDone01NO#1
1.2ready-for-devReady01YES#2
2.1backlog(not synced)02NO
Summary: {N} in sync, {M} out of sync, {K} not yet pushed

---

输出对比表:
=== GITHUB SYNC — STATUS ===
StoryLocal StatusGitHub StatusSprintSynced?Issue
1.1ready-for-devDone01NO#1
1.2ready-for-devReady01YES#2
2.1backlog(not synced)02NO
Summary: {N} in sync, {M} out of sync, {K} not yet pushed

---

Partial Sync Filters

部分同步筛选器

FilterExampleEffect
By story IDs
push stories 1.1 1.2 1.3
Only these stories
By epic
push epic 3
All stories in Epic 3
By sprint
push sprint 2
All stories assigned to Sprint 2
By status
push unsynced
Only stories not yet pushed
All
push
or
push all
All stories (default)

筛选维度示例效果
按story ID
push stories 1.1 1.2 1.3
仅同步这些stories
按epic
push epic 3
同步Epic 3下的所有stories
按sprint
push sprint 2
同步分配到Sprint 2的所有stories
按状态
push unsynced
仅同步尚未推送的stories
全部
push
push all
同步所有stories(默认)

Error Handling

错误处理

ErrorAction
gh
command returns non-zero exit code
Show the error output, suggest fix, halt
Field ID missing from configRe-query field IDs via section 4 of gh-commands.md
Rate limit hit (HTTP 429)Show warning, suggest waiting 60 seconds, halt
Story file has unexpected formatSkip with warning in the sync report
Milestone already existsSkip creation (idempotent)
Label already existsSkip creation (idempotent)
Issue already exists for storySwitch to update mode
Single-select option IDs staleRe-query after any
updateProjectV2Field
call — the mutation replaces all options and issues new IDs
addBlockedBy
payload field error
Return field is
blockingIssue
(not
blockedByIssue
)
updateProjectV2Field
rejects
projectId
This mutation takes only
fieldId
, not
projectId
updateProjectV2Field
rejects option
id
Options use
name
/
color
/
description
only — no
id
field

错误处理方式
gh
命令返回非零退出码
展示错误输出,给出修复建议,终止流程
配置中缺少字段ID通过gh-commands.md第4节重新查询字段ID
触发速率限制(HTTP 429)展示警告,建议等待60秒,终止流程
Story文件格式不符合预期在同步报告中给出警告并跳过
里程碑已存在跳过创建(幂等)
标签已存在跳过创建(幂等)
Story对应的issue已存在切换到更新模式
单选选项ID过期任何
updateProjectV2Field
调用后重新查询——该变更操作会替换所有选项并生成新ID
addBlockedBy
payload字段错误
返回字段是
blockingIssue
(不是
blockedByIssue
updateProjectV2Field
拒绝
projectId
该变更操作仅接受
fieldId
,不接受
projectId
updateProjectV2Field
拒绝选项
id
选项仅使用
name
/
color
/
description
——没有
id
字段

Reference File Index

参考文件索引

FileRead When
references/gh-commands.md
You need exact
gh
CLI commands or GraphQL queries
references/content-mapping.md
You need to build issue body, map fields, or check label/milestone scheme
references/config-schema.md
You need to create or read
.github-sync.yaml
文件读取时机
references/gh-commands.md
需要准确的
gh
CLI命令或GraphQL查询时
references/content-mapping.md
需要构建issue主体、映射字段或检查标签/里程碑方案时
references/config-schema.md
需要创建或读取
.github-sync.yaml