@jjchill/probity-rules 0.4.14 → 0.4.16
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 +150 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/presets/js.d.ts +21 -0
- package/dist/presets/js.d.ts.map +1 -1
- package/dist/presets/js.js +45 -4
- package/dist/presets/js.js.map +1 -1
- package/dist/rules/js-tdd.d.ts +18 -0
- package/dist/rules/js-tdd.d.ts.map +1 -0
- package/dist/rules/js-tdd.js +25 -0
- package/dist/rules/js-tdd.js.map +1 -0
- package/dist/rules/ports-and-adapters.d.ts +88 -0
- package/dist/rules/ports-and-adapters.d.ts.map +1 -1
- package/dist/rules/ports-and-adapters.js +289 -0
- package/dist/rules/ports-and-adapters.js.map +1 -1
- package/package.json +1 -1
- package/probity.config.ts +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,155 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.16
|
|
4
|
+
|
|
5
|
+
The JS preset now keeps driving adapters (UI components, pages, route
|
|
6
|
+
handlers) thin (#72). Business logic leaking out of the core into UI
|
|
7
|
+
code is blocked, and the deny names where it should go.
|
|
8
|
+
|
|
9
|
+
- **What went wrong.** The existing ports-and-adapters rules stop
|
|
10
|
+
vendors getting *into* core code. Nothing stopped logic leaking *out*
|
|
11
|
+
of it. In a React consumer on 0.4.14, with clean and fully policed
|
|
12
|
+
core boundaries, `src/ui/` grew:
|
|
13
|
+
- a submit handler running a whole use case (domain `submit()`,
|
|
14
|
+
`repository.save()`, `notifier.timesheetSubmitted()`, and a "a
|
|
15
|
+
failed notification must never fail the submit" policy)
|
|
16
|
+
- `viewer.role === 'SuperUser'` permission checks in four places,
|
|
17
|
+
next to a domain that already exported `canEdit` and `canApprove`
|
|
18
|
+
- a display-name rule copied seven times, with two copies disagreeing
|
|
19
|
+
- a React-free use case filed under `src/ui/`
|
|
20
|
+
|
|
21
|
+
Each one had a component test, so the TDD judge had no reason to
|
|
22
|
+
object. It checks whether code is tested, not where it belongs.
|
|
23
|
+
- **Now:** two new rules in `rules/ports-and-adapters.ts`.
|
|
24
|
+
- `enforceThinDrivingAdapter`, an AI judge. It blocks a write that
|
|
25
|
+
adds (a) a decision in domain terms, (b) coordination of more than
|
|
26
|
+
one port or use-case call, (c) a re-implementation of something the
|
|
27
|
+
core exports, or (d) a framework-free use case under a UI path. The
|
|
28
|
+
deny names the extraction target: a domain function or a use case.
|
|
29
|
+
Rendering, display formatting, local view state, and one call per
|
|
30
|
+
user intent pass. Only what a write adds is judged, so an existing
|
|
31
|
+
thick component doesn't freeze.
|
|
32
|
+
- `forbidNewDomainDiscriminantChecks`, a free deterministic screen.
|
|
33
|
+
It blocks net-new comparisons of configured fields to a literal
|
|
34
|
+
(`viewer.role === 'SuperUser'`, either order) and points to a domain
|
|
35
|
+
function. Off until you list the fields: there is no default,
|
|
36
|
+
because `status === 'loading'` is ordinary view state.
|
|
37
|
+
- **Preset wiring (JS only).** `jsRuleEntries` gets a block on the new
|
|
38
|
+
`drivingAdapterGlobs` option, **on by default**: `src/ui/**`,
|
|
39
|
+
`src/components/**` and `src/**/*.tsx`, minus `*.test.*`, `*.spec.*`
|
|
40
|
+
and `*.stories.*`. It runs before the TDD judge, so a denial costs one
|
|
41
|
+
AI call. New options:
|
|
42
|
+
- `drivingAdapterGlobs`: the scope; `[]` switches the rules off.
|
|
43
|
+
- `domainDiscriminants`: turns on the free screen, e.g. `['role']`.
|
|
44
|
+
- `domainHint`: appended to the screen's deny, e.g. where permission
|
|
45
|
+
rules live.
|
|
46
|
+
- `coreExportsInJudge`: gives the judge the export names of every
|
|
47
|
+
module under `coreGlobs` (capped at 8,000 characters), so it can
|
|
48
|
+
name the existing function a copy duplicates. Off by default; it
|
|
49
|
+
scans the tree on each judged write.
|
|
50
|
+
- **Measured** with Probity's real Claude Code judge, 5 runs per case,
|
|
51
|
+
on synthetic writes built from the four cases above plus five
|
|
52
|
+
controls that must pass: a pure render change, adding a `canX()`
|
|
53
|
+
call, a single use-case call, a local `status === 'loading'` check,
|
|
54
|
+
and calling an existing `displayName` export. These are written from
|
|
55
|
+
the issue's descriptions, not replays of the consumer's real writes.
|
|
56
|
+
With and without the export list, 90/90 verdicts were correct (40
|
|
57
|
+
blocked, 50 allowed). The prompt's examples were then made
|
|
58
|
+
domain-neutral and the replay rerun: 76 of 90 runs returned a verdict
|
|
59
|
+
and all 76 were correct. The other 14 hit a judge login failure in
|
|
60
|
+
the test environment. On 0.4.14 no rule judged these writes, so all
|
|
61
|
+
would pass.
|
|
62
|
+
- **Cost:** one extra AI call per write to a matching UI file, on top of
|
|
63
|
+
the TDD judge.
|
|
64
|
+
- **Migration.** Consumers calling `jsRuleEntries` get the new block on
|
|
65
|
+
upgrade. Check it with `probity-scope-report`: it lists the block and
|
|
66
|
+
flags it `DEAD SCOPE` if your UI lives elsewhere. Then set
|
|
67
|
+
`drivingAdapterGlobs` to your layout, or `[]` to opt out. Hand-composed
|
|
68
|
+
configs add the block themselves:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
{
|
|
72
|
+
files: ['src/ui/**', '!**/*.test.*'],
|
|
73
|
+
rules: [
|
|
74
|
+
forbidNewDomainDiscriminantChecks({ discriminants: ['role'] }),
|
|
75
|
+
withJudgeFailureDiagnostics(withContradictionRetry(enforceThinDrivingAdapter())),
|
|
76
|
+
],
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The Kotlin, KMP and Swift presets are unchanged; Compose and SwiftUI
|
|
81
|
+
globs are a follow-up.
|
|
82
|
+
- New exports: `enforceThinDrivingAdapter`,
|
|
83
|
+
`forbidNewDomainDiscriminantChecks`, `domainDiscriminantPatterns`,
|
|
84
|
+
`exportedNames` and `listCoreExports`.
|
|
85
|
+
- Skills: `ports-and-adapters` gets a "Driving adapters are equally
|
|
86
|
+
thin" section with a checklist, red flags and a rationalization;
|
|
87
|
+
`frontend-ui-engineering` points to it.
|
|
88
|
+
|
|
89
|
+
## 0.4.15
|
|
90
|
+
|
|
91
|
+
The JS/TS TDD judge no longer blocks adding a new red test (#73), and it
|
|
92
|
+
now blocks a production write whose new test was never run.
|
|
93
|
+
|
|
94
|
+
- **What went wrong.** In #73, a JS/TS project on 0.4.14 added one new
|
|
95
|
+
failing `it(...)` to an existing Vitest file, straight after a green
|
|
96
|
+
run, with no production change. The judge denied it: "This test has
|
|
97
|
+
not been observed failing … here it is being added as a green->red
|
|
98
|
+
crossing without that observed red." A test can't fail before it
|
|
99
|
+
exists. This is the #43 bug in the Kotlin judge, fixed in 0.4.3. The
|
|
100
|
+
JS preset runs Probity's built-in `enforceTdd()`, which never got
|
|
101
|
+
that fix. Its default rules say both "adding a test is the red step"
|
|
102
|
+
and "judge a new red at the green->red boundary too" (the refactor
|
|
103
|
+
check), and the judge read the second as a demand for a failing run.
|
|
104
|
+
- **Now:** a new rule, `enforceJsTdd()` (in `rules/js-tdd.ts`,
|
|
105
|
+
exported), is `enforceTdd()` with an addendum, wrapped the way the JS
|
|
106
|
+
preset already wrapped it. The JS preset uses it. The addendum says:
|
|
107
|
+
- Adding one failing test is the red step and needs no prior run.
|
|
108
|
+
"Must be observed failing" applies only to the production write
|
|
109
|
+
that follows. This holds even when the test contradicts what the
|
|
110
|
+
previous cycle just implemented.
|
|
111
|
+
- At a test write, the only green->red question is whether the prior
|
|
112
|
+
green left a refactor unmade. A passing prior run is never a reason
|
|
113
|
+
to block a new test.
|
|
114
|
+
- A production write still needs an observed failing test: a run,
|
|
115
|
+
after the test was written, whose output shows that test failing.
|
|
116
|
+
A test written but never run does not count. Neither does an
|
|
117
|
+
earlier failing run of a different test.
|
|
118
|
+
- **Measured** against the live judge (Probity's `claudeCode()` agent,
|
|
119
|
+
as the hook runs it), replaying the real #73 write. The input was the
|
|
120
|
+
session's own transcript, cut just before the write and read with
|
|
121
|
+
Probity's transcript reader, plus the test and production files as
|
|
122
|
+
they stood on disk then (10 runs each, 0.4.14 → 0.4.15):
|
|
123
|
+
- the reported write: allowed **2/10 → 10/10**. On 0.4.14 the
|
|
124
|
+
denials read like the reported one ("has not been observed
|
|
125
|
+
failing");
|
|
126
|
+
- the same session, then a production write with the new test never
|
|
127
|
+
run: blocked **4/10 → 9/10**;
|
|
128
|
+
- the same session, then the new test run and seen failing, then the
|
|
129
|
+
production write: allowed 10/10 → 10/10.
|
|
130
|
+
|
|
131
|
+
A replica built from the same files, but with a hand-written session,
|
|
132
|
+
never reproduced the denial (allowed 20/20 on both versions). On it,
|
|
133
|
+
the controls that must stay blocked, as 0.4.14 → 0.4.15 (5 runs
|
|
134
|
+
each unless noted):
|
|
135
|
+
- a production write before any test for it: 5/5 → 5/5;
|
|
136
|
+
- a test plus a production change in one write (an in-source `it` in
|
|
137
|
+
`account.ts`): 5/5 → 5/5;
|
|
138
|
+
- two new tests in one write: 5/5 → 5/5;
|
|
139
|
+
- a production write after the new test was added but never run:
|
|
140
|
+
1/10 → 15/15.
|
|
141
|
+
- **Not changed:** Probity's own `enforceTdd({ fastPath: true })` stays
|
|
142
|
+
off. It would pass a single-test write with no AI call, but it skips
|
|
143
|
+
the refactor check at the green->red boundary. It also lacks the
|
|
144
|
+
byte-preservation checks the Kotlin fast path has.
|
|
145
|
+
- **Action needed** if your `probity.config.ts` wires the TDD rule
|
|
146
|
+
itself rather than through `jsRuleEntries`. Replace
|
|
147
|
+
`withJudgeFailureDiagnostics(withContradictionRetry(enforceTdd()))`
|
|
148
|
+
with `enforceJsTdd()`, imported from `@jjchill/probity-rules` or
|
|
149
|
+
`@jjchill/probity-rules/rules/js-tdd`. Configs that use
|
|
150
|
+
`jsRuleEntries` get it automatically.
|
|
151
|
+
- New exports: `enforceJsTdd`, `JS_TDD_ADDENDUM`.
|
|
152
|
+
|
|
3
153
|
## 0.4.14
|
|
4
154
|
|
|
5
155
|
Extracting existing code into a new file under green now passes in the
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA"}
|
package/dist/presets/js.d.ts
CHANGED
|
@@ -17,6 +17,27 @@ export type JsPresetOptions = {
|
|
|
17
17
|
/** Point at your canonical ports once they exist, e.g. "inject the
|
|
18
18
|
* Clock port from src/ports/clock.ts". */
|
|
19
19
|
seamHint?: string;
|
|
20
|
+
/** Driving (inbound) adapter files — UI components, pages, route
|
|
21
|
+
* handlers, CLI commands — held thin by `enforceThinDrivingAdapter`
|
|
22
|
+
* (an AI call per matching write). Default: `src/ui/**`,
|
|
23
|
+
* `src/components/**` and every `.tsx` under `src/`, minus tests
|
|
24
|
+
* and stories. Pass `[]` to switch
|
|
25
|
+
* the thinness rules off. */
|
|
26
|
+
drivingAdapterGlobs?: Globs;
|
|
27
|
+
/** Field names whose comparison to a literal in a driving adapter is
|
|
28
|
+
* a domain decision (e.g. `['role', 'plan']`). OFF by default —
|
|
29
|
+
* `status === 'loading'` is ordinary view state, so only your model
|
|
30
|
+
* knows which fields carry domain meaning. Set it to block net-new
|
|
31
|
+
* comparisons free, before the AI call. */
|
|
32
|
+
domainDiscriminants?: string[];
|
|
33
|
+
/** Appended to the discriminant block message, e.g. "permission
|
|
34
|
+
* rules live in src/domain/permissions.ts". */
|
|
35
|
+
domainHint?: string;
|
|
36
|
+
/** Give the thin-driving-adapter judge the export names of every
|
|
37
|
+
* module under `coreGlobs`, so it can spot a copy of an existing
|
|
38
|
+
* domain rule. Off by default: it costs a directory scan per judged
|
|
39
|
+
* write. */
|
|
40
|
+
coreExportsInJudge?: boolean;
|
|
20
41
|
/** Files where internal-module mocking is forbidden (the only test
|
|
21
42
|
* seam is a port). */
|
|
22
43
|
mockGlobs?: Globs;
|
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":"AAqBA,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAiBrE,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;;;;;kCAK8B;IAC9B,mBAAmB,CAAC,EAAE,KAAK,CAAA;IAC3B;;;;gDAI4C;IAC5C,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC9B;oDACgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;iBAGa;IACb,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;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,CA2MxE"}
|
package/dist/presets/js.js
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* Turns three of the agent-skills catalog's prose disciplines into
|
|
5
5
|
* hard PreToolUse gates via https://github.com/nizos/probity :
|
|
6
6
|
*
|
|
7
|
-
* test-driven-development →
|
|
7
|
+
* test-driven-development → enforceJsTdd (built-in enforceTdd + addendum)
|
|
8
8
|
* ports-and-adapters → enforcePortsBoundary + forbidInternalModuleMocks
|
|
9
9
|
* + a deterministic import screen
|
|
10
|
+
* + enforceThinDrivingAdapter on UI/inbound
|
|
11
|
+
* adapter files
|
|
10
12
|
* acceptance-testing → enforceAcceptanceLanguage
|
|
11
13
|
*
|
|
12
14
|
* `jsRuleEntries(options?)` reproduces exactly what the shipped
|
|
@@ -16,10 +18,11 @@
|
|
|
16
18
|
* only the options its layout needs.
|
|
17
19
|
*/
|
|
18
20
|
import { basename } from 'node:path';
|
|
19
|
-
import {
|
|
21
|
+
import { forbidContentPattern } from '@nizos/probity';
|
|
20
22
|
import { enforceAcceptanceLanguage } from '../rules/acceptance-language.js';
|
|
21
23
|
import { forbidNewAmbientEffects, JS_AMBIENT_EFFECT_PATTERNS, requireGreenTestRun, withJudgeFailureDiagnostics, withContradictionRetry, } from '../rules/gates.js';
|
|
22
|
-
import {
|
|
24
|
+
import { enforceJsTdd } from '../rules/js-tdd.js';
|
|
25
|
+
import { enforcePortsBoundary, enforceThinDrivingAdapter, forbidInternalModuleMocks, forbidNewDomainDiscriminantChecks, } from '../rules/ports-and-adapters.js';
|
|
23
26
|
import { withExcludeGlobs } from '../rules/scoping.js';
|
|
24
27
|
import { enforceSpecTestParity, JS_TEST_DECLARATION, requireSpecBackedAcceptanceTest, surfaceScenarioLinkBreakage, } from '../rules/spec-test-parity.js';
|
|
25
28
|
import { surfaceGlossaryTermBreakage } from '../rules/ubiquitous-language.js';
|
|
@@ -43,6 +46,18 @@ export function jsRuleEntries(options = {}) {
|
|
|
43
46
|
const tddGlobs = options.tddGlobs ?? ['src/**', 'test/**', 'tests/**'];
|
|
44
47
|
const specGlobs = options.specGlobs ?? ['specs/**', 'acceptance/**', '**/*.feature'];
|
|
45
48
|
const excludeGlobs = options.excludeGlobs ?? ['spikes/**', '**/build/**'];
|
|
49
|
+
const drivingAdapterGlobs = [
|
|
50
|
+
...(options.drivingAdapterGlobs ?? [
|
|
51
|
+
'src/ui/**',
|
|
52
|
+
'src/components/**',
|
|
53
|
+
'src/**/*.tsx',
|
|
54
|
+
'!**/*.test.*',
|
|
55
|
+
'!**/*.spec.*',
|
|
56
|
+
'!**/*.stories.*',
|
|
57
|
+
]),
|
|
58
|
+
// Core code is never a driving adapter, even as .tsx.
|
|
59
|
+
...coreGlobs.filter((glob) => !glob.startsWith('!')).map((glob) => `!${glob}`),
|
|
60
|
+
];
|
|
46
61
|
const entries = [
|
|
47
62
|
// ── Boundaries: ports-and-adapters ──────────────────────────────
|
|
48
63
|
// Core purity. Point these globs at your core/domain/use-case
|
|
@@ -77,6 +92,32 @@ export function jsRuleEntries(options = {}) {
|
|
|
77
92
|
rules: [forbidInternalModuleMocks()],
|
|
78
93
|
},
|
|
79
94
|
];
|
|
95
|
+
// Driving adapters must be thin (issue #72). The core-purity block
|
|
96
|
+
// above stops vendors getting INTO core code; this stops business
|
|
97
|
+
// logic leaking OUT of it into UI components and handlers, which the
|
|
98
|
+
// TDD gate alone never questions (a component test makes the logic
|
|
99
|
+
// "tested"). The free discriminant screen runs first when
|
|
100
|
+
// configured; the judge runs before the TDD judge, so a denial here
|
|
101
|
+
// costs one AI call, not two.
|
|
102
|
+
if (drivingAdapterGlobs.some((glob) => !glob.startsWith('!'))) {
|
|
103
|
+
const [first, ...rest] = drivingAdapterGlobs;
|
|
104
|
+
entries.push({
|
|
105
|
+
files: [first, ...rest],
|
|
106
|
+
rules: [
|
|
107
|
+
...(options.domainDiscriminants?.length
|
|
108
|
+
? [
|
|
109
|
+
forbidNewDomainDiscriminantChecks({
|
|
110
|
+
discriminants: options.domainDiscriminants,
|
|
111
|
+
domainHint: options.domainHint,
|
|
112
|
+
}),
|
|
113
|
+
]
|
|
114
|
+
: []),
|
|
115
|
+
withJudgeFailureDiagnostics(withContradictionRetry(enforceThinDrivingAdapter({
|
|
116
|
+
coreExports: options.coreExportsInJudge ? { globs: coreGlobs } : undefined,
|
|
117
|
+
}))),
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
80
121
|
// Spec-to-test traceability (issue #18): OFF by default, so a
|
|
81
122
|
// project that hasn't opted in sees no behavior change. Setting
|
|
82
123
|
// `specsDir` wires the same set the KMP preset wires — deterministic
|
|
@@ -137,7 +178,7 @@ export function jsRuleEntries(options = {}) {
|
|
|
137
178
|
// screen, never after a model call.
|
|
138
179
|
entries.push({
|
|
139
180
|
files: tddGlobs,
|
|
140
|
-
rules: [
|
|
181
|
+
rules: [enforceJsTdd()],
|
|
141
182
|
});
|
|
142
183
|
// ── Outer loop: acceptance-testing ──────────────────────────────
|
|
143
184
|
// The Language Test on the spec layer only. Do NOT widen this to
|
package/dist/presets/js.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"js.js","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"js.js","sourceRoot":"","sources":["../../presets/js.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Rule } from '@nizos/probity';
|
|
2
|
+
/**
|
|
3
|
+
* Appended to Probity's default TDD rules for JS/TS. The defaults say
|
|
4
|
+
* both "adding a test is the red step" and "judge a new red at the
|
|
5
|
+
* green->red boundary too" (the refactor check), and the judge has
|
|
6
|
+
* read the second as a demand that the new test was already observed
|
|
7
|
+
* failing (#73; the Kotlin judge did the same in #43).
|
|
8
|
+
*/
|
|
9
|
+
export declare const JS_TDD_ADDENDUM = "## Adding a red test\n\n- Adding a failing test is the red step itself. A test-file write that adds one new test (with any imports, fixtures, or helpers it needs) passes without any prior run of that test: a test cannot have failed before it exists. \"Must be observed failing for the right reason\" applies only to the production write that follows it, never to the test write. This holds whether the asserted behavior is missing entirely or exists but is wrong, including behavior the previous cycle just implemented.\n- At a test write, the only green->red question is whether the prior green left an unmistakable refactor unmade. A passing prior run is the expected state before a new test is added, never a reason to block it. Do not block a test write because the new test has not been observed failing, because the last run was for a previous test, or because the test contradicts what production code does now.\n- The other rules still hold: a write adding more than one new test is a violation (restructuring existing tests is not adding), and so is a production write with no observed failing test for it. Observed failing means a test run, after the test was written, whose output shows that test failing. A test written in the session with no run after it has not been observed failing, and an earlier failing run of a different test does not count.";
|
|
10
|
+
/**
|
|
11
|
+
* Probity's `enforceTdd()` with {@link JS_TDD_ADDENDUM} appended, wrapped
|
|
12
|
+
* as the JS preset wires it: a self-contradicting deny is retried, and a
|
|
13
|
+
* judge that returns no verdict (spend limit, auth failure) is reported
|
|
14
|
+
* as an infrastructure failure rather than a TDD rejection. Use this in
|
|
15
|
+
* place of `withJudgeFailureDiagnostics(withContradictionRetry(enforceTdd()))`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function enforceJsTdd(): Rule;
|
|
18
|
+
//# sourceMappingURL=js-tdd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"js-tdd.d.ts","sourceRoot":"","sources":["../../rules/js-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAItD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,s1CAI8Z,CAAA;AAE1b;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAMnC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { enforceTdd } from '@nizos/probity';
|
|
2
|
+
import { withJudgeFailureDiagnostics, withContradictionRetry } from './gates.js';
|
|
3
|
+
/**
|
|
4
|
+
* Appended to Probity's default TDD rules for JS/TS. The defaults say
|
|
5
|
+
* both "adding a test is the red step" and "judge a new red at the
|
|
6
|
+
* green->red boundary too" (the refactor check), and the judge has
|
|
7
|
+
* read the second as a demand that the new test was already observed
|
|
8
|
+
* failing (#73; the Kotlin judge did the same in #43).
|
|
9
|
+
*/
|
|
10
|
+
export const JS_TDD_ADDENDUM = `## Adding a red test
|
|
11
|
+
|
|
12
|
+
- Adding a failing test is the red step itself. A test-file write that adds one new test (with any imports, fixtures, or helpers it needs) passes without any prior run of that test: a test cannot have failed before it exists. "Must be observed failing for the right reason" applies only to the production write that follows it, never to the test write. This holds whether the asserted behavior is missing entirely or exists but is wrong, including behavior the previous cycle just implemented.
|
|
13
|
+
- At a test write, the only green->red question is whether the prior green left an unmistakable refactor unmade. A passing prior run is the expected state before a new test is added, never a reason to block it. Do not block a test write because the new test has not been observed failing, because the last run was for a previous test, or because the test contradicts what production code does now.
|
|
14
|
+
- The other rules still hold: a write adding more than one new test is a violation (restructuring existing tests is not adding), and so is a production write with no observed failing test for it. Observed failing means a test run, after the test was written, whose output shows that test failing. A test written in the session with no run after it has not been observed failing, and an earlier failing run of a different test does not count.`;
|
|
15
|
+
/**
|
|
16
|
+
* Probity's `enforceTdd()` with {@link JS_TDD_ADDENDUM} appended, wrapped
|
|
17
|
+
* as the JS preset wires it: a self-contradicting deny is retried, and a
|
|
18
|
+
* judge that returns no verdict (spend limit, auth failure) is reported
|
|
19
|
+
* as an infrastructure failure rather than a TDD rejection. Use this in
|
|
20
|
+
* place of `withJudgeFailureDiagnostics(withContradictionRetry(enforceTdd()))`.
|
|
21
|
+
*/
|
|
22
|
+
export function enforceJsTdd() {
|
|
23
|
+
return withJudgeFailureDiagnostics(withContradictionRetry(enforceTdd({ instructions: (defaults) => `${defaults}\n\n${JS_TDD_ADDENDUM}` })));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=js-tdd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"js-tdd.js","sourceRoot":"","sources":["../../rules/js-tdd.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,gBAAgB,CAAA;AAEtD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEhF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;0bAI2Z,CAAA;AAE1b;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,2BAA2B,CAChC,sBAAsB,CACpB,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,QAAQ,OAAO,eAAe,EAAE,EAAE,CAAC,CAChF,CACF,CAAA;AACH,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Rule } from '@nizos/probity';
|
|
2
|
+
import { type NamedPattern } from './gates.js';
|
|
2
3
|
/**
|
|
3
4
|
* AI-validated enforcement of the `ports-and-adapters` skill: the
|
|
4
5
|
* Dependency Rule (core imports nothing from adapters, frameworks,
|
|
@@ -83,4 +84,91 @@ export declare function enforceAdapterObservability(options?: {
|
|
|
83
84
|
export declare function forbidInternalModuleMocks(options?: {
|
|
84
85
|
allow?: string | RegExp;
|
|
85
86
|
}): Rule;
|
|
87
|
+
/**
|
|
88
|
+
* One pattern per discriminant: the field compared to a string literal
|
|
89
|
+
* with `===`, `!==`, `==` or `!=`, in either order
|
|
90
|
+
* (`viewer.role === 'SuperUser'`, `'Draft' !== order.status`).
|
|
91
|
+
*/
|
|
92
|
+
export declare function domainDiscriminantPatterns(discriminants: readonly string[]): NamedPattern[];
|
|
93
|
+
/**
|
|
94
|
+
* Deterministic first screen for thin driving adapters (issue #72): a
|
|
95
|
+
* UI component or other inbound adapter that compares a domain
|
|
96
|
+
* discriminant — a role, a status, a plan — to a literal is deciding a
|
|
97
|
+
* business rule itself. The domain should export that decision
|
|
98
|
+
* (`canApprove(actor)`, `isEditable(order)`) and the adapter call
|
|
99
|
+
* it.
|
|
100
|
+
*
|
|
101
|
+
* Delta-based, like `forbidNewAmbientEffects`: only a write that adds
|
|
102
|
+
* comparisons beyond what the file on disk already has blocks, so an
|
|
103
|
+
* existing thick component doesn't freeze. No AI call.
|
|
104
|
+
*
|
|
105
|
+
* There is no default list. `status === 'loading'` is ordinary local
|
|
106
|
+
* view state in a UI, so the discriminants must be the fields that
|
|
107
|
+
* carry domain meaning in YOUR model.
|
|
108
|
+
*
|
|
109
|
+
* Applies to: write actions. Scope it to driving-adapter files (UI
|
|
110
|
+
* components, route handlers, CLI commands).
|
|
111
|
+
*
|
|
112
|
+
* @param options.discriminants — field names whose literal comparisons
|
|
113
|
+
* are domain decisions, e.g. `['role', 'plan']`.
|
|
114
|
+
* @param options.domainHint — appended to the block message to name
|
|
115
|
+
* where the decision should go, e.g. "permission rules live in
|
|
116
|
+
* src/domain/permissions.ts".
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* { files: ['src/ui/**'], rules: [forbidNewDomainDiscriminantChecks({ discriminants: ['role'] })] }
|
|
120
|
+
*/
|
|
121
|
+
export declare function forbidNewDomainDiscriminantChecks(options: {
|
|
122
|
+
discriminants: readonly string[];
|
|
123
|
+
domainHint?: string;
|
|
124
|
+
}): Rule;
|
|
125
|
+
/** Names a JS/TS module exports, from its source text. */
|
|
126
|
+
export declare function exportedNames(content: string): string[];
|
|
127
|
+
/**
|
|
128
|
+
* The core's export list, one line per module (`src/domain/roles.ts:
|
|
129
|
+
* canApprove, canEdit`), for the thin-driving-adapter judge. Test files
|
|
130
|
+
* are skipped. Truncated beyond `maxChars`.
|
|
131
|
+
*/
|
|
132
|
+
export declare function listCoreExports(options: {
|
|
133
|
+
globs: readonly string[];
|
|
134
|
+
root: string;
|
|
135
|
+
maxChars: number;
|
|
136
|
+
}): string;
|
|
137
|
+
/**
|
|
138
|
+
* AI-validated rule for thin driving adapters (issue #72): UI
|
|
139
|
+
* components, pages, route handlers and CLI commands must not add
|
|
140
|
+
* business logic. The judge blocks a write that adds (a) a decision in
|
|
141
|
+
* domain terms, (b) coordination of more than one port/use-case call,
|
|
142
|
+
* (c) a re-implementation of something the core already exports, or
|
|
143
|
+
* (d) a framework-free use case filed as an adapter — naming the
|
|
144
|
+
* extraction target (domain function or use case) in the deny.
|
|
145
|
+
* Rendering, display formatting, local view state and one call per
|
|
146
|
+
* user intent pass. Delta-based: only what a write adds is judged.
|
|
147
|
+
*
|
|
148
|
+
* The other ports-and-adapters rules stop vendors getting INTO core
|
|
149
|
+
* code; this one stops logic leaking OUT of it.
|
|
150
|
+
*
|
|
151
|
+
* Applies to: write actions. Scope it to driving-adapter files — every
|
|
152
|
+
* matching write costs an AI call. Pair it with
|
|
153
|
+
* `forbidNewDomainDiscriminantChecks` so the obvious cases block free.
|
|
154
|
+
*
|
|
155
|
+
* @param options.coreExports — when set, the judge is given the
|
|
156
|
+
* export names of every source file matching `globs` under `root`
|
|
157
|
+
* (default `process.cwd()`), truncated beyond `maxChars` (default
|
|
158
|
+
* 8000), so it can spot a copy of an existing domain rule. Costs a
|
|
159
|
+
* directory scan per judged write.
|
|
160
|
+
* @param options.instructions — replaces or extends the default rules
|
|
161
|
+
* text (string, or `(defaults) => ...`).
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* { files: ['src/ui/**', '!**\/*.test.*'], rules: [enforceThinDrivingAdapter()] }
|
|
165
|
+
*/
|
|
166
|
+
export declare function enforceThinDrivingAdapter(options?: {
|
|
167
|
+
coreExports?: {
|
|
168
|
+
globs: readonly string[];
|
|
169
|
+
root?: string;
|
|
170
|
+
maxChars?: number;
|
|
171
|
+
};
|
|
172
|
+
instructions?: string | ((defaults: string) => string);
|
|
173
|
+
}): Rule;
|
|
86
174
|
//# sourceMappingURL=ports-and-adapters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports-and-adapters.d.ts","sourceRoot":"","sources":["../../rules/ports-and-adapters.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ports-and-adapters.d.ts","sourceRoot":"","sources":["../../rules/ports-and-adapters.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAU,IAAI,EAA2B,MAAM,gBAAgB,CAAA;AAE3E,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAA;AAoJlE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;IACtD,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CACrB,GACL,IAAI,CAuCN;AAsED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,GAAE;IACP,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;CAClD,GACL,IAAI,CAoCN;AAcD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAO,GACxC,IAAI,CAkCN;AAMD;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,YAAY,EAAE,CAYhB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE;IACzD,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,IAAI,CAwBP;AAeD,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAYvD;AAmBD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;CACjB,GAAG,MAAM,CAmBT;AAgFD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,GAAE;IACP,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5E,YAAY,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,CAAA;CAClD,GACL,IAAI,CAwCN"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join, relative, sep } from 'node:path';
|
|
3
|
+
import { introducedPatterns } from './gates.js';
|
|
4
|
+
import { buildMatcher } from './scoping.js';
|
|
1
5
|
// reason comes FIRST in the shape: an autoregressive model commits to
|
|
2
6
|
// each field in order, so kind-first forces the verdict before the
|
|
3
7
|
// analysis — observed live producing a "violation" whose reason
|
|
@@ -372,4 +376,289 @@ export function forbidInternalModuleMocks(options = {}) {
|
|
|
372
376
|
};
|
|
373
377
|
};
|
|
374
378
|
}
|
|
379
|
+
function escapeRegExp(text) {
|
|
380
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* One pattern per discriminant: the field compared to a string literal
|
|
384
|
+
* with `===`, `!==`, `==` or `!=`, in either order
|
|
385
|
+
* (`viewer.role === 'SuperUser'`, `'Draft' !== order.status`).
|
|
386
|
+
*/
|
|
387
|
+
export function domainDiscriminantPatterns(discriminants) {
|
|
388
|
+
return discriminants.map((name) => {
|
|
389
|
+
const field = escapeRegExp(name);
|
|
390
|
+
const literal = String.raw `(['"\x60])[^'"\x60\n]*\1`;
|
|
391
|
+
return {
|
|
392
|
+
label: `${name} compared to a literal`,
|
|
393
|
+
pattern: new RegExp(String.raw `\b${field}\s*[!=]==?\s*['"\x60]|${literal}\s*[!=]==?\s*[\w$.?!]*\b${field}\b`, 'g'),
|
|
394
|
+
};
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Deterministic first screen for thin driving adapters (issue #72): a
|
|
399
|
+
* UI component or other inbound adapter that compares a domain
|
|
400
|
+
* discriminant — a role, a status, a plan — to a literal is deciding a
|
|
401
|
+
* business rule itself. The domain should export that decision
|
|
402
|
+
* (`canApprove(actor)`, `isEditable(order)`) and the adapter call
|
|
403
|
+
* it.
|
|
404
|
+
*
|
|
405
|
+
* Delta-based, like `forbidNewAmbientEffects`: only a write that adds
|
|
406
|
+
* comparisons beyond what the file on disk already has blocks, so an
|
|
407
|
+
* existing thick component doesn't freeze. No AI call.
|
|
408
|
+
*
|
|
409
|
+
* There is no default list. `status === 'loading'` is ordinary local
|
|
410
|
+
* view state in a UI, so the discriminants must be the fields that
|
|
411
|
+
* carry domain meaning in YOUR model.
|
|
412
|
+
*
|
|
413
|
+
* Applies to: write actions. Scope it to driving-adapter files (UI
|
|
414
|
+
* components, route handlers, CLI commands).
|
|
415
|
+
*
|
|
416
|
+
* @param options.discriminants — field names whose literal comparisons
|
|
417
|
+
* are domain decisions, e.g. `['role', 'plan']`.
|
|
418
|
+
* @param options.domainHint — appended to the block message to name
|
|
419
|
+
* where the decision should go, e.g. "permission rules live in
|
|
420
|
+
* src/domain/permissions.ts".
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* { files: ['src/ui/**'], rules: [forbidNewDomainDiscriminantChecks({ discriminants: ['role'] })] }
|
|
424
|
+
*/
|
|
425
|
+
export function forbidNewDomainDiscriminantChecks(options) {
|
|
426
|
+
const patterns = domainDiscriminantPatterns(options.discriminants);
|
|
427
|
+
return async function forbidNewDomainDiscriminantChecks(action, ctx) {
|
|
428
|
+
if (action.kind !== 'write' || patterns.length === 0)
|
|
429
|
+
return { kind: 'pass' };
|
|
430
|
+
const introduced = await introducedPatterns(action, ctx, patterns);
|
|
431
|
+
if (introduced.length === 0)
|
|
432
|
+
return { kind: 'pass' };
|
|
433
|
+
const hint = options.domainHint ? ` ${options.domainHint}.` : '';
|
|
434
|
+
return {
|
|
435
|
+
kind: 'violation',
|
|
436
|
+
reason: `This write adds a domain decision to a driving adapter (${introduced.join(', ')}). Driving adapters (UI components, route handlers) render ` +
|
|
437
|
+
'core-supplied state and forward user intent; they do not decide ' +
|
|
438
|
+
'business rules. Add a function to the domain that makes this ' +
|
|
439
|
+
'decision (e.g. `canApprove(actor)`, `isEditable(order)`), ' +
|
|
440
|
+
`test it without the UI framework, and call it here.${hint} ` +
|
|
441
|
+
'Existing comparisons in the file are untouched by this rule — ' +
|
|
442
|
+
'only new ones are blocked.',
|
|
443
|
+
};
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
const EXPORT_DECLARATION = /^\s*export\s+(?:default\s+)?(?:declare\s+)?(?:async\s+)?(?:abstract\s+)?(?:function\*?|const|let|var|class|type|interface|enum)\s+([A-Za-z_$][\w$]*)/gm;
|
|
447
|
+
const EXPORT_LIST = /^\s*export\s+(?:type\s+)?\{([^}]*)\}/gm;
|
|
448
|
+
const SOURCE_FILE = /\.(?:[cm]?[jt]sx?)$/;
|
|
449
|
+
const EXPORT_SCAN_SKIP_DIRS = new Set([
|
|
450
|
+
'node_modules',
|
|
451
|
+
'.git',
|
|
452
|
+
'build',
|
|
453
|
+
'dist',
|
|
454
|
+
'out',
|
|
455
|
+
'coverage',
|
|
456
|
+
]);
|
|
457
|
+
/** Names a JS/TS module exports, from its source text. */
|
|
458
|
+
export function exportedNames(content) {
|
|
459
|
+
const names = new Set();
|
|
460
|
+
for (const match of content.matchAll(EXPORT_DECLARATION)) {
|
|
461
|
+
if (match[1])
|
|
462
|
+
names.add(match[1]);
|
|
463
|
+
}
|
|
464
|
+
for (const match of content.matchAll(EXPORT_LIST)) {
|
|
465
|
+
for (const part of (match[1] ?? '').split(',')) {
|
|
466
|
+
const name = part.trim().split(/\s+as\s+/).pop()?.replace(/^type\s+/, '').trim();
|
|
467
|
+
if (name && /^[A-Za-z_$][\w$]*$/.test(name))
|
|
468
|
+
names.add(name);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
return [...names];
|
|
472
|
+
}
|
|
473
|
+
function sourceFiles(dir, out = []) {
|
|
474
|
+
let entries;
|
|
475
|
+
try {
|
|
476
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return out;
|
|
480
|
+
}
|
|
481
|
+
for (const entry of entries) {
|
|
482
|
+
if (entry.isDirectory()) {
|
|
483
|
+
if (!EXPORT_SCAN_SKIP_DIRS.has(entry.name))
|
|
484
|
+
sourceFiles(join(dir, entry.name), out);
|
|
485
|
+
}
|
|
486
|
+
else if (entry.isFile() && SOURCE_FILE.test(entry.name)) {
|
|
487
|
+
out.push(join(dir, entry.name));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return out;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* The core's export list, one line per module (`src/domain/roles.ts:
|
|
494
|
+
* canApprove, canEdit`), for the thin-driving-adapter judge. Test files
|
|
495
|
+
* are skipped. Truncated beyond `maxChars`.
|
|
496
|
+
*/
|
|
497
|
+
export function listCoreExports(options) {
|
|
498
|
+
const matches = buildMatcher(options.globs);
|
|
499
|
+
const lines = [];
|
|
500
|
+
for (const file of sourceFiles(options.root).sort()) {
|
|
501
|
+
const rel = relative(options.root, file).split(sep).join('/');
|
|
502
|
+
if (!matches(rel) || /\.(?:test|spec)\.[^.]+$/.test(rel))
|
|
503
|
+
continue;
|
|
504
|
+
let content;
|
|
505
|
+
try {
|
|
506
|
+
content = readFileSync(file, 'utf8');
|
|
507
|
+
}
|
|
508
|
+
catch {
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
const names = exportedNames(content);
|
|
512
|
+
if (names.length > 0)
|
|
513
|
+
lines.push(`${rel}: ${names.join(', ')}`);
|
|
514
|
+
}
|
|
515
|
+
const text = lines.join('\n');
|
|
516
|
+
return text.length > options.maxChars
|
|
517
|
+
? `${text.slice(0, options.maxChars)}\n(...export list truncated...)`
|
|
518
|
+
: text;
|
|
519
|
+
}
|
|
520
|
+
const THIN_DRIVING_ADAPTER_INSTRUCTIONS = `## Role
|
|
521
|
+
|
|
522
|
+
You are a driving-adapter thinness validator. A driving (inbound)
|
|
523
|
+
adapter is the code the outside world calls first: a UI component, a
|
|
524
|
+
page, a route handler, a CLI command. In this codebase it renders
|
|
525
|
+
core-supplied state and forwards user intent to the core. Business
|
|
526
|
+
logic in it can only be tested through the framework, drifts when it
|
|
527
|
+
is copied, and is invisible to headless and acceptance tests. Judge
|
|
528
|
+
whether the pending write keeps this adapter thin, per the rules below.
|
|
529
|
+
|
|
530
|
+
## Inputs
|
|
531
|
+
|
|
532
|
+
1. "Current file content" — what's on disk right now (may be a marker
|
|
533
|
+
like \`(file does not exist)\`).
|
|
534
|
+
2. "Pending action" — the file path and the file content after the
|
|
535
|
+
write.
|
|
536
|
+
3. Optionally, "Core exports" — what the domain and use-case modules
|
|
537
|
+
already export, one module per line.
|
|
538
|
+
|
|
539
|
+
## What you judge
|
|
540
|
+
|
|
541
|
+
Judge only what this write adds (before → after), never pre-existing
|
|
542
|
+
code: an existing thick component is migrated incrementally, so a
|
|
543
|
+
write that leaves old logic in place but adds none passes. A transient
|
|
544
|
+
state (an unresolved import, a half-built component) is never itself a
|
|
545
|
+
violation. A block recorded earlier in the session is a past verdict,
|
|
546
|
+
not a rule; when the user says to let a change through, treat that as
|
|
547
|
+
authoritative and pass. The bar is a clear violation; when genuinely
|
|
548
|
+
ambiguous, pass.
|
|
549
|
+
|
|
550
|
+
## Block a write that adds any of these
|
|
551
|
+
|
|
552
|
+
(a) **A decision expressed in domain terms**: eligibility, permission,
|
|
553
|
+
a state transition, a validation rule, or a derived value used to
|
|
554
|
+
make one (who may approve, which approver a request is routed to,
|
|
555
|
+
whether an order can still be edited). Comparing a role, status or plan
|
|
556
|
+
to a literal is the usual shape. Extraction target: a domain
|
|
557
|
+
function the adapter calls.
|
|
558
|
+
(b) **Coordination of more than one port or use-case call in one
|
|
559
|
+
handler**, or a policy about their outcomes (call the domain, then
|
|
560
|
+
save, then notify; "a failed notification must never fail the
|
|
561
|
+
submit"). That is a use case. Extraction target: a use-case
|
|
562
|
+
function, tested headless with fakes at its ports, which the
|
|
563
|
+
handler calls once.
|
|
564
|
+
(c) **A re-implementation of something the core already exports**, or
|
|
565
|
+
a copy of a domain rule that already lives elsewhere (a
|
|
566
|
+
display-name rule, a permission check). When "Core exports" lists
|
|
567
|
+
a matching name, block and name it. Extraction target: call the
|
|
568
|
+
existing export, or move the rule into the domain once and call it.
|
|
569
|
+
(d) **A use case filed as an adapter**: a module under a driving-
|
|
570
|
+
adapter path that uses no UI or framework API and coordinates
|
|
571
|
+
ports (e.g. \`startCheckout(billing, logger)\`). Extraction target:
|
|
572
|
+
move it to the use-case layer.
|
|
573
|
+
|
|
574
|
+
## Always pass
|
|
575
|
+
|
|
576
|
+
- Rendering and layout, styling, accessibility attributes.
|
|
577
|
+
- Formatting for display: dates, currency, pluralization, truncation.
|
|
578
|
+
- Local view state: open/closed, loading/error flags, form field
|
|
579
|
+
values, the selected tab, input focus.
|
|
580
|
+
- Parsing and shaping user input into the arguments of a call.
|
|
581
|
+
- Calling ONE use case or port per user intent and showing its
|
|
582
|
+
result or error.
|
|
583
|
+
- Calling a domain function to make a decision (\`canApprove(actor)\`)
|
|
584
|
+
— that is the intended pattern.
|
|
585
|
+
- Wiring/composition (providers, DI, routing tables), test code, and
|
|
586
|
+
deleting code.
|
|
587
|
+
- Files that are clearly not driving adapters despite the path.
|
|
588
|
+
|
|
589
|
+
## When you block
|
|
590
|
+
|
|
591
|
+
Name the exact logic the write adds and its extraction target: a
|
|
592
|
+
domain function (for a decision or a duplicated rule) or a use case
|
|
593
|
+
(for coordination). Name the existing core export to call when there
|
|
594
|
+
is one. Remind the agent that under this codebase's TDD gate the
|
|
595
|
+
extracted function gets its failing test first, written without the UI
|
|
596
|
+
framework.`;
|
|
597
|
+
/**
|
|
598
|
+
* AI-validated rule for thin driving adapters (issue #72): UI
|
|
599
|
+
* components, pages, route handlers and CLI commands must not add
|
|
600
|
+
* business logic. The judge blocks a write that adds (a) a decision in
|
|
601
|
+
* domain terms, (b) coordination of more than one port/use-case call,
|
|
602
|
+
* (c) a re-implementation of something the core already exports, or
|
|
603
|
+
* (d) a framework-free use case filed as an adapter — naming the
|
|
604
|
+
* extraction target (domain function or use case) in the deny.
|
|
605
|
+
* Rendering, display formatting, local view state and one call per
|
|
606
|
+
* user intent pass. Delta-based: only what a write adds is judged.
|
|
607
|
+
*
|
|
608
|
+
* The other ports-and-adapters rules stop vendors getting INTO core
|
|
609
|
+
* code; this one stops logic leaking OUT of it.
|
|
610
|
+
*
|
|
611
|
+
* Applies to: write actions. Scope it to driving-adapter files — every
|
|
612
|
+
* matching write costs an AI call. Pair it with
|
|
613
|
+
* `forbidNewDomainDiscriminantChecks` so the obvious cases block free.
|
|
614
|
+
*
|
|
615
|
+
* @param options.coreExports — when set, the judge is given the
|
|
616
|
+
* export names of every source file matching `globs` under `root`
|
|
617
|
+
* (default `process.cwd()`), truncated beyond `maxChars` (default
|
|
618
|
+
* 8000), so it can spot a copy of an existing domain rule. Costs a
|
|
619
|
+
* directory scan per judged write.
|
|
620
|
+
* @param options.instructions — replaces or extends the default rules
|
|
621
|
+
* text (string, or `(defaults) => ...`).
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* { files: ['src/ui/**', '!**\/*.test.*'], rules: [enforceThinDrivingAdapter()] }
|
|
625
|
+
*/
|
|
626
|
+
export function enforceThinDrivingAdapter(options = {}) {
|
|
627
|
+
const rules = typeof options.instructions === 'function'
|
|
628
|
+
? options.instructions(THIN_DRIVING_ADAPTER_INSTRUCTIONS)
|
|
629
|
+
: (options.instructions ?? THIN_DRIVING_ADAPTER_INSTRUCTIONS);
|
|
630
|
+
return async function enforceThinDrivingAdapter(action, ctx) {
|
|
631
|
+
if (action.kind !== 'write')
|
|
632
|
+
return { kind: 'pass' };
|
|
633
|
+
if (!ctx?.agent) {
|
|
634
|
+
return {
|
|
635
|
+
kind: 'violation',
|
|
636
|
+
reason: 'enforceThinDrivingAdapter: no AI agent available; configure Config.ai or use a vendor that ships one.',
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
const before = (await ctx.readFile?.(action.path)) ?? {
|
|
640
|
+
kind: 'unknown',
|
|
641
|
+
};
|
|
642
|
+
const sections = [
|
|
643
|
+
rules,
|
|
644
|
+
`## Current file content\n\n${formatBefore(before)}`,
|
|
645
|
+
`## Pending action\n\nFile: ${action.path}\n\n${action.content}`,
|
|
646
|
+
];
|
|
647
|
+
if (options.coreExports) {
|
|
648
|
+
const exports = listCoreExports({
|
|
649
|
+
globs: options.coreExports.globs,
|
|
650
|
+
root: options.coreExports.root ?? process.cwd(),
|
|
651
|
+
maxChars: options.coreExports.maxChars ?? 8000,
|
|
652
|
+
});
|
|
653
|
+
if (exports)
|
|
654
|
+
sections.push(`## Core exports\n\n${exports}`);
|
|
655
|
+
}
|
|
656
|
+
sections.push(RESPONSE_SPEC);
|
|
657
|
+
const verdict = await ctx.agent.reason(sections.join('\n\n'));
|
|
658
|
+
if (verdict.kind === 'violation') {
|
|
659
|
+
return { kind: 'violation', reason: verdict.reason };
|
|
660
|
+
}
|
|
661
|
+
return { kind: 'pass', reason: verdict.reason };
|
|
662
|
+
};
|
|
663
|
+
}
|
|
375
664
|
//# sourceMappingURL=ports-and-adapters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports-and-adapters.js","sourceRoot":"","sources":["../../rules/ports-and-adapters.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ports-and-adapters.js","sourceRoot":"","sources":["../../rules/ports-and-adapters.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jjchill/probity-rules",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.16",
|
|
4
4
|
"description": "Versioned Probity rule presets and CLI tooling for the agent-skills catalog (test-driven-development, ports-and-adapters, acceptance-testing, spec-test parity, ubiquitous-language) — see hooks/PROBITY.md.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/probity.config.ts
CHANGED
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
* - coreGlobs — where your core/domain code lives
|
|
15
15
|
* - infrastructureImports — your stack's known vendor/framework imports
|
|
16
16
|
* - specGlobs — where your acceptance specs live
|
|
17
|
+
* - drivingAdapterGlobs — your UI components / route handlers, held
|
|
18
|
+
* thin (an AI call per write; [] = off)
|
|
19
|
+
* - domainDiscriminants — fields whose literal comparison in UI code
|
|
20
|
+
* is a domain decision, e.g. ['role'] (off
|
|
21
|
+
* until set; blocks free, before the AI call)
|
|
17
22
|
* - glossaryPath — absolute path to a ubiquitous-language glossary
|
|
18
23
|
* - commitCommand / commitSuccessPattern / commitFailurePattern
|
|
19
24
|
* — your real test command and its output shapes
|
|
@@ -36,5 +41,7 @@ import { jsRuleEntries } from '@jjchill/probity-rules/presets/js'
|
|
|
36
41
|
export default defineConfig({
|
|
37
42
|
rules: jsRuleEntries({
|
|
38
43
|
// glossaryPath: fileURLToPath(new URL('./docs/GLOSSARY.md', import.meta.url)),
|
|
44
|
+
// domainDiscriminants: ['role'],
|
|
45
|
+
// coreExportsInJudge: true,
|
|
39
46
|
}),
|
|
40
47
|
})
|