@webpieces/rules-config 0.4.516 → 0.4.518

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/rules-config",
3
- "version": "0.4.516",
3
+ "version": "0.4.518",
4
4
  "description": "Shared webpieces.config.json loader. Single source of truth for validation rule configuration consumed by @webpieces/ai-hook-rules, @webpieces/code-rules, and @webpieces/nx-webpieces-rules.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -51,10 +51,54 @@ squash commit. If a command tells you the tree is dirty, commit or delete the li
51
51
  - **B = feature HEAD**: your branch tip
52
52
  - **C = main HEAD**: `origin/main`
53
53
 
54
- Never `git merge` or `git rebase` main into your branch directly — it breaks the fork point (A) that
55
- produces clean PR diffs. Sync only via the gated 3-point squash-update — `pnpm wp-start-update` when no
56
- PR is open, `pnpm wp-start-upsert-pr` when one is (see "Which flow?" below). This is enforced by the
57
- `redirect-how-to-merge-main` guard.
54
+ ### THE FORK POINT INVARIANT (read this once, it explains every rule below)
55
+
56
+ > The fork point must be a **pure `main` commit containing none of your work**, AND your branch must
57
+ > contain **none of main's commits after it**. Only then is `diff(fork point → HEAD)` *exactly* your
58
+ > changes — no more and no less.
59
+
60
+ The invariant is symmetric, and both halves matter. Pollute the fork point with your own work and the
61
+ diff *understates* what you did; pull main's commits onto your branch and the diff *overstates* it with
62
+ work other people already landed. Either way the answer to "what did this branch change?" stops being
63
+ computable, and three separate consumers are asking exactly that question:
64
+
65
+ 1. **The 3-point merge.** `A` is the base, `B` is what *you* intended, `C` is what *main* intended, and
66
+ the whole method is reading `B−A` against `C−A` to see the two intentions side by side. If `A`
67
+ already contains your work, `B−A` no longer shows what you changed; if `B` already contains main's
68
+ commits, `C−A` is being compared against a branch that partly *is* main. The diffs stop describing
69
+ intentions and conflict resolution degrades into guessing which side a hunk came from.
70
+ 2. **`nx affected` — the build gate's scope.** The gate's `--base` is the fork point, not
71
+ `origin/main`, and the config states why verbatim:
72
+ > `--base is the FORK POINT via $(git merge-base origin/main HEAD), NOT origin/main: basing on origin/main marks projects from other people's already-merged PRs as 'affected' (your branch still has their pre-merge versions), wasting rebuilds. The fork point scopes affected to only your branch's work.`
73
+ 3. **The review diff.** `wp-review-upsert-pr` extracts this branch's diff for the reviewer subagents
74
+ from the same two endpoints. A polluted fork point hands reviewers changes nobody on this branch
75
+ made, and they will dutifully review them.
76
+
77
+ **Why an ordinary `git merge main` breaks it:** it violates *both* halves in one command. Your branch
78
+ now carries main's commits (so the diff shows work you did not do) and the base is no longer a clean
79
+ main state. That is why the `redirect-how-to-merge-main` guard blocks `git merge` and `git rebase` in
80
+ every form — the block is not stylistic, and there is nothing to work around.
81
+
82
+ **Why the gated flow squash-rewrites and force-pushes:** it restores the invariant *by construction*.
83
+ After a sync your branch is `current main + one commit that is precisely your work`, so the fork point
84
+ is a real, unmodified main commit by definition. The rewrite **is** the mechanism, not a side effect of
85
+ one — which is why the flow cannot politely skip it.
86
+
87
+ **Why squash rather than rebase:** a rebase would restore the same invariant, but it preserves N
88
+ commits and makes you resolve the same conflict once per commit. Squash gives you one resolution and
89
+ one commit. And since this repo squash-merges PRs anyway, those individual commits were never going to
90
+ survive into main's history — the `<feature>PreMerge<n>` snapshot branches exist precisely to preserve
91
+ the original pre-squash history for debugging, which is their entire purpose.
92
+
93
+ **Consequence — never sync a branch you do not own.** Because the flow rewrites history and
94
+ force-pushes, **never run `pnpm wp-start-upsert-pr` (or `pnpm wp-start-update`) against a branch that
95
+ another process, session, or agent owns.** This is not caution or etiquette, it is a correctness
96
+ requirement: that other process's fork point and its `PreMerge<n>` snapshot trail would be replaced
97
+ underneath it mid-flight, and the work it was holding becomes unrecoverable-by-construction. If you
98
+ find yourself looking at an open PR on a branch this session did not create, leave it alone.
99
+
100
+ Sync only via the gated 3-point squash-update — `pnpm wp-start-update` when no PR is open,
101
+ `pnpm wp-start-upsert-pr` when one is (see "Which flow?" below).
58
102
 
59
103
  **AI never runs `git merge` or `git rebase` — at all.** The guard blocks both outright: on any branch,
60
104
  against any target, in any form (including `--squash` and `--ff-only`), and in any compound command