@monte3l/groundwork 1.0.0-rc.2 → 1.0.0-rc.4

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 (170) hide show
  1. package/README.md +13 -5
  2. package/bin/m3l-groundwork.mjs +36 -2
  3. package/dist/assets.d.ts +10 -0
  4. package/dist/assets.js +14 -0
  5. package/dist/baseline-stage.d.ts +173 -0
  6. package/dist/baseline-stage.js +215 -0
  7. package/dist/caps.d.ts +4 -1
  8. package/dist/caps.js +17 -3
  9. package/dist/conflicts.d.ts +23 -2
  10. package/dist/conflicts.js +89 -11
  11. package/dist/customize-paths.d.ts +92 -0
  12. package/dist/customize-paths.js +115 -0
  13. package/dist/emit.d.ts +50 -1
  14. package/dist/emit.js +121 -13
  15. package/dist/fatal.d.ts +70 -0
  16. package/dist/fatal.js +132 -0
  17. package/dist/format-error.d.ts +113 -0
  18. package/dist/format-error.js +553 -0
  19. package/dist/fs-guard.d.ts +142 -0
  20. package/dist/fs-guard.js +222 -0
  21. package/dist/git.js +10 -1
  22. package/dist/harness/conformance.js +2 -0
  23. package/dist/harness/frontmatter.js +2 -13
  24. package/dist/harness/grade.js +37 -8
  25. package/dist/harness/rules.d.ts +20 -3
  26. package/dist/harness/rules.js +108 -6
  27. package/dist/harness/types.d.ts +13 -0
  28. package/dist/harness/types.js +3 -0
  29. package/dist/inventory.d.ts +77 -3
  30. package/dist/inventory.js +103 -12
  31. package/dist/jsonc.d.ts +49 -2
  32. package/dist/jsonc.js +140 -7
  33. package/dist/main.d.ts +62 -3
  34. package/dist/main.js +574 -67
  35. package/dist/merge-json.d.ts +47 -4
  36. package/dist/merge-json.js +120 -8
  37. package/dist/mode.js +12 -2
  38. package/dist/pack-stage.d.ts +210 -0
  39. package/dist/pack-stage.js +287 -0
  40. package/dist/packs.d.ts +21 -13
  41. package/dist/packs.js +241 -28
  42. package/dist/palette.d.ts +23 -0
  43. package/dist/palette.js +22 -0
  44. package/dist/plugin.d.ts +122 -6
  45. package/dist/plugin.js +687 -47
  46. package/dist/report.d.ts +21 -2
  47. package/dist/report.js +93 -5
  48. package/dist/staging.d.ts +176 -0
  49. package/dist/staging.js +375 -0
  50. package/dist/survey/fs-walk.d.ts +34 -2
  51. package/dist/survey/fs-walk.js +70 -5
  52. package/dist/survey/internal/blocked-path.d.ts +27 -0
  53. package/dist/survey/internal/blocked-path.js +129 -0
  54. package/dist/survey/internal/package-json.d.ts +13 -0
  55. package/dist/survey/internal/package-json.js +37 -0
  56. package/dist/survey/internal/read-guard.d.ts +178 -0
  57. package/dist/survey/internal/read-guard.js +276 -0
  58. package/dist/survey/survey-docs.d.ts +17 -2
  59. package/dist/survey/survey-docs.js +61 -21
  60. package/dist/survey/survey-harness.d.ts +20 -2
  61. package/dist/survey/survey-harness.js +87 -46
  62. package/dist/survey/survey-shape.d.ts +17 -2
  63. package/dist/survey/survey-shape.js +60 -46
  64. package/dist/survey/survey-toolchain.d.ts +16 -1
  65. package/dist/survey/survey-toolchain.js +69 -66
  66. package/dist/survey/survey.js +6 -4
  67. package/dist/survey/types.d.ts +79 -0
  68. package/dist/survey/types.js +2 -6
  69. package/dist/term.d.ts +80 -0
  70. package/dist/term.js +145 -0
  71. package/dist/tokens.js +2 -0
  72. package/dist/toolchain/conformance.js +2 -0
  73. package/dist/toolchain/grade.js +26 -8
  74. package/dist/toolchain/rules.d.ts +13 -4
  75. package/dist/toolchain/rules.js +16 -0
  76. package/dist/toolchain/tsconfig-chain.d.ts +2 -0
  77. package/dist/toolchain/tsconfig-chain.js +32 -8
  78. package/dist/toolchain/types.d.ts +16 -4
  79. package/dist/toolchain/types.js +3 -0
  80. package/package.json +4 -3
  81. package/plugin/skills/customize/SKILL.md +292 -18
  82. package/plugin/src/domain-map.ts +39 -14
  83. package/plugin/src/index.ts +5 -1
  84. package/plugin/src/kind-facet-map.ts +25 -8
  85. package/plugin/src/pack-map.ts +147 -25
  86. package/plugin/src/plugin-map.ts +236 -0
  87. package/templates/core/.claude/agents/Explore.md +0 -1
  88. package/templates/core/.claude/agents/code-implementer.md +4 -4
  89. package/templates/core/.claude/agents/code-reviewer.md +4 -4
  90. package/templates/core/.claude/agents/silent-failure-hunter.md +2 -2
  91. package/templates/core/.claude/agents/test-author.md +7 -5
  92. package/templates/core/.claude/hooks/guard-branch-isolation.mjs +56 -10
  93. package/templates/core/.claude/hooks/guard-double-background.mjs +13 -8
  94. package/templates/core/.claude/hooks/guard-git-push-signed.mjs +12 -9
  95. package/templates/core/.claude/hooks/guard-hub-src-writes.mjs +1890 -38
  96. package/templates/core/.claude/hooks/guard-js-extension.mjs +2 -1
  97. package/templates/core/.claude/hooks/guard-no-commonjs.mjs +7 -5
  98. package/templates/core/.claude/hooks/guard-secret-writes.mjs +7 -5
  99. package/templates/core/.claude/hooks/inject-decision-gate.mjs +12 -9
  100. package/templates/core/.claude/hooks/post-edit-verify.mjs +276 -98
  101. package/templates/core/.claude/rules/agent-dispatch.md +7 -0
  102. package/templates/core/.claude/rules/tests.md +2 -2
  103. package/templates/core/.claude/settings.json +5 -0
  104. package/templates/core/.claude/skills/finishing-work/SKILL.md +58 -10
  105. package/templates/core/.claude/skills/harness-guidance/SKILL.md +16 -7
  106. package/templates/core/.claude/skills/starting-work/SKILL.md +5 -0
  107. package/templates/core/.claude/skills/triaging-ci/SKILL.md +9 -8
  108. package/templates/core/.claude/skills/typescript-guidance/SKILL.md +137 -20
  109. package/templates/core/.claude/skills/typescript-guidance/references/area-catalog.md +135 -0
  110. package/templates/core/.claude/skills/typescript-guidance/references/tooling-sources.md +113 -0
  111. package/templates/core/.claude/skills/writing-commits/SKILL.md +2 -2
  112. package/templates/core/.github/dependabot.yml +18 -0
  113. package/templates/core/.github/workflows/ci.yml +15 -15
  114. package/templates/core/.github/workflows/dependency-review.yml +2 -2
  115. package/templates/core/.github/workflows/security-audit.yml +10 -4
  116. package/templates/core/.prettierignore +4 -0
  117. package/templates/core/CLAUDE.md +53 -3
  118. package/templates/core/README.md +30 -10
  119. package/templates/core/_gitignore +17 -0
  120. package/templates/core/bin/check-exports.mjs +11 -5
  121. package/templates/core/bin/lib/agent-roster.mjs +1 -1
  122. package/templates/core/bin/lib/frontmatter.mjs +4 -2
  123. package/templates/core/bin/lib/harness-rules.mjs +169 -20
  124. package/templates/core/bin/lib/protected-paths.mjs +93 -5
  125. package/templates/core/bin/lib/toolchain-rules.mjs +187 -26
  126. package/templates/core/bin/lib/verify-steps.mjs +29 -11
  127. package/templates/core/bin/verify.mjs +12 -0
  128. package/templates/core/eslint.config.js +5 -0
  129. package/templates/core/package.json +7 -7
  130. package/templates/core/vitest.config.ts +8 -1
  131. package/templates/packs/README.md +44 -24
  132. package/templates/packs/github/files/.claude/skills/reviewing-dependabot-prs/SKILL.md +133 -0
  133. package/templates/packs/github/files/.claude/skills/triaging-scan-alerts/SKILL.md +88 -0
  134. package/templates/packs/github/files/.claude/skills/watching-pr-checks/SKILL.md +94 -0
  135. package/templates/packs/github/files/.github/workflows/claude-pr-review.yml +267 -0
  136. package/templates/packs/github/files/.github/workflows/claude.yml +106 -0
  137. package/templates/packs/github/pack.json +19 -0
  138. package/templates/packs/harness-extras/files/.claude/hooks/guard-readonly-bash.mjs +1122 -65
  139. package/templates/packs/harness-extras/files/.claude/hooks/reinject-compact-handoff.mjs +147 -13
  140. package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline.mjs +6 -2
  141. package/templates/packs/harness-extras/files/.claude/hooks/write-compact-handoff.mjs +227 -44
  142. package/templates/packs/harness-extras/pack.json +18 -13
  143. package/templates/packs/publishing/files/.changeset/README.md +25 -0
  144. package/templates/packs/publishing/files/.changeset/config.json +7 -0
  145. package/templates/packs/publishing/files/.github/release-tools/package.json +9 -0
  146. package/templates/packs/publishing/files/.github/workflows/release.yml +295 -0
  147. package/templates/packs/publishing/files/REUSE.toml +28 -0
  148. package/templates/packs/publishing/files/bin/check-dts-deps.mjs +234 -0
  149. package/templates/packs/publishing/files/bin/check-license-headers.mjs +217 -0
  150. package/templates/packs/publishing/files/bin/check-publish-version.mjs +149 -0
  151. package/templates/packs/publishing/files/bin/lib/npm-publish-args.mjs +86 -0
  152. package/templates/packs/publishing/files/bin/pnpm-publish-shim.mjs +86 -0
  153. package/templates/packs/publishing/pack.json +41 -0
  154. package/templates/packs/{harness-extras → quality}/files/bin/check-file-budget.mjs +6 -4
  155. package/templates/packs/quality/pack.json +29 -0
  156. package/templates/packs/supply-chain/files/.github/workflows/gitleaks.yml +52 -0
  157. package/templates/packs/supply-chain/files/.github/workflows/scorecard.yml +48 -0
  158. package/templates/packs/supply-chain/files/.gitleaks.toml +2 -0
  159. package/templates/packs/supply-chain/pack.json +19 -0
  160. package/templates/packs/worktrees/files/.claude/hooks/ensure-worktree-deps.mjs +283 -0
  161. package/templates/packs/worktrees/files/.claude/hooks/guard-worktree-only.mjs +245 -0
  162. package/templates/packs/worktrees/files/.claude/hooks/repair-core-bare.mjs +335 -0
  163. package/templates/packs/worktrees/files/.claude/skills/working-in-worktrees/SKILL.md +139 -0
  164. package/templates/packs/worktrees/files/.worktreeinclude +11 -0
  165. package/templates/packs/worktrees/pack.json +64 -0
  166. package/templates/packs/statusline/pack.json +0 -31
  167. /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline-layout.mjs +0 -0
  168. /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/subagent-statusline.mjs +0 -0
  169. /package/templates/packs/{harness-extras → quality}/files/.claude/agents/type-design-analyzer.md +0 -0
  170. /package/templates/packs/{harness-extras → quality}/files/bin/file-budget-baseline.json +0 -0
@@ -18,24 +18,33 @@ templates/packs/<name>/
18
18
 
19
19
  ## The wiring contract
20
20
 
21
- **A pack never edits YAML or JavaScript.** It may add files under `files/`,
22
- and may extend three JSON files the baseline already reads at runtime:
21
+ **A pack never edits YAML or JavaScript.** It may add files under `files/`.
22
+ **A pack also can't ship a `.claude/rules/*.md` file**: the harness grader's
23
+ structural `claudemd-refs` rule fails on any rule `CLAUDE.md` doesn't name
24
+ by path, and a pack has no way to edit `CLAUDE.md` (that's not one of the
25
+ three JSON files below either). If a pack needs to state a project-wide
26
+ policy, put it in the body of a skill it ships instead — see the `worktrees`
27
+ pack's `working-in-worktrees` skill for the pattern.
28
+ It may also extend three JSON files the baseline already reads at runtime:
23
29
  `.claude/settings.json` (hook registrations, and top-level harness settings
24
30
  such as `statusLine`), `package.json` (`scripts`), and
25
- `bin/lib/verify-steps.packs.json` (gate steps, keyed to one of the five
26
- fixed verify groups `templates/core/bin/lib/verify-steps.mjs` defines —
27
- `format`/`lint`/`typecheck`/`build`/`test`). A gate registered this way runs
31
+ `bin/lib/verify-steps.packs.json`. That last file holds gate steps, each
32
+ keyed to one of the five fixed verify groups
33
+ `templates/core/bin/lib/verify-steps.mjs` defines —
34
+ `format`/`lint`/`typecheck`/`build`/`test`. A gate registered this way runs
28
35
  under `pnpm verify`, every `lefthook.yml` `pre-push` lane, and every
29
- `.github/workflows/ci.yml` job automatically, because all three already
30
- enumerate groups rather than individual steps.
36
+ `.github/workflows/ci.yml` job automatically. That works because all three
37
+ already enumerate groups rather than individual steps.
31
38
 
32
39
  `pack.json` fields:
33
40
 
34
41
  - `schemaVersion` — currently `1`.
35
- - `modes` — `["fresh"]` and/or `["fresh", "adopt"]`. Only artifacts with no
36
- dependency on the baseline's exact file layout (an agent, most hooks) are
37
- safely adopt-capable; a gate that assumes a specific source layout should
38
- say so honestly in `adoptNotes` instead of claiming `adopt`.
42
+ - `modes` — `["fresh"]` and/or `["fresh", "adopt"]`. "Adopt-capable" means
43
+ an artifact has no dependency on the baseline's exact file layout (an
44
+ agent, most hooks), so it's safe to install into an already-existing
45
+ project's own layout. A gate that assumes a specific source layout isn't
46
+ adopt-capable -- it should say so honestly in `adoptNotes` instead of
47
+ claiming `adopt`.
39
48
  - `budget` — the pack's cap deltas (`agents`/`skills`/`hooks`/`workflows`/
40
49
  `scripts`), checked against `templates/core`'s own counts by a structural
41
50
  test, never against `templates/core` + every other pack.
@@ -56,6 +65,15 @@ enumerate groups rather than individual steps.
56
65
  - `wiring.verifySteps` — entries appended to `bin/lib/verify-steps.packs.json`.
57
66
  - `adoptNotes` — free text surfaced verbatim in `/customize`'s Step 0
58
67
  confirmation round when the pack applies to an adopted project.
68
+ - `setupSteps` — the exact commands a user must run in the new project after
69
+ the pack is installed and before the first `pnpm verify`, or verify fails
70
+ (for example, `publishing` needs `@changesets/cli` added, since a pack can
71
+ never edit `dependencies`). A non-empty array of single-line, non-empty
72
+ strings; `loadPack` rejects anything else. Fresh mode prints every installed
73
+ pack's steps in one block after its `ready` line. Adopt mode neither prints
74
+ them nor adds them to the inventory (the staged `pack.json` still carries the
75
+ field verbatim): a pack that is adopt-capable and needs setup says so in
76
+ `adoptNotes`. Optional.
59
77
 
60
78
  ## Install path
61
79
 
@@ -63,19 +81,21 @@ enumerate groups rather than individual steps.
63
81
  repeatable) — it wrote the baseline moments ago, so there's no uncertainty
64
82
  to defer.
65
83
  - **Adopt mode**: the CLI never installs a pack. It surveys which packs
66
- apply and stages their payload at `.groundwork/packs/<name>/`;
67
- `/customize`'s Step 0 confirms and Round 1 installs, translating
68
- `wiring.verifySteps`/`wiring.settings` against the project's _real_ gate
69
- runner and hook config — read for real by that point, not guessed at
70
- offline.
84
+ apply and stages their payload at `.groundwork/packs/<name>/`. Later,
85
+ `/customize` confirms the install in **Step 0** (its first, up-front
86
+ confirmation round, before any file is written) and performs it in
87
+ **Round 1** (the first pass of deterministic edits that follows). That
88
+ installation translates `wiring.verifySteps`/`wiring.settings` against
89
+ the project's _real_ gate runner and hook config — read for real by that
90
+ point, not guessed at offline.
71
91
 
72
92
  ## Available packs
73
93
 
74
- | Pack | Contents |
75
- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
76
- | `harness-extras` | A type-design-analyzer agent, the compaction-handoff hook pair, a read-only Bash guard, and a per-file size ratchet gate — the four artifacts the original baseline build cut purely to hold its caps. |
77
- | `statusline` | A five-row Claude Code status line (session, model, context, quota, work) plus a per-subagent row renderer, both width-fit to the terminal. Registers top-level `statusLine`/`subagentStatusLine` settings, no hooks and no gate. Runs the same on macOS and Linux. |
78
-
79
- `github-ops` (dependabot/scan-alert triage skills) and `publishing` (a
80
- release workflow + npm-publish gates) are documented follow-ups, not yet
81
- built — see root `CLAUDE.md`'s Known gaps.
94
+ | Pack | Contents |
95
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
96
+ | `harness-extras` | Claude Code session ergonomics: the compaction-handoff hook pair, a read-only Bash guard, and a five-row status line (session, model, context, quota, work) plus a per-subagent row renderer. The only pack that sets top-level settings keys (`statusLine`, `subagentStatusLine`). |
97
+ | `quality` | Two language-level review aids: a per-file size ratchet gate (`check-file-budget.mjs`, a `build`-group verify step) and a read-only `type-design-analyzer` agent. No hooks, no settings. Adopt-capable and recommended for every project kind. |
98
+ | `github` | GitHub-hosted collaboration: Anthropic's official Claude Code GitHub Action wired for `@claude` mention-mode, a second Action that posts an automated Claude review comment on every PR, and three `gh`-CLI skills — `reviewing-dependabot-prs`, `triaging-scan-alerts`, `watching-pr-checks`. No hooks, no gate. The two workflows need an auth secret this pack cannot create; see its `adoptNotes`. |
99
+ | `publishing` | A release pipeline: `release.yml` (changesets version-PR / staged, provenance-attested npm publish via trusted publishing), `check-publish-version.mjs`, `check-dts-deps.mjs`, `check-license-headers.mjs` and a `REUSE.toml` template. Fresh mode only — see "Install path" below and its `adoptNotes`. |
100
+ | `supply-chain` | Secret scanning (`gitleaks.yml` with a `.gitleaks.toml`) and an OpenSSF Scorecard run (`scorecard.yml`) for any project on GitHub, published or not. A pure file drop of two read-only workflows: no hooks, no settings, no scripts, no gate. Adopt-capable and recommended for every project kind. |
101
+ | `worktrees` | Enforces that all src/tests development happens inside an isolated git worktree, on any branch, for any caller: a `working-in-worktrees` skill (start/status/sync/finish/fan-out), a `SessionStart` hook that installs dependencies into a freshly created worktree, a `PreToolUse` guard stricter than the baseline's own `guard-branch-isolation.mjs`/`guard-hub-src-writes.mjs`, a `repair-core-bare.mjs` hook (`SessionStart`, and `PostToolUse` after `EnterWorktree`/`ExitWorktree`/`Agent`) that resets the `core.bare = true` Claude Code's worktree tools are reported to leave in a normal repo's shared config, and a `.worktreeinclude` copying `.env`/`.env.local`/`.env.*.local` into every worktree Claude Code creates. Changes the day-to-day workflow, not just a nicety — see its `adoptNotes`. |
@@ -0,0 +1,133 @@
1
+ ---
2
+ name: reviewing-dependabot-prs
3
+ description: >-
4
+ Reviews every open Dependabot pull request, classifies each by semver bump
5
+ level and CI check status, and proposes merge/hold/close per PR -- then
6
+ acts only on the batch the user confirms, never a PR the user didn't
7
+ approve. Use for /reviewing-dependabot-prs, "review the dependabot PRs",
8
+ "triage dependency updates", or when several Dependabot PRs have
9
+ accumulated. GitHub stance: gh CLI.
10
+ ---
11
+
12
+ Triage every open Dependabot pull request in this repository: classify each
13
+ by how risky its bump is and whether its checks are green, propose an
14
+ action per PR, then act only on the batch the user actually confirms. This
15
+ skill never merges or closes a PR the user hasn't approved, and never
16
+ guesses at a version bump's safety from the checks alone -- a major bump is
17
+ always held for a human look, checks or no checks.
18
+
19
+ ## Steps
20
+
21
+ ### 1 — List every open Dependabot PR
22
+
23
+ ```bash
24
+ gh pr list --search "author:app/dependabot" --state open --limit 100 --json \
25
+ number,title,headRefName,isDraft,mergeable,statusCheckRollup
26
+ ```
27
+
28
+ `--limit 100` avoids `gh pr list`'s 30-result default silently truncating a
29
+ large backlog. If this returns nothing, report that there is nothing to
30
+ triage and stop.
31
+
32
+ ### 2 — Classify each PR's bump level
33
+
34
+ Dependabot's own titles follow `Bump <package> from <old> to <new>` (or
35
+ `Bump <package> in <dir> from <old> to <new>` for a monorepo/directory-scoped
36
+ config) -- but a project with a `commit-message.prefix` in its
37
+ `dependabot.yml` gets a prefixed, often-lowercased title instead, e.g.
38
+ `chore(deps): bump <package> from <old> to <new>`. Match case-insensitively
39
+ and allow an optional prefix before `bump`, then parse `<old>`/`<new>` and
40
+ compare them as semver:
41
+
42
+ - **major**: the leftmost _non-zero_ version segment differs (not simply
43
+ the first segment -- under semver a `0.x` package treats its second
44
+ segment as breaking, so `0.3.0 -> 0.4.0` is major, not minor). A major
45
+ bump is a breaking-change risk by definition, regardless of check status.
46
+ - **minor**/**patch**: lower risk, but still gated on checks (next step).
47
+ - **unparseable** (a non-semver ecosystem, a grouped-update PR covering
48
+ several packages, or a title that doesn't match the pattern even with the
49
+ prefix/case allowance above): mark it **unknown** and never guess a risk
50
+ level for it -- always propose _hold_ for a human look, and say why
51
+ parsing failed.
52
+
53
+ ### 3 — Classify each PR's check status and mergeability
54
+
55
+ `statusCheckRollup` mixes two entry shapes: a GitHub Actions **check run**
56
+ (carries `conclusion`) and a third-party **commit status** (carries `state`
57
+ instead -- no `conclusion` field at all). Read whichever field the entry
58
+ actually has, and reduce the whole set to one of:
59
+
60
+ - **green**: every entry's `conclusion` is `SUCCESS`, `NEUTRAL`, or
61
+ `SKIPPED` (not a failure), or its `state` is `SUCCESS`.
62
+ - **red**: at least one entry's `conclusion` is `FAILURE`, `CANCELLED`,
63
+ `TIMED_OUT`, `ACTION_REQUIRED`, `STARTUP_FAILURE`, or `STALE`, or its
64
+ `state` is `FAILURE`/`ERROR`.
65
+ - **pending**: at least one entry is still queued/in-progress (`conclusion`
66
+ absent, or `state: PENDING`) and none are red.
67
+ - **no checks configured**: `statusCheckRollup` is empty -- this is _not_
68
+ the same as green; propose **hold** and say the repository has no CI
69
+ configured for this PR, rather than treating silence as success.
70
+
71
+ Also read `mergeable`: a PR reported as `CONFLICTING` is never proposed for
72
+ merge regardless of bump level or check status. A draft PR (`isDraft:
73
+ true`) is never proposed for merge either.
74
+
75
+ ### 4 — Propose an action per PR
76
+
77
+ | Bump level | Checks | Mergeable | Draft | Proposal |
78
+ | ------------------- | --------- | ---------------- | ----- | ----------------------------------------------------- |
79
+ | patch/minor | green | yes | no | **merge** |
80
+ | patch/minor | red | any | no | **hold** -- name the failing check |
81
+ | patch/minor | pending | any | no | **hold** -- checks still running, re-check later |
82
+ | patch/minor | no checks | any | no | **hold** -- no CI configured, needs a human look |
83
+ | any | any | no (conflicting) | any | **hold** -- merge conflict, needs a rebase/human look |
84
+ | major | any | any | no | **hold** -- breaking-change risk, needs a human read |
85
+ | unknown/unparseable | any | any | any | **hold** -- couldn't classify the bump safely |
86
+ | any | any | any | yes | **skip** -- draft PR |
87
+
88
+ For a **held** PR whose changelog or release notes look clearly abandoned,
89
+ irrelevant, or superseded by a newer PR for the same package, note **close**
90
+ as an alternative to raise with the user in the next step -- this skill
91
+ never closes a PR on its own initiative, only on explicit confirmation.
92
+
93
+ ### 5 — Present the report and confirm the batch
94
+
95
+ Show one table: PR number, title, bump level, check status, mergeable,
96
+ proposed action. Then ask the user which of the **merge**-proposed PRs to
97
+ actually merge, and separately whether any **held** PR should instead be
98
+ **closed** -- offer "all of them", a subset by number, or none for each.
99
+ Never treat silence or a general "looks good" as consent to act; get an
100
+ explicit list or an explicit "yes, all of them" for merges, and a separate
101
+ explicit confirmation for any close.
102
+
103
+ ### 6 — Act only on the confirmed batch
104
+
105
+ For each confirmed merge:
106
+
107
+ ```bash
108
+ gh pr merge <number> --squash --auto
109
+ ```
110
+
111
+ Prefer `--squash` (the common convention for a Dependabot PR), but if `gh`
112
+ rejects it (squash merges disabled by the repository, or "Allow auto-merge"
113
+ itself is off -- GitHub's own default), fall back to whichever merge method
114
+ the repository actually allows (`--merge`/`--rebase`, or drop `--auto` and
115
+ report that the PR is ready but must be merged by hand) rather than treating
116
+ the rejection as this skill's own failure. `--auto` arms auto-merge rather
117
+ than forcing an immediate merge -- if the repository's branch protection
118
+ requires checks or reviews, the merge still waits for those; this skill does
119
+ not bypass a repository's own merge rules. If `gh pr merge` reports the PR
120
+ isn't mergeable (a conflict, a newly-failed check since step 1), report that
121
+ PR's failure and continue with the rest of the batch rather than aborting it.
122
+
123
+ For each confirmed close:
124
+
125
+ ```bash
126
+ gh pr close <number> --comment "<one-line reason from step 4>"
127
+ ```
128
+
129
+ ### 7 — Report outcomes
130
+
131
+ Summarize what was merged, what's queued behind `--auto`, what was closed,
132
+ and what was held or skipped, with a one-line reason for every held/skipped/
133
+ closed PR.
@@ -0,0 +1,88 @@
1
+ ---
2
+ name: triaging-scan-alerts
3
+ description: >-
4
+ Fetches this repository's open code-scanning alerts via gh api, groups
5
+ them by tool and severity, and maps each to its file:line -- the output
6
+ is a triage report and options only, it never edits code. Use for
7
+ /triaging-scan-alerts, "review the scan alerts", "what does CodeQL flag",
8
+ "triage the security findings", or after a code-scanning workflow run.
9
+ GitHub stance: gh CLI.
10
+ ---
11
+
12
+ Fetch every open code-scanning alert for this repository, group it by
13
+ which tool raised it and how severe it is, and map each to the exact
14
+ file and line it points at. This skill produces a report and a set of
15
+ options per alert -- it never edits code, dismisses an alert, or opens a
16
+ PR on its own.
17
+
18
+ ## Steps
19
+
20
+ ### 1 — Fetch open alerts
21
+
22
+ ```bash
23
+ gh api 'repos/{owner}/{repo}/code-scanning/alerts?state=open' \
24
+ --paginate \
25
+ -q '.[] | {number, tool: .tool.name, severity: .rule.security_severity_level // .rule.severity, rule: .rule.id, path: .most_recent_instance.location.path, line: .most_recent_instance.location.start_line, description: .rule.description}'
26
+ ```
27
+
28
+ (`state=open` is in the query string, not a `-f` field -- `gh api` switches
29
+ to `POST` the moment any `-f`/`-F` field is passed without an explicit
30
+ `--method GET`, which would break this list call. The whole path is single-
31
+ quoted because `?` is a glob character in zsh -- macOS's default shell --
32
+ and an unquoted one there fails with "no matches found" before `gh` runs.)
33
+
34
+ Use the current repository (`gh` infers `{owner}/{repo}` from the working
35
+ directory's remote when the placeholders are left as-is). If the endpoint
36
+ returns a 404 or a permissions error, code scanning may not be enabled on
37
+ this repository -- report that plainly rather than treating it as "no
38
+ alerts".
39
+
40
+ ### 2 — Group by tool and severity
41
+
42
+ Group the results by `tool` (CodeQL, a third-party SARIF uploader, etc.)
43
+ first, then by `severity` within each tool (`critical`/`high`/`medium`/
44
+ `low`, or the tool's own scale if it doesn't use those exact words --
45
+ report the tool's own label rather than forcing it into one of the four).
46
+
47
+ ### 3 — Map each alert to file:line
48
+
49
+ Every alert in the fetched output already carries `path`/`line` from its
50
+ most recent instance -- present these verbatim (`path:line`) so the user
51
+ can jump straight to the code. If `path`/`line` is absent (some
52
+ alert-generating tools don't localize to a line), say so rather than
53
+ inventing a location.
54
+
55
+ ### 4 — Present the report
56
+
57
+ One table per tool, ordered severity-first: alert number, rule id, one-line
58
+ description, `path:line`, severity. Note the total open-alert count at the
59
+ top.
60
+
61
+ ### 5 — Offer options per alert -- never act automatically
62
+
63
+ For each alert, describe (not perform) the realistic options:
64
+
65
+ - **fix now**: a one-line description of what the fix would look like, if
66
+ obvious from the rule/description -- this skill still does not make the
67
+ edit itself; the option is to hand it to a code-writing task.
68
+ - **dismiss as false positive** / **won't fix** / **used in tests**: the
69
+ three reasons GitHub's own dismissal UI accepts, named but not run:
70
+ ```bash
71
+ gh api -X PATCH repos/{owner}/{repo}/code-scanning/alerts/{number} \
72
+ -f state=dismissed -f "dismissed_reason=false positive"
73
+ ```
74
+ (swap the quoted value for `won't fix` or `used in tests` -- each contains
75
+ a space or apostrophe, so it must stay quoted as one shell argument).
76
+ - **needs a human decision**: for anything ambiguous (a finding in
77
+ generated code, a suppressed pattern that might be intentional).
78
+
79
+ Ask the user which option applies before running any dismissal command --
80
+ this skill's own default is to report, not to close anything out.
81
+
82
+ ### 6 — Note the adjacent alert surfaces this skill doesn't cover
83
+
84
+ Dependabot alerts (`gh api repos/{owner}/{repo}/dependabot/alerts`) and
85
+ secret-scanning alerts (`gh api repos/{owner}/{repo}/secret-scanning/alerts`)
86
+ are separate GitHub endpoints from code-scanning -- if the user asks about
87
+ either, say so and fetch that endpoint too rather than assuming this
88
+ skill's code-scanning report already covers it.
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: watching-pr-checks
3
+ description: >-
4
+ Checks a pull request's CI status via gh pr checks: reports ready-to-merge
5
+ and asks before merging on green, or reads the real failing job log and
6
+ hands off to /triaging-ci on red -- never guesses at a failure from the
7
+ check name alone. Use for /watching-pr-checks, "check this PR's status",
8
+ "is this PR ready to merge", "did CI pass on my PR". GitHub stance: gh
9
+ CLI.
10
+ ---
11
+
12
+ Check one pull request's CI status and act on what the checks actually
13
+ say, rather than assuming green or guessing at a failure. This is a
14
+ single check, not a polling loop -- if checks are still running, report
15
+ that plainly and let the user decide whether to ask again later or wait.
16
+
17
+ ## Steps
18
+
19
+ ### 1 — Resolve the PR
20
+
21
+ If the user gave an explicit PR number or URL, use it. Otherwise, resolve
22
+ the PR for the current branch:
23
+
24
+ ```bash
25
+ gh pr view --json number,headRefName,state
26
+ ```
27
+
28
+ If there is no PR for the current branch, or its `state` isn't `OPEN` (a
29
+ merged or closed PR still resolves by branch name), say so and stop --
30
+ there is nothing to watch.
31
+
32
+ ### 2 — Check status
33
+
34
+ ```bash
35
+ gh pr checks <number> --json name,bucket,link,workflow
36
+ ```
37
+
38
+ `bucket` (not `conclusion` -- `gh pr checks --json` has no `conclusion`
39
+ field) is the ready-made summary each check reduces to: `pass`, `fail`,
40
+ `pending`, `skipping`, or `cancel`. Reduce the whole set to one of:
41
+
42
+ - **all green**: every check's `bucket` is `pass` or `skipping`.
43
+ - **still running**: at least one `pending` and none `fail`/`cancel`.
44
+ - **failed**: at least one `fail` or `cancel`.
45
+ - **no checks configured**: the list is empty -- report this plainly rather
46
+ than treating it as either green or failed; there is nothing to watch
47
+ until the repository has CI wired up for this PR.
48
+
49
+ ### 3a — All green
50
+
51
+ Report the PR is ready to merge, name every check that passed, and ask the
52
+ user before merging -- never merge without that confirmation, even when
53
+ every check is green:
54
+
55
+ ```bash
56
+ gh pr merge <number> --squash --auto
57
+ ```
58
+
59
+ If `gh` rejects `--squash --auto` (squash merges disabled, or "Allow
60
+ auto-merge" itself is off -- GitHub's own default), fall back to whichever
61
+ merge method the repository actually allows, or drop `--auto` and report
62
+ that the PR is ready but must be merged by hand -- don't report the
63
+ rejection as this skill's own failure. (`--auto` respects any
64
+ branch-protection requirement still pending -- see
65
+ `reviewing-dependabot-prs`'s step 6 for the same reasoning if that skill is
66
+ also installed.)
67
+
68
+ ### 3b — Still running
69
+
70
+ Report which checks are still pending and which have already passed. Do
71
+ not guess at the eventual outcome. Suggest the user re-invoke this skill
72
+ in a few minutes, or -- if the calling session supports scheduling a
73
+ recurring check -- offer to check again automatically rather than blocking
74
+ on a manual re-ask.
75
+
76
+ ### 3c — Failed
77
+
78
+ Do not report the failure from the check's name alone -- pull the actual
79
+ job log before describing what went wrong. The failing check's `workflow`
80
+ field distinguishes a GitHub Actions run (has a log `gh run view` can read)
81
+ from a third-party check (a status-only integration with no run to fetch):
82
+
83
+ ```bash
84
+ gh run view <run-id> --log-failed
85
+ ```
86
+
87
+ (`<run-id>` comes from the failing check's `link`, a
88
+ `.../actions/runs/<run-id>/job/...` URL -- a check with no such `link`, or
89
+ whose `workflow` is empty, is from an external app; report its `link` and
90
+ that no log is available to read rather than guessing at why it failed.)
91
+ Once the real failure is in hand, hand off to `/triaging-ci` (if the
92
+ project has it installed) to map the failure to its root cause and present
93
+ fix options -- this skill's own job ends at "here's what actually failed
94
+ and why," not at proposing or applying a fix.