@promptci/core 0.2.2 → 0.4.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 (181) hide show
  1. package/dist/action-pinning.d.ts.map +1 -1
  2. package/dist/action-pinning.js +86 -55
  3. package/dist/action-pinning.js.map +1 -1
  4. package/dist/agent-practices.d.ts +5 -1
  5. package/dist/agent-practices.d.ts.map +1 -1
  6. package/dist/agent-practices.js +59 -34
  7. package/dist/agent-practices.js.map +1 -1
  8. package/dist/ai-config.d.ts +13 -6
  9. package/dist/ai-config.d.ts.map +1 -1
  10. package/dist/ai-config.js +25 -78
  11. package/dist/ai-config.js.map +1 -1
  12. package/dist/baseline.d.ts +8 -0
  13. package/dist/baseline.d.ts.map +1 -1
  14. package/dist/baseline.js +15 -0
  15. package/dist/baseline.js.map +1 -1
  16. package/dist/ci-alignment.d.ts +3 -1
  17. package/dist/ci-alignment.d.ts.map +1 -1
  18. package/dist/ci-alignment.js +8 -1
  19. package/dist/ci-alignment.js.map +1 -1
  20. package/dist/close-match.d.ts +97 -0
  21. package/dist/close-match.d.ts.map +1 -0
  22. package/dist/close-match.js +215 -0
  23. package/dist/close-match.js.map +1 -0
  24. package/dist/command-context.d.ts +67 -0
  25. package/dist/command-context.d.ts.map +1 -0
  26. package/dist/command-context.js +291 -0
  27. package/dist/command-context.js.map +1 -0
  28. package/dist/command-validity.d.ts.map +1 -1
  29. package/dist/command-validity.js +510 -32
  30. package/dist/command-validity.js.map +1 -1
  31. package/dist/context-optimizer.d.ts.map +1 -1
  32. package/dist/context-optimizer.js +9 -2
  33. package/dist/context-optimizer.js.map +1 -1
  34. package/dist/dead-references.d.ts +14 -1
  35. package/dist/dead-references.d.ts.map +1 -1
  36. package/dist/dead-references.js +264 -17
  37. package/dist/dead-references.js.map +1 -1
  38. package/dist/dependency-staleness.d.ts.map +1 -1
  39. package/dist/dependency-staleness.js +24 -38
  40. package/dist/dependency-staleness.js.map +1 -1
  41. package/dist/detectors.js +1 -1
  42. package/dist/detectors.js.map +1 -1
  43. package/dist/discovery.d.ts +138 -0
  44. package/dist/discovery.d.ts.map +1 -0
  45. package/dist/discovery.js +569 -0
  46. package/dist/discovery.js.map +1 -0
  47. package/dist/duplicates.d.ts +24 -2
  48. package/dist/duplicates.d.ts.map +1 -1
  49. package/dist/duplicates.js +313 -9
  50. package/dist/duplicates.js.map +1 -1
  51. package/dist/fix-engine.d.ts.map +1 -1
  52. package/dist/fix-engine.js +75 -1
  53. package/dist/fix-engine.js.map +1 -1
  54. package/dist/frameworks/dotnet.d.ts.map +1 -1
  55. package/dist/frameworks/dotnet.js +10 -11
  56. package/dist/frameworks/dotnet.js.map +1 -1
  57. package/dist/frameworks/go.d.ts.map +1 -1
  58. package/dist/frameworks/go.js +8 -4
  59. package/dist/frameworks/go.js.map +1 -1
  60. package/dist/frameworks/nextjs.d.ts.map +1 -1
  61. package/dist/frameworks/nextjs.js +8 -17
  62. package/dist/frameworks/nextjs.js.map +1 -1
  63. package/dist/frameworks/python.d.ts.map +1 -1
  64. package/dist/frameworks/python.js +5 -3
  65. package/dist/frameworks/python.js.map +1 -1
  66. package/dist/frameworks/rust.d.ts.map +1 -1
  67. package/dist/frameworks/rust.js +3 -3
  68. package/dist/frameworks/rust.js.map +1 -1
  69. package/dist/frameworks/unity.d.ts.map +1 -1
  70. package/dist/frameworks/unity.js +6 -5
  71. package/dist/frameworks/unity.js.map +1 -1
  72. package/dist/gitignore.d.ts +31 -2
  73. package/dist/gitignore.d.ts.map +1 -1
  74. package/dist/gitignore.js +33 -8
  75. package/dist/gitignore.js.map +1 -1
  76. package/dist/health-score.d.ts +15 -1
  77. package/dist/health-score.d.ts.map +1 -1
  78. package/dist/health-score.js +25 -2
  79. package/dist/health-score.js.map +1 -1
  80. package/dist/hooks-settings-detector.d.ts.map +1 -1
  81. package/dist/hooks-settings-detector.js +5 -1
  82. package/dist/hooks-settings-detector.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +16 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/known-paths.d.ts +82 -0
  88. package/dist/known-paths.d.ts.map +1 -0
  89. package/dist/known-paths.js +152 -0
  90. package/dist/known-paths.js.map +1 -0
  91. package/dist/makefile.d.ts.map +1 -1
  92. package/dist/makefile.js +17 -13
  93. package/dist/makefile.js.map +1 -1
  94. package/dist/manifest-consistency.d.ts +1 -1
  95. package/dist/manifest-consistency.d.ts.map +1 -1
  96. package/dist/manifest-consistency.js +18 -8
  97. package/dist/manifest-consistency.js.map +1 -1
  98. package/dist/markdown-fences.d.ts.map +1 -1
  99. package/dist/markdown-fences.js +7 -3
  100. package/dist/markdown-fences.js.map +1 -1
  101. package/dist/mcp-config-detector.d.ts.map +1 -1
  102. package/dist/mcp-config-detector.js +5 -1
  103. package/dist/mcp-config-detector.js.map +1 -1
  104. package/dist/project-type.d.ts +2 -1
  105. package/dist/project-type.d.ts.map +1 -1
  106. package/dist/project-type.js +36 -48
  107. package/dist/project-type.js.map +1 -1
  108. package/dist/prompt-cache.d.ts.map +1 -1
  109. package/dist/prompt-cache.js +13 -2
  110. package/dist/prompt-cache.js.map +1 -1
  111. package/dist/provenance/check.d.ts +40 -0
  112. package/dist/provenance/check.d.ts.map +1 -0
  113. package/dist/provenance/check.js +157 -0
  114. package/dist/provenance/check.js.map +1 -0
  115. package/dist/provenance/index.d.ts +13 -0
  116. package/dist/provenance/index.d.ts.map +1 -0
  117. package/dist/provenance/index.js +21 -0
  118. package/dist/provenance/index.js.map +1 -0
  119. package/dist/provenance/instruction-advice.d.ts +3 -0
  120. package/dist/provenance/instruction-advice.d.ts.map +1 -0
  121. package/dist/provenance/instruction-advice.js +570 -0
  122. package/dist/provenance/instruction-advice.js.map +1 -0
  123. package/dist/provenance/repo-checks.d.ts +3 -0
  124. package/dist/provenance/repo-checks.d.ts.map +1 -0
  125. package/dist/provenance/repo-checks.js +644 -0
  126. package/dist/provenance/repo-checks.js.map +1 -0
  127. package/dist/provenance/tool-config.d.ts +3 -0
  128. package/dist/provenance/tool-config.d.ts.map +1 -0
  129. package/dist/provenance/tool-config.js +480 -0
  130. package/dist/provenance/tool-config.js.map +1 -0
  131. package/dist/provenance/types.d.ts +116 -0
  132. package/dist/provenance/types.d.ts.map +1 -0
  133. package/dist/provenance/types.js +17 -0
  134. package/dist/provenance/types.js.map +1 -0
  135. package/dist/repo-context.d.ts +9 -0
  136. package/dist/repo-context.d.ts.map +1 -1
  137. package/dist/repo-context.js +35 -41
  138. package/dist/repo-context.js.map +1 -1
  139. package/dist/repo-tree.d.ts +163 -9
  140. package/dist/repo-tree.d.ts.map +1 -1
  141. package/dist/repo-tree.js +226 -34
  142. package/dist/repo-tree.js.map +1 -1
  143. package/dist/report.d.ts.map +1 -1
  144. package/dist/report.js +6 -0
  145. package/dist/report.js.map +1 -1
  146. package/dist/sample-text.d.ts +36 -0
  147. package/dist/sample-text.d.ts.map +1 -0
  148. package/dist/sample-text.js +72 -0
  149. package/dist/sample-text.js.map +1 -0
  150. package/dist/sarif.d.ts +27 -0
  151. package/dist/sarif.d.ts.map +1 -0
  152. package/dist/sarif.js +357 -0
  153. package/dist/sarif.js.map +1 -0
  154. package/dist/scan.d.ts.map +1 -1
  155. package/dist/scan.js +8 -2
  156. package/dist/scan.js.map +1 -1
  157. package/dist/scanner.d.ts +4 -3
  158. package/dist/scanner.d.ts.map +1 -1
  159. package/dist/scanner.js +36 -77
  160. package/dist/scanner.js.map +1 -1
  161. package/dist/security-pack.d.ts.map +1 -1
  162. package/dist/security-pack.js +117 -35
  163. package/dist/security-pack.js.map +1 -1
  164. package/dist/skill-supply-chain.d.ts.map +1 -1
  165. package/dist/skill-supply-chain.js +29 -19
  166. package/dist/skill-supply-chain.js.map +1 -1
  167. package/dist/skills-detector.d.ts.map +1 -1
  168. package/dist/skills-detector.js +11 -3
  169. package/dist/skills-detector.js.map +1 -1
  170. package/dist/token-estimates.d.ts +42 -0
  171. package/dist/token-estimates.d.ts.map +1 -0
  172. package/dist/token-estimates.js +200 -0
  173. package/dist/token-estimates.js.map +1 -0
  174. package/dist/types.d.ts +99 -0
  175. package/dist/types.d.ts.map +1 -1
  176. package/dist/types.js.map +1 -1
  177. package/dist/workspace-manifests.d.ts +6 -0
  178. package/dist/workspace-manifests.d.ts.map +1 -1
  179. package/dist/workspace-manifests.js +13 -8
  180. package/dist/workspace-manifests.js.map +1 -1
  181. package/package.json +5 -2
@@ -0,0 +1,644 @@
1
+ /**
2
+ * Provenance for the repository-facing checks (pcic-kvv3.1, issue #162): dead references,
3
+ * command validity, manifest consistency, dependency staleness, CI alignment, conflicts,
4
+ * stale instructions, action pinning, the security pack and the framework packs.
5
+ *
6
+ * Backfilled by an agent run that read each page listed below; the records are pending human
7
+ * review. A `repo-fact` is a statement about the scanned repository and needs no source. A
8
+ * `tool-fact` or `opinion` with no page found says `unverified: true` instead of citing one.
9
+ */
10
+ const READ_ON = '2026-11-13';
11
+ const VERIFIED = { date: '2026-11-13', by: 'Claude agent backfill (pcic-kvv3.1), pending human review' };
12
+ const src = (url, title, stance, note) => ({
13
+ url,
14
+ title,
15
+ readOn: READ_ON,
16
+ stance,
17
+ note,
18
+ });
19
+ // ── Package managers and workspaces ───────────────────────────────────────────
20
+ const NPM_RUN = src('https://docs.npmjs.com/cli/v11/commands/npm-run', 'npm run documentation', 'supports', 'Lists run-script among the aliases of run, says npm run puts node_modules/.bin on the PATH of a script, and says run is used by the test, start, restart and stop commands.');
21
+ const PNPM_RUN = src('https://pnpm.io/cli/run', 'pnpm run documentation', 'supports', 'Lists run-script as an alias, says pnpm <script> is shorthand for pnpm run <script> only when the name is not a pnpm command, and says a built-in command runs instead of a same-named script; the page does not list the built-ins.');
22
+ const YARN_RUN = src('https://yarnpkg.com/cli/run', 'Yarn run documentation', 'supports', 'Says yarn run checks package.json scripts first and then runs a dependency binary of the same name, and shows yarn <name> as the same thing without the run keyword.');
23
+ const BUN_RUN = src('https://bun.sh/docs/runtime', 'bun run documentation', 'supports', 'Says bun <script> works without run, that a built-in bun command takes precedence over a same-named script, and that bun run resolves binaries from project packages.');
24
+ const PNPM_FILTER = src('https://pnpm.io/filtering', 'pnpm filtering documentation', 'context', 'Documents --filter and -F as the workspace selector; it does not define -r or --recursive, so the detector treating pnpm -r as running in every workspace package is not covered by this page.');
25
+ const NPM_WORKSPACES = src('https://docs.npmjs.com/cli/v11/using-npm/workspaces', 'npm workspaces documentation', 'supports', 'Documents the workspaces field of package.json, -w and --workspace to target one workspace, and --workspaces to run in all of them; the -ws short form is not mentioned on the page.');
26
+ const PNPM_WORKSPACE_YAML = src('https://pnpm.io/settings', 'pnpm-workspace.yaml documentation', 'contradicts', 'Says pnpm reads workspaces only from pnpm-workspace.yaml and not from the workspaces field of the root package.json, while workspace-manifests.ts merges package.json workspaces globs with pnpm-workspace.yaml globs for every repository whatever its package manager.');
27
+ const GNU_MAKE_NAMES = src('https://www.gnu.org/software/make/manual/html_node/Makefile-Names.html', 'GNU make manual, makefile names', 'supports', 'Says GNU make looks for GNUmakefile, then makefile, then Makefile, and that -f disables the search.');
28
+ const NPM_PACKAGE_JSON = src('https://docs.npmjs.com/cli/v11/configuring-npm/package-json', 'npm package.json documentation', 'supports', 'Documents engines.node as the Node.js versions a package works on and says the field is advisory unless engine-strict is set; it documents packageManager only under devEngines, not as a top-level field.');
29
+ const COREPACK = src('https://github.com/nodejs/corepack', 'Corepack README', 'supports', 'Says to set the package manager with the packageManager field of package.json in name@version form and lists yarn, npm and pnpm as permitted values; bun is not among them.');
30
+ // ── Python ────────────────────────────────────────────────────────────────────
31
+ const POETRY_PYPROJECT = src('https://python-poetry.org/docs/pyproject/', 'Poetry pyproject.toml documentation', 'supports', 'Documents the [tool.poetry] table, the [project] table with requires-python, and the python dependency constraint that Poetry uses for locking; it does not explain caret syntax.');
32
+ const PYPA_PYPROJECT = src('https://packaging.python.org/en/latest/specifications/pyproject-toml/', 'PyPA pyproject.toml specification', 'supports', 'Lists requires-python as a [project] key giving the Python version requirements, and says the [tool] table holds per-tool configuration such as [tool.flit].');
33
+ const PIPENV_PIPFILE = src('https://pipenv.pypa.io/en/latest/pipfile.html', 'Pipenv Pipfile documentation', 'supports', 'Describes the Pipfile as the TOML dependency manifest that Pipenv uses in place of requirements.txt.');
34
+ const CONDA_ENVIRONMENTS = src('https://docs.conda.io/projects/conda/en/stable/user-guide/tasks/manage-environments.html', 'conda environment management', 'supports', 'Says environments are created from a YAML file such as environment.yml, and that conda env create --file still works but conda create --file is now preferred.');
35
+ const PYTEST_START = src('https://docs.pytest.org/en/stable/getting-started.html', 'pytest getting started', 'supports', 'Shows that running pytest finds test_*.py or *_test.py files and reports which tests passed or failed.');
36
+ const PYTHON_DEVGUIDE = src('https://devguide.python.org/versions/', 'Python developer guide, status of Python versions', 'supports', 'Lists Python 2.7 end of life on 2020-01-01, 3.8 on 2024-10-07 and 3.9 on 2025-10-31, and also lists 3.10 as end of life on 2026-10-01, which the detector does not flag.');
37
+ // ── Node, Next.js, React, Angular ─────────────────────────────────────────────
38
+ const NODE_RELEASES = src('https://nodejs.org/en/about/previous-releases', 'Node.js previous releases', 'supports', 'Lists every Node.js release line up to v20 and v25 as EOL, including v12, v14 and v16; v18 is also EOL, so the detector cut-off of 16 understates what is end of life.');
39
+ const NEXT_SERVER_CLIENT = src('https://nextjs.org/docs/app/getting-started/server-and-client-components', 'Next.js server and client components', 'supports', 'Says layouts and pages in the App Router are Server Components by default and that the use client directive marks a Client Component boundary.');
40
+ const NEXT_MIGRATION = src('https://nextjs.org/docs/app/guides/migrating/app-router-migration', 'Next.js migrating from Pages to the App Router', 'contradicts', 'Says the app directory is intentionally designed to work simultaneously with the pages directory for incremental migration and that the two routers can be used together, which contradicts treating pages router and app router as mutually exclusive; it also says getServerSideProps, getStaticProps and getInitialProps are replaced inside app.');
41
+ const NEXT_MIGRATION_SUPPORTS = src('https://nextjs.org/docs/app/guides/migrating/app-router-migration', 'Next.js migrating from Pages to the App Router', 'supports', 'Says data fetching functions such as getServerSideProps and getStaticProps have been replaced by a new API inside app, and that getInitialProps is replaced too.');
42
+ const NEXT_GET_INITIAL_PROPS = src('https://nextjs.org/docs/pages/api-reference/functions/get-initial-props', 'Next.js getInitialProps', 'supports', 'Documents getInitialProps as a legacy Pages Router API usable only in top-level files under pages, and points to the App Router for component-level data fetching.');
43
+ const NEXT_CONFIG = src('https://nextjs.org/docs/app/api-reference/config/next-config-js', 'Next.js next.config.js reference', 'supports', 'Accepts next.config.js in the project root, next.config.mjs for ES modules and next.config.ts for TypeScript, and says the .cjs and .cts extensions are not supported.');
44
+ const NEXT_STRUCTURE = src('https://nextjs.org/docs/app/getting-started/project-structure', 'Next.js project structure', 'supports', 'Lists app as the App Router folder and pages as the Pages Router folder at the top level, allows an optional src folder for application code, and names page and layout as the routing files.');
45
+ const REACT_19 = src('https://react.dev/blog/2024/04/25/react-19-upgrade-guide', 'React 19 upgrade guide', 'supports', 'Says ReactDOM.render was deprecated in 18.0.0 and removed in React 19, with createRoot from react-dom/client as the replacement.');
46
+ const REACT_18 = src('https://react.dev/blog/2022/03/08/react-18-upgrade-guide', 'React 18 upgrade guide', 'supports', 'Says ReactDOM.render is deprecated in React 18, warns and runs the app in React 17 mode, and that createRoot enables the concurrent renderer.');
47
+ const ANGULAR_COMPONENTS = src('https://angular.dev/guide/components', 'Angular components guide', 'contradicts', 'Says components are standalone by default and that in versions before 19.0.0 the standalone option defaults to false, while the detector treats Angular 17 and 18 as already standalone by default; the page does not say what ng new generated in those versions.');
48
+ const ANGULAR_NGMODULES = src('https://angular.dev/guide/ngmodules/overview', 'Angular NgModules overview', 'supports', 'Says the Angular team recommends standalone components instead of NgModule for all new code and bootstrapApplication instead of bootstrapModule.');
49
+ // ── Deprecated packages ───────────────────────────────────────────────────────
50
+ const MOMENT_STATUS = src('https://momentjs.com/docs/#/-project-status/', 'Moment.js project status', 'supports', 'States that Moment.js is a legacy project in maintenance mode.');
51
+ const TSLINT_README = src('https://github.com/palantir/tslint', 'TSLint repository README', 'supports', 'Says TSLint is deprecated, points to ESLint as the replacement, and shows the repository archived on 2021-03-25.');
52
+ const LIBSASS_DEPRECATED = src('https://sass-lang.com/blog/libsass-is-deprecated/', 'Sass blog, LibSass is deprecated', 'contradicts', 'Says LibSass and Node Sass are deprecated and Dart Sass is the replacement, but also says LibSass and Node Sass will continue to be maintained indefinitely on a best-effort basis, which contradicts the detector wording that LibSass is no longer maintained.');
53
+ const REQUEST_ISSUE = src('https://github.com/request/request/issues/3142', 'request issue 3142, consider deprecating', 'context', 'Shows the maintainers discussing maintenance mode and deprecation and an npm warning that request has been deprecated quoted in an October 2022 comment; no 2020 deprecation date appears on the page.');
54
+ const REQUEST_NPM = src('https://registry.npmjs.org/request/latest', 'npm registry entry for the latest request release', 'supports', 'The registry marks the latest release deprecated with the message: request has been deprecated, see https://github.com/request/request/issues/3142.');
55
+ const CRA_SUNSET = src('https://react.dev/blog/2025/02/14/sunsetting-create-react-app', 'React blog, sunsetting Create React App', 'supports', 'Announces on 2025-02-14 that Create React App is deprecated for new apps and in maintenance mode; the page never names the react-scripts package.');
56
+ const ENZYME_README = src('https://github.com/enzymejs/enzyme', 'Enzyme repository README', 'context', 'Lists adapters only up to enzyme-adapter-react-16 and states no maintenance status or React 17 or 18 adapter, so it neither confirms nor refutes that Enzyme is unmaintained.');
57
+ const VUE2_EOL = src('https://v2.vuejs.org/', 'Vue 2 documentation', 'supports', 'States that Vue 2 has reached EOL and is no longer actively maintained, without giving a date on the page.');
58
+ // ── Rust, Go, .NET, Unity ─────────────────────────────────────────────────────
59
+ const CARGO_RUST_VERSION = src('https://doc.rust-lang.org/cargo/reference/rust-version.html', 'Cargo rust-version reference', 'supports', 'Says rust-version sets the minimum supported Rust version, must be a bare version number without operators, and makes Cargo error on an older toolchain.');
60
+ const CARGO_TEST = src('https://doc.rust-lang.org/cargo/commands/cargo-test.html', 'cargo test reference', 'supports', 'Says cargo test compiles and runs a package unit, integration and documentation tests.');
61
+ const CLIPPY_USAGE = src('https://doc.rust-lang.org/clippy/usage.html', 'Clippy usage', 'supports', 'Says Clippy can be used as a cargo subcommand or directly with the clippy-driver binary; the page does not state in one sentence what Clippy is for.');
62
+ const CARGO_FMT = src('https://doc.rust-lang.org/cargo/commands/cargo-fmt.html', 'cargo fmt reference', 'context', 'Documents cargo fmt as formatting the bin and lib files of a crate, shipped as an optional toolchain component that may need installing separately.');
63
+ const CARGO_SEMVER_ZERO = src('https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html', 'Cargo specifying dependencies', 'supports', 'Says for versions below 1.0 the left-most non-zero component decides compatibility, so ^0.2.3 allows >=0.2.3 and <0.3.0, which backs treating a 0.2 to 0.3 change as significant for crates such as tokio and axum.');
64
+ const RUST_EDITIONS = src('https://doc.rust-lang.org/edition-guide/editions/index.html', 'Rust edition guide, what are editions', 'context', 'Says each crate chooses its edition in Cargo.toml and that crates of different editions interoperate; the fetched page names only the 2018 edition, so the year values the detector compares are not listed on it.');
65
+ const GO_MOD_REF = src('https://go.dev/ref/mod', 'Go modules reference', 'supports', 'Says a module is defined by a go.mod file in its root directory and that the go directive sets the minimum Go version and changes behaviour at thresholds such as go 1.14, 1.16 and 1.17.');
66
+ const GO_TEST = src('https://pkg.go.dev/cmd/go#hdr-Test_packages', 'go command, test packages', 'supports', 'Says go test compiles each named package with its _test.go files, runs the test binary and prints a summary; the visible text does not define the ./... pattern.');
67
+ const GO_118 = src('https://go.dev/doc/go1.18', 'Go 1.18 release notes', 'supports', 'Says Go 1.18 includes an implementation of generics as described by the type parameters proposal.');
68
+ const DOTNET_FRAMEWORKS = src('https://learn.microsoft.com/en-us/dotnet/standard/frameworks', 'Target frameworks in SDK-style projects', 'supports', 'Lists net5.0 and later and netcoreapp3.1 as target framework monikers, specified with the TargetFramework element in the project file.');
69
+ const DOTNET_POLICY = src('https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core', '.NET support policy', 'supports', 'Lists .NET 5 as ended on 2022-05-10 and .NET Core 3.1 on 2022-12-13, and also lists .NET 6, 7, 8 and 9 as ended, so the detector cut-off at .NET 5 understates what is out of support.');
70
+ const DOTNET_BUILD = src('https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-build', 'dotnet build command', 'context', 'Says dotnet build accepts a project file or a solution file with a .sln or .slnx extension; the detector recognises .sln and .csproj but not .slnx.');
71
+ const DOTNET_TEST = src('https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test', 'dotnet test command', 'supports', 'Says dotnet test builds the solution and runs the tests with VSTest or Microsoft Testing Platform.');
72
+ const UNITY_MONOBEHAVIOUR_MANUAL = src('https://docs.unity.com/en-us/engine/6000.6/manual/scripting/get-started/fundamental-unity-types/class-mono-behaviour', 'Unity manual, MonoBehaviour', 'supports', 'Warns that defining a constructor for a MonoBehaviour interferes with the normal operation of Unity, and describes Start and Update as the initialisation and per-frame hooks; it says nothing about empty methods costing performance.');
73
+ const UNITY_MONOBEHAVIOUR_REF = src('https://docs.unity.com/en-us/engine/6000.6/script-reference/unityengine/monobehaviour', 'Unity script reference, MonoBehaviour', 'supports', 'Says a MonoBehaviour always exists as a Component of a GameObject and can be instantiated with GameObject.AddComponent; it does not explicitly forbid new and does not mention empty event methods.');
74
+ const UNITY_SERIALIZE_FIELD = src('https://docs.unity.com/en-us/engine/6000.6/script-reference/unityengine/serializefield', 'Unity script reference, SerializeField', 'supports', 'Says SerializeField forces Unity to serialize a private field and that Unity only serializes public fields by default; the page does not mention the Inspector.');
75
+ const UNITY_META = src('https://docs.unity.com/en-us/engine/6000.6/manual/assets-and-media/import-assets/asset-metadata', 'Unity manual, asset metadata', 'supports', 'Says Unity creates a .meta file per asset holding its unique ID and import settings, that losing it breaks references to the asset, and that moving an asset outside Unity requires moving its .meta file too; it does not say never to edit it.');
76
+ const UNITY_TEST_FRAMEWORK = src('https://docs.unity3d.com/Packages/com.unity.test-framework@1.4/manual/index.html', 'Unity Test Framework manual', 'supports', 'Says the Unity Test Framework tests code in Edit Mode and Play Mode and was previously called the Unity Test Runner; the menu path is not given on the page.');
77
+ // ── Git, GitHub Actions, security ─────────────────────────────────────────────
78
+ const GITIGNORE = src('https://git-scm.com/docs/gitignore', 'gitignore documentation', 'supports', 'Says the last matching pattern decides, lower-level .gitignore files override higher ones, a trailing slash matches only directories, and it is not possible to re-include a file if a parent directory is excluded.');
79
+ const GIT_PUSH = src('https://git-scm.com/docs/git-push', 'git push documentation', 'context', 'Says --force can cause the remote repository to lose commits and describes --force-with-lease as saying you expect the remote to hold the history you are replacing; the page does not recommend one over the other.');
80
+ const GH_SECURE_USE = src('https://docs.github.com/en/actions/reference/security/secure-use', 'GitHub Actions secure use reference', 'supports', 'Says pinning an action to a full-length commit SHA mitigates a backdoor being added to the action repository and that a tag can be moved or deleted if a bad actor gains access to the repository.');
81
+ const GH_WORKFLOW_SYNTAX = src('https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax', 'GitHub Actions workflow syntax', 'supports', 'Says the commit SHA of a released action version is the safest for stability and security, a branch reference is risky, ./ refers to an action in the same repository, and docker:// references use image tags.');
82
+ const SUPABASE_KEYS = src('https://supabase.com/docs/guides/getting-started/api-keys', 'Supabase API keys', 'supports', 'Says the secret and service_role key bypasses every Row Level Security policy and must never be put in a browser, a shipped application or source control.');
83
+ const OWASP_SECRETS = src('https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html', 'OWASP Secrets Management Cheat Sheet', 'supports', 'Advises avoiding checking secrets into code, says secrets should never be logged, and warns against hardcoding them; it has no blanket rule about printing to a console.');
84
+ const OWASP_UPLOAD = src('https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html', 'OWASP File Upload Cheat Sheet', 'supports', 'Recommends an allowlist of extensions, not trusting the Content-Type header and setting a file size limit for uploads.');
85
+ const CURSOR_IGNORE = src('https://cursor.com/docs/reference/ignore-file', 'Cursor ignore files', 'contradicts', 'Says Cursor ignores files in .gitignore and also a default ignore list (.env*, *.lock, node_modules/, .git/) and blocks Agent and Tab access to files in .cursorignore, so it skips more than gitignored paths; terminal and MCP tools are not blocked.');
86
+ const CLAUDE_SETTINGS_REFERENCE = src('https://code.claude.com/docs/en/settings-reference', 'Claude Code settings reference', 'context', 'Lists respectGitignore only as keeping gitignored files out of the @ file picker and shows no setting making gitignore govern file reads, which are controlled by permissions.deny rules.');
87
+ const CLAUDE_MEMORY = src('https://code.claude.com/docs/en/memory', 'Claude Code memory and CLAUDE.md', 'supports', 'Says CLAUDE.md files import other files with @path/to/import syntax, relative paths resolve against the importing file, imports nest to a depth of four, and code spans and fenced blocks are skipped.');
88
+ const CLAUDE_BEST_PRACTICES = src('https://code.claude.com/docs/en/best-practices', 'Claude Code best practices', 'supports', 'Says that when a repo already has a check, the single most useful line in CLAUDE.md is the command that runs it, because Claude otherwise has no way to verify its own work.');
89
+ const TS_NOEMIT = src('https://www.typescriptlang.org/tsconfig/#noEmit', 'TypeScript tsconfig reference, noEmit', 'supports', 'Says noEmit stops the compiler producing output files and leaves TypeScript for editor integration and type checking.');
90
+ export const REPO_CHECKS_PROVENANCE = [
91
+ // ── dead-references ─────────────────────────────────────────────────────────
92
+ {
93
+ id: 'dead-references',
94
+ detector: 'dead-references',
95
+ title: 'Dead file and directory references',
96
+ kind: 'repo-fact',
97
+ claim: 'A link, @-reference or code-span path in an instruction file that names a file or directory absent from the scanned repository is a dead reference.',
98
+ appliesTo: 'all',
99
+ sources: [],
100
+ thresholds: [
101
+ {
102
+ name: 'MAX_UNANCHORED_DEPTH',
103
+ value: 2,
104
+ unit: 'missing path levels below a first segment that exists',
105
+ where: 'dead-references.ts:MAX_UNANCHORED_DEPTH',
106
+ source: 'unverified',
107
+ },
108
+ {
109
+ name: 'MIN_CONFIDENCE',
110
+ value: 0.45,
111
+ unit: 'confidence score',
112
+ where: 'dead-references.ts:MIN_CONFIDENCE',
113
+ source: 'unverified',
114
+ },
115
+ {
116
+ name: 'minimum path segments for a code-span directory',
117
+ value: 2,
118
+ unit: 'path segments',
119
+ where: 'dead-references.ts:BACKTICK_DIR_RE',
120
+ source: 'unverified',
121
+ },
122
+ ],
123
+ lastVerified: VERIFIED,
124
+ },
125
+ {
126
+ id: 'dead-references/at-imports',
127
+ detector: 'dead-references',
128
+ title: 'At-sign file imports',
129
+ kind: 'tool-fact',
130
+ claim: 'An @path reference in a CLAUDE.md file is a file import that Claude Code resolves relative to the importing file, so a missing target is a broken instruction.',
131
+ appliesTo: ['claude-code'],
132
+ sources: [CLAUDE_MEMORY],
133
+ lastVerified: VERIFIED,
134
+ },
135
+ {
136
+ id: 'dead-references/gitignore-matching',
137
+ detector: 'dead-references',
138
+ title: 'Gitignored paths are expected to be absent',
139
+ kind: 'tool-fact',
140
+ claim: 'A path that the repository gitignore rules exclude is expected to be missing from a checkout, with the last matching rule winning, deeper gitignore files overriding shallower ones and files under an ignored directory ignored.',
141
+ appliesTo: 'n/a',
142
+ sources: [GITIGNORE],
143
+ lastVerified: VERIFIED,
144
+ },
145
+ {
146
+ id: 'dead-references/credential-paths',
147
+ detector: 'dead-references',
148
+ title: 'Credential and local-config paths are expected to be absent',
149
+ kind: 'opinion',
150
+ claim: 'A referenced .env file, secrets file, local-override config, private key or certificate is deliberately kept out of the repository, so its absence is not a stale reference.',
151
+ appliesTo: 'all',
152
+ sources: [],
153
+ unverified: true,
154
+ lastVerified: VERIFIED,
155
+ },
156
+ // ── command-validity ────────────────────────────────────────────────────────
157
+ {
158
+ id: 'command-validity',
159
+ detector: 'command-validity',
160
+ title: 'Documented commands name scripts, files and targets that exist',
161
+ kind: 'repo-fact',
162
+ claim: 'A command in an instruction file that names a package script, file path or make target that the scanned repository does not define will fail when run.',
163
+ appliesTo: 'all',
164
+ sources: [],
165
+ thresholds: [
166
+ { name: 'MAX_MANIFEST_DIRS', value: 2000, unit: 'directories', where: 'command-validity.ts:MAX_MANIFEST_DIRS', source: 'unverified' },
167
+ { name: 'MAX_MANIFEST_DEPTH', value: 12, unit: 'directory levels', where: 'command-validity.ts:MAX_MANIFEST_DEPTH', source: 'unverified' },
168
+ { name: 'MAX_MANIFEST_BYTES', value: 524288, unit: 'bytes per package.json', where: 'command-validity.ts:MAX_MANIFEST_BYTES', source: 'unverified' },
169
+ { name: 'MAX_TOKENS', value: 24, unit: 'directory names read from the text around a command', where: 'command-context.ts:MAX_TOKENS', source: 'unverified' },
170
+ { name: 'MAX_WORKSPACE_MANIFESTS', value: 200, unit: 'package.json files', where: 'workspace-manifests.ts:MAX_WORKSPACE_MANIFESTS', source: 'unverified' },
171
+ { name: 'CLOSE_MATCH_MAX_DISTANCE', value: 2, unit: 'edits', where: 'close-match.ts:CLOSE_MATCH_MAX_DISTANCE', source: 'unverified' },
172
+ { name: 'CLOSE_MATCH_MIN_LENGTH', value: 4, unit: 'characters', where: 'close-match.ts:CLOSE_MATCH_MIN_LENGTH', source: 'unverified' },
173
+ { name: 'MECHANICAL_TWO_EDIT_MIN_LENGTH', value: 8, unit: 'characters', where: 'close-match.ts:MECHANICAL_TWO_EDIT_MIN_LENGTH', source: 'unverified' },
174
+ { name: 'MECHANICAL_SEGMENT_MIN_LENGTH', value: 5, unit: 'characters', where: 'close-match.ts:MECHANICAL_SEGMENT_MIN_LENGTH', source: 'unverified' },
175
+ ],
176
+ lastVerified: VERIFIED,
177
+ },
178
+ {
179
+ id: 'command-validity/package-manager-scripts',
180
+ detector: 'command-validity',
181
+ title: 'How npm, pnpm, yarn and bun resolve a script name',
182
+ kind: 'tool-fact',
183
+ claim: 'npm and pnpm treat run-script as an alias of run, pnpm and yarn and bun also run a script or an installed binary through the bare form, and a built-in command takes precedence over a same-named script.',
184
+ appliesTo: 'n/a',
185
+ sources: [NPM_RUN, PNPM_RUN, YARN_RUN, BUN_RUN],
186
+ lastVerified: VERIFIED,
187
+ },
188
+ {
189
+ id: 'command-validity/workspaces',
190
+ detector: 'command-validity',
191
+ title: 'Workspace selectors and where workspace packages come from',
192
+ kind: 'tool-fact',
193
+ claim: 'pnpm --filter, npm -w and --workspace, and the workspaces globs of package.json or pnpm-workspace.yaml decide which workspace package a script command runs in, with conventional apps, packages and libs roots assumed when none are declared.',
194
+ appliesTo: 'n/a',
195
+ sources: [PNPM_FILTER, NPM_WORKSPACES, PNPM_WORKSPACE_YAML],
196
+ lastVerified: VERIFIED,
197
+ },
198
+ {
199
+ id: 'command-validity/make-targets',
200
+ detector: 'command-validity',
201
+ title: 'Which Makefile make reads and what counts as a target',
202
+ kind: 'tool-fact',
203
+ claim: 'GNU make reads GNUmakefile, then makefile, then Makefile when no -f is given, and a target can come from an explicit rule, a .PHONY name, a pattern rule or a built-in implicit rule.',
204
+ appliesTo: 'n/a',
205
+ sources: [GNU_MAKE_NAMES],
206
+ lastVerified: VERIFIED,
207
+ },
208
+ // ── manifest-consistency ────────────────────────────────────────────────────
209
+ {
210
+ id: 'manifest-consistency',
211
+ detector: 'manifest-consistency',
212
+ title: 'Instructions agree with the repository manifests',
213
+ kind: 'repo-fact',
214
+ claim: 'An instruction file that names a Python or Node.js version, a library major version, a package manager, a script or a test tool that differs from what pyproject.toml, package.json or the lockfile declares disagrees with the repository.',
215
+ appliesTo: 'all',
216
+ sources: [],
217
+ thresholds: [
218
+ { name: 'Python library intent window before', value: 80, unit: 'characters', where: 'manifest-consistency.ts:hasCompatibilityIntent', source: 'unverified' },
219
+ { name: 'Python library intent window after', value: 120, unit: 'characters', where: 'manifest-consistency.ts:hasCompatibilityIntent', source: 'unverified' },
220
+ { name: 'JavaScript library intent window before', value: 100, unit: 'characters', where: 'manifest-consistency.ts:hasJsVersionIntent', source: 'unverified' },
221
+ { name: 'JavaScript library intent window after', value: 140, unit: 'characters', where: 'manifest-consistency.ts:hasJsVersionIntent', source: 'unverified' },
222
+ ],
223
+ lastVerified: VERIFIED,
224
+ },
225
+ {
226
+ id: 'manifest-consistency/package-manager-and-engines',
227
+ detector: 'manifest-consistency',
228
+ title: 'packageManager field, lockfiles and engines.node',
229
+ kind: 'tool-fact',
230
+ claim: 'The packageManager field of package.json names the project package manager as name@version, the lockfile is the fallback signal, and engines.node states the Node.js versions the package works on.',
231
+ appliesTo: 'n/a',
232
+ sources: [COREPACK, NPM_PACKAGE_JSON],
233
+ lastVerified: VERIFIED,
234
+ },
235
+ {
236
+ id: 'manifest-consistency/python-manifest',
237
+ detector: 'manifest-consistency',
238
+ title: 'Python version and Poetry projects in pyproject.toml',
239
+ kind: 'tool-fact',
240
+ claim: 'A pyproject.toml states the required Python version in requires-python or in the Poetry python dependency, and a Poetry project is installed from pyproject.toml rather than from a requirements.txt.',
241
+ appliesTo: 'n/a',
242
+ sources: [POETRY_PYPROJECT, PYPA_PYPROJECT],
243
+ lastVerified: VERIFIED,
244
+ },
245
+ // ── dependency-staleness ────────────────────────────────────────────────────
246
+ {
247
+ id: 'dependency-staleness',
248
+ detector: 'dependency-staleness',
249
+ title: 'Packages named in instructions that no manifest declares',
250
+ kind: 'repo-fact',
251
+ claim: 'An npm package named by an install command or import line in an instruction file that no package.json in the scanned repository declares is a missing dependency.',
252
+ appliesTo: 'all',
253
+ sources: [],
254
+ thresholds: [
255
+ { name: 'EXTRA_MANIFEST_LIMIT', value: 200, unit: 'package.json files', where: 'dependency-staleness.ts:EXTRA_MANIFEST_LIMIT', source: 'unverified' },
256
+ { name: 'NgModule file search depth', value: 8, unit: 'directory levels', where: 'dependency-staleness.ts:hasNgModuleFiles', source: 'unverified' },
257
+ ],
258
+ lastVerified: VERIFIED,
259
+ },
260
+ {
261
+ id: 'dependency-staleness/deprecated-packages',
262
+ detector: 'dependency-staleness',
263
+ title: 'Packages their maintainers have deprecated or stopped maintaining',
264
+ kind: 'tool-fact',
265
+ claim: 'moment is in maintenance mode, request, tslint and node-sass are deprecated, react-scripts belongs to the deprecated Create React App, and enzyme has no adapter for current React versions.',
266
+ appliesTo: 'n/a',
267
+ sources: [MOMENT_STATUS, REQUEST_NPM, REQUEST_ISSUE, TSLINT_README, LIBSASS_DEPRECATED, CRA_SUNSET, ENZYME_README],
268
+ lastVerified: VERIFIED,
269
+ },
270
+ {
271
+ id: 'dependency-staleness/version-gated-apis',
272
+ detector: 'dependency-staleness',
273
+ title: 'APIs that a framework major version removed or replaced',
274
+ kind: 'tool-fact',
275
+ claim: 'ReactDOM.render was deprecated in React 18 and removed in React 19, and getInitialProps belongs to the Next.js Pages Router only.',
276
+ appliesTo: 'n/a',
277
+ sources: [REACT_19, REACT_18, NEXT_GET_INITIAL_PROPS, NEXT_MIGRATION_SUPPORTS],
278
+ thresholds: [
279
+ { name: 'ReactDOM.render warning at React major', value: 18, unit: 'major version', where: 'dependency-staleness.ts:checkReactRender', source: REACT_18 },
280
+ { name: 'ReactDOM.render removed at React major', value: 19, unit: 'major version', where: 'dependency-staleness.ts:checkReactRender', source: REACT_19 },
281
+ ],
282
+ lastVerified: VERIFIED,
283
+ },
284
+ {
285
+ id: 'dependency-staleness/angular-standalone-default',
286
+ refuted: true,
287
+ detector: 'dependency-staleness',
288
+ title: 'Angular standalone components by default',
289
+ kind: 'tool-fact',
290
+ claim: 'Angular 17 and later projects default to standalone components rather than NgModules.',
291
+ appliesTo: 'n/a',
292
+ sources: [ANGULAR_COMPONENTS, { ...ANGULAR_NGMODULES, stance: 'context' }],
293
+ thresholds: [
294
+ { name: 'NgModule guidance stale from Angular major (the detector value; the standalone default arrives in 19.0.0)', value: 17, unit: 'major version', where: 'dependency-staleness.ts:checkNgModule', source: 'unverified' },
295
+ ],
296
+ lastVerified: VERIFIED,
297
+ },
298
+ // ── ci-alignment ────────────────────────────────────────────────────────────
299
+ {
300
+ id: 'ci-alignment',
301
+ detector: 'ci-alignment',
302
+ title: 'CI runs checks the instructions do not mention',
303
+ kind: 'repo-fact',
304
+ claim: 'A GitHub workflow that runs lint, typecheck, test, build or format while no instruction file tells the agent to run it, or that uses a different package manager than the instructions, is out of step with the instructions.',
305
+ appliesTo: 'all',
306
+ sources: [],
307
+ lastVerified: VERIFIED,
308
+ },
309
+ {
310
+ id: 'ci-alignment/package-scripts',
311
+ detector: 'ci-alignment',
312
+ title: 'Package-manager command forms used to recognise CI tasks',
313
+ kind: 'tool-fact',
314
+ claim: 'npm, pnpm, yarn and bun run a package script through the run form, and npm test, start, stop and restart are built-in lifecycle commands rather than user scripts.',
315
+ appliesTo: 'n/a',
316
+ sources: [NPM_RUN, PNPM_RUN, YARN_RUN, BUN_RUN],
317
+ lastVerified: VERIFIED,
318
+ },
319
+ {
320
+ id: 'ci-alignment/typecheck-vs-build',
321
+ detector: 'ci-alignment',
322
+ title: 'tsc --noEmit is a typecheck and bare tsc is a build',
323
+ kind: 'tool-fact',
324
+ claim: 'Running tsc with --noEmit type-checks without writing output files, while running tsc without it emits compiled output as a build.',
325
+ appliesTo: 'n/a',
326
+ sources: [TS_NOEMIT],
327
+ lastVerified: VERIFIED,
328
+ },
329
+ // ── conflicts ───────────────────────────────────────────────────────────────
330
+ {
331
+ id: 'conflicts',
332
+ detector: 'conflicts',
333
+ title: 'Contradictory directives in instruction files',
334
+ kind: 'repo-fact',
335
+ claim: 'Two instruction sections that carry opposite directives such as use against do not use, or always against never, about the same or a highly similar subject contradict each other.',
336
+ appliesTo: 'all',
337
+ sources: [],
338
+ thresholds: [
339
+ { name: 'subject word overlap for a partial match', value: 0.5, unit: 'Jaccard similarity', where: 'conflicts.ts:detectConflicts', source: 'unverified' },
340
+ { name: 'minimum confidence to report', value: 0.4, unit: 'confidence score', where: 'conflicts.ts:detectConflicts', source: 'unverified' },
341
+ { name: 'confidence at which severity becomes high', value: 0.7, unit: 'confidence score', where: 'conflicts.ts:detectConflicts', source: 'unverified' },
342
+ { name: 'subject words kept after a directive', value: 3, unit: 'words', where: 'conflicts.ts:extractSubjectWords', source: 'unverified' },
343
+ { name: 'subject words kept before a directive', value: 4, unit: 'words', where: 'conflicts.ts:extractSubjectWordsBefore', source: 'unverified' },
344
+ { name: 'minimum tokens per side for a partial match', value: 2, unit: 'words', where: 'conflicts.ts:detectConflicts', source: 'unverified' },
345
+ { name: 'MIN_SECTION_LENGTH', value: 1, unit: 'characters', where: 'conflicts.ts:MIN_SECTION_LENGTH', source: 'unverified' },
346
+ ],
347
+ lastVerified: VERIFIED,
348
+ },
349
+ // ── version-conflicts ───────────────────────────────────────────────────────
350
+ {
351
+ id: 'version-conflicts',
352
+ detector: 'version-conflicts',
353
+ title: 'Instruction files state different versions of one framework',
354
+ kind: 'repo-fact',
355
+ claim: 'Two different instruction files that each positively state a different version of the same framework or runtime disagree with each other.',
356
+ appliesTo: 'all',
357
+ sources: [],
358
+ thresholds: [
359
+ { name: 'minimum instruction files', value: 2, unit: 'files', where: 'conflicts.ts:detectVersionConflicts', source: 'unverified' },
360
+ { name: 'finding confidence', value: 0.75, unit: 'confidence score', where: 'conflicts.ts:detectVersionConflicts', source: 'unverified' },
361
+ ],
362
+ lastVerified: VERIFIED,
363
+ },
364
+ {
365
+ id: 'version-conflicts/version-significance',
366
+ detector: 'version-conflicts',
367
+ title: 'Which version differences are significant',
368
+ kind: 'tool-fact',
369
+ claim: 'A difference in major version is significant for most frameworks, a difference in Go minor version is significant, and for Rust crates below 1.0 a change of minor version is a compatibility break.',
370
+ appliesTo: 'n/a',
371
+ sources: [CARGO_SEMVER_ZERO, GO_MOD_REF, RUST_EDITIONS],
372
+ lastVerified: VERIFIED,
373
+ },
374
+ // ── competing-tech-conflicts ────────────────────────────────────────────────
375
+ {
376
+ id: 'competing-tech-conflicts',
377
+ detector: 'competing-tech-conflicts',
378
+ title: 'Mutually exclusive technology choices',
379
+ kind: 'opinion',
380
+ claim: 'Instruction files that recommend competing options for one dimension, such as redux against zustand, kebab-case against camelCase file names or pip against poetry, leave an agent unable to choose.',
381
+ appliesTo: 'all',
382
+ sources: [],
383
+ unverified: true,
384
+ thresholds: [
385
+ { name: 'minimum instruction files', value: 2, unit: 'files', where: 'conflicts.ts:detectCompetingTechConflicts', source: 'unverified' },
386
+ { name: 'finding confidence', value: 0.6, unit: 'confidence score', where: 'conflicts.ts:detectCompetingTechConflicts', source: 'unverified' },
387
+ ],
388
+ lastVerified: VERIFIED,
389
+ },
390
+ {
391
+ id: 'competing-tech-conflicts/nextjs-routers',
392
+ refuted: true,
393
+ detector: 'competing-tech-conflicts',
394
+ title: 'Pages Router and App Router treated as exclusive',
395
+ kind: 'tool-fact',
396
+ claim: 'The Next.js Pages Router and App Router are mutually exclusive routing strategies, so instruction files recommending one and the other conflict.',
397
+ appliesTo: 'n/a',
398
+ sources: [NEXT_MIGRATION],
399
+ lastVerified: VERIFIED,
400
+ },
401
+ // ── stale-instructions ──────────────────────────────────────────────────────
402
+ {
403
+ id: 'stale-instructions',
404
+ detector: 'stale-instructions',
405
+ title: 'Past years, cleanup markers and deprecated notes',
406
+ kind: 'opinion',
407
+ claim: 'An instruction section that names a calendar year from the last seven, a workaround or temporary fix marker, a dated TODO comment or a deprecated tool is likely out of date.',
408
+ appliesTo: 'all',
409
+ sources: [],
410
+ unverified: true,
411
+ thresholds: [
412
+ { name: 'STALE_YEAR_WINDOW', value: 7, unit: 'years before the current year', where: 'stale-instructions.ts:STALE_YEAR_WINDOW', source: 'unverified' },
413
+ { name: 'negation context lookback', value: 80, unit: 'characters', where: 'stale-instructions.ts:isVersionInNegationContext', source: 'unverified' },
414
+ { name: 'deprecated-near-tool window', value: 60, unit: 'characters', where: 'stale-instructions.ts:DEPRECATED_NEAR_VERSION_RE', source: 'unverified' },
415
+ ],
416
+ lastVerified: VERIFIED,
417
+ },
418
+ {
419
+ id: 'stale-instructions/end-of-life-runtimes',
420
+ detector: 'stale-instructions',
421
+ title: 'End-of-life runtime versions',
422
+ kind: 'tool-fact',
423
+ claim: 'Node.js 16 and earlier, Python 3.9 and earlier, Python 2, .NET 5 and earlier and Vue 2 are past end of life, and Go 1.17 and earlier pre-date generics.',
424
+ appliesTo: 'n/a',
425
+ sources: [NODE_RELEASES, PYTHON_DEVGUIDE, DOTNET_POLICY, VUE2_EOL, GO_118],
426
+ thresholds: [
427
+ { name: 'Node.js newest flagged major', value: 16, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: NODE_RELEASES },
428
+ { name: 'Python newest flagged 3.x minor', value: 9, unit: 'minor version of 3', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: PYTHON_DEVGUIDE },
429
+ { name: '.NET newest flagged major', value: 5, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: DOTNET_POLICY },
430
+ { name: 'Go newest flagged 1.x minor', value: 17, unit: 'minor version of 1', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: GO_118 },
431
+ ],
432
+ lastVerified: VERIFIED,
433
+ },
434
+ {
435
+ id: 'stale-instructions/old-framework-majors',
436
+ detector: 'stale-instructions',
437
+ title: 'Old framework and tool majors',
438
+ kind: 'tool-fact',
439
+ claim: 'React 16 and earlier, Next.js 9 and earlier, Angular 9 and earlier, Webpack 3 and earlier, Babel 6 and earlier, TypeScript 3 and earlier and Unity 2019 and earlier are old enough that instructions naming them are stale.',
440
+ appliesTo: 'n/a',
441
+ sources: [],
442
+ unverified: true,
443
+ thresholds: [
444
+ { name: 'React newest flagged major', value: 16, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
445
+ { name: 'Next.js newest flagged major', value: 9, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
446
+ { name: 'Angular newest flagged major', value: 9, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
447
+ { name: 'Webpack newest flagged major', value: 3, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
448
+ { name: 'Babel newest flagged major', value: 6, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
449
+ { name: 'TypeScript newest flagged major', value: 3, unit: 'major version', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
450
+ { name: 'Unity newest flagged year', value: 2019, unit: 'release year', where: 'stale-instructions.ts:OLD_VERSION_PATTERNS', source: 'unverified' },
451
+ ],
452
+ lastVerified: VERIFIED,
453
+ },
454
+ // ── action-pinning ──────────────────────────────────────────────────────────
455
+ {
456
+ id: 'action-pinning',
457
+ detector: 'action-pinning',
458
+ title: 'Tag and branch action references are mutable',
459
+ kind: 'tool-fact',
460
+ claim: 'A GitHub Actions uses reference pinned to a tag or branch can be moved by whoever controls the action repository, while a full commit SHA cannot be repointed.',
461
+ appliesTo: 'n/a',
462
+ sources: [GH_SECURE_USE, GH_WORKFLOW_SYNTAX],
463
+ thresholds: [
464
+ { name: 'SHA-1 commit id length', value: 40, unit: 'hex characters', where: 'action-pinning.ts:FULL_SHA_RE', source: 'unverified' },
465
+ { name: 'SHA-256 commit id length', value: 64, unit: 'hex characters', where: 'action-pinning.ts:FULL_SHA_RE', source: 'unverified' },
466
+ ],
467
+ lastVerified: VERIFIED,
468
+ },
469
+ {
470
+ id: 'action-pinning/exempt-references',
471
+ detector: 'action-pinning',
472
+ title: 'Local and container action references have no git ref to pin',
473
+ kind: 'tool-fact',
474
+ claim: 'A local ./ action lives in the same repository and a docker:// action names an image rather than a git ref, so a commit SHA pin does not apply to either.',
475
+ appliesTo: 'n/a',
476
+ sources: [GH_WORKFLOW_SYNTAX],
477
+ lastVerified: VERIFIED,
478
+ },
479
+ {
480
+ id: 'action-pinning/first-party-owners',
481
+ detector: 'action-pinning',
482
+ title: 'GitHub-maintained actions carry a lower risk',
483
+ kind: 'opinion',
484
+ claim: 'An unpinned action owned by the actions or github organisations is a lower risk than an unpinned third-party action, though still a mutable pointer.',
485
+ appliesTo: 'all',
486
+ sources: [],
487
+ unverified: true,
488
+ lastVerified: VERIFIED,
489
+ },
490
+ // ── security-pack ───────────────────────────────────────────────────────────
491
+ {
492
+ id: 'security-pack',
493
+ detector: 'security-pack',
494
+ title: 'Security signals in the repository',
495
+ kind: 'repo-fact',
496
+ claim: 'A repository that has an env file, a Supabase dependency, upload code or a .promptci directory while no instruction file carries the matching safeguard wording lacks that safeguard in its instructions.',
497
+ appliesTo: 'all',
498
+ sources: [],
499
+ lastVerified: VERIFIED,
500
+ },
501
+ {
502
+ id: 'security-pack/secret-handling',
503
+ unverified: true,
504
+ detector: 'security-pack',
505
+ title: 'Instructions should say never to print or commit secrets',
506
+ kind: 'opinion',
507
+ claim: 'A repository that uses environment variables should tell the agent in its instructions never to print, log or commit secrets, API keys or credentials.',
508
+ appliesTo: 'all',
509
+ sources: [{ ...OWASP_SECRETS, stance: 'context' }],
510
+ lastVerified: VERIFIED,
511
+ },
512
+ {
513
+ id: 'security-pack/supabase-service-role',
514
+ detector: 'security-pack',
515
+ title: 'Supabase service role key stays server-side',
516
+ kind: 'tool-fact',
517
+ claim: 'The Supabase service role key bypasses Row Level Security and must only be used server-side, never in browser code, logs or committed files.',
518
+ appliesTo: 'n/a',
519
+ sources: [SUPABASE_KEYS],
520
+ lastVerified: VERIFIED,
521
+ },
522
+ {
523
+ id: 'security-pack/upload-validation',
524
+ unverified: true,
525
+ detector: 'security-pack',
526
+ title: 'Instructions should define upload validation',
527
+ kind: 'opinion',
528
+ claim: 'A repository with file upload code should document allowed file types, a size limit and validation steps for user-provided files in its instructions.',
529
+ appliesTo: 'all',
530
+ sources: [{ ...OWASP_UPLOAD, stance: 'context' }],
531
+ lastVerified: VERIFIED,
532
+ },
533
+ {
534
+ id: 'security-pack/destructive-commands',
535
+ unverified: true,
536
+ detector: 'security-pack',
537
+ title: 'Destructive commands need safety language',
538
+ kind: 'opinion',
539
+ claim: 'An instruction file that names rm -rf, drop table or git push --force should carry nearby language such as ask before running or confirm before, so an agent does not run it unprompted.',
540
+ appliesTo: 'all',
541
+ sources: [GIT_PUSH],
542
+ lastVerified: VERIFIED,
543
+ },
544
+ {
545
+ id: 'security-pack/gitignore-semantics',
546
+ detector: 'security-pack',
547
+ title: 'How gitignore matches and re-includes paths',
548
+ kind: 'tool-fact',
549
+ claim: 'A gitignore negation cannot re-include a file under an excluded parent directory, so ignoring .promptci with a carve-out needs .promptci/* rather than .promptci/, and a line ignores a directory only when a path segment matches its name exactly.',
550
+ appliesTo: 'n/a',
551
+ sources: [GITIGNORE],
552
+ lastVerified: VERIFIED,
553
+ },
554
+ {
555
+ id: 'security-pack/generated-directories',
556
+ refuted: true,
557
+ detector: 'security-pack',
558
+ title: 'Unignored generated directories reach AI tools',
559
+ kind: 'tool-fact',
560
+ claim: 'Directories such as coverage, dist, build and .next that are not gitignored can be read into the context of AI coding tools, which inflates token cost, because tools such as Cursor skip only gitignored paths.',
561
+ appliesTo: ['cursor', 'claude-code'],
562
+ sources: [CURSOR_IGNORE, CLAUDE_SETTINGS_REFERENCE],
563
+ lastVerified: VERIFIED,
564
+ },
565
+ // ── framework-packs ─────────────────────────────────────────────────────────
566
+ {
567
+ id: 'framework-packs/nextjs',
568
+ detector: 'framework-packs',
569
+ title: 'Next.js pack',
570
+ kind: 'tool-fact',
571
+ claim: 'In Next.js the app directory is the App Router whose layouts and pages are Server Components by default, getStaticProps and getServerSideProps and getInitialProps are Pages Router APIs, and the config file is next.config.js, .mjs or .ts.',
572
+ appliesTo: 'n/a',
573
+ sources: [NEXT_SERVER_CLIENT, NEXT_MIGRATION_SUPPORTS, NEXT_GET_INITIAL_PROPS, NEXT_CONFIG, NEXT_STRUCTURE],
574
+ lastVerified: VERIFIED,
575
+ },
576
+ {
577
+ id: 'framework-packs/python',
578
+ detector: 'framework-packs',
579
+ title: 'Python pack',
580
+ kind: 'tool-fact',
581
+ claim: 'A Pipfile marks a Pipenv project, an environment.yml marks a Conda environment, a [tool.poetry] table marks a Poetry project, and pytest runs tests by discovering test_*.py or *_test.py files.',
582
+ appliesTo: 'n/a',
583
+ sources: [PIPENV_PIPFILE, CONDA_ENVIRONMENTS, POETRY_PYPROJECT, PYTEST_START],
584
+ lastVerified: VERIFIED,
585
+ },
586
+ {
587
+ id: 'framework-packs/rust',
588
+ detector: 'framework-packs',
589
+ title: 'Rust pack',
590
+ kind: 'tool-fact',
591
+ claim: 'The rust-version key of Cargo.toml is the minimum supported Rust version, and cargo test, cargo clippy and cargo fmt are the standard Rust verification commands.',
592
+ appliesTo: 'n/a',
593
+ sources: [CARGO_RUST_VERSION, CARGO_TEST, CLIPPY_USAGE, CARGO_FMT],
594
+ lastVerified: VERIFIED,
595
+ },
596
+ {
597
+ id: 'framework-packs/go',
598
+ detector: 'framework-packs',
599
+ title: 'Go pack',
600
+ kind: 'tool-fact',
601
+ claim: 'A go.mod file in the root directory defines a Go module, and go test with the three-dot package pattern runs the tests of every package in it.',
602
+ appliesTo: 'n/a',
603
+ sources: [GO_MOD_REF, GO_TEST],
604
+ lastVerified: VERIFIED,
605
+ },
606
+ {
607
+ id: 'framework-packs/dotnet',
608
+ detector: 'framework-packs',
609
+ title: '.NET pack',
610
+ kind: 'tool-fact',
611
+ claim: 'A .sln or .csproj file marks a .NET project, its TargetFramework is a moniker such as net8.0, netcoreapp3.1 and net5.0 are out of support, and dotnet build and dotnet test are the validation commands.',
612
+ appliesTo: 'n/a',
613
+ sources: [DOTNET_FRAMEWORKS, DOTNET_POLICY, DOTNET_BUILD, DOTNET_TEST],
614
+ lastVerified: VERIFIED,
615
+ },
616
+ {
617
+ id: 'framework-packs/unity',
618
+ detector: 'framework-packs',
619
+ title: 'Unity pack',
620
+ kind: 'tool-fact',
621
+ claim: 'A MonoBehaviour is attached to a GameObject rather than created with a constructor, SerializeField makes Unity serialize a private field, a missing .meta file breaks asset references, and the Unity Test Framework runs Edit Mode and Play Mode tests.',
622
+ appliesTo: 'n/a',
623
+ sources: [
624
+ UNITY_MONOBEHAVIOUR_MANUAL,
625
+ UNITY_MONOBEHAVIOUR_REF,
626
+ UNITY_SERIALIZE_FIELD,
627
+ UNITY_META,
628
+ UNITY_TEST_FRAMEWORK,
629
+ ],
630
+ lastVerified: VERIFIED,
631
+ },
632
+ {
633
+ id: 'framework-packs/verification-guidance',
634
+ unverified: true,
635
+ detector: 'framework-packs',
636
+ title: 'Instructions should name the verification command',
637
+ kind: 'opinion',
638
+ claim: 'Instructions for a repository that uses a framework should name its verification commands so an agent runs them before declaring work complete.',
639
+ appliesTo: ['claude-code'],
640
+ sources: [{ ...CLAUDE_BEST_PRACTICES, stance: 'context' }],
641
+ lastVerified: VERIFIED,
642
+ },
643
+ ];
644
+ //# sourceMappingURL=repo-checks.js.map