@ploaness/governance 1.0.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.
Files changed (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/access-boundary.d.ts +41 -0
  4. package/dist/access-boundary.d.ts.map +1 -0
  5. package/dist/access-boundary.js +26 -0
  6. package/dist/access-boundary.js.map +1 -0
  7. package/dist/agent-references.d.ts +12 -0
  8. package/dist/agent-references.d.ts.map +1 -0
  9. package/dist/agent-references.js +53 -0
  10. package/dist/agent-references.js.map +1 -0
  11. package/dist/architecture-layers.d.ts +11 -0
  12. package/dist/architecture-layers.d.ts.map +1 -0
  13. package/dist/architecture-layers.js +47 -0
  14. package/dist/architecture-layers.js.map +1 -0
  15. package/dist/asset-policy.d.ts +138 -0
  16. package/dist/asset-policy.d.ts.map +1 -0
  17. package/dist/asset-policy.js +312 -0
  18. package/dist/asset-policy.js.map +1 -0
  19. package/dist/banned-typography.d.ts +13 -0
  20. package/dist/banned-typography.d.ts.map +1 -0
  21. package/dist/banned-typography.js +78 -0
  22. package/dist/banned-typography.js.map +1 -0
  23. package/dist/bundle-budget.d.ts +16 -0
  24. package/dist/bundle-budget.d.ts.map +1 -0
  25. package/dist/bundle-budget.js +37 -0
  26. package/dist/bundle-budget.js.map +1 -0
  27. package/dist/commit-message.d.ts +37 -0
  28. package/dist/commit-message.d.ts.map +1 -0
  29. package/dist/commit-message.js +144 -0
  30. package/dist/commit-message.js.map +1 -0
  31. package/dist/config-references.d.ts +17 -0
  32. package/dist/config-references.d.ts.map +1 -0
  33. package/dist/config-references.js +54 -0
  34. package/dist/config-references.js.map +1 -0
  35. package/dist/container-failure.d.ts +40 -0
  36. package/dist/container-failure.d.ts.map +1 -0
  37. package/dist/container-failure.js +154 -0
  38. package/dist/container-failure.js.map +1 -0
  39. package/dist/container-files.d.ts +36 -0
  40. package/dist/container-files.d.ts.map +1 -0
  41. package/dist/container-files.js +74 -0
  42. package/dist/container-files.js.map +1 -0
  43. package/dist/container-freshness.d.ts +102 -0
  44. package/dist/container-freshness.d.ts.map +1 -0
  45. package/dist/container-freshness.js +129 -0
  46. package/dist/container-freshness.js.map +1 -0
  47. package/dist/dependency-freshness.d.ts +129 -0
  48. package/dist/dependency-freshness.d.ts.map +1 -0
  49. package/dist/dependency-freshness.js +161 -0
  50. package/dist/dependency-freshness.js.map +1 -0
  51. package/dist/doc-blocks.d.ts +13 -0
  52. package/dist/doc-blocks.d.ts.map +1 -0
  53. package/dist/doc-blocks.js +75 -0
  54. package/dist/doc-blocks.js.map +1 -0
  55. package/dist/document-references.d.ts +44 -0
  56. package/dist/document-references.d.ts.map +1 -0
  57. package/dist/document-references.js +94 -0
  58. package/dist/document-references.js.map +1 -0
  59. package/dist/editorconfig-policy.d.ts +24 -0
  60. package/dist/editorconfig-policy.d.ts.map +1 -0
  61. package/dist/editorconfig-policy.js +106 -0
  62. package/dist/editorconfig-policy.js.map +1 -0
  63. package/dist/environment-files.d.ts +42 -0
  64. package/dist/environment-files.d.ts.map +1 -0
  65. package/dist/environment-files.js +76 -0
  66. package/dist/environment-files.js.map +1 -0
  67. package/dist/file-roles.d.ts +39 -0
  68. package/dist/file-roles.d.ts.map +1 -0
  69. package/dist/file-roles.js +82 -0
  70. package/dist/file-roles.js.map +1 -0
  71. package/dist/generated-denial.d.ts +42 -0
  72. package/dist/generated-denial.d.ts.map +1 -0
  73. package/dist/generated-denial.js +87 -0
  74. package/dist/generated-denial.js.map +1 -0
  75. package/dist/history-policy.d.ts +32 -0
  76. package/dist/history-policy.d.ts.map +1 -0
  77. package/dist/history-policy.js +50 -0
  78. package/dist/history-policy.js.map +1 -0
  79. package/dist/image-assets.d.ts +14 -0
  80. package/dist/image-assets.d.ts.map +1 -0
  81. package/dist/image-assets.js +205 -0
  82. package/dist/image-assets.js.map +1 -0
  83. package/dist/index.d.ts +49 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +53 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/install-policy.d.ts +35 -0
  88. package/dist/install-policy.d.ts.map +1 -0
  89. package/dist/install-policy.js +61 -0
  90. package/dist/install-policy.js.map +1 -0
  91. package/dist/json-shapes.d.ts +86 -0
  92. package/dist/json-shapes.d.ts.map +1 -0
  93. package/dist/json-shapes.js +124 -0
  94. package/dist/json-shapes.js.map +1 -0
  95. package/dist/license-allowlist.d.ts +15 -0
  96. package/dist/license-allowlist.d.ts.map +1 -0
  97. package/dist/license-allowlist.js +157 -0
  98. package/dist/license-allowlist.js.map +1 -0
  99. package/dist/network-policy.d.ts +69 -0
  100. package/dist/network-policy.d.ts.map +1 -0
  101. package/dist/network-policy.js +173 -0
  102. package/dist/network-policy.js.map +1 -0
  103. package/dist/paired-assets.d.ts +34 -0
  104. package/dist/paired-assets.d.ts.map +1 -0
  105. package/dist/paired-assets.js +63 -0
  106. package/dist/paired-assets.js.map +1 -0
  107. package/dist/payload-access.d.ts +9 -0
  108. package/dist/payload-access.d.ts.map +1 -0
  109. package/dist/payload-access.js +168 -0
  110. package/dist/payload-access.js.map +1 -0
  111. package/dist/payload-policy.d.ts +18 -0
  112. package/dist/payload-policy.d.ts.map +1 -0
  113. package/dist/payload-policy.js +124 -0
  114. package/dist/payload-policy.js.map +1 -0
  115. package/dist/payload-source.d.ts +29 -0
  116. package/dist/payload-source.d.ts.map +1 -0
  117. package/dist/payload-source.js +84 -0
  118. package/dist/payload-source.js.map +1 -0
  119. package/dist/release-age.d.ts +23 -0
  120. package/dist/release-age.d.ts.map +1 -0
  121. package/dist/release-age.js +38 -0
  122. package/dist/release-age.js.map +1 -0
  123. package/dist/request-limits.d.ts +39 -0
  124. package/dist/request-limits.d.ts.map +1 -0
  125. package/dist/request-limits.js +57 -0
  126. package/dist/request-limits.js.map +1 -0
  127. package/dist/run-plan.d.ts +32 -0
  128. package/dist/run-plan.d.ts.map +1 -0
  129. package/dist/run-plan.js +43 -0
  130. package/dist/run-plan.js.map +1 -0
  131. package/dist/run-policy.d.ts +32 -0
  132. package/dist/run-policy.d.ts.map +1 -0
  133. package/dist/run-policy.js +37 -0
  134. package/dist/run-policy.js.map +1 -0
  135. package/dist/secret-policy.d.ts +13 -0
  136. package/dist/secret-policy.d.ts.map +1 -0
  137. package/dist/secret-policy.js +69 -0
  138. package/dist/secret-policy.js.map +1 -0
  139. package/dist/settings-layering.d.ts +45 -0
  140. package/dist/settings-layering.d.ts.map +1 -0
  141. package/dist/settings-layering.js +134 -0
  142. package/dist/settings-layering.js.map +1 -0
  143. package/dist/settings.d.ts +238 -0
  144. package/dist/settings.d.ts.map +1 -0
  145. package/dist/settings.js +378 -0
  146. package/dist/settings.js.map +1 -0
  147. package/dist/skill-manifest.d.ts +18 -0
  148. package/dist/skill-manifest.d.ts.map +1 -0
  149. package/dist/skill-manifest.js +125 -0
  150. package/dist/skill-manifest.js.map +1 -0
  151. package/dist/source-text.d.ts +83 -0
  152. package/dist/source-text.d.ts.map +1 -0
  153. package/dist/source-text.js +310 -0
  154. package/dist/source-text.js.map +1 -0
  155. package/dist/suppression-ceiling.d.ts +48 -0
  156. package/dist/suppression-ceiling.d.ts.map +1 -0
  157. package/dist/suppression-ceiling.js +115 -0
  158. package/dist/suppression-ceiling.js.map +1 -0
  159. package/dist/tailwind-tokens.d.ts +16 -0
  160. package/dist/tailwind-tokens.d.ts.map +1 -0
  161. package/dist/tailwind-tokens.js +70 -0
  162. package/dist/tailwind-tokens.js.map +1 -0
  163. package/dist/text-escapes.d.ts +7 -0
  164. package/dist/text-escapes.d.ts.map +1 -0
  165. package/dist/text-escapes.js +14 -0
  166. package/dist/text-escapes.js.map +1 -0
  167. package/dist/toolchain-pins.d.ts +42 -0
  168. package/dist/toolchain-pins.d.ts.map +1 -0
  169. package/dist/toolchain-pins.js +99 -0
  170. package/dist/toolchain-pins.js.map +1 -0
  171. package/dist/url-safety.d.ts +12 -0
  172. package/dist/url-safety.d.ts.map +1 -0
  173. package/dist/url-safety.js +58 -0
  174. package/dist/url-safety.js.map +1 -0
  175. package/dist/version-policy.d.ts +99 -0
  176. package/dist/version-policy.d.ts.map +1 -0
  177. package/dist/version-policy.js +306 -0
  178. package/dist/version-policy.js.map +1 -0
  179. package/dist/vulnerability-policy.d.ts +66 -0
  180. package/dist/vulnerability-policy.d.ts.map +1 -0
  181. package/dist/vulnerability-policy.js +106 -0
  182. package/dist/vulnerability-policy.js.map +1 -0
  183. package/dist/wiring-policy.d.ts +226 -0
  184. package/dist/wiring-policy.d.ts.map +1 -0
  185. package/dist/wiring-policy.js +458 -0
  186. package/dist/wiring-policy.js.map +1 -0
  187. package/dist/wiring-violation.d.ts +6 -0
  188. package/dist/wiring-violation.d.ts.map +1 -0
  189. package/dist/wiring-violation.js +8 -0
  190. package/dist/wiring-violation.js.map +1 -0
  191. package/dist/workspace-policy.d.ts +177 -0
  192. package/dist/workspace-policy.d.ts.map +1 -0
  193. package/dist/workspace-policy.js +228 -0
  194. package/dist/workspace-policy.js.map +1 -0
  195. package/dist/yaml-blocks.d.ts +43 -0
  196. package/dist/yaml-blocks.d.ts.map +1 -0
  197. package/dist/yaml-blocks.js +87 -0
  198. package/dist/yaml-blocks.js.map +1 -0
  199. package/package.json +41 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-blocks.js","sourceRoot":"","sources":["../src/doc-blocks.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,iGAAiG;AACjG,EAAE;AACF,qGAAqG;AACrG,uGAAuG;AACvG,iGAAiG;AACjG,8FAA8F;AAC9F,qGAAqG;AACrG,WAAW;AACX,EAAE;AACF,kGAAkG;AAClG,iGAAiG;AACjG,sFAAsF;AAEtF,oGAAoG;AACpG,qGAAqG;AACrG,yCAAyC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAsB;IACtD,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;CACP,CAAA;AAED,MAAM,QAAQ,GAAW,KAAK,CAAA;AAC9B,MAAM,WAAW,GAAW,IAAI,CAAA;AAEhC,qGAAqG;AACrG,MAAM,aAAa,GAAW,CAAC,CAAC,CAAA;AAEhC,uEAAuE;AACvE,MAAM,UAAU,GAAW,CAAC,CAAA;AAa5B,MAAM,UAAU,GAAc,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;AAEjE,iGAAiG;AACjG,kGAAkG;AAClG,MAAM,iBAAiB,GAAG,CAAC,OAAe,EAAW,EAAE,CACrD,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AAEtD,MAAM,aAAa,GAAG,CAAC,KAAgB,EAAE,OAAe,EAAE,IAAY,EAAa,EAAE;IACnF,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAA;IACd,CAAC;IACD,OAAO,iBAAiB,CAAC,OAAO,CAAC;QAC/B,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE;QAC7E,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;AAC1C,CAAC,CAAA;AAED,MAAM,aAAa,GAAG,CAAC,KAAgB,EAAE,OAAe,EAAE,IAAY,EAAa,EAAE,CACnF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC3B,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE;IACzF,CAAC,CAAC,KAAK,CAAA;AAEX,uGAAuG;AACvG,sGAAsG;AACtG,0EAA0E;AAC1E,MAAM,SAAS,GAAG,CAAC,KAAwB,EAAuB,EAAE,CAClE,KAAK,CAAC,MAAM,CAAC,CAAC,KAAgB,EAAE,GAAW,EAAE,KAAa,EAAa,EAAE;IACvE,MAAM,OAAO,GAAW,GAAG,CAAC,IAAI,EAAE,CAAA;IAClC,MAAM,IAAI,GAAW,KAAK,GAAG,UAAU,CAAA;IACvC,OAAO,KAAK,CAAC,IAAI,KAAK,aAAa;QACjC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC;QACrC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;AACzC,CAAC,EAAE,UAAU,CAAC,CAAC,MAAM,CAAA;AAEvB,qGAAqG;AACrG,uGAAuG;AACvG,uEAAuE;AACvE,MAAM,iBAAiB,GAAG,CAAC,KAAwB,EAAE,OAAe,EAAW,EAAE;IAC/E,MAAM,IAAI,GAAuB,KAAK;SACnC,KAAK,CAAC,OAAO,CAAC;SACd,IAAI,CAAC,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC1D,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;AACtD,CAAC,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAuB,EAAE;IACzE,MAAM,KAAK,GAAsB,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1E,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAe,EAAW,EAAE,CAC1D,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CACxC,CAAA;AACH,CAAC,CAAA"}
@@ -0,0 +1,44 @@
1
+ /** A documentation reference that no longer resolves to a real script or file. */
2
+ export interface DocumentViolation {
3
+ readonly reference: string;
4
+ readonly kind: 'script' | 'path';
5
+ readonly reason: string;
6
+ }
7
+ /** Inputs for {@link findDocumentReferenceViolations}, with `isExistingFile` injected so the core stays pure. */
8
+ interface DocumentReferenceInputs {
9
+ readonly markdown: string;
10
+ readonly scriptNames: ReadonlySet<string>;
11
+ readonly isExistingFile: (relativePath: string) => boolean;
12
+ /**
13
+ * Words that look like a script name but are not one, so a mention of them is not rot. Under ploaness
14
+ * the gate identifiers (`knip`, `tests`, `build`) share a vocabulary with the old npm scripts they
15
+ * replaced, and documenting a gate must not be read as referencing a script that no longer exists.
16
+ */
17
+ readonly reservedWords: ReadonlySet<string>;
18
+ /**
19
+ * The dependency names this document may name a subpath of. A token beginning with one is a module
20
+ * SPECIFIER rather than a repository path, so it is not judged as a file.
21
+ */
22
+ readonly packageNames: ReadonlySet<string>;
23
+ }
24
+ /**
25
+ * Return every documentation reference that no longer resolves: a named script absent from
26
+ * package.json, or a full-path file that does not exist. An empty array means the docs are in sync.
27
+ */
28
+ export declare const findDocumentReferenceViolations: (inputs: DocumentReferenceInputs) => readonly DocumentViolation[];
29
+ /** One instruction file, paired with the member that owns it. */
30
+ export interface DocumentLocation {
31
+ /** Repo-relative path of the file. */
32
+ readonly file: string;
33
+ /** Repo-relative directory it belongs to, {@link ROOT_MEMBER_PATH} at the repository root. */
34
+ readonly directory: string;
35
+ }
36
+ /**
37
+ * Locate every agent instruction file this repository holds.
38
+ * @param memberPaths the governed members, repo-relative.
39
+ * @param isExistingFile whether a repo-relative path exists.
40
+ * @returns one entry per file present, the root's first, then each member's in the order given.
41
+ */
42
+ export declare const findAgentDocuments: (memberPaths: readonly string[], isExistingFile: (relativePath: string) => boolean) => readonly DocumentLocation[];
43
+ export {};
44
+ //# sourceMappingURL=document-references.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-references.d.ts","sourceRoot":"","sources":["../src/document-references.ts"],"names":[],"mappings":"AAYA,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,iHAAiH;AACjH,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IACzC,QAAQ,CAAC,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAA;IAC1D;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC3C;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAC3C;AAqDD;;;GAGG;AACH,eAAO,MAAM,+BAA+B,GAC1C,QAAQ,uBAAuB,KAC9B,SAAS,iBAAiB,EA4B5B,CAAA;AAgBD,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAKD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,aAAa,SAAS,MAAM,EAAE,EAC9B,gBAAgB,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,KAChD,SAAS,gBAAgB,EAOuD,CAAA"}
@@ -0,0 +1,94 @@
1
+ // Doc-rot policy: the pure logic that finds references in the agent docs (AGENTS.md, CLAUDE.md) which
2
+ // no longer match reality. The `docs` gate in packages/cli/src/checks/references.ts reads the files.
3
+ //
4
+ // Two reference kinds are validated, both chosen to be HIGH-SIGNAL and false-positive-free:
5
+ // 1. Script references - a backticked npm-script token (`lint:arch`, `verify:full`, `knip`, ...) or a
6
+ // `pnpm run <name>` invocation - must name a script that exists in package.json.
7
+ // 2. Path references - a backticked FULL repository path to a concrete file (contains `/` and a file
8
+ // extension) - must exist on disk. Directory/glob references (`src/access/**`) and bare filenames
9
+ // are deliberately NOT checked: docs legitimately mention not-yet-existing dirs (e.g. the
10
+ // "no src/migrations yet" note) and use shorthand, and flagging those would make the gate lie.
11
+ import { ROOT_MEMBER_PATH } from './workspace-policy.js';
12
+ const BACKTICK_TOKEN = /`[^`\n]+`/g;
13
+ const PNPM_RUN = /pnpm run [a-z][a-z0-9:_-]*/g;
14
+ const SCRIPT_TOKEN = /^(?:verify(?::full)?|format|knip|(?:lint|test|generate):[a-z][a-z:-]*|ensure:db|with:test-db)$/;
15
+ const PATH_EXTENSION = /\.(?:tsx?|mts|cts|mjs|cjs|js|jsonc?|ya?ml|md|css|scss|grit)$/;
16
+ const PNPM_RUN_PREFIX = 'pnpm run ';
17
+ const backtickTokens = (markdown) => (markdown.match(BACKTICK_TOKEN) ?? []).map((raw) => raw.slice(1, -1).trim());
18
+ const pnpmRunScripts = (markdown) => (markdown.match(PNPM_RUN) ?? []).map((raw) => raw.slice(PNPM_RUN_PREFIX.length));
19
+ // Strip a trailing `/**` or `/*` glob so `src/access/**` becomes `src/access`; a token with any other
20
+ // `*` cannot be existence-checked and is dropped by the caller.
21
+ const stripTrailingGlob = (token) => token.replace(/\/\*\*?$/, '');
22
+ const extractScriptReferences = (markdown) => {
23
+ const backticked = backtickTokens(markdown).filter((token) => SCRIPT_TOKEN.test(token));
24
+ return new Set([...backticked, ...pnpmRunScripts(markdown)]);
25
+ };
26
+ // A token beginning with the name of a declared dependency is a module SPECIFIER, not a repository
27
+ // path, and the header above says this rule judges repository paths. `ploaness/tsconfig.json` is the
28
+ // case that forced the distinction: the wiring gate mandates that exact `extends` value, so a project
29
+ // documenting what another gate REQUIRES was reported for naming a file it is obliged to name.
30
+ //
31
+ // The exemption is derived from what the project declares rather than from a list of the harness's own
32
+ // subpaths, which keeps the useful half: drop the dependency and the same reference is rot again.
33
+ // A scope and a name: the most of a specifier that can still be a package name.
34
+ const PACKAGE_NAME_SEGMENTS = 2;
35
+ const specifierPackage = (token) => {
36
+ const [first = '', second = ''] = token.split('/', PACKAGE_NAME_SEGMENTS);
37
+ return first.startsWith('@') ? `${first}/${second}` : first;
38
+ };
39
+ const extractPathReferences = (markdown, packageNames) => {
40
+ const paths = backtickTokens(markdown)
41
+ .filter((token) => token.includes('/') && !token.includes(' '))
42
+ .map((token) => stripTrailingGlob(token))
43
+ .filter((token) => !token.includes('*') && PATH_EXTENSION.test(token))
44
+ .filter((token) => !packageNames.has(specifierPackage(token)));
45
+ return new Set(paths);
46
+ };
47
+ /**
48
+ * Return every documentation reference that no longer resolves: a named script absent from
49
+ * package.json, or a full-path file that does not exist. An empty array means the docs are in sync.
50
+ */
51
+ export const findDocumentReferenceViolations = (inputs) => {
52
+ const scriptViolations = [
53
+ ...extractScriptReferences(inputs.markdown),
54
+ ]
55
+ .filter((name) => !(inputs.scriptNames.has(name) || inputs.reservedWords.has(name)))
56
+ .map((name) => ({
57
+ reference: name,
58
+ kind: 'script',
59
+ reason: 'no matching script in package.json',
60
+ }));
61
+ const pathViolations = [
62
+ ...extractPathReferences(inputs.markdown, inputs.packageNames),
63
+ ]
64
+ .filter((path) => !inputs.isExistingFile(path))
65
+ .map((path) => ({
66
+ reference: path,
67
+ kind: 'path',
68
+ reason: 'referenced file does not exist',
69
+ }));
70
+ return [...scriptViolations, ...pathViolations];
71
+ };
72
+ // Which instruction files a repository has, and whose scripts each one is read against. This was a
73
+ // constant list joined onto the repository root, which meant a workspace's member docs were never read
74
+ // at all: a real project carried three AGENTS.md, two of them naming a config file the harness forbids
75
+ // and a pipeline no commit ever added, past a gate reporting that every reference resolved.
76
+ //
77
+ // The root is a candidate whether or not it is a MEMBER, and that is the whole reason this is a
78
+ // function rather than a mapped member list. pnpm does not require the workspace root to appear in
79
+ // `packages:`, and the project that exposed the defect does not list it - so deriving the candidates
80
+ // from the member list alone would have stopped reading the root's own docs, trading one blind spot
81
+ // for the other.
82
+ /** The instruction files an agent reads, in the order it meets them. */
83
+ const DOCUMENT_FILES = ['AGENTS.md', 'CLAUDE.md'];
84
+ const joinPath = (directory, file) => directory === ROOT_MEMBER_PATH ? file : `${directory}/${file}`;
85
+ /**
86
+ * Locate every agent instruction file this repository holds.
87
+ * @param memberPaths the governed members, repo-relative.
88
+ * @param isExistingFile whether a repo-relative path exists.
89
+ * @returns one entry per file present, the root's first, then each member's in the order given.
90
+ */
91
+ export const findAgentDocuments = (memberPaths, isExistingFile) => [ROOT_MEMBER_PATH, ...memberPaths.filter((path) => path !== ROOT_MEMBER_PATH)]
92
+ .flatMap((directory) => DOCUMENT_FILES.map((file) => ({ file: joinPath(directory, file), directory })))
93
+ .filter((location) => isExistingFile(location.file));
94
+ //# sourceMappingURL=document-references.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-references.js","sourceRoot":"","sources":["../src/document-references.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** The standard's line cap. Not configurable: a cap is never raised. */
2
+ export declare const MAX_LINE_LENGTH: number;
3
+ /** The properties this rule reads out of an `.editorconfig`. */
4
+ export interface EditorconfigRules {
5
+ readonly endOfLine: string | undefined;
6
+ readonly insertFinalNewline: boolean;
7
+ readonly trimTrailingWhitespace: boolean;
8
+ readonly indentStyle: string | undefined;
9
+ }
10
+ /** One place a file departs from the committed configuration. */
11
+ export interface EditorconfigViolation {
12
+ readonly line: number;
13
+ readonly reason: string;
14
+ }
15
+ export declare const parseEditorconfig: (text: string) => EditorconfigRules;
16
+ /**
17
+ * Check one file against the committed configuration.
18
+ * @param content the file's decoded content.
19
+ * @param rules the properties read from the `.editorconfig`.
20
+ * @param isLineLengthEnforced whether the standard's line cap applies to this file's role.
21
+ * @returns one violation per departure, in line order.
22
+ */
23
+ export declare const findEditorconfigViolations: (content: string, rules: EditorconfigRules, isLineLengthEnforced: boolean) => readonly EditorconfigViolation[];
24
+ //# sourceMappingURL=editorconfig-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorconfig-policy.d.ts","sourceRoot":"","sources":["../src/editorconfig-policy.ts"],"names":[],"mappings":"AAaA,wEAAwE;AACxE,eAAO,MAAM,eAAe,EAAE,MAAY,CAAA;AAE1C,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAA;IACpC,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAA;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC;AAED,iEAAiE;AACjE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AA8BD,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,iBAqBhD,CAAA;AA2CD;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GACrC,SAAS,MAAM,EACf,OAAO,iBAAiB,EACxB,sBAAsB,OAAO,KAC5B,SAAS,qBAAqB,EAgBhC,CAAA"}
@@ -0,0 +1,106 @@
1
+ // Conformance to the committed `.editorconfig`, plus the standard's line cap.
2
+ //
3
+ // The `.editorconfig` is a pinned managed file, so every project holds the same one - and until now
4
+ // nothing checked a single file against it. The formatter covers only the globs it owns, which leaves
5
+ // Markdown, YAML, shell scripts, and Dockerfiles free to carry a CRLF, a tab, a trailing space, or a
6
+ // missing final newline.
7
+ //
8
+ // The expectations are read from the `.editorconfig` itself rather than restated here, so editing the
9
+ // pinned file moves the gate with it and the gate cannot contradict the file it checks against. The one
10
+ // value that does NOT come from there is the line cap: `max_line_length` is an editor hint that tells a
11
+ // ruler where to sit, while the standard's 120 characters is a cap that binds as an error. A project's
12
+ // formatter may aim shorter, and frequently does.
13
+ /** The standard's line cap. Not configurable: a cap is never raised. */
14
+ export const MAX_LINE_LENGTH = 120;
15
+ const FIRST_LINE = 1;
16
+ // Named by code point rather than written out, for the reason `banned-typography.ts` gives about the
17
+ // characters IT bans: a source file that spells an invisible character invites a tool to normalise it
18
+ // away - and here that tool would silently disarm the very rule this constant implements.
19
+ const BYTE_ORDER_MARK = 0xfe_ff;
20
+ const BOM = String.fromCodePoint(BYTE_ORDER_MARK);
21
+ /**
22
+ * Read the `[*]` section of an `.editorconfig`.
23
+ * @param text the file's content.
24
+ * @returns the properties the conformance rule binds.
25
+ */
26
+ // The `[*]` section is the span between that header and the next one, so it can be sliced out before
27
+ // any property is read rather than tracked with a flag while reading.
28
+ const wildcardSection = (text) => {
29
+ const lines = text.split('\n').map((raw) => raw.trim());
30
+ const start = lines.indexOf('[*]');
31
+ if (start === -1) {
32
+ return [];
33
+ }
34
+ const rest = lines.slice(start + 1);
35
+ const end = rest.findIndex((line) => line.startsWith('['));
36
+ return end === -1 ? rest : rest.slice(0, end);
37
+ };
38
+ const isProperty = (line) => line.length > 0 && !line.startsWith('#') && !line.startsWith(';') && line.includes('=');
39
+ export const parseEditorconfig = (text) => {
40
+ const properties = Object.fromEntries(wildcardSection(text)
41
+ .filter((line) => isProperty(line))
42
+ .map((line) => {
43
+ const separator = line.indexOf('=');
44
+ return [
45
+ line.slice(0, separator).trim().toLowerCase(),
46
+ line
47
+ .slice(separator + 1)
48
+ .trim()
49
+ .toLowerCase(),
50
+ ];
51
+ }));
52
+ return {
53
+ endOfLine: properties['end_of_line'],
54
+ insertFinalNewline: properties['insert_final_newline'] === 'true',
55
+ trimTrailingWhitespace: properties['trim_trailing_whitespace'] === 'true',
56
+ indentStyle: properties['indent_style'],
57
+ };
58
+ };
59
+ const lineRules = (rules, isLineLengthEnforced) => [
60
+ (_body, raw) => rules.endOfLine === 'lf' && raw.endsWith('\r')
61
+ ? 'carriage return; end_of_line is lf'
62
+ : undefined,
63
+ (body) => rules.trimTrailingWhitespace && /[ \t]$/.test(body) ? 'trailing whitespace' : undefined,
64
+ (body) => rules.indentStyle === 'space' && body.startsWith('\t')
65
+ ? 'tab indentation; indent_style is space'
66
+ : undefined,
67
+ (body) => isLineLengthEnforced && body.length > MAX_LINE_LENGTH
68
+ ? `line is ${String(body.length)} characters; the cap is ${String(MAX_LINE_LENGTH)}`
69
+ : undefined,
70
+ ];
71
+ const lineViolations = (content, rules, isLineLengthEnforced) => {
72
+ const checks = lineRules(rules, isLineLengthEnforced);
73
+ return content
74
+ .split('\n')
75
+ .flatMap((raw, index) => {
76
+ const body = raw.replace(/\r$/, '');
77
+ return checks.flatMap((check) => {
78
+ const reason = check(body, raw);
79
+ return reason === undefined ? [] : [{ line: index + 1, reason }];
80
+ });
81
+ });
82
+ };
83
+ /**
84
+ * Check one file against the committed configuration.
85
+ * @param content the file's decoded content.
86
+ * @param rules the properties read from the `.editorconfig`.
87
+ * @param isLineLengthEnforced whether the standard's line cap applies to this file's role.
88
+ * @returns one violation per departure, in line order.
89
+ */
90
+ export const findEditorconfigViolations = (content, rules, isLineLengthEnforced) => {
91
+ if (content.length === 0) {
92
+ return [];
93
+ }
94
+ const byteOrderMark = content.startsWith(BOM)
95
+ ? [{ line: FIRST_LINE, reason: 'byte order mark; charset is utf-8' }]
96
+ : [];
97
+ const finalNewline = rules.insertFinalNewline && !content.endsWith('\n')
98
+ ? [{ line: content.split('\n').length, reason: 'no final newline' }]
99
+ : [];
100
+ return [
101
+ ...byteOrderMark,
102
+ ...lineViolations(content, rules, isLineLengthEnforced),
103
+ ...finalNewline,
104
+ ];
105
+ };
106
+ //# sourceMappingURL=editorconfig-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorconfig-policy.js","sourceRoot":"","sources":["../src/editorconfig-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The environment files a run reads, highest precedence first. `.env.local` leads because it is the
3
+ * personal, untracked override of `.env`; the managed `.gitignore` ignores both, which is what makes
4
+ * these the two a project can be assumed to keep out of the tree.
5
+ */
6
+ export declare const RUN_ENVIRONMENT_FILES: readonly string[];
7
+ /**
8
+ * The environment files a run should read, in the order it must read them.
9
+ * @param isExistingFile whether a repository-relative path names a file that exists.
10
+ * @returns the present subset of {@link RUN_ENVIRONMENT_FILES}, highest precedence first.
11
+ */
12
+ export declare const runEnvironmentFiles: (isExistingFile: (relativePath: string) => boolean) => readonly string[];
13
+ /**
14
+ * The port an origin names, as a string a child process's environment can carry.
15
+ *
16
+ * A project declares the origin its application serves, and ploaness starts that application itself.
17
+ * Reading the origin without reading the port meant the two disagreed: the server was started on the
18
+ * framework's default while the runner waited on the declared one, so the only setting that exists to
19
+ * describe a non-default port made the run hang rather than work.
20
+ * @param serverUrl the declared origin.
21
+ * @returns the port, or undefined when the origin names none and the default applies.
22
+ */
23
+ export declare const portOf: (serverUrl: string) => string | undefined;
24
+ /**
25
+ * The variables a run must be GIVEN, as distinct from the ones it inherits.
26
+ *
27
+ * `process.loadEnvFile` is the answer where the process reading the files is the process that boots the
28
+ * project. A gate is not: it starts a CHILD, and mutating the gate's own environment to configure that
29
+ * child would take the project's settings into the harness for every gate after it. So the same
30
+ * precedence has to be rebuilt as an override map - and it is the REVERSE of what spawning does by
31
+ * default, where an override beats the inherited value. Here a file must LOSE to a variable the run
32
+ * already carries, for the reason stated above: that variable was there before any file was read.
33
+ *
34
+ * Returning only the names the run lacks is what makes that safe to hand to a plain merge. The
35
+ * alternative, merging the files under `process.env`, silently reinstates any name the parent happens
36
+ * to carry as empty rather than absent.
37
+ * @param current the environment the run already has, typically `process.env`.
38
+ * @param parsedFiles the parsed files, in the order {@link runEnvironmentFiles} returned them.
39
+ * @returns the names the run does not carry, each with the value of the FIRST file to declare it.
40
+ */
41
+ export declare const runEnvironmentOverrides: (current: Readonly<Record<string, string | undefined>>, parsedFiles: readonly Readonly<Record<string, string | undefined>>[]) => Readonly<Record<string, string>>;
42
+ //# sourceMappingURL=environment-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-files.d.ts","sourceRoot":"","sources":["../src/environment-files.ts"],"names":[],"mappings":"AAoBA;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAA2B,CAAA;AAE9E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAC9B,gBAAgB,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,KAChD,SAAS,MAAM,EAC6D,CAAA;AAE/E;;;;;;;;;GASG;AACH,eAAO,MAAM,MAAM,GAAI,WAAW,MAAM,KAAG,MAAM,GAAG,SASnD,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EACrD,aAAa,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,EAAE,KACnE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAe/B,CAAA"}
@@ -0,0 +1,76 @@
1
+ // The environment files a run of the project reads into its own process.
2
+ //
3
+ // A Payload config validates `process.env` at module scope, so anything that boots the project boots
4
+ // its configuration first. Next reads these files itself, which is why the application under test never
5
+ // had a problem - but a test runner does not, and the runner ploaness ships a Playwright config for
6
+ // boots the project in its OWN process: an end-to-end helper that seeds a user through `getPayload`
7
+ // evaluates `payload.config.ts` at spec-collection time, before a browser or a server is involved.
8
+ //
9
+ // The project used to load them from its own `playwright.config.ts`. The wiring gate now requires that
10
+ // file to be a bare re-export, which removes the only seam it had, so the harness that took the seam
11
+ // away owes the load. Vitest is the other half of the same shape and keeps its own answer: a project
12
+ // writes `vitest.setup.ts` and ploaness loads it, which is a seam the project still owns.
13
+ //
14
+ // The order is the part that carries meaning, and it is stated here rather than at the call site so
15
+ // that it is measured: `packages/config` is an analyzer configuration that no coverage floor reads,
16
+ // while everything in this package is unit-tested. Nothing loaded later may replace a value already
17
+ // set, so the file that must win is read first, and a variable the real environment already carries -
18
+ // a CI secret, a `DATABASE_URL` exported by a service container - outranks every file, because it was
19
+ // there before any of them was read.
20
+ /**
21
+ * The environment files a run reads, highest precedence first. `.env.local` leads because it is the
22
+ * personal, untracked override of `.env`; the managed `.gitignore` ignores both, which is what makes
23
+ * these the two a project can be assumed to keep out of the tree.
24
+ */
25
+ export const RUN_ENVIRONMENT_FILES = ['.env.local', '.env'];
26
+ /**
27
+ * The environment files a run should read, in the order it must read them.
28
+ * @param isExistingFile whether a repository-relative path names a file that exists.
29
+ * @returns the present subset of {@link RUN_ENVIRONMENT_FILES}, highest precedence first.
30
+ */
31
+ export const runEnvironmentFiles = (isExistingFile) => RUN_ENVIRONMENT_FILES.filter((file) => isExistingFile(file));
32
+ /**
33
+ * The port an origin names, as a string a child process's environment can carry.
34
+ *
35
+ * A project declares the origin its application serves, and ploaness starts that application itself.
36
+ * Reading the origin without reading the port meant the two disagreed: the server was started on the
37
+ * framework's default while the runner waited on the declared one, so the only setting that exists to
38
+ * describe a non-default port made the run hang rather than work.
39
+ * @param serverUrl the declared origin.
40
+ * @returns the port, or undefined when the origin names none and the default applies.
41
+ */
42
+ export const portOf = (serverUrl) => {
43
+ try {
44
+ const port = new URL(serverUrl).port;
45
+ return port.length > 0 ? port : undefined;
46
+ }
47
+ catch {
48
+ // A malformed origin is the project's to fix, and the gate that drives it will say so far more
49
+ // clearly than a crash inside a configuration file that no stack trace points at.
50
+ return undefined;
51
+ }
52
+ };
53
+ /**
54
+ * The variables a run must be GIVEN, as distinct from the ones it inherits.
55
+ *
56
+ * `process.loadEnvFile` is the answer where the process reading the files is the process that boots the
57
+ * project. A gate is not: it starts a CHILD, and mutating the gate's own environment to configure that
58
+ * child would take the project's settings into the harness for every gate after it. So the same
59
+ * precedence has to be rebuilt as an override map - and it is the REVERSE of what spawning does by
60
+ * default, where an override beats the inherited value. Here a file must LOSE to a variable the run
61
+ * already carries, for the reason stated above: that variable was there before any file was read.
62
+ *
63
+ * Returning only the names the run lacks is what makes that safe to hand to a plain merge. The
64
+ * alternative, merging the files under `process.env`, silently reinstates any name the parent happens
65
+ * to carry as empty rather than absent.
66
+ * @param current the environment the run already has, typically `process.env`.
67
+ * @param parsedFiles the parsed files, in the order {@link runEnvironmentFiles} returned them.
68
+ * @returns the names the run does not carry, each with the value of the FIRST file to declare it.
69
+ */
70
+ export const runEnvironmentOverrides = (current, parsedFiles) => Object.fromEntries(parsedFiles
71
+ .flatMap((file) => Object.entries(file))
72
+ .filter((entry) => entry[1] !== undefined && current[entry[0]] === undefined)
73
+ // Among the files the earliest wins, and `Object.fromEntries` gives the LAST entry for a repeated
74
+ // name, so the list is reversed rather than de-duplicated by hand.
75
+ .toReversed());
76
+ //# sourceMappingURL=environment-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environment-files.js","sourceRoot":"","sources":["../src/environment-files.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,qGAAqG;AACrG,wGAAwG;AACxG,oGAAoG;AACpG,oGAAoG;AACpG,mGAAmG;AACnG,EAAE;AACF,uGAAuG;AACvG,qGAAqG;AACrG,qGAAqG;AACrG,0FAA0F;AAC1F,EAAE;AACF,oGAAoG;AACpG,oGAAoG;AACpG,oGAAoG;AACpG,sGAAsG;AACtG,sGAAsG;AACtG,qCAAqC;AAErC;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,YAAY,EAAE,MAAM,CAAC,CAAA;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,cAAiD,EAC9B,EAAE,CACrB,qBAAqB,CAAC,MAAM,CAAC,CAAC,IAAY,EAAW,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAA;AAE/E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,SAAiB,EAAsB,EAAE;IAC9D,IAAI,CAAC;QACH,MAAM,IAAI,GAAW,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAA;QAC5C,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,+FAA+F;QAC/F,kFAAkF;QAClF,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,OAAqD,EACrD,WAAoE,EAClC,EAAE,CACpC,MAAM,CAAC,WAAW,CAChB,WAAW;KACR,OAAO,CACN,CACE,IAAkD,EACT,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CACnE;KACA,MAAM,CACL,CAAC,KAA4C,EAA6B,EAAE,CAC1E,KAAK,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAC5D;IACD,kGAAkG;IAClG,mEAAmE;KAClE,UAAU,EAAE,CAChB,CAAA"}
@@ -0,0 +1,39 @@
1
+ /** Extensions the Code Rules apply to, used where a rule is about code rather than about any text. */
2
+ export declare const CODE_EXTENSIONS: readonly string[];
3
+ /** Extensions whose role is prose, where a code-shaped rule such as a line cap does not apply. */
4
+ export declare const PROSE_EXTENSIONS: readonly string[];
5
+ /**
6
+ * Decide whether a file is binary, from the file itself rather than from its name.
7
+ * @param bytes the file's leading content.
8
+ * @returns true when a NUL byte appears in the probed span, which no text encoding produces.
9
+ */
10
+ export declare const isBinary: (bytes: Uint8Array) => boolean;
11
+ /**
12
+ * Decide whether a path carries one of the given extensions.
13
+ * @param filePath the repo-relative path.
14
+ * @param extensions the extensions to test.
15
+ * @returns true when the path ends with one of them.
16
+ */
17
+ export declare const hasExtension: (filePath: string, extensions: readonly string[]) => boolean;
18
+ /**
19
+ * Decide whether a path is excluded by a declared role pattern.
20
+ * @param filePath the repo-relative path.
21
+ * @param patterns the declared exclusion patterns.
22
+ * @returns true when any pattern matches.
23
+ */
24
+ export declare const matchesRole: (filePath: string, patterns: readonly string[]) => boolean;
25
+ /**
26
+ * Whether a repo-relative path matches a glob pattern of the kind the coverage settings carry.
27
+ * @param pattern the glob, such as `src/app/**` or `src/**\/*.tsx`.
28
+ * @param filePath the repo-relative path to test.
29
+ * @returns whether the whole path matches the whole pattern.
30
+ */
31
+ export declare const matchesGlob: (pattern: string, filePath: string) => boolean;
32
+ /**
33
+ * Decide whether a path holds code the Code Rules govern.
34
+ * @param filePath the repo-relative path.
35
+ * @param excluded the declared generated-role patterns.
36
+ * @returns true when the file is code and no declared role excludes it.
37
+ */
38
+ export declare const isGovernedCode: (filePath: string, excluded: readonly string[]) => boolean;
39
+ //# sourceMappingURL=file-roles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-roles.d.ts","sourceRoot":"","sources":["../src/file-roles.ts"],"names":[],"mappings":"AAYA,sGAAsG;AACtG,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAU5C,CAAA;AAED,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAA6B,CAAA;AAE3E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,UAAU,KAAG,OACM,CAAA;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU,MAAM,EAAE,YAAY,SAAS,MAAM,EAAE,KAAG,OACA,CAAA;AAE/E;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,UAAU,SAAS,MAAM,EAAE,KAAG,OACK,CAAA;AA2BjF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,EAAE,UAAU,MAAM,KAAG,OAG9C,CAAA;AAElB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,UAAU,SAAS,MAAM,EAAE,KAAG,OACF,CAAA"}
@@ -0,0 +1,82 @@
1
+ // File roles: the categories a repository can determine from a file itself and uses to include or
2
+ // exclude it from a check.
3
+ //
4
+ // The typography ban used to carry its own allowlist of ten extensions, which is the wrong shape for a
5
+ // rule that reaches "every tracked file the repository does not exclude by role": a `.css`, a `.adoc`,
6
+ // a shell script, or a Dockerfile went unscanned, and every new text format arrived unscanned until
7
+ // someone remembered to extend the list. A role predicate is default-safe in the opposite direction -
8
+ // a new format is covered by construction, and exclusion is the thing that must be stated.
9
+ /** How much of a file is inspected before deciding it is text. Enough to reach any real header. */
10
+ const BINARY_PROBE_BYTES = 8192;
11
+ /** Extensions the Code Rules apply to, used where a rule is about code rather than about any text. */
12
+ export const CODE_EXTENSIONS = [
13
+ '.ts',
14
+ '.tsx',
15
+ '.mts',
16
+ '.cts',
17
+ '.js',
18
+ '.mjs',
19
+ '.cjs',
20
+ '.css',
21
+ '.scss',
22
+ ];
23
+ /** Extensions whose role is prose, where a code-shaped rule such as a line cap does not apply. */
24
+ export const PROSE_EXTENSIONS = ['.md', '.adoc', '.txt'];
25
+ /**
26
+ * Decide whether a file is binary, from the file itself rather than from its name.
27
+ * @param bytes the file's leading content.
28
+ * @returns true when a NUL byte appears in the probed span, which no text encoding produces.
29
+ */
30
+ export const isBinary = (bytes) => bytes.subarray(0, BINARY_PROBE_BYTES).includes(0);
31
+ /**
32
+ * Decide whether a path carries one of the given extensions.
33
+ * @param filePath the repo-relative path.
34
+ * @param extensions the extensions to test.
35
+ * @returns true when the path ends with one of them.
36
+ */
37
+ export const hasExtension = (filePath, extensions) => extensions.some((extension) => filePath.endsWith(extension));
38
+ /**
39
+ * Decide whether a path is excluded by a declared role pattern.
40
+ * @param filePath the repo-relative path.
41
+ * @param patterns the declared exclusion patterns.
42
+ * @returns true when any pattern matches.
43
+ */
44
+ export const matchesRole = (filePath, patterns) => patterns.some((pattern) => new RegExp(pattern).test(filePath));
45
+ // The glob dialect the coverage settings are written in, which is not the regex dialect `matchesRole`
46
+ // reads. `**/` crosses directory boundaries and `*` does not, which is the whole distinction between
47
+ // `src/**/*.tsx` and `src/*.tsx`; collapsing the two would silently widen every pattern that uses one.
48
+ const GLOB_TOKEN = /\*\*\/|\*\*|[*?.+^${}()|[\]\\]/g;
49
+ const asRegexToken = (token) => {
50
+ switch (token) {
51
+ case '**/': {
52
+ return '(?:[^/]*/)*';
53
+ }
54
+ case '**': {
55
+ return '.*';
56
+ }
57
+ case '*': {
58
+ return '[^/]*';
59
+ }
60
+ case '?': {
61
+ return '[^/]';
62
+ }
63
+ default: {
64
+ return `\\${token}`;
65
+ }
66
+ }
67
+ };
68
+ /**
69
+ * Whether a repo-relative path matches a glob pattern of the kind the coverage settings carry.
70
+ * @param pattern the glob, such as `src/app/**` or `src/**\/*.tsx`.
71
+ * @param filePath the repo-relative path to test.
72
+ * @returns whether the whole path matches the whole pattern.
73
+ */
74
+ export const matchesGlob = (pattern, filePath) => new RegExp(`^${pattern.replaceAll(GLOB_TOKEN, (token) => asRegexToken(token))}$`).test(filePath);
75
+ /**
76
+ * Decide whether a path holds code the Code Rules govern.
77
+ * @param filePath the repo-relative path.
78
+ * @param excluded the declared generated-role patterns.
79
+ * @returns true when the file is code and no declared role excludes it.
80
+ */
81
+ export const isGovernedCode = (filePath, excluded) => hasExtension(filePath, CODE_EXTENSIONS) && !matchesRole(filePath, excluded);
82
+ //# sourceMappingURL=file-roles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-roles.js","sourceRoot":"","sources":["../src/file-roles.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,2BAA2B;AAC3B,EAAE;AACF,uGAAuG;AACvG,uGAAuG;AACvG,oGAAoG;AACpG,sGAAsG;AACtG,2FAA2F;AAE3F,mGAAmG;AACnG,MAAM,kBAAkB,GAAW,IAAI,CAAA;AAEvC,sGAAsG;AACtG,MAAM,CAAC,MAAM,eAAe,GAAsB;IAChD,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;CACR,CAAA;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,gBAAgB,GAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;AAE3E;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAiB,EAAW,EAAE,CACrD,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AAEnD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAE,UAA6B,EAAW,EAAE,CACvF,UAAU,CAAC,IAAI,CAAC,CAAC,SAAiB,EAAW,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAA;AAE/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,QAA2B,EAAW,EAAE,CACpF,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAe,EAAW,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AAEjF,sGAAsG;AACtG,qGAAqG;AACrG,uGAAuG;AACvG,MAAM,UAAU,GAAW,iCAAiC,CAAA;AAE5D,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE;IAC7C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,OAAO,aAAa,CAAA;QACtB,CAAC;QACD,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,OAAO,IAAI,CAAA;QACb,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACT,OAAO,OAAO,CAAA;QAChB,CAAC;QACD,KAAK,GAAG,CAAC,CAAC,CAAC;YACT,OAAO,MAAM,CAAA;QACf,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,KAAK,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,QAAgB,EAAW,EAAE,CACxE,IAAI,MAAM,CACR,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,KAAa,EAAU,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,CACtF,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAElB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAgB,EAAE,QAA2B,EAAW,EAAE,CACvF,YAAY,CAAC,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA"}
@@ -0,0 +1,42 @@
1
+ /** The artefacts Payload derives from the configuration. Declared once and consumed by every rule. */
2
+ export declare const GENERATED_ARTEFACTS: readonly string[];
3
+ /**
4
+ * The deny rules a runtime must carry for a set of generated artefacts.
5
+ *
6
+ * The artefacts are a parameter rather than the constant above so the rule stays a statement about a
7
+ * SET of generated paths rather than about Payload's three. What ploaness governs is one such set; the
8
+ * ploaness repository denies its own regenerated asset bodies through the same shaped list, written by
9
+ * hand in `.claude/settings.json` because nothing here runs `ploaness sync`. Closing over the constant
10
+ * would have made the rule untestable against any set but that one.
11
+ * @param artefacts the repo-relative paths a generator owns.
12
+ * @returns the Edit and Write denials the runtime settings must carry.
13
+ */
14
+ export declare const requiredDenyRules: (artefacts: readonly string[]) => readonly string[];
15
+ /**
16
+ * Merge the required deny rules into an existing runtime settings object.
17
+ * @param existing the parsed settings, or undefined when the file does not exist.
18
+ * @param artefacts the repo-relative paths a generator owns.
19
+ * @returns the settings to write, preserving every key the project owns.
20
+ */
21
+ export declare const applyDenyRules: (existing: unknown, artefacts: readonly string[]) => Record<string, unknown>;
22
+ /**
23
+ * Report every required denial the runtime settings do not carry, and every re-permission of one.
24
+ * @param settings the parsed runtime settings, or undefined when absent.
25
+ * @param localSettings the parsed machine-local overrides, or undefined when absent.
26
+ * @param artefacts the repo-relative paths a generator owns.
27
+ * @returns one message per missing denial or re-permitted artefact.
28
+ */
29
+ export declare const findDenialViolations: (settings: unknown, localSettings: unknown, artefacts: readonly string[]) => readonly string[];
30
+ /**
31
+ * The generated paths a repository denies, across every member that has any.
32
+ *
33
+ * The runtime reads one settings file, at the repository root, while the artefacts are named relative
34
+ * to the member that generates them. A rule written for one member would therefore bind nothing in a
35
+ * workspace. For a single member at the root the union is the artefact list unchanged, which is what
36
+ * keeps a single-package project's settings file byte-identical.
37
+ * @param memberPaths the repo-relative paths of the members that own generated artefacts.
38
+ * @param artefacts the member-relative paths a generator owns.
39
+ * @returns every repo-relative path the runtime must deny, in member order.
40
+ */
41
+ export declare const deniedPathsFor: (memberPaths: readonly string[], artefacts: readonly string[]) => readonly string[];
42
+ //# sourceMappingURL=generated-denial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generated-denial.d.ts","sourceRoot":"","sources":["../src/generated-denial.ts"],"names":[],"mappings":"AAWA,sGAAsG;AACtG,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAIhD,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,GAAI,WAAW,SAAS,MAAM,EAAE,KAAG,SAAS,MAAM,EAI5E,CAAA;AASJ;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GACzB,UAAU,OAAO,EACjB,WAAW,SAAS,MAAM,EAAE,KAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CASxB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,OAAO,EACjB,eAAe,OAAO,EACtB,WAAW,SAAS,MAAM,EAAE,KAC3B,SAAS,MAAM,EAgBjB,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,GACzB,aAAa,SAAS,MAAM,EAAE,EAC9B,WAAW,SAAS,MAAM,EAAE,KAC3B,SAAS,MAAM,EAKf,CAAA"}