@webpieces/rules-config 0.4.670 → 0.4.671

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.670",
3
+ "version": "0.4.671",
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",
@@ -76,12 +76,11 @@ exports.defaultRules = {
76
76
  },
77
77
  'pr-lifecycle-guard': { mode: 'ON' },
78
78
  // NOTE: `whole-repo-build-guard` is deliberately ABSENT from this table, and from RULE_SCHEMAS and
79
- // HOOK_GUARD_NAMES with it. It is ON by default and turned off only from the optional machine-local
80
- // ~/.webpieces/config.json (`experimental.whole-repo-build-guard: false`). Adding it back here would
81
- // make it a rule every consumer must CONFIGURE — which is fault Y, i.e. every Bash call blocked on
82
- // upgrade, which is exactly what it did the first time. That fault was the required KEY, not the
83
- // default; being on by default from a file nobody has to create cannot reproduce it. See
84
- // RETIRED_CONFIG_KEYS.
79
+ // HOOK_GUARD_NAMES with it. It is EXPERIMENTAL and OFF by default; the ONLY thing that turns it on
80
+ // is `experimental.whole-repo-build-guard: true` in the optional machine-local
81
+ // ~/.webpieces/config.json. Adding it back here would make it a rule every consumer must CONFIGURE
82
+ // which is fault Y, i.e. every Bash call blocked on upgrade, which is exactly what it did the
83
+ // first time. See RETIRED_CONFIG_KEYS.
85
84
  //
86
85
  // branch-state-guard ships ON, INCLUDING its Read-blocking half.
87
86
  //
@@ -1 +1 @@
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/logs/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-lifecycle-guard': { mode: 'ON' },\n // NOTE: `whole-repo-build-guard` is deliberately ABSENT from this table, and from RULE_SCHEMAS and\n // HOOK_GUARD_NAMES with it. It is ON by default and turned off only from the optional machine-local\n // ~/.webpieces/config.json (`experimental.whole-repo-build-guard: false`). Adding it back here would\n // make it a rule every consumer must CONFIGURE — which is fault Y, i.e. every Bash call blocked on\n // upgrade, which is exactly what it did the first time. That fault was the required KEY, not the\n // default; being on by default from a file nobody has to create cannot reproduce it. See\n // RETIRED_CONFIG_KEYS.\n //\n // branch-state-guard ships ON, INCLUDING its Read-blocking half.\n //\n // Its predecessor `read-stale-guard` shipped OFF as a \"phase 1\" staged rollout, on the reasoning\n // that Read is the highest-blast-radius tool there is and nobody should be armed before verifying\n // the fail-open paths against their own git layout. Phase 1 is over: this repo has run it ON in\n // production for releases, and the fail-open paths (branch undeterminable, cache absent, cache for\n // another branch, offline, dirty tree on main) are each covered by tests. Keeping it OFF now buys\n // nothing and costs the exact incident the guard exists for — a session spent reading a tree 18\n // commits behind while the log read \"handled\".\n //\n // Nothing is armed behind anyone's back either way: every built-in requires an explicit entry (the\n // config-sync check blocks until one exists), so a consumer states this mode themselves on upgrade.\n 'branch-state-guard': { mode: 'ON' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
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/logs/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-lifecycle-guard': { mode: 'ON' },\n // NOTE: `whole-repo-build-guard` is deliberately ABSENT from this table, and from RULE_SCHEMAS and\n // HOOK_GUARD_NAMES with it. It is EXPERIMENTAL and OFF by default; the ONLY thing that turns it on\n // is `experimental.whole-repo-build-guard: true` in the optional machine-local\n // ~/.webpieces/config.json. Adding it back here would make it a rule every consumer must CONFIGURE\n // — which is fault Y, i.e. every Bash call blocked on upgrade, which is exactly what it did the\n // first time. See RETIRED_CONFIG_KEYS.\n //\n // branch-state-guard ships ON, INCLUDING its Read-blocking half.\n //\n // Its predecessor `read-stale-guard` shipped OFF as a \"phase 1\" staged rollout, on the reasoning\n // that Read is the highest-blast-radius tool there is and nobody should be armed before verifying\n // the fail-open paths against their own git layout. Phase 1 is over: this repo has run it ON in\n // production for releases, and the fail-open paths (branch undeterminable, cache absent, cache for\n // another branch, offline, dirty tree on main) are each covered by tests. Keeping it OFF now buys\n // nothing and costs the exact incident the guard exists for — a session spent reading a tree 18\n // commits behind while the log read \"handled\".\n //\n // Nothing is armed behind anyone's back either way: every built-in requires an explicit entry (the\n // config-sync check blocks until one exists), so a consumer states this mode themselves on upgrade.\n 'branch-state-guard': { mode: 'ON' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
@@ -70,12 +70,12 @@
70
70
  * used to be a loud rejection; it is now a key nothing reads, so the flag keeps its default and nothing
71
71
  * about the machine's behaviour reveals the mistake.
72
72
  *
73
- * That bites HARDEST on a key whose default is ON, which `whole-repo-build-guard` now is
74
- * (WHOLE_REPO_BUILD_GUARD_DEFAULT). Misspell the OPT-OUT and the guard stays on while the author
75
- * believes they turned it off a failure that argues with them rather than one they can shrug at. It is
76
- * the strongest reason the warning below is not optional decoration, and the reason `nearestKnownKey`
77
- * had to get fuzzier than the case-insensitive match it replaced: `gaurd` is a transposition, exactly
78
- * the class of typo an equality test cannot see.
73
+ * Every key here is an OPT-IN that defaults OFF, so a typo costs the author the feature they meant to
74
+ * switch on: misspell `whole-repo-build-guard` and the guard stays inert while they believe they armed
75
+ * it. That is the milder of the two failures nothing they were doing stops working but it is still
76
+ * invisible without a signal, which is why the warning below is not optional decoration, and why
77
+ * `nearestKnownKey` had to get fuzzier than the case-insensitive match it replaced: `gaurd` is a
78
+ * transposition, exactly the class of typo an equality test cannot see.
79
79
  *
80
80
  * That is mitigated, not eliminated, by making the ignore VISIBLE: every unknown key is printed once per
81
81
  * load as a `[webpieces]` warning on stderr, and `nearestKnownKey` upgrades that line with a "did you
@@ -106,10 +106,16 @@
106
106
  * default state. A repo-tracked config key cannot express that — an entry there is something every
107
107
  * consumer must add, on a schedule set by whoever bumps the release.
108
108
  *
109
- * Note which half of that was the outage. It was the REQUIRED KEY, not the on-by-default behaviour: the
110
- * failure was at config LOAD, before any command was judged. `whole-repo-build-guard` defaults ON again
111
- * today (see WHOLE_REPO_BUILD_GUARD_DEFAULT) and cannot reproduce it, because there is nothing to add
112
- * anywhere — the only file that could carry it is optional, and absent is a fully supported state.
109
+ * Note which half of that was the outage. It was the REQUIRED KEY: the failure was at config LOAD,
110
+ * before any command was judged. That is why every key here stays OPTIONAL and why an absent file
111
+ * returns all-defaults silently.
112
+ *
113
+ * The DEFAULT is settled separately, by a standing policy this file does not get to re-litigate: EVERY
114
+ * `experimental.*` flag ships OFF and stays OFF for two years. `whole-repo-build-guard` is one of them,
115
+ * so it is OFF unless a machine writes `{"experimental": {"whole-repo-build-guard": true}}`. A flag that
116
+ * defaults ON is not an experiment — it is a shipped behaviour that skipped its soak period, and it
117
+ * changes what every agent on every machine can do the moment they upgrade. Low uptake of an opt-in
118
+ * experiment is information ABOUT the experiment; it is not a licence to force it on everybody.
113
119
  */
114
120
  export declare const HOME_CONFIG_DIR = ".webpieces";
115
121
  export declare const HOME_CONFIG_FILE = "config.json";
@@ -117,28 +123,6 @@ export declare const HOME_EXPERIMENTAL_SECTION = "experimental";
117
123
  export declare const HOME_KEY_BUILD_GATE_LOG_CAPTURE = "buildGateLogCapture";
118
124
  export declare const HOME_KEY_WHOLE_REPO_BUILD_GUARD = "whole-repo-build-guard";
119
125
  export declare const HOME_KEY_ORPHAN_DIR_SWEEP = "orphan-dir-sweep";
120
- /**
121
- * `whole-repo-build-guard`'s value on a machine that does not name the key — including the machine with
122
- * no such file at all, which is essentially every machine. It is TRUE: the guard is ON by default.
123
- *
124
- * ─── Why this one key defaults ON, and why that is not the outage this file warns about ─────────────
125
- * The outage recorded below was a CONFIG-LOAD failure: the guard once required an entry under
126
- * `hookGuards` in the repo-tracked `webpieces.config.json`, so every consumer who upgraded without
127
- * adding it hit fault Y and had EVERY Bash call blocked, for a feature they had never asked for. The
128
- * shape of that failure is "you must edit a file to get your shell back". Nothing here reproduces it:
129
- * no file needs to exist, no key needs to be added, and the load path for an absent or silent file is
130
- * unchanged. What changes is only what the guard DOES once loaded — it refuses a command that would
131
- * build the whole monorepo, and hands back the scoped command in its place.
132
- *
133
- * That is the behaviour the guard was written for, and OFF-by-default is why it never delivered it: a
134
- * guard nobody opts into never fires. The measured consequence is a sibling repo whose `ci:local`
135
- * verify chain ran three whole-world passes on every inner loop for months, while the correct command
136
- * sat unused in `commands.pr-gate.buildCommand`.
137
- *
138
- * The escape hatch stays, and it is one line: `{"experimental": {"whole-repo-build-guard": false}}`
139
- * turns it off for a machine, with no repo config involved.
140
- */
141
- export declare const WHOLE_REPO_BUILD_GUARD_DEFAULT = true;
142
126
  /**
143
127
  * The complete UNDERSTOOD shape. A key not on these lists is ignored with a warning rather than
144
128
  * rejected (see the class docblock: this document is machine-global and older releases must survive
@@ -162,16 +146,15 @@ export declare class HomeConfig {
162
146
  */
163
147
  buildGateLogCapture: boolean;
164
148
  /**
165
- * NOT experimental, and ON unless this machine says otherwise: `WHOLE_REPO_BUILD_GUARD_DEFAULT`.
166
- * When true, `whole-repo-build-guard` BLOCKS a Bash command that would build the WHOLE monorepo and
167
- * hands back the repo's own scoped build command (`pnpm wp-build`). Setting it false makes the guard
168
- * completely inert: no block, no log, no message.
149
+ * EXPERIMENTAL, and OFF unless this machine opts IN with an explicit `true`. When true,
150
+ * `whole-repo-build-guard` BLOCKS a Bash command that would build the WHOLE monorepo and hands back
151
+ * the repo's own scoped build command (`pnpm wp-build`). False and absent, and no file at all —
152
+ * makes the guard completely inert: no block, no log, no message.
169
153
  *
170
- * This is the guard's ONLY switch, and it is an OPT-OUT. There is deliberately no
154
+ * This is the guard's ONLY switch, and it is an OPT-IN. There is deliberately no
171
155
  * webpieces.config.json entry for it (see RETIRED_CONFIG_KEYS): a guard that every consumer must
172
156
  * ADD A KEY to avoid being blocked by is a guard that ships an outage on upgrade, which is exactly
173
- * what happened. Defaulting ON here is the opposite shape nothing has to be added anywhere, and
174
- * see WHOLE_REPO_BUILD_GUARD_DEFAULT for why that distinction is the whole argument.
157
+ * what happened once. Living here means the default state needs no file, no key and no edit.
175
158
  */
176
159
  wholeRepoBuildGuard: boolean;
177
160
  /**
@@ -256,12 +239,12 @@ export declare class HomeConfigService {
256
239
  private parse;
257
240
  private validate;
258
241
  /**
259
- * An absent key falls back to `whenAbsent`, which every caller states OUT LOUD there is no implicit
260
- * "absent means false" any more, because `whole-repo-build-guard` defaults ON and a hidden default
261
- * would put the two halves of that fact in different files.
242
+ * An absent key falls back to `whenAbsent`, which every caller states OUT LOUD by passing
243
+ * `GUARD_OFF_WHEN_ABSENT` — an implicit "absent means false" buried in this method would put the
244
+ * default and the key that carries it in different places, free to drift apart.
262
245
  *
263
- * A PRESENT key of the wrong type is still an ERROR, and that is the line the unknown-key change
264
- * deliberately did not move: `"whole-repo-build-guard": "yes"` is a file somebody wrote wrongly, not
246
+ * A PRESENT key of the wrong type is still an ERROR, and that is the line neither the unknown-key change
247
+ * nor this one moved: `"whole-repo-build-guard": "yes"` is a file somebody wrote wrongly, not
265
248
  * a file written for a different release. No release of webpieces has ever given this key a string
266
249
  * meaning, so there is no forward-compatibility story to protect and nothing is gained by guessing —
267
250
  * whereas guessing would turn a typed value into a silent fallback to the default, which is the very
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.HomeConfigService = exports.RETIRED_HOME_CONFIG_KEYS = exports.RetiredHomeConfigKey = exports.HomeConfig = exports.ALLOWED_EXPERIMENTAL = exports.ALLOWED_TOP_LEVEL = exports.WHOLE_REPO_BUILD_GUARD_DEFAULT = exports.HOME_KEY_ORPHAN_DIR_SWEEP = exports.HOME_KEY_WHOLE_REPO_BUILD_GUARD = exports.HOME_KEY_BUILD_GATE_LOG_CAPTURE = exports.HOME_EXPERIMENTAL_SECTION = exports.HOME_CONFIG_FILE = exports.HOME_CONFIG_DIR = void 0;
3
+ exports.HomeConfigService = exports.RETIRED_HOME_CONFIG_KEYS = exports.RetiredHomeConfigKey = exports.HomeConfig = exports.ALLOWED_EXPERIMENTAL = exports.ALLOWED_TOP_LEVEL = exports.HOME_KEY_ORPHAN_DIR_SWEEP = exports.HOME_KEY_WHOLE_REPO_BUILD_GUARD = exports.HOME_KEY_BUILD_GATE_LOG_CAPTURE = exports.HOME_EXPERIMENTAL_SECTION = exports.HOME_CONFIG_FILE = exports.HOME_CONFIG_DIR = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const fs = tslib_1.__importStar(require("fs"));
6
6
  const os = tslib_1.__importStar(require("os"));
@@ -80,12 +80,12 @@ const to_error_1 = require("./to-error");
80
80
  * used to be a loud rejection; it is now a key nothing reads, so the flag keeps its default and nothing
81
81
  * about the machine's behaviour reveals the mistake.
82
82
  *
83
- * That bites HARDEST on a key whose default is ON, which `whole-repo-build-guard` now is
84
- * (WHOLE_REPO_BUILD_GUARD_DEFAULT). Misspell the OPT-OUT and the guard stays on while the author
85
- * believes they turned it off a failure that argues with them rather than one they can shrug at. It is
86
- * the strongest reason the warning below is not optional decoration, and the reason `nearestKnownKey`
87
- * had to get fuzzier than the case-insensitive match it replaced: `gaurd` is a transposition, exactly
88
- * the class of typo an equality test cannot see.
83
+ * Every key here is an OPT-IN that defaults OFF, so a typo costs the author the feature they meant to
84
+ * switch on: misspell `whole-repo-build-guard` and the guard stays inert while they believe they armed
85
+ * it. That is the milder of the two failures nothing they were doing stops working but it is still
86
+ * invisible without a signal, which is why the warning below is not optional decoration, and why
87
+ * `nearestKnownKey` had to get fuzzier than the case-insensitive match it replaced: `gaurd` is a
88
+ * transposition, exactly the class of typo an equality test cannot see.
89
89
  *
90
90
  * That is mitigated, not eliminated, by making the ignore VISIBLE: every unknown key is printed once per
91
91
  * load as a `[webpieces]` warning on stderr, and `nearestKnownKey` upgrades that line with a "did you
@@ -116,10 +116,16 @@ const to_error_1 = require("./to-error");
116
116
  * default state. A repo-tracked config key cannot express that — an entry there is something every
117
117
  * consumer must add, on a schedule set by whoever bumps the release.
118
118
  *
119
- * Note which half of that was the outage. It was the REQUIRED KEY, not the on-by-default behaviour: the
120
- * failure was at config LOAD, before any command was judged. `whole-repo-build-guard` defaults ON again
121
- * today (see WHOLE_REPO_BUILD_GUARD_DEFAULT) and cannot reproduce it, because there is nothing to add
122
- * anywhere — the only file that could carry it is optional, and absent is a fully supported state.
119
+ * Note which half of that was the outage. It was the REQUIRED KEY: the failure was at config LOAD,
120
+ * before any command was judged. That is why every key here stays OPTIONAL and why an absent file
121
+ * returns all-defaults silently.
122
+ *
123
+ * The DEFAULT is settled separately, by a standing policy this file does not get to re-litigate: EVERY
124
+ * `experimental.*` flag ships OFF and stays OFF for two years. `whole-repo-build-guard` is one of them,
125
+ * so it is OFF unless a machine writes `{"experimental": {"whole-repo-build-guard": true}}`. A flag that
126
+ * defaults ON is not an experiment — it is a shipped behaviour that skipped its soak period, and it
127
+ * changes what every agent on every machine can do the moment they upgrade. Low uptake of an opt-in
128
+ * experiment is information ABOUT the experiment; it is not a licence to force it on everybody.
123
129
  */
124
130
  exports.HOME_CONFIG_DIR = '.webpieces';
125
131
  exports.HOME_CONFIG_FILE = 'config.json';
@@ -137,30 +143,17 @@ exports.HOME_KEY_WHOLE_REPO_BUILD_GUARD = 'whole-repo-build-guard';
137
143
  // it switches, exactly as the guard key above is — one name, greppable from either end.
138
144
  exports.HOME_KEY_ORPHAN_DIR_SWEEP = 'orphan-dir-sweep';
139
145
  /**
140
- * `whole-repo-build-guard`'s value on a machine that does not name the key — including the machine with
141
- * no such file at all, which is essentially every machine. It is TRUE: the guard is ON by default.
142
- *
143
- * ─── Why this one key defaults ON, and why that is not the outage this file warns about ─────────────
144
- * The outage recorded below was a CONFIG-LOAD failure: the guard once required an entry under
145
- * `hookGuards` in the repo-tracked `webpieces.config.json`, so every consumer who upgraded without
146
- * adding it hit fault Y and had EVERY Bash call blocked, for a feature they had never asked for. The
147
- * shape of that failure is "you must edit a file to get your shell back". Nothing here reproduces it:
148
- * no file needs to exist, no key needs to be added, and the load path for an absent or silent file is
149
- * unchanged. What changes is only what the guard DOES once loaded — it refuses a command that would
150
- * build the whole monorepo, and hands back the scoped command in its place.
151
- *
152
- * That is the behaviour the guard was written for, and OFF-by-default is why it never delivered it: a
153
- * guard nobody opts into never fires. The measured consequence is a sibling repo whose `ci:local`
154
- * verify chain ran three whole-world passes on every inner loop for months, while the correct command
155
- * sat unused in `commands.pr-gate.buildCommand`.
156
- *
157
- * The escape hatch stays, and it is one line: `{"experimental": {"whole-repo-build-guard": false}}`
158
- * turns it off for a machine, with no repo config involved.
146
+ * EVERY key's value when it is not named — including on the machine with no such file at all, which is
147
+ * essentially every machine. False, for all of them, with no exceptions and no per-key table.
148
+ *
149
+ * That uniformity is the policy, not a coincidence: every `experimental.*` flag ships OFF and stays OFF
150
+ * for two years, so "this machine never opted in" is byte-for-byte the behaviour of having no file. ON
151
+ * requires an explicit `true`; absent, and an explicit `false`, are the same state.
152
+ *
153
+ * Named rather than written as a bare `false` at each call site so the reason travels with the value —
154
+ * and there is deliberately exactly ONE such constant, because a second one would be a second place a
155
+ * default is stated, free to disagree with this one.
159
156
  */
160
- exports.WHOLE_REPO_BUILD_GUARD_DEFAULT = true;
161
- // Every OTHER key's value when it is not named. False — "this machine never opted in" — which for those
162
- // keys is byte-for-byte the behaviour of having no file at all. Named rather than written as a bare
163
- // `false` at each call site so the asymmetry with the constant above is visible where it is passed.
164
157
  const GUARD_OFF_WHEN_ABSENT = false;
165
158
  /**
166
159
  * The complete UNDERSTOOD shape. A key not on these lists is ignored with a warning rather than
@@ -192,10 +185,8 @@ exports.ALLOWED_EXPERIMENTAL = [
192
185
  * reasoning was sound for a single version and wrong for a shared file. It is optional now, along with
193
186
  * every other key.
194
187
  *
195
- * Absent then reads as each key's declared default. For every EXPERIMENTAL key that is false, which is
196
- * byte-for-byte the behaviour of having no file at all. `whole-repo-build-guard` is the one exception
197
- * and it defaults TRUE — it is no longer experimental — for the reason spelled out at
198
- * WHOLE_REPO_BUILD_GUARD_DEFAULT.
188
+ * Absent then reads as the ONE declared default, `GUARD_OFF_WHEN_ABSENT`: false, for every key without
189
+ * exception, which is byte-for-byte the behaviour of having no file at all.
199
190
  *
200
191
  * The other half of cross-version safety — an OLD release IGNORING a key a NEW one added, rather than
201
192
  * rejecting it — is solved by `warnUnknownKeys` below. The two halves are one invariant: for the set of
@@ -216,16 +207,15 @@ class HomeConfig {
216
207
  */
217
208
  buildGateLogCapture;
218
209
  /**
219
- * NOT experimental, and ON unless this machine says otherwise: `WHOLE_REPO_BUILD_GUARD_DEFAULT`.
220
- * When true, `whole-repo-build-guard` BLOCKS a Bash command that would build the WHOLE monorepo and
221
- * hands back the repo's own scoped build command (`pnpm wp-build`). Setting it false makes the guard
222
- * completely inert: no block, no log, no message.
210
+ * EXPERIMENTAL, and OFF unless this machine opts IN with an explicit `true`. When true,
211
+ * `whole-repo-build-guard` BLOCKS a Bash command that would build the WHOLE monorepo and hands back
212
+ * the repo's own scoped build command (`pnpm wp-build`). False and absent, and no file at all —
213
+ * makes the guard completely inert: no block, no log, no message.
223
214
  *
224
- * This is the guard's ONLY switch, and it is an OPT-OUT. There is deliberately no
215
+ * This is the guard's ONLY switch, and it is an OPT-IN. There is deliberately no
225
216
  * webpieces.config.json entry for it (see RETIRED_CONFIG_KEYS): a guard that every consumer must
226
217
  * ADD A KEY to avoid being blocked by is a guard that ships an outage on upgrade, which is exactly
227
- * what happened. Defaulting ON here is the opposite shape nothing has to be added anywhere, and
228
- * see WHOLE_REPO_BUILD_GUARD_DEFAULT for why that distinction is the whole argument.
218
+ * what happened once. Living here means the default state needs no file, no key and no edit.
229
219
  */
230
220
  wholeRepoBuildGuard;
231
221
  /**
@@ -314,13 +304,12 @@ let HomeConfigService = class HomeConfigService {
314
304
  */
315
305
  load(homeDir = os.homedir()) {
316
306
  const raw = this.readIfPresent(this.configPath(homeDir));
317
- // THE ABSENT-FILE STATE, and the ONE place it is constructed. Every EXPERIMENTAL flag is off;
318
- // `whole-repo-build-guard` is NOT experimental any more and takes WHOLE_REPO_BUILD_GUARD_DEFAULT
319
- // (true) the same value a present file that does not name the key gets, so "no file" and "file
320
- // that ignores this key" can never disagree. Spelled out rather than defaulted in the
321
- // constructor — see the note there on why a defaulted parameter is a shim.
307
+ // THE ABSENT-FILE STATE, and the ONE place it is constructed. Every flag is off — the same value
308
+ // a present file that does not name the key gets, so "no file" and "file that ignores this key"
309
+ // can never disagree. Spelled out rather than defaulted in the constructor see the note there
310
+ // on why a defaulted parameter is a shim.
322
311
  if (raw === null) {
323
- return new HomeConfig(GUARD_OFF_WHEN_ABSENT, exports.WHOLE_REPO_BUILD_GUARD_DEFAULT, GUARD_OFF_WHEN_ABSENT);
312
+ return new HomeConfig(GUARD_OFF_WHEN_ABSENT, GUARD_OFF_WHEN_ABSENT, GUARD_OFF_WHEN_ABSENT);
324
313
  }
325
314
  return this.validate(this.parse(raw, this.configPath(homeDir)), this.configPath(homeDir));
326
315
  }
@@ -407,15 +396,15 @@ let HomeConfigService = class HomeConfigService {
407
396
  // webpieces-disable no-any-unknown -- narrowed to a non-null, non-array object one line above
408
397
  const experimental = (section ?? {});
409
398
  this.warnUnknownKeys(Object.keys(experimental), exports.ALLOWED_EXPERIMENTAL, `${exports.HOME_EXPERIMENTAL_SECTION}.`);
410
- return new HomeConfig(this.readOptionalBoolean(experimental, exports.HOME_KEY_BUILD_GATE_LOG_CAPTURE, file, GUARD_OFF_WHEN_ABSENT), this.readOptionalBoolean(experimental, exports.HOME_KEY_WHOLE_REPO_BUILD_GUARD, file, exports.WHOLE_REPO_BUILD_GUARD_DEFAULT), this.readOptionalBoolean(experimental, exports.HOME_KEY_ORPHAN_DIR_SWEEP, file, GUARD_OFF_WHEN_ABSENT));
399
+ return new HomeConfig(this.readOptionalBoolean(experimental, exports.HOME_KEY_BUILD_GATE_LOG_CAPTURE, file, GUARD_OFF_WHEN_ABSENT), this.readOptionalBoolean(experimental, exports.HOME_KEY_WHOLE_REPO_BUILD_GUARD, file, GUARD_OFF_WHEN_ABSENT), this.readOptionalBoolean(experimental, exports.HOME_KEY_ORPHAN_DIR_SWEEP, file, GUARD_OFF_WHEN_ABSENT));
411
400
  }
412
401
  /**
413
- * An absent key falls back to `whenAbsent`, which every caller states OUT LOUD there is no implicit
414
- * "absent means false" any more, because `whole-repo-build-guard` defaults ON and a hidden default
415
- * would put the two halves of that fact in different files.
402
+ * An absent key falls back to `whenAbsent`, which every caller states OUT LOUD by passing
403
+ * `GUARD_OFF_WHEN_ABSENT` — an implicit "absent means false" buried in this method would put the
404
+ * default and the key that carries it in different places, free to drift apart.
416
405
  *
417
- * A PRESENT key of the wrong type is still an ERROR, and that is the line the unknown-key change
418
- * deliberately did not move: `"whole-repo-build-guard": "yes"` is a file somebody wrote wrongly, not
406
+ * A PRESENT key of the wrong type is still an ERROR, and that is the line neither the unknown-key change
407
+ * nor this one moved: `"whole-repo-build-guard": "yes"` is a file somebody wrote wrongly, not
419
408
  * a file written for a different release. No release of webpieces has ever given this key a string
420
409
  * meaning, so there is no forward-compatibility story to protect and nothing is gained by guessing —
421
410
  * whereas guessing would turn a typed value into a silent fallback to the default, which is the very