@jterrazz/test 16.1.1 → 18.0.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/README.md +45 -171
- package/dist/browser/index.js +1 -2980
- package/dist/browser/services.js +1 -0
- package/dist/browser/stubs.js +1 -0
- package/dist/browser-shared-index.browser.js +3233 -0
- package/dist/checker.d.ts +6 -1
- package/dist/checker.js +3721 -2624
- package/dist/config.d.ts +40 -0
- package/dist/config.js +309 -0
- package/dist/in-place.global-setup.d.ts +12 -0
- package/dist/in-place.global-setup.js +21 -0
- package/dist/index.d.ts +1641 -3004
- package/dist/index.js +5095 -3835
- package/dist/mobile-session.global-setup.d.ts +15 -0
- package/dist/mobile-session.global-setup.js +31 -0
- package/dist/oxlint.cjs +6069 -5634
- package/dist/oxlint.d.cts +43 -7212
- package/dist/oxlint.d.ts +43 -7212
- package/dist/oxlint.js +3979 -5799
- package/dist/route-coverage.global-setup.d.ts +43 -0
- package/dist/route-coverage.global-setup.js +1 -0
- package/dist/services.d.ts +3 -0
- package/dist/services.global-setup.d.ts +43 -0
- package/dist/services.global-setup.js +1 -0
- package/dist/services.js +597 -0
- package/dist/shared-appium.adapter.js +428 -0
- package/dist/shared-artifacts.js +34 -0
- package/dist/shared-chapter.js +7 -0
- package/dist/shared-container.port.d.ts +31 -0
- package/dist/shared-derived-projects.js +73 -0
- package/dist/shared-device.port.d.ts +189 -0
- package/dist/shared-exchange.js +447 -0
- package/dist/shared-in-place.js +172 -0
- package/dist/shared-index.services.d.ts +346 -0
- package/dist/shared-index.stubs.d.ts +287 -0
- package/dist/shared-json-shape.js +17 -0
- package/dist/shared-landmarks.js +71 -0
- package/dist/shared-ledger.js +68 -0
- package/dist/shared-listened-port.js +19 -0
- package/dist/shared-literate-plugin.js +184 -0
- package/dist/shared-manifest.js +1321 -0
- package/dist/shared-pause.js +22 -0
- package/dist/shared-peer.js +88 -0
- package/dist/shared-playwright.adapter.js +328 -0
- package/dist/shared-process-alive.js +13 -0
- package/dist/shared-process.adapter.js +74 -0
- package/dist/shared-record-key.js +13 -0
- package/dist/shared-refusal.js +35 -0
- package/dist/shared-resolve.js +24 -0
- package/dist/shared-route-coverage.global-setup.js +187 -0
- package/dist/shared-scenario-failure.js +198 -0
- package/dist/shared-serve.js +407 -0
- package/dist/shared-service-images.js +10 -0
- package/dist/shared-services.global-setup.js +174 -0
- package/dist/shared-session-ledger.js +305 -0
- package/dist/shared-setup-entry.js +12 -0
- package/dist/shared-source-scan.js +133 -0
- package/dist/shared-spec-document.js +303 -0
- package/dist/shared-spec-grammar.js +66 -0
- package/dist/shared-specifications.js +26 -0
- package/dist/shared-specs-modules.js +1033 -0
- package/dist/shared-stub-reply.js +167 -0
- package/dist/shared-stub-server.js +142 -0
- package/dist/shared-temp-root.global-setup.js +73 -0
- package/dist/shared-test-baseline.js +26 -0
- package/dist/shared-test-section.js +58 -0
- package/dist/shared-testcontainers.adapter.js +306 -0
- package/dist/shared-tokens.js +55 -0
- package/dist/shared-yaml-document.js +119 -0
- package/dist/stubs.d.ts +2 -0
- package/dist/stubs.js +657 -0
- package/dist/temp-root.global-setup.d.ts +7 -0
- package/dist/temp-root.global-setup.js +1 -0
- package/dist/vitest.d.ts +93 -164
- package/dist/vitest.js +382 -550
- package/docs/README.md +82 -36
- package/docs/concepts/architecture.md +118 -0
- package/docs/concepts/conventions.md +333 -0
- package/docs/guides/api-specs.md +374 -0
- package/docs/guides/cli-specs.md +566 -0
- package/docs/guides/component-specs.md +252 -0
- package/docs/guides/develop.md +97 -0
- package/docs/guides/integration-specs.md +181 -0
- package/docs/guides/job-specs.md +180 -0
- package/docs/guides/lint-specs.md +174 -0
- package/docs/guides/mobile-specs.md +319 -0
- package/docs/guides/module-tests.md +149 -0
- package/docs/guides/release.md +44 -0
- package/docs/guides/spec-documents.md +189 -0
- package/docs/guides/website-specs.md +413 -0
- package/docs/reference/assertions.md +345 -0
- package/docs/reference/glossary.md +20 -0
- package/docs/reference/linting.md +483 -0
- package/docs/reference/services.md +236 -0
- package/docs/reference/stubs.md +500 -0
- package/docs/reference/time-and-doubles.md +137 -0
- package/docs/reference/tokens.md +258 -0
- package/docs/reference/visitor.md +221 -0
- package/docs/start/getting-started.md +187 -0
- package/docs/start/set-up-a-project.md +228 -0
- package/package.json +56 -36
- package/schema/spec.schema.json +43 -17
- package/dist/appium.adapter.js +0 -489
- package/dist/artifacts.js +0 -32
- package/dist/fixtures.js +0 -110
- package/dist/literate.js +0 -1747
- package/dist/match.js +0 -804
- package/dist/playwright.adapter.js +0 -438
- package/dist/server.js +0 -160
- package/dist/stream.js +0 -321
- package/dist/substring-warning.js +0 -282
- package/docs/01-architecture.md +0 -95
- package/docs/02-developing.md +0 -351
- package/docs/03-testing.md +0 -495
- package/docs/04-operating.md +0 -101
- package/docs/05-module-tests.md +0 -152
- package/docs/06-integration.md +0 -180
- package/docs/07-component.md +0 -246
- package/docs/08-website.md +0 -404
- package/docs/09-mobile.md +0 -270
- package/docs/10-api.md +0 -264
- package/docs/11-jobs.md +0 -157
- package/docs/12-cli.md +0 -677
- package/docs/13-elements.md +0 -248
- package/docs/14-assertions.md +0 -314
- package/docs/15-tokens.md +0 -253
- package/docs/16-contracts.md +0 -438
- package/docs/17-services.md +0 -188
- package/docs/18-conventions.md +0 -332
- package/docs/19-linting.md +0 -512
- package/docs/decisions/001-v9-conventions-on-three-channels.md +0 -50
- package/docs/decisions/002-the-statique-channel-holds-only-what-upstream-does-not.md +0 -49
- package/docs/decisions/003-a-rendered-component-is-a-facet-on-vitest-browser-mode.md +0 -84
- package/docs/decisions/004-a-module-against-real-services-or-a-golden-is-the-integration-facet.md +0 -81
- package/docs/decisions/005-the-doubles-ladder-is-closed.md +0 -86
- package/docs/decisions/006-the-catalogue-reaches-a-file-by-its-role.md +0 -245
- package/docs/decisions/007-compose-mode-leaves-the-package.md +0 -53
- package/docs/decisions/008-vitest-5-node-24-and-the-native-seams-as-optional-peers.md +0 -75
- package/docs/decisions/_template.md +0 -22
- package/docs/reference/classes/Matcher.md +0 -120
- package/docs/reference/classes/ProcessHandle.md +0 -368
- package/docs/reference/functions/defineContract.md +0 -39
- package/docs/reference/functions/defineContracts.md +0 -36
- package/docs/reference/functions/disabled.md +0 -28
- package/docs/reference/functions/enabled.md +0 -20
- package/docs/reference/functions/focused.md +0 -26
- package/docs/reference/functions/mockOf.md +0 -79
- package/docs/reference/functions/postgres.md +0 -31
- package/docs/reference/functions/process.md +0 -33
- package/docs/reference/functions/redis.md +0 -28
- package/docs/reference/functions/required.md +0 -41
- package/docs/reference/functions/selected.md +0 -26
- package/docs/reference/functions/sqlite.md +0 -33
- package/docs/reference/functions/testId.md +0 -20
- package/docs/reference/functions/text.md +0 -40
- package/docs/reference/functions/valued.md +0 -28
- package/docs/reference/functions/waitUntil.md +0 -46
- package/docs/reference/functions/within.md +0 -29
- package/docs/reference/index.md +0 -196
- package/docs/reference/interfaces/BaseResult.md +0 -87
- package/docs/reference/interfaces/CallResult.md +0 -160
- package/docs/reference/interfaces/CaptureScope.md +0 -82
- package/docs/reference/interfaces/CliResult.md +0 -253
- package/docs/reference/interfaces/ContainerAccessor.md +0 -166
- package/docs/reference/interfaces/DirectoryAccessor.md +0 -33
- package/docs/reference/interfaces/FetchResult.md +0 -180
- package/docs/reference/interfaces/FilesystemAccessor.md +0 -46
- package/docs/reference/interfaces/HttpResult.md +0 -126
- package/docs/reference/interfaces/JsonAccessor.md +0 -46
- package/docs/reference/interfaces/PageResult.md +0 -356
- package/docs/reference/interfaces/RenderResult.md +0 -72
- package/docs/reference/interfaces/RenderedText.md +0 -110
- package/docs/reference/interfaces/ResponseAccessor.md +0 -47
- package/docs/reference/interfaces/ScreenResult.md +0 -128
- package/docs/reference/interfaces/TableAccessor.md +0 -26
- package/docs/reference/interfaces/TextAccessor.md +0 -96
- package/docs/reference/type-aliases/ApiHandle.md +0 -68
- package/docs/reference/type-aliases/ApiSpecification.md +0 -213
- package/docs/reference/type-aliases/ApiSpecificationOptions.md +0 -68
- package/docs/reference/type-aliases/BrowserConsoleMessage.md +0 -30
- package/docs/reference/type-aliases/BrowserLinkElement.md +0 -50
- package/docs/reference/type-aliases/BrowserMetaElement.md +0 -40
- package/docs/reference/type-aliases/BrowserOpenOptions.md +0 -87
- package/docs/reference/type-aliases/BrowserPage.md +0 -132
- package/docs/reference/type-aliases/BrowserPort.md +0 -51
- package/docs/reference/type-aliases/CliEnv.md +0 -11
- package/docs/reference/type-aliases/CliHandle.md +0 -80
- package/docs/reference/type-aliases/CliInput.md +0 -36
- package/docs/reference/type-aliases/CliOutput.md +0 -46
- package/docs/reference/type-aliases/CliPort.md +0 -58
- package/docs/reference/type-aliases/CliSpecification.md +0 -144
- package/docs/reference/type-aliases/CliSpecificationOptions.md +0 -134
- package/docs/reference/type-aliases/ComponentChain.md +0 -156
- package/docs/reference/type-aliases/ComponentScenario.md +0 -20
- package/docs/reference/type-aliases/ComponentUi.md +0 -47
- package/docs/reference/type-aliases/ComponentVisitor.md +0 -10
- package/docs/reference/type-aliases/ContainerPort.md +0 -113
- package/docs/reference/type-aliases/Contract.md +0 -68
- package/docs/reference/type-aliases/ContractInput.md +0 -13
- package/docs/reference/type-aliases/ContractRequest.md +0 -95
- package/docs/reference/type-aliases/ContractResponder.md +0 -23
- package/docs/reference/type-aliases/ContractResponse.md +0 -78
- package/docs/reference/type-aliases/ContractResponseValue.md +0 -13
- package/docs/reference/type-aliases/Contracts.md +0 -48
- package/docs/reference/type-aliases/DatabaseKeys.md +0 -16
- package/docs/reference/type-aliases/DatabasePort.md +0 -72
- package/docs/reference/type-aliases/DeviceOpenOptions.md +0 -46
- package/docs/reference/type-aliases/DevicePort.md +0 -51
- package/docs/reference/type-aliases/DeviceScreen.md +0 -32
- package/docs/reference/type-aliases/DeviceTimeouts.md +0 -39
- package/docs/reference/type-aliases/DockerSpecConfig.md +0 -43
- package/docs/reference/type-aliases/DomMount.md +0 -21
- package/docs/reference/type-aliases/ElementKind.md +0 -27
- package/docs/reference/type-aliases/ElementMatch.md +0 -74
- package/docs/reference/type-aliases/ElementOptions.md +0 -29
- package/docs/reference/type-aliases/ElementRef.md +0 -128
- package/docs/reference/type-aliases/ExecOptions.md +0 -37
- package/docs/reference/type-aliases/FileAccessor.md +0 -54
- package/docs/reference/type-aliases/HonoApp.md +0 -31
- package/docs/reference/type-aliases/HttpContractFilter.md +0 -49
- package/docs/reference/type-aliases/HttpResponseInit.md +0 -46
- package/docs/reference/type-aliases/HttpStreamInit.md +0 -58
- package/docs/reference/type-aliases/IntegrationHandle.md +0 -46
- package/docs/reference/type-aliases/IntegrationSpecification.md +0 -111
- package/docs/reference/type-aliases/IntegrationSpecificationOptions.md +0 -42
- package/docs/reference/type-aliases/Intercept.md +0 -19
- package/docs/reference/type-aliases/InterceptOptions.md +0 -28
- package/docs/reference/type-aliases/InterceptScope.md +0 -11
- package/docs/reference/type-aliases/IsolationStrategy.md +0 -75
- package/docs/reference/type-aliases/JobHandle.md +0 -34
- package/docs/reference/type-aliases/JobsHandle.md +0 -57
- package/docs/reference/type-aliases/JobsResult.md +0 -16
- package/docs/reference/type-aliases/JobsSpecification.md +0 -94
- package/docs/reference/type-aliases/JobsSpecificationOptions.md +0 -56
- package/docs/reference/type-aliases/LandmarkKind.md +0 -20
- package/docs/reference/type-aliases/LiterateRunFlags.md +0 -27
- package/docs/reference/type-aliases/LiterateServeRegistration.md +0 -70
- package/docs/reference/type-aliases/MatchFixtureOptions.md +0 -27
- package/docs/reference/type-aliases/MatchableRequest.md +0 -61
- package/docs/reference/type-aliases/MatcherKind.md +0 -34
- package/docs/reference/type-aliases/MobileBackendOptions.md +0 -28
- package/docs/reference/type-aliases/MobileElementKind.md +0 -14
- package/docs/reference/type-aliases/MobileElementMatch.md +0 -60
- package/docs/reference/type-aliases/MobileElementRef.md +0 -20
- package/docs/reference/type-aliases/MobileHandle.md +0 -65
- package/docs/reference/type-aliases/MobileScenario.md +0 -20
- package/docs/reference/type-aliases/MobileSpecification.md +0 -51
- package/docs/reference/type-aliases/MobileSpecificationOptions.md +0 -126
- package/docs/reference/type-aliases/MobileVisitor.md +0 -81
- package/docs/reference/type-aliases/MockOfOptions.md +0 -26
- package/docs/reference/type-aliases/MockPort.md +0 -10
- package/docs/reference/type-aliases/PinnedClock.md +0 -10
- package/docs/reference/type-aliases/PostgresOptions.md +0 -32
- package/docs/reference/type-aliases/ProcessOptions.md +0 -112
- package/docs/reference/type-aliases/RedisOptions.md +0 -20
- package/docs/reference/type-aliases/RenderSubject.md +0 -12
- package/docs/reference/type-aliases/ScreenNode.md +0 -67
- package/docs/reference/type-aliases/ServerPort.md +0 -36
- package/docs/reference/type-aliases/ServerResponse.md +0 -46
- package/docs/reference/type-aliases/ServerSpec.md +0 -21
- package/docs/reference/type-aliases/ServiceHandle.md +0 -216
- package/docs/reference/type-aliases/ServiceRecord.md +0 -12
- package/docs/reference/type-aliases/SpecDocument.md +0 -84
- package/docs/reference/type-aliases/SpecEnvToken.md +0 -21
- package/docs/reference/type-aliases/SpecFileAssertion.md +0 -27
- package/docs/reference/type-aliases/SpecFixture.md +0 -30
- package/docs/reference/type-aliases/SpecKind.md +0 -8
- package/docs/reference/type-aliases/SpecRun.md +0 -108
- package/docs/reference/type-aliases/SpecServeEntry.md +0 -40
- package/docs/reference/type-aliases/SpecStream.md +0 -32
- package/docs/reference/type-aliases/SpecificationConfig.md +0 -290
- package/docs/reference/type-aliases/SqliteOptions.md +0 -36
- package/docs/reference/type-aliases/SseEvent.md +0 -58
- package/docs/reference/type-aliases/StreamBody.md +0 -61
- package/docs/reference/type-aliases/TextFilter.md +0 -22
- package/docs/reference/type-aliases/VisitScenario.md +0 -20
- package/docs/reference/type-aliases/Visitor.md +0 -215
- package/docs/reference/type-aliases/WaitUntilOptions.md +0 -46
- package/docs/reference/type-aliases/WebsiteBackendOptions.md +0 -37
- package/docs/reference/type-aliases/WebsiteHandle.md +0 -51
- package/docs/reference/type-aliases/WebsiteSpecification.md +0 -118
- package/docs/reference/type-aliases/WebsiteSpecificationOptions.md +0 -40
- package/docs/reference/variables/anthropic.md +0 -19
- package/docs/reference/variables/banner.md +0 -10
- package/docs/reference/variables/button.md +0 -10
- package/docs/reference/variables/clock.md +0 -16
- package/docs/reference/variables/complementary.md +0 -10
- package/docs/reference/variables/component.md +0 -10
- package/docs/reference/variables/content.md +0 -10
- package/docs/reference/variables/contentinfo.md +0 -10
- package/docs/reference/variables/dialog.md +0 -10
- package/docs/reference/variables/field.md +0 -10
- package/docs/reference/variables/form.md +0 -10
- package/docs/reference/variables/heading.md +0 -10
- package/docs/reference/variables/http.md +0 -40
- package/docs/reference/variables/intercept.md +0 -11
- package/docs/reference/variables/link.md +0 -10
- package/docs/reference/variables/listitem.md +0 -10
- package/docs/reference/variables/main.md +0 -10
- package/docs/reference/variables/match.md +0 -8
- package/docs/reference/variables/navigation.md +0 -10
- package/docs/reference/variables/openai.md +0 -21
- package/docs/reference/variables/option.md +0 -17
- package/docs/reference/variables/region.md +0 -10
- package/docs/reference/variables/row.md +0 -10
- package/docs/reference/variables/search.md +0 -10
- package/docs/reference/variables/specification.md +0 -8
- package/docs/reference/variables/status.md +0 -10
- package/docs/reference/variables/table.md +0 -10
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# ADR-001: v9 — conventions enforced on three channels
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-07-17
|
|
5
|
-
|
|
6
|
-
Retroactive record, written 2026-09-04 from the v9 design lock (2026-07-17)
|
|
7
|
-
and the `@jterrazz/test@9.0.0` ship (2026-07-18, after a multi-agent review
|
|
8
|
-
campaign). Moved into this repository 2026-09-06, from the OS wiki where it
|
|
9
|
-
was ADR-003 — this package alone can falsify it, and the normative spec was
|
|
10
|
-
always here.
|
|
11
|
-
|
|
12
|
-
## Context
|
|
13
|
-
|
|
14
|
-
Testing conventions lived in prose and review habits; every consumer repo
|
|
15
|
-
drifted its own way, and partial assertions ("status is 200") hid silent
|
|
16
|
-
failures.
|
|
17
|
-
|
|
18
|
-
## Decision
|
|
19
|
-
|
|
20
|
-
v9 is specification-first: three constructors (`specification.api/jobs/cli`),
|
|
21
|
-
one `{{token}}` grammar across every fixture kind, and golden files (`.http`
|
|
22
|
-
_requests/responses, full-output text snapshots) as the default assertion — a
|
|
23
|
-
partial probe must earn its place as a deliberate scalpel.
|
|
24
|
-
|
|
25
|
-
Crucially, every convention is enforced on one of THREE channels, or
|
|
26
|
-
documents why it cannot be:
|
|
27
|
-
|
|
28
|
-
1. **Static** — oxlint rules living IN this package, so a rule versions with
|
|
29
|
-
the API it describes, wired by `@jterrazz/typescript` through composable
|
|
30
|
-
presets (`compose(node, testing)`).
|
|
31
|
-
2. **Meta-tests** — executed truths: every token matcher tested both ways,
|
|
32
|
-
update-mode fixtures re-verified on the next run.
|
|
33
|
-
3. **Runtime** — strict errors: an outbound request with no matching intercept
|
|
34
|
-
fails the spec.
|
|
35
|
-
|
|
36
|
-
Any newly discovered defect class must, in the same change, produce a rule on
|
|
37
|
-
one of the channels — the package's "rule K".
|
|
38
|
-
|
|
39
|
-
## Consequences
|
|
40
|
-
|
|
41
|
-
- Product specs live under `specs/<facet>/<domain>/`; unit tests are siblings
|
|
42
|
-
of their module. A consumer's own conventions derive from this package,
|
|
43
|
-
except where its doctrine states a more specific shape — the first such case
|
|
44
|
-
is jterrazz-os's `docs/decisions/006-cli-specs-mirror-the-command-tree.md`.
|
|
45
|
-
- Migrations proved the value immediately: strict intercepts caught a real
|
|
46
|
-
production-class bug in a consumer (an undrained handler), and dead test
|
|
47
|
-
layers were deleted by the dead-fixture checker.
|
|
48
|
-
- The docs are code: each rule's normative text lives in its implementation's
|
|
49
|
-
metadata and the catalog is generated — hand-synced convention documents are
|
|
50
|
-
banned by construction.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# ADR-002: the statique channel holds only what upstream does not
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-09-15
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
The statique channel grew by writing a rule for every mechanizable convention,
|
|
9
|
-
without asking whether oxlint already carried one. Four hygiene rules ended up
|
|
10
|
-
restating rules of oxlint's own `vitest` plugin — J1 (`.only`/`.skip`), J3 (an
|
|
11
|
-
assertion per test), J4 (unique literal titles), J5 (a lowercase title).
|
|
12
|
-
|
|
13
|
-
That cost nothing while the plugin was off. `@jterrazz/typescript` v10 turns it
|
|
14
|
-
on over the test globs in every profile, so a consumer composing
|
|
15
|
-
`compose(node, testing)` gets both layers: one violation reported twice, two
|
|
16
|
-
ids to suppress, and two normative sentences that have to be kept in step by
|
|
17
|
-
hand — the drift this package's docs-as-code inversion exists to prevent.
|
|
18
|
-
|
|
19
|
-
## Decision
|
|
20
|
-
|
|
21
|
-
A convention an upstream oxlint rule already enforces belongs to that rule. The
|
|
22
|
-
statique channel holds only the residue: what no loaded plugin carries.
|
|
23
|
-
|
|
24
|
-
Equivalence is proved before a rule is deleted, on this package's own fixtures
|
|
25
|
-
and on both the installed oxlint and the version the preset pins — every
|
|
26
|
-
invalid sample of the rule's test must fire the upstream rule, and every valid
|
|
27
|
-
sample must stay silent. A rule that catches something upstream misses is kept
|
|
28
|
-
and narrowed to that residue.
|
|
29
|
-
|
|
30
|
-
The four were proved equivalent and deleted (`vitest/no-focused-tests` +
|
|
31
|
-
`vitest/no-disabled-tests`, `vitest/expect-expect`, `vitest/no-identical-title`,
|
|
32
|
-
`vitest/prefer-lowercase-title`). J2, the arbitrary-sleep ban, has no upstream
|
|
33
|
-
counterpart and stays.
|
|
34
|
-
|
|
35
|
-
## Consequences
|
|
36
|
-
|
|
37
|
-
- Breaking for consumers: `jterrazz/j1-no-only-skip`,
|
|
38
|
-
`jterrazz/j3-no-expectless-test`, `jterrazz/j4-unique-test-names` and
|
|
39
|
-
`jterrazz/j5-lowercase-title` no longer exist, and a config still naming one
|
|
40
|
-
fails oxlint's unknown-rule check.
|
|
41
|
-
- The hygiene floor now reaches this package only through the base preset. A
|
|
42
|
-
repository that adopts the conventions without `@jterrazz/typescript` wires
|
|
43
|
-
`plugins: ['vitest']` itself — the catalogue chapter says which rules.
|
|
44
|
-
- One behaviour is configuration, not code: `prefer-lowercase-title` flags an
|
|
45
|
-
all-caps first word (`VALID_CATEGORIES`, `HTTP`, `DI`) that J5 exempted, and
|
|
46
|
-
`allowedPrefixes` restores the exemption.
|
|
47
|
-
- The rule of growth changes with it. A new mechanizable defect class (K1) is
|
|
48
|
-
now searched for upstream first, and a rule is written here only where the
|
|
49
|
-
search comes back empty.
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# ADR-003: A rendered component is a facet, on Vitest Browser Mode
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-09-19
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
The estate tested its UI in two dialects at once. A page spec said
|
|
9
|
-
`click(link('Articles'))` against a real Chromium and goldened what the page
|
|
10
|
-
MEANT; beside it, in the same repository, a component test said
|
|
11
|
-
`render / screen / fireEvent / waitFor` against `happy-dom` with a scripted
|
|
12
|
-
`fetch`, and goldened nothing. Same product, same reader, two vocabularies —
|
|
13
|
-
and the second proves the least of the two, because the thing it renders never
|
|
14
|
-
met a browser.
|
|
15
|
-
|
|
16
|
-
The corpus had sanctioned that split. `docs/18-conventions.md` and the agent
|
|
17
|
-
skill both said a component test "needs vitest alone", on the ground that the
|
|
18
|
-
framework is for a SURFACE and a component has none. The reading was wrong in
|
|
19
|
-
one word: a component has no surface it is SERVED through, but it needs
|
|
20
|
-
everything the framework owns — a real browser, a Vite pipeline, a network
|
|
21
|
-
double, a golden engine, an element vocabulary. Rule I2's own message had been
|
|
22
|
-
saying so all along: "a test needing more than its module is a specification".
|
|
23
|
-
|
|
24
|
-
What forced a decision now is that the estate has a UI to migrate (a console's
|
|
25
|
-
42 tests, a browser extension's DOM renderer, a web app's string renderer) and
|
|
26
|
-
every one of them would otherwise be written a third time.
|
|
27
|
-
|
|
28
|
-
## Decision
|
|
29
|
-
|
|
30
|
-
A rendered component is a FACET of `@jterrazz/test`, running in Vitest Browser
|
|
31
|
-
Mode on the `playwright` peer the website facet already drives.
|
|
32
|
-
|
|
33
|
-
It is the facet with **no constructor**. A component starts nothing — no
|
|
34
|
-
server, no database, no binary, no simulator — so there is no handle to
|
|
35
|
-
destructure and no `*.specification.ts` to hold it. The chain is exported
|
|
36
|
-
directly (`component.intercept(…).wrap(…).render(<X />, scenario)`), and what
|
|
37
|
-
every render of a project shares belongs to the PROJECT: `component()` in
|
|
38
|
-
`vitest.config.ts`.
|
|
39
|
-
|
|
40
|
-
Its test file sits **beside its subject**, as a module test does, and the
|
|
41
|
-
suffix states the kind: `<file>.test.ts` is a module, `<file>.test.tsx` is a
|
|
42
|
-
component. `unit()` excludes `.test.tsx`; `component()` collects exactly those.
|
|
43
|
-
|
|
44
|
-
The package keeps **one specifier**. A page cannot load the node entry, so
|
|
45
|
-
`exports["."]` gains a `browser` condition resolving to a second build of the
|
|
46
|
-
same surface, in which every node-only name is a stub that throws where it was
|
|
47
|
-
called. The split is the runtime's, never the facets'.
|
|
48
|
-
|
|
49
|
-
Weighed and rejected:
|
|
50
|
-
|
|
51
|
-
- **A Node-side gallery** — Playwright driven from the test process, one
|
|
52
|
-
browser context per render. Measured at ~15 s against 0.6–1.1 s per file for
|
|
53
|
-
Browser Mode, and it needs an undeclared `vite` to build what it serves.
|
|
54
|
-
- **Playwright Component Testing** — a second runner beside vitest, with its
|
|
55
|
-
own config, its own reporters and its own assertion library. The estate has
|
|
56
|
-
one runner on purpose.
|
|
57
|
-
- **`happy-dom` + Testing Library** — the status quo. Two vocabularies, and the
|
|
58
|
-
cheaper one is the one that proves least.
|
|
59
|
-
- **A second specifier, `@jterrazz/test/browser`** — considered and dropped: it
|
|
60
|
-
makes every test file remember which entry it may import, and needs a rule to
|
|
61
|
-
enforce the memory. One specifier and a condition costs nothing at the call
|
|
62
|
-
site.
|
|
63
|
-
|
|
64
|
-
## Consequences
|
|
65
|
-
|
|
66
|
-
- `happy-dom`, `jsdom` and `@testing-library/*` leave the estate's test
|
|
67
|
-
vocabulary. Rules E5, E5b, F6 and G4 refuse them and name the move; E6
|
|
68
|
-
refuses a hand-rolled `browser:` project, because the provider pin, the
|
|
69
|
-
service worker, the JSX transform and the cold-cache pre-bundling are four
|
|
70
|
-
ways for a run to pass here and fail on the next machine.
|
|
71
|
-
- A component spec and a page spec now read alike: same descriptors, same
|
|
72
|
-
verbs, same W3 ambiguity refusal, same ARIA-tree golden in the same dialect.
|
|
73
|
-
The vocabulary gains what a rendered surface needs and a page lacked —
|
|
74
|
-
`gone`, `focused`, and five role descriptors.
|
|
75
|
-
- A consumer takes on optional peers it did not have (`@vitest/browser-playwright`,
|
|
76
|
-
`vitest-browser-react`, `vite`, `react`), and one hard constraint with them:
|
|
77
|
-
the provider peers vitest on an EXACT version, so the two move in one change.
|
|
78
|
-
- CI pays for a second Chromium project. `sequence.groupOrder` keeps it from
|
|
79
|
-
sharing a slot with the website project on a two-vCPU runner.
|
|
80
|
-
- React Native stays out: Browser Mode does not run it. `.astro` pages stay
|
|
81
|
-
website specs; only islands are components.
|
|
82
|
-
- The package's own suite grows a component tree that is NOT under `_fixtures/`
|
|
83
|
-
— ground is what a spec stands on from a distance, and here the spec stands
|
|
84
|
-
next to it.
|
package/docs/decisions/004-a-module-against-real-services-or-a-golden-is-the-integration-facet.md
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# ADR-004: A module against real services, or against a golden, is the integration facet
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-09-19
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
The fork the corpus drew had two rungs: a module alone, tested beside its code
|
|
9
|
-
with no runner, and the assembled product behind an entry — HTTP, a binary, a
|
|
10
|
-
served page, a screen — specified through `specification.*`. A whole kind of
|
|
11
|
-
test fell between them, and every repository invented its own answer for it.
|
|
12
|
-
|
|
13
|
-
A module that needs a real database is one. signews-api kept a
|
|
14
|
-
global-setup file that built a sqlite template by hand and a project named
|
|
15
|
-
"integrations" running plain vitest, because no constructor covered "this
|
|
16
|
-
repository function, against the real schema". package-broadcast and
|
|
17
|
-
package-analytics did the same with a root tests folder and `vi.mock`.
|
|
18
|
-
|
|
19
|
-
A module whose oracle is a GOLDEN is the other. package-attestation's byte
|
|
20
|
-
contracts and package-intelligence's fifty-three input/output pairs are
|
|
21
|
-
golden-file tests, and both reached for `toMatchSnapshot` — a second golden
|
|
22
|
-
mechanism, with no token grammar, no `{ frozen }`, and no `TEST_UPDATE=1`,
|
|
23
|
-
living beside the one the package owns. Rule D20 could ban the matcher only
|
|
24
|
-
once the tests it serves had somewhere to go.
|
|
25
|
-
|
|
26
|
-
Neither case needed a new idea. Both needed a constructor.
|
|
27
|
-
|
|
28
|
-
Three shapes were weighed and refused:
|
|
29
|
-
|
|
30
|
-
- **Widen `jobs`.** `trigger(name)` takes no input and a job is
|
|
31
|
-
`() => Promise<void>`, so the Given would have to leave the test and live in
|
|
32
|
-
the specification file. A spec whose input is elsewhere is not a spec.
|
|
33
|
-
- **Plain vitest under a folder named for it.** The shape every repository had
|
|
34
|
-
already reached, and the shape the evidence indicts: the services are
|
|
35
|
-
hand-started, nothing resets between tests, and the goldens are somebody's.
|
|
36
|
-
- **`sqlite()` outside a runner.** A second lifecycle path for services — two
|
|
37
|
-
answers to "when does this start and who stops it", which is the defect the
|
|
38
|
-
orchestrator exists to prevent.
|
|
39
|
-
|
|
40
|
-
## Decision
|
|
41
|
-
|
|
42
|
-
`specification.integration({ services?, root? })` is the eighth kind of test
|
|
43
|
-
and the sixth constructor. Its subject is a MODULE; its terminal action is
|
|
44
|
-
`.call((services) => …)`, which hands the started record to the subject so it
|
|
45
|
-
is built with real connection strings; its result is `CallResult`.
|
|
46
|
-
|
|
47
|
-
`CallResult` has two readings and never both: `value` is what the call
|
|
48
|
-
returned — a `TextAccessor` for a string, a `JsonAccessor` for anything else —
|
|
49
|
-
and `error` is what it threw, as text, empty when it returned. Both are the
|
|
50
|
-
package's ordinary accessors, so `toMatch`, the `{{token}}` grammar,
|
|
51
|
-
`{ frozen }` and `TEST_UPDATE=1` reach them with no new mechanism.
|
|
52
|
-
|
|
53
|
-
The setups are the ones every facet already has: `.seed()`, `.intercept()`,
|
|
54
|
-
`.clock()`. Without `services` the constructor starts nothing: that is the
|
|
55
|
-
golden-only half, and it is the whole of what a fifty-three-row table needs —
|
|
56
|
-
one `.call()` inside `test.each`.
|
|
57
|
-
|
|
58
|
-
## Consequences
|
|
59
|
-
|
|
60
|
-
- **A refusal is a reading.** No `try`/`catch` in a spec, and no "it should
|
|
61
|
-
throw" test that passes because nothing threw. A chain says "and it did not
|
|
62
|
-
refuse" with `await expect(result.error).toBeEmpty()`.
|
|
63
|
-
- **D20 gains its destination.** `toMatchSnapshot` can be banned because every
|
|
64
|
-
test it served now has a facet, a folder and a golden engine.
|
|
65
|
-
- **One more folder name is spoken for, and no unowned one is added.**
|
|
66
|
-
`specs/integration/` is a facet folder: singular, like `website/`, and
|
|
67
|
-
holding a `*.specification.ts` at its root. The package renamed its own
|
|
68
|
-
plural folder in the same change. What lived there — probes of the container
|
|
69
|
-
adapters themselves — became integration specs under
|
|
70
|
-
`specs/integration/<seam>/`: an adapter met against a real service IS a
|
|
71
|
-
module against a real service. Folder = constructor holds for the package
|
|
72
|
-
too, so no probe earns a folder under `specs/` that no constructor owns, and
|
|
73
|
-
what a probe cannot reach through the public entry is a module test beside
|
|
74
|
-
its module (rule F3).
|
|
75
|
-
- **An env-gated sub-suite stops being a project.** With `{ include, exclude }`
|
|
76
|
-
on the helper, package-attestation's five projects become `unit()` plus one
|
|
77
|
-
`integration()`.
|
|
78
|
-
- **A door closed.** A module test may not carry a golden (D20) and an
|
|
79
|
-
integration spec may not assert only on doubles: the ladder's rungs are now
|
|
80
|
-
distinguishable by where the test lives, which is what makes both
|
|
81
|
-
mechanizable.
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# ADR-005: The doubles ladder is closed, and a ban an upstream rule can carry is an option, not a rule
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-09-19
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
Two questions had no written answer, and the estate's tests answered them
|
|
9
|
-
differently in every repository.
|
|
10
|
-
|
|
11
|
-
**What may stand in for the real thing?** The measured failure mode is not
|
|
12
|
-
subtle: a survey of the workbench found seven files replacing `fetch` with
|
|
13
|
-
`vi.stubGlobal`, thirteen importing `vitest-mock-extended` directly, sixteen
|
|
14
|
-
calling `vi.mock` on a module, two declaring `msw` themselves, five using
|
|
15
|
-
`toMatchSnapshot`. Every one of them is a substitute chosen because nothing
|
|
16
|
-
said which substitute to reach for first. Agents make this worse rather than
|
|
17
|
-
better — the published measurements put a third of agent-written test commits
|
|
18
|
-
at "adds a mock", and nearly all of those at "mocks everything".
|
|
19
|
-
|
|
20
|
-
**Who owns a ban?** ADR-002 settled that a convention oxlint's own `vitest`
|
|
21
|
-
plugin already enforces belongs to that plugin, and four hygiene rules left the
|
|
22
|
-
`jterrazz/*` channel on that ground. It did not settle the case where the
|
|
23
|
-
upstream rule exists but is inert without OPTIONS —
|
|
24
|
-
`vitest/no-restricted-matchers` bans nothing until it is told which matchers,
|
|
25
|
-
`vitest/no-restricted-vi-methods` until it is told which methods. Those options
|
|
26
|
-
are a convention, and they had nowhere to live.
|
|
27
|
-
|
|
28
|
-
Two shapes were weighed and refused. Writing a `jterrazz/*` rule for each ban
|
|
29
|
-
duplicates an upstream rule that already does the work, which is exactly what
|
|
30
|
-
ADR-002 forbids. Asking `compose()` to MERGE options across fragments is a
|
|
31
|
-
toolchain change with no other caller, and it would make two owners of one
|
|
32
|
-
rule's configuration.
|
|
33
|
-
|
|
34
|
-
## Decision
|
|
35
|
-
|
|
36
|
-
**The ladder is closed and ordered.** An agent takes the first rung that fits:
|
|
37
|
-
|
|
38
|
-
1. **The real thing**, in-process — a pure module, a Hono app handed to
|
|
39
|
-
`server`, a component mounted in a real Chromium.
|
|
40
|
-
2. **A declared service** — `sqlite()`, `postgres()`, `redis()`, `process()`:
|
|
41
|
-
real, isolated per worker, reset per chain.
|
|
42
|
-
3. **A contract** — `.intercept()` on a chain, `intercept()` in module scope;
|
|
43
|
-
msw's server, msw's worker, or the `node:http` stub, all over one queue;
|
|
44
|
-
strict from the first contract.
|
|
45
|
-
4. **A typed port double** — `mockOf<Port>()`, or `vi.fn<Fn>()` for a
|
|
46
|
-
function-shaped dependency.
|
|
47
|
-
|
|
48
|
-
Nothing else is a rung. `vi.mock`, `vi.stubGlobal`, a raw `msw` import, `nock`,
|
|
49
|
-
`sinon`, `jest` and `mockdate` are not lower rungs; they are off the ladder,
|
|
50
|
-
and each has a named destination.
|
|
51
|
-
|
|
52
|
-
**A ban an upstream vitest rule can carry as an OPTION is set from the
|
|
53
|
-
`testing` fragment**, and the rulebook marks that rule `covered` so one owner
|
|
54
|
-
states it. A ban a CORE rule would carry — `no-restricted-imports`,
|
|
55
|
-
`no-restricted-globals` — stays a `jterrazz/*` rule, because an oxlint override
|
|
56
|
-
REPLACES a rule's options rather than merging them, and three toolchain owners
|
|
57
|
-
already set those two.
|
|
58
|
-
|
|
59
|
-
This extends ADR-002: the option mechanism is this record's, the principle it
|
|
60
|
-
serves is that one.
|
|
61
|
-
|
|
62
|
-
## Consequences
|
|
63
|
-
|
|
64
|
-
- **The ladder is citable.** "Use a contract, not a stubbed `fetch`" is a rung
|
|
65
|
-
number, not an opinion, and each ban's message names the rung above it.
|
|
66
|
-
- **`mockOf` earns its place on rung four.** It pins
|
|
67
|
-
`vitest-mock-extended`'s range on the consumer's behalf, which is why the
|
|
68
|
-
consumer is forbidden to declare it. Its `{ deep: false }` form exists so
|
|
69
|
-
rung four does not push a test back down to a hand-written object.
|
|
70
|
-
- **A mandatory type argument is not expressible.** `mockOf<T extends object>()`
|
|
71
|
-
has no default, but TypeScript falls back to the CONSTRAINT where no
|
|
72
|
-
inference site says otherwise, so `mockOf()` compiles and answers for
|
|
73
|
-
`object`. The refusal lands where the double is used — it is assignable to
|
|
74
|
-
no port — rather than where it was made. Stated rather than worked around: a
|
|
75
|
-
cast or a never-typed overload would buy the earlier error with a worse
|
|
76
|
-
signature.
|
|
77
|
-
- **Three bans move upstream.** `no-restricted-matchers` (the snapshot
|
|
78
|
-
matchers), `no-restricted-vi-methods` (`stubGlobal`, the timer methods) and
|
|
79
|
-
`max-nested-describe` are configured, not reimplemented. They turn on in the
|
|
80
|
-
toolchain release that follows the package's next major.
|
|
81
|
-
- **`vi.mock` keeps one door.** A native module a consumer cannot inject is
|
|
82
|
-
allow-listed per specifier, with a reason, and the allow-list is the
|
|
83
|
-
repository's — not a silent exception.
|
|
84
|
-
- **A cost accepted.** Two channels now state bans: the fragment's options and
|
|
85
|
-
the `jterrazz/*` rules. The catalogue carries both, with `upstream` as a
|
|
86
|
-
channel value, so a reader still finds one list.
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
# ADR-006: The catalogue reaches a file by its role, states its reach, and is born on a count
|
|
2
|
-
|
|
3
|
-
**Status:** Accepted
|
|
4
|
-
**Date:** 2026-09-20
|
|
5
|
-
|
|
6
|
-
## Context
|
|
7
|
-
|
|
8
|
-
The catalogue of 15.x held sixty-odd rows and could not answer three questions
|
|
9
|
-
a reader asks of any one of them: which files does this reach, what do I do
|
|
10
|
-
about it, and what proves it is true.
|
|
11
|
-
|
|
12
|
-
**Reach was a path segment.** Five rules gated on `parts.includes('specs')` or
|
|
13
|
-
`includes('src')` — I2, I4, J2, d12w, d15w — and each of them drew the line in
|
|
14
|
-
a slightly different place. The consequences were not theoretical: a sleep in a
|
|
15
|
-
module test beside `src/` was invisible to J2, while the same sleep two folders
|
|
16
|
-
away failed a build; a repository's consistency suite was an "orphan module
|
|
17
|
-
test" to I2 because it sat under a folder called `specs`. The gate was also
|
|
18
|
-
unreadable: nothing in a row said which files it judged, so the only way to
|
|
19
|
-
find out was to read the implementation.
|
|
20
|
-
|
|
21
|
-
**A row could not say what to do.** A ban with no destination is an argument
|
|
22
|
-
rather than a rule, and forty-odd messages ended on `see docs/19-linting.md`
|
|
23
|
-
with no fragment — a route to a chapter, not to a row. Nothing failed when a
|
|
24
|
-
heading moved, so the routes rotted silently.
|
|
25
|
-
|
|
26
|
-
**Nothing said which pass a finding came from.** The manifest's `channel` field
|
|
27
|
-
was a union a row could name loosely, and three of the seven values (`type`,
|
|
28
|
-
`meta`, `upstream`) had no rows at all: the conventions they stood for were
|
|
29
|
-
held by tests nobody could find from the catalogue, or by nothing.
|
|
30
|
-
|
|
31
|
-
**And a row could be born out of nothing.** The A-family's `allowedPrefixes`
|
|
32
|
-
story is the warning: a rule shipped at `error` on a shape no consumer had ever
|
|
33
|
-
been run against, and every consumer paid for it.
|
|
34
|
-
|
|
35
|
-
## Decision
|
|
36
|
-
|
|
37
|
-
### One gate, by role
|
|
38
|
-
|
|
39
|
-
**One gate, by ROLE.** `roleOf(file)` returns `{ role, inSpecs, legacyDir }`,
|
|
40
|
-
and the role is read from the SUFFIX: `.specification.ts(x)`, `.spec.yaml`,
|
|
41
|
-
`.spec.ts`, `.test.tsx`, `.test.ts`, `vitest.config.*`, a ground ancestor, a
|
|
42
|
-
`contracts/` ancestor. A statique rule reads those three fields and, where it
|
|
43
|
-
must know where the file sits, the ONE package-bounded anchor every pass shares
|
|
44
|
-
(`specsAnchor` in `src/lint/ast.ts`) — never a bare path segment. The rules
|
|
45
|
-
that need it say so: C1, C4, C8, C13, F2, F3, I1, I4. Walking a TREE is the
|
|
46
|
-
checker's — C1's depth, C12, C18, C20, C21w.
|
|
47
|
-
|
|
48
|
-
### A row says what it reaches, and what to do
|
|
49
|
-
|
|
50
|
-
**Every row states its REACH and its FIX**, both required by the type, and the
|
|
51
|
-
fix is one imperative line the message carries too.
|
|
52
|
-
|
|
53
|
-
### Seven channels, each answering for its rows
|
|
54
|
-
|
|
55
|
-
**Seven channels, one per row** — `statique`, `upstream`, `checker`, `runtime`,
|
|
56
|
-
`type`, `meta`, `process` — and each channel answers for its rows the way that
|
|
57
|
-
channel can: a rule file and a fixture pair, an assertion on the resolved
|
|
58
|
-
option, a bundled pass, a `// RUNTIME <ID>` marker above the spec that drives
|
|
59
|
-
the refusal, an `@ts-expect-error` in `src/type-channel.test-d.ts`, a named
|
|
60
|
-
meta-test. One meta-test holds that contract for all seven.
|
|
61
|
-
|
|
62
|
-
**English, and anchored.** Every sentence the catalogue publishes is English
|
|
63
|
-
(K5 holds the line with a deny-list of the tokens the manifest actually
|
|
64
|
-
carried), and every message the PLUGIN ships ends with a generated
|
|
65
|
-
`(<ID> — <chapter>#<rule>)` tail whose anchor is asserted to exist (K3). A
|
|
66
|
-
checker finding carries its id and its chapter; several of its passes report
|
|
67
|
-
under a family code (`d4`, `d4b`, `d10w`) rather than a row name, so the tail
|
|
68
|
-
routes to the chapter and the id says which row.
|
|
69
|
-
|
|
70
|
-
### A row is born on a count
|
|
71
|
-
|
|
72
|
-
**A row is born on a COUNT.** A rule is written when its defect class has been
|
|
73
|
-
seen once and its criterion is decidable. A class nobody has seen is a backlog
|
|
74
|
-
line with its criterion written, coded on its first occurrence. The R8 dry run
|
|
75
|
-
— the whole catalogue run over every clone of the workbench, read-only — is
|
|
76
|
-
what settles which of the two a row is, and it is re-run whenever a criterion
|
|
77
|
-
changes. The counts below are the run of 2026-09-20, re-run after the fix pass
|
|
78
|
-
that bounded six false classes: 27 clones plus the estate's own `apps`,
|
|
79
|
-
`packages` and `specs`, with each package's own violation FIXTURES excluded —
|
|
80
|
-
they violate on purpose, and counting them would let a rule justify itself.
|
|
81
|
-
`jterrazz-web-astro-react` and `signews-web-astro` are not repositories: they
|
|
82
|
-
are clones of `jterrazz-web` and `signews-web` checked out on a merged
|
|
83
|
-
experiment branch, counted here as the folders the run walked.
|
|
84
|
-
|
|
85
|
-
| rule | total | where |
|
|
86
|
-
| ----------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
87
|
-
| `b4-given-then` | 2569 | jterrazz-design 902, signews-mobile 532, archive 419, hoverfly-lsp 246, extensions 216, package-attestation 144, spwn 104, package-typescript 4, package-test 2 |
|
|
88
|
-
| `b11-marker-one-line` | 240 | package-test 160, signews-api 40, hoverfly-lsp 13, jterrazz-web-astro-react 5, jterrazz-web 5, archive 4, package-typescript 4, spwn 4, jterrazz-studio 3, jterrazz-os 2 |
|
|
89
|
-
| `i2-sibling-test-naming` | 224 | archive 169, signews-mobile 35, hoverfly-lsp 15, package-typescript 2, jterrazz-design 1, package-test 1, spwn 1 |
|
|
90
|
-
| `c12-spec-file-name` | 180 | spwn 40, package-test 37, jterrazz-web 22, jterrazz-web-astro-react 21, signews-api 15, package-typescript 9, signews-mobile 8, jterrazz-os 6, package-attestation 6, package-intelligence 3, signews-web 3, jterrazz-design 2, jterrazz-studio 2, spwn-web 2, cap01 1, package-analytics 1, package-broadcast 1, signews-web-astro 1 |
|
|
91
|
-
| `j6w-given-in-the-test` | 165 | archive 54, package-test 41, signews-api 19, package-typescript 17, hoverfly-lsp 14, jterrazz-os 6, spwn 6, package-telemetry 4, signews-mobile 2, package-analytics 1, package-intelligence 1 |
|
|
92
|
-
| `d16w-ambient-value` | 57 | signews-api 36, package-test 10, archive 6, hoverfly-lsp 2, jterrazz-os 2, signews-mobile 1 |
|
|
93
|
-
| `e9w-env-assignment-in-test` | 49 | package-test 47, jterrazz-os 2 |
|
|
94
|
-
| `d18w-existence-only-oracle` | 37 | package-test 14, hoverfly-lsp 10, archive 4, package-intelligence 2, signews-mobile 2, jterrazz-os 1, jterrazz-web-astro-react 1, jterrazz-web 1, package-typescript 1, signews-api 1 |
|
|
95
|
-
| `c1-domain-structure` | 33 | jterrazz-os 26, package-typescript 7 |
|
|
96
|
-
| `c18-module-test-under-facet` | 31 | package-typescript 27, jterrazz-web 2, spwn 2 |
|
|
97
|
-
| `i4-no-module-doubles` | 23 | signews-mobile 13, archive 5, package-intelligence 2, jterrazz-web 1, package-typescript 1, signews-api 1 |
|
|
98
|
-
| `d19w-probe-cluster` | 22 | package-typescript 7, spwn 6, jterrazz-os 3, jterrazz-web 3, archive 2, jterrazz-web-astro-react 1 |
|
|
99
|
-
| `f2-no-test-imports-in-prod` | 21 | package-test 13, jterrazz-design 3, archive 2, package-manifest 2, hoverfly-lsp 1 |
|
|
100
|
-
| `e3-config-present` | 17 | archive 16, extensions 1 |
|
|
101
|
-
| `d12w-response-body-probe` | 14 | signews-api 9, archive 5 |
|
|
102
|
-
| `d15w-status-only-probe` | 14 | package-test 4, archive 3, jterrazz-os 3, jterrazz-web-astro-react 2, jterrazz-web 1, signews-api 1 |
|
|
103
|
-
| `d5w-spec-pinned-value` | 10 | jterrazz-os 9, package-test 1 |
|
|
104
|
-
| `d8w-text-bypass` | 9 | jterrazz-web-astro-react 3, jterrazz-web 3, archive 2, spwn 1 |
|
|
105
|
-
| `c9-dead-fixtures` | 8 | package-test 7, spwn 1 |
|
|
106
|
-
| `d17w-double-only-oracle` | 8 | signews-api 4, signews-mobile 4 |
|
|
107
|
-
| `j2-no-sleep` | 8 | package-test 3, archive 2, jterrazz-os 1, signews-mobile 1, spwn 1 |
|
|
108
|
-
| `w5w-scenario-settles` | 8 | package-test 4, cap01 1, jterrazz-web-astro-react 1, jterrazz-web 1, signews-mobile 1 |
|
|
109
|
-
| `a1-specification-file` | 7 | package-test 7 |
|
|
110
|
-
| `e2-preset-config` | 6 | package-test 3, spwn 2, archive 1 |
|
|
111
|
-
| `c21w-ground-owned-by-one` | 5 | spwn 2, jterrazz-web-astro-react 1, package-attestation 1, signews-api 1 |
|
|
112
|
-
| `d5-spec-volatile-literal` | 3 | package-test 3 |
|
|
113
|
-
| `e7w-include-prefix-exists` | 3 | spwn 2, package-test 1 |
|
|
114
|
-
| `f5-fixtures-only-from-tests` | 3 | jterrazz-design 3 |
|
|
115
|
-
| `f8-no-seam-dependency` | 3 | archive 1, jterrazz-design 1, spwn 1 |
|
|
116
|
-
| `b10-when-between-markers` | 2 | archive 1, spwn 1 |
|
|
117
|
-
| `e4w-project-binding` | 1 | package-test 1 |
|
|
118
|
-
| `f6-no-foreign-test-runtime` | 1 | signews-web 1 |
|
|
119
|
-
|
|
120
|
-
Four rows were at zero with no new surface to be the boundary of, and the gate
|
|
121
|
-
moved them to the backlog with their criteria written: **B12** (a marker inside
|
|
122
|
-
a declarator chain), **C19** (backend ground under a screen facet — the
|
|
123
|
-
component facet that was its reason stopped being a folder when component tests
|
|
124
|
-
became colocated), **D21w** (a volatile literal in a golden: 108 findings, every
|
|
125
|
-
one a publication date the PRODUCT pins rather than a value a run minted; once
|
|
126
|
-
the criterion excludes midnight UTC, which a clock read never is, it falls to
|
|
127
|
-
zero) and **D22w**. Three rows ship at zero as the boundary of a surface born
|
|
128
|
-
with them: **W2** (the escape hatch nobody uses yet), **E8** (the literate door
|
|
129
|
-
the `cli()` helper now defaults) and **C20** (folder = constructor, which the
|
|
130
|
-
`integration` facet of 15.3 is the first new folder to answer to).
|
|
131
|
-
|
|
132
|
-
Two rows ship at zero for a reason the re-run wrote itself. **D16** is the
|
|
133
|
-
error half of a class d16w counts 57 times: the one occurrence the first run
|
|
134
|
-
found was a test that PINS its clock and then reads it, which is what the rule
|
|
135
|
-
tells an author to do — so the exemption that made it disappear is the rule
|
|
136
|
-
working. **J9** has no occurrence because the toolchain's suppression gate
|
|
137
|
-
reads `oxlint-disable*` and nothing else: the checker's own directive has never
|
|
138
|
-
been held by anything, and the 16 of them on the workbench were written under
|
|
139
|
-
no obligation to say why.
|
|
140
|
-
|
|
141
|
-
Six false classes the re-run bounded, each of which had made a row look larger
|
|
142
|
-
than it is: C18 read a spec importing `../x.specification` (no extension) as
|
|
143
|
-
reaching no runner — 13 of its 44; C12 and C18 both claimed the same file, and
|
|
144
|
-
`--fix` performed the wrong one; C21w counted a golden named through a template
|
|
145
|
-
as no reader at all; W5w read a `db.select()` as a visitor's action and every
|
|
146
|
-
component test as a screen scenario — 13 of its 26 were the estate's console;
|
|
147
|
-
D18w called a precise negative (`not.toHaveBeenCalled()`) an existence check;
|
|
148
|
-
D19w called three reads of one `value` a cluster.
|
|
149
|
-
|
|
150
|
-
The chapters are renumbered ONCE, in the same release, so a link repointed by
|
|
151
|
-
this change is repointed for good. The map it lands on runs the fork's own
|
|
152
|
-
order: the spine, then the kinds of test from the one with no runner to the one
|
|
153
|
-
that drives a simulator, then the shared references every kind links into, then
|
|
154
|
-
the enforcement. Two chapters are BORN by it — 05, the majority kind that had no
|
|
155
|
-
page, and 13, the element vocabulary two facet chapters were each holding half
|
|
156
|
-
of — and every kind chapter is rewritten on one seven-section skeleton.
|
|
157
|
-
|
|
158
|
-
| Old | New | Chapter |
|
|
159
|
-
| --- | --- | ----------------------------------------- |
|
|
160
|
-
| 01 | 01 | Architecture |
|
|
161
|
-
| 02 | 02 | Developing |
|
|
162
|
-
| 03 | 03 | Testing |
|
|
163
|
-
| 04 | 04 | Operating |
|
|
164
|
-
| — | 05 | Module tests (new) |
|
|
165
|
-
| 17 | 06 | Integration specs |
|
|
166
|
-
| 16 | 07 | Component specs |
|
|
167
|
-
| 14 | 08 | Website specs |
|
|
168
|
-
| 15 | 09 | Mobile specs |
|
|
169
|
-
| 05 | 10 | API specs |
|
|
170
|
-
| 06 | 11 | Jobs specs |
|
|
171
|
-
| 07 | 12 | CLI specs |
|
|
172
|
-
| — | 13 | Elements (new) |
|
|
173
|
-
| 08 | 14 | Assertions |
|
|
174
|
-
| 09 | 15 | Tokens (+ update mode end to end) |
|
|
175
|
-
| 10 | 16 | Contracts (+ `intercept()`) |
|
|
176
|
-
| 11 | 17 | Services |
|
|
177
|
-
| 12 | 18 | Conventions |
|
|
178
|
-
| 13 | 19 | Linting (carries the generated catalogue) |
|
|
179
|
-
|
|
180
|
-
A rule message anchored at `docs/13-linting.md#<name>` now reads
|
|
181
|
-
`docs/19-linting.md#<name>`; K3 holds that every one of them resolves, so a
|
|
182
|
-
renumbering that missed a message fails the suite rather than a reader.
|
|
183
|
-
|
|
184
|
-
## What the proof holds, and what it does not
|
|
185
|
-
|
|
186
|
-
The release proof of this wave reads: the package's own tree green under
|
|
187
|
-
`typescript check`, the `unit` project inside the budget
|
|
188
|
-
[03 — Testing](../03-testing.md) states, the
|
|
189
|
-
catalogue's own meta-tests holding freshness, completeness, reach and channel,
|
|
190
|
-
and the R8 counts above re-derivable from the branch head. All of it holds.
|
|
191
|
-
|
|
192
|
-
**Suppressions are the one stated exception**, and it has two halves, both
|
|
193
|
-
counted. The proof as written asked for zero directives added to this package's
|
|
194
|
-
own tree: `src/` and `specs/` carry 66 `oxlint-disable` outside fixtures and
|
|
195
|
-
goldens where `main` carried 51, so the wave adds 15. They are three shapes,
|
|
196
|
-
and none of them is debt: a test whose SUBJECT is the primitive the rule bans —
|
|
197
|
-
the clock seam, `waitUntil`, the adapter deadlines, the marker rule's own
|
|
198
|
-
one-line fixture; a negative spec whose violation IS the behaviour under test;
|
|
199
|
-
and one skipped spec, the repro of the seam defect chapter 16 names, which
|
|
200
|
-
leaves the day the seam answers. A rule cannot exempt the test that proves it
|
|
201
|
-
without exempting the class it guards, so the directive carries the reason
|
|
202
|
-
instead.
|
|
203
|
-
|
|
204
|
-
The second half is the RATCHET, and it is debt rather than exemption: the wave
|
|
205
|
-
absorbs 107 findings of this package's own rules into `oxlint.baseline.json` —
|
|
206
|
-
`e9w` 39, `j6w` 37, `d18w` 14, `d16w` 10, `w5w` 4, `d15w` 3, beside the single
|
|
207
|
-
`i1` line `main` already carried. A ratchet key names a convention, never a
|
|
208
|
-
pass, so those are 107 lines a reader can spend one convention at a time, and
|
|
209
|
-
the baseline may only fall.
|
|
210
|
-
|
|
211
|
-
Both numbers are written here so the next release holds itself to them: 66
|
|
212
|
-
directives and 107 absorbed findings, and a rise in either asks for the same
|
|
213
|
-
reading.
|
|
214
|
-
|
|
215
|
-
**Not done in this cut**, deliberately, each with the reason:
|
|
216
|
-
|
|
217
|
-
- **The website and mobile duplicates**, and **the eight hand-written skill
|
|
218
|
-
references**, were both deferred from the catalogue cut to the renumbering
|
|
219
|
-
that follows it in the same release: the vocabulary had no page to move to
|
|
220
|
-
until chapter 13 existed, and the references had no generated card to be
|
|
221
|
-
replaced by. Both landed with it — 13 owns the vocabulary, and
|
|
222
|
-
`references/<kind>.md` is generated from the facet matrix.
|
|
223
|
-
- **`response.body.cancel()`.** A seam defect, not a catalogue one: chapter 16
|
|
224
|
-
states it and M3's row names the one suppression it sanctions, with the repro
|
|
225
|
-
skipped beside the other intercept specs.
|
|
226
|
-
- **W4 stays a runtime row** rather than a type one, for the reason written in
|
|
227
|
-
`src/type-channel.test-d.ts`.
|
|
228
|
-
- **The three statuses.** ADR-006, 007 and 008 are `Proposed`; only the owner
|
|
229
|
-
writes `Accepted`, in the commit that cuts the version.
|
|
230
|
-
|
|
231
|
-
## Consequences
|
|
232
|
-
|
|
233
|
-
- A reader deciding whether a rule applies to the file in front of them reads
|
|
234
|
-
the row, never the implementation; a rule that wants a different reach must
|
|
235
|
-
change `roleOf`, where every rule sees it at once.
|
|
236
|
-
- The three channels that were empty carry rows, and a row of any channel that
|
|
237
|
-
loses its proof fails a meta-test rather than going quietly stale.
|
|
238
|
-
- The gate costs rules: four written, tested and fixtured rows went to the
|
|
239
|
-
backlog on the strength of the dry run. That is the price of the criterion,
|
|
240
|
-
and the criterion is the reason a consumer can trust a new `error`.
|
|
241
|
-
- A count is evidence of a CLASS, not a migration estimate: `b4-given-then` at
|
|
242
|
-
2575 is narration debt that is already baselined everywhere, and no row's
|
|
243
|
-
tier is decided by how expensive it would be to fix.
|
|
244
|
-
- Every consumer's first 16.0 run is a baseline update. The counts above are
|
|
245
|
-
what that update will hold.
|