@webpieces/rules-config 0.4.554 → 0.4.556
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.
|
|
3
|
+
"version": "0.4.556",
|
|
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",
|
package/src/default-rules.js
CHANGED
|
@@ -57,14 +57,22 @@ exports.defaultRules = {
|
|
|
57
57
|
'validate-packagejson': { mode: 'RUN_EVERY_TIME' },
|
|
58
58
|
'validate-versions-locked': { mode: 'RUN_EVERY_TIME' },
|
|
59
59
|
'validate-eslint-sync': { mode: 'RUN_EVERY_TIME' },
|
|
60
|
-
// autoReapMergedBranches ships
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
60
|
+
// autoReapMergedBranches ships TRUE, and it is also what a fresh config is seeded with.
|
|
61
|
+
//
|
|
62
|
+
// It shipped FALSE on the reasoning that an upgrade must never delete branches unattended before a
|
|
63
|
+
// human opts in. In practice that produced the opposite of safety: nobody opts in, dead branches
|
|
64
|
+
// pile up, and the pile is what makes a real branch hard to find. The reap is also NOT destructive
|
|
65
|
+
// in the way the old comment implied — BranchReaper deletes only provably-dead branches (a merged
|
|
66
|
+
// PR, a squash-merge backup of one, or no commits of their own), spares everything else for a
|
|
67
|
+
// human, and logs each deletion to .webpieces/hooks/branch-mutations.log with the pre-delete SHA
|
|
68
|
+
// and a ready-made `recover=` command. So the worst case is one paste to undo, which a human can
|
|
69
|
+
// resolve; the previous default's worst case was unbounded accumulation nobody ever cleaned.
|
|
70
|
+
//
|
|
71
|
+
// Set it false to keep reaping manual; `pnpm wp-cleanup` works either way.
|
|
64
72
|
'branch-creation-guard': {
|
|
65
73
|
mode: 'ON',
|
|
66
74
|
subBranchNaming: 'feature/<ticket>/<short-description>',
|
|
67
|
-
autoReapMergedBranches:
|
|
75
|
+
autoReapMergedBranches: true,
|
|
68
76
|
},
|
|
69
77
|
'pr-creation-or-push-guard': { mode: 'ON' },
|
|
70
78
|
'merge-in-progress-guard': { mode: 'ON' },
|
package/src/default-rules.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/default-rules.ts"],"names":[],"mappings":";;;AAAA,2DAA2D;AAC3D,4EAA4E;AAC5E,kEAAkE;AAClE,0EAA0E;AAC1E,MAAM,qBAAqB,GAAsB;IAC7C,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IACrC,WAAW,EAAE,mBAAmB;CACnC,CAAC;AAEF,2EAA2E;AAC3E,6EAA6E;AAC7E,sFAAsF;AACtF,iFAAiF;AACpE,QAAA,YAAY,GAA4C;IACjE,gBAAgB,EAAE,EAAE;IACpB,iBAAiB,EAAE,EAAE;IACrB,gBAAgB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;IAChC,kBAAkB,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;IACjC,qBAAqB,EAAE,EAAE;IACzB,yBAAyB,EAAE,EAAE;IAC7B,gBAAgB,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE;IACzC,qBAAqB,EAAE,EAAE;IACzB,yBAAyB,EAAE,EAAE;IAC7B,uBAAuB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACnD,sBAAsB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,aAAa,EAAE,EAAE,EAAE;IACrE,sBAAsB,EAAE,EAAE;IAC1B,kBAAkB,EAAE,EAAE;IACtB,mCAAmC,EAAE,EAAE;IACvC,qBAAqB,EAAE,EAAE;IACzB,sFAAsF;IACtF,6FAA6F;IAC7F,6CAA6C;IAC7C,6CAA6C,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;IAC9D,eAAe,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE;IACnC,8BAA8B,EAAE,EAAE;IAClC,iDAAiD,EAAE,EAAE;IACrD,eAAe,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE;IAC9G,UAAU,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;IACpH,WAAW,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACvC,UAAU,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACtC,2BAA2B,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACvD,oBAAoB,EAAE;QAClB,IAAI,EAAE,wBAAwB;QAC9B,gBAAgB,EAAE,CAAC,eAAe,CAAC;QACnC,YAAY,EAAE,CAAC,GAAG,qBAAqB,CAAC;KAC3C;IACD,aAAa,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;IAC9B,iGAAiG;IACjG,kGAAkG;IAClG,0EAA0E;IAC1E,yFAAyF;IACzF,oFAAoF;IACpF,iCAAiC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAC7D,iCAAiC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAC7D,sBAAsB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAClD,0BAA0B,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IACtD,sBAAsB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAClD,kGAAkG;IAClG,iGAAiG;IACjG,iGAAiG;IACjG
|
|
1
|
+
{"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/default-rules.ts"],"names":[],"mappings":"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","sourcesContent":["// Default holistic exclude list for the validate-ts-in-src\n// rules. Bare names match a directory segment at any depth; globs match the\n// workspace-relative path. `**/*.d.ts` (ambient declarations) and\n// `**/jest.config.ts` legitimately live outside src/ and are exempt here.\nconst DEFAULT_EXCLUDE_PATHS: readonly string[] = [\n 'node_modules', 'dist', '.nx', '.git',\n '**/*.d.ts', '**/jest.config.ts',\n];\n\n// On/off is driven by `mode` (\"OFF\" disables; an absent mode leaves a rule\n// on). Code-rules entries omit `mode` so each executor keeps its own default\n// scope; structural rules declare `mode: 'RUN_EVERY_TIME'`, bash guards `mode: 'ON'`.\n// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': {},\n 'no-implicit-any': {},\n 'max-file-lines': { limit: 900 },\n 'max-method-lines': { limit: 80 },\n 'require-return-type': {},\n 'no-inline-type-literals': {},\n 'no-destructure': { allowTopLevel: true },\n 'catch-error-pattern': {},\n 'no-unmanaged-exceptions': {},\n 'no-file-import-cycles': { mode: 'RUN_EVERY_TIME' },\n 'runtime-architecture': { mode: 'RUN_EVERY_TIME', allowedCycles: [] },\n 'prisma-validate-dtos': {},\n 'prisma-converter': {},\n 'angular-no-direct-api-in-resolver': {},\n 'no-symbol-di-tokens': {},\n // Ships OFF: a repo opts in per webpieces.config.json once it is ready to migrate any\n // client-in-a-lib sites (severity defaults to \"warn\" so even when enabled it reports without\n // failing until a repo flips it to \"error\").\n 'no-client-creation-outside-server-or-client': { mode: 'OFF' },\n 'no-custom-css': { allowGlobs: [] },\n 'no-process-exit-outside-main': {},\n 'inject-annotation-not-needed-for-concrete-class': {},\n 'framework-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['browser', 'react', 'angular', 'node', 'express'] },\n 'role-tag': { mode: 'MODIFIED_PROJECTS', knownTypes: ['server', 'app', 'designed-lib', 'lib', 'client', 'api-lib'] },\n 'nx-wiring': { mode: 'RUN_EVERY_TIME' },\n 'di-graph': { mode: 'RUN_EVERY_TIME' },\n 'missing-design-annotation': { mode: 'RUN_EVERY_TIME' },\n 'validate-ts-in-src': {\n mode: 'NEW_AND_MODIFIED_FILES',\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [...DEFAULT_EXCLUDE_PATHS],\n },\n 'no-js-files': { mode: 'OFF' },\n // The five Nx infrastructure validators. They enforced unconditionally before they were wired to\n // config, so RUN_EVERY_TIME is the only default that keeps existing repos behaving identically on\n // upgrade. Set \"mode\": \"OFF\" to disable one; the two graph-baseline rules\n // (validate-architecture-unchanged / validate-no-architecture-cycles) additionally honor\n // turnOffRuleUntilEpoch — the other three are all-or-nothing (see rule-configs.ts).\n 'validate-architecture-unchanged': { mode: 'RUN_EVERY_TIME' },\n 'validate-no-architecture-cycles': { mode: 'RUN_EVERY_TIME' },\n 'validate-packagejson': { mode: 'RUN_EVERY_TIME' },\n 'validate-versions-locked': { mode: 'RUN_EVERY_TIME' },\n 'validate-eslint-sync': { mode: 'RUN_EVERY_TIME' },\n // autoReapMergedBranches ships TRUE, and it is also what a fresh config is seeded with.\n //\n // It shipped FALSE on the reasoning that an upgrade must never delete branches unattended before a\n // human opts in. In practice that produced the opposite of safety: nobody opts in, dead branches\n // pile up, and the pile is what makes a real branch hard to find. The reap is also NOT destructive\n // in the way the old comment implied — BranchReaper deletes only provably-dead branches (a merged\n // PR, a squash-merge backup of one, or no commits of their own), spares everything else for a\n // human, and logs each deletion to .webpieces/hooks/branch-mutations.log with the pre-delete SHA\n // and a ready-made `recover=` command. So the worst case is one paste to undo, which a human can\n // resolve; the previous default's worst case was unbounded accumulation nobody ever cleaned.\n //\n // Set it false to keep reaping manual; `pnpm wp-cleanup` works either way.\n 'branch-creation-guard': {\n mode: 'ON',\n subBranchNaming: 'feature/<ticket>/<short-description>',\n autoReapMergedBranches: true,\n },\n 'pr-creation-or-push-guard': { mode: 'ON' },\n 'merge-in-progress-guard': { mode: 'ON' },\n 'pr-merge-guard': { mode: 'ON' },\n 'redirect-how-to-merge-main': { mode: 'ON' },\n // Phase 1 ships OFF on purpose. This guard blocks Read, the highest-blast-radius tool there is,\n // so it is opted into per-repo (webpieces.config.json → hookGuards) only AFTER the release\n // carrying it is published and installed. Flipping it ON here would arm it for every consumer\n // on upgrade, before anyone has verified the fail-open paths against their own git layout.\n 'read-stale-guard': { mode: 'OFF' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
|
package/src/seed-entry.js
CHANGED
|
@@ -50,7 +50,7 @@ function recommendedSeedMode(ruleName) {
|
|
|
50
50
|
// 2. `mode` — the shared recommendation (see recommendedSeedMode);
|
|
51
51
|
// 3. the framework's documented default for that rule (defaultRules) — the value the rule's own
|
|
52
52
|
// config class commits to, e.g. max-file-lines.limit: 900, branch-creation-guard
|
|
53
|
-
// .autoReapMergedBranches:
|
|
53
|
+
// .autoReapMergedBranches: true (reaping is on by default — see default-rules.ts for why);
|
|
54
54
|
// 4. a conservative fallback by type — null if the field accepts null, false for boolean, [] for
|
|
55
55
|
// string[], the first enum value for an enum, '' / 0 otherwise. Reaching step 4 for a NEW field
|
|
56
56
|
// means the rule forgot to give defaultRules an entry, which the seed-validates-clean spec in
|
package/src/seed-entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seed-entry.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/seed-entry.ts"],"names":[],"mappings":";;AA0BA,wDAMC;AAQD,kDAIC;AAwCD,4CAWC;AAKD,sCAEC;AAjGD,iDAA8C;AAC9C,mDAA+C;AAE/C,0FAA0F;AAC1F,2FAA2F;AAC3F,2FAA2F;AAC3F,MAAM,uBAAuB,GAAG;IAC5B,mBAAmB;IACnB,uBAAuB;IACvB,0BAA0B;IAC1B,gBAAgB;IAChB,aAAa;IACb,wBAAwB;CAC3B,CAAC;AAEF,kGAAkG;AAClG,4HAA4H;AAC5H,oGAAoG;AACpG,oGAAoG;AACpG,6CAA6C;AAC7C,yGAAyG;AACzG,SAAgB,sBAAsB,CAAC,KAAwB;IAC3D,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,IAAI,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,gBAAgB,CAAC;IAC9D,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,yGAAyG;AACzG,SAAgB,mBAAmB,CAAC,QAAgB;IAChD,MAAM,MAAM,GAAG,2BAAY,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,yFAAyF;AACzF,uGAAuG;AACvG,qEAAqE;AACrE,kGAAkG;AAClG,sFAAsF;AACtF,
|
|
1
|
+
{"version":3,"file":"seed-entry.js","sourceRoot":"","sources":["../../../../../packages/tooling/rules-config/src/seed-entry.ts"],"names":[],"mappings":"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","sourcesContent":["// Seeding: what a rule's webpieces.config.json entry should look like when nothing has configured it\n// yet. Split out of validate-config.ts (700-line cap). This is the SINGLE source of truth shared by the\n// validator's copy-paste snippet (rolloutTip), the installer (ai-hook-rules setup.seedRule) and fault Y's\n// deny — so a seeded config can never contradict the advice printed beside it.\nimport { FieldDef } from './field-def';\nimport { RULE_SCHEMAS } from './rule-schemas';\nimport { defaultRules } from './default-rules';\n\n// Scoped modes (narrowest → broadest) that enforce ONLY on what changed, so a rule can be\n// adopted gradually instead of all-at-once. When a rule offers one, recommend the first it\n// supports so a fresh config opts into a low-friction rollout rather than reflexively OFF.\nconst GRADUAL_MODE_PREFERENCE = [\n 'MODIFIED_PROJECTS',\n 'NEW_AND_MODIFIED_CODE',\n 'NEW_AND_MODIFIED_METHODS',\n 'MODIFIED_CLASS',\n 'NEW_METHODS',\n 'NEW_AND_MODIFIED_FILES',\n];\n\n// The ONE place that decides what mode a rule should arrive as. Every consumer of that decision —\n// the validator's copy-paste snippet (rolloutTip in validate-config.ts), the installer's seeding, and the fault-`Y` deny in\n// ai-hook-rules — calls this, so a seeded config can never contradict the advice printed beside it.\n// Precedence: narrowest gradual mode the rule supports → ON → RUN_EVERY_TIME → OFF (a rule offering\n// none of those has nothing else it can be).\n// webpieces-disable no-function-outside-class -- sibling of the module-scope schema helpers in this file\nexport function recommendedSeedModeFor(modes: readonly string[]): string {\n const gradual = GRADUAL_MODE_PREFERENCE.find((m: string) => modes.includes(m));\n if (gradual) return gradual;\n if (modes.includes('ON')) return 'ON';\n if (modes.includes('RUN_EVERY_TIME')) return 'RUN_EVERY_TIME';\n return 'OFF';\n}\n\n/**\n * The mode a fresh/migrated `webpieces.config.json` entry for `ruleName` should be seeded with.\n * Unknown rule names (custom rules from `rulesDir`) fall back to 'OFF' — we have no schema to know\n * which modes they accept.\n */\n// webpieces-disable no-function-outside-class -- sibling of the module-scope schema helpers in this file\nexport function recommendedSeedMode(ruleName: string): string {\n const schema = RULE_SCHEMAS[ruleName];\n if (!schema) return 'OFF';\n return recommendedSeedModeFor(schema['mode']?.enumValues ?? []);\n}\n\n// The value a seeded entry gets for ONE required field. Order matters and is deliberate:\n// 1. the two universal escape hatches — always their \"active\" state (0 / null), never a placeholder;\n// 2. `mode` — the shared recommendation (see recommendedSeedMode);\n// 3. the framework's documented default for that rule (defaultRules) — the value the rule's own\n// config class commits to, e.g. max-file-lines.limit: 900, branch-creation-guard\n// .autoReapMergedBranches: true (reaping is on by default — see default-rules.ts for why);\n// 4. a conservative fallback by type — null if the field accepts null, false for boolean, [] for\n// string[], the first enum value for an enum, '' / 0 otherwise. Reaching step 4 for a NEW field\n// means the rule forgot to give defaultRules an entry, which the seed-validates-clean spec in\n// ai-hook-rules/src/bin/setup.spec.ts turns into a build failure if the fallback is not valid.\n// webpieces-disable no-any-unknown -- a config field value is opaque JSON by construction\n// webpieces-disable no-function-outside-class -- sibling of the module-scope schema helpers in this file\nfunction seedFieldValue(ruleName: string, key: string, def: FieldDef): unknown {\n if (key === 'turnOffRuleUntilEpoch') return 0;\n if (key === 'turnOffRuleWhileOnBranch') return null;\n if (key === 'mode') return recommendedSeedModeFor(def.enumValues ?? []);\n\n const documented = defaultRules[ruleName]?.[key];\n if (documented !== undefined) return documented;\n\n if (def.nullable) return null;\n if (def.type === 'boolean') return false;\n if (def.type === 'string[]') return [];\n if (def.enumValues && def.enumValues.length > 0) return def.enumValues[0];\n return def.type === 'number' ? 0 : '';\n}\n\n/**\n * The COMPLETE `webpieces.config.json` entry for `ruleName` — recommended mode, both escape hatches,\n * and a value for every other schema-REQUIRED field.\n *\n * Emitting only mode+hatches is what let `wp-install-ai-hooks` write a config the loader then\n * rejected (`[branch-creation-guard] Missing required field \"autoReapMergedBranches\"`), so the\n * installer and the validator read the SAME schema here. Unknown rule names (custom rules from\n * `rulesDir`) get the minimal entry — we have no schema to enumerate their required fields.\n */\n// webpieces-disable no-any-unknown -- a config entry is opaque JSON by construction\n// webpieces-disable no-function-outside-class -- sibling of the module-scope schema helpers in this file\nexport function seedEntryForRule(ruleName: string): Record<string, unknown> {\n const schema = RULE_SCHEMAS[ruleName];\n const entry: Record<string, unknown> = {\n mode: recommendedSeedMode(ruleName), turnOffRuleUntilEpoch: 0, turnOffRuleWhileOnBranch: null,\n };\n if (!schema) return entry;\n for (const key of Object.keys(schema)) {\n if (schema[key].optional) continue;\n entry[key] = seedFieldValue(ruleName, key, schema[key]);\n }\n return entry;\n}\n\n\n/** True when `mode` is one of the gradual (change-scoped) modes — used to decide whether to print the rollout prose. */\n// webpieces-disable no-function-outside-class -- sibling of the seeding helpers in this file\nexport function isGradualMode(mode: string): boolean {\n return GRADUAL_MODE_PREFERENCE.includes(mode);\n}\n"]}
|
|
@@ -26,24 +26,6 @@ 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;
|
|
36
|
-
/**
|
|
37
|
-
* The FEATURE-BRANCH half, split out of updateMainAdvice() on purpose.
|
|
38
|
-
*
|
|
39
|
-
* It names `wp-start-update` / `wp-start-upsert-pr`, and NEITHER is on the L0 allowlist — correctly
|
|
40
|
-
* so, since a 3-point merge is not a tooling-integrity cure. While an L0 fault is up, printing this
|
|
41
|
-
* sentence unqualified hands the reader a command the guard will reject, which is the deadlock shape
|
|
42
|
-
* the whole L0 module exists to prevent. So a caller printing this from inside an L0 deny must first
|
|
43
|
-
* say how to CLEAR the fault (for drift: `pnpm install`), and only then offer this. Same free of
|
|
44
|
-
* backticks / `$` / `"` as its sibling, so it stays safe inside the shim's double-quoted REASON.
|
|
45
|
-
*/
|
|
46
|
-
featureBranchSyncAdvice(): string;
|
|
47
29
|
/**
|
|
48
30
|
* The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This
|
|
49
31
|
* exists because `git merge --ff-only origin/main` gets typed as if it were a query — it is not,
|
|
@@ -84,34 +84,11 @@ class SyncFlowGuidance {
|
|
|
84
84
|
return 'wp-start-upsert-pr';
|
|
85
85
|
return finishCommand;
|
|
86
86
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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.';
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* The FEATURE-BRANCH half, split out of updateMainAdvice() on purpose.
|
|
103
|
-
*
|
|
104
|
-
* It names `wp-start-update` / `wp-start-upsert-pr`, and NEITHER is on the L0 allowlist — correctly
|
|
105
|
-
* so, since a 3-point merge is not a tooling-integrity cure. While an L0 fault is up, printing this
|
|
106
|
-
* sentence unqualified hands the reader a command the guard will reject, which is the deadlock shape
|
|
107
|
-
* the whole L0 module exists to prevent. So a caller printing this from inside an L0 deny must first
|
|
108
|
-
* say how to CLEAR the fault (for drift: `pnpm install`), and only then offer this. Same free of
|
|
109
|
-
* backticks / `$` / `"` as its sibling, so it stays safe inside the shim's double-quoted REASON.
|
|
110
|
-
*/
|
|
111
|
-
featureBranchSyncAdvice() {
|
|
112
|
-
return 'To sync a FEATURE branch from main use pnpm wp-start-update (no PR open) or '
|
|
113
|
-
+ 'pnpm wp-start-upsert-pr (a PR is open).';
|
|
114
|
-
}
|
|
87
|
+
// updateMainAdvice() / featureBranchSyncAdvice() were DELETED 2026-08-03. Their only caller was the
|
|
88
|
+
// shim's fault-D deny, and both paragraphs were another guard's job: redirect-how-to-merge-main
|
|
89
|
+
// fires on its own, with its own message, on exactly the commands they warned about — and
|
|
90
|
+
// featureBranchSyncAdvice() named wp-start-update / wp-start-upsert-pr only to say "not while this
|
|
91
|
+
// block is up", which is pure cost in a message whose one instruction is `pnpm install`.
|
|
115
92
|
/**
|
|
116
93
|
* The read-only alternatives, for when the AI only wanted to LOOK at how it stands vs main. This
|
|
117
94
|
* 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
|
|
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,oGAAoG;IACpG,gGAAgG;IAChG,0FAA0F;IAC1F,mGAAmG;IACnG,yFAAyF;IAEzF;;;;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;AAhGD,4CAgGC","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 // updateMainAdvice() / featureBranchSyncAdvice() were DELETED 2026-08-03. Their only caller was the\n // shim's fault-D deny, and both paragraphs were another guard's job: redirect-how-to-merge-main\n // fires on its own, with its own message, on exactly the commands they warned about — and\n // featureBranchSyncAdvice() named wp-start-update / wp-start-upsert-pr only to say \"not while this\n // block is up\", which is pure cost in a message whose one instruction is `pnpm install`.\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"]}
|