@oddessentials/repo-standards 5.1.0 → 5.2.0

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/README.md CHANGED
@@ -106,6 +106,11 @@ The `version` field indicates schema compatibility:
106
106
  - `4` — Stable API contract with `getStandards()`, `getSchema()`, `STANDARDS_VERSION` exports; Node 22 LTS alignment.
107
107
  - `5` — Adds automated version-guard guidance for repositories using semantic-release; schema aligned to package major version 5.
108
108
 
109
+ To keep `config/standards.json` in sync with semantic-release major bumps, use
110
+ `scripts/sync-standards-version.cjs` during the semantic-release prepare step
111
+ and commit the updated files. This updates the schema version and README
112
+ references in one place.
113
+
109
114
  Consumers should ignore unknown fields for forward compatibility.
110
115
 
111
116
  ---
@@ -235,6 +235,28 @@
235
235
  "verification": "Run the guard and confirm it fails when <Version> or <VersionPrefix> changes in props/csproj files."
236
236
  }
237
237
  },
238
+ {
239
+ "ciHints": {
240
+ "azure-devops": {
241
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
242
+ "stage": "quality"
243
+ }
244
+ },
245
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
246
+ "id": "release-artifact-exclusion",
247
+ "label": "Release Artifact Formatter Exclusion",
248
+ "stack": {
249
+ "exampleConfigFiles": [
250
+ ".editorconfig"
251
+ ],
252
+ "exampleTools": [
253
+ "dotnet format",
254
+ "GitVersion"
255
+ ],
256
+ "notes": "Use .editorconfig to exclude auto-generated files from formatting. GitVersion may generate or modify files that shouldn't be reformatted. Add glob patterns for generated code directories (e.g., **/obj/**, **/bin/**).",
257
+ "verification": "Run 'dotnet format --verify-no-changes' and confirm generated files are excluded."
258
+ }
259
+ },
238
260
  {
239
261
  "ciHints": {
240
262
  "azure-devops": {
@@ -235,6 +235,28 @@
235
235
  "verification": "Run the guard and confirm it fails when <Version> or <VersionPrefix> changes in props/csproj files."
236
236
  }
237
237
  },
238
+ {
239
+ "ciHints": {
240
+ "github-actions": {
241
+ "job": "ci",
242
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
243
+ }
244
+ },
245
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
246
+ "id": "release-artifact-exclusion",
247
+ "label": "Release Artifact Formatter Exclusion",
248
+ "stack": {
249
+ "exampleConfigFiles": [
250
+ ".editorconfig"
251
+ ],
252
+ "exampleTools": [
253
+ "dotnet format",
254
+ "GitVersion"
255
+ ],
256
+ "notes": "Use .editorconfig to exclude auto-generated files from formatting. GitVersion may generate or modify files that shouldn't be reformatted. Add glob patterns for generated code directories (e.g., **/obj/**, **/bin/**).",
257
+ "verification": "Run 'dotnet format --verify-no-changes' and confirm generated files are excluded."
258
+ }
259
+ },
238
260
  {
239
261
  "ciHints": {
240
262
  "github-actions": {
@@ -262,6 +262,32 @@
262
262
  "verification": "Run the guard and confirm it fails when <Version> or <VersionPrefix> changes in props/csproj files."
263
263
  }
264
264
  },
265
+ {
266
+ "ciHints": {
267
+ "azure-devops": {
268
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
269
+ "stage": "quality"
270
+ },
271
+ "github-actions": {
272
+ "job": "ci",
273
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
274
+ }
275
+ },
276
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
277
+ "id": "release-artifact-exclusion",
278
+ "label": "Release Artifact Formatter Exclusion",
279
+ "stack": {
280
+ "exampleConfigFiles": [
281
+ ".editorconfig"
282
+ ],
283
+ "exampleTools": [
284
+ "dotnet format",
285
+ "GitVersion"
286
+ ],
287
+ "notes": "Use .editorconfig to exclude auto-generated files from formatting. GitVersion may generate or modify files that shouldn't be reformatted. Add glob patterns for generated code directories (e.g., **/obj/**, **/bin/**).",
288
+ "verification": "Run 'dotnet format --verify-no-changes' and confirm generated files are excluded."
289
+ }
290
+ },
265
291
  {
266
292
  "ciHints": {
267
293
  "azure-devops": {
@@ -229,6 +229,28 @@
229
229
  "verification": "Run the guard and confirm it fails when VERSION or version constants change outside release automation."
230
230
  }
231
231
  },
232
+ {
233
+ "ciHints": {
234
+ "azure-devops": {
235
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
236
+ "stage": "quality"
237
+ }
238
+ },
239
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
240
+ "id": "release-artifact-exclusion",
241
+ "label": "Release Artifact Formatter Exclusion",
242
+ "stack": {
243
+ "exampleConfigFiles": [
244
+ ".golangci.yml"
245
+ ],
246
+ "exampleTools": [
247
+ "gofmt",
248
+ "goreleaser"
249
+ ],
250
+ "notes": "Go formatting (gofmt) only affects .go files, so CHANGELOG.md is automatically excluded. If using code generators, exclude generated directories in .golangci.yml skip-dirs.",
251
+ "verification": "Run 'gofmt -d .' and confirm generated code directories are excluded."
252
+ }
253
+ },
232
254
  {
233
255
  "ciHints": {
234
256
  "azure-devops": {
@@ -229,6 +229,28 @@
229
229
  "verification": "Run the guard and confirm it fails when VERSION or version constants change outside release automation."
230
230
  }
231
231
  },
232
+ {
233
+ "ciHints": {
234
+ "github-actions": {
235
+ "job": "ci",
236
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
237
+ }
238
+ },
239
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
240
+ "id": "release-artifact-exclusion",
241
+ "label": "Release Artifact Formatter Exclusion",
242
+ "stack": {
243
+ "exampleConfigFiles": [
244
+ ".golangci.yml"
245
+ ],
246
+ "exampleTools": [
247
+ "gofmt",
248
+ "goreleaser"
249
+ ],
250
+ "notes": "Go formatting (gofmt) only affects .go files, so CHANGELOG.md is automatically excluded. If using code generators, exclude generated directories in .golangci.yml skip-dirs.",
251
+ "verification": "Run 'gofmt -d .' and confirm generated code directories are excluded."
252
+ }
253
+ },
232
254
  {
233
255
  "ciHints": {
234
256
  "github-actions": {
@@ -256,6 +256,32 @@
256
256
  "verification": "Run the guard and confirm it fails when VERSION or version constants change outside release automation."
257
257
  }
258
258
  },
259
+ {
260
+ "ciHints": {
261
+ "azure-devops": {
262
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
263
+ "stage": "quality"
264
+ },
265
+ "github-actions": {
266
+ "job": "ci",
267
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
268
+ }
269
+ },
270
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
271
+ "id": "release-artifact-exclusion",
272
+ "label": "Release Artifact Formatter Exclusion",
273
+ "stack": {
274
+ "exampleConfigFiles": [
275
+ ".golangci.yml"
276
+ ],
277
+ "exampleTools": [
278
+ "gofmt",
279
+ "goreleaser"
280
+ ],
281
+ "notes": "Go formatting (gofmt) only affects .go files, so CHANGELOG.md is automatically excluded. If using code generators, exclude generated directories in .golangci.yml skip-dirs.",
282
+ "verification": "Run 'gofmt -d .' and confirm generated code directories are excluded."
283
+ }
284
+ },
259
285
  {
260
286
  "ciHints": {
261
287
  "azure-devops": {
@@ -1001,6 +1001,95 @@
1001
1001
  }
1002
1002
  }
1003
1003
  },
1004
+ {
1005
+ "appliesTo": {
1006
+ "stacks": [
1007
+ "typescript-js",
1008
+ "csharp-dotnet",
1009
+ "python",
1010
+ "rust",
1011
+ "go"
1012
+ ]
1013
+ },
1014
+ "ciHints": {
1015
+ "azure-devops": {
1016
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
1017
+ "stage": "quality"
1018
+ },
1019
+ "github-actions": {
1020
+ "job": "ci",
1021
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
1022
+ }
1023
+ },
1024
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
1025
+ "enforcement": "required",
1026
+ "executionStage": "pre-commit",
1027
+ "id": "release-artifact-exclusion",
1028
+ "label": "Release Artifact Formatter Exclusion",
1029
+ "severity": "error",
1030
+ "stackHints": {
1031
+ "csharp-dotnet": {
1032
+ "exampleConfigFiles": [
1033
+ ".editorconfig"
1034
+ ],
1035
+ "exampleTools": [
1036
+ "dotnet format",
1037
+ "GitVersion"
1038
+ ],
1039
+ "notes": "Use .editorconfig to exclude auto-generated files from formatting. GitVersion may generate or modify files that shouldn't be reformatted. Add glob patterns for generated code directories (e.g., **/obj/**, **/bin/**).",
1040
+ "verification": "Run 'dotnet format --verify-no-changes' and confirm generated files are excluded."
1041
+ },
1042
+ "go": {
1043
+ "exampleConfigFiles": [
1044
+ ".golangci.yml"
1045
+ ],
1046
+ "exampleTools": [
1047
+ "gofmt",
1048
+ "goreleaser"
1049
+ ],
1050
+ "notes": "Go formatting (gofmt) only affects .go files, so CHANGELOG.md is automatically excluded. If using code generators, exclude generated directories in .golangci.yml skip-dirs.",
1051
+ "verification": "Run 'gofmt -d .' and confirm generated code directories are excluded."
1052
+ },
1053
+ "python": {
1054
+ "exampleConfigFiles": [
1055
+ "pyproject.toml"
1056
+ ],
1057
+ "exampleTools": [
1058
+ "black",
1059
+ "ruff",
1060
+ "bumpversion"
1061
+ ],
1062
+ "notes": "In pyproject.toml [tool.black] or [tool.ruff], add extend-exclude patterns for auto-generated files like CHANGELOG.md. Some versioning tools generate or modify files that should not be reformatted.",
1063
+ "verification": "Run 'black --check .' or 'ruff format --check' and confirm generated files are excluded."
1064
+ },
1065
+ "rust": {
1066
+ "exampleConfigFiles": [
1067
+ "rustfmt.toml"
1068
+ ],
1069
+ "exampleTools": [
1070
+ "rustfmt",
1071
+ "cargo-release"
1072
+ ],
1073
+ "notes": "Rust rarely has auto-generated source files, but if using tools that generate Rust code, exclude those directories in rustfmt.toml. CHANGELOG.md isn't checked by rustfmt (it only checks .rs files).",
1074
+ "verification": "Run 'cargo fmt --check' and confirm it passes after releases."
1075
+ },
1076
+ "typescript-js": {
1077
+ "exampleConfigFiles": [
1078
+ ".prettierignore",
1079
+ ".releaserc.json"
1080
+ ],
1081
+ "exampleTools": [
1082
+ "prettier",
1083
+ "semantic-release"
1084
+ ],
1085
+ "notes": "Add CHANGELOG.md and package-lock.json to .prettierignore. These files are auto-generated by semantic-release and npm respectively. Without this exclusion, format:check fails after releases because the generated format differs from Prettier's expected style. Document each exclusion with a comment explaining it's auto-generated.",
1086
+ "requiredFiles": [
1087
+ ".prettierignore"
1088
+ ],
1089
+ "verification": "Run 'npm run format:check' and confirm CHANGELOG.md is not checked. Review .prettierignore and confirm auto-generated files are listed with explanatory comments."
1090
+ }
1091
+ }
1092
+ },
1004
1093
  {
1005
1094
  "appliesTo": {
1006
1095
  "stacks": [
@@ -243,6 +243,29 @@
243
243
  "verification": "Run the guard and confirm it fails when version lines change in pyproject.toml or setup.cfg."
244
244
  }
245
245
  },
246
+ {
247
+ "ciHints": {
248
+ "azure-devops": {
249
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
250
+ "stage": "quality"
251
+ }
252
+ },
253
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
254
+ "id": "release-artifact-exclusion",
255
+ "label": "Release Artifact Formatter Exclusion",
256
+ "stack": {
257
+ "exampleConfigFiles": [
258
+ "pyproject.toml"
259
+ ],
260
+ "exampleTools": [
261
+ "black",
262
+ "ruff",
263
+ "bumpversion"
264
+ ],
265
+ "notes": "In pyproject.toml [tool.black] or [tool.ruff], add extend-exclude patterns for auto-generated files like CHANGELOG.md. Some versioning tools generate or modify files that should not be reformatted.",
266
+ "verification": "Run 'black --check .' or 'ruff format --check' and confirm generated files are excluded."
267
+ }
268
+ },
246
269
  {
247
270
  "ciHints": {
248
271
  "azure-devops": {
@@ -243,6 +243,29 @@
243
243
  "verification": "Run the guard and confirm it fails when version lines change in pyproject.toml or setup.cfg."
244
244
  }
245
245
  },
246
+ {
247
+ "ciHints": {
248
+ "github-actions": {
249
+ "job": "ci",
250
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
251
+ }
252
+ },
253
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
254
+ "id": "release-artifact-exclusion",
255
+ "label": "Release Artifact Formatter Exclusion",
256
+ "stack": {
257
+ "exampleConfigFiles": [
258
+ "pyproject.toml"
259
+ ],
260
+ "exampleTools": [
261
+ "black",
262
+ "ruff",
263
+ "bumpversion"
264
+ ],
265
+ "notes": "In pyproject.toml [tool.black] or [tool.ruff], add extend-exclude patterns for auto-generated files like CHANGELOG.md. Some versioning tools generate or modify files that should not be reformatted.",
266
+ "verification": "Run 'black --check .' or 'ruff format --check' and confirm generated files are excluded."
267
+ }
268
+ },
246
269
  {
247
270
  "ciHints": {
248
271
  "github-actions": {
@@ -270,6 +270,33 @@
270
270
  "verification": "Run the guard and confirm it fails when version lines change in pyproject.toml or setup.cfg."
271
271
  }
272
272
  },
273
+ {
274
+ "ciHints": {
275
+ "azure-devops": {
276
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
277
+ "stage": "quality"
278
+ },
279
+ "github-actions": {
280
+ "job": "ci",
281
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
282
+ }
283
+ },
284
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
285
+ "id": "release-artifact-exclusion",
286
+ "label": "Release Artifact Formatter Exclusion",
287
+ "stack": {
288
+ "exampleConfigFiles": [
289
+ "pyproject.toml"
290
+ ],
291
+ "exampleTools": [
292
+ "black",
293
+ "ruff",
294
+ "bumpversion"
295
+ ],
296
+ "notes": "In pyproject.toml [tool.black] or [tool.ruff], add extend-exclude patterns for auto-generated files like CHANGELOG.md. Some versioning tools generate or modify files that should not be reformatted.",
297
+ "verification": "Run 'black --check .' or 'ruff format --check' and confirm generated files are excluded."
298
+ }
299
+ },
273
300
  {
274
301
  "ciHints": {
275
302
  "azure-devops": {
@@ -234,6 +234,28 @@
234
234
  "verification": "Run the guard and confirm it fails when Cargo.toml version changes."
235
235
  }
236
236
  },
237
+ {
238
+ "ciHints": {
239
+ "azure-devops": {
240
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
241
+ "stage": "quality"
242
+ }
243
+ },
244
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
245
+ "id": "release-artifact-exclusion",
246
+ "label": "Release Artifact Formatter Exclusion",
247
+ "stack": {
248
+ "exampleConfigFiles": [
249
+ "rustfmt.toml"
250
+ ],
251
+ "exampleTools": [
252
+ "rustfmt",
253
+ "cargo-release"
254
+ ],
255
+ "notes": "Rust rarely has auto-generated source files, but if using tools that generate Rust code, exclude those directories in rustfmt.toml. CHANGELOG.md isn't checked by rustfmt (it only checks .rs files).",
256
+ "verification": "Run 'cargo fmt --check' and confirm it passes after releases."
257
+ }
258
+ },
237
259
  {
238
260
  "ciHints": {
239
261
  "azure-devops": {
@@ -234,6 +234,28 @@
234
234
  "verification": "Run the guard and confirm it fails when Cargo.toml version changes."
235
235
  }
236
236
  },
237
+ {
238
+ "ciHints": {
239
+ "github-actions": {
240
+ "job": "ci",
241
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
242
+ }
243
+ },
244
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
245
+ "id": "release-artifact-exclusion",
246
+ "label": "Release Artifact Formatter Exclusion",
247
+ "stack": {
248
+ "exampleConfigFiles": [
249
+ "rustfmt.toml"
250
+ ],
251
+ "exampleTools": [
252
+ "rustfmt",
253
+ "cargo-release"
254
+ ],
255
+ "notes": "Rust rarely has auto-generated source files, but if using tools that generate Rust code, exclude those directories in rustfmt.toml. CHANGELOG.md isn't checked by rustfmt (it only checks .rs files).",
256
+ "verification": "Run 'cargo fmt --check' and confirm it passes after releases."
257
+ }
258
+ },
237
259
  {
238
260
  "ciHints": {
239
261
  "github-actions": {
@@ -261,6 +261,32 @@
261
261
  "verification": "Run the guard and confirm it fails when Cargo.toml version changes."
262
262
  }
263
263
  },
264
+ {
265
+ "ciHints": {
266
+ "azure-devops": {
267
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
268
+ "stage": "quality"
269
+ },
270
+ "github-actions": {
271
+ "job": "ci",
272
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
273
+ }
274
+ },
275
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
276
+ "id": "release-artifact-exclusion",
277
+ "label": "Release Artifact Formatter Exclusion",
278
+ "stack": {
279
+ "exampleConfigFiles": [
280
+ "rustfmt.toml"
281
+ ],
282
+ "exampleTools": [
283
+ "rustfmt",
284
+ "cargo-release"
285
+ ],
286
+ "notes": "Rust rarely has auto-generated source files, but if using tools that generate Rust code, exclude those directories in rustfmt.toml. CHANGELOG.md isn't checked by rustfmt (it only checks .rs files).",
287
+ "verification": "Run 'cargo fmt --check' and confirm it passes after releases."
288
+ }
289
+ },
264
290
  {
265
291
  "ciHints": {
266
292
  "azure-devops": {
@@ -256,6 +256,32 @@
256
256
  "verification": "Run the guard with the PR base ref (for example, origin/main) and confirm it fails when package.json version changes."
257
257
  }
258
258
  },
259
+ {
260
+ "ciHints": {
261
+ "azure-devops": {
262
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
263
+ "stage": "quality"
264
+ }
265
+ },
266
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
267
+ "id": "release-artifact-exclusion",
268
+ "label": "Release Artifact Formatter Exclusion",
269
+ "stack": {
270
+ "exampleConfigFiles": [
271
+ ".prettierignore",
272
+ ".releaserc.json"
273
+ ],
274
+ "exampleTools": [
275
+ "prettier",
276
+ "semantic-release"
277
+ ],
278
+ "notes": "Add CHANGELOG.md and package-lock.json to .prettierignore. These files are auto-generated by semantic-release and npm respectively. Without this exclusion, format:check fails after releases because the generated format differs from Prettier's expected style. Document each exclusion with a comment explaining it's auto-generated.",
279
+ "requiredFiles": [
280
+ ".prettierignore"
281
+ ],
282
+ "verification": "Run 'npm run format:check' and confirm CHANGELOG.md is not checked. Review .prettierignore and confirm auto-generated files are listed with explanatory comments."
283
+ }
284
+ },
259
285
  {
260
286
  "ciHints": {
261
287
  "azure-devops": {
@@ -256,6 +256,32 @@
256
256
  "verification": "Run the guard with the PR base ref (for example, origin/main) and confirm it fails when package.json version changes."
257
257
  }
258
258
  },
259
+ {
260
+ "ciHints": {
261
+ "github-actions": {
262
+ "job": "ci",
263
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
264
+ }
265
+ },
266
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
267
+ "id": "release-artifact-exclusion",
268
+ "label": "Release Artifact Formatter Exclusion",
269
+ "stack": {
270
+ "exampleConfigFiles": [
271
+ ".prettierignore",
272
+ ".releaserc.json"
273
+ ],
274
+ "exampleTools": [
275
+ "prettier",
276
+ "semantic-release"
277
+ ],
278
+ "notes": "Add CHANGELOG.md and package-lock.json to .prettierignore. These files are auto-generated by semantic-release and npm respectively. Without this exclusion, format:check fails after releases because the generated format differs from Prettier's expected style. Document each exclusion with a comment explaining it's auto-generated.",
279
+ "requiredFiles": [
280
+ ".prettierignore"
281
+ ],
282
+ "verification": "Run 'npm run format:check' and confirm CHANGELOG.md is not checked. Review .prettierignore and confirm auto-generated files are listed with explanatory comments."
283
+ }
284
+ },
259
285
  {
260
286
  "ciHints": {
261
287
  "github-actions": {
@@ -283,6 +283,36 @@
283
283
  "verification": "Run the guard with the PR base ref (for example, origin/main) and confirm it fails when package.json version changes."
284
284
  }
285
285
  },
286
+ {
287
+ "ciHints": {
288
+ "azure-devops": {
289
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts.",
290
+ "stage": "quality"
291
+ },
292
+ "github-actions": {
293
+ "job": "ci",
294
+ "notes": "Ensure format:check step uses ignore file that excludes release artifacts."
295
+ }
296
+ },
297
+ "description": "Exclude auto-generated release artifacts (CHANGELOG.md, package-lock.json, etc.) from code formatters to prevent CI failures. Release automation tools generate files that may not conform to your formatter's style, causing format checks to fail on subsequent CI runs.",
298
+ "id": "release-artifact-exclusion",
299
+ "label": "Release Artifact Formatter Exclusion",
300
+ "stack": {
301
+ "exampleConfigFiles": [
302
+ ".prettierignore",
303
+ ".releaserc.json"
304
+ ],
305
+ "exampleTools": [
306
+ "prettier",
307
+ "semantic-release"
308
+ ],
309
+ "notes": "Add CHANGELOG.md and package-lock.json to .prettierignore. These files are auto-generated by semantic-release and npm respectively. Without this exclusion, format:check fails after releases because the generated format differs from Prettier's expected style. Document each exclusion with a comment explaining it's auto-generated.",
310
+ "requiredFiles": [
311
+ ".prettierignore"
312
+ ],
313
+ "verification": "Run 'npm run format:check' and confirm CHANGELOG.md is not checked. Review .prettierignore and confirm auto-generated files are listed with explanatory comments."
314
+ }
315
+ },
286
316
  {
287
317
  "ciHints": {
288
318
  "azure-devops": {
package/dist/index.cjs CHANGED
@@ -41,7 +41,7 @@ var import_node_fs = require("fs");
41
41
  var import_node_path = require("path");
42
42
 
43
43
  // src/version.ts
44
- var STANDARDS_VERSION = "5.0.0";
44
+ var STANDARDS_VERSION = "5.1.0";
45
45
  var STANDARDS_SCHEMA_VERSION = 5;
46
46
 
47
47
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '5.0.0';\nexport const STANDARDS_SCHEMA_VERSION = 5;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ADZ9D,sBAA8B;AAC9B,qBAA6B;AAC7B,uBAA8B;;;AEOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;AFQxC,IAAMA,kBAAa,+BAAc,aAAe;AAChD,IAAM,gBAAY,0BAAQA,WAAU;AAKpC,IAAM,YAAY,UAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,gBACd,uBAAK,WAAW,MAAM,QAAQ,QAC9B,uBAAK,WAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,eAAW,uBAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,eAAW,uBAAK,WAAW,IAAI;AACrC,SAAO,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename"]}
1
+ {"version":3,"sources":["../src/index.ts","../node_modules/tsup/assets/cjs_shims.js","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '5.1.0';\nexport const STANDARDS_SCHEMA_VERSION = 5;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ADZ9D,sBAA8B;AAC9B,qBAA6B;AAC7B,uBAA8B;;;AEOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;AFQxC,IAAMA,kBAAa,+BAAc,aAAe;AAChD,IAAM,gBAAY,0BAAQA,WAAU;AAKpC,IAAM,YAAY,UAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,gBACd,uBAAK,WAAW,MAAM,QAAQ,QAC9B,uBAAK,WAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,eAAW,uBAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,eAAW,uBAAK,WAAW,IAAI;AACrC,SAAO,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename"]}
package/dist/index.d.cts CHANGED
@@ -156,7 +156,7 @@ interface StackChecklistJson {
156
156
  * Consumers should import from here instead of package.json to avoid
157
157
  * ESM/CJS interop issues.
158
158
  */
159
- declare const STANDARDS_VERSION = "5.0.0";
159
+ declare const STANDARDS_VERSION = "5.1.0";
160
160
  declare const STANDARDS_SCHEMA_VERSION = 5;
161
161
 
162
162
  /** Load the master spec JSON from the packaged dist directory */
package/dist/index.d.ts CHANGED
@@ -156,7 +156,7 @@ interface StackChecklistJson {
156
156
  * Consumers should import from here instead of package.json to avoid
157
157
  * ESM/CJS interop issues.
158
158
  */
159
- declare const STANDARDS_VERSION = "5.0.0";
159
+ declare const STANDARDS_VERSION = "5.1.0";
160
160
  declare const STANDARDS_SCHEMA_VERSION = 5;
161
161
 
162
162
  /** Load the master spec JSON from the packaged dist directory */
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { readFileSync } from "fs";
4
4
  import { join, dirname } from "path";
5
5
 
6
6
  // src/version.ts
7
- var STANDARDS_VERSION = "5.0.0";
7
+ var STANDARDS_VERSION = "5.1.0";
8
8
  var STANDARDS_SCHEMA_VERSION = 5;
9
9
 
10
10
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '5.0.0';\nexport const STANDARDS_SCHEMA_VERSION = 5;\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAM,eAAe;;;ACOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;ADQxC,IAAMA,cAAa,cAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQD,WAAU;AAKpC,IAAM,YAAYC,WAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,YACd,KAAKA,YAAW,MAAM,QAAQ,IAC9B,KAAKA,YAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,WAAW,KAAK,WAAW,IAAI;AACrC,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename","__dirname"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/version.ts"],"sourcesContent":["import { fileURLToPath } from \"node:url\";\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport type {\n MasterJson,\n StackChecklistJson,\n StackId,\n CiSystem,\n} from \"./types.js\";\nimport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION } from \"./version.js\";\n\n// Re-export types for consumers\nexport type { MasterJson, StackChecklistJson, StackId, CiSystem };\n\n// Re-export version info (stable API contract)\nexport { STANDARDS_VERSION, STANDARDS_SCHEMA_VERSION };\n\n// ESM equivalent of __dirname\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n// Path to config directory:\n// - When running from src/ (dev/test): use repo root config/\n// - When running from dist/ (installed): use dist/config/\nconst isDevMode = __dirname.includes(\"src\");\nconst configDir = isDevMode\n ? join(__dirname, \"..\", \"config\")\n : join(__dirname, \"config\");\n\n/** Load the master spec JSON from the packaged dist directory */\nexport function loadMasterSpec(): MasterJson {\n const filePath = join(configDir, \"standards.json\");\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** Load a stack-specific checklist (optionally filtered by CI system) */\nexport function loadBaseline(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n const suffix = ci ? `.${ci}` : \"\";\n const file = `standards.${stack}${suffix}.json`;\n const filePath = join(configDir, file);\n return JSON.parse(readFileSync(filePath, \"utf8\"));\n}\n\n/** List all supported stacks (derived from the master spec) */\nexport function listSupportedStacks(): readonly StackId[] {\n const spec = loadMasterSpec();\n return Object.keys(spec.stacks) as StackId[];\n}\n\n/** List all supported CI systems (derived from the master spec) */\nexport function listSupportedCiSystems(): readonly CiSystem[] {\n const spec = loadMasterSpec();\n return spec.ciSystems as CiSystem[];\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadBaseline - loads stack-specific standards checklist.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getStandards(\n stack: StackId,\n ci?: CiSystem,\n): StackChecklistJson {\n return loadBaseline(stack, ci);\n}\n\n/**\n * PUBLIC API CONTRACT (semver-governed)\n * Alias for loadMasterSpec - loads the master standards schema.\n * Breaking changes to this function signature require a major version bump.\n */\nexport function getSchema(): MasterJson {\n return loadMasterSpec();\n}\n","/**\n * AUTO-GENERATED at build time by scripts/build.ts\n * DO NOT EDIT MANUALLY\n *\n * This module provides version information for the repo-standards package.\n * Consumers should import from here instead of package.json to avoid\n * ESM/CJS interop issues.\n */\n\nexport const STANDARDS_VERSION = '5.1.0';\nexport const STANDARDS_SCHEMA_VERSION = 5;\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,SAAS,MAAM,eAAe;;;ACOvB,IAAM,oBAAoB;AAC1B,IAAM,2BAA2B;;;ADQxC,IAAMA,cAAa,cAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQD,WAAU;AAKpC,IAAM,YAAYC,WAAU,SAAS,KAAK;AAC1C,IAAM,YAAY,YACd,KAAKA,YAAW,MAAM,QAAQ,IAC9B,KAAKA,YAAW,QAAQ;AAGrB,SAAS,iBAA6B;AAC3C,QAAM,WAAW,KAAK,WAAW,gBAAgB;AACjD,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,aACd,OACA,IACoB;AACpB,QAAM,SAAS,KAAK,IAAI,EAAE,KAAK;AAC/B,QAAM,OAAO,aAAa,KAAK,GAAG,MAAM;AACxC,QAAM,WAAW,KAAK,WAAW,IAAI;AACrC,SAAO,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AAClD;AAGO,SAAS,sBAA0C;AACxD,QAAM,OAAO,eAAe;AAC5B,SAAO,OAAO,KAAK,KAAK,MAAM;AAChC;AAGO,SAAS,yBAA8C;AAC5D,QAAM,OAAO,eAAe;AAC5B,SAAO,KAAK;AACd;AAOO,SAAS,aACd,OACA,IACoB;AACpB,SAAO,aAAa,OAAO,EAAE;AAC/B;AAOO,SAAS,YAAwB;AACtC,SAAO,eAAe;AACxB;","names":["__filename","__dirname"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oddessentials/repo-standards",
3
3
  "private": false,
4
- "version": "5.1.0",
4
+ "version": "5.2.0",
5
5
  "description": "Standards and CI filtering utilities for multi-stack repository governance.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Syncs standards.json schema version (and README references) to the provided
3
+ * semantic-release version. Intended for @semantic-release/exec prepare step.
4
+ */
5
+ const fs = require("fs");
6
+ const path = require("path");
7
+
8
+ const rootDir = process.cwd();
9
+ const pkgPath = path.join(rootDir, "package.json");
10
+ const standardsPath = path.join(rootDir, "config", "standards.json");
11
+ const readmePath = path.join(rootDir, "README.md");
12
+
13
+ const providedVersion = process.argv[2];
14
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
15
+ const standards = JSON.parse(fs.readFileSync(standardsPath, "utf8"));
16
+
17
+ const versionSource = providedVersion ?? pkg.version;
18
+ const nextMajor = parseInt(versionSource.split(".")[0], 10);
19
+
20
+ if (Number.isNaN(nextMajor)) {
21
+ console.error(
22
+ `[sync-standards] Unable to parse major version from ${versionSource}`,
23
+ );
24
+ process.exit(1);
25
+ }
26
+
27
+ if (nextMajor <= standards.version) {
28
+ console.log(
29
+ `[sync-standards] standards.json version ${standards.version} already >= ${nextMajor}; no update needed.`,
30
+ );
31
+ process.exit(0);
32
+ }
33
+
34
+ standards.version = nextMajor;
35
+ fs.writeFileSync(standardsPath, JSON.stringify(standards, null, 2) + "\n");
36
+ console.log(
37
+ `[sync-standards] Updated standards.json schema version to ${nextMajor}`,
38
+ );
39
+
40
+ if (!fs.existsSync(readmePath)) {
41
+ console.warn("[sync-standards] README.md not found; skipping README update");
42
+ process.exit(0);
43
+ }
44
+
45
+ let readme = fs.readFileSync(readmePath, "utf8");
46
+ const currentLineRegex = /version\s+—\s+schema version \(currently `\d+`\)/;
47
+ if (currentLineRegex.test(readme)) {
48
+ readme = readme.replace(
49
+ currentLineRegex,
50
+ `version — schema version (currently \`${nextMajor}\`)`,
51
+ );
52
+ } else {
53
+ console.warn(
54
+ "[sync-standards] README current schema version line not found; skipping update",
55
+ );
56
+ }
57
+
58
+ const versionEntry = `- \`${nextMajor}\` — Schema version aligned to package major version ${nextMajor}.`;
59
+ if (!readme.includes(`- \`${nextMajor}\` —`)) {
60
+ const anchor =
61
+ "Consumers should ignore unknown fields for forward compatibility.";
62
+ if (readme.includes(anchor)) {
63
+ readme = readme.replace(anchor, `${versionEntry}\n\n${anchor}`);
64
+ } else {
65
+ console.warn(
66
+ "[sync-standards] README schema version list anchor not found; skipping list update",
67
+ );
68
+ }
69
+ }
70
+
71
+ fs.writeFileSync(readmePath, readme);
72
+ console.log("[sync-standards] Updated README schema version references");
@@ -10,6 +10,7 @@ import path from "node:path";
10
10
  const rootDir = process.cwd();
11
11
  const configPath = path.join(rootDir, "config", "standards.json");
12
12
  const schemaPath = path.join(rootDir, "config", "standards.schema.json");
13
+ const readmePath = path.join(rootDir, "README.md");
13
14
 
14
15
  interface ValidationResult {
15
16
  valid: boolean;
@@ -53,6 +54,42 @@ interface Config {
53
54
  };
54
55
  }
55
56
 
57
+ /**
58
+ * Validate README schema version references match standards.json version
59
+ */
60
+ function validateReadmeSchemaVersion(
61
+ config: Config,
62
+ readmeRaw?: string,
63
+ ): ValidationResult {
64
+ if (!readmeRaw) {
65
+ return {
66
+ valid: false,
67
+ errors: ["README.md not provided for version consistency check"],
68
+ };
69
+ }
70
+
71
+ const errors: string[] = [];
72
+ const actualVersion = config.version;
73
+
74
+ const currentMatch = readmeRaw.match(/version.*\(currently `(\d+)`\)/i);
75
+ if (!currentMatch) {
76
+ errors.push("README.md missing current schema version reference");
77
+ } else if (Number(currentMatch[1]) !== actualVersion) {
78
+ errors.push(
79
+ `README.md current schema version (${currentMatch[1]}) does not match standards.json (${actualVersion})`,
80
+ );
81
+ }
82
+
83
+ const listPattern = new RegExp(`-\\s*\`${actualVersion}\`\\s*—`);
84
+ if (!listPattern.test(readmeRaw)) {
85
+ errors.push(
86
+ `README.md schema version list does not include current version ${actualVersion}`,
87
+ );
88
+ }
89
+
90
+ return { valid: errors.length === 0, errors };
91
+ }
92
+
56
93
  /**
57
94
  * Validate config against JSON Schema using Ajv
58
95
  */
@@ -254,6 +291,7 @@ export function normalizeConfig(config: unknown): string {
254
291
  export function validateStandardsConfig(
255
292
  configRaw: string,
256
293
  schemaRaw: string,
294
+ readmeRaw?: string,
257
295
  ): ValidationResult {
258
296
  let config: Config;
259
297
  let schema: unknown;
@@ -281,6 +319,7 @@ export function validateStandardsConfig(
281
319
  validateCiHintKeys(config),
282
320
  validateCoverageThreshold(config),
283
321
  validateExecutionStageCoverage(config),
322
+ validateReadmeSchemaVersion(config, readmeRaw),
284
323
  ];
285
324
 
286
325
  const allErrors = results.flatMap((r) => r.errors);
@@ -304,10 +343,16 @@ export function validateStandardsSchema(): void {
304
343
  process.exit(1);
305
344
  }
306
345
 
346
+ if (!fs.existsSync(readmePath)) {
347
+ console.error(`README file not found: ${readmePath}`);
348
+ process.exit(1);
349
+ }
350
+
307
351
  const configRaw = fs.readFileSync(configPath, "utf8");
308
352
  const schemaRaw = fs.readFileSync(schemaPath, "utf8");
353
+ const readmeRaw = fs.readFileSync(readmePath, "utf8");
309
354
 
310
- const result = validateStandardsConfig(configRaw, schemaRaw);
355
+ const result = validateStandardsConfig(configRaw, schemaRaw, readmeRaw);
311
356
 
312
357
  if (!result.valid) {
313
358
  console.error("Schema validation failed:");
@@ -324,6 +369,7 @@ export function validateStandardsSchema(): void {
324
369
  console.log("✓ All ciHints keys are valid ciSystems");
325
370
  console.log("✓ Coverage threshold semantics are valid");
326
371
  console.log("✓ All items have valid executionStage");
372
+ console.log("✓ README schema version references are aligned");
327
373
  }
328
374
 
329
375
  // CLI entry point