@jjchill/probity-rules 0.2.3 → 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 (39) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/internal/kotlin-tdd.d.ts +3 -1
  3. package/dist/internal/kotlin-tdd.d.ts.map +1 -1
  4. package/dist/internal/kotlin-tdd.js +10 -3
  5. package/dist/internal/kotlin-tdd.js.map +1 -1
  6. package/dist/presets/js.d.ts +35 -17
  7. package/dist/presets/js.d.ts.map +1 -1
  8. package/dist/presets/js.js +110 -38
  9. package/dist/presets/js.js.map +1 -1
  10. package/dist/presets/kmp.d.ts +45 -8
  11. package/dist/presets/kmp.d.ts.map +1 -1
  12. package/dist/presets/kmp.js +65 -39
  13. package/dist/presets/kmp.js.map +1 -1
  14. package/dist/presets/kotlin.d.ts +3 -0
  15. package/dist/presets/kotlin.d.ts.map +1 -1
  16. package/dist/presets/kotlin.js +15 -3
  17. package/dist/presets/kotlin.js.map +1 -1
  18. package/dist/presets/swift.d.ts.map +1 -1
  19. package/dist/presets/swift.js +7 -1
  20. package/dist/presets/swift.js.map +1 -1
  21. package/dist/rules/gates.d.ts +30 -0
  22. package/dist/rules/gates.d.ts.map +1 -1
  23. package/dist/rules/gates.js +70 -0
  24. package/dist/rules/gates.js.map +1 -1
  25. package/dist/rules/kotlin.d.ts +12 -0
  26. package/dist/rules/kotlin.d.ts.map +1 -1
  27. package/dist/rules/kotlin.js +40 -3
  28. package/dist/rules/kotlin.js.map +1 -1
  29. package/dist/rules/scoping.d.ts +10 -0
  30. package/dist/rules/scoping.d.ts.map +1 -1
  31. package/dist/rules/scoping.js +20 -0
  32. package/dist/rules/scoping.js.map +1 -1
  33. package/dist/rules/spec-test-parity.d.ts +17 -0
  34. package/dist/rules/spec-test-parity.d.ts.map +1 -1
  35. package/dist/rules/spec-test-parity.js +17 -0
  36. package/dist/rules/spec-test-parity.js.map +1 -1
  37. package/dist/scripts/scope-report.js +49 -5
  38. package/dist/scripts/scope-report.js.map +1 -1
  39. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0
4
+
5
+ Preset options, so projects stop forking rule lists:
6
+
7
+ - **KMP preset options (#19).** `kmpRuleEntries(root, options)` takes a
8
+ `KmpPresetOptions` object: `specsDir`, `specGlobs`, `glossaryPath`,
9
+ `coreGlobs`, `acceptanceTestGlobs`, `testRoots`, `testFilePattern`,
10
+ `testDeclarationPattern`, `baselinePath`, `driverScopes`,
11
+ `defaultScopes`. Each defaults to the previous hardcoded value, and
12
+ the old `kmpRuleEntries(root, { driverScopes, defaultScopes })` call
13
+ still works.
14
+ - **Excluding spikes and build output (#21).** The JS, Kotlin, and KMP
15
+ presets take `excludeGlobs`, default `['spikes/**', '**/build/**']`,
16
+ appended as `!` negations to every files-scoped block. Pass `[]` to
17
+ turn it off. **Behavior change:** writes under `spikes/` or a `build/`
18
+ directory are no longer checked by these presets' rules.
19
+ - **JS spec-to-test traceability (#18).** Setting `specsDir` on
20
+ `jsRuleEntries` wires `requireSpecBackedAcceptanceTest`,
21
+ `surfaceScenarioLinkBreakage`, `enforceSpecTestParity`, and (with
22
+ `glossaryPath`) `surfaceGlossaryTermBreakage`, as the KMP preset
23
+ does. Off by default.
24
+ - **TypeScript test declarations (#12).** New `JS_TEST_DECLARATION`
25
+ matches vitest/jest/mocha `it(`/`test(` and their `.only`/`.skip`/
26
+ `.each(...)(` variants; the JS preset uses it by default.
27
+ - New helper `withExcludeGlobs(entries, globs)` in `rules/scoping.ts`.
28
+
29
+ `probity-scope-report --allow-empty <glob>` (repeatable) marks a block
30
+ as expected to be empty, so a greenfield repository can run `--strict`
31
+ in CI from its first commit (#20). A flag that matches no block's glob
32
+ is a warning; a flag whose block now has files is noted.
33
+
34
+ ## 0.3.0
35
+
36
+ Kotlin and KMP presets now wire the characterization round-trip the
37
+ Swift preset already had (issue #34). A test that pins behavior
38
+ production already has — for example a branch an independent mutation
39
+ review found untested — is born green, so no red can precede it, and
40
+ the TDD judge could block it with no honest way forward. Now:
41
+
42
+ - a test-source write (`src/test`, or any `src/<name>Test` source set)
43
+ carrying `// probity: characterization` above the test passes without
44
+ the judge; the marker does nothing in production source;
45
+ - the marker comes off only when the session transcript records that
46
+ test failing (typically under a `// probity: mutation-probe`), and the
47
+ new `enforceCharacterizationResolution` commit gate blocks `git commit`
48
+ while any marker is on disk;
49
+ - `withCharacterizationTest` (all presets that use it) appends a note
50
+ naming the marker when it denies an unmarked test-layer write for
51
+ lacking a red, and resolves backticked Kotlin test names
52
+ (``fun `rejects blank ids`()``) in full for the removal proof.
53
+
54
+ **Behavior change:** Kotlin/KMP commits are now blocked while a
55
+ `probity: characterization` marker is on disk. No existing project
56
+ carries the marker unless it opted in.
57
+
58
+ The TDD judge in every preset reports a judge that returned no verdict
59
+ as an infrastructure failure (issue #32). A spend-limit, quota, or auth
60
+ notice used to surface as `could not parse verdict from validator
61
+ output: …`, which reads as a rejection of the change. The write is
62
+ still blocked (fail closed), but the deny text now says it was not
63
+ judged, whether the provider reported itself unavailable, and which
64
+ writes still pass deterministically. The wrapper is exported as
65
+ `withJudgeFailureDiagnostics` from `rules/gates.ts`.
66
+
67
+ `probity-scope-report` no longer flags test files under a core-purity
68
+ rule as "adapter/DI/UI-looking" (issue #26). A test-wide
69
+ `forbidContentPattern` (such as a no-mocking-library screen over every
70
+ test source set) legitimately covers adapter tests; the old warning
71
+ suggested excluding them, which would weaken the check. Production
72
+ adapter paths are still flagged.
73
+
3
74
  ## 0.2.3
4
75
 
5
76
  `enforceSpecTestParity` now inspects the pending Git commit before scanning
@@ -2,7 +2,9 @@ import { type Rule } from '@nizos/probity';
2
2
  /**
3
3
  * Kotlin sessions commonly include Gradle output plus several source reads between
4
4
  * red and green. Twenty events preserves that nearby red; clipping each event at
5
- * 6,000 characters keeps the additional context bounded.
5
+ * 6,000 characters keeps the additional context bounded. A judge that
6
+ * returns no verdict (spend limit, auth failure) is reported as an
7
+ * infrastructure failure rather than a TDD rejection.
6
8
  */
7
9
  export declare function enforceKotlinTdd(): Rule;
8
10
  //# sourceMappingURL=kotlin-tdd.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kotlin-tdd.d.ts","sourceRoot":"","sources":["../../internal/kotlin-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAStD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC"}
1
+ {"version":3,"file":"kotlin-tdd.d.ts","sourceRoot":"","sources":["../../internal/kotlin-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAiBtD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC"}
@@ -1,4 +1,9 @@
1
1
  import { enforceTdd } from '@nizos/probity';
2
+ import { withJudgeFailureDiagnostics } from '../rules/gates.js';
3
+ const KOTLIN_DETERMINISTIC_PATHS = 'Writes that never call the judge still go through: a test-source write ' +
4
+ 'adding exactly one @Test function (Kotlin fast path), telemetry-only ' +
5
+ 'lines, writes marked `// probity: mutation-probe`, and test-source ' +
6
+ 'writes marked `// probity: characterization`.';
2
7
  const KOTLIN_TDD_ADDENDUM = `## Kotlin/JVM TDD clarification
3
8
 
4
9
  - Kotlin-specific exception to the generic placeholder guidance: when a targeted, relevant Kotlin test executes a \`TODO()\` placeholder and reports \`kotlin.NotImplementedError\`, that runtime failure is a clean red. Do not require a second run that reaches an assertion before replacing the placeholder. The implementation remains bounded by the assertions present in the relevant test source visible in the recent session.
@@ -8,13 +13,15 @@ const KOTLIN_TDD_ADDENDUM = `## Kotlin/JVM TDD clarification
8
13
  /**
9
14
  * Kotlin sessions commonly include Gradle output plus several source reads between
10
15
  * red and green. Twenty events preserves that nearby red; clipping each event at
11
- * 6,000 characters keeps the additional context bounded.
16
+ * 6,000 characters keeps the additional context bounded. A judge that
17
+ * returns no verdict (spend limit, auth failure) is reported as an
18
+ * infrastructure failure rather than a TDD rejection.
12
19
  */
13
20
  export function enforceKotlinTdd() {
14
- return enforceTdd({
21
+ return withJudgeFailureDiagnostics(enforceTdd({
15
22
  instructions: (defaults) => `${defaults}\n\n${KOTLIN_TDD_ADDENDUM}`,
16
23
  maxEvents: 20,
17
24
  maxContentChars: 6_000,
18
- });
25
+ }), { deterministicPaths: KOTLIN_DETERMINISTIC_PATHS });
19
26
  }
20
27
  //# sourceMappingURL=kotlin-tdd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"kotlin-tdd.js","sourceRoot":"","sources":["../../internal/kotlin-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,gBAAgB,CAAA;AAEtD,MAAM,mBAAmB,GAAG;;;;;2LAK+J,CAAA;AAE3L;;;;GAIG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,UAAU,CAAC;QAChB,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,QAAQ,OAAO,mBAAmB,EAAE;QACnE,SAAS,EAAE,EAAE;QACb,eAAe,EAAE,KAAK;KACvB,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"kotlin-tdd.js","sourceRoot":"","sources":["../../internal/kotlin-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,gBAAgB,CAAA;AAEtD,OAAO,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAA;AAE/D,MAAM,0BAA0B,GAC9B,yEAAyE;IACzE,uEAAuE;IACvE,qEAAqE;IACrE,+CAA+C,CAAA;AAEjD,MAAM,mBAAmB,GAAG;;;;;2LAK+J,CAAA;AAE3L;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,2BAA2B,CAChC,UAAU,CAAC;QACT,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,QAAQ,OAAO,mBAAmB,EAAE;QACnE,SAAS,EAAE,EAAE;QACb,eAAe,EAAE,KAAK;KACvB,CAAC,EACF,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,CACnD,CAAA;AACH,CAAC"}
@@ -1,22 +1,6 @@
1
- /**
2
- * Probity rule-entry factory — plain JS/TS preset.
3
- *
4
- * Turns three of the agent-skills catalog's prose disciplines into
5
- * hard PreToolUse gates via https://github.com/nizos/probity :
6
- *
7
- * test-driven-development → enforceTdd (built-in)
8
- * ports-and-adapters → enforcePortsBoundary + forbidInternalModuleMocks
9
- * + a deterministic import screen
10
- * acceptance-testing → enforceAcceptanceLanguage
11
- *
12
- * `jsRuleEntries(options?)` reproduces exactly what the shipped
13
- * `probity.config.ts` template wires by default — every option below
14
- * defaults to that template's current value. A consuming project
15
- * copies the thin template (which calls this factory) and overrides
16
- * only the options its layout needs.
17
- */
18
1
  import { type RuleEntry } from '@nizos/probity';
19
2
  import type { Globs } from '../rules/scoping.js';
3
+ import { type DriverScope } from '../rules/spec-test-parity.js';
20
4
  /**
21
5
  * Deterministic first line of defense for the Dependency Rule: known
22
6
  * framework/vendor/OS-I/O imports never belong in core code, so block
@@ -51,6 +35,40 @@ export type JsPresetOptions = {
51
35
  commitSuccessPattern?: RegExp;
52
36
  /** Your runner's failure summary line. */
53
37
  commitFailurePattern?: RegExp;
38
+ /**
39
+ * Absolute path to the specs directory (e.g. `docs/specs`). OFF by
40
+ * default — no behavior change until set. Setting it switches on
41
+ * spec-to-test traceability, the same set the KMP/Kotlin presets
42
+ * wire: `requireSpecBackedAcceptanceTest` on `acceptanceTestGlobs`
43
+ * (deterministic, write-time, ordered before every AI-validated
44
+ * rule below), `surfaceScenarioLinkBreakage` on `specGlobs`, and
45
+ * `enforceSpecTestParity` as a commit gate. `surfaceGlossaryTermBreakage`
46
+ * on `glossaryPath` is added too, once that option is also set.
47
+ */
48
+ specsDir?: string;
49
+ /** Test-case files that must carry a spec-backed Covers: tag. */
50
+ acceptanceTestGlobs?: Globs;
51
+ /** Absolute paths to scan for acceptance tests (Covers: tags);
52
+ * defaults to `[process.cwd()]` — Probity hook processes are
53
+ * anchored to the project root. */
54
+ testRoots?: string[];
55
+ /** Which files count as acceptance tests when scanning for Covers:
56
+ * tags (default: any file under an `acceptance/` directory). */
57
+ testFilePattern?: RegExp;
58
+ /** What counts as a test-case declaration for the write-time gate
59
+ * (default: {@link JS_TEST_DECLARATION} — vitest/jest/mocha
60
+ * `it(`/`test(` and their `.only`/`.skip`/`.each(...)( `/
61
+ * `.concurrent` variants). */
62
+ testDeclarationPattern?: RegExp;
63
+ /** Per-scenario driver mapping; see {@link DriverScope}. */
64
+ driverScopes?: DriverScope[];
65
+ /** Scope names every scenario must satisfy even untagged. */
66
+ defaultScopes?: string[];
67
+ /** Incremental-adoption baseline path for the commit-time parity gate. */
68
+ parityBaselinePath?: string;
69
+ /** Globs excluded (as `!`-negations) from every files-scoped block —
70
+ * spikes and build output by default. Pass `[]` to disable. */
71
+ excludeGlobs?: string[];
54
72
  };
55
73
  /**
56
74
  * Rule entries for a plain JS/TS project. Probity stops at the first
@@ -1 +1 @@
1
- {"version":3,"file":"js.d.ts","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAYjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAC2O,CAAA;AAEpR,MAAM,MAAM,eAAe,GAAG;IAC5B;qDACiD;IACjD,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;+CAC2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;2BACuB;IACvB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB;wDACoD;IACpD,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB;sDACkD;IAClD,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB;oBACgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,eAAoB,GAAG,SAAS,EAAE,CAkFxE"}
1
+ {"version":3,"file":"js.d.ts","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAoC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAajF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAA;AAGrC;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAC2O,CAAA;AAEpR,MAAM,MAAM,eAAe,GAAG;IAC5B;qDACiD;IACjD,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,oEAAoE;IACpE,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B;+CAC2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;2BACuB;IACvB,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB;wDACoD;IACpD,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB;sDACkD;IAClD,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB;oBACgB;IAChB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,0CAA0C;IAC1C,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,KAAK,CAAA;IAC3B;;wCAEoC;IACpC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;qEACiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;mCAG+B;IAC/B,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,WAAW,EAAE,CAAA;IAC5B,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;oEACgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,eAAoB,GAAG,SAAS,EAAE,CAgKxE"}
@@ -15,10 +15,14 @@
15
15
  * copies the thin template (which calls this factory) and overrides
16
16
  * only the options its layout needs.
17
17
  */
18
+ import { basename } from 'node:path';
18
19
  import { enforceTdd, forbidContentPattern } from '@nizos/probity';
19
20
  import { enforceAcceptanceLanguage } from '../rules/acceptance-language.js';
20
- import { forbidNewAmbientEffects, JS_AMBIENT_EFFECT_PATTERNS, requireGreenTestRun, } from '../rules/gates.js';
21
+ import { forbidNewAmbientEffects, JS_AMBIENT_EFFECT_PATTERNS, requireGreenTestRun, withJudgeFailureDiagnostics, } from '../rules/gates.js';
21
22
  import { enforcePortsBoundary, forbidInternalModuleMocks, } from '../rules/ports-and-adapters.js';
23
+ import { withExcludeGlobs } from '../rules/scoping.js';
24
+ import { enforceSpecTestParity, JS_TEST_DECLARATION, requireSpecBackedAcceptanceTest, surfaceScenarioLinkBreakage, } from '../rules/spec-test-parity.js';
25
+ import { surfaceGlossaryTermBreakage } from '../rules/ubiquitous-language.js';
22
26
  /**
23
27
  * Deterministic first line of defense for the Dependency Rule: known
24
28
  * framework/vendor/OS-I/O imports never belong in core code, so block
@@ -38,7 +42,8 @@ export function jsRuleEntries(options = {}) {
38
42
  const mockGlobs = options.mockGlobs ?? ['**/*.test.*', '**/*.spec.*', 'test/**', 'tests/**'];
39
43
  const tddGlobs = options.tddGlobs ?? ['src/**', 'test/**', 'tests/**'];
40
44
  const specGlobs = options.specGlobs ?? ['specs/**', 'acceptance/**', '**/*.feature'];
41
- return [
45
+ const excludeGlobs = options.excludeGlobs ?? ['spikes/**', '**/build/**'];
46
+ const entries = [
42
47
  // ── Boundaries: ports-and-adapters ──────────────────────────────
43
48
  // Core purity. Point these globs at your core/domain/use-case
44
49
  // code only — adapters and composition roots import vendors by
@@ -71,42 +76,109 @@ export function jsRuleEntries(options = {}) {
71
76
  files: mockGlobs,
72
77
  rules: [forbidInternalModuleMocks()],
73
78
  },
74
- // ── Inner loop: test-driven-development ─────────────────────────
75
- // Red → Green → Refactor on all production and test code. This is
76
- // the expensive rule (AI call per matching write) — scope it to
77
- // the code you actually TDD. Listed AFTER the deterministic
78
- // screens above: Probity stops at the first violation, so a
79
- // vendor import in core code is rejected free by the import
80
- // screen, never after a model call.
81
- {
82
- files: tddGlobs,
83
- rules: [enforceTdd()],
84
- },
85
- // ── Outer loop: acceptance-testing ──────────────────────────────
86
- // The Language Test on the spec layer only. Do NOT widen this to
87
- // DSL or protocol-driver files — those layers are supposed to
88
- // contain the mechanics this rule blocks. To hold specs to your
89
- // glossary (ubiquitous-language skill), pass glossaryPath as an
90
- // absolute path, e.g.:
91
- // enforceAcceptanceLanguage({
92
- // glossaryPath: fileURLToPath(new URL('./docs/GLOSSARY.md', import.meta.url)),
93
- // })
94
- {
95
- files: specGlobs,
96
- rules: [enforceAcceptanceLanguage({ glossaryPath: options.glossaryPath })],
97
- },
98
- // ── Ship gate ────────────────────────────────────────────────────
99
- // No commit on an unverified tree — and the recorded run must be
100
- // GREEN. Probity's built-in requireCommand only checks that a test
101
- // command ran after the last write; a run whose output was all
102
- // failures would still unlock the commit. Match your real test
103
- // command and your runner's summary lines (defaults below cover
104
- // vitest and jest).
105
- requireGreenTestRun({
106
- command: options.commitCommand ?? /npm (run )?test|vitest|jest/,
107
- successPattern: options.commitSuccessPattern ?? /Test Files\s+\d+ passed|Tests:\s+.*\b\d+ passed/,
108
- failurePattern: options.commitFailurePattern ?? /\d+ failed|FAIL\s/,
109
- }),
110
79
  ];
80
+ // Spec-to-test traceability (issue #18): OFF by default, so a
81
+ // project that hasn't opted in sees no behavior change. Setting
82
+ // `specsDir` wires the same set the KMP preset wires — deterministic
83
+ // rules, ordered before the AI-validated TDD/Language Test rules
84
+ // below (Probity stops at the first violation, so a tagless
85
+ // acceptance test is rejected free, never after a model call).
86
+ if (options.specsDir) {
87
+ const specsDir = options.specsDir;
88
+ const acceptanceTestGlobs = options.acceptanceTestGlobs ?? [
89
+ 'acceptance/**/*.test.*',
90
+ 'acceptance/**/*.spec.*',
91
+ ];
92
+ const testRoots = options.testRoots ?? [process.cwd()];
93
+ // Spec↔test traceability. Editing a spec must not silently break
94
+ // the tests that claim its scenarios: removing or renaming a
95
+ // `## Scenario:` heading still covered by a test blocks with the
96
+ // list of affected tests, so the rename updates its Covers: tags
97
+ // in the same change.
98
+ entries.push({
99
+ files: specGlobs,
100
+ rules: [
101
+ surfaceScenarioLinkBreakage({ testRoots, testFilePattern: options.testFilePattern }),
102
+ ],
103
+ });
104
+ // Spec-first, at write time: adding a new test case (it(/test(,
105
+ // see JS_TEST_DECLARATION) requires a new Covers: tag resolving to
106
+ // a scenario that already exists in specsDir — the feature file is
107
+ // written before the test that claims it.
108
+ entries.push({
109
+ files: acceptanceTestGlobs,
110
+ rules: [
111
+ requireSpecBackedAcceptanceTest({
112
+ specsDir,
113
+ testDeclarationPattern: options.testDeclarationPattern ?? JS_TEST_DECLARATION,
114
+ }),
115
+ ],
116
+ });
117
+ if (options.glossaryPath) {
118
+ // Ubiquitous-language drift: renaming or removing a glossary
119
+ // term that specs, tests, or code still use blocks the glossary
120
+ // edit with the list of users. The JS preset has no `root` to
121
+ // anchor a relative glob against (unlike the KMP/Kotlin
122
+ // presets), so this scopes by basename anywhere in the tree —
123
+ // broader than an exact path, but safe regardless of where
124
+ // `glossaryPath` (an absolute path) points.
125
+ entries.push({
126
+ files: [`**/${basename(options.glossaryPath)}`],
127
+ rules: [surfaceGlossaryTermBreakage({ searchRoots: testRoots })],
128
+ });
129
+ }
130
+ }
131
+ // ── Inner loop: test-driven-development ─────────────────────────
132
+ // Red → Green → Refactor on all production and test code. This is
133
+ // the expensive rule (AI call per matching write) — scope it to
134
+ // the code you actually TDD. Listed AFTER the deterministic
135
+ // screens above: Probity stops at the first violation, so a
136
+ // vendor import in core code is rejected free by the import
137
+ // screen, never after a model call.
138
+ entries.push({
139
+ files: tddGlobs,
140
+ rules: [withJudgeFailureDiagnostics(enforceTdd())],
141
+ });
142
+ // ── Outer loop: acceptance-testing ──────────────────────────────
143
+ // The Language Test on the spec layer only. Do NOT widen this to
144
+ // DSL or protocol-driver files — those layers are supposed to
145
+ // contain the mechanics this rule blocks. To hold specs to your
146
+ // glossary (ubiquitous-language skill), pass glossaryPath as an
147
+ // absolute path, e.g.:
148
+ // enforceAcceptanceLanguage({
149
+ // glossaryPath: fileURLToPath(new URL('./docs/GLOSSARY.md', import.meta.url)),
150
+ // })
151
+ entries.push({
152
+ files: specGlobs,
153
+ rules: [enforceAcceptanceLanguage({ glossaryPath: options.glossaryPath })],
154
+ });
155
+ if (options.specsDir) {
156
+ // ── Ship gate: spec↔test parity ─────────────────────────────────
157
+ // Definition of done, made mechanical: every non-wip scenario in
158
+ // specsDir is claimed by an acceptance test (Covers: tag), and
159
+ // every tag resolves to a real scenario. Mark in-progress specs
160
+ // `## Scenario (wip):`.
161
+ entries.push(enforceSpecTestParity({
162
+ specsDir: options.specsDir,
163
+ testRoots: options.testRoots ?? [process.cwd()],
164
+ testFilePattern: options.testFilePattern,
165
+ baselinePath: options.parityBaselinePath,
166
+ driverScopes: options.driverScopes,
167
+ defaultScopes: options.defaultScopes,
168
+ }));
169
+ }
170
+ // ── Ship gate: green tests ──────────────────────────────────────
171
+ // No commit on an unverified tree — and the recorded run must be
172
+ // GREEN. Probity's built-in requireCommand only checks that a test
173
+ // command ran after the last write; a run whose output was all
174
+ // failures would still unlock the commit. Match your real test
175
+ // command and your runner's summary lines (defaults below cover
176
+ // vitest and jest).
177
+ entries.push(requireGreenTestRun({
178
+ command: options.commitCommand ?? /npm (run )?test|vitest|jest/,
179
+ successPattern: options.commitSuccessPattern ?? /Test Files\s+\d+ passed|Tests:\s+.*\b\d+ passed/,
180
+ failurePattern: options.commitFailurePattern ?? /\d+ failed|FAIL\s/,
181
+ }));
182
+ return withExcludeGlobs(entries, excludeGlobs);
111
183
  }
112
184
  //# sourceMappingURL=js.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"js.js","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAkB,MAAM,gBAAgB,CAAA;AAEjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,gCAAgC,CAAA;AAGvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GACvC,kRAAkR,CAAA;AA+BpR;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,UAA2B,EAAE;IACzD,MAAM,SAAS,GAAU,OAAO,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;IAC9E,MAAM,SAAS,GAAU,OAAO,CAAC,SAAS,IAAI,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IACnG,MAAM,QAAQ,GAAU,OAAO,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;IAC7E,MAAM,SAAS,GAAU,OAAO,CAAC,SAAS,IAAI,CAAC,UAAU,EAAE,eAAe,EAAE,cAAc,CAAC,CAAA;IAE3F,OAAO;QACL,mEAAmE;QACnE,8DAA8D;QAC9D,+DAA+D;QAC/D,kCAAkC;QAClC;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE;gBACL,oBAAoB,CAAC;oBACnB,KAAK,EAAE,OAAO,CAAC,qBAAqB,IAAI,4BAA4B;oBACpE,MAAM,EACJ,6DAA6D;wBAC7D,wDAAwD;wBACxD,2DAA2D;wBAC3D,6CAA6C;wBAC7C,4BAA4B;iBAC/B,CAAC;gBACF,iEAAiE;gBACjE,0DAA0D;gBAC1D,oDAAoD;gBACpD,uBAAuB,CAAC;oBACtB,QAAQ,EAAE,0BAA0B;oBACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ;iBAC3B,CAAC;gBACF,oBAAoB,EAAE;aACvB;SACF;QAED,gEAAgE;QAChE,iEAAiE;QACjE,WAAW;QACX;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,CAAC,yBAAyB,EAAE,CAAC;SACrC;QAED,mEAAmE;QACnE,kEAAkE;QAClE,gEAAgE;QAChE,4DAA4D;QAC5D,4DAA4D;QAC5D,4DAA4D;QAC5D,oCAAoC;QACpC;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,CAAC,UAAU,EAAE,CAAC;SACtB;QAED,mEAAmE;QACnE,iEAAiE;QACjE,8DAA8D;QAC9D,gEAAgE;QAChE,gEAAgE;QAChE,uBAAuB;QACvB,gCAAgC;QAChC,mFAAmF;QACnF,OAAO;QACP;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,CAAC,yBAAyB,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;SAC3E;QAED,oEAAoE;QACpE,iEAAiE;QACjE,mEAAmE;QACnE,+DAA+D;QAC/D,+DAA+D;QAC/D,gEAAgE;QAChE,oBAAoB;QACpB,mBAAmB,CAAC;YAClB,OAAO,EAAE,OAAO,CAAC,aAAa,IAAI,6BAA6B;YAC/D,cAAc,EACZ,OAAO,CAAC,oBAAoB,IAAI,iDAAiD;YACnF,cAAc,EAAE,OAAO,CAAC,oBAAoB,IAAI,mBAAmB;SACpE,CAAC;KACH,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"js.js","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,45 @@
1
1
  import { type RuleEntry } from '@nizos/probity';
2
+ import type { Globs } from '../rules/scoping.js';
2
3
  import { type DriverScope } from '../rules/spec-test-parity.js';
4
+ /**
5
+ * Options for {@link kmpRuleEntries}. A superset of the factory's
6
+ * original `{ driverScopes, defaultScopes }` second parameter, so
7
+ * existing callers passing that shape unchanged keep working. Every
8
+ * option defaults to the reference KMP layout's current hardcoded
9
+ * value — a consuming project overrides only what its layout needs.
10
+ */
11
+ export type KmpPresetOptions = {
12
+ /** Absolute path to the specs directory. */
13
+ specsDir?: string;
14
+ /** Spec files the traceability rules scan/scope to (Markdown
15
+ * `*.feature.md` by default; add `**\/*.feature` for Gherkin). */
16
+ specGlobs?: Globs;
17
+ /** Absolute path to the ubiquitous-language glossary. */
18
+ glossaryPath?: string;
19
+ /** Core purity scope — domain/port/usecase/presentation packages in
20
+ * commonMain. Adapter, DI, and Compose ui packages import vendors
21
+ * by design and must NOT match here. */
22
+ coreGlobs?: Globs;
23
+ /** Test-case files that must carry a spec-backed Covers: tag. */
24
+ acceptanceTestGlobs?: Globs;
25
+ /** Absolute paths to scan for acceptance tests (Covers: tags). */
26
+ testRoots?: string[];
27
+ /** Which files count as acceptance tests when scanning for Covers:
28
+ * tags (default: any file under an `acceptance/` directory). */
29
+ testFilePattern?: RegExp;
30
+ /** What counts as a test-case declaration for the write-time gate
31
+ * (default: Kotlin/Java `@Test` or Swift `func test…`). */
32
+ testDeclarationPattern?: RegExp;
33
+ /** Per-scenario driver mapping; see {@link DriverScope}. */
34
+ driverScopes?: DriverScope[];
35
+ /** Scope names every scenario must satisfy even untagged. */
36
+ defaultScopes?: string[];
37
+ /** Incremental-adoption baseline path for the commit-time parity gate. */
38
+ baselinePath?: string;
39
+ /** Globs excluded (as `!`-negations) from every files-scoped block —
40
+ * spikes and build output by default. Pass `[]` to disable. */
41
+ excludeGlobs?: string[];
42
+ };
3
43
  /**
4
44
  * The rule entries, as a factory over the project root. Probity only
5
45
  * reads the default export below; the factory exists so tooling can
@@ -13,15 +53,12 @@ import { type DriverScope } from '../rules/spec-test-parity.js';
13
53
  * `loadConfig` anchors them against this file's directory at load
14
54
  * time, and the tooling replicates that via `rules/scoping.ts`.
15
55
  *
16
- * `parity` optionally switches on the per-scenario driver mapping
17
- * (`driverScopes`/`defaultScopes` on the commit-time parity gate) —
56
+ * `options.driverScopes`/`options.defaultScopes` optionally switch on
57
+ * the per-scenario driver mapping on the commit-time parity gate —
18
58
  * projects normally enable it by uncommenting the block in the
19
- * `enforceSpecTestParity` call below; the parameter exists so the
20
- * workflow eval can exercise the scope checks without changing the
59
+ * `enforceSpecTestParity` call below; the workflow eval passes them
60
+ * directly so it can exercise the scope checks without changing the
21
61
  * template's default-off posture.
22
62
  */
23
- export declare function kmpRuleEntries(root: string, parity?: {
24
- driverScopes?: DriverScope[];
25
- defaultScopes?: string[];
26
- }): RuleEntry[];
63
+ export declare function kmpRuleEntries(root: string, options?: KmpPresetOptions): RuleEntry[];
27
64
  //# sourceMappingURL=kmp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kmp.d.ts","sourceRoot":"","sources":["../../presets/kmp.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAUrE,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAA;AAmBrC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAClE,SAAS,EAAE,CAuOb"}
1
+ {"version":3,"file":"kmp.d.ts","sourceRoot":"","sources":["../../presets/kmp.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAIrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAOhD,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAA;AAsBrC;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;uEACmE;IACnE,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;6CAEyC;IACzC,SAAS,CAAC,EAAE,KAAK,CAAA;IACjB,iEAAiE;IACjE,mBAAmB,CAAC,EAAE,KAAK,CAAA;IAC3B,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB;qEACiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;gEAC4D;IAC5D,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,4DAA4D;IAC5D,YAAY,CAAC,EAAE,WAAW,EAAE,CAAA;IAC5B,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;oEACgE;IAChE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,SAAS,EAAE,CAsQxF"}