@rtorcato/repo-tooling 3.15.1 → 3.15.2

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.
@@ -9,8 +9,10 @@ import fs from 'fs-extra';
9
9
  */
10
10
  const PLACEHOLDER_DOMAINS = ['example.com', 'example.org', 'example.net', 'invalid', 'test'];
11
11
  /**
12
- * Suffixes of a machine-derived hostname. `.local` is mDNS (macOS default),
13
- * `.matrix` is this user's LAN — both produced real commits in the #327 set.
12
+ * Suffixes of a machine-derived hostname. `.local` is mDNS (macOS default); the
13
+ * rest are the conventional private-LAN suffixes a router hands out. `.matrix`
14
+ * is one such router default rather than a registered TLD — it is here because
15
+ * it produced real commits in the #327 set, alongside `.local`.
14
16
  */
15
17
  const HOSTNAME_SUFFIXES = ['.local', '.matrix', '.localhost', '.lan', '.home', '.internal'];
16
18
  /** Pure so the rules are testable without a git repo or a spawn. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtorcato/repo-tooling",
3
- "version": "3.15.1",
3
+ "version": "3.15.2",
4
4
  "description": "One CLI to scaffold, audit and fix your repo's whole toolchain — linting, tests, commits, releases & CI.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -230,7 +230,7 @@
230
230
  "./package.json": "./package.json"
231
231
  },
232
232
  "dependencies": {
233
- "chalk": "^5.6.2",
233
+ "chalk": "^6.0.0",
234
234
  "commander": "^15.0.0",
235
235
  "diff": "^9.0.0",
236
236
  "fs-extra": "^11.4.0",
@@ -263,14 +263,14 @@
263
263
  "conventional-changelog-conventionalcommits": "^10.2.1",
264
264
  "cz-conventional-changelog": "^3.3.0",
265
265
  "esbuild": "^0.28.0",
266
- "esbuild-node-externals": "^1.23.1",
266
+ "esbuild-node-externals": "^2.0.0",
267
267
  "eslint": "10.8.0",
268
268
  "eslint-plugin-import": "^2.32.0",
269
269
  "eslint-plugin-jest": "29.16.0",
270
270
  "husky": "^9.1.7",
271
271
  "is-ci": "^4.1.0",
272
272
  "jest": "^30.4.2",
273
- "jsdom": "^29.1.1",
273
+ "jsdom": "^30.0.1",
274
274
  "knip": "^6.29.0",
275
275
  "prettier": "^3.9.6",
276
276
  "rimraf": "6.1.3",
@@ -64,13 +64,15 @@ header names the agent *and* says why it is wearing a human's face:
64
64
  | `ai-reviewing-sec` | PR | `security-expert` claimed and running. Cleared with its verdict. |
65
65
  | `ai-ok-code` | PR | `code-reviewer` passed. |
66
66
  | `ai-ok-sec` | PR | `security-expert` passed. |
67
- | `ai-changes` | PR | A reviewer requested changes. |
67
+ | `ai-changes` | PR | A reviewer requested changes. Reviewers never apply it to a Dependabot PR. |
68
68
  | `ai-notes` | PR | Passed, but a reviewer left something to read before merging. |
69
69
  | `holding` | issue | A gate — closes on human judgement, never picked up. |
70
70
 
71
71
  **`ai-notes` is advisory and never blocks.** It rides *alongside* a pass label,
72
72
  never instead of one, and it never sends a PR back — a finding that should block
73
- is `ai-changes`. It exists because a pass label currently means both "clean" and
73
+ an issue PR is `ai-changes`. On a Dependabot PR there is nothing to send back to,
74
+ so `ai-notes` is the hold itself: it suppresses auto-merge and routes the PR to
75
+ the human. It exists because a pass label currently means both "clean" and
74
76
  "I found something real but would not hold the PR over it", and those two are
75
77
  indistinguishable in the *Assigned to you* view where merges actually happen.
76
78
  The bar is a finding that **changes what a human would do**: a semver
@@ -121,8 +123,8 @@ PR: ai-review ─> ai-reviewing-* ─┬─> ai-ok-code + ai-ok-sec ─┬─ is
121
123
  │ (± ai-notes) │ ─> YOU merge ─> worktree removed
122
124
  │ └─ dependabot ─┬─ no ai-notes ─> auto-merge ─> worktree removed
123
125
  │ └─ ai-notes ───> assigned to you
124
- └─> ai-changes ─> fix round (max 2) ─> ai-review
125
- └─ round 3 ─> ai-blocked
126
+ └─> ai-changes (issue PRs only) ─> fix round (max 2) ─> ai-review
127
+ └─ round 3 ─> ai-blocked
126
128
  ```
127
129
 
128
130
  `ai-reviewing-code` / `ai-reviewing-sec` are the *claim* step: Pass 3 applies one
@@ -168,8 +170,7 @@ gh issue list --state open --label ai-wip --json number
168
170
  **`OWNER_REPO` always comes from the working directory's remote — never from
169
171
  `$ARGUMENTS`.** The loop labels, pushes, and merges, so it operates on the **current
170
172
  repo only**, even if a prompt or an issue body names another one. Reads against other
171
- repos are fine for checking a dependency; writes are not. (`/_loop-status` is the
172
- exception — it takes an `owner/repo` argument, but it is read-only.) GitHub only —
173
+ repos are fine for checking a dependency; writes are not. GitHub only —
173
174
  bail in one line if the remote is GitLab.
174
175
 
175
176
  **`ROOT` is load-bearing — resolve it first and use it for every path in every
@@ -290,6 +291,17 @@ gh pr edit <N> --add-label ai-changes \
290
291
 
291
292
  Count it as `rev`, not `ready`. A merge conflict (`DIRTY`) takes the same route.
292
293
 
294
+ **Assign any Dependabot PR carrying `ai-changes`.** Pass 3 never spawns a fix
295
+ round for one, so it is waiting on a human from the moment the label lands — and
296
+ no other branch of this pass assigns it, which leaves it in no *Assigned to you*
297
+ view at all:
298
+
299
+ ```bash
300
+ gh pr edit <N> --add-assignee @me
301
+ ```
302
+
303
+ Count it as `rev`. Idempotent, so it also picks up ones an earlier tick stranded.
304
+
293
305
  So: every open PR **authored by `dependabot[bot]`**, labelled both `ai-ok-code`
294
306
  and `ai-ok-sec`, **not** `ai-changes`, **not** `ai-notes`, that has no
295
307
  `autoMergeRequest` yet:
@@ -577,15 +589,24 @@ package/from/to table survives because it sits at the top; classify from that.
577
589
  > the label. If you cannot tell whether a workspace publishes, treat it as
578
590
  > production.
579
591
  >
580
- > Apply `ai-changes` if **either** holds:
592
+ > Apply your **pass** label *plus* `ai-notes` if **either** holds:
581
593
  > - a package's major version differs between the `from` and `to` columns
582
594
  > - a package ships to consumers — it appears in `dependencies`,
583
595
  > `optionalDependencies`, or `peerDependencies` of a **non-private** package
584
596
  >
585
597
  > Those wait for a human — a runtime dependency of the published package, or a
586
- > major, is not something an automated verdict should wave through. Dev-only
587
- > minor/patch bumps with green CI get the pass label. **If you cannot determine a
588
- > package's type, treat it as production and block**; failing closed is correct here.
598
+ > major, is not something an automated verdict should wave through. `ai-notes` is
599
+ > the gate that holds them: it suppresses auto-merge outright and gets the PR
600
+ > assigned to the human, so nothing production-facing lands unattended. Dev-only
601
+ > minor/patch bumps with green CI get the pass label alone. **If you cannot
602
+ > determine a package's type, treat it as production and note it**; failing
603
+ > closed is correct here.
604
+ >
605
+ > **Never apply `ai-changes` to a Dependabot PR.** It dispatches an implementer
606
+ > agent, and there is no change an agent could make — rewriting a bot's lockfile
607
+ > is not its business, and the decision here is a human's either way. That is the
608
+ > same rule as the generic prompt above: `ai-changes` only when you can name a
609
+ > concrete change an agent could make.
589
610
  >
590
611
  > State in your comment which rule fired, name the packages that tripped it, and say
591
612
  > whether the body was truncated so the reader knows what you could and couldn't see.
@@ -595,9 +616,10 @@ package/from/to table survives because it sits at the top; classify from that.
595
616
  > Pass 3 claimed you with it before spawning you, and a claim left behind wedges
596
617
  > your half of the review until Pass 2 reaps it.
597
618
  >
598
- > Be sparing with `ai-notes` here specifically: it suppresses auto-merge, so a
599
- > reflexive note on every dependency bump wedges the one path that runs
600
- > unattended. A truncated body you could not fully read **is** worth a note; a
619
+ > Keep `ai-notes` load-bearing here: it suppresses auto-merge, so a *decorative*
620
+ > note on a bump you would otherwise wave through wedges the one path that runs
621
+ > unattended. A major, a package that ships to consumers, or a truncated body you
622
+ > could not fully read **is** worth a note; restating the version table on a
601
623
  > routine dev-only patch bump is not.
602
624
 
603
625
  Be honest about what this buys: an agent reading a version table catches majors,
@@ -609,10 +631,11 @@ gate. This pass is a *policy* gate: nothing major or production-facing merges
609
631
  unattended.
610
632
 
611
633
  **A Dependabot PR labelled `ai-changes` is terminal — never spawn a fix round for
612
- it.** There is no linked issue to mark `ai-blocked` and no worktree to enter, and
613
- an agent has no business rewriting a bot's lockfile. It simply waits for a human,
614
- and Pass 5 counts it as `⚠<n>held`. Everything below applies only to PRs this loop
615
- opened from an `ai-ready` issue.
634
+ it.** Reviewers no longer produce that state, but Pass 1's non-`CLEAN` check
635
+ still does, so the guard stays. There is no linked issue to mark `ai-blocked` and
636
+ no worktree to enter, and an agent has no business rewriting a bot's lockfile.
637
+ Pass 1 assigns it and counts it as `rev`; here it simply waits for a human.
638
+ Everything below applies only to PRs this loop opened from an `ai-ready` issue.
616
639
 
617
640
  **PRs labelled `ai-changes`.** Count prior `ai-changes` applications from the
618
641
  timeline: