forge-workflow 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/dev.md +345 -340
- package/.claude/commands/plan.md +566 -521
- package/.claude/commands/premerge.md +186 -176
- package/.claude/commands/research.md +42 -42
- package/.claude/commands/review.md +448 -442
- package/.claude/commands/rollback.md +721 -721
- package/.claude/commands/ship.md +212 -164
- package/.claude/commands/sonarcloud.md +152 -152
- package/.claude/commands/status.md +90 -48
- package/.claude/commands/validate.md +288 -282
- package/.claude/commands/verify.md +269 -221
- package/.claude/rules/greptile-review-process.md +285 -285
- package/.claude/rules/workflow.md +121 -105
- package/.claude/scripts/greptile-resolve.sh +558 -526
- package/.claude/scripts/load-env.sh +32 -32
- package/.cline/workflows/dev.md +342 -337
- package/.cline/workflows/plan.md +563 -518
- package/.cline/workflows/premerge.md +183 -173
- package/.cline/workflows/research.md +39 -39
- package/.cline/workflows/review.md +445 -439
- package/.cline/workflows/rollback.md +718 -718
- package/.cline/workflows/ship.md +209 -161
- package/.cline/workflows/sonarcloud.md +146 -146
- package/.cline/workflows/status.md +87 -45
- package/.cline/workflows/validate.md +285 -279
- package/.cline/workflows/verify.md +266 -218
- package/.codex/config.toml +11 -11
- package/.codex/skills/dev/SKILL.md +345 -340
- package/.codex/skills/plan/SKILL.md +566 -521
- package/.codex/skills/premerge/SKILL.md +186 -176
- package/.codex/skills/research/SKILL.md +42 -42
- package/.codex/skills/review/SKILL.md +448 -442
- package/.codex/skills/rollback/SKILL.md +721 -721
- package/.codex/skills/ship/SKILL.md +212 -164
- package/.codex/skills/sonarcloud/SKILL.md +149 -149
- package/.codex/skills/status/SKILL.md +90 -48
- package/.codex/skills/validate/SKILL.md +288 -282
- package/.codex/skills/verify/SKILL.md +269 -221
- package/.cursor/commands/dev.md +342 -337
- package/.cursor/commands/plan.md +563 -518
- package/.cursor/commands/premerge.md +183 -173
- package/.cursor/commands/research.md +39 -39
- package/.cursor/commands/review.md +445 -439
- package/.cursor/commands/rollback.md +718 -718
- package/.cursor/commands/ship.md +209 -161
- package/.cursor/commands/sonarcloud.md +146 -146
- package/.cursor/commands/status.md +87 -45
- package/.cursor/commands/validate.md +285 -279
- package/.cursor/commands/verify.md +266 -218
- package/.cursor/rules/permissions-guidance.mdc +37 -37
- package/.forge/hooks/check-tdd.js +240 -240
- package/.github/PLUGIN_TEMPLATE.json +32 -32
- package/.github/prompts/dev.prompt.md +347 -342
- package/.github/prompts/plan.prompt.md +568 -523
- package/.github/prompts/premerge.prompt.md +188 -178
- package/.github/prompts/research.prompt.md +44 -44
- package/.github/prompts/review.prompt.md +450 -444
- package/.github/prompts/rollback.prompt.md +723 -723
- package/.github/prompts/ship.prompt.md +214 -166
- package/.github/prompts/sonarcloud.prompt.md +151 -151
- package/.github/prompts/status.prompt.md +92 -50
- package/.github/prompts/validate.prompt.md +290 -284
- package/.github/prompts/verify.prompt.md +271 -223
- package/.github/workflows/beads-to-github.yml +56 -0
- package/.github/workflows/github-to-beads.yml +97 -0
- package/.kilocode/workflows/dev.md +346 -341
- package/.kilocode/workflows/plan.md +567 -522
- package/.kilocode/workflows/premerge.md +187 -177
- package/.kilocode/workflows/research.md +43 -43
- package/.kilocode/workflows/review.md +449 -443
- package/.kilocode/workflows/rollback.md +722 -722
- package/.kilocode/workflows/ship.md +213 -165
- package/.kilocode/workflows/sonarcloud.md +150 -150
- package/.kilocode/workflows/status.md +91 -49
- package/.kilocode/workflows/validate.md +289 -283
- package/.kilocode/workflows/verify.md +270 -222
- package/.mcp.json.example +12 -12
- package/.opencode/commands/dev.md +345 -340
- package/.opencode/commands/plan.md +566 -521
- package/.opencode/commands/premerge.md +186 -176
- package/.opencode/commands/research.md +42 -42
- package/.opencode/commands/review.md +448 -442
- package/.opencode/commands/rollback.md +721 -721
- package/.opencode/commands/ship.md +212 -164
- package/.opencode/commands/sonarcloud.md +149 -149
- package/.opencode/commands/status.md +90 -48
- package/.opencode/commands/validate.md +288 -282
- package/.opencode/commands/verify.md +269 -221
- package/.roo/commands/dev.md +346 -341
- package/.roo/commands/plan.md +567 -522
- package/.roo/commands/premerge.md +187 -177
- package/.roo/commands/research.md +43 -43
- package/.roo/commands/review.md +449 -443
- package/.roo/commands/rollback.md +722 -722
- package/.roo/commands/ship.md +213 -165
- package/.roo/commands/sonarcloud.md +150 -150
- package/.roo/commands/status.md +91 -49
- package/.roo/commands/validate.md +289 -283
- package/.roo/commands/verify.md +270 -222
- package/AGENTS.md +272 -175
- package/CLAUDE.md +110 -100
- package/README.md +429 -416
- package/bin/forge-cmd.js +317 -313
- package/bin/forge-preflight.js +322 -309
- package/bin/forge.js +4765 -4303
- package/docs/AGENT_INSTALL_PROMPT.md +342 -342
- package/docs/BEADS_GITHUB_SYNC.md +251 -251
- package/docs/ENHANCED_ONBOARDING.md +612 -602
- package/docs/EXAMPLES.md +482 -482
- package/docs/GREPTILE_SETUP.md +400 -400
- package/docs/MANUAL_REVIEW_GUIDE.md +106 -106
- package/docs/ROADMAP.md +359 -359
- package/docs/SETUP.md +663 -631
- package/docs/TOOLCHAIN.md +653 -630
- package/docs/VALIDATION.md +363 -363
- package/install.sh +40 -1056
- package/lefthook.yml +50 -39
- package/lib/agents/README.md +198 -198
- package/lib/agents/claude.plugin.json +28 -28
- package/lib/agents/cline.plugin.json +22 -22
- package/lib/agents/codex.plugin.json +19 -19
- package/lib/agents/copilot.plugin.json +24 -24
- package/lib/agents/cursor.plugin.json +25 -25
- package/lib/agents/kilocode.plugin.json +22 -22
- package/lib/agents/opencode.plugin.json +20 -20
- package/lib/agents/roo.plugin.json +23 -23
- package/lib/agents-config.js +2112 -2112
- package/lib/beads-health-check.js +143 -0
- package/lib/beads-setup.js +341 -0
- package/lib/beads-sync-scaffold.js +260 -0
- package/lib/commands/_registry.js +134 -0
- package/lib/commands/clean.js +181 -0
- package/lib/commands/dev.js +571 -513
- package/lib/commands/plan.js +692 -692
- package/lib/commands/push.js +196 -0
- package/lib/commands/recommend.js +119 -119
- package/lib/commands/ship.js +377 -377
- package/lib/commands/status.js +378 -378
- package/lib/commands/sync.js +55 -0
- package/lib/commands/team.js +37 -0
- package/lib/commands/test.js +207 -0
- package/lib/commands/validate.js +602 -602
- package/lib/commands/worktree.js +310 -0
- package/lib/context-merge.js +359 -359
- package/lib/dep-guard/analyzer.js +294 -294
- package/lib/dep-guard/behavior-detector.js +98 -98
- package/lib/dep-guard/contract-detector.js +162 -162
- package/lib/dep-guard/import-detector.js +498 -498
- package/lib/dep-guard/path-utils.js +13 -13
- package/lib/dep-guard/rubric.js +120 -120
- package/lib/dep-guard/task-parser.js +318 -318
- package/lib/detect-agent.js +191 -191
- package/lib/detect-worktree.js +47 -47
- package/lib/docs-command.js +51 -0
- package/lib/docs-copy.js +50 -0
- package/lib/file-hash.js +26 -26
- package/lib/freshness-token.js +148 -0
- package/lib/greptile-match.js +80 -0
- package/lib/husky-migration.js +450 -0
- package/lib/lefthook-check.js +65 -0
- package/lib/pat-setup.js +207 -0
- package/lib/plugin-catalog.js +350 -350
- package/lib/plugin-manager.js +166 -166
- package/lib/plugin-recommender.js +141 -141
- package/lib/project-discovery.js +491 -491
- package/lib/reset.js +309 -0
- package/lib/setup-action-log.js +139 -139
- package/lib/setup-summary-renderer.js +106 -106
- package/lib/setup-utils.js +96 -0
- package/lib/setup.js +192 -192
- package/lib/smart-merge.js +64 -0
- package/lib/symlink-utils.js +81 -0
- package/lib/task-ownership.js +117 -0
- package/lib/workflow-profiles.js +197 -197
- package/package.json +131 -128
- package/scripts/beads-context.sh +426 -0
- package/scripts/beads-context.test.js +567 -0
- package/scripts/behavioral-judge.sh +378 -0
- package/scripts/benchmark.js +85 -0
- package/scripts/branch-protection.js +183 -0
- package/scripts/check-agents.js +172 -0
- package/scripts/check-forge-token.js +98 -0
- package/scripts/commitlint.js +42 -0
- package/scripts/conflict-detect.sh +323 -0
- package/scripts/dep-guard-analyze.js +71 -0
- package/scripts/dep-guard.sh +789 -0
- package/scripts/eval_win.py +249 -0
- package/scripts/file-index.sh +493 -0
- package/scripts/forge-team/index.sh +86 -0
- package/scripts/forge-team/lib/agent-prompt.sh +52 -0
- package/scripts/forge-team/lib/claim.sh +256 -0
- package/scripts/forge-team/lib/dashboard.sh +341 -0
- package/scripts/forge-team/lib/epic.sh +332 -0
- package/scripts/forge-team/lib/hooks.sh +253 -0
- package/scripts/forge-team/lib/identity.sh +235 -0
- package/scripts/forge-team/lib/sync-github.sh +317 -0
- package/scripts/forge-team/lib/verify.sh +284 -0
- package/scripts/forge-team/lib/workload.sh +296 -0
- package/scripts/forge-team/tests/agent-prompt.test.sh +72 -0
- package/scripts/forge-team/tests/claim.test.sh +179 -0
- package/scripts/forge-team/tests/dashboard.test.sh +170 -0
- package/scripts/forge-team/tests/dispatcher.test.sh +79 -0
- package/scripts/forge-team/tests/epic.test.sh +176 -0
- package/scripts/forge-team/tests/hooks.test.sh +239 -0
- package/scripts/forge-team/tests/identity.test.sh +176 -0
- package/scripts/forge-team/tests/integration.test.sh +371 -0
- package/scripts/forge-team/tests/sync-github.test.sh +209 -0
- package/scripts/forge-team/tests/verify.test.sh +314 -0
- package/scripts/forge-team/tests/workflow-integration.test.sh +43 -0
- package/scripts/forge-team/tests/workload.test.sh +209 -0
- package/scripts/github-beads-sync/comment.mjs +64 -0
- package/scripts/github-beads-sync/config.mjs +148 -0
- package/scripts/github-beads-sync/github-api.mjs +131 -0
- package/scripts/github-beads-sync/index.mjs +332 -0
- package/scripts/github-beads-sync/label-mapper.mjs +54 -0
- package/scripts/github-beads-sync/mapping.mjs +78 -0
- package/scripts/github-beads-sync/reverse-sync-cli.mjs +31 -0
- package/scripts/github-beads-sync/reverse-sync.mjs +138 -0
- package/scripts/github-beads-sync/run-bd.mjs +159 -0
- package/scripts/github-beads-sync/sanitize.mjs +121 -0
- package/scripts/github-beads-sync.config.json +26 -0
- package/scripts/improve-command.js +375 -0
- package/scripts/lib/eval-runner.js +268 -0
- package/scripts/lib/eval-schema.js +135 -0
- package/scripts/lib/eval-storage.js +78 -0
- package/scripts/lib/grading.js +203 -0
- package/scripts/lib/jsonl-lock.sh +48 -0
- package/scripts/lib/sanitize.sh +116 -0
- package/scripts/lib/transcript-parser.js +63 -0
- package/scripts/lint.js +47 -0
- package/scripts/migrate-to-bun-test.js +412 -0
- package/scripts/pr-coordinator.sh +706 -0
- package/scripts/run-command-eval.js +236 -0
- package/scripts/smart-status.sh +809 -0
- package/scripts/sync-commands.js +571 -0
- package/scripts/sync-utils.sh +455 -0
- package/scripts/test-dashboard.js +123 -0
- package/scripts/test.js +46 -0
- package/scripts/validate.sh +94 -0
- package/skills/parallel-deep-research/SKILL.md +108 -108
- package/skills/parallel-deep-research/evals/README.md +27 -27
- package/skills/parallel-deep-research/evals/evals.json +62 -62
- package/skills/sonarcloud-analysis/SKILL.md +171 -171
- package/skills/sonarcloud-analysis/evals/README.md +27 -27
- package/skills/sonarcloud-analysis/evals/evals.json +50 -50
- package/skills/sonarcloud-analysis/references/api-reference.md +466 -466
- package/.cursor/hooks/state/continual-learning-index.json +0 -19
- package/.cursor/hooks/state/continual-learning.json +0 -8
|
@@ -1,251 +1,251 @@
|
|
|
1
|
-
# GitHub <-> Beads Issue Sync
|
|
2
|
-
|
|
3
|
-
Automatic synchronization between GitHub Issues and Beads issue tracking.
|
|
4
|
-
|
|
5
|
-
**GitHub Issues** = human/team/public interface.
|
|
6
|
-
**Beads** = AI agent engine (`bd ready`, `bd close`).
|
|
7
|
-
|
|
8
|
-
Neither side needs to know about the other. Contributors file issues on GitHub; AI agents pick up work via Beads. Status changes propagate automatically.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Architecture
|
|
13
|
-
|
|
14
|
-
### Phase 1: GitHub -> Beads (CI-driven)
|
|
15
|
-
|
|
16
|
-
```mermaid
|
|
17
|
-
sequenceDiagram
|
|
18
|
-
participant U as User
|
|
19
|
-
participant GH as GitHub Issues
|
|
20
|
-
participant WF as GitHub Actions
|
|
21
|
-
participant BD as Beads CLI
|
|
22
|
-
participant Repo as .beads/ + mapping
|
|
23
|
-
|
|
24
|
-
U->>GH: Opens issue #42
|
|
25
|
-
GH->>WF: issues.opened trigger
|
|
26
|
-
WF->>WF: Guard checks (bot? skip label? no-beads?)
|
|
27
|
-
WF->>WF: Idempotency check (existing bot comment?)
|
|
28
|
-
WF->>BD: bd create --title "..." --type bug --priority 1
|
|
29
|
-
BD->>Repo: Write .beads/issues.jsonl
|
|
30
|
-
WF->>Repo: Write .github/beads-mapping.json {"42": "forge-abc"}
|
|
31
|
-
WF->>GH: Post bot comment <!-- beads-sync:42 -->
|
|
32
|
-
WF->>Repo: git commit + push
|
|
33
|
-
|
|
34
|
-
U->>GH: Closes issue #42
|
|
35
|
-
GH->>WF: issues.closed trigger
|
|
36
|
-
WF->>Repo: Read mapping: "42" -> "forge-abc"
|
|
37
|
-
WF->>BD: bd close forge-abc --reason "Closed via GitHub #42"
|
|
38
|
-
WF->>Repo: git commit + push
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Phase 2: Beads -> GitHub (push-triggered)
|
|
42
|
-
|
|
43
|
-
```mermaid
|
|
44
|
-
sequenceDiagram
|
|
45
|
-
participant AI as AI Agent
|
|
46
|
-
participant BD as Beads CLI
|
|
47
|
-
participant Repo as .beads/
|
|
48
|
-
participant WF as GitHub Actions
|
|
49
|
-
participant GH as GitHub Issues
|
|
50
|
-
|
|
51
|
-
AI->>BD: bd close forge-abc
|
|
52
|
-
BD->>Repo: Update issues.jsonl
|
|
53
|
-
AI->>Repo: git push
|
|
54
|
-
Repo->>WF: push trigger (paths: .beads/**)
|
|
55
|
-
WF->>WF: Guard: skip if commit msg starts with "chore(beads):"
|
|
56
|
-
WF->>Repo: Diff issues.jsonl for closed transitions
|
|
57
|
-
WF->>GH: gh api PATCH /issues/42 state=closed
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Loop Prevention
|
|
61
|
-
|
|
62
|
-
Three guards prevent infinite ping-pong:
|
|
63
|
-
|
|
64
|
-
1. **Bot detection** -- workflows skip events from `github-actions[bot]`
|
|
65
|
-
2. **Commit message prefix** -- Phase 2 workflow skips commits starting with `chore(beads):`
|
|
66
|
-
3. **Opt-out label** -- `skip-beads-sync` label on any issue disables sync entirely
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Setup
|
|
71
|
-
|
|
72
|
-
### Via Forge Setup (recommended)
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
bunx forge setup
|
|
76
|
-
# During interactive prompts:
|
|
77
|
-
# "Enable GitHub <-> Beads sync? (y/n)" -> y
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
This scaffolds:
|
|
81
|
-
- `.github/workflows/github-to-beads.yml`
|
|
82
|
-
- `.github/workflows/beads-to-github.yml` (Phase 2)
|
|
83
|
-
- `.github/beads-mapping.json`
|
|
84
|
-
- `scripts/github-beads-sync/` (Node modules)
|
|
85
|
-
- `scripts/github-beads-sync.config.json`
|
|
86
|
-
|
|
87
|
-
### Manual Setup
|
|
88
|
-
|
|
89
|
-
1. Copy workflow files from `templates/` into `.github/workflows/`
|
|
90
|
-
2. Copy `scripts/github-beads-sync/` and `scripts/github-beads-sync.config.json`
|
|
91
|
-
3. Create `.github/beads-mapping.json` with `{}`
|
|
92
|
-
4. Ensure Beads is initialized: `bd init`
|
|
93
|
-
5. Commit and push to enable the workflows
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Configuration Reference
|
|
98
|
-
|
|
99
|
-
All settings live in `scripts/github-beads-sync.config.json`.
|
|
100
|
-
|
|
101
|
-
### Label and Type Mapping
|
|
102
|
-
|
|
103
|
-
| Field | Type | Default | Description |
|
|
104
|
-
|-------|------|---------|-------------|
|
|
105
|
-
| `labelToType` | `object` | `{"bug":"bug", "enhancement":"feature", "documentation":"task", "question":"task"}` | Maps GitHub labels to Beads issue types. First matching label wins. |
|
|
106
|
-
| `labelToPriority` | `object` | `{"P0":0, "critical":0, "P1":1, "high":1, "P2":2, "medium":2, "P3":3, "low":3, "P4":4, "backlog":4}` | Maps GitHub labels to Beads priority levels (0-4). First matching label wins. |
|
|
107
|
-
| `defaultType` | `string` | `"task"` | Beads type when no label matches `labelToType`. |
|
|
108
|
-
| `defaultPriority` | `number` | `2` | Beads priority when no label matches `labelToPriority`. |
|
|
109
|
-
| `mapAssignee` | `boolean` | `true` | Whether to copy GitHub assignee to Beads issue on creation. |
|
|
110
|
-
|
|
111
|
-
### Security Gates (Public Repos)
|
|
112
|
-
|
|
113
|
-
| Field | Type | Default | Description |
|
|
114
|
-
|-------|------|---------|-------------|
|
|
115
|
-
| `publicRepoGate` | `string` | `"none"` | Access control for public repos. See [Security](#security) section. |
|
|
116
|
-
| `gateLabelName` | `string` | `"beads-track"` | Required label when `publicRepoGate` is `"label"`. |
|
|
117
|
-
| `gateAssociations` | `string[]` | `["MEMBER", "COLLABORATOR", "OWNER"]` | Allowed author associations when `publicRepoGate` is `"author_association"`. |
|
|
118
|
-
|
|
119
|
-
### Example: Custom Configuration
|
|
120
|
-
|
|
121
|
-
```json
|
|
122
|
-
{
|
|
123
|
-
"labelToType": {
|
|
124
|
-
"bug": "bug",
|
|
125
|
-
"feature": "feature",
|
|
126
|
-
"chore": "chore",
|
|
127
|
-
"spike": "task"
|
|
128
|
-
},
|
|
129
|
-
"labelToPriority": {
|
|
130
|
-
"urgent": 0,
|
|
131
|
-
"important": 1,
|
|
132
|
-
"normal": 2,
|
|
133
|
-
"nice-to-have": 3
|
|
134
|
-
},
|
|
135
|
-
"defaultType": "task",
|
|
136
|
-
"defaultPriority": 2,
|
|
137
|
-
"mapAssignee": true,
|
|
138
|
-
"publicRepoGate": "author_association",
|
|
139
|
-
"gateAssociations": ["MEMBER", "COLLABORATOR", "OWNER"]
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
## Security
|
|
146
|
-
|
|
147
|
-
### Public Repo Gate
|
|
148
|
-
|
|
149
|
-
On public repos, anyone can open an issue -- which triggers a commit to your default branch via the sync workflow. The `publicRepoGate` setting controls who can trigger sync:
|
|
150
|
-
|
|
151
|
-
| Value | Behavior | Recommended For |
|
|
152
|
-
|-------|----------|-----------------|
|
|
153
|
-
| `"none"` | All issues sync (default). | Private repos, trusted teams. |
|
|
154
|
-
| `"author_association"` | Only issues from authors in `gateAssociations` sync. | Public repos with known contributors. |
|
|
155
|
-
| `"label"` | Only issues with the `gateLabelName` label sync. A maintainer must add the label. | Public repos accepting external issues. |
|
|
156
|
-
|
|
157
|
-
### Input Sanitization
|
|
158
|
-
|
|
159
|
-
- Issue titles and bodies are **never interpolated in shell commands**. The sync scripts use Node `execFile` with array arguments (no shell).
|
|
160
|
-
- Workflow files pass event data via `env:` blocks, never via `${{ }}` in `run:` blocks (prevents GitHub Actions injection).
|
|
161
|
-
- Only title, URL, mapped type, and priority are stored in Beads -- raw issue body is not committed.
|
|
162
|
-
|
|
163
|
-
### SHA-Pinned Actions
|
|
164
|
-
|
|
165
|
-
All third-party actions in the workflow files are pinned to full commit SHAs, not tags. This prevents supply-chain attacks via tag mutation.
|
|
166
|
-
|
|
167
|
-
```yaml
|
|
168
|
-
# Good: SHA-pinned
|
|
169
|
-
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
170
|
-
|
|
171
|
-
# Bad: tag-only (never used)
|
|
172
|
-
- uses: actions/checkout@v4
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Opt-Out
|
|
178
|
-
|
|
179
|
-
Two ways to prevent an issue from syncing:
|
|
180
|
-
|
|
181
|
-
1. **Label**: Add `skip-beads-sync` to the GitHub issue. The workflow checks labels before processing.
|
|
182
|
-
2. **Body keyword**: Include `no-beads` anywhere in the issue body. Useful for quick one-off exclusions.
|
|
183
|
-
|
|
184
|
-
Both are checked at the `issues.opened` trigger. If added after creation, they prevent close-sync but not the already-created Beads issue.
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Troubleshooting
|
|
189
|
-
|
|
190
|
-
### Sync not triggering
|
|
191
|
-
|
|
192
|
-
- **Check workflow is enabled**: Go to Actions tab in GitHub, verify `github-to-beads` workflow exists and is active.
|
|
193
|
-
- **Check branch**: Workflows must exist on the default branch (usually `main` or `master`).
|
|
194
|
-
- **Check permissions**: The workflow needs `contents: write` and `issues: write` permissions.
|
|
195
|
-
|
|
196
|
-
### Duplicate Beads issues
|
|
197
|
-
|
|
198
|
-
- The workflow checks for an existing `<!-- beads-sync:N -->` bot comment before creating. If the comment was deleted, a duplicate may be created.
|
|
199
|
-
- Fix: Check `.github/beads-mapping.json` for the existing mapping and manually remove the duplicate Beads issue with `bd delete`.
|
|
200
|
-
|
|
201
|
-
### Loop detection firing incorrectly
|
|
202
|
-
|
|
203
|
-
- If legitimate commits starting with `chore(beads):` are being skipped by the Phase 2 workflow, rename the commit prefix in the workflow file.
|
|
204
|
-
- The bot-actor check uses `github.actor` -- ensure your CI bot user matches the expected name.
|
|
205
|
-
|
|
206
|
-
### Mapping file conflicts
|
|
207
|
-
|
|
208
|
-
- If two issues are created simultaneously, the `git push` for the second may fail due to a stale mapping file.
|
|
209
|
-
- The workflow retries with `git pull --rebase` up to 3 times. If it still fails, the workflow run will show as failed -- re-run it manually.
|
|
210
|
-
|
|
211
|
-
### `bd` command not found in CI
|
|
212
|
-
|
|
213
|
-
- The workflow installs Beads fresh each run: `bun add -g @beads/bd`.
|
|
214
|
-
- If this fails, check that the workflow uses a runner with Node/Bun available.
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## Fork Behavior
|
|
219
|
-
|
|
220
|
-
Sync does **not** work in forks. The `GITHUB_TOKEN` provided to forked repo workflows is scoped to the fork and cannot write to the upstream repo's `.beads/` directory or post comments on upstream issues.
|
|
221
|
-
|
|
222
|
-
When a fork PR uses `Closes #N`, GitHub closes the issue on the **upstream** repo on merge. This triggers the upstream's `issues.closed` workflow, which handles the Beads close normally.
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
## GitHub Projects Integration
|
|
227
|
-
|
|
228
|
-
This plugin creates well-labeled GitHub issues but does **not** manage GitHub Projects boards. Use GitHub's built-in automation instead:
|
|
229
|
-
|
|
230
|
-
### Setting Up Auto-Add to Project
|
|
231
|
-
|
|
232
|
-
1. Go to your GitHub Project (Projects tab on your profile or org)
|
|
233
|
-
2. Click the `...` menu, then **Workflows**
|
|
234
|
-
3. Enable **"Auto-add to project"**
|
|
235
|
-
4. Set the filter, for example: `is:issue is:open label:bug,enhancement`
|
|
236
|
-
5. All matching issues (including those created by the sync) will auto-appear on your board
|
|
237
|
-
|
|
238
|
-
### Recommended Project Views
|
|
239
|
-
|
|
240
|
-
- **Board view**: Columns for `Open`, `In Progress`, `Done` -- map to Beads statuses
|
|
241
|
-
- **Table view**: Add `Labels`, `Assignees`, `Priority` fields for triage
|
|
242
|
-
- **Filter by label**: Use the labels mapped in your config to create focused views
|
|
243
|
-
|
|
244
|
-
This approach is more flexible than automating board placement -- you control the filters and views entirely within GitHub's UI.
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## Related Documentation
|
|
249
|
-
|
|
250
|
-
- [Design doc](plans/2026-03-21-github-beads-sync-design.md) -- full design decisions, OWASP analysis, and edge cases
|
|
251
|
-
- [Toolchain reference](TOOLCHAIN.md) -- Beads CLI commands, installation, and troubleshooting
|
|
1
|
+
# GitHub <-> Beads Issue Sync
|
|
2
|
+
|
|
3
|
+
Automatic synchronization between GitHub Issues and Beads issue tracking.
|
|
4
|
+
|
|
5
|
+
**GitHub Issues** = human/team/public interface.
|
|
6
|
+
**Beads** = AI agent engine (`bd ready`, `bd close`).
|
|
7
|
+
|
|
8
|
+
Neither side needs to know about the other. Contributors file issues on GitHub; AI agents pick up work via Beads. Status changes propagate automatically.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
### Phase 1: GitHub -> Beads (CI-driven)
|
|
15
|
+
|
|
16
|
+
```mermaid
|
|
17
|
+
sequenceDiagram
|
|
18
|
+
participant U as User
|
|
19
|
+
participant GH as GitHub Issues
|
|
20
|
+
participant WF as GitHub Actions
|
|
21
|
+
participant BD as Beads CLI
|
|
22
|
+
participant Repo as .beads/ + mapping
|
|
23
|
+
|
|
24
|
+
U->>GH: Opens issue #42
|
|
25
|
+
GH->>WF: issues.opened trigger
|
|
26
|
+
WF->>WF: Guard checks (bot? skip label? no-beads?)
|
|
27
|
+
WF->>WF: Idempotency check (existing bot comment?)
|
|
28
|
+
WF->>BD: bd create --title "..." --type bug --priority 1
|
|
29
|
+
BD->>Repo: Write .beads/issues.jsonl
|
|
30
|
+
WF->>Repo: Write .github/beads-mapping.json {"42": "forge-abc"}
|
|
31
|
+
WF->>GH: Post bot comment <!-- beads-sync:42 -->
|
|
32
|
+
WF->>Repo: git commit + push
|
|
33
|
+
|
|
34
|
+
U->>GH: Closes issue #42
|
|
35
|
+
GH->>WF: issues.closed trigger
|
|
36
|
+
WF->>Repo: Read mapping: "42" -> "forge-abc"
|
|
37
|
+
WF->>BD: bd close forge-abc --reason "Closed via GitHub #42"
|
|
38
|
+
WF->>Repo: git commit + push
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Phase 2: Beads -> GitHub (push-triggered)
|
|
42
|
+
|
|
43
|
+
```mermaid
|
|
44
|
+
sequenceDiagram
|
|
45
|
+
participant AI as AI Agent
|
|
46
|
+
participant BD as Beads CLI
|
|
47
|
+
participant Repo as .beads/
|
|
48
|
+
participant WF as GitHub Actions
|
|
49
|
+
participant GH as GitHub Issues
|
|
50
|
+
|
|
51
|
+
AI->>BD: bd close forge-abc
|
|
52
|
+
BD->>Repo: Update issues.jsonl
|
|
53
|
+
AI->>Repo: git push
|
|
54
|
+
Repo->>WF: push trigger (paths: .beads/**)
|
|
55
|
+
WF->>WF: Guard: skip if commit msg starts with "chore(beads):"
|
|
56
|
+
WF->>Repo: Diff issues.jsonl for closed transitions
|
|
57
|
+
WF->>GH: gh api PATCH /issues/42 state=closed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Loop Prevention
|
|
61
|
+
|
|
62
|
+
Three guards prevent infinite ping-pong:
|
|
63
|
+
|
|
64
|
+
1. **Bot detection** -- workflows skip events from `github-actions[bot]`
|
|
65
|
+
2. **Commit message prefix** -- Phase 2 workflow skips commits starting with `chore(beads):`
|
|
66
|
+
3. **Opt-out label** -- `skip-beads-sync` label on any issue disables sync entirely
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Setup
|
|
71
|
+
|
|
72
|
+
### Via Forge Setup (recommended)
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bunx forge setup
|
|
76
|
+
# During interactive prompts:
|
|
77
|
+
# "Enable GitHub <-> Beads sync? (y/n)" -> y
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This scaffolds:
|
|
81
|
+
- `.github/workflows/github-to-beads.yml`
|
|
82
|
+
- `.github/workflows/beads-to-github.yml` (Phase 2)
|
|
83
|
+
- `.github/beads-mapping.json`
|
|
84
|
+
- `scripts/github-beads-sync/` (Node modules)
|
|
85
|
+
- `scripts/github-beads-sync.config.json`
|
|
86
|
+
|
|
87
|
+
### Manual Setup
|
|
88
|
+
|
|
89
|
+
1. Copy workflow files from `templates/` into `.github/workflows/`
|
|
90
|
+
2. Copy `scripts/github-beads-sync/` and `scripts/github-beads-sync.config.json`
|
|
91
|
+
3. Create `.github/beads-mapping.json` with `{}`
|
|
92
|
+
4. Ensure Beads is initialized: `bd init`
|
|
93
|
+
5. Commit and push to enable the workflows
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Configuration Reference
|
|
98
|
+
|
|
99
|
+
All settings live in `scripts/github-beads-sync.config.json`.
|
|
100
|
+
|
|
101
|
+
### Label and Type Mapping
|
|
102
|
+
|
|
103
|
+
| Field | Type | Default | Description |
|
|
104
|
+
|-------|------|---------|-------------|
|
|
105
|
+
| `labelToType` | `object` | `{"bug":"bug", "enhancement":"feature", "documentation":"task", "question":"task"}` | Maps GitHub labels to Beads issue types. First matching label wins. |
|
|
106
|
+
| `labelToPriority` | `object` | `{"P0":0, "critical":0, "P1":1, "high":1, "P2":2, "medium":2, "P3":3, "low":3, "P4":4, "backlog":4}` | Maps GitHub labels to Beads priority levels (0-4). First matching label wins. |
|
|
107
|
+
| `defaultType` | `string` | `"task"` | Beads type when no label matches `labelToType`. |
|
|
108
|
+
| `defaultPriority` | `number` | `2` | Beads priority when no label matches `labelToPriority`. |
|
|
109
|
+
| `mapAssignee` | `boolean` | `true` | Whether to copy GitHub assignee to Beads issue on creation. |
|
|
110
|
+
|
|
111
|
+
### Security Gates (Public Repos)
|
|
112
|
+
|
|
113
|
+
| Field | Type | Default | Description |
|
|
114
|
+
|-------|------|---------|-------------|
|
|
115
|
+
| `publicRepoGate` | `string` | `"none"` | Access control for public repos. See [Security](#security) section. |
|
|
116
|
+
| `gateLabelName` | `string` | `"beads-track"` | Required label when `publicRepoGate` is `"label"`. |
|
|
117
|
+
| `gateAssociations` | `string[]` | `["MEMBER", "COLLABORATOR", "OWNER"]` | Allowed author associations when `publicRepoGate` is `"author_association"`. |
|
|
118
|
+
|
|
119
|
+
### Example: Custom Configuration
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"labelToType": {
|
|
124
|
+
"bug": "bug",
|
|
125
|
+
"feature": "feature",
|
|
126
|
+
"chore": "chore",
|
|
127
|
+
"spike": "task"
|
|
128
|
+
},
|
|
129
|
+
"labelToPriority": {
|
|
130
|
+
"urgent": 0,
|
|
131
|
+
"important": 1,
|
|
132
|
+
"normal": 2,
|
|
133
|
+
"nice-to-have": 3
|
|
134
|
+
},
|
|
135
|
+
"defaultType": "task",
|
|
136
|
+
"defaultPriority": 2,
|
|
137
|
+
"mapAssignee": true,
|
|
138
|
+
"publicRepoGate": "author_association",
|
|
139
|
+
"gateAssociations": ["MEMBER", "COLLABORATOR", "OWNER"]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Security
|
|
146
|
+
|
|
147
|
+
### Public Repo Gate
|
|
148
|
+
|
|
149
|
+
On public repos, anyone can open an issue -- which triggers a commit to your default branch via the sync workflow. The `publicRepoGate` setting controls who can trigger sync:
|
|
150
|
+
|
|
151
|
+
| Value | Behavior | Recommended For |
|
|
152
|
+
|-------|----------|-----------------|
|
|
153
|
+
| `"none"` | All issues sync (default). | Private repos, trusted teams. |
|
|
154
|
+
| `"author_association"` | Only issues from authors in `gateAssociations` sync. | Public repos with known contributors. |
|
|
155
|
+
| `"label"` | Only issues with the `gateLabelName` label sync. A maintainer must add the label. | Public repos accepting external issues. |
|
|
156
|
+
|
|
157
|
+
### Input Sanitization
|
|
158
|
+
|
|
159
|
+
- Issue titles and bodies are **never interpolated in shell commands**. The sync scripts use Node `execFile` with array arguments (no shell).
|
|
160
|
+
- Workflow files pass event data via `env:` blocks, never via `${{ }}` in `run:` blocks (prevents GitHub Actions injection).
|
|
161
|
+
- Only title, URL, mapped type, and priority are stored in Beads -- raw issue body is not committed.
|
|
162
|
+
|
|
163
|
+
### SHA-Pinned Actions
|
|
164
|
+
|
|
165
|
+
All third-party actions in the workflow files are pinned to full commit SHAs, not tags. This prevents supply-chain attacks via tag mutation.
|
|
166
|
+
|
|
167
|
+
```yaml
|
|
168
|
+
# Good: SHA-pinned
|
|
169
|
+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
170
|
+
|
|
171
|
+
# Bad: tag-only (never used)
|
|
172
|
+
- uses: actions/checkout@v4
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Opt-Out
|
|
178
|
+
|
|
179
|
+
Two ways to prevent an issue from syncing:
|
|
180
|
+
|
|
181
|
+
1. **Label**: Add `skip-beads-sync` to the GitHub issue. The workflow checks labels before processing.
|
|
182
|
+
2. **Body keyword**: Include `no-beads` anywhere in the issue body. Useful for quick one-off exclusions.
|
|
183
|
+
|
|
184
|
+
Both are checked at the `issues.opened` trigger. If added after creation, they prevent close-sync but not the already-created Beads issue.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Troubleshooting
|
|
189
|
+
|
|
190
|
+
### Sync not triggering
|
|
191
|
+
|
|
192
|
+
- **Check workflow is enabled**: Go to Actions tab in GitHub, verify `github-to-beads` workflow exists and is active.
|
|
193
|
+
- **Check branch**: Workflows must exist on the default branch (usually `main` or `master`).
|
|
194
|
+
- **Check permissions**: The workflow needs `contents: write` and `issues: write` permissions.
|
|
195
|
+
|
|
196
|
+
### Duplicate Beads issues
|
|
197
|
+
|
|
198
|
+
- The workflow checks for an existing `<!-- beads-sync:N -->` bot comment before creating. If the comment was deleted, a duplicate may be created.
|
|
199
|
+
- Fix: Check `.github/beads-mapping.json` for the existing mapping and manually remove the duplicate Beads issue with `bd delete`.
|
|
200
|
+
|
|
201
|
+
### Loop detection firing incorrectly
|
|
202
|
+
|
|
203
|
+
- If legitimate commits starting with `chore(beads):` are being skipped by the Phase 2 workflow, rename the commit prefix in the workflow file.
|
|
204
|
+
- The bot-actor check uses `github.actor` -- ensure your CI bot user matches the expected name.
|
|
205
|
+
|
|
206
|
+
### Mapping file conflicts
|
|
207
|
+
|
|
208
|
+
- If two issues are created simultaneously, the `git push` for the second may fail due to a stale mapping file.
|
|
209
|
+
- The workflow retries with `git pull --rebase` up to 3 times. If it still fails, the workflow run will show as failed -- re-run it manually.
|
|
210
|
+
|
|
211
|
+
### `bd` command not found in CI
|
|
212
|
+
|
|
213
|
+
- The workflow installs Beads fresh each run: `bun add -g @beads/bd`.
|
|
214
|
+
- If this fails, check that the workflow uses a runner with Node/Bun available.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## Fork Behavior
|
|
219
|
+
|
|
220
|
+
Sync does **not** work in forks. The `GITHUB_TOKEN` provided to forked repo workflows is scoped to the fork and cannot write to the upstream repo's `.beads/` directory or post comments on upstream issues.
|
|
221
|
+
|
|
222
|
+
When a fork PR uses `Closes #N`, GitHub closes the issue on the **upstream** repo on merge. This triggers the upstream's `issues.closed` workflow, which handles the Beads close normally.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## GitHub Projects Integration
|
|
227
|
+
|
|
228
|
+
This plugin creates well-labeled GitHub issues but does **not** manage GitHub Projects boards. Use GitHub's built-in automation instead:
|
|
229
|
+
|
|
230
|
+
### Setting Up Auto-Add to Project
|
|
231
|
+
|
|
232
|
+
1. Go to your GitHub Project (Projects tab on your profile or org)
|
|
233
|
+
2. Click the `...` menu, then **Workflows**
|
|
234
|
+
3. Enable **"Auto-add to project"**
|
|
235
|
+
4. Set the filter, for example: `is:issue is:open label:bug,enhancement`
|
|
236
|
+
5. All matching issues (including those created by the sync) will auto-appear on your board
|
|
237
|
+
|
|
238
|
+
### Recommended Project Views
|
|
239
|
+
|
|
240
|
+
- **Board view**: Columns for `Open`, `In Progress`, `Done` -- map to Beads statuses
|
|
241
|
+
- **Table view**: Add `Labels`, `Assignees`, `Priority` fields for triage
|
|
242
|
+
- **Filter by label**: Use the labels mapped in your config to create focused views
|
|
243
|
+
|
|
244
|
+
This approach is more flexible than automating board placement -- you control the filters and views entirely within GitHub's UI.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Related Documentation
|
|
249
|
+
|
|
250
|
+
- [Design doc](plans/2026-03-21-github-beads-sync-design.md) -- full design decisions, OWASP analysis, and edge cases
|
|
251
|
+
- [Toolchain reference](TOOLCHAIN.md) -- Beads CLI commands, installation, and troubleshooting
|