@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.
- package/README.md +13 -5
- package/bin/m3l-groundwork.mjs +36 -2
- package/dist/assets.d.ts +10 -0
- package/dist/assets.js +14 -0
- package/dist/baseline-stage.d.ts +173 -0
- package/dist/baseline-stage.js +215 -0
- package/dist/caps.d.ts +4 -1
- package/dist/caps.js +17 -3
- package/dist/conflicts.d.ts +23 -2
- package/dist/conflicts.js +89 -11
- package/dist/customize-paths.d.ts +92 -0
- package/dist/customize-paths.js +115 -0
- package/dist/emit.d.ts +50 -1
- package/dist/emit.js +121 -13
- package/dist/fatal.d.ts +70 -0
- package/dist/fatal.js +132 -0
- package/dist/format-error.d.ts +113 -0
- package/dist/format-error.js +553 -0
- package/dist/fs-guard.d.ts +142 -0
- package/dist/fs-guard.js +222 -0
- package/dist/git.js +10 -1
- package/dist/harness/conformance.js +2 -0
- package/dist/harness/frontmatter.js +2 -13
- package/dist/harness/grade.js +37 -8
- package/dist/harness/rules.d.ts +20 -3
- package/dist/harness/rules.js +108 -6
- package/dist/harness/types.d.ts +13 -0
- package/dist/harness/types.js +3 -0
- package/dist/inventory.d.ts +77 -3
- package/dist/inventory.js +103 -12
- package/dist/jsonc.d.ts +49 -2
- package/dist/jsonc.js +140 -7
- package/dist/main.d.ts +62 -3
- package/dist/main.js +574 -67
- package/dist/merge-json.d.ts +47 -4
- package/dist/merge-json.js +120 -8
- package/dist/mode.js +12 -2
- package/dist/pack-stage.d.ts +210 -0
- package/dist/pack-stage.js +287 -0
- package/dist/packs.d.ts +21 -13
- package/dist/packs.js +241 -28
- package/dist/palette.d.ts +23 -0
- package/dist/palette.js +22 -0
- package/dist/plugin.d.ts +122 -6
- package/dist/plugin.js +687 -47
- package/dist/report.d.ts +21 -2
- package/dist/report.js +93 -5
- package/dist/staging.d.ts +176 -0
- package/dist/staging.js +375 -0
- package/dist/survey/fs-walk.d.ts +34 -2
- package/dist/survey/fs-walk.js +70 -5
- package/dist/survey/internal/blocked-path.d.ts +27 -0
- package/dist/survey/internal/blocked-path.js +129 -0
- package/dist/survey/internal/package-json.d.ts +13 -0
- package/dist/survey/internal/package-json.js +37 -0
- package/dist/survey/internal/read-guard.d.ts +178 -0
- package/dist/survey/internal/read-guard.js +276 -0
- package/dist/survey/survey-docs.d.ts +17 -2
- package/dist/survey/survey-docs.js +61 -21
- package/dist/survey/survey-harness.d.ts +20 -2
- package/dist/survey/survey-harness.js +87 -46
- package/dist/survey/survey-shape.d.ts +17 -2
- package/dist/survey/survey-shape.js +60 -46
- package/dist/survey/survey-toolchain.d.ts +16 -1
- package/dist/survey/survey-toolchain.js +69 -66
- package/dist/survey/survey.js +6 -4
- package/dist/survey/types.d.ts +79 -0
- package/dist/survey/types.js +2 -6
- package/dist/term.d.ts +80 -0
- package/dist/term.js +145 -0
- package/dist/tokens.js +2 -0
- package/dist/toolchain/conformance.js +2 -0
- package/dist/toolchain/grade.js +26 -8
- package/dist/toolchain/rules.d.ts +13 -4
- package/dist/toolchain/rules.js +16 -0
- package/dist/toolchain/tsconfig-chain.d.ts +2 -0
- package/dist/toolchain/tsconfig-chain.js +32 -8
- package/dist/toolchain/types.d.ts +16 -4
- package/dist/toolchain/types.js +3 -0
- package/package.json +4 -3
- package/plugin/skills/customize/SKILL.md +292 -18
- package/plugin/src/domain-map.ts +39 -14
- package/plugin/src/index.ts +5 -1
- package/plugin/src/kind-facet-map.ts +25 -8
- package/plugin/src/pack-map.ts +147 -25
- package/plugin/src/plugin-map.ts +236 -0
- package/templates/core/.claude/agents/Explore.md +0 -1
- package/templates/core/.claude/agents/code-implementer.md +4 -4
- package/templates/core/.claude/agents/code-reviewer.md +4 -4
- package/templates/core/.claude/agents/silent-failure-hunter.md +2 -2
- package/templates/core/.claude/agents/test-author.md +7 -5
- package/templates/core/.claude/hooks/guard-branch-isolation.mjs +56 -10
- package/templates/core/.claude/hooks/guard-double-background.mjs +13 -8
- package/templates/core/.claude/hooks/guard-git-push-signed.mjs +12 -9
- package/templates/core/.claude/hooks/guard-hub-src-writes.mjs +1890 -38
- package/templates/core/.claude/hooks/guard-js-extension.mjs +2 -1
- package/templates/core/.claude/hooks/guard-no-commonjs.mjs +7 -5
- package/templates/core/.claude/hooks/guard-secret-writes.mjs +7 -5
- package/templates/core/.claude/hooks/inject-decision-gate.mjs +12 -9
- package/templates/core/.claude/hooks/post-edit-verify.mjs +276 -98
- package/templates/core/.claude/rules/agent-dispatch.md +7 -0
- package/templates/core/.claude/rules/tests.md +2 -2
- package/templates/core/.claude/settings.json +5 -0
- package/templates/core/.claude/skills/finishing-work/SKILL.md +58 -10
- package/templates/core/.claude/skills/harness-guidance/SKILL.md +16 -7
- package/templates/core/.claude/skills/starting-work/SKILL.md +5 -0
- package/templates/core/.claude/skills/triaging-ci/SKILL.md +9 -8
- package/templates/core/.claude/skills/typescript-guidance/SKILL.md +137 -20
- package/templates/core/.claude/skills/typescript-guidance/references/area-catalog.md +135 -0
- package/templates/core/.claude/skills/typescript-guidance/references/tooling-sources.md +113 -0
- package/templates/core/.claude/skills/writing-commits/SKILL.md +2 -2
- package/templates/core/.github/dependabot.yml +18 -0
- package/templates/core/.github/workflows/ci.yml +15 -15
- package/templates/core/.github/workflows/dependency-review.yml +2 -2
- package/templates/core/.github/workflows/security-audit.yml +10 -4
- package/templates/core/.prettierignore +4 -0
- package/templates/core/CLAUDE.md +53 -3
- package/templates/core/README.md +30 -10
- package/templates/core/_gitignore +17 -0
- package/templates/core/bin/check-exports.mjs +11 -5
- package/templates/core/bin/lib/agent-roster.mjs +1 -1
- package/templates/core/bin/lib/frontmatter.mjs +4 -2
- package/templates/core/bin/lib/harness-rules.mjs +169 -20
- package/templates/core/bin/lib/protected-paths.mjs +93 -5
- package/templates/core/bin/lib/toolchain-rules.mjs +187 -26
- package/templates/core/bin/lib/verify-steps.mjs +29 -11
- package/templates/core/bin/verify.mjs +12 -0
- package/templates/core/eslint.config.js +5 -0
- package/templates/core/package.json +7 -7
- package/templates/core/vitest.config.ts +8 -1
- package/templates/packs/README.md +44 -24
- package/templates/packs/github/files/.claude/skills/reviewing-dependabot-prs/SKILL.md +133 -0
- package/templates/packs/github/files/.claude/skills/triaging-scan-alerts/SKILL.md +88 -0
- package/templates/packs/github/files/.claude/skills/watching-pr-checks/SKILL.md +94 -0
- package/templates/packs/github/files/.github/workflows/claude-pr-review.yml +267 -0
- package/templates/packs/github/files/.github/workflows/claude.yml +106 -0
- package/templates/packs/github/pack.json +19 -0
- package/templates/packs/harness-extras/files/.claude/hooks/guard-readonly-bash.mjs +1122 -65
- package/templates/packs/harness-extras/files/.claude/hooks/reinject-compact-handoff.mjs +147 -13
- package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline.mjs +6 -2
- package/templates/packs/harness-extras/files/.claude/hooks/write-compact-handoff.mjs +227 -44
- package/templates/packs/harness-extras/pack.json +18 -13
- package/templates/packs/publishing/files/.changeset/README.md +25 -0
- package/templates/packs/publishing/files/.changeset/config.json +7 -0
- package/templates/packs/publishing/files/.github/release-tools/package.json +9 -0
- package/templates/packs/publishing/files/.github/workflows/release.yml +295 -0
- package/templates/packs/publishing/files/REUSE.toml +28 -0
- package/templates/packs/publishing/files/bin/check-dts-deps.mjs +234 -0
- package/templates/packs/publishing/files/bin/check-license-headers.mjs +217 -0
- package/templates/packs/publishing/files/bin/check-publish-version.mjs +149 -0
- package/templates/packs/publishing/files/bin/lib/npm-publish-args.mjs +86 -0
- package/templates/packs/publishing/files/bin/pnpm-publish-shim.mjs +86 -0
- package/templates/packs/publishing/pack.json +41 -0
- package/templates/packs/{harness-extras → quality}/files/bin/check-file-budget.mjs +6 -4
- package/templates/packs/quality/pack.json +29 -0
- package/templates/packs/supply-chain/files/.github/workflows/gitleaks.yml +52 -0
- package/templates/packs/supply-chain/files/.github/workflows/scorecard.yml +48 -0
- package/templates/packs/supply-chain/files/.gitleaks.toml +2 -0
- package/templates/packs/supply-chain/pack.json +19 -0
- package/templates/packs/worktrees/files/.claude/hooks/ensure-worktree-deps.mjs +283 -0
- package/templates/packs/worktrees/files/.claude/hooks/guard-worktree-only.mjs +245 -0
- package/templates/packs/worktrees/files/.claude/hooks/repair-core-bare.mjs +335 -0
- package/templates/packs/worktrees/files/.claude/skills/working-in-worktrees/SKILL.md +139 -0
- package/templates/packs/worktrees/files/.worktreeinclude +11 -0
- package/templates/packs/worktrees/pack.json +64 -0
- package/templates/packs/statusline/pack.json +0 -31
- /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/statusline-layout.mjs +0 -0
- /package/templates/packs/{statusline → harness-extras}/files/.claude/hooks/subagent-statusline.mjs +0 -0
- /package/templates/packs/{harness-extras → quality}/files/.claude/agents/type-design-analyzer.md +0 -0
- /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
|
-
|
|
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
|
|
26
|
-
fixed verify groups
|
|
27
|
-
`
|
|
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
|
|
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"]`.
|
|
36
|
-
dependency on the baseline's exact file layout (an
|
|
37
|
-
|
|
38
|
-
|
|
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`
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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` |
|
|
77
|
-
| `
|
|
78
|
-
|
|
79
|
-
`
|
|
80
|
-
|
|
81
|
-
|
|
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.
|