@webpieces/rules-config 0.4.769 → 0.4.771

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.
@@ -35,7 +35,8 @@ row 4 skip list). Two skip lists drift, and the half that drifts is the half tha
35
35
  on its own cure.
36
36
 
37
37
  **What is gated is WHEN that polarity applies, not the polarity.** stale-main asks the cache
38
- whether local `main` is BEHIND (rows 6/7) and default-denies only then; a current `main` — which is
38
+ whether cached `commitsBehind` exceeds `branch-state-guard.maxCommitsBehind` (rows 6/7) and
39
+ default-denies only then; a current or tolerated `main` — which is
39
40
  exactly where `pnpm wp-sync-main` leaves you — is not this guard's business at all.
40
41
 
41
42
  They remain separate CLASSES because the states they detect are different — one reads the branch
@@ -47,6 +48,7 @@ name, the other the cached merged flag — and because each carries its own mess
47
48
  refresher**. It is fire-and-forget: it populates the cache for the NEXT call, never the current
48
49
  one — so the first tool call of every session sees no cache and takes row 11. That is intended,
49
50
  and it is why the on-main write block (row 5) must not depend on the cache.
51
+ That refresh also computes `commitsBehind`; guards never count on the hot path, and missing counts fail open.
50
52
 
51
53
  The file holds a **map of branch → status**, so every worktree's guards stay armed. Before that it
52
54
  held one branch's snapshot, so with N worktrees at most one tree was armed at any instant and the
@@ -76,8 +78,8 @@ guards, meant at most one of the four values could ever reach a spawn.
76
78
  | 11 | `B R E` | **the state could not be established** — branch undeterminable, no cache yet, the cache holds another branch, `origin/main` unknown, or the forge unreachable | 1 allow (fail-open) | — (nothing to fix; the refresher populates the cache for the next call) |
77
79
  | 12 | `B` | on `main`, behind `origin/main`, and the command STARTS with a refresh-main cure joined to the work by `&&` | 1 allow | — |
78
80
  | 13 | `B` | on `main`, behind `origin/main`, and the cure is joined to the work by `;` (or `||`, `&`, a newline) — the work runs even if the cure fails | 4 block | `pnpm wp-sync-main && <your command>` |
79
- | 6 | `B R` | on `main`, behind `origin/main` | 4 block | `pnpm wp-sync-main`, or `git checkout -b <new> origin/main` |
80
- | 7 | `B R` | on `main`, current | 1 allow | — |
81
+ | 6 | `B R` | on `main`, farther behind `origin/main` than `maxCommitsBehind` | 4 block | `pnpm wp-sync-main`, or `git checkout -b <new> origin/main` |
82
+ | 7 | `B R` | on `main`, current or within `maxCommitsBehind` | 1 allow | — |
81
83
  | 8 | `B R E` | on a branch whose PR is **already merged** | 4 block | `git fetch origin main && git checkout -b <new> origin/main` |
82
84
  | 9 | `B R E` | no fork point with `origin/main`, or `origin/main` moved and collided with your files | 4 block | `pnpm wp-start-update`, or `pnpm wp-start-upsert-pr` when a PR is open |
83
85
  | 10 | `B R E` | healthy feature branch | 1 allow | — |
@@ -188,12 +190,13 @@ under. So a case whose row is wrong fails the build rather than misinforming a r
188
190
  | 14 | Mid-rebase, every guard abstains | detached HEAD — there is no branch name to judge | ALLOW (fail-open), logged LOUDLY when the branch is unresolvable rather than merely detached | None — finish or abort the rebase |
189
191
  | 29 | `git fetch --prune origin main -q && git pull --ff-only origin main 2>&1 | tail -1 && sed -n '30,75p' src/app.ts` — the agent cures and reads in one call | on `main`, behind `origin/main`, cure first, `&&` between | ALLOW: `&&` short-circuits, so the `sed` never runs if the pull fails — the guard was refusing a safety property the shell already enforces. Measured fleet-wide as `cure_bundled_and`, and filed as a TOOLING defect, not an agent one | None needed |
190
192
  | 30 | `pnpm wp-sync-main >/dev/null 2>&1; git log --oneline -1; sed -n '598,612p' eslint.config.mjs` — and the agent then quotes an eslint rule out of a file 15 commits stale | on `main`, behind `origin/main`, cure first, `;` between | BLOCK: `;` discards the cure's exit code, so a conflict, a dirty tree or no network leaves the `sed` reading still-stale content — and 7 of the 9 observed cases also silenced the cure with `>/dev/null 2>&1`, so the failure was invisible too. The two-step is safer because the NEXT tool call re-computes `localMain` against `originMain`, so a failed pull re-blocks; an allowed `;` compound never gets that second look | Swap the `;` for `&&` — `pnpm wp-sync-main && <your command>` — or run the cure alone and re-issue the command in the next call |
191
- | 13 | The Read tool refuses a file on a stale `main` while you have UNCOMMITTED edits | on `main`, behind `origin/main`, dirty tree | BLOCK. This used to fail open, on the argument that the prescribed `git pull` is not a clean fast-forward when the tree is dirty. That was true of the MESSAGE, not the row: the cure cell always offered a second form, and it works dirty | `git checkout -b <new> origin/main` — uncommitted changes come with you onto the new branch. If git refuses because `origin/main` touched the same files, `git stash` first (never blocked), then retry, then `git stash pop` |
192
- | 15 | The Read tool refuses a file that exists, on a `main` 18 commits behind | on `main`, behind `origin/main`, clean tree | BLOCK: judged by live ancestry (`git merge-base --is-ancestor`), not hash equality, so a pull takes effect instantly | `pnpm wp-sync-main`, or `git checkout -b <new> origin/main` |
193
+ | 13 | The Read tool refuses a file on a stale `main` while you have UNCOMMITTED edits | on `main`, beyond `maxCommitsBehind`, dirty tree | BLOCK. This used to fail open, on the argument that the prescribed `git pull` is not a clean fast-forward when the tree is dirty. That was true of the MESSAGE, not the row: the cure cell always offered a second form, and it works dirty | `git checkout -b <new> origin/main` — uncommitted changes come with you onto the new branch. If git refuses because `origin/main` touched the same files, `git stash` first (never blocked), then retry, then `git stash pop` |
194
+ | 15 | The Read tool refuses a file that exists, on a `main` 18 commits behind | on `main`, beyond `maxCommitsBehind`, clean tree | BLOCK: judged by live ancestry (`git merge-base --is-ancestor`), not hash equality, so a pull takes effect instantly | `pnpm wp-sync-main`, or `git checkout -b <new> origin/main` |
193
195
  | 16 | Read is blocked, so the session reaches for `cat`, `grep` and `ls` instead — and describes a CI workflow set missing a whole workflow that existed upstream | the SIDE DOOR: same tree, same staleness, different tool | BLOCK: `B` is judged here beside `R`, so closing the Read tool no longer opens a shell-shaped hole. The log used to read "read-stale-guard handled", which is worse than no guard — it looks covered | `git checkout -b <new> origin/main` |
194
- | 10 | A Bash command that WRITES tracked files as a side effect — `npx expo install`, a formatter, codegen, `sed -i`, a `>` redirect | on a `main` known to be BEHIND, and the write is incidental to a command whose stated purpose is something else | BLOCK: inside this row `B` is default-DENY plus row 4's skip list, never a blocklist of readers — a command nobody thought to enumerate is caught by not being on the list, which is the only shape that could have caught this one | `git checkout -b <new> origin/main` BEFORE running anything that may write |
196
+ | 10 | A Bash command that WRITES tracked files as a side effect — `npx expo install`, a formatter, codegen, `sed -i`, a `>` redirect | on a `main` known to be beyond `maxCommitsBehind`, and the write is incidental to a command whose stated purpose is something else | BLOCK: inside this row `B` is default-DENY plus row 4's skip list, never a blocklist of readers — a command nobody thought to enumerate is caught by not being on the list, which is the only shape that could have caught this one | `git checkout -b <new> origin/main` BEFORE running anything that may write |
195
197
  | 17 | Reading files on a `main` you just pulled | on `main`, and `origin/main` is an ancestor of HEAD | ALLOW: ancestry, not hash equality, so the allow arrives the instant the pull lands rather than when the detached refresher next runs | None needed |
196
198
  | 24 | `curl`, `gh pr close` or a test run, immediately after `pnpm wp-sync-main` landed you on a perfectly current `main` | on `main`, current — no staleness anywhere | ALLOW. This used to BLOCK, from the branch alone: the tool the repo prescribes put the agent here, and the guard whose name says STALE then refused everything off a narrow allowlist for a reason that had nothing to do with staleness. WRITES here are still blocked, by row 5 — that hazard is real at any freshness | None needed |
199
+ | 31 | Reading or running Bash while local `main` is five commits behind and the configured maximum is five | on `main`, cached `commitsBehind` is at or below `maxCommitsBehind` | ALLOW: the detached refresher computed the distance; the guard hot path only reads the cache | None needed |
197
200
  | 18 | You keep working on the branch after its PR merged, and the next PR reopens code review already landed | branch whose PR is merged — `merged` is monotonic, so the cached flag is trusted with no TTL | BLOCK across all three tools | `git fetch origin main && git checkout -b <new> origin/main` |
198
201
  | 26 | You have uncommitted edits on a branch whose PR just merged | merged branch, dirty tree | BLOCK. This used to fail open too, and that valve never had an argument behind it — row 8's cure carries uncommitted work onto the fresh branch, so nothing was ever trapped. It was drift from the documented design, which `read-stale-guard`'s own class comment still described correctly | `git fetch origin main && git checkout -b <new> origin/main` — your edits come with you |
199
202
  | 19 | A shell-only session sails through on a merged branch | merged branch, Bash only — both FILE guards are file-scoped, so Bash reached neither | BLOCK: `merged-branch-bash-guard` exists because `branchAlreadyMerged` was being computed and logged on that very path, then thrown away | `git fetch origin main && git checkout -b <new> origin/main` |