@webpieces/rules-config 0.4.429 → 0.4.430

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.429",
3
+ "version": "0.4.430",
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",
@@ -26,6 +26,13 @@ export declare class SyncFlowGuidance {
26
26
  * unrecognized comes back unchanged rather than inventing a name.
27
27
  */
28
28
  pairedStart(finishCommand: string): string;
29
+ /**
30
+ * "How do I get main itself current?" — a DIFFERENT question from syncing a feature branch, and
31
+ * the one that had no answer in the merge block (which sent readers to reset --hard for lack of
32
+ * one). Single line, and deliberately free of backticks / `$` / double quotes so it can be
33
+ * interpolated straight into the shim's double-quoted shell REASON string.
34
+ */
35
+ updateMainAdvice(): string;
29
36
  /**
30
37
  * The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This
31
38
  * exists because `git merge --ff-only origin/main` gets typed as if it were a query — it is not,
@@ -84,6 +84,21 @@ class SyncFlowGuidance {
84
84
  return 'wp-start-upsert-pr';
85
85
  return finishCommand;
86
86
  }
87
+ /**
88
+ * "How do I get main itself current?" — a DIFFERENT question from syncing a feature branch, and
89
+ * the one that had no answer in the merge block (which sent readers to reset --hard for lack of
90
+ * one). Single line, and deliberately free of backticks / `$` / double quotes so it can be
91
+ * interpolated straight into the shim's double-quoted shell REASON string.
92
+ */
93
+ updateMainAdvice() {
94
+ return 'To get main itself current: ON main, run \'git pull origin main\'. In a linked worktree '
95
+ + '(main is checked out in the primary clone, so checkout main fatals there), run '
96
+ + '\'git fetch origin main\' and branch off origin/main. Do NOT reach for git merge '
97
+ + '--ff-only / git reset --hard / git checkout -B main: merge and rebase are blocked in '
98
+ + 'EVERY form by redirect-how-to-merge-main, and the reset/-B forms silently throw away '
99
+ + 'commits. To sync a FEATURE branch from main use pnpm wp-start-update (no PR open) or '
100
+ + 'pnpm wp-start-upsert-pr (a PR is open).';
101
+ }
87
102
  /**
88
103
  * The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This
89
104
  * exists because `git merge --ff-only origin/main` gets typed as if it were a query — it is not,
@@ -1 +1 @@
1
- {"version":3,"file":"sync-flow-guidance.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/sync-flow-guidance.ts"],"names":[],"mappings":";AAAA,oFAAoF;AACpF,EAAE;AACF,qGAAqG;AACrG,qGAAqG;AACrG,qGAAqG;AACrG,qGAAqG;AACrG,wBAAwB;;;AAExB,6EAA6E;AAChE,QAAA,eAAe,GAAG,sBAAsB,CAAC;AACzC,QAAA,gBAAgB,GAAG,uBAAuB,CAAC;AAC3C,QAAA,kBAAkB,GAAG,yBAAyB,CAAC;AAC/C,QAAA,mBAAmB,GAAG,0BAA0B,CAAC;AAE9D;;;GAGG;AACH,MAAa,gBAAgB;IACzB;;;OAGG;IACH,KAAK;QACD,OAAO;YACH,4EAA4E;YAC5E,8CAA8C;YAC9C,EAAE;SACL;aACI,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;aAC7B,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;aACrB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,+BAA+B;IAC/B,cAAc;QACV,OAAO;YACH,qFAAqF;YACrF,WAAW,uBAAe,2DAA2D;YACrF,qFAAqF;YACrF,WAAW,wBAAgB,6CAA6C;SAC3E,CAAC;IACN,CAAC;IAED,iDAAiD;IACjD,MAAM;QACF,OAAO;YACH,qEAAqE;YACrE,WAAW,0BAAkB,oCAAoC;YACjE,qFAAqF;YACrF,WAAW,2BAAmB,yDAAyD;SAC1F,CAAC;IACN,CAAC;IAED,kGAAkG;IAClG,WAAW;QACP,OAAO;YACH,qFAAqF;YACrF,yCAAyC;YACzC,4CAA4C;SAC/C,CAAC;IACN,CAAC;IAED,8FAA8F;IAC9F,gBAAgB;QACZ,OAAO;YACH,6FAA6F;YAC7F,2FAA2F;YAC3F,8FAA8F;YAC9F,4FAA4F;YAC5F,4DAA4D;SAC/D,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,aAAqB;QAC7B,IAAI,aAAa,KAAK,kBAAkB;YAAE,OAAO,iBAAiB,CAAC;QACnE,IAAI,aAAa,KAAK,qBAAqB;YAAE,OAAO,oBAAoB,CAAC;QACzE,OAAO,aAAa,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,cAAc;QACV,OAAO;YACH,4FAA4F;YAC5F,6FAA6F;YAC7F,0FAA0F;YAC1F,sFAAsF;YACtF,yFAAyF;YACzF,iGAAiG;YACjG,4FAA4F;YAC5F,2FAA2F;YAC3F,2FAA2F;YAC3F,kFAAkF;SACrF,CAAC;IACN,CAAC;CACJ;AA1FD,4CA0FC","sourcesContent":["// SINGLE SOURCE OF TRUTH for \"how do I bring main into my branch\" as told to an AI.\n//\n// Why this file exists: the guards and the pr-gate bins each used to hand-write their own version of\n// this advice, and they drifted — one message told the AI to START with `wp-start-update` and FINISH\n// with `wp-finish-upsert-pr`, which is a pairing that does not exist. An AI reading that cannot tell\n// which flow it is in. Every guard/bin message now renders from HERE, so the two flows can only ever\n// be described one way.\n\n// The four gated bins, as the AI must type them. Two flows, two halves each.\nexport const WP_START_UPDATE = 'pnpm wp-start-update';\nexport const WP_FINISH_UPDATE = 'pnpm wp-finish-update';\nexport const WP_START_UPSERT_PR = 'pnpm wp-start-upsert-pr';\nexport const WP_FINISH_UPSERT_PR = 'pnpm wp-finish-upsert-pr';\n\n/**\n * Renders the canonical guidance blocks. Methods return string[] (not a joined string) so callers can\n * indent//interleave them into their own message without re-wrapping.\n */\nexport class SyncFlowGuidance {\n /**\n * Both flows, ALWAYS paired. Use this when the caller does NOT know whether a PR is open — an AI\n * shown only one flow picks it even when the other one is the correct one.\n */\n flows(): string[] {\n return [\n 'There are exactly TWO flows. Which one you use is decided by ONE question:',\n 'is there already an OPEN PR for this branch?',\n '',\n ]\n .concat(this.updateOnlyFlow())\n .concat([''])\n .concat(this.prFlow())\n .concat([''])\n .concat(this.pairingRule())\n .concat([''])\n .concat(this.whyPrForcesFlowB());\n }\n\n /** Flow A — no PR open yet. */\n updateOnlyFlow(): string[] {\n return [\n ' A. NO PR yet — update-only flow (you are mid-work and just want main\\'s changes):',\n ` 1. ${WP_START_UPDATE} ← 3-point merge from main (auto-finalizes if clean)`,\n ' 2. /wp-merge ← resolve conflicts (ONLY if step 1 reported any)',\n ` 3. ${WP_FINISH_UPDATE} ← finalize (ONLY on the conflict path)`,\n ];\n }\n\n /** Flow B — a PR is open (or is about to be). */\n prFlow(): string[] {\n return [\n ' B. A PR IS ALREADY OPEN (or you are ready to post one) — PR flow:',\n ` 1. ${WP_START_UPSERT_PR} ← same 3-point merge, then push`,\n ' 2. /wp-merge ← resolve conflicts (ONLY if step 1 reported any)',\n ` 3. ${WP_FINISH_UPSERT_PR} ← authoritative build gate, then create/update the PR`,\n ];\n }\n\n /** The half that keeps drifting: a start from one pair NEVER finishes with the other's finish. */\n pairingRule(): string[] {\n return [\n 'PAIRING IS NOT OPTIONAL — a start and a finish from different flows is not a thing:',\n ' wp-start-update → wp-finish-update',\n ' wp-start-upsert-pr → wp-finish-upsert-pr',\n ];\n }\n\n /** Why an open PR removes the choice. Safe to print on its own alongside just the PR flow. */\n whyPrForcesFlowB(): string[] {\n return [\n 'If a PR is open you MUST use the upsert-pr pair. The 3-point merge REWRITES this branch (it',\n 'squashes onto main and force-pushes a new generation), so the open PR\\'s history is blown',\n 'away and has to be re-pointed in the SAME run. The update-only pair never touches the PR, so',\n 'running it with a PR open would strand that PR on the OLD branch generation — which is why',\n 'wp-start-update refuses outright when it finds an open PR.',\n ];\n }\n\n /**\n * The start bin that PAIRS with a finish bin (bare names, no `pnpm` prefix) — so generated text can\n * name the command that actually produced it instead of guessing one of the two. Anything\n * unrecognized comes back unchanged rather than inventing a name.\n */\n pairedStart(finishCommand: string): string {\n if (finishCommand === 'wp-finish-update') return 'wp-start-update';\n if (finishCommand === 'wp-finish-upsert-pr') return 'wp-start-upsert-pr';\n return finishCommand;\n }\n\n /**\n * The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This\n * exists because `git merge --ff-only origin/main` gets typed as if it were a query — it is not,\n * it mutates the branch whenever it succeeds, which is exactly the case you were probing for.\n */\n readOnlyChecks(): string[] {\n return [\n 'Only wanted to LOOK (am I behind main? would it fast-forward?) — none of the below mutate:',\n ' git fetch origin main ← refresh the remote ref (no merge)',\n ' git merge-base --is-ancestor origin/main HEAD ← exit 0 = already contains main',\n ' git rev-list --left-right --count origin/main...HEAD ← prints \"<behind> <ahead>\"',\n ' git log --oneline HEAD..origin/main ← what main has that you do not',\n ' git diff --stat origin/main...HEAD ← what you changed since the fork point',\n ' cat .webpieces/main-sync-status.json ← the tooling\\'s own answer, incl.',\n ' the files predicted to conflict',\n '`git merge --ff-only` is NOT a look — it MUTATES on success (that is the whole point of a',\n 'fast-forward), so it is blocked like every other merge. Never use it as a probe.',\n ];\n }\n}\n"]}
1
+ {"version":3,"file":"sync-flow-guidance.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/sync-flow-guidance.ts"],"names":[],"mappings":";AAAA,oFAAoF;AACpF,EAAE;AACF,qGAAqG;AACrG,qGAAqG;AACrG,qGAAqG;AACrG,qGAAqG;AACrG,wBAAwB;;;AAExB,6EAA6E;AAChE,QAAA,eAAe,GAAG,sBAAsB,CAAC;AACzC,QAAA,gBAAgB,GAAG,uBAAuB,CAAC;AAC3C,QAAA,kBAAkB,GAAG,yBAAyB,CAAC;AAC/C,QAAA,mBAAmB,GAAG,0BAA0B,CAAC;AAE9D;;;GAGG;AACH,MAAa,gBAAgB;IACzB;;;OAGG;IACH,KAAK;QACD,OAAO;YACH,4EAA4E;YAC5E,8CAA8C;YAC9C,EAAE;SACL;aACI,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;aAC7B,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;aACrB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;aACZ,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,+BAA+B;IAC/B,cAAc;QACV,OAAO;YACH,qFAAqF;YACrF,WAAW,uBAAe,2DAA2D;YACrF,qFAAqF;YACrF,WAAW,wBAAgB,6CAA6C;SAC3E,CAAC;IACN,CAAC;IAED,iDAAiD;IACjD,MAAM;QACF,OAAO;YACH,qEAAqE;YACrE,WAAW,0BAAkB,oCAAoC;YACjE,qFAAqF;YACrF,WAAW,2BAAmB,yDAAyD;SAC1F,CAAC;IACN,CAAC;IAED,kGAAkG;IAClG,WAAW;QACP,OAAO;YACH,qFAAqF;YACrF,yCAAyC;YACzC,4CAA4C;SAC/C,CAAC;IACN,CAAC;IAED,8FAA8F;IAC9F,gBAAgB;QACZ,OAAO;YACH,6FAA6F;YAC7F,2FAA2F;YAC3F,8FAA8F;YAC9F,4FAA4F;YAC5F,4DAA4D;SAC/D,CAAC;IACN,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,aAAqB;QAC7B,IAAI,aAAa,KAAK,kBAAkB;YAAE,OAAO,iBAAiB,CAAC;QACnE,IAAI,aAAa,KAAK,qBAAqB;YAAE,OAAO,oBAAoB,CAAC;QACzE,OAAO,aAAa,CAAC;IACzB,CAAC;IAED;;;;;OAKG;IACH,gBAAgB;QACZ,OAAO,0FAA0F;cAC3F,iFAAiF;cACjF,mFAAmF;cACnF,uFAAuF;cACvF,uFAAuF;cACvF,uFAAuF;cACvF,yCAAyC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,cAAc;QACV,OAAO;YACH,4FAA4F;YAC5F,6FAA6F;YAC7F,0FAA0F;YAC1F,sFAAsF;YACtF,yFAAyF;YACzF,iGAAiG;YACjG,4FAA4F;YAC5F,2FAA2F;YAC3F,2FAA2F;YAC3F,kFAAkF;SACrF,CAAC;IACN,CAAC;CACJ;AA1GD,4CA0GC","sourcesContent":["// SINGLE SOURCE OF TRUTH for \"how do I bring main into my branch\" as told to an AI.\n//\n// Why this file exists: the guards and the pr-gate bins each used to hand-write their own version of\n// this advice, and they drifted — one message told the AI to START with `wp-start-update` and FINISH\n// with `wp-finish-upsert-pr`, which is a pairing that does not exist. An AI reading that cannot tell\n// which flow it is in. Every guard/bin message now renders from HERE, so the two flows can only ever\n// be described one way.\n\n// The four gated bins, as the AI must type them. Two flows, two halves each.\nexport const WP_START_UPDATE = 'pnpm wp-start-update';\nexport const WP_FINISH_UPDATE = 'pnpm wp-finish-update';\nexport const WP_START_UPSERT_PR = 'pnpm wp-start-upsert-pr';\nexport const WP_FINISH_UPSERT_PR = 'pnpm wp-finish-upsert-pr';\n\n/**\n * Renders the canonical guidance blocks. Methods return string[] (not a joined string) so callers can\n * indent//interleave them into their own message without re-wrapping.\n */\nexport class SyncFlowGuidance {\n /**\n * Both flows, ALWAYS paired. Use this when the caller does NOT know whether a PR is open — an AI\n * shown only one flow picks it even when the other one is the correct one.\n */\n flows(): string[] {\n return [\n 'There are exactly TWO flows. Which one you use is decided by ONE question:',\n 'is there already an OPEN PR for this branch?',\n '',\n ]\n .concat(this.updateOnlyFlow())\n .concat([''])\n .concat(this.prFlow())\n .concat([''])\n .concat(this.pairingRule())\n .concat([''])\n .concat(this.whyPrForcesFlowB());\n }\n\n /** Flow A — no PR open yet. */\n updateOnlyFlow(): string[] {\n return [\n ' A. NO PR yet — update-only flow (you are mid-work and just want main\\'s changes):',\n ` 1. ${WP_START_UPDATE} ← 3-point merge from main (auto-finalizes if clean)`,\n ' 2. /wp-merge ← resolve conflicts (ONLY if step 1 reported any)',\n ` 3. ${WP_FINISH_UPDATE} ← finalize (ONLY on the conflict path)`,\n ];\n }\n\n /** Flow B — a PR is open (or is about to be). */\n prFlow(): string[] {\n return [\n ' B. A PR IS ALREADY OPEN (or you are ready to post one) — PR flow:',\n ` 1. ${WP_START_UPSERT_PR} ← same 3-point merge, then push`,\n ' 2. /wp-merge ← resolve conflicts (ONLY if step 1 reported any)',\n ` 3. ${WP_FINISH_UPSERT_PR} ← authoritative build gate, then create/update the PR`,\n ];\n }\n\n /** The half that keeps drifting: a start from one pair NEVER finishes with the other's finish. */\n pairingRule(): string[] {\n return [\n 'PAIRING IS NOT OPTIONAL — a start and a finish from different flows is not a thing:',\n ' wp-start-update → wp-finish-update',\n ' wp-start-upsert-pr → wp-finish-upsert-pr',\n ];\n }\n\n /** Why an open PR removes the choice. Safe to print on its own alongside just the PR flow. */\n whyPrForcesFlowB(): string[] {\n return [\n 'If a PR is open you MUST use the upsert-pr pair. The 3-point merge REWRITES this branch (it',\n 'squashes onto main and force-pushes a new generation), so the open PR\\'s history is blown',\n 'away and has to be re-pointed in the SAME run. The update-only pair never touches the PR, so',\n 'running it with a PR open would strand that PR on the OLD branch generation — which is why',\n 'wp-start-update refuses outright when it finds an open PR.',\n ];\n }\n\n /**\n * The start bin that PAIRS with a finish bin (bare names, no `pnpm` prefix) — so generated text can\n * name the command that actually produced it instead of guessing one of the two. Anything\n * unrecognized comes back unchanged rather than inventing a name.\n */\n pairedStart(finishCommand: string): string {\n if (finishCommand === 'wp-finish-update') return 'wp-start-update';\n if (finishCommand === 'wp-finish-upsert-pr') return 'wp-start-upsert-pr';\n return finishCommand;\n }\n\n /**\n * \"How do I get main itself current?\" — a DIFFERENT question from syncing a feature branch, and\n * the one that had no answer in the merge block (which sent readers to reset --hard for lack of\n * one). Single line, and deliberately free of backticks / `$` / double quotes so it can be\n * interpolated straight into the shim's double-quoted shell REASON string.\n */\n updateMainAdvice(): string {\n return 'To get main itself current: ON main, run \\'git pull origin main\\'. In a linked worktree '\n + '(main is checked out in the primary clone, so checkout main fatals there), run '\n + '\\'git fetch origin main\\' and branch off origin/main. Do NOT reach for git merge '\n + '--ff-only / git reset --hard / git checkout -B main: merge and rebase are blocked in '\n + 'EVERY form by redirect-how-to-merge-main, and the reset/-B forms silently throw away '\n + 'commits. To sync a FEATURE branch from main use pnpm wp-start-update (no PR open) or '\n + 'pnpm wp-start-upsert-pr (a PR is open).';\n }\n\n /**\n * The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This\n * exists because `git merge --ff-only origin/main` gets typed as if it were a query — it is not,\n * it mutates the branch whenever it succeeds, which is exactly the case you were probing for.\n */\n readOnlyChecks(): string[] {\n return [\n 'Only wanted to LOOK (am I behind main? would it fast-forward?) — none of the below mutate:',\n ' git fetch origin main ← refresh the remote ref (no merge)',\n ' git merge-base --is-ancestor origin/main HEAD ← exit 0 = already contains main',\n ' git rev-list --left-right --count origin/main...HEAD ← prints \"<behind> <ahead>\"',\n ' git log --oneline HEAD..origin/main ← what main has that you do not',\n ' git diff --stat origin/main...HEAD ← what you changed since the fork point',\n ' cat .webpieces/main-sync-status.json ← the tooling\\'s own answer, incl.',\n ' the files predicted to conflict',\n '`git merge --ff-only` is NOT a look — it MUTATES on success (that is the whole point of a',\n 'fast-forward), so it is blocked like every other merge. Never use it as a probe.',\n ];\n }\n}\n"]}