claude-autopm 1.20.1 → 1.21.0
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/README.md +255 -878
- package/autopm/.claude/commands/pm/epic-sync.md +37 -4
- package/autopm/.claude/rules/framework-path-rules.md +180 -0
- package/autopm/.claude/scripts/pm/epic-sync/README.md +208 -0
- package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +68 -192
- package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +60 -328
- package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +61 -354
- package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +67 -305
- package/autopm/.claude/scripts/pm/epic-sync.sh +137 -0
- package/package.json +4 -2
- package/scripts/validate-framework-paths.sh +104 -0
|
@@ -11,6 +11,21 @@ Push epic and tasks to GitHub as issues using modular scripts.
|
|
|
11
11
|
/pm:epic-sync <feature_name>
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
The simplest way to sync an epic to GitHub:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Full automated sync (recommended)
|
|
20
|
+
bash .claude/scripts/pm/epic-sync.sh "$ARGUMENTS"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This orchestration script automatically runs all 4 steps:
|
|
24
|
+
1. Creates epic issue
|
|
25
|
+
2. Creates task issues
|
|
26
|
+
3. Renames files to issue numbers
|
|
27
|
+
4. Updates all references
|
|
28
|
+
|
|
14
29
|
## Quick Check
|
|
15
30
|
|
|
16
31
|
```bash
|
|
@@ -32,7 +47,14 @@ If no tasks found: "❌ No tasks to sync. Run: /pm:epic-decompose $ARGUMENTS"
|
|
|
32
47
|
|
|
33
48
|
## Instructions
|
|
34
49
|
|
|
35
|
-
|
|
50
|
+
**⚡ Quick Command:**
|
|
51
|
+
```bash
|
|
52
|
+
bash .claude/scripts/pm/epic-sync.sh "$ARGUMENTS"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The epic sync process is modularized into 4 specialized scripts that handle different aspects of the synchronization. Each script is designed for reliability, testability, and maintainability.
|
|
56
|
+
|
|
57
|
+
The orchestration script (`.claude/scripts/pm/epic-sync.sh`) automatically runs all 4 steps in sequence. The individual scripts are documented below for reference and debugging.
|
|
36
58
|
|
|
37
59
|
### Processing Mode Detection
|
|
38
60
|
|
|
@@ -158,13 +180,24 @@ echo "✅ Created branch: epic/$ARGUMENTS"
|
|
|
158
180
|
|
|
159
181
|
## Complete Workflow Examples
|
|
160
182
|
|
|
161
|
-
### Single Epic Workflow
|
|
183
|
+
### Single Epic Workflow (Automated - Recommended)
|
|
184
|
+
|
|
185
|
+
The **easiest way** is to use the orchestration script that handles everything:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# One command does it all!
|
|
189
|
+
bash .claude/scripts/pm/epic-sync.sh "$ARGUMENTS"
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
This automatically runs all 4 steps and provides a complete summary.
|
|
193
|
+
|
|
194
|
+
### Single Epic Workflow (Manual Steps)
|
|
162
195
|
|
|
163
|
-
|
|
196
|
+
If you need to run steps individually for debugging:
|
|
164
197
|
|
|
165
198
|
```bash
|
|
166
199
|
#!/bin/bash
|
|
167
|
-
# Complete epic sync using modular scripts
|
|
200
|
+
# Complete epic sync using modular scripts (manual)
|
|
168
201
|
|
|
169
202
|
EPIC_NAME="$ARGUMENTS"
|
|
170
203
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Framework Path Rules
|
|
2
|
+
|
|
3
|
+
## Critical Path Convention
|
|
4
|
+
|
|
5
|
+
**NEVER** hardcode the `autopm/` directory path in framework files. The `autopm/` directory only exists during development and is **NOT** present after installation in user projects.
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
8
|
+
|
|
9
|
+
During installation, files from `autopm/.claude/` are copied to user projects as `.claude/`. Any references to `autopm/.claude/` or `autopm/scripts/` will be broken after installation.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
❌ WRONG (Development structure):
|
|
13
|
+
autopm/
|
|
14
|
+
├── .claude/
|
|
15
|
+
│ ├── commands/
|
|
16
|
+
│ ├── scripts/
|
|
17
|
+
│ └── agents/
|
|
18
|
+
|
|
19
|
+
✅ CORRECT (After installation):
|
|
20
|
+
user-project/
|
|
21
|
+
├── .claude/
|
|
22
|
+
│ ├── commands/
|
|
23
|
+
│ ├── scripts/
|
|
24
|
+
│ └── agents/
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Rules
|
|
28
|
+
|
|
29
|
+
### 1. Use Relative Paths from Project Root
|
|
30
|
+
|
|
31
|
+
All paths in framework files must be relative to the **user's project root** (where `.claude/` will exist after installation).
|
|
32
|
+
|
|
33
|
+
**✅ CORRECT:**
|
|
34
|
+
```bash
|
|
35
|
+
bash .claude/scripts/pm/epic-sync/create-epic-issue.sh "$EPIC_NAME"
|
|
36
|
+
node .claude/lib/commands/pm/prdStatus.js
|
|
37
|
+
source .claude/scripts/lib/github-utils.sh
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**❌ WRONG:**
|
|
41
|
+
```bash
|
|
42
|
+
bash autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh "$EPIC_NAME"
|
|
43
|
+
node autopm/.claude/lib/commands/pm/prdStatus.js
|
|
44
|
+
source autopm/.claude/scripts/lib/github-utils.sh
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Exception: Comments and Documentation References
|
|
48
|
+
|
|
49
|
+
It's acceptable to reference `autopm/` in:
|
|
50
|
+
- Code comments explaining migration history
|
|
51
|
+
- Documentation describing the development structure
|
|
52
|
+
- Git commit messages
|
|
53
|
+
|
|
54
|
+
**✅ ACCEPTABLE:**
|
|
55
|
+
```javascript
|
|
56
|
+
/**
|
|
57
|
+
* Migrated from autopm/.claude/scripts/azure/validate.sh to Node.js
|
|
58
|
+
*/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**✅ ACCEPTABLE:**
|
|
62
|
+
```markdown
|
|
63
|
+
## Development Structure
|
|
64
|
+
During development, framework files are in `autopm/.claude/`, but after
|
|
65
|
+
installation they are copied to the user project's `.claude/` directory.
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Files That Must Follow These Rules
|
|
69
|
+
|
|
70
|
+
- **Commands** (`autopm/.claude/commands/**/*.md`)
|
|
71
|
+
- **Scripts** (`autopm/.claude/scripts/**/*.sh`, `**/*.js`)
|
|
72
|
+
- **Agents** (`autopm/.claude/agents/**/*.md`)
|
|
73
|
+
- **Rules** (`autopm/.claude/rules/**/*.md`)
|
|
74
|
+
- **Templates** (`autopm/.claude/templates/**/*`)
|
|
75
|
+
|
|
76
|
+
### 4. Environment Variables
|
|
77
|
+
|
|
78
|
+
If you need to reference the framework location dynamically, use environment variables that work in both contexts:
|
|
79
|
+
|
|
80
|
+
**✅ CORRECT:**
|
|
81
|
+
```bash
|
|
82
|
+
CLAUDE_DIR="${CLAUDE_DIR:-.claude}"
|
|
83
|
+
bash "${CLAUDE_DIR}/scripts/pm/epic-sync/create-epic-issue.sh"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This allows:
|
|
87
|
+
- Development: `CLAUDE_DIR=autopm/.claude`
|
|
88
|
+
- Production: `CLAUDE_DIR=.claude` (default)
|
|
89
|
+
|
|
90
|
+
## Validation
|
|
91
|
+
|
|
92
|
+
### Pre-Commit Hook
|
|
93
|
+
|
|
94
|
+
A pre-commit hook validates all framework files before commit:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Checks for hardcoded autopm/ paths (excluding comments)
|
|
98
|
+
grep -r "bash autopm" autopm/.claude --include="*.md" --include="*.sh"
|
|
99
|
+
grep -r "node autopm" autopm/.claude --include="*.md" --include="*.sh"
|
|
100
|
+
grep -r "source autopm" autopm/.claude --include="*.md" --include="*.sh"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Manual Check
|
|
104
|
+
|
|
105
|
+
Before committing changes to framework files:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Run validation
|
|
109
|
+
npm run validate:paths
|
|
110
|
+
|
|
111
|
+
# Or manually
|
|
112
|
+
./scripts/validate-framework-paths.sh
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Common Mistakes
|
|
116
|
+
|
|
117
|
+
### Mistake 1: Copy-Paste from Development Environment
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# ❌ Copying terminal command that worked in development
|
|
121
|
+
bash autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh "feature-name"
|
|
122
|
+
|
|
123
|
+
# ✅ Use project-relative path
|
|
124
|
+
bash .claude/scripts/pm/epic-sync/create-epic-issue.sh "feature-name"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Mistake 2: Documentation Examples
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
❌ WRONG:
|
|
131
|
+
To run the script:
|
|
132
|
+
`bash autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh`
|
|
133
|
+
|
|
134
|
+
✅ CORRECT:
|
|
135
|
+
To run the script:
|
|
136
|
+
`bash .claude/scripts/pm/issue-sync/preflight-validation.sh`
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Mistake 3: Relative Imports in Scripts
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# ❌ WRONG - hardcoded framework path
|
|
143
|
+
source autopm/.claude/scripts/lib/github-utils.sh
|
|
144
|
+
|
|
145
|
+
# ✅ CORRECT - relative to project root
|
|
146
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
147
|
+
source "${SCRIPT_DIR}/../lib/github-utils.sh"
|
|
148
|
+
|
|
149
|
+
# ✅ ALSO CORRECT - explicit project root
|
|
150
|
+
source .claude/scripts/lib/github-utils.sh
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Enforcement
|
|
154
|
+
|
|
155
|
+
This rule is enforced by:
|
|
156
|
+
|
|
157
|
+
1. **Pre-commit hook** - Blocks commits with hardcoded `autopm/` paths
|
|
158
|
+
2. **CI/CD validation** - GitHub Actions check on every PR
|
|
159
|
+
3. **Installation tests** - Verify all paths work post-installation
|
|
160
|
+
4. **Code review** - Reviewers check for path correctness
|
|
161
|
+
|
|
162
|
+
## Quick Reference
|
|
163
|
+
|
|
164
|
+
| Context | Use | Don't Use |
|
|
165
|
+
|---------|-----|-----------|
|
|
166
|
+
| Shell scripts | `.claude/scripts/` | `autopm/.claude/scripts/` |
|
|
167
|
+
| Node.js scripts | `.claude/lib/` | `autopm/.claude/lib/` |
|
|
168
|
+
| Command files | `.claude/commands/` | `autopm/.claude/commands/` |
|
|
169
|
+
| Documentation | `.claude/agents/` | `autopm/.claude/agents/` |
|
|
170
|
+
| Comments | `autopm/` ✅ OK | N/A |
|
|
171
|
+
|
|
172
|
+
## Related Rules
|
|
173
|
+
|
|
174
|
+
- `/rules/naming-conventions.md` - File and directory naming
|
|
175
|
+
- `/rules/development-workflow.md` - Development best practices
|
|
176
|
+
- `/rules/golden-rules.md` - Core framework principles
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
**Remember:** If a user installs this framework, the `autopm/` directory will not exist in their project. All paths must work from their project root where `.claude/` is located.
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# Epic Sync Modular Scripts
|
|
2
|
+
|
|
3
|
+
This directory contains the modular implementation of the epic-sync workflow that pushes epics and tasks to GitHub as issues.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
The epic-sync process is split into 4 specialized scripts:
|
|
8
|
+
|
|
9
|
+
1. **create-epic-issue.sh** - Creates the main epic GitHub issue
|
|
10
|
+
2. **create-task-issues.sh** - Creates GitHub issues for all tasks
|
|
11
|
+
3. **update-references.sh** - Renames task files to match GitHub issue numbers
|
|
12
|
+
4. **update-epic-file.sh** - Updates epic.md with real issue numbers
|
|
13
|
+
|
|
14
|
+
## Orchestration
|
|
15
|
+
|
|
16
|
+
The **recommended way** to use these scripts is via the orchestration script:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# From project root
|
|
20
|
+
bash .claude/scripts/pm/epic-sync.sh <epic_name>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This automatically runs all 4 steps in the correct order.
|
|
24
|
+
|
|
25
|
+
## Individual Scripts
|
|
26
|
+
|
|
27
|
+
### 1. create-epic-issue.sh
|
|
28
|
+
|
|
29
|
+
**Purpose:** Creates the main GitHub issue for the epic
|
|
30
|
+
|
|
31
|
+
**Input:**
|
|
32
|
+
- Epic name (e.g., `postgresql-connection-module`)
|
|
33
|
+
|
|
34
|
+
**Output:**
|
|
35
|
+
- GitHub issue number (stdout)
|
|
36
|
+
|
|
37
|
+
**What it does:**
|
|
38
|
+
- Strips frontmatter from epic.md
|
|
39
|
+
- Counts tasks in epic directory
|
|
40
|
+
- Detects epic type (bug vs feature)
|
|
41
|
+
- Creates GitHub issue with proper labels
|
|
42
|
+
- Returns epic issue number
|
|
43
|
+
|
|
44
|
+
**Usage:**
|
|
45
|
+
```bash
|
|
46
|
+
epic_number=$(bash .claude/scripts/pm/epic-sync/create-epic-issue.sh "my-feature")
|
|
47
|
+
echo "Epic created: #$epic_number"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 2. create-task-issues.sh
|
|
51
|
+
|
|
52
|
+
**Purpose:** Creates GitHub issues for all task files
|
|
53
|
+
|
|
54
|
+
**Input:**
|
|
55
|
+
- Epic name
|
|
56
|
+
- Epic issue number (from step 1)
|
|
57
|
+
|
|
58
|
+
**Output:**
|
|
59
|
+
- Path to task mapping file (stdout)
|
|
60
|
+
|
|
61
|
+
**What it does:**
|
|
62
|
+
- Finds all `[0-9]*.md` files in epic directory
|
|
63
|
+
- Strips frontmatter from each task
|
|
64
|
+
- Creates GitHub issue for each task
|
|
65
|
+
- Labels with `task,epic:<epic_name>`
|
|
66
|
+
- Saves mapping of old_name -> issue_number to `.task-mapping.txt`
|
|
67
|
+
- **Mapping file is saved in epic directory** (persistent, not in /tmp)
|
|
68
|
+
|
|
69
|
+
**Usage:**
|
|
70
|
+
```bash
|
|
71
|
+
mapping=$(bash .claude/scripts/pm/epic-sync/create-task-issues.sh "my-feature" "42")
|
|
72
|
+
echo "Mapping saved: $mapping"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Important:** The mapping file is saved as `.claude/epics/<epic>/.task-mapping.txt` for use in subsequent steps.
|
|
76
|
+
|
|
77
|
+
### 3. update-references.sh
|
|
78
|
+
|
|
79
|
+
**Purpose:** Renames task files to GitHub issue numbers and updates frontmatter
|
|
80
|
+
|
|
81
|
+
**Input:**
|
|
82
|
+
- Epic name
|
|
83
|
+
- Path to task mapping file (from step 2)
|
|
84
|
+
|
|
85
|
+
**Output:**
|
|
86
|
+
- None (modifies files in place)
|
|
87
|
+
|
|
88
|
+
**What it does:**
|
|
89
|
+
- Reads `.task-mapping.txt` file
|
|
90
|
+
- For each mapping (e.g., `001 -> 2`):
|
|
91
|
+
- Renames `001.md` to `2.md`
|
|
92
|
+
- Updates frontmatter with GitHub URL
|
|
93
|
+
- Updates frontmatter timestamp
|
|
94
|
+
- Creates backups during rename (removed on success)
|
|
95
|
+
|
|
96
|
+
**Usage:**
|
|
97
|
+
```bash
|
|
98
|
+
bash .claude/scripts/pm/epic-sync/update-references.sh "my-feature" ".claude/epics/my-feature/.task-mapping.txt"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Before:**
|
|
102
|
+
```
|
|
103
|
+
.claude/epics/my-feature/
|
|
104
|
+
├── 001.md (github: [Will be updated...])
|
|
105
|
+
├── 002.md (github: [Will be updated...])
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**After:**
|
|
109
|
+
```
|
|
110
|
+
.claude/epics/my-feature/
|
|
111
|
+
├── 2.md (github: https://github.com/user/repo/issues/2)
|
|
112
|
+
├── 3.md (github: https://github.com/user/repo/issues/3)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 4. update-epic-file.sh
|
|
116
|
+
|
|
117
|
+
**Purpose:** Updates epic.md with GitHub URL and real task references
|
|
118
|
+
|
|
119
|
+
**Input:**
|
|
120
|
+
- Epic name
|
|
121
|
+
- Epic issue number
|
|
122
|
+
|
|
123
|
+
**Output:**
|
|
124
|
+
- None (modifies epic.md in place)
|
|
125
|
+
|
|
126
|
+
**What it does:**
|
|
127
|
+
- Updates epic.md frontmatter with GitHub URL
|
|
128
|
+
- Updates timestamp
|
|
129
|
+
- Reads `.task-mapping.txt`
|
|
130
|
+
- Replaces task references (e.g., `- [ ] 001` → `- [ ] #2`)
|
|
131
|
+
- Creates backup during update (removed on success)
|
|
132
|
+
|
|
133
|
+
**Usage:**
|
|
134
|
+
```bash
|
|
135
|
+
bash .claude/scripts/pm/epic-sync/update-epic-file.sh "my-feature" "42"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## File Persistence Fix
|
|
139
|
+
|
|
140
|
+
**IMPORTANT:** The task mapping file is saved to a **persistent location**:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
.claude/epics/<epic_name>/.task-mapping.txt
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
This fixes the bug where the mapping file was being saved to `/tmp` and deleted before subsequent scripts could use it.
|
|
147
|
+
|
|
148
|
+
## Error Handling
|
|
149
|
+
|
|
150
|
+
All scripts use `set -euo pipefail` for robust error handling:
|
|
151
|
+
- `-e`: Exit on error
|
|
152
|
+
- `-u`: Error on undefined variables
|
|
153
|
+
- `-o pipefail`: Fail if any command in pipeline fails
|
|
154
|
+
|
|
155
|
+
## Testing
|
|
156
|
+
|
|
157
|
+
Test individual scripts:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Create a test epic first
|
|
161
|
+
mkdir -p .claude/epics/test-epic
|
|
162
|
+
echo "---\ntitle: Test\n---\n# Test Epic" > .claude/epics/test-epic/epic.md
|
|
163
|
+
echo "---\ntitle: Task 1\n---\n# Task 1" > .claude/epics/test-epic/001.md
|
|
164
|
+
echo "---\ntitle: Task 2\n---\n# Task 2" > .claude/epics/test-epic/002.md
|
|
165
|
+
|
|
166
|
+
# Run orchestration script
|
|
167
|
+
bash .claude/scripts/pm/epic-sync.sh test-epic
|
|
168
|
+
|
|
169
|
+
# Verify files were renamed
|
|
170
|
+
ls .claude/epics/test-epic/
|
|
171
|
+
# Should show: epic.md, <issue_number>.md files
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Dependencies
|
|
175
|
+
|
|
176
|
+
- **bash** >= 4.0
|
|
177
|
+
- **gh** (GitHub CLI) - authenticated
|
|
178
|
+
- **awk** - for frontmatter processing
|
|
179
|
+
- **find** - for file discovery
|
|
180
|
+
- **grep** - for pattern matching
|
|
181
|
+
|
|
182
|
+
## Common Issues
|
|
183
|
+
|
|
184
|
+
### "Template repository detected"
|
|
185
|
+
```bash
|
|
186
|
+
# Fix: Set correct remote
|
|
187
|
+
git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### "GitHub CLI not authenticated"
|
|
191
|
+
```bash
|
|
192
|
+
gh auth login
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### "Mapping file not found"
|
|
196
|
+
- Ensure step 2 completed successfully
|
|
197
|
+
- Check `.claude/epics/<epic>/.task-mapping.txt` exists
|
|
198
|
+
|
|
199
|
+
### "Task files still numbered 001, 002..."
|
|
200
|
+
- Step 3 (update-references.sh) may not have run
|
|
201
|
+
- Check for errors in step 2 output
|
|
202
|
+
- Run orchestration script instead of individual scripts
|
|
203
|
+
|
|
204
|
+
## Related Files
|
|
205
|
+
|
|
206
|
+
- **/.claude/commands/pm/epic-sync.md** - Command documentation
|
|
207
|
+
- **/.claude/commands/pm/issue-start.md** - Works with renamed files
|
|
208
|
+
- **/.claude/commands/pm/issue-analyze.md** - Expects GitHub issue numbers
|