@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.
- package/CHANGELOG.md +71 -0
- package/dist/internal/kotlin-tdd.d.ts +3 -1
- package/dist/internal/kotlin-tdd.d.ts.map +1 -1
- package/dist/internal/kotlin-tdd.js +10 -3
- package/dist/internal/kotlin-tdd.js.map +1 -1
- package/dist/presets/js.d.ts +35 -17
- package/dist/presets/js.d.ts.map +1 -1
- package/dist/presets/js.js +110 -38
- package/dist/presets/js.js.map +1 -1
- package/dist/presets/kmp.d.ts +45 -8
- package/dist/presets/kmp.d.ts.map +1 -1
- package/dist/presets/kmp.js +65 -39
- package/dist/presets/kmp.js.map +1 -1
- package/dist/presets/kotlin.d.ts +3 -0
- package/dist/presets/kotlin.d.ts.map +1 -1
- package/dist/presets/kotlin.js +15 -3
- package/dist/presets/kotlin.js.map +1 -1
- package/dist/presets/swift.d.ts.map +1 -1
- package/dist/presets/swift.js +7 -1
- package/dist/presets/swift.js.map +1 -1
- package/dist/rules/gates.d.ts +30 -0
- package/dist/rules/gates.d.ts.map +1 -1
- package/dist/rules/gates.js +70 -0
- package/dist/rules/gates.js.map +1 -1
- package/dist/rules/kotlin.d.ts +12 -0
- package/dist/rules/kotlin.d.ts.map +1 -1
- package/dist/rules/kotlin.js +40 -3
- package/dist/rules/kotlin.js.map +1 -1
- package/dist/rules/scoping.d.ts +10 -0
- package/dist/rules/scoping.d.ts.map +1 -1
- package/dist/rules/scoping.js +20 -0
- package/dist/rules/scoping.js.map +1 -1
- package/dist/rules/spec-test-parity.d.ts +17 -0
- package/dist/rules/spec-test-parity.d.ts.map +1 -1
- package/dist/rules/spec-test-parity.js +17 -0
- package/dist/rules/spec-test-parity.js.map +1 -1
- package/dist/scripts/scope-report.js +49 -5
- package/dist/scripts/scope-report.js.map +1 -1
- 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;
|
|
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
|
|
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"}
|
package/dist/presets/js.d.ts
CHANGED
|
@@ -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
|
package/dist/presets/js.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js.d.ts","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/presets/js.js
CHANGED
|
@@ -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
|
-
|
|
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
|
package/dist/presets/js.js.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"js.js","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"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"}
|
package/dist/presets/kmp.d.ts
CHANGED
|
@@ -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
|
-
* `
|
|
17
|
-
*
|
|
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
|
|
20
|
-
*
|
|
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,
|
|
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;
|
|
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"}
|