repo-contract 0.3.0 → 0.3.2

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 (108) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +46 -0
  3. package/dist/.dts/config/define-repo-contract.d.ts +36 -0
  4. package/dist/.dts/config/define-repo-contract.d.ts.map +1 -0
  5. package/dist/.dts/config/tokenize-command.d.ts +33 -0
  6. package/dist/.dts/config/tokenize-command.d.ts.map +1 -0
  7. package/dist/.dts/config/validate-config.d.ts +32 -0
  8. package/dist/.dts/config/validate-config.d.ts.map +1 -0
  9. package/dist/.dts/errors.d.ts +172 -0
  10. package/dist/.dts/errors.d.ts.map +1 -0
  11. package/dist/.dts/evidence/build-evidence.d.ts +26 -0
  12. package/dist/.dts/evidence/build-evidence.d.ts.map +1 -0
  13. package/dist/.dts/execution/abort-signals.d.ts +29 -0
  14. package/dist/.dts/execution/abort-signals.d.ts.map +1 -0
  15. package/dist/.dts/execution/concurrency-pool.d.ts +14 -0
  16. package/dist/.dts/execution/concurrency-pool.d.ts.map +1 -0
  17. package/dist/.dts/execution/dependency-scheduler.d.ts +30 -0
  18. package/dist/.dts/execution/dependency-scheduler.d.ts.map +1 -0
  19. package/dist/.dts/execution/process-tree.d.ts +59 -0
  20. package/dist/.dts/execution/process-tree.d.ts.map +1 -0
  21. package/dist/.dts/execution/run-checks.d.ts +31 -0
  22. package/dist/.dts/execution/run-checks.d.ts.map +1 -0
  23. package/dist/.dts/execution/spawn-check.d.ts +49 -0
  24. package/dist/.dts/execution/spawn-check.d.ts.map +1 -0
  25. package/dist/.dts/index.d.ts +14 -0
  26. package/dist/.dts/index.d.ts.map +1 -0
  27. package/dist/.dts/parsing/format-schema-issues.d.ts +11 -0
  28. package/dist/.dts/parsing/format-schema-issues.d.ts.map +1 -0
  29. package/dist/.dts/parsing/parse-json.d.ts +8 -0
  30. package/dist/.dts/parsing/parse-json.d.ts.map +1 -0
  31. package/dist/.dts/parsing/parse-output.d.ts +25 -0
  32. package/dist/.dts/parsing/parse-output.d.ts.map +1 -0
  33. package/dist/.dts/parsing/parse-text.d.ts +8 -0
  34. package/dist/.dts/parsing/parse-text.d.ts.map +1 -0
  35. package/dist/.dts/parsing/parse-yaml.d.ts +21 -0
  36. package/dist/.dts/parsing/parse-yaml.d.ts.map +1 -0
  37. package/dist/.dts/policy/run-policies.d.ts +38 -0
  38. package/dist/.dts/policy/run-policies.d.ts.map +1 -0
  39. package/dist/.dts/presets/arethetypeswrong.d.ts +39 -0
  40. package/dist/.dts/presets/arethetypeswrong.d.ts.map +1 -0
  41. package/dist/.dts/presets/broken-links.d.ts +16 -0
  42. package/dist/.dts/presets/broken-links.d.ts.map +1 -0
  43. package/dist/.dts/presets/commitlint.d.ts +22 -0
  44. package/dist/.dts/presets/commitlint.d.ts.map +1 -0
  45. package/dist/.dts/presets/dead-code.d.ts +23 -0
  46. package/dist/.dts/presets/dead-code.d.ts.map +1 -0
  47. package/dist/.dts/presets/duplication.d.ts +14 -0
  48. package/dist/.dts/presets/duplication.d.ts.map +1 -0
  49. package/dist/.dts/presets/e2e.d.ts +4 -0
  50. package/dist/.dts/presets/e2e.d.ts.map +1 -0
  51. package/dist/.dts/presets/format.d.ts +4 -0
  52. package/dist/.dts/presets/format.d.ts.map +1 -0
  53. package/dist/.dts/presets/index.d.ts +31 -0
  54. package/dist/.dts/presets/index.d.ts.map +1 -0
  55. package/dist/.dts/presets/license.d.ts +4 -0
  56. package/dist/.dts/presets/license.d.ts.map +1 -0
  57. package/dist/.dts/presets/lint.d.ts +20 -0
  58. package/dist/.dts/presets/lint.d.ts.map +1 -0
  59. package/dist/.dts/presets/markdownlint.d.ts +23 -0
  60. package/dist/.dts/presets/markdownlint.d.ts.map +1 -0
  61. package/dist/.dts/presets/publint.d.ts +13 -0
  62. package/dist/.dts/presets/publint.d.ts.map +1 -0
  63. package/dist/.dts/presets/security-deps.d.ts +4 -0
  64. package/dist/.dts/presets/security-deps.d.ts.map +1 -0
  65. package/dist/.dts/presets/security-secrets.d.ts +4 -0
  66. package/dist/.dts/presets/security-secrets.d.ts.map +1 -0
  67. package/dist/.dts/presets/shared/error-warning-pass-policy.d.ts +13 -0
  68. package/dist/.dts/presets/shared/error-warning-pass-policy.d.ts.map +1 -0
  69. package/dist/.dts/presets/shared/exit-code-fail-rationale.d.ts +23 -0
  70. package/dist/.dts/presets/shared/exit-code-fail-rationale.d.ts.map +1 -0
  71. package/dist/.dts/presets/shared/missing-dependency.d.ts +19 -0
  72. package/dist/.dts/presets/shared/missing-dependency.d.ts.map +1 -0
  73. package/dist/.dts/presets/shared/read-json-report.d.ts +33 -0
  74. package/dist/.dts/presets/shared/read-json-report.d.ts.map +1 -0
  75. package/dist/.dts/presets/shared/terminal-status.d.ts +25 -0
  76. package/dist/.dts/presets/shared/terminal-status.d.ts.map +1 -0
  77. package/dist/.dts/presets/shared/vitest-json-policy.d.ts +20 -0
  78. package/dist/.dts/presets/shared/vitest-json-policy.d.ts.map +1 -0
  79. package/dist/.dts/presets/stylelint.d.ts +17 -0
  80. package/dist/.dts/presets/stylelint.d.ts.map +1 -0
  81. package/dist/.dts/presets/test.d.ts +4 -0
  82. package/dist/.dts/presets/test.d.ts.map +1 -0
  83. package/dist/.dts/presets/typecheck.d.ts +4 -0
  84. package/dist/.dts/presets/typecheck.d.ts.map +1 -0
  85. package/dist/.dts/run-repo-contract.d.ts +38 -0
  86. package/dist/.dts/run-repo-contract.d.ts.map +1 -0
  87. package/dist/.dts/standard-schema/types.d.ts +76 -0
  88. package/dist/.dts/standard-schema/types.d.ts.map +1 -0
  89. package/dist/.dts/types.d.ts +424 -0
  90. package/dist/.dts/types.d.ts.map +1 -0
  91. package/dist/index.cjs +99 -4
  92. package/dist/index.cjs.map +1 -1
  93. package/dist/index.d.cts +1 -0
  94. package/dist/index.d.ts +1 -0
  95. package/dist/index.js +99 -5
  96. package/dist/index.js.map +1 -1
  97. package/dist/presets.d.cts +1 -0
  98. package/dist/presets.d.ts +1 -0
  99. package/package.json +1 -1
  100. package/schemas/evidence.schema.json +2 -2
  101. package/src/config/validate-config.ts +55 -1
  102. package/src/errors.ts +26 -0
  103. package/src/evidence/build-evidence.ts +6 -1
  104. package/src/index.ts +3 -0
  105. package/src/parsing/format-schema-issues.ts +56 -0
  106. package/src/parsing/parse-output.ts +50 -3
  107. package/src/standard-schema/types.ts +93 -0
  108. package/src/types.ts +48 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.2](https://github.com/MaverickCER/repo-contract/compare/repo-contract-v0.3.1...repo-contract-v0.3.2) (2026-09-04)
4
+
5
+
6
+ ### Features
7
+
8
+ * validate and transform check output with a Standard Schema ([d53cb17](https://github.com/MaverickCER/repo-contract/commit/d53cb17a9e3a3f939cd403226ab5256be0de79ac))
9
+ * validate and transform check output with a Standard Schema ([fbb7925](https://github.com/MaverickCER/repo-contract/commit/fbb79259f4a6cede1da64a0abd7e1f1541e1d505))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * address CodeRabbit findings and close mutation-testing gaps in Standard Schema support ([53baf87](https://github.com/MaverickCER/repo-contract/commit/53baf877d367fd17dbe1ec2f312ab9ed790e6ae6))
15
+ * **api-contract:** don't classify a required property on a brand-new container as breaking ([27ad5d5](https://github.com/MaverickCER/repo-contract/commit/27ad5d5c57811d90393b00f48ae8a8bbd413407b))
16
+ * **test:** harden isRuntimeAvailable against spawnSync throwing under load ([60c76b6](https://github.com/MaverickCER/repo-contract/commit/60c76b642dfd6187888f02d31639e68468e77b17))
17
+
18
+ ## [0.3.1](https://github.com/MaverickCER/repo-contract/compare/repo-contract-v0.3.0...repo-contract-v0.3.1) (2026-09-03)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * correct the release runbook that shipped types-less tarballs ([f56ea34](https://github.com/MaverickCER/repo-contract/commit/f56ea342606cfc92a09943ea5eb787936e7b7ba9))
24
+ * published tarball missing types; simplify CI matrix ([7ec8fd9](https://github.com/MaverickCER/repo-contract/commit/7ec8fd946bd584098255c5d2ab3f07b98b55ba1f))
25
+
3
26
  ## [0.3.0](https://github.com/MaverickCER/repo-contract/compare/repo-contract-v0.2.1...repo-contract-v0.3.0) (2026-09-03)
4
27
 
5
28
 
package/README.md CHANGED
@@ -529,6 +529,50 @@ Provides trimmed text passthrough and always succeeds.
529
529
 
530
530
  The sibling mistake -- reading `result.output.value` when the format _was_ requested but the parse itself failed (`result.output.success === false`, so `result.output` has `error`, not `value`) -- similarly rejects with [`PolicyReadFailedParseValueError`](docs/api-report/repo-contract.api.md) instead of a generic `PolicyThrewError`. Check `result.output.success` before reading `.value` to handle a parse failure explicitly rather than hitting either error.
531
531
 
532
+ #### Validating parsed output with a schema
533
+
534
+ `output.schema` accepts any object implementing [Standard Schema](https://standardschema.dev) --
535
+ Zod, Valibot, ArkType, and others already do. repo-contract does not install or depend on any of
536
+ them; it hand-vendors the (pure-type, zero-runtime-code) `StandardSchemaV1` interface itself (see
537
+ [ADR 0012](specs/decisions/0012-hand-vendored-standard-schema-support-for-optional-output-validation.md)). Bring whichever schema
538
+ library your own repo already uses -- `npm install zod` (or `valibot`, or `arktype`) is your call,
539
+ not repo-contract's. The smallest possible example, using a hand-written object satisfying the
540
+ interface directly rather than any particular library:
541
+
542
+ ```ts
543
+ output: {
544
+ format: "json",
545
+ schema: {
546
+ "~standard": {
547
+ version: 1,
548
+ vendor: "example",
549
+ validate: (value) => {
550
+ const errorCount =
551
+ value !== null && typeof value === "object"
552
+ ? (value as { errorCount?: unknown }).errorCount
553
+ : undefined
554
+ return typeof errorCount === "number"
555
+ ? { value: { errorCount } }
556
+ : { issues: [{ message: "errorCount must be a number", path: ["errorCount"] }] }
557
+ },
558
+ },
559
+ },
560
+ }
561
+ ```
562
+
563
+ A successful validation _replaces_ `result.output.value` with the schema's own (possibly
564
+ transformed or coerced) output -- one of the most useful aspects of Standard Schema, not just a
565
+ boolean check: a schema can normalize, default, or reshape its input, and the policy receives that
566
+ result, not the raw parsed value. A failing validation becomes a normal `ParsedOutputFailure` --
567
+ indistinguishable in shape from a malformed-JSON parse failure, joining every issue's own path and
568
+ message into `result.output.error` (e.g. `Schema validation failed: errorCount: errorCount must be
569
+ a number`). `result.output.value`'s declared TypeScript type stays `unknown` regardless -- narrow
570
+ or cast it yourself, same as without a schema.
571
+
572
+ `schema["~standard"].validate()` itself throwing or rejecting (rather than returning a `Result`) is
573
+ different from a failed validation -- it means the schema is broken, not the check's output, so it
574
+ rejects `runRepoContract()` with `StandardSchemaValidateThrewError` instead of becoming evidence.
575
+
532
576
  ### `dependsOn`
533
577
 
534
578
  By default, every check runs independently and in parallel.
@@ -1001,6 +1045,8 @@ A **policy throwing** is different. A synchronous throw or rejected promise from
1001
1045
 
1002
1046
  Two specific mistakes get their own error instead of a plain `PolicyThrewError`, both naming the check: reading `result.output.value` (or `.success`/`.error`/`.format`) on a check that never configured `output` throws `PolicyReadUnrequestedOutputError`, telling you to add `output: { format: "json" }` (or `"yaml"`/`"text"`); reading `result.output.value` on a check whose requested parse actually failed throws `PolicyReadFailedParseValueError`, telling you to check `result.output.success` first -- see [`output`](#output).
1003
1047
 
1048
+ A **schema throwing** (`output.schema["~standard"].validate()` itself throwing or rejecting, rather than returning a `Result` -- see [Validating parsed output with a schema](#validating-parsed-output-with-a-schema)) is treated the same as a throwing policy: `StandardSchemaValidateThrewError`, or an `AggregateError` when multiple checks' schemas throw in the same run. A schema _returning_ failure `issues`, by contrast, is not an error at all -- it becomes an ordinary parser-error-shaped `result.output`, exactly like the **Parser errors** case above.
1049
+
1004
1050
  ## Status and versioning
1005
1051
 
1006
1052
  repo-contract is pre-1.0.
@@ -0,0 +1,36 @@
1
+ import type { CheckSchema, RepoContractConfig, ValidatedCheckSchema } from "../types.js";
2
+ /**
3
+ * Identity function whose only job is type inference: authoring a config
4
+ * through `defineRepoContract` lets each check's `output` (present or
5
+ * absent, and which format) flow into that same check's `policy` parameter
6
+ * type, without the consumer writing any type annotations themselves. It
7
+ * also statically validates every check's `dependsOn` against its sibling
8
+ * check ids (see `ValidatedCheckSchema`) -- a typo'd or self-referencing id
9
+ * fails to compile here rather than only failing at runtime. Performs no
10
+ * other validation and no cloning -- `runRepoContract` validates whatever
11
+ * config it is ultimately given, whether or not it passed through this
12
+ * function first.
13
+ *
14
+ * `const TChecks` (TypeScript 5.0's `const` type parameter modifier) keeps
15
+ * each check's own configuration -- notably whether `output` is present at
16
+ * all -- from being widened during inference; without it, TypeScript's
17
+ * inference for a `Record` of heterogeneous generic entries does not
18
+ * reliably preserve that per-check shape once a callback property
19
+ * (`policy`) is also present. See `InferParsedValue` in types.ts for the
20
+ * related limitation this does not fully solve.
21
+ *
22
+ * `TChecks` is inferred from the plain, unwrapped `RepoContractConfig<TChecks>`
23
+ * position -- the `ValidatedCheckSchema<TChecks>` constraint on `checks` is
24
+ * intersected in afterward, computed from that already-inferred `TChecks`,
25
+ * rather than substituted in its place. Inferring `TChecks` directly from a
26
+ * mapped/conditional type over itself (as `ValidatedCheckSchema` is) loses
27
+ * the contextual typing every check's `policy` callback otherwise gets --
28
+ * another real, confirmed TypeScript inference limitation, distinct from
29
+ * the `output`-to-`policy` one above.
30
+ * @param config - the config to type-check and return unchanged.
31
+ * @returns the same `config` object, untouched and uncloned.
32
+ */
33
+ export declare function defineRepoContract<const TChecks extends CheckSchema>(config: RepoContractConfig<TChecks> & {
34
+ readonly checks: ValidatedCheckSchema<TChecks>;
35
+ }): RepoContractConfig<TChecks>;
36
+ //# sourceMappingURL=define-repo-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"define-repo-contract.d.ts","sourceRoot":"","sources":["../../../src/config/define-repo-contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,OAAO,SAAS,WAAW,EAClE,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAA;CAAE,GACvF,kBAAkB,CAAC,OAAO,CAAC,CAE7B"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Splits a `run` string into argv (executable + arguments) without invoking
3
+ * a shell -- no shell operator is ever executed, no glob is ever expanded by
4
+ * this package, no environment variable is ever substituted. The result is
5
+ * deterministic: the same input string always produces the same argv array.
6
+ *
7
+ * Quoting: `'...'` and `"..."` group whitespace into a single argument and
8
+ * are themselves stripped from the resulting token. `\` escapes the next
9
+ * character (and is itself stripped) when unquoted or inside a double-quoted
10
+ * span; inside single quotes it is a literal character, exactly as in every
11
+ * POSIX shell -- so a Windows path in single quotes survives intact.
12
+ * Unquoted whitespace (space, tab) separates tokens.
13
+ *
14
+ * Rejected outright (throws `InvalidCheckConfigError`, checkId identifies
15
+ * which check's `run` was invalid): any *unquoted* occurrence of a true
16
+ * shell/multi-command operator -- `;`, `&`, `|`, a backtick, `$(`, `<`, `>`,
17
+ * or a literal newline. A string containing one of these almost always
18
+ * reflects a mistaken assumption that shell interpretation is happening;
19
+ * the fix is either `run: [...]` (array form, bypasses tokenization
20
+ * entirely) or explicit `shell: true`.
21
+ *
22
+ * Deliberately NOT rejected: glob characters (`*`, `?`, `~`, `[`, `]`, `{`,
23
+ * `}`) and a bare `$`. These are common, legitimate literal argv content --
24
+ * many CLI tools (eslint, prettier, tsc) accept and internally expand glob
25
+ * patterns themselves, e.g. `eslint "src/**\/*.ts"` -- and since no shell is
26
+ * ever invoked here, they carry zero shell-injection risk regardless of
27
+ * where they appear in the string.
28
+ * @param run - the command string to tokenize.
29
+ * @param checkId - identifies which check's `run` was invalid, used in the thrown error message.
30
+ * @returns the tokenized argv (executable followed by its arguments).
31
+ */
32
+ export declare function tokenizeRunString(run: string, checkId: string): readonly string[];
33
+ //# sourceMappingURL=tokenize-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenize-command.d.ts","sourceRoot":"","sources":["../../../src/config/tokenize-command.ts"],"names":[],"mappings":"AA8DA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAwHjF"}
@@ -0,0 +1,32 @@
1
+ import type { RepoContractConfig } from "../types.js";
2
+ /**
3
+ * Validates a `RepoContractConfig` structurally and throws before any
4
+ * process spawns. A config with zero checks is valid (an empty `checks`
5
+ * object vacuously satisfies "every check passed"); everything else here is
6
+ * a genuine structural problem. Runtime checks are deliberately defensive
7
+ * about field types rather than trusting the compile-time type, since a
8
+ * config can arrive from plain JavaScript or a widened/cast value.
9
+ * @param config - the config to validate; throws if structurally invalid.
10
+ */
11
+ export declare function validateRepoContractConfig(config: RepoContractConfig): void;
12
+ /**
13
+ * Whole-graph properties that can't be checked per-check in isolation --
14
+ * run once, after every check's own `dependsOn` shape has already been
15
+ * validated by `validateDependsOn` above, so this can walk every
16
+ * `dependsOn` array without re-checking its shape.
17
+ *
18
+ * Declaration order in the `checks` object doubles as the required topological order (see
19
+ * `CheckDefinition.dependsOn`'s own doc comment): every `dependsOn` id must name a check declared
20
+ * earlier* than the check declaring it. This single backward-reference check subsumes what used
21
+ * to be two separate passes (an unknown-id check, then a DFS cycle detector) -- a cycle is no
22
+ * longer expressible at all once every edge is required to point backward, so there is nothing
23
+ * left for a separate cycle detector to catch. `isolated` needs no validation-time edge computation
24
+ * here: its own implied positional edges (see `run-checks.ts`'s `dependencyIndexesFor`) always
25
+ * point backward (to earlier-declared checks) or are pointed at by later-declared checks, by
26
+ * construction, so they can never introduce a cycle either.
27
+ * @param checks - the full check map, keyed by check id, in declaration order.
28
+ */
29
+ export declare function validateDependencyGraph(checks: Record<string, {
30
+ dependsOn?: readonly string[];
31
+ }>): void;
32
+ //# sourceMappingURL=validate-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-config.d.ts","sourceRoot":"","sources":["../../../src/config/validate-config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAKnE;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAuE3E;AA2VD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC,GACxD,IAAI,CAoBN"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Error hierarchy for repo-contract. Every concrete error carries a stable
3
+ * `code` string for programmatic handling, and never embeds raw
4
+ * stdout/stderr/env values in its message -- only check ids and field names
5
+ * (see SECURITY.md).
6
+ *
7
+ * Three distinct failure classes are kept deliberately separate (see
8
+ * specs/architecture.md):
9
+ * - Structural config problems throw synchronously, before any process
10
+ * spawns (`InvalidRepoContractConfigError`, `InvalidCheckConfigError`).
11
+ * - Anything only discoverable by attempting execution becomes evidence,
12
+ * never a throw (a bad `cwd`, a missing binary -- recorded as
13
+ * `status: "spawn_error"` on that check's `CheckEvidence`).
14
+ * - A policy function throwing or rejecting is a bug in consumer code, not
15
+ * a check failing its contract -- it propagates as a rejected
16
+ * `runRepoContract()` promise (`PolicyThrewError`), never silently
17
+ * turned into a failed verdict entry.
18
+ */
19
+ export declare abstract class RepoContractError extends Error {
20
+ /** Stable, machine-readable identifier for this error's specific failure mode. */
21
+ abstract readonly code: string;
22
+ }
23
+ /** The top-level `RepoContractConfig` itself is structurally invalid -- e.g. `checks` is not an object, or `concurrency` is not a positive integer. (A `checks` object with zero entries is deliberately valid: the run produces an empty, passing `Verdict`.) Thrown synchronously by `runRepoContract`, before anything spawns -- not by `defineRepoContract`, which performs no runtime validation of its own (see its own doc comment). */
24
+ export declare class InvalidRepoContractConfigError extends RepoContractError {
25
+ /** Always `"REPO_CONTRACT_INVALID_CONFIG"`. */
26
+ readonly code = "REPO_CONTRACT_INVALID_CONFIG";
27
+ constructor(reason: string);
28
+ }
29
+ /** One check's `CheckDefinition` is structurally invalid -- e.g. an empty `run`, a `run` string containing an unquoted shell operator without `shell: true`, or a missing `policy`. Thrown synchronously, before that check (or any other) spawns. */
30
+ export declare class InvalidCheckConfigError extends RepoContractError {
31
+ /** Always `"REPO_CONTRACT_INVALID_CHECK_CONFIG"`. */
32
+ readonly code = "REPO_CONTRACT_INVALID_CHECK_CONFIG";
33
+ /** The id of the check whose configuration was invalid. */
34
+ readonly checkId: string;
35
+ constructor(checkId: string, reason: string);
36
+ }
37
+ /**
38
+ * `RunRepoContractOptions.checks` (a partial-run request) names a check id that doesn't exist in
39
+ * the configured `checks`. Unlike a `dependsOn` id (already validated to exist by
40
+ * `validateRepoContractConfig` before any run starts), `options.checks` is only ever checked once
41
+ * `runChecks` actually resolves it -- there is no earlier structural-validation pass for it.
42
+ */
43
+ export declare class UnknownCheckIdError extends RepoContractError {
44
+ /** Always `"REPO_CONTRACT_UNKNOWN_CHECK_ID"`. */
45
+ readonly code = "REPO_CONTRACT_UNKNOWN_CHECK_ID";
46
+ /** The unrecognized check id named in `options.checks`. */
47
+ readonly checkId: string;
48
+ constructor(checkId: string);
49
+ }
50
+ /**
51
+ * A check's `dependsOn` names a check declared *later* in the same `checks` object.
52
+ * `dependsOn` may only reference a check declared earlier -- see `CheckDefinition.dependsOn`'s own
53
+ * doc comment. Declaration order doubles as the required topological order, so this is the only
54
+ * way an invalid dependency graph can arise; a real cycle is structurally impossible once every
55
+ * edge points backward. Thrown synchronously, before any check spawns.
56
+ */
57
+ export declare class DependencyDeclaredLaterError extends RepoContractError {
58
+ /** Always `"REPO_CONTRACT_DEPENDENCY_DECLARED_LATER"`. */
59
+ readonly code = "REPO_CONTRACT_DEPENDENCY_DECLARED_LATER";
60
+ /** The id of the check whose `dependsOn` names a later-declared check. */
61
+ readonly checkId: string;
62
+ /** The later-declared check id named in `checkId`'s `dependsOn`. */
63
+ readonly dependencyId: string;
64
+ constructor(checkId: string, dependencyId: string);
65
+ }
66
+ /** A check requested `output: { format: "yaml" }` but the optional `yaml` peer dependency is not installed. Thrown when that check's output is parsed, not at config-validation time (parsing only happens after the process has already run). */
67
+ export declare class ParserDependencyMissingError extends RepoContractError {
68
+ /** Always `"REPO_CONTRACT_PARSER_DEPENDENCY_MISSING"`. */
69
+ readonly code = "REPO_CONTRACT_PARSER_DEPENDENCY_MISSING";
70
+ /** The id of the check whose output could not be parsed. */
71
+ readonly checkId: string;
72
+ /** The output format that was requested but whose optional peer dependency is missing. */
73
+ readonly format: OutputFormatForError;
74
+ constructor(checkId: string, format: OutputFormatForError, cause: unknown);
75
+ }
76
+ type OutputFormatForError = "yaml";
77
+ /**
78
+ * A check's `output.schema["~standard"].validate()` threw synchronously, or returned a `Promise`
79
+ * that rejected, instead of returning a `Result`. This is a bug in the consumer-supplied schema
80
+ * object, not malformed check output -- the same distinction `PolicyThrewError` below draws for a
81
+ * throwing policy: a schema *returning* failure `issues` becomes an ordinary
82
+ * `ParsedOutputFailure` (reported as data, exactly like a malformed-JSON/YAML parse failure), but
83
+ * a schema *throwing* means the validator itself is broken, so it propagates as a rejected
84
+ * `runRepoContract()` promise instead. The original thrown/rejected value is preserved verbatim
85
+ * via the native `Error` `cause` chain.
86
+ */
87
+ export declare class StandardSchemaValidateThrewError extends RepoContractError {
88
+ /** Always `"REPO_CONTRACT_STANDARD_SCHEMA_VALIDATE_THREW"`. */
89
+ readonly code = "REPO_CONTRACT_STANDARD_SCHEMA_VALIDATE_THREW";
90
+ /** The id of the check whose `output.schema` threw during validation. */
91
+ readonly checkId: string;
92
+ constructor(checkId: string, cause: unknown);
93
+ }
94
+ /**
95
+ * A check's `policy` function threw synchronously, or returned a `Promise`
96
+ * that later rejected. Both failure modes are wrapped identically. The
97
+ * original thrown/rejected value is preserved verbatim via the native
98
+ * `Error` `cause` chain -- never stringified, summarized, or discarded --
99
+ * so a consumer catching this can still inspect exactly what their own
100
+ * policy code did wrong.
101
+ *
102
+ * A policy throwing never stops any other check's policy from running --
103
+ * every configured check's policy is invoked exactly once regardless of
104
+ * what any other policy does. If more than one policy fails this way in the
105
+ * same run, `runRepoContract()` rejects with a native `AggregateError` whose
106
+ * `errors` array holds one error per failing check -- `PolicyThrewError`,
107
+ * or one of its two narrower siblings below (`PolicyReadUnrequestedOutputError`,
108
+ * `PolicyReadFailedParseValueError`) when the failure matches one of their
109
+ * more specific shapes -- rather than surfacing only the first one found.
110
+ */
111
+ export declare class PolicyThrewError extends RepoContractError {
112
+ /** Always `"REPO_CONTRACT_POLICY_THREW"`. */
113
+ readonly code = "REPO_CONTRACT_POLICY_THREW";
114
+ /** The id of the check whose policy threw or rejected. */
115
+ readonly checkId: string;
116
+ constructor(checkId: string, cause: unknown);
117
+ }
118
+ /**
119
+ * A narrower `runPolicies` throws instead of `PolicyThrewError` when the
120
+ * thrown `TypeError`'s own message shows it came from reading a
121
+ * `result.output` property (`.success`, `.value`, `.error`, or `.format`),
122
+ * and this check's `CheckEvidence.output` really is `undefined` -- which
123
+ * happens only when its config never requested `output: { format: ... }` in
124
+ * the first place (see `CheckEvidence.output` in types.ts). Detected from
125
+ * the `TypeError`'s exact V8-produced message ("Cannot read properties of
126
+ * undefined (reading '...')") cross-checked against that `undefined` fact,
127
+ * so it is thrown only for a policy that plausibly hit this exact mistake --
128
+ * any other `TypeError`, or a check that did request a format, still becomes
129
+ * a plain `PolicyThrewError`. This is best-effort inference from the
130
+ * `TypeError`'s message text, not a verified trace back to `result.output`
131
+ * itself -- V8's message carries only the property name, so an unrelated
132
+ * bug that happens to read the same property name off some other
133
+ * `undefined` value can still be misclassified this way (see
134
+ * `unrequestedOutputProperty` in run-policies.ts). `cause` still holds the
135
+ * original `TypeError` verbatim, exactly as `PolicyThrewError` guarantees
136
+ * for every other policy failure, so the true cause remains recoverable
137
+ * either way.
138
+ */
139
+ export declare class PolicyReadUnrequestedOutputError extends RepoContractError {
140
+ /** Always `"REPO_CONTRACT_POLICY_READ_UNREQUESTED_OUTPUT"`. */
141
+ readonly code = "REPO_CONTRACT_POLICY_READ_UNREQUESTED_OUTPUT";
142
+ /** The id of the check whose policy read `result.output` without requesting a format. */
143
+ readonly checkId: string;
144
+ constructor(checkId: string, property: string, cause: unknown);
145
+ }
146
+ /**
147
+ * `PolicyThrewError`'s other special case, alongside
148
+ * `PolicyReadUnrequestedOutputError`: this check *did* request
149
+ * `output: { format: ... }`, but that parse itself failed
150
+ * (`result.output.success === false` -- see `ParsedOutputFailure` in types.ts, which
151
+ * has no `value` field, only `error`), and the policy read a property off
152
+ * `result.output.value` anyway without checking `.success` first. Detected the same
153
+ * way `runPolicies` detects the sibling case -- a thrown `TypeError` whose own
154
+ * message shows a property read off `undefined` -- cross-checked against this
155
+ * check's own evidence having `output.success === false`, so a genuinely unrelated
156
+ * `TypeError`, or a check whose parse actually succeeded, still becomes a plain
157
+ * `PolicyThrewError`. Unlike `PolicyReadUnrequestedOutputError`, the read property
158
+ * isn't restricted to a known list here -- `result.output.value`'s shape is whatever
159
+ * the external tool printed, entirely unknown to repo-contract -- so this match is
160
+ * necessarily a little broader. `cause` still holds the original `TypeError`
161
+ * verbatim; the message never repeats `result.output.error`'s own text, which may
162
+ * contain raw stdout content (see SECURITY.md).
163
+ */
164
+ export declare class PolicyReadFailedParseValueError extends RepoContractError {
165
+ /** Always `"REPO_CONTRACT_POLICY_READ_FAILED_PARSE_VALUE"`. */
166
+ readonly code = "REPO_CONTRACT_POLICY_READ_FAILED_PARSE_VALUE";
167
+ /** The id of the check whose policy read `result.output.value` after a failed parse. */
168
+ readonly checkId: string;
169
+ constructor(checkId: string, property: string, cause: unknown);
170
+ }
171
+ export {};
172
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,8BAAsB,iBAAkB,SAAQ,KAAK;IACnD,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAC/B;AAED,+aAA+a;AAC/a,qBAAa,8BAA+B,SAAQ,iBAAiB;IACnE,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,kCAAiC;gBAElC,MAAM,EAAE,MAAM;CAI3B;AAED,sPAAsP;AACtP,qBAAa,uBAAwB,SAAQ,iBAAiB;IAC5D,qDAAqD;IACrD,QAAQ,CAAC,IAAI,wCAAuC;IACpD,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAK5C;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,iBAAiB;IACxD,iDAAiD;IACjD,QAAQ,CAAC,IAAI,oCAAmC;IAChD,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM;CAO5B;AAED;;;;;;GAMG;AACH,qBAAa,4BAA6B,SAAQ,iBAAiB;IACjE,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,6CAA4C;IACzD,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;gBAEjB,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;CAUlD;AAED,kPAAkP;AAClP,qBAAa,4BAA6B,SAAQ,iBAAiB;IACjE,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,6CAA4C;IACzD,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAA;gBAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,EAAE,KAAK,EAAE,OAAO;CAU1E;AAMD,KAAK,oBAAoB,GAAG,MAAM,CAAA;AAElC;;;;;;;;;GASG;AACH,qBAAa,gCAAiC,SAAQ,iBAAiB;IACrE,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,kDAAiD;IAC9D,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAQ5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,SAAQ,iBAAiB;IACrD,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,gCAA+B;IAC5C,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAK5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,gCAAiC,SAAQ,iBAAiB;IACrE,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,kDAAiD;IAC9D,yFAAyF;IACzF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAY9D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,+BAAgC,SAAQ,iBAAiB;IACpE,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,kDAAiD;IAC9D,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;CAU9D"}
@@ -0,0 +1,26 @@
1
+ import type { CheckExecutionEntry } from "../execution/run-checks.js";
2
+ import type { CheckDefinition, CheckEvidence, Evidence } from "../types.js";
3
+ /** One check's id, its original definition, and its final evidence (parsed output attached, if requested) -- the parsed-output counterpart to `CheckExecutionEntry`, consumed directly by the policy phase so it never needs to look a check up by id either. */
4
+ export type ParsedCheckEntry = readonly [string, CheckDefinition, CheckEvidence];
5
+ interface BuiltEvidence {
6
+ readonly evidence: Evidence;
7
+ readonly entries: readonly ParsedCheckEntry[];
8
+ }
9
+ /**
10
+ * Attaches parsed output (if requested) to every check's raw execution
11
+ * evidence and assembles the versioned, immutable `Evidence` object for the
12
+ * run as a whole. Also returns the same information as a flat entries array
13
+ * (see `ParsedCheckEntry`) for the policy phase to consume directly -- by
14
+ * the time this function returns, every check's evidence -- including every
15
+ * sibling check's -- is fully assembled; nothing here is generated lazily
16
+ * or streamed, which is what makes it safe for a policy to read the full
17
+ * `evidence` object, not just its own check's `result` (see
18
+ * specs/architecture.md).
19
+ * @param results - each check's id, definition, and raw execution evidence from the run phase
20
+ * @param startedAt - when the overall run began, recorded on the assembled `Evidence`
21
+ * @param completedAt - when the overall run finished, used with `startedAt` to compute the assembled `Evidence`'s `durationMs`
22
+ * @returns the assembled `Evidence` for the whole run, plus the same checks as a flat `ParsedCheckEntry` array for the policy phase
23
+ */
24
+ export declare function buildEvidence(results: readonly CheckExecutionEntry[], startedAt: Date, completedAt: Date): Promise<BuiltEvidence>;
25
+ export {};
26
+ //# sourceMappingURL=build-evidence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-evidence.d.ts","sourceRoot":"","sources":["../../../src/evidence/build-evidence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAGrE,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3E,iQAAiQ;AACjQ,MAAM,MAAM,gBAAgB,GAAG,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,CAAA;AAIhF,UAAU,aAAa;IACrB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAC9C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,SAAS,mBAAmB,EAAE,EACvC,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,IAAI,GAChB,OAAO,CAAC,aAAa,CAAC,CAgExB"}
@@ -0,0 +1,29 @@
1
+ /** The composed signal, and a `dispose` to release any resources this composition holds once it's no longer needed. */
2
+ interface ComposedSignal {
3
+ readonly signal: AbortSignal;
4
+ readonly dispose: () => void;
5
+ }
6
+ /**
7
+ * Combines multiple signals into one that aborts as soon as any input does.
8
+ * Prefers the native `AbortSignal.any()` where available; falls back to a
9
+ * manual composition for engines without it. `AbortSignal.any` landed in
10
+ * Node 20.3.0 -- genuinely newer than this package's `engines.node >=20.0.0`
11
+ * floor, so the fallback is live code for a real gap (a 20.0-20.2 patch
12
+ * release), not dead code kept out of caution.
13
+ *
14
+ * The native path's `dispose` is a no-op -- `AbortSignal.any` manages its own
15
+ * source-signal listeners internally and doesn't leak them. The manual
16
+ * fallback's `dispose` removes the "abort" listeners it added to each input
17
+ * `signal`; without calling it, a long-lived input (like a whole run's shared
18
+ * `AbortSignal`, composed fresh for every check the run spawns) would
19
+ * accumulate one permanent, never-removed listener per composed signal for
20
+ * the rest of its own lifetime, regardless of whether that particular
21
+ * composition ever actually needed to abort. Callers should call `dispose()`
22
+ * once the composed signal is no longer needed, whether or not it ever
23
+ * aborted.
24
+ * @param signals - the signals to combine; the composed signal aborts as soon as any one of them does
25
+ * @returns the composed signal (aborting with that input's abort reason as soon as any signal in `signals` aborts), and a `dispose` to release this composition's own resources
26
+ */
27
+ export declare function composeSignals(signals: readonly AbortSignal[]): ComposedSignal;
28
+ export {};
29
+ //# sourceMappingURL=abort-signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort-signals.d.ts","sourceRoot":"","sources":["../../../src/execution/abort-signals.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,UAAU,cAAc;IACtB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,cAAc,CA4B9E"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Runs `worker` over `items` with at most `concurrency` invocations in
3
+ * flight at once, preserving each result at its original index regardless
4
+ * of completion order. Has no knowledge of aborting, killing, or check
5
+ * evidence -- a pure, reusable bounded-parallelism primitive; abort-
6
+ * awareness lives entirely in the caller's `worker` function (see
7
+ * spawn-check.ts).
8
+ * @param items - the items to process, each passed to `worker` along with its index
9
+ * @param concurrency - the maximum number of `worker` calls allowed in flight at once
10
+ * @param worker - the async function run per item; its resolved value becomes that item's result
11
+ * @returns the results, one per item, in the same order as `items` regardless of completion order
12
+ */
13
+ export declare function runWithConcurrency<T, R>(items: readonly T[], concurrency: number, worker: (item: T, index: number) => Promise<R>): Promise<R[]>;
14
+ //# sourceMappingURL=concurrency-pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concurrency-pool.d.ts","sourceRoot":"","sources":["../../../src/execution/concurrency-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAC3C,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,EAAE,CAAC,CA+Cd"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Runs `worker` over `items` with at most `concurrency` invocations in
3
+ * flight at once, like `concurrency-pool.ts`'s `runWithConcurrency`, but
4
+ * additionally respecting a dependency graph: an item whose
5
+ * `dependencyIndexes` are non-empty is not started until every one of
6
+ * those indexes has settled. Has no knowledge of checks, evidence, or
7
+ * abort semantics -- a pure, reusable bounded-parallelism-plus-ordering
8
+ * primitive, kept in its own file rather than folded into
9
+ * `concurrency-pool.ts` so that file's simpler, more heavily-used flat
10
+ * primitive stays untouched.
11
+ *
12
+ * A reactive, event-driven scheduler (conceptually Kahn's algorithm run
13
+ * incrementally): a completing item immediately re-evaluates and unblocks
14
+ * its own dependents, with no artificial "wave" boundary -- a wave/layer
15
+ * design was considered and rejected because it would stall a dependent
16
+ * whose single dependency finished early behind an unrelated slow item
17
+ * sharing its layer, a real regression for a diamond or fan-out shape.
18
+ *
19
+ * The caller is responsible for ensuring `dependencyIndexes` describes an
20
+ * acyclic graph (see `validate-config.ts`'s cycle detection) -- this
21
+ * function's own stall guard below exists only as defense in depth against
22
+ * that invariant being violated, not as the primary means of catching it.
23
+ * @param items - the items to process, each passed to `worker` and `dependencyIndexes` along with its index
24
+ * @param concurrency - the maximum number of `worker` calls allowed in flight at once
25
+ * @param dependencyIndexes - given an item and its index, returns the indexes into `items` that must settle first
26
+ * @param worker - the async function run per item once its dependencies have settled; its resolved value becomes that item's result
27
+ * @returns the results, one per item, in the same order as `items` regardless of completion order
28
+ */
29
+ export declare function runWithConcurrencyGraph<T, R>(items: readonly T[], concurrency: number, dependencyIndexes: (item: T, index: number) => readonly number[], worker: (item: T, index: number) => Promise<R>): Promise<R[]>;
30
+ //# sourceMappingURL=dependency-scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-scheduler.d.ts","sourceRoot":"","sources":["../../../src/execution/dependency-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAChD,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,EAChE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,CAAC,EAAE,CAAC,CAsLd"}
@@ -0,0 +1,59 @@
1
+ import type { SyncSpawner } from "../types.js";
2
+ /**
3
+ * Whether a check's process should be spawned with `detached: true`. On
4
+ * POSIX this makes the spawned process the leader of a new process group
5
+ * (sharing its own pid as the group id), which is what lets `killTree`
6
+ * target the whole group rather than just the immediate child. On Windows,
7
+ * process groups work differently and `detached: true` would instead launch
8
+ * the process in its own console window -- not what's wanted here, since
9
+ * Windows cleanup goes through `taskkill /t` instead (see `killTree`).
10
+ * @returns true on POSIX (spawn as its own process group leader, killable via `killTree`); false on Windows
11
+ */
12
+ export declare function shouldSpawnDetached(): boolean;
13
+ /**
14
+ * Best-effort termination of an entire process tree rooted at `pid`, not
15
+ * just the immediate process -- necessary because a check's command is
16
+ * often itself a wrapper (`npm run test` spawns `npm`, which spawns the
17
+ * actual test runner), and killing only the wrapper would orphan its
18
+ * descendants. `spawn`'s own `timeout`/`signal` options only ever affect the
19
+ * directly spawned process, never its descendants, which is why this exists
20
+ * as a separate utility rather than relying on those.
21
+ *
22
+ * On POSIX, sends `signal` to the whole process group via the negative-pid
23
+ * convention (requires the process to have been spawned with
24
+ * `detached: true`, see `shouldSpawnDetached`) -- no process spawning
25
+ * required, a single syscall via `process.kill`. On Windows, process groups
26
+ * don't work the same way, so this shells out to `taskkill /pid <pid> /t
27
+ * /f` -- the same technique the `tree-kill` package uses internally -- which
28
+ * walks the system process table for descendants of `pid` regardless of how
29
+ * it was spawned; that requires a synchronous spawn, which -- like every
30
+ * other process-spawning capability in this package -- is a trusted
31
+ * capability the caller supplies (`killProcessTree`, threaded from
32
+ * `RepoContractConfig.killProcessTree`), never imported internally (see
33
+ * specs/decisions/0011-process-spawning-and-ambient-environment-access-are-consumer-supplied-capabilities-not-package-owned.md).
34
+ * When `killProcessTree` is omitted on Windows, this function is a
35
+ * documented no-op -- the caller (`spawn-check.ts`) falls back to
36
+ * terminating just the tracked child process handle directly, which needs
37
+ * no spawn at all.
38
+ *
39
+ * Swallows the expected best-effort-cleanup failures, but not every failure: a
40
+ * process that has already exited (POSIX `ESRCH`, or `taskkill`'s "not found"
41
+ * case) is a no-op, and a POSIX `EPERM` permission error is swallowed the same
42
+ * way -- by the time cleanup runs the process may well have exited on its own,
43
+ * and a failed cleanup should not crash the run. Any *other* failure is
44
+ * rethrown: an unexpected POSIX errno, or (on Windows) a JS-level spawn failure
45
+ * of `taskkill` itself (`result.error`, e.g. the tool missing from PATH), which
46
+ * would otherwise silently leave an orphaned process tree behind.
47
+ *
48
+ * On Windows this always runs `taskkill` with `/f` regardless of which `signal` was requested --
49
+ * not a partial implementation of POSIX's cooperative-SIGTERM-then-SIGKILL escalation, but a
50
+ * reflection of a real platform difference: Windows has no signal-delivery mechanism for an
51
+ * arbitrary process tree by pid at all (this is also why Node's own `ChildProcess.kill()` treats
52
+ * every signal identically on Windows, per Node's own child_process documentation), so there is no
53
+ * more-cooperative alternative to fall back to here the way there is on POSIX.
54
+ * @param pid - the pid of the tree's root process (the process group id on POSIX, since it was spawned detached)
55
+ * @param signal - the POSIX signal to send (on Windows, ignored -- see doc comment above)
56
+ * @param killProcessTree - the consumer-supplied synchronous spawner used only on Windows; a no-op there when omitted (see doc comment above)
57
+ */
58
+ export declare function killTree(pid: number, signal: NodeJS.Signals, killProcessTree?: SyncSpawner): void;
59
+ //# sourceMappingURL=process-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-tree.d.ts","sourceRoot":"","sources":["../../../src/execution/process-tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAoDjG"}
@@ -0,0 +1,31 @@
1
+ import type { CheckDefinition, CheckEvidence, CheckSchema, RunRepoContractOptions } from "../types.js";
2
+ import type { ExecutionCapability } from "./spawn-check.js";
3
+ /**
4
+ * One check's id, its original definition, and its raw execution evidence,
5
+ * threaded together as a triple rather than three separately-keyed maps --
6
+ * every later stage (parsing, policy evaluation) consumes this directly
7
+ * instead of re-looking a check up by id, which under `noUncheckedIndexedAccess`
8
+ * would otherwise force handling an "undefined" case that can't actually
9
+ * happen (every checkId here comes from the same `Object.entries(checks)`
10
+ * that produced it).
11
+ */
12
+ export type CheckExecutionEntry = readonly [string, CheckDefinition, CheckEvidence];
13
+ export declare const SELF_TERMINATE_DELAY_MS: number;
14
+ /**
15
+ * Executes every resolved check with at most `concurrency` running at once,
16
+ * returning each check's raw evidence keyed by check id. For a full run
17
+ * (`options.checks` omitted), every configured check id is resolved and
18
+ * therefore appears in the result exactly once, regardless of whether it
19
+ * ever actually spawned (see spawnCheck's documentation for the pre-aborted
20
+ * case). When `options.checks` restricts execution to a subset, only the
21
+ * requested ids and their transitive `dependsOn` are resolved (see
22
+ * `resolveCheckDependencies` above) -- every other configured check id is
23
+ * simply absent from the result, not present with some placeholder value.
24
+ * @param checks - the full set of configured checks, keyed by id
25
+ * @param concurrency - the maximum number of checks to run in parallel at once
26
+ * @param execution - the run's trusted execution capabilities (`spawn`, `env`, resolved global `shell` default), forwarded to every `spawnCheck` call
27
+ * @param options - run options; `options.checks` restricts execution to those ids (plus their dependencies), `options.signal` cancels the whole run
28
+ * @returns each executed check's id, definition, and raw evidence, one entry per resolved check regardless of whether it actually spawned
29
+ */
30
+ export declare function runChecks(checks: CheckSchema, concurrency: number, execution: ExecutionCapability, options?: RunRepoContractOptions): Promise<readonly CheckExecutionEntry[]>;
31
+ //# sourceMappingURL=run-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-checks.d.ts","sourceRoot":"","sources":["../../../src/execution/run-checks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,sBAAsB,EACvB,MAAM,aAAa,CAAA;AAIpB,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAG9E;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,aAAa,CAAC,CAAA;AAYnF,eAAO,MAAM,uBAAuB,QAAgC,CAAA;AAoJpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,mBAAmB,EAC9B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC,CAkJzC"}