engsys 1.0.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.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -0
  3. package/core/agents/aaron.md +152 -0
  4. package/core/agents/bert.md +115 -0
  5. package/core/agents/isabelle.md +136 -0
  6. package/core/agents/jody.md +150 -0
  7. package/core/agents/leith.md +111 -0
  8. package/core/agents/marcelo.md +282 -0
  9. package/core/agents/melvin.md +101 -0
  10. package/core/agents/nyx.md +152 -0
  11. package/core/agents/otto.md +168 -0
  12. package/core/agents/patricia.md +283 -0
  13. package/core/commands/design-audit-local.md +155 -0
  14. package/core/commands/design-audit.md +235 -0
  15. package/core/commands/design-critique.md +96 -0
  16. package/core/commands/file-issue.md +22 -0
  17. package/core/commands/generate-project.md +45 -0
  18. package/core/commands/implement-issue.md +37 -0
  19. package/core/commands/implement-project.md +40 -0
  20. package/core/commands/naturalize.md +61 -0
  21. package/core/commands/pre-push.md +29 -0
  22. package/core/commands/prep-review-collect.md +130 -0
  23. package/core/commands/prep-review-finalize.md +121 -0
  24. package/core/commands/prep-review-publish.md +113 -0
  25. package/core/commands/prep-review.md +65 -0
  26. package/core/commands/project-closeout.md +25 -0
  27. package/core/skills/agentic-eval/SKILL.md +195 -0
  28. package/core/skills/chrome-devtools/SKILL.md +97 -0
  29. package/core/skills/code-review/SKILL.md +26 -0
  30. package/core/skills/gh-cli/SKILL.md +2202 -0
  31. package/core/skills/git-commit/SKILL.md +124 -0
  32. package/core/skills/git-workflow-agents/SKILL.md +462 -0
  33. package/core/skills/git-workflow-agents/reference.md +220 -0
  34. package/core/skills/github-actions/SKILL.md +190 -0
  35. package/core/skills/github-issues/SKILL.md +154 -0
  36. package/core/skills/llm-structured-outputs/SKILL.md +323 -0
  37. package/core/skills/llm-structured-outputs/references/provider-details.md +392 -0
  38. package/core/skills/pre-push/SKILL.md +115 -0
  39. package/core/skills/refactor/SKILL.md +645 -0
  40. package/core/skills/web-design-reviewer/SKILL.md +371 -0
  41. package/core/skills/webapp-testing/SKILL.md +127 -0
  42. package/core/skills/webapp-testing/test-helper.js +56 -0
  43. package/core/templates/CLAUDE.md.tmpl +98 -0
  44. package/core/templates/adr-template.md +67 -0
  45. package/core/templates/gh-issue-templates/bug.md +39 -0
  46. package/core/templates/gh-issue-templates/content.md +42 -0
  47. package/core/templates/gh-issue-templates/enhancement.md +36 -0
  48. package/core/templates/gh-issue-templates/feature.md +39 -0
  49. package/core/templates/gh-issue-templates/infrastructure.md +41 -0
  50. package/core/templates/post-edit-reminders.sh.tmpl +19 -0
  51. package/core/templates/settings.json.tmpl +90 -0
  52. package/core/templates/settings.local.json.tmpl +3 -0
  53. package/core/workflows/agent-implementation-workflow.md +346 -0
  54. package/core/workflows/generate-project.md +258 -0
  55. package/core/workflows/implement-project-workflow.md +190 -0
  56. package/core/workflows/issue-tracking.md +89 -0
  57. package/core/workflows/project-closeout-ceremony.md +77 -0
  58. package/core/workflows/review-workflow.md +266 -0
  59. package/engsys.config.example.yaml +46 -0
  60. package/install +202 -0
  61. package/lessons-library/README.md +80 -0
  62. package/lessons-library/async-callbacks-verify-liveness.md +15 -0
  63. package/lessons-library/change-isnt-done-until-every-surface-updated.md +15 -0
  64. package/lessons-library/claim-then-act-for-irreversible-ops.md +16 -0
  65. package/lessons-library/co-commit-entangled-work.md +15 -0
  66. package/lessons-library/dependabot-triage-playbook.md +17 -0
  67. package/lessons-library/deploy-by-digest-and-verify-the-running-revision.md +15 -0
  68. package/lessons-library/enforce-your-guarantee-at-your-boundary.md +16 -0
  69. package/lessons-library/gate-changes-on-measurement-not-vibes.md +15 -0
  70. package/lessons-library/iac-first-no-console-changes.md +15 -0
  71. package/lessons-library/independent-objective-review-gate.md +15 -0
  72. package/lessons-library/keep-an-immutable-source-of-truth.md +15 -0
  73. package/lessons-library/long-agent-runs-checkpoint-not-poll.md +15 -0
  74. package/lessons-library/model-identity-with-stable-ids-and-provenance.md +15 -0
  75. package/lessons-library/operator-choices-are-first-class.md +15 -0
  76. package/lessons-library/prefer-tool-enforced-structured-output.md +15 -0
  77. package/lessons-library/prove-causation-before-acting.md +15 -0
  78. package/lessons-library/re-read-state-before-acting.md +14 -0
  79. package/lessons-library/read-layer-tolerates-unbackfilled-rows.md +15 -0
  80. package/lessons-library/shell-safety-pipefail-and-validate-before-teardown.md +14 -0
  81. package/lessons-library/shift-correctness-left-and-distrust-false-greens.md +15 -0
  82. package/lessons-library/stray-control-bytes-hide-changes.md +14 -0
  83. package/lessons-library/tests-can-assert-the-bug.md +15 -0
  84. package/lessons-library/verify-ground-truth-not-reports.md +15 -0
  85. package/lessons-library/worktrees-need-bootstrap-from-origin-main.md +15 -0
  86. package/lib/commands.js +356 -0
  87. package/lib/generate-team-avatars.mjs +251 -0
  88. package/lib/manifest.js +155 -0
  89. package/lib/render.js +135 -0
  90. package/lib/selftest.js +90 -0
  91. package/lib/util.js +89 -0
  92. package/lib/yaml.js +156 -0
  93. package/optional-agents/gary.md +86 -0
  94. package/optional-agents/jos.md +136 -0
  95. package/optional-agents/sandy.md +101 -0
  96. package/optional-agents/steve.md +161 -0
  97. package/package.json +43 -0
  98. package/stacks/cloud/aws/claude.fragment.md +17 -0
  99. package/stacks/cloud/aws/settings.fragment.json +39 -0
  100. package/stacks/cloud/aws/skills/aws-deployment-preflight/SKILL.md +165 -0
  101. package/stacks/cloud/aws/skills/cloud-architecture-aws/SKILL.md +265 -0
  102. package/stacks/cloud/azure/claude.fragment.md +17 -0
  103. package/stacks/cloud/azure/settings.fragment.json +45 -0
  104. package/stacks/cloud/azure/skills/azure-deployment-preflight/SKILL.md +175 -0
  105. package/stacks/cloud/azure/skills/cloud-architecture-azure/SKILL.md +211 -0
  106. package/stacks/cloud/cloudflare/claude.fragment.md +21 -0
  107. package/stacks/cloud/cloudflare/settings.fragment.json +31 -0
  108. package/stacks/cloud/cloudflare/skills/cloud-architecture-cloudflare/SKILL.md +294 -0
  109. package/stacks/cloud/cloudflare/skills/cloudflare-deployment-preflight/SKILL.md +175 -0
  110. package/stacks/cloud/gcp/claude.fragment.md +17 -0
  111. package/stacks/cloud/gcp/settings.fragment.json +40 -0
  112. package/stacks/cloud/gcp/skills/cloud-architecture-gcp/SKILL.md +208 -0
  113. package/stacks/cloud/gcp/skills/gcp-deployment-preflight/SKILL.md +137 -0
  114. package/stacks/db/mongo/skills/mongo-conventions/SKILL.md +96 -0
  115. package/stacks/db/prisma/claude.fragment.md +49 -0
  116. package/stacks/db/prisma/skills/docker-database-package-copy/SKILL.md +44 -0
  117. package/stacks/db/prisma/skills/prisma-conventions/SKILL.md +37 -0
  118. package/stacks/domain/mobile-growth/skills/apple-ads/SKILL.md +184 -0
  119. package/stacks/domain/mobile-growth/skills/apple-ads/references/benchmark-notes.md +47 -0
  120. package/stacks/domain/mobile-growth/skills/apple-ads/references/official-links.md +53 -0
  121. package/stacks/domain/mobile-growth/skills/google-play-growth/SKILL.md +197 -0
  122. package/stacks/domain/mobile-growth/skills/google-play-growth/references/benchmark-notes.md +47 -0
  123. package/stacks/domain/mobile-growth/skills/google-play-growth/references/official-links.md +45 -0
  124. package/stacks/iac/bicep/claude.fragment.md +14 -0
  125. package/stacks/iac/bicep/settings.fragment.json +20 -0
  126. package/stacks/iac/bicep/skills/iac-bicep/SKILL.md +113 -0
  127. package/stacks/iac/cdk/claude.fragment.md +14 -0
  128. package/stacks/iac/cdk/settings.fragment.json +23 -0
  129. package/stacks/iac/cdk/skills/iac-cdk/SKILL.md +104 -0
  130. package/stacks/iac/terraform/claude.fragment.md +13 -0
  131. package/stacks/iac/terraform/settings.fragment.json +25 -0
  132. package/stacks/iac/terraform/skills/iac-terraform/SKILL.md +93 -0
  133. package/stacks/iac/terraform/skills/terraform-conventions/SKILL.md +87 -0
  134. package/stacks/lang/kotlin/skills/android-testing/SKILL.md +263 -0
  135. package/stacks/lang/kotlin/skills/jetpack-compose/SKILL.md +264 -0
  136. package/stacks/lang/kotlin/skills/kotlin-coroutines/SKILL.md +329 -0
  137. package/stacks/lang/python/skills/python-conventions/SKILL.md +61 -0
  138. package/stacks/lang/shell/skills/shell-scripting/SKILL.md +110 -0
  139. package/stacks/lang/swift/skills/swift-concurrency/SKILL.md +423 -0
  140. package/stacks/lang/swift/skills/swift-concurrency/references/approachable-concurrency.md +80 -0
  141. package/stacks/lang/swift/skills/swift-concurrency/references/concurrency-patterns.md +233 -0
  142. package/stacks/lang/swift/skills/swift-concurrency/references/swiftui-concurrency.md +187 -0
  143. package/stacks/lang/swift/skills/swift-concurrency/references/synchronization-primitives.md +341 -0
  144. package/stacks/lang/swift/skills/swift-testing/SKILL.md +497 -0
  145. package/stacks/lang/swift/skills/swift-testing/references/testing-advanced.md +106 -0
  146. package/stacks/lang/swift/skills/swift-testing/references/testing-patterns.md +504 -0
  147. package/stacks/lang/swift/skills/swiftdata/SKILL.md +334 -0
  148. package/stacks/lang/swift/skills/swiftdata/references/core-data-coexistence.md +504 -0
  149. package/stacks/lang/swift/skills/swiftdata/references/swiftdata-advanced.md +975 -0
  150. package/stacks/lang/swift/skills/swiftdata/references/swiftdata-queries.md +675 -0
  151. package/stacks/lang/swift/skills/swiftui-patterns/SKILL.md +371 -0
  152. package/stacks/lang/swift/skills/swiftui-patterns/references/architecture-patterns.md +486 -0
  153. package/stacks/lang/swift/skills/swiftui-patterns/references/deprecated-migration.md +1097 -0
  154. package/stacks/lang/swift/skills/swiftui-patterns/references/design-polish.md +780 -0
  155. package/stacks/lang/swift/skills/swiftui-patterns/references/platform-and-sharing.md +696 -0
  156. package/stacks/lang/typescript/skills/typescript-conventions/SKILL.md +91 -0
  157. package/stacks/platform/android/claude.fragment.md +40 -0
  158. package/stacks/platform/android/hooks/pre-push-gradle.sh +70 -0
  159. package/stacks/platform/android/settings.fragment.json +13 -0
  160. package/stacks/platform/android/skills/android-build-conventions/SKILL.md +247 -0
  161. package/stacks/platform/ios/claude.fragment.md +24 -0
  162. package/stacks/platform/ios/hooks/pre-push-xcodebuild.sh +82 -0
  163. package/stacks/platform/ios/settings.fragment.json +21 -0
  164. package/stacks/platform/ios/skills/xcodebuildmcp-simulator-logs/SKILL.md +76 -0
  165. package/stacks/platform/web/skills/frontend-testing/SKILL.md +246 -0
  166. package/stacks/platform/web/skills/react-conventions/SKILL.md +261 -0
  167. package/stacks/platform/web/skills/web-platform-conventions/SKILL.md +55 -0
  168. package/stacks/tooling/issue-tracker-github/claude.fragment.md +10 -0
  169. package/stacks/tooling/issue-tracker-github/settings.fragment.json +24 -0
  170. package/stacks/tooling/issue-tracker-github/skills/issue-tracker-github/SKILL.md +278 -0
  171. package/stacks/tooling/issue-tracker-linear/claude.fragment.md +17 -0
  172. package/stacks/tooling/issue-tracker-linear/settings.fragment.json +9 -0
  173. package/stacks/tooling/issue-tracker-linear/skills/issue-tracker-linear/SKILL.md +183 -0
@@ -0,0 +1,220 @@
1
+ # Git Workflow for Agents - Reference
2
+
3
+ This is auxiliary, stack-agnostic reference material for the worktree workflow. The authoritative
4
+ guidance is [SKILL.md](SKILL.md). Commands here use placeholders like `<install-deps-command>`,
5
+ `<build-command>`, `<test-command>`, and `<project>` — substitute your project's actual tooling.
6
+ Examples are shown in bash; translate to your shell as needed.
7
+
8
+ ## Helper Script Sketch
9
+
10
+ A `create-worktree` helper takes an issue number and slug, then:
11
+
12
+ ```bash
13
+ # Usage: create-worktree <issue-number> <slug>
14
+ ISSUE="$1"; SLUG="$2"
15
+ BRANCH="agent/${ISSUE}-${SLUG}"
16
+ WORKTREE="../worktrees/issue-${ISSUE}-${SLUG}"
17
+
18
+ cd <repo-root>
19
+ git fetch origin
20
+ git checkout main
21
+ git pull origin main
22
+
23
+ # Create worktree AND branch together
24
+ git worktree add "$WORKTREE" -b "$BRANCH"
25
+
26
+ cd "$WORKTREE"
27
+ [ -f ../../<project>/.env.local ] && cp ../../<project>/.env.local .env.local
28
+ <install-deps-command>
29
+ echo "Worktree ready at $WORKTREE on branch $BRANCH"
30
+ ```
31
+
32
+ A `cleanup-worktrees` helper lists worktrees, empties each directory (so removal does not fail with
33
+ "Directory not empty" — git won't delete non-git files like dependency dirs or build output), then
34
+ removes them and prunes stale references and merged `agent/` branches:
35
+
36
+ ```bash
37
+ cd <repo-root>
38
+ git worktree list
39
+ # For each non-primary worktree: empty its dir, then `git worktree remove <path> --force`
40
+ git worktree prune
41
+ git branch --merged main | grep 'agent/' | xargs -r git branch -d
42
+ ```
43
+
44
+ ## Single vs. Multi-Package Workflows
45
+
46
+ For a single package/module, install and build just that target. For a monorepo touching several
47
+ packages, install all workspaces and use the package manager's filter/scope mechanism to build only
48
+ the affected packages plus their dependents. The principle is the same regardless of language:
49
+ **build the changed package and everything that depends on it.**
50
+
51
+ ## Database / Schema Migration Strategies
52
+
53
+ When a change includes a schema or data-layer migration, coordinate so parallel agents don't
54
+ corrupt a shared database.
55
+
56
+ - **Strategy 1 — Coordination (recommended for dev):** one agent creates and commits the migration;
57
+ others rebase on `origin/main` and apply pending migrations to their local DB before continuing.
58
+ - **Strategy 2 — Separate databases per worktree:** override the DB connection string in each
59
+ worktree's `.env.local`, create a uniquely-named database per worktree, and run migrations there.
60
+ - **Strategy 3 — Isolated dev database:** point each worktree at its own remote dev database.
61
+
62
+ After a migration lands, regenerate any generated client/codegen artifacts and rebuild dependent
63
+ packages.
64
+
65
+ ## Infrastructure Validation
66
+
67
+ If the project uses infrastructure-as-code, validate locally before committing using the project's
68
+ IaC tool (Terraform `plan`/`validate`, Bicep `build` + deployment `what-if`/`validate`,
69
+ CloudFormation `validate-template`, Pulumi `preview`, etc.). Preview the diff against the target
70
+ environment before deploying. Never make changes through a cloud console that bypass the IaC.
71
+
72
+ ## Troubleshooting
73
+
74
+ ### Worktree creation fails
75
+
76
+ `fatal: '<branch>' is already checked out at '<path>'` — the branch is checked out elsewhere.
77
+
78
+ ```bash
79
+ git worktree list # find where it's checked out
80
+ git worktree remove <path> # remove if stale
81
+ # or pick a new branch name
82
+ git worktree add ../worktrees/issue-42-foo-v2 -b agent/42-foo-v2
83
+ ```
84
+
85
+ ### Worktree won't remove
86
+
87
+ `contains modified or untracked files` — commit/stash first, or force:
88
+
89
+ ```bash
90
+ git worktree remove --force <worktree-path>
91
+ ```
92
+
93
+ `Directory not empty` — git does not delete non-git files (dependency dirs, build output). Empty the
94
+ directory first, then remove:
95
+
96
+ ```bash
97
+ rm -rf ../worktrees/issue-42-foo/*
98
+ git worktree remove ../worktrees/issue-42-foo
99
+ ```
100
+
101
+ ### Build fails after switching worktrees
102
+
103
+ Stale dependencies are the usual cause. Clean and reinstall:
104
+
105
+ ```bash
106
+ rm -rf <deps-dir> <lockfile>
107
+ <install-deps-command>
108
+ <build-command>
109
+ ```
110
+
111
+ ### Tests fail with database errors
112
+
113
+ Point tests at a dedicated test database (separate connection string in `.env.local`/`.env.test`),
114
+ reset/seed it, and isolate the test DB per worktree if agents run in parallel.
115
+
116
+ ### Merge conflicts during rebase
117
+
118
+ ```bash
119
+ git fetch origin main
120
+ git rebase origin/main
121
+ # resolve conflicts, then:
122
+ git add <resolved-files>
123
+ git rebase --continue
124
+ # if it gets messy:
125
+ git rebase --abort
126
+ ```
127
+
128
+ If the rebase stops on a commit already merged to main (expected for stacked branches):
129
+
130
+ ```bash
131
+ git rebase --skip
132
+ ```
133
+
134
+ After a successful rebase, force-push safely:
135
+
136
+ ```bash
137
+ git push --force-with-lease origin agent/<branch>
138
+ ```
139
+
140
+ ### Disk-space pressure from many worktrees
141
+
142
+ Prefer a package manager that hard-links/dedupes dependencies, install only the workspaces you need,
143
+ and clean build artifacts and removed worktrees aggressively (`git worktree prune`).
144
+
145
+ ## Advanced Workflows
146
+
147
+ ### Cleaning up commit history
148
+
149
+ ```bash
150
+ git rebase -i origin/main # squash/reword/drop commits
151
+ git push --force-with-lease # only if the branch isn't shared
152
+ ```
153
+
154
+ ### Cherry-picking / sharing work between worktrees
155
+
156
+ ```bash
157
+ # In source worktree: find the commit
158
+ git log --oneline
159
+ # In target worktree: apply it
160
+ git cherry-pick <commit-hash>
161
+ ```
162
+
163
+ Sharing via committed-and-pushed commits (then `git fetch` + cherry-pick) is safer than copying
164
+ working-tree files.
165
+
166
+ ### Switching issues mid-work
167
+
168
+ Commit WIP (`wip: save progress (#42)`), optionally push to preserve it, create/switch to the other
169
+ issue's worktree, and return later by `cd`-ing back.
170
+
171
+ ## GitHub via gh CLI (preferred) and MCP (fallback)
172
+
173
+ Prefer `gh` CLI for issues, PRs, Actions, and project boards. Examples:
174
+
175
+ ```bash
176
+ gh issue create --repo <owner>/<repo> --title "..." --body-file tmp/issue-body.md --label "bug"
177
+ gh issue view 42 --repo <owner>/<repo>
178
+ gh pr create --base main --head agent/42-foo --title "fix(scope): ..." --body-file tmp/pr-body-42.md
179
+ ```
180
+
181
+ The `github` MCP server (configured in `.mcp.json`) is a fallback for when `gh` auth or network
182
+ fails. ProjectV2 (project boards) must always use `gh project` / `gh api graphql` — MCP does not
183
+ support them.
184
+
185
+ ## Git Worktree Command Reference
186
+
187
+ ```bash
188
+ git worktree list # list
189
+ git worktree list --porcelain # machine-readable
190
+ git worktree add <path> -b <branch> # new branch + worktree (preferred)
191
+ git worktree add <path> <branch> # existing branch (if not checked out elsewhere)
192
+ git worktree add <path> -b <branch> <sha> # from a specific commit
193
+ git worktree remove <path> # remove
194
+ git worktree remove --force <path> # ignore uncommitted changes
195
+ git worktree prune # drop stale references
196
+ git worktree prune --dry-run # preview
197
+ ```
198
+
199
+ To "move" a worktree: note its branch, `git worktree remove` the old path, then `git worktree add`
200
+ at the new path.
201
+
202
+ ## Diffing your branch against main
203
+
204
+ ```bash
205
+ git diff main...HEAD # changes in your branch only (merge-base)
206
+ git diff main..HEAD # all differences between the two tips
207
+ git diff --name-only main...HEAD # file names only
208
+ git diff --stat main...HEAD # summary stats
209
+ ```
210
+
211
+ ## FAQ
212
+
213
+ - **Multiple worktrees for one issue?** No — one issue, one worktree. Use commits to checkpoint and
214
+ share progress.
215
+ - **Committed in the main checkout by mistake?** Note the hash, `git reset --hard origin/main` in the
216
+ main checkout, then `git cherry-pick <hash>` in the worktree.
217
+ - **Run the same service in two worktrees at once?** Yes, but assign different ports (e.g. via a
218
+ `PORT` env var) to avoid collisions.
219
+ - **Worktrees for small fixes?** Only when isolation/parallelism justifies the setup overhead;
220
+ otherwise a plain branch in the main checkout is fine.
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: github-actions
3
+ description: GitHub Actions workflow authoring guidance — the `${{ }}` expression function set, shell-injection and multi-line-output safety in `run:` steps, draft-gated CI triggers, and GraphQL rate-limit handling. Activate when editing `.github/workflows/*.yml`/`*.yaml`, authoring or reviewing GitHub Actions workflows, or debugging a CI gate that runs/skips unexpectedly.
4
+ ---
5
+
6
+ # GitHub Actions
7
+
8
+ Practical, hard-won guidance for authoring and reviewing GitHub Actions workflows.
9
+ GitHub is the assumed code host for every project here — PRs and CI live on GitHub — so
10
+ this skill is installed everywhere. It complements core `gh-cli` (which covers `gh run`,
11
+ `gh workflow`, `gh secret` from the command line); this skill is about the workflow YAML
12
+ itself.
13
+
14
+ Each lesson below is something that **looks right but is silently wrong**: it passes
15
+ review, ships, and then fails open (a gate never runs, a value truncates, an injection
16
+ lands). Apply the review checklist at the bottom to any workflow PR.
17
+
18
+ ## 1. The `${{ }}` expression language has a tiny function set
19
+
20
+ GitHub Actions expressions are **not JavaScript**. The only built-in functions are:
21
+
22
+ ```text
23
+ contains startsWith endsWith format join toJSON fromJSON hashFiles
24
+ ```
25
+
26
+ There is **no** `toLower`, `toUpper`, `trim`, or `replace`. Typing one does not error —
27
+ the expression evaluates to an empty string **silently**, so a condition that was meant
28
+ to exclude something fails open and never excludes it.
29
+
30
+ ```yaml
31
+ # ❌ WRONG — toLower() does not exist; the whole expression is "" and the guard never fires
32
+ if: ${{ !contains(toLower(github.event.pull_request.title), 'release') }}
33
+ ```
34
+
35
+ Workaround A — enumerate the case variants with the functions that do exist:
36
+
37
+ ```yaml
38
+ # ✅ Cover the common cases explicitly
39
+ if: |
40
+ !startsWith(github.event.pull_request.title, 'Release') &&
41
+ !startsWith(github.event.pull_request.title, 'release') &&
42
+ !startsWith(github.event.pull_request.title, 'RELEASE')
43
+ ```
44
+
45
+ Workaround B — do the string munging in a `run:` step (shell has real `tr`, `sed`, etc.)
46
+ and emit a normalized value as a step output, then branch on that:
47
+
48
+ ```yaml
49
+ - id: norm
50
+ env:
51
+ TITLE: ${{ github.event.pull_request.title }}
52
+ run: |
53
+ lower="$(printf '%s' "$TITLE" | tr '[:upper:]' '[:lower:]')"
54
+ echo "is_release=$(case "$lower" in release*) echo true;; *) echo false;; esac)" >> "$GITHUB_OUTPUT"
55
+ - if: steps.norm.outputs.is_release == 'false'
56
+ run: ...
57
+ ```
58
+
59
+ Reference: <https://docs.github.com/en/actions/learn-github-actions/expressions#functions>.
60
+ Any `toLower`/`toUpper`/`trim`/`replace` inside `${{ }}` is a bug — rewrite it.
61
+
62
+ ## 2. `run:` step safety — outputs and injection
63
+
64
+ ### Multi-line step outputs need a heredoc delimiter
65
+
66
+ Writing `echo "result=$value" >> "$GITHUB_OUTPUT"` captures only the **first line** when
67
+ `$value` is multi-line (e.g. a failed `gh api` JSON body, a `git log`/`git diff`
68
+ aggregation, anything piped through `jq`/`yq` without `-r .field`). Downstream steps then
69
+ branch on a truncated, present-but-stale string — silent state corruption.
70
+
71
+ ```yaml
72
+ # ❌ WRONG — truncates at the first newline
73
+ - id: convert
74
+ run: |
75
+ output="$(gh api graphql ... 2>&1)"
76
+ echo "result=$output" >> "$GITHUB_OUTPUT"
77
+
78
+ # ✅ CORRECT — heredoc delimiter; runner reads until the closing EOF
79
+ - id: convert
80
+ run: |
81
+ output="$(gh api graphql ... 2>&1)"
82
+ {
83
+ echo "result<<EOF"
84
+ echo "$output"
85
+ echo "EOF"
86
+ } >> "$GITHUB_OUTPUT"
87
+ ```
88
+
89
+ The delimiter (`EOF`, or any unique string not present in the payload) tells the runner
90
+ to read to the matching closer instead of splitting on `\n`. When in doubt, use it — the
91
+ cost is two lines, the bug is invisible.
92
+
93
+ ### Never inline-expand `${{ github.* }}` inside a `run:` body
94
+
95
+ `${{ ... }}` is **textually substituted before the shell parses the line**. If the value
96
+ contains shell metacharacters — quotes, backticks, `$(...)`, `;` — the shell executes
97
+ them. With attacker-influenced inputs (PR title, `head_ref`, branch name, issue body,
98
+ fork commit messages) this is direct command injection.
99
+
100
+ ```yaml
101
+ # ❌ WRONG — injection surface; substituted before the shell parses it
102
+ - run: |
103
+ gh api graphql -F id='${{ github.event.pull_request.node_id }}' -f query='...'
104
+
105
+ # ✅ CORRECT — pass via env:, dereference the (quoted) env var
106
+ - env:
107
+ PR_NODE_ID: ${{ github.event.pull_request.node_id }}
108
+ run: |
109
+ gh api graphql -F id="$PR_NODE_ID" -f query='...'
110
+ ```
111
+
112
+ Rule of thumb: **`${{ ... }}` belongs in `with:`, `env:`, `if:`, and `name:` — not in
113
+ `run:` script bodies.** The bar is not "is this field safe today?" but "will the pattern
114
+ still be safe when someone copies it and substitutes the PR title?" Genuinely safe
115
+ exceptions: `${{ secrets.* }}` in an `env:` mapping, and `${{ runner.os }}` / `${{ matrix.* }}`
116
+ defined entirely by the workflow itself. For user-influenced data there are no exceptions.
117
+
118
+ (Optional but cheap: `pipx install zizmor && zizmor .github/workflows` flags the
119
+ `template-injection` category automatically.)
120
+
121
+ ## 3. Draft-gated jobs need `ready_for_review` in the trigger
122
+
123
+ A job guarded by `if: github.event.pull_request.draft == false` only runs on events the
124
+ workflow is actually subscribed to. A `pull_request:` trigger with no `types:` key
125
+ defaults to `[opened, synchronize, reopened]` — which does **not** include
126
+ `ready_for_review`.
127
+
128
+ Consequence: you mark the PR Ready expecting the required gate to run, but no new run is
129
+ scheduled. The gated leg stays `SKIPPED` from the last draft run, and GitHub treats a
130
+ SKIPPED required check as satisfied — so the PR shows mergeable as a **hollow green**.
131
+
132
+ ```yaml
133
+ # ❌ Marking Ready never schedules a run — ready_for_review isn't subscribed
134
+ on:
135
+ pull_request:
136
+ branches: [main]
137
+
138
+ # ✅ The draft→ready transition itself fires the workflow
139
+ on:
140
+ pull_request:
141
+ types: [opened, synchronize, reopened, ready_for_review]
142
+ branches: [main]
143
+ ```
144
+
145
+ Add `synchronize` too (it's in the default set, but list it explicitly once you specify
146
+ `types:`, since specifying `types:` replaces the default entirely). Until the trigger is
147
+ fixed, the manual workaround is to force a `synchronize` event:
148
+
149
+ ```bash
150
+ git commit --allow-empty -m "chore: trigger CI after ready-for-review" && git push
151
+ gh pr checks <pr-number> --watch # confirm the gated leg shows COMPLETED/SUCCESS, not SKIPPED
152
+ ```
153
+
154
+ Before merging a draft-gated PR: confirm `mergeStateStatus == CLEAN` (not merely
155
+ `MERGEABLE`), the specific leg shows COMPLETED/SUCCESS, and that run was triggered **after**
156
+ the PR was marked Ready.
157
+
158
+ ## 4. GraphQL / API rate limits — defer, don't block the run
159
+
160
+ `gh api graphql`, `gh project item-edit`, and `gh issue edit --add-assignee` consume the
161
+ **per-user** GraphQL budget (5,000/hr), shared across every tool and agent on that token.
162
+ A burst of parallel mutations drains it in minutes; the error is
163
+ `API rate limit already exceeded for user ID …`.
164
+
165
+ - **Don't block the whole run on it.** Capture the GraphQL-dependent work (assign issues,
166
+ flip board status) and continue with everything that doesn't need GraphQL. Most REST
167
+ calls (`gh issue view`, `gh pr create`, `gh api repos/...`) draw on the separate `core`
168
+ budget. Retry the deferred work after the `reset` timestamp passes (~15 min).
169
+ - **Mutate sequentially, not in parallel.** A tight `for` loop (one mutation per item)
170
+ is gentler than bursty parallel calls, which compound the problem.
171
+ - Peek before a long sequence of board mutations; below ~200 remaining, defer:
172
+
173
+ ```bash
174
+ gh api rate_limit --jq '.resources' # compare .graphql.remaining vs .core.remaining
175
+ ```
176
+
177
+ ## Review checklist (any workflow PR)
178
+
179
+ ```text
180
+ [ ] No toLower/toUpper/trim/replace inside ${{ }} — only contains/startsWith/endsWith/
181
+ format/join/toJSON/fromJSON/hashFiles exist; munge strings in a run: step instead.
182
+ [ ] Every `>> $GITHUB_OUTPUT` for a possibly-multi-line value uses the heredoc
183
+ delimiter form (or the value is guaranteed single-line via `-r .field`/`head -n1`).
184
+ [ ] No ${{ github.* }} / ${{ steps.* }} / ${{ inputs.* }} inline-expanded inside a
185
+ run: body — pass via env: and dereference the quoted env var.
186
+ [ ] Any draft-gated required job: `ready_for_review` (and `synchronize`) is in the
187
+ pull_request: types: list, so marking Ready actually schedules the gate.
188
+ [ ] GraphQL-heavy steps tolerate a rate limit (defer, don't fail the run) and mutate
189
+ sequentially rather than in parallel.
190
+ ```
@@ -0,0 +1,154 @@
1
+ ---
2
+ name: github-issues
3
+ description: 'Create, update, and manage GitHub issues using MCP tools. Use this skill when users want to create bug reports, feature requests, or task issues, update existing issues, add labels/assignees/milestones, or manage issue workflows. Triggers on requests like "create an issue", "file a bug", "request a feature", "update issue X", or any GitHub issue management task.'
4
+ ---
5
+
6
+ # GitHub Issues
7
+
8
+ Manage GitHub issues using `gh` CLI (preferred) with `user-github` MCP server as fallback.
9
+
10
+ **Important:** The GitHub MCP does **not** support GitHub Projects (ProjectV2). For project board operations (priorities, status, custom fields, waves), always use `gh project` or `gh api graphql`.
11
+
12
+ ## Tool Priority
13
+
14
+ 1. **`gh` CLI** (preferred) — full coverage, projects support, GraphQL access
15
+ 2. **GitHub MCP** (fallback) — use when `gh` CLI has auth or connectivity issues
16
+
17
+ ## Available MCP Tools (fallback only)
18
+
19
+ | Tool | Purpose |
20
+ | -------------------------------- | ---------------------- |
21
+ | `mcp__github__create_issue` | Create new issues |
22
+ | `mcp__github__update_issue` | Update existing issues |
23
+ | `mcp__github__get_issue` | Fetch issue details |
24
+ | `mcp__github__search_issues` | Search issues |
25
+ | `mcp__github__add_issue_comment` | Add comments |
26
+ | `mcp__github__list_issues` | List repository issues |
27
+
28
+ ## Workflow
29
+
30
+ 1. **Determine action**: Create, update, or query?
31
+ 2. **Gather context**: Get repo info, existing labels, milestones if needed
32
+ 3. **Structure content**: Use appropriate template from [references/templates.md](references/templates.md)
33
+ 4. **Execute**: Use `gh` CLI first; fall back to MCP tools if CLI has issues
34
+ 5. **Confirm**: Report the issue URL to user
35
+
36
+ ## Creating Issues
37
+
38
+ ### Using gh CLI (preferred)
39
+
40
+ ```bash
41
+ # Write body to tmp/ file first, then:
42
+ gh issue create \
43
+ --repo <owner>/<repo> \
44
+ --title "🐛 Bug: Description" \
45
+ --body-file tmp/issue-body-slug.md \
46
+ --label "bug,<component>"
47
+ ```
48
+
49
+ ### Using MCP (fallback)
50
+
51
+ ### Required Parameters
52
+
53
+ ```text
54
+ owner: repository owner (org or user)
55
+ repo: repository name
56
+ title: clear, actionable title
57
+ body: structured markdown content
58
+ ```
59
+
60
+ ### Optional Parameters
61
+
62
+ ```text
63
+ labels: ["bug", "enhancement", "documentation", ...]
64
+ assignees: ["username1", "username2"]
65
+ milestone: milestone number (integer)
66
+ ```
67
+
68
+ ### Title Guidelines
69
+
70
+ - Start with type prefix when useful: `[Bug]`, `[Feature]`, `[Docs]`
71
+ - Be specific and actionable
72
+ - Keep under 72 characters
73
+ - Examples:
74
+ - `[Bug] Login fails with SSO enabled`
75
+ - `[Feature] Add dark mode support`
76
+ - `Add unit tests for auth module`
77
+
78
+ ### Body Structure
79
+
80
+ Always use the templates in [references/templates.md](references/templates.md). Choose based on issue type:
81
+
82
+ | User Request | Template |
83
+ | ------------------------------- | --------------- |
84
+ | Bug, error, broken, not working | Bug Report |
85
+ | Feature, enhancement, add, new | Feature Request |
86
+ | Task, chore, refactor, update | Task |
87
+
88
+ ## Updating Issues
89
+
90
+ Use `mcp__github__update_issue` with:
91
+
92
+ ```text
93
+ owner, repo, issue_number (required)
94
+ title, body, state, labels, assignees, milestone (optional - only changed fields)
95
+ ```
96
+
97
+ State values: `open`, `closed`
98
+
99
+ ## Examples
100
+
101
+ ### Example 1: Bug Report
102
+
103
+ **User**: "Create a bug issue - the login page crashes when using SSO"
104
+
105
+ **Action**: Call `mcp__github__create_issue` with:
106
+
107
+ ```json
108
+ {
109
+ "owner": "github",
110
+ "repo": "awesome-copilot",
111
+ "title": "[Bug] Login page crashes when using SSO",
112
+ "body": "## Description\nThe login page crashes when users attempt to authenticate using SSO.\n\n## Steps to Reproduce\n1. Navigate to login page\n2. Click 'Sign in with SSO'\n3. Page crashes\n\n## Expected Behavior\nSSO authentication should complete and redirect to dashboard.\n\n## Actual Behavior\nPage becomes unresponsive and displays error.\n\n## Environment\n- Browser: [To be filled]\n- OS: [To be filled]\n\n## Additional Context\nReported by user.",
113
+ "labels": ["bug"]
114
+ }
115
+ ```
116
+
117
+ ### Example 2: Feature Request
118
+
119
+ **User**: "Create a feature request for dark mode with high priority"
120
+
121
+ **Action**: Call `mcp__github__create_issue` with:
122
+
123
+ ```json
124
+ {
125
+ "owner": "github",
126
+ "repo": "awesome-copilot",
127
+ "title": "[Feature] Add dark mode support",
128
+ "body": "## Summary\nAdd dark mode theme option for improved user experience and accessibility.\n\n## Motivation\n- Reduces eye strain in low-light environments\n- Increasingly expected by users\n- Improves accessibility\n\n## Proposed Solution\nImplement theme toggle with system preference detection.\n\n## Acceptance Criteria\n- [ ] Toggle switch in settings\n- [ ] Persists user preference\n- [ ] Respects system preference by default\n- [ ] All UI components support both themes\n\n## Alternatives Considered\nNone specified.\n\n## Additional Context\nHigh priority request.",
129
+ "labels": ["enhancement", "high-priority"]
130
+ }
131
+ ```
132
+
133
+ ## Common Labels
134
+
135
+ Use these standard labels when applicable:
136
+
137
+ | Label | Use For |
138
+ | ------------------ | ----------------------------- |
139
+ | `bug` | Something isn't working |
140
+ | `enhancement` | New feature or improvement |
141
+ | `documentation` | Documentation updates |
142
+ | `good first issue` | Good for newcomers |
143
+ | `help wanted` | Extra attention needed |
144
+ | `question` | Further information requested |
145
+ | `wontfix` | Will not be addressed |
146
+ | `duplicate` | Already exists |
147
+ | `high-priority` | Urgent issues |
148
+
149
+ ## Tips
150
+
151
+ - Always confirm the repository context before creating issues
152
+ - Ask for missing critical information rather than guessing
153
+ - Link related issues when known: `Related to #123`
154
+ - For updates, fetch current issue first to preserve unchanged fields