@rtorcato/repo-tooling 3.16.1 → 3.16.3

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.
@@ -108,7 +108,7 @@ export async function setupProject(options) {
108
108
  const interactive = !options.config && !options.preset;
109
109
  const dryRun = options.dryRun === true;
110
110
  if (interactive && !dryRun) {
111
- console.log(chalk.cyan('\nšŸ› ļø Welcome to JS Tooling Setup!\n'));
111
+ console.log(chalk.cyan('\nšŸ› ļø Welcome to repo-tooling setup!\n'));
112
112
  console.log(chalk.gray(`Setting up tooling in: ${targetDir}\n`));
113
113
  }
114
114
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rtorcato/repo-tooling",
3
- "version": "3.16.1",
3
+ "version": "3.16.3",
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": [
@@ -43,14 +43,12 @@ real approvals.
43
43
 
44
44
  The same constraint makes everything an agent posts *look* hand-written by the
45
45
  owner. So **every comment any agent leaves — review, blocked, gave-up, declined —
46
- opens with a `šŸ¤– *Automated …*` italic header line** naming which agent wrote it,
47
- followed by a blank line. Non-negotiable: a detailed security review under a
48
- human's avatar misrepresents who reviewed the code.
46
+ opens with a `šŸ¤– *Automated …*` italic header line naming which agent wrote it**,
47
+ then a blank line. Name the agent and stop there: a detailed security review
48
+ under a human's avatar misrepresents who reviewed the code, but *why* it wears
49
+ that avatar is read once and then reread on every comment forever.
49
50
 
50
- Spell the reason out rather than assuming the reader knows the convention — the
51
- header names the agent *and* says why it is wearing a human's face:
52
-
53
- `šŸ¤– *Automated — <which agent> via ai-issue-loop. Posted under the owner's account by an agent; not a human message. There is no separate GitHub account for AI agents, so this appears under @<owner>'s avatar.*`
51
+ `šŸ¤– *Automated — <which agent> via ai-issue-loop.*`
54
52
 
55
53
  **Comment budget: ≤10 lines, and a clean outcome gets no comment at all.** A
56
54
  40-line comment on every PR trains the reader to skip all of them, including the
@@ -63,16 +61,16 @@ drift with a second copy to maintain.
63
61
  | Clean and ready | **None.** `ai-ok-code, ai-ok-sec` + assigned + no `ai-review` already says it. |
64
62
  | `ai-notes` | ≤10 lines; link the reviewer's `### Before merging`. |
65
63
  | `ai-changes`, CI red, `ai-blocked` | ≤10 lines, action first, then the specific cause. |
66
- | Reviewer verdict | `### Before merging` plus at most 3 short paragraphs above it. |
64
+ | Reviewer verdict | `### Before merging` plus ≤600 characters above it. |
67
65
  | Declining an issue | The one exception — a hard handoff needs its reasoning; see Pass 4. |
68
66
 
69
67
  ## Labels
70
68
 
71
69
  | Label | On | Meaning |
72
70
  |---|---|---|
73
- | `ai-ready` | issue | Eligible for an agent. The hard gate. |
74
- | `ai-wip` | issue | Claimed; a worktree exists. |
75
- | `ai-blocked` | issue | Agent gave up; needs a human. |
71
+ | `ai-ready` | issue | Eligible for an agent. The hard gate; **cleared on pickup**. |
72
+ | `ai-wip` | issue | Claimed; a worktree exists. Never rides alongside `ai-ready`. |
73
+ | `ai-blocked` | issue | Agent gave up; needs a human. Only a human re-adds `ai-ready`. |
76
74
  | `ai-review` | PR | Awaiting agent review. |
77
75
  | `ai-reviewing-code` | PR | `code-reviewer` claimed and running. Cleared with its verdict. |
78
76
  | `ai-reviewing-sec` | PR | `security-expert` claimed and running. Cleared with its verdict. |
@@ -400,13 +398,21 @@ Only then:
400
398
  git -C "$ROOT" worktree remove --force "$WT_DIR" # the path found above, not a rebuilt one
401
399
  git -C "$ROOT" branch -D "$BRANCH" 2>/dev/null
402
400
  gh issue edit <N> --remove-label ai-wip 2>/dev/null
401
+ # Still OPEN means the PR said only `Refs #N`; a `Closes #N` issue is already closed.
402
+ if [ "$(gh issue view <N> --json state -q .state)" = OPEN ]; then
403
+ gh issue edit <N> --add-assignee @me
404
+ fi
403
405
  ```
404
406
 
405
407
  A closed-unmerged PR is the exception: there is no squash to find, so skip the
406
408
  confirmation and remove — the work was abandoned deliberately.
407
409
 
408
- The issue itself closes from the PR body's `Closes #N`. This pass is what frees
409
- concurrency slots, so it must run before Pass 4.
410
+ The issue itself closes from the PR body's `Closes #N`, so both edits are normally
411
+ no-ops on a closed issue. A PR that said only `Refs #N` leaves it **open**, which is
412
+ what the state check catches. The work has landed, so it must not go back in
413
+ the queue; pickup already dropped `ai-ready`, and assigning it is what stops a
414
+ merged issue sitting unowned instead (#429 had to be moved to `holding` by hand).
415
+ This pass is what frees concurrency slots, so it must run before Pass 4.
410
416
 
411
417
  **Then reap the stalled.** Nothing can time out an agent: the Agent tool takes no
412
418
  timeout, and an agent whose session died leaves its labels behind with no process
@@ -432,13 +438,15 @@ work must never be reaped out from under itself.
432
438
  The **no PR exists** condition on the first row is what makes reaping safe. An
433
439
  agent that got as far as opening a PR has handed off to the label state machine
434
440
  and is no longer the thing being waited on; only a run that produced nothing is
435
- presumed dead. The reaped issue keeps its worktree removed, so a re-labelled
436
- `ai-ready` starts clean.
441
+ presumed dead. Reaping deliberately does **not** restore `ai-ready` — `ai-blocked`
442
+ means a human decides when the issue re-enters the queue, and the removed worktree
443
+ means their re-label starts clean. The other two `ai-blocked` exits, Pass 3's
444
+ ping-pong stop and an implementer handing back, leave it off for the same reason.
437
445
 
438
446
  **Every `ai-blocked` must say why, and land in front of a human.** So reaping always
439
447
  does three things together — label, assign, comment — and the comment opens with
440
448
 
441
- `šŸ¤– *Automated — \`ai-issue-loop\` Pass 2 (stall reaping). Posted under the owner's account; not a human message.*`
449
+ `šŸ¤– *Automated — \`ai-issue-loop\` Pass 2 (stall reaping).*`
442
450
 
443
451
  then a blank line. State which stall rule fired, how long the label sat, and whether a
444
452
  worktree was removed. A bare `ai-blocked` with no explanation is worse than no label:
@@ -448,9 +456,12 @@ puts it in the statusline and fires a notification with a sound.
448
456
  **Reaping is not always the right call — say so when it isn't.** The rule assumes a
449
457
  dead agent, but a stale `ai-wip` can also come from a run that was cancelled
450
458
  deliberately, in which case the work is fine and only the claim is stale. If you know
451
- the cause and it is benign, clear `ai-wip` **without** `ai-blocked` so Pass 4 can pick
452
- it straight back up, and say in the comment that you deviated and why. `ai-blocked`
453
- means *a human must look*; do not spend it on a claim you already understand.
459
+ the cause and it is benign, **return it to the queue** — `gh issue edit <N> --add-label
460
+ ai-ready --remove-label ai-wip`, no `ai-blocked` — so Pass 4 picks it straight back up,
461
+ and say in the comment that you re-queued it, that you deviated, and why. Re-adding
462
+ `ai-ready` is not optional: pickup cleared it, so clearing `ai-wip` alone drops the
463
+ issue out of the queue silently, which is the worse failure. `ai-blocked` means *a
464
+ human must look*; do not spend it on a claim you already understand.
454
465
 
455
466
  ### Pass 3 — review
456
467
 
@@ -493,20 +504,19 @@ Reviewer prompt template:
493
504
  > purpose. Also read the repo's `CLAUDE.md` if the diff plausibly touches a rule
494
505
  > it states.
495
506
  >
496
- > `<code-reviewer: Judge correctness, obvious bugs, and adherence to the repo's
497
- > stated conventions.>` / `<security-expert: Judge injection risk, leaked
498
- > secrets, unsafe shell/SQL construction, and dependency or supply-chain
499
- > changes.>`
507
+ > `<code-reviewer: Judge correctness, obvious bugs, and adherence to the repo's stated
508
+ > conventions.>` / `<security-expert: Judge injection risk, leaked secrets, unsafe
509
+ > shell/SQL construction, and dependency or supply-chain changes.>` That is the
510
+ > checklist to run, not an outline to write up.
500
511
  >
501
512
  > Post your verdict as a comment — **never** `--approve`, it errors on your own
502
513
  > PR:
503
514
  > `gh pr review <N> --comment --body "..."`
504
515
  >
505
- > The body **must** begin with this exact header line, then a blank line. Every
506
- > agent authenticates as the repo owner, so without it the timeline reads as if
507
- > a human wrote the review:
516
+ > The body **must** begin with this exact header line, then a blank line — you
517
+ > authenticate as the repo owner, so without it the review reads as a human's:
508
518
  >
509
- > `šŸ¤– *Automated review — \`<your agent type>\` via ai-issue-loop. Posted under the owner's account; not a human review.*`
519
+ > `šŸ¤– *Automated review — \`<your agent type>\` via ai-issue-loop.*`
510
520
  >
511
521
  > The body **must end** with this section, as its last thing:
512
522
  >
@@ -525,13 +535,14 @@ Reviewer prompt template:
525
535
  > That section is what a human reads at merge time, so put anything you would
526
536
  > want them to know there rather than leaving it in the prose above — a finding
527
537
  > buried mid-paragraph does not survive the handoff. For the same reason, **cap
528
- > the body at that section plus at most 3 short paragraphs above it**: no process
529
- > narration, no restating the diff, no listing what you checked and found fine.
530
- > The bar is a finding that
531
- > **changes what a human would do**: a semver implication, a deliberate
532
- > omission, a follow-up that must be filed. Not observations, not praise, not
533
- > restating the diff. Writing `Nothing.` is a real verdict and the common one —
534
- > say it plainly rather than padding the section to look thorough.
538
+ > the body at that section plus ≤600 characters above it**. Verify everything;
539
+ > narrate only where the PR is **wrong** or **silent**. Never list what you
540
+ > checked and found clean, and never confirm a claim the PR body already makes —
541
+ > agreement is what the pass label is for, so a review that agrees is nearly
542
+ > empty. The bar is a finding that **changes what a human would do**: a semver
543
+ > implication, a deliberate omission, a follow-up that must be filed. Writing
544
+ > `Nothing.` is a real verdict and the common one — say it plainly rather than
545
+ > padding to look thorough.
535
546
  >
536
547
  > Then apply exactly one verdict label, **clearing your claim label in the same
537
548
  > command**:
@@ -633,8 +644,8 @@ package/from/to table survives because it sits at the top; classify from that.
633
644
  > State in your comment which rule fired, name the packages that tripped it, and say
634
645
  > whether the body was truncated so the reader knows what you could and couldn't see.
635
646
  > Same `šŸ¤– *Automated review — …*` header line, same closing `### Before merging`
636
- > section, same 3-paragraph cap on the body, and same one-verdict-label rule as
637
- > above — **including clearing your
647
+ > section, same ≤600-character cap and no-negative-findings rule on the body, and same
648
+ > one-verdict-label rule as above — **including clearing your
638
649
  > `<ai-reviewing-code|ai-reviewing-sec>` claim label in the same `gh pr edit`**.
639
650
  > Pass 3 claimed you with it before spawning you, and a claim left behind wedges
640
651
  > your half of the review until Pass 2 reaps it.
@@ -669,7 +680,7 @@ gh api "repos/$OWNER_REPO/issues/<N>/timeline" \
669
680
  ```
670
681
 
671
682
  If that count is **≄ 3**, stop looping. Comment the reason on the PR — opening with
672
- `šŸ¤– *Automated — \`ai-issue-loop\` Pass 3. Posted under the owner's account; not a human message.*`
683
+ `šŸ¤– *Automated — \`ai-issue-loop\` Pass 3.*`
673
684
  and a blank line — naming what each round changed and why the reviewer kept objecting,
674
685
  then:
675
686
 
@@ -738,10 +749,9 @@ same issue gets re-triaged from scratch every time, and the reasoning that took
738
749
  real work to reach is lost.
739
750
 
740
751
  The comment opens with the standard `šŸ¤– *Automated …*` header — see the top of this
741
- file; it must state that no GitHub account exists for AI agents, so the comment
742
- wears the owner's avatar. Then, in the body — **this is the one comment exempt
743
- from the ≤10-line budget, and only this one.** Declining is a hard handoff whose
744
- whole value is the reasoning; do not reach for this shape on a PR handoff:
752
+ file. Then, in the body — **this is the one comment exempt from the ≤10-line
753
+ budget, and only this one.** Declining is a hard handoff whose whole value is the
754
+ reasoning; do not reach for this shape on a PR handoff:
745
755
 
746
756
  - **Why an agent cannot finish it**, concretely. "Not suitable" is useless. Name
747
757
  the blocker: binary assets it cannot author, a force-push past branch
@@ -769,9 +779,17 @@ Take the first `slots` issues. For each, **claim it first** so a concurrent tick
769
779
  can't double-pick:
770
780
 
771
781
  ```bash
772
- gh issue edit <N> --add-label ai-wip
782
+ gh issue edit <N> --add-label ai-wip --remove-label ai-ready
773
783
  ```
774
784
 
785
+ Dropping `ai-ready` is half the claim, not tidiness — the diagram above is a
786
+ transition, not an accumulation. An issue left carrying both re-enters the queue
787
+ the instant `ai-wip` clears for any reason other than the PR closing it, and the
788
+ next tick spawns an agent to re-implement work already sitting in an open PR
789
+ (#458, #467, #461, #452, all in one session). Every path that legitimately returns
790
+ an issue to the queue therefore re-adds `ai-ready` explicitly; Pass 2's benign-stall
791
+ path is the only one, and a human does the rest.
792
+
775
793
  **Then create the worktree yourself**, before spawning anything. `<slug>` is 3–4
776
794
  kebab-case words from the title:
777
795
 
@@ -858,7 +876,7 @@ Then spawn a background implementer agent:
858
876
  > **must** open with this exact line, then a blank line — you authenticate as the
859
877
  > owner, so without it the issue reads as if they wrote it themselves:
860
878
  >
861
- > `šŸ¤– *Automated — implementer via ai-issue-loop. Posted under the owner's account; not a human message.*`
879
+ > `šŸ¤– *Automated — implementer via ai-issue-loop.*`
862
880
  >
863
881
  > Say what you tried, the exact error, and what a human would need to decide. "Could
864
882
  > not finish" with no detail wastes the handoff — the whole point of the label is that