@am_shork/attest 0.2.0 → 0.2.1
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 +178 -13
- package/README.md +15 -2
- package/dist/core/registry.d.ts +51 -2
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +3 -0
- package/dist/core/registry.js.map +1 -1
- package/dist/core/validator.d.ts +3 -0
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +26 -0
- package/dist/core/validator.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,127 @@ not API.
|
|
|
15
15
|
|
|
16
16
|
## [Unreleased]
|
|
17
17
|
|
|
18
|
+
### Under consideration
|
|
19
|
+
|
|
20
|
+
Queued from the skills-manager adoption report (0.2.0, 41 requirements / 106
|
|
21
|
+
scenarios, plain-TS). **Nothing below is built.** An entry here is a decision to
|
|
22
|
+
ship, not a claim that it ships; each moves into `Added` / `Changed` / `Fixed`
|
|
23
|
+
when it does, and this heading is deliberately not one of those, so no reader
|
|
24
|
+
can take the section for a release note. The report's other proposals were
|
|
25
|
+
declined and are not recorded.
|
|
26
|
+
|
|
27
|
+
- **A report of N issues sharing one `code` should say so once.** The 0.1.1 →
|
|
28
|
+
0.2.0 upgrade printed six `registry-not-static` ERRORs in a row — one per
|
|
29
|
+
registry file, every one caused by the same prose written as `'…' + '…'` — and
|
|
30
|
+
left the reader to work out that they were one cause and one mechanical fix.
|
|
31
|
+
A summary line will name the shared cause when a code repeats; the per-file
|
|
32
|
+
lines stay exactly as they are, because they are what makes a diagnostic
|
|
33
|
+
clickable. Human output only — a summary that became an `Issue` would carry a
|
|
34
|
+
`code` into `--json`, `summary` and `hasError`, which is a report-contract
|
|
35
|
+
change and not what this is.
|
|
36
|
+
|
|
37
|
+
## [0.2.1] - 2026-07-26
|
|
38
|
+
|
|
39
|
+
The type layer stopped charging for the one behaviour the tool rewards, and
|
|
40
|
+
three limits an adoption had to find on its own are now written down.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **Reading a param cost a cast, and the cast was charged on the one behaviour
|
|
45
|
+
the tool rewards.** `defineRequirements` returned `Registry`, so every param
|
|
46
|
+
was the full `string | number | boolean | Array<…>` union and
|
|
47
|
+
`reqs[id].params.x` had to be converged at each read site — the reporting
|
|
48
|
+
adopter wrote `str()` / `strList()` helpers to do it. `possible-drift` goes
|
|
49
|
+
quiet precisely when a scenario reads `.params`, so the type layer was taxing
|
|
50
|
+
the behaviour the anti-drift heuristic exists to reward. It is now generic
|
|
51
|
+
over its argument with a `const` type parameter: `params.idleTimeoutMin` is
|
|
52
|
+
`30`, `params.vendorDirs` is an array of the strings written there, and a
|
|
53
|
+
declared ID is known to exist, so `reqs['AUTH-3']` needs no `!` under
|
|
54
|
+
`noUncheckedIndexedAccess`. Removing the casts from Attest's own `self/`
|
|
55
|
+
specs closed 21 latent type errors there. No runtime behaviour and no `--json`
|
|
56
|
+
change: since 0.2.0 the analysing commands read the registry from the AST, so
|
|
57
|
+
this type has no bearing on anything the engine sees.
|
|
58
|
+
**A widening, deliberately.** A `const` type parameter would infer array
|
|
59
|
+
literals as tuples — `readonly` ones under a constraint that admits them —
|
|
60
|
+
and neither is assignable to the mutable `Array<number | string | boolean>`
|
|
61
|
+
the schema parses to, which would have broken `const reqs: Registry =
|
|
62
|
+
defineRequirements({…})` and every `const xs: string[] = req.params.foo`; the
|
|
63
|
+
mapped type collapses them back to `E[]`. The result is still intersected with
|
|
64
|
+
`Registry`, so its index signature survives and `reqs[id]` with an `id: string`
|
|
65
|
+
— a shared test helper — still resolves, as does a param the registry does not
|
|
66
|
+
declare. **What that costs**, against the intent recorded when this was queued:
|
|
67
|
+
a mistyped literal `reqs['TYPO-9']` is *not* rejected outright. Rejecting an
|
|
68
|
+
unknown key and accepting a `string` one are the same question asked of one
|
|
69
|
+
index signature, and it cannot answer both ways; the fallback is what keeps
|
|
70
|
+
this non-breaking, so it wins. The weaker half is real — an unknown ID misses
|
|
71
|
+
the declared keys and resolves through the index signature, so under
|
|
72
|
+
`noUncheckedIndexedAccess` reading through it is an error where `reqs['AUTH-3']`
|
|
73
|
+
no longer is — and a wrong ID is an `unknown-req-id` ERROR from `check`
|
|
74
|
+
regardless, which reads registry and specs together. The type layer is the
|
|
75
|
+
second reader here, not the only one.
|
|
76
|
+
- **Three things an adoption had to discover for itself.** Documentation only —
|
|
77
|
+
no behaviour changed, and each is a property the design deliberately has.
|
|
78
|
+
**`check` has no detection power over a params change**: editing a value
|
|
79
|
+
(`'main'` → `'trunk'`, an entry dropped from a nine-element list) leaves it at
|
|
80
|
+
`✓ No issues`, because `check` executes nothing and nothing became unbound or
|
|
81
|
+
uncovered. The single source makes the value impossible to *diverge*, which is
|
|
82
|
+
a different and stronger claim than announcing that it *moved* — but "params
|
|
83
|
+
are the single source for values that change" reads easily as "`check` guards
|
|
84
|
+
them", and what actually guards them is a scenario asserting on the value it
|
|
85
|
+
read. Now stated where params are introduced (README, design §2, the prompt
|
|
86
|
+
guide) and recorded as a limit in design §11, next to the others.
|
|
87
|
+
**`verify` does not read your `vitest.config.ts`**: the child run starts
|
|
88
|
+
isolated, so a verdict never depends on ambient configuration — which also
|
|
89
|
+
means framework code gets no transforms, no DOM and no aliases until
|
|
90
|
+
`--vitest-config` points it at one. The flag was documented in the README; the
|
|
91
|
+
trade-off behind it now sits in design §5.4, where the run scope is described,
|
|
92
|
+
because that is where a reader meets the isolation.
|
|
93
|
+
**A template literal keeps its whitespace**: one with no substitution reads
|
|
94
|
+
statically and is accepted, but preserves every newline and space of
|
|
95
|
+
indentation, and `render` copies the statement into the Markdown as written —
|
|
96
|
+
so editor-friendly wrapping lands in the generated document. This is the
|
|
97
|
+
reason registry prose is written as one long single-line string, which was
|
|
98
|
+
folklore until now.
|
|
99
|
+
- **A codemod for the 0.2.0 `registry-not-static` migration.** Collapsing
|
|
100
|
+
multi-line `'…' + '…'` prose into one literal is mechanical and was done by
|
|
101
|
+
hand across 21 requirements in the first reported adoption. The 0.2.0 entry
|
|
102
|
+
now carries a compiler-API script that does it, tested on the shapes that make
|
|
103
|
+
it awkward: mixed quote styles, an apostrophe inside the prose, a template
|
|
104
|
+
literal in the chain, and a numeric `1 + 2` it must leave alone.
|
|
105
|
+
- **Type tests, and a suite that runs them.** The repo had none, and this change
|
|
106
|
+
is entirely type-level: no runtime test and no `verify self` run could observe
|
|
107
|
+
a regression in it. `tests/registry-types.spec-d.ts` pins the narrowing, both
|
|
108
|
+
compatibility promises and the trade-off above; `vitest run` now typechecks in
|
|
109
|
+
the same pass (`tsconfig.typecheck.json`, which unlike the build project covers
|
|
110
|
+
`tests/` and `self/` — neither had ever been through a compiler). `DefinedRegistry`
|
|
111
|
+
is exported for consumers that need to name the type.
|
|
112
|
+
|
|
113
|
+
- **A `{placeholder}` in a `rationale` reached the document unread.** `render`
|
|
114
|
+
interpolates `statement` and nothing else, and `unbound-param` only scans
|
|
115
|
+
statements, so braces written into a rationale passed through every check and
|
|
116
|
+
landed verbatim in the generated Markdown. The mistyped placeholder is the
|
|
117
|
+
obvious case; the one that misleads is the **correctly spelled** one, where
|
|
118
|
+
the author declared the param and simply picked the wrong field — nothing was
|
|
119
|
+
unbound, so nothing fired, and the document reviewers and audit read showed a
|
|
120
|
+
placeholder where a value was meant. A new `rationale-placeholder` WARNING now
|
|
121
|
+
reports any `{name}` in a rationale, bound or not.
|
|
122
|
+
Deliberately not the two alternatives. Extending `unbound-param` to rationales
|
|
123
|
+
would cover only the undeclared half — the half that misleads least. And
|
|
124
|
+
making `render` interpolate rationales would change the bytes of every
|
|
125
|
+
committed rendering, turning `render --check` red on an upgrade where the user
|
|
126
|
+
moved no intent, which this file already treats as breaking for that surface.
|
|
127
|
+
**A placeholder inside a Markdown code span is not reported.** That exclusion
|
|
128
|
+
came from dogfooding: the first run against Attest's own registry flagged
|
|
129
|
+
ATX-14, whose rationale explains that `` `{toString}` `` *looks* bound — prose
|
|
130
|
+
about a placeholder, not a misfiled one, and the only way to write a
|
|
131
|
+
requirement whose subject is the syntax itself. A rationale is Markdown and
|
|
132
|
+
`render` leaves a code span exactly as written, so a backticked token is
|
|
133
|
+
already marked as quoted.
|
|
134
|
+
WARNING sits below the `hasError` predicate that `ok`, `--json` and the exit
|
|
135
|
+
code all read from, so an existing green registry with braces in a rationale
|
|
136
|
+
gains a line of output and keeps its verdict. A new `code` on the existing
|
|
137
|
+
`Issue` shape is additive: `schemaVersion` stays `1`.
|
|
138
|
+
|
|
18
139
|
## [0.2.0] - 2026-07-26
|
|
19
140
|
|
|
20
141
|
Three things that could each end a run with the wrong verdict: a registry read
|
|
@@ -63,6 +184,47 @@ never pointed at.
|
|
|
63
184
|
A registry file may still be written as `const reqs = defineRequirements({…});
|
|
64
185
|
export default reqs;`, and may import `defineRequirements` under any alias or
|
|
65
186
|
through a namespace.
|
|
187
|
+
**Migrating concatenated prose.** The common shape is a statement or rationale
|
|
188
|
+
wrapped across lines as `'…' + '…'`, which is a computation and so no longer
|
|
189
|
+
reads. Collapsing it is purely mechanical — 21 requirements by hand in the
|
|
190
|
+
first reported adoption — so it is worth a codemod. Save this at the project
|
|
191
|
+
root and run it over the registry files; it rewrites only concatenations whose
|
|
192
|
+
every operand is a string (or substitution-free template) literal, leaving
|
|
193
|
+
`1 + 2` and anything with an identifier in it alone:
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
// flatten-reqs.mjs — node flatten-reqs.mjs requirements/*.reqs.ts
|
|
197
|
+
import ts from 'typescript';
|
|
198
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
199
|
+
|
|
200
|
+
const flat = (n) =>
|
|
201
|
+
ts.isBinaryExpression(n) && n.operatorToken.kind === ts.SyntaxKind.PlusToken
|
|
202
|
+
? [flat(n.left), flat(n.right)].every(Boolean) && flat(n.left) + flat(n.right)
|
|
203
|
+
: (ts.isStringLiteral(n) || ts.isNoSubstitutionTemplateLiteral(n)) && n.text;
|
|
204
|
+
|
|
205
|
+
for (const file of process.argv.slice(2)) {
|
|
206
|
+
const src = readFileSync(file, 'utf8');
|
|
207
|
+
const sf = ts.createSourceFile(file, src, ts.ScriptTarget.Latest, true);
|
|
208
|
+
const edits = [];
|
|
209
|
+
const visit = (n) => {
|
|
210
|
+
const text = flat(n);
|
|
211
|
+
// the whole chain is one edit, so do not descend into it
|
|
212
|
+
if (text !== false && ts.isBinaryExpression(n)) return void edits.push([n.getStart(sf), n.getEnd(), text]);
|
|
213
|
+
n.forEachChild(visit);
|
|
214
|
+
};
|
|
215
|
+
visit(sf);
|
|
216
|
+
let out = src;
|
|
217
|
+
for (const [start, end, text] of edits.reverse())
|
|
218
|
+
out = `${out.slice(0, start)}${JSON.stringify(text)}${out.slice(end)}`;
|
|
219
|
+
if (edits.length) writeFileSync(file, out), console.log(`${file}: ${edits.length} collapsed`);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
It emits double-quoted strings (`JSON.stringify` does the escaping, so prose
|
|
224
|
+
containing an apostrophe survives); run the formatter afterwards. Write the
|
|
225
|
+
result as one long line rather than re-wrapping it — a template literal reads
|
|
226
|
+
statically but keeps its newlines and indentation, and `render` copies the
|
|
227
|
+
statement into the Markdown exactly as written.
|
|
66
228
|
The `--json` envelope is unchanged: `registry-not-static` is a new `code` on
|
|
67
229
|
the existing `Issue` shape, which is additive, so `schemaVersion` stays `1`.
|
|
68
230
|
`vite` remains a peer dependency — `verify` and `archive` run the suite through
|
|
@@ -174,12 +336,13 @@ not move when one is cut.
|
|
|
174
336
|
when a requirement is added without a hand-labelled obligation count, because
|
|
175
337
|
the reach figure once quoted here went stale exactly that way.
|
|
176
338
|
*`compound-requirement` (WARNING) — rejected.* More than one RFC-2119 keyword
|
|
177
|
-
in one `statement` is objectively more than one obligation. Measured: of the
|
|
178
|
-
requirements in the corpus carrying more than one, it flags
|
|
179
|
-
misses `ATX-5`, `ATX-9`, `ATX-13`, `ATX-14`, `ATX-17` — every
|
|
180
|
-
clauses under a single keyword, which is the form the coverage
|
|
181
|
-
actually rewards. A wider variant (keyword plus a coordinating
|
|
182
|
-
|
|
339
|
+
in one `statement` is objectively more than one obligation. Measured: of the 7
|
|
340
|
+
requirements in the corpus carrying more than one, it flags 2 (`ATX-10`,
|
|
341
|
+
`ATX-21`) and misses `ATX-5`, `ATX-9`, `ATX-13`, `ATX-14`, `ATX-17` — every
|
|
342
|
+
one that packs clauses under a single keyword, which is the form the coverage
|
|
343
|
+
incentive actually rewards. A wider variant (keyword plus a coordinating
|
|
344
|
+
`and`/`while`/`;`) reaches 6 of 7 with one wrong hit, so reach is not the
|
|
345
|
+
deciding argument.
|
|
183
346
|
This is: both variants are silenced by deleting the word that triggered them,
|
|
184
347
|
and neither can tell that deletion from a real split. `SHALL do A and MUST do
|
|
185
348
|
B` clears the warning as `SHALL do A and do B` — same two obligations, one
|
|
@@ -189,12 +352,13 @@ not move when one is cut.
|
|
|
189
352
|
different values in two requirements sharing an id prefix. Measured: it fires
|
|
190
353
|
twice on this repo and both firings are wrong — `idleTimeoutMin` (`15` in
|
|
191
354
|
`ATX-3`, `30` in `ATX-10`), unrelated illustrative fixtures, and `code`
|
|
192
|
-
(`registry-not-static` in `ATX-17`, `empty-spec` in `ATX-18
|
|
193
|
-
that could not possibly
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
355
|
+
(`registry-not-static` in `ATX-17`, `empty-spec` in `ATX-18`,
|
|
356
|
+
`rationale-placeholder` in `ATX-21`), diagnostics that could not possibly
|
|
357
|
+
agree. The second arrived on its own when `ATX-18` was added and grew a third
|
|
358
|
+
member on its own again when `ATX-21` was, which is the more damning half: a
|
|
359
|
+
generic param name collides more often as a registry grows, so the
|
|
360
|
+
false-positive rate rises with adoption — the opposite of what a shippable rule
|
|
361
|
+
does. Still zero true positives across 25 requirements. The escape hatch it was blocked on has since been designed
|
|
198
362
|
and does not rescue it: with no config file the only workable shape is an
|
|
199
363
|
additive `independentParams?: string[]` on the requirement (a CLI flag is
|
|
200
364
|
per-invocation for what is a permanent property of two requirements; changing
|
|
@@ -534,7 +698,8 @@ Initial release.
|
|
|
534
698
|
(MIT), whose four-stage engine and diff-first change model Attest's
|
|
535
699
|
architecture is adapted from (re-implemented from scratch, no source copied).
|
|
536
700
|
|
|
537
|
-
[Unreleased]: https://gitlab.com/Pseudorca/attest/-/compare/v0.2.
|
|
701
|
+
[Unreleased]: https://gitlab.com/Pseudorca/attest/-/compare/v0.2.1...main
|
|
702
|
+
[0.2.1]: https://gitlab.com/Pseudorca/attest/-/tags/v0.2.1
|
|
538
703
|
[0.2.0]: https://gitlab.com/Pseudorca/attest/-/tags/v0.2.0
|
|
539
704
|
[0.1.7]: https://gitlab.com/Pseudorca/attest/-/tags/v0.1.7
|
|
540
705
|
[0.1.6]: https://gitlab.com/Pseudorca/attest/-/tags/v0.1.6
|
package/README.md
CHANGED
|
@@ -14,6 +14,13 @@ physically impossible to drift between the spec and the assertion. A param may b
|
|
|
14
14
|
a scalar or an array of scalars, so list-shaped constants (vendor blacklists, id
|
|
15
15
|
sets) get the same single source as a lone number.
|
|
16
16
|
|
|
17
|
+
What that does not buy is a warning when you change the value. `check` runs
|
|
18
|
+
nothing, so editing a param leaves it at `✓ No issues` — nothing became unbound,
|
|
19
|
+
nothing became uncovered. The value cannot *diverge* from the assertion, which is
|
|
20
|
+
the stronger property; noticing that it *moved* is `verify`'s job, and only when
|
|
21
|
+
a scenario asserts on the value it read from `params`. Read the param inside the
|
|
22
|
+
assertion, not beside it.
|
|
23
|
+
|
|
17
24
|
See the authoritative design — [English](https://gitlab.com/Pseudorca/attest/-/blob/main/docs/en/attest-design.md) · [中文](https://gitlab.com/Pseudorca/attest/-/blob/main/docs/zh/attest-design.md) — and the rest of the [docs](https://gitlab.com/Pseudorca/attest/-/tree/main/docs).
|
|
18
25
|
|
|
19
26
|
## Prerequisites
|
|
@@ -57,7 +64,7 @@ import { createSession, advance, isValid } from './session.js';
|
|
|
57
64
|
|
|
58
65
|
requirement('AUTH-3', () => {
|
|
59
66
|
scenario('idle timeout invalidates the session', () => {
|
|
60
|
-
const t = reqs['AUTH-3'].params.idleTimeoutMin; //
|
|
67
|
+
const t = reqs['AUTH-3'].params.idleTimeoutMin; // single source, typed `30` — no cast
|
|
61
68
|
const s = createSession();
|
|
62
69
|
advance(s, t + 1, 'minutes');
|
|
63
70
|
expect(isValid(s, t)).toBe(false);
|
|
@@ -115,6 +122,12 @@ behaviour instead, `--eval` restores it on all three commands:
|
|
|
115
122
|
attest check --eval # reads the registry by executing every *.reqs.ts
|
|
116
123
|
```
|
|
117
124
|
|
|
125
|
+
One more thing to know about literals: write registry prose as **one long
|
|
126
|
+
single-line string**. A template literal with no substitution reads statically and
|
|
127
|
+
is accepted — but it keeps every newline and every space of indentation inside it,
|
|
128
|
+
and `render` puts the statement into the Markdown exactly as written, so the
|
|
129
|
+
wrapping that looked tidy in the editor lands in the generated document.
|
|
130
|
+
|
|
118
131
|
### A readable spec for humans (`attest render`)
|
|
119
132
|
|
|
120
133
|
The intent layer lives in TypeScript, which means a reviewer, a QA engineer, or
|
|
@@ -208,7 +221,7 @@ attest check --json
|
|
|
208
221
|
{
|
|
209
222
|
"tool": "attest",
|
|
210
223
|
"schemaVersion": 1,
|
|
211
|
-
"version": "0.2.
|
|
224
|
+
"version": "0.2.1",
|
|
212
225
|
"command": "check",
|
|
213
226
|
"ok": false,
|
|
214
227
|
"summary": { "error": 1, "warning": 0, "info": 0 },
|
package/dist/core/registry.d.ts
CHANGED
|
@@ -1,18 +1,66 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { type RegistryInput, type RequirementInput } from './schema.js';
|
|
3
|
-
import type { Registry } from './types.js';
|
|
3
|
+
import type { Registry, Requirement } from './types.js';
|
|
4
4
|
/** Thrown when a registry fails structural validation (design §5.1). */
|
|
5
5
|
export declare class RegistryValidationError extends Error {
|
|
6
6
|
readonly issues: z.ZodIssue[];
|
|
7
7
|
constructor(issues: z.ZodIssue[]);
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A `const` type parameter infers an array literal as a tuple, and would infer
|
|
11
|
+
* it as a `readonly` tuple under a constraint that admits one. Neither is what
|
|
12
|
+
* the registry parses to: the schema's array params are plain mutable
|
|
13
|
+
* `Array<scalar>`, and `const xs: string[] = req.params.dirs` has to keep
|
|
14
|
+
* compiling. Collapsing to `E[]` keeps the element types the author wrote —
|
|
15
|
+
* the point of the exercise — without claiming a length or a mutability the
|
|
16
|
+
* parsed value does not have.
|
|
17
|
+
*/
|
|
18
|
+
type AsArray<V> = V extends readonly (infer E)[] ? E[] : V;
|
|
19
|
+
/**
|
|
20
|
+
* The params of one requirement as written, over the schema's wider record.
|
|
21
|
+
* The intersection is what keeps this a widening: `params.retries` narrows to
|
|
22
|
+
* the literal `3`, while `params.somethingElse` still resolves through the
|
|
23
|
+
* record, so no read that compiled before stops compiling.
|
|
24
|
+
*/
|
|
25
|
+
type DefinedParams<R> = R extends {
|
|
26
|
+
params: infer P;
|
|
27
|
+
} ? {
|
|
28
|
+
-readonly [K in keyof P]: AsArray<P[K]>;
|
|
29
|
+
} & Requirement['params'] : Requirement['params'];
|
|
30
|
+
/**
|
|
31
|
+
* What `defineRequirements` returns for a literal registry: each declared ID
|
|
32
|
+
* keeps the param types its author wrote, so a scenario reads a value without
|
|
33
|
+
* converging the `string | number | boolean | Array<…>` union at the read site
|
|
34
|
+
* (design §6, mechanism 3 — a scenario reading `.params` is what quiets the
|
|
35
|
+
* anti-drift heuristic, so the type layer must not tax the one behaviour the
|
|
36
|
+
* rest of the tool exists to reward).
|
|
37
|
+
*
|
|
38
|
+
* The intersection with {@link Registry} is deliberate and load-bearing: it
|
|
39
|
+
* keeps the index signature, so `reqs[id]` with an `id: string` — a shared test
|
|
40
|
+
* helper — still compiles, and the result is still assignable to `Registry`.
|
|
41
|
+
* The cost is that an index signature admits *every* string, so a mistyped
|
|
42
|
+
* literal `reqs['TYPO-9']` falls through to it instead of being rejected
|
|
43
|
+
* outright: rejecting an unknown key and accepting a `string` one are the same
|
|
44
|
+
* question asked of one index signature, and it cannot answer both ways. What
|
|
45
|
+
* survives is the weaker form — an unknown ID misses the declared keys, so
|
|
46
|
+
* under `noUncheckedIndexedAccess` reading through it is an error where a
|
|
47
|
+
* declared ID is not. Compatibility takes the tie because a wrong ID is
|
|
48
|
+
* already an `unknown-req-id` ERROR from `check`, which reads the registry and
|
|
49
|
+
* the specs together; the type layer is the second reader here, not the only
|
|
50
|
+
* one.
|
|
51
|
+
*/
|
|
52
|
+
export type DefinedRegistry<T extends RegistryInput> = {
|
|
53
|
+
[K in keyof T]: Omit<Requirement, 'params'> & {
|
|
54
|
+
params: DefinedParams<T[K]>;
|
|
55
|
+
};
|
|
56
|
+
} & Registry;
|
|
9
57
|
/**
|
|
10
58
|
* Declare a requirement registry. Validates structure against RegistrySchema
|
|
11
59
|
* (SHALL/MUST keyword, non-empty rationale, well-formed IDs, scalar params) and
|
|
12
60
|
* returns the parsed registry with defaults applied (design §2, §5.1).
|
|
13
61
|
* Throws {@link RegistryValidationError} on invalid input.
|
|
14
62
|
*/
|
|
15
|
-
export declare function defineRequirements(input:
|
|
63
|
+
export declare function defineRequirements<const T extends RegistryInput>(input: T): DefinedRegistry<T>;
|
|
16
64
|
/**
|
|
17
65
|
* Shape of a change delta over the registry (design §7). Authoring (input)
|
|
18
66
|
* shapes are used so added / modified entries may omit defaulted fields.
|
|
@@ -32,4 +80,5 @@ export interface RegistryDelta {
|
|
|
32
80
|
* (RENAMED -> REMOVED -> MODIFIED -> ADDED) lives in applyDelta (design §7).
|
|
33
81
|
*/
|
|
34
82
|
export declare function delta(d: RegistryDelta): RegistryDelta;
|
|
83
|
+
export {};
|
|
35
84
|
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAExD,wEAAwE;AACxE,qBAAa,uBAAwB,SAAQ,KAAK;aACpB,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;gBAApB,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAIjD;AAQD;;;;;;;;GAQG;AACH,KAAK,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACjD;IAAE,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,GACnE,WAAW,CAAC,QAAQ,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,aAAa,IAAI;KACpD,CAAC,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG;QAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE;CAC9E,GAAG,QAAQ,CAAC;AAEb;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAS9F;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,aAAa,GAAG,aAAa,CAErD"}
|
package/dist/core/registry.js
CHANGED
|
@@ -28,6 +28,9 @@ export function defineRequirements(input) {
|
|
|
28
28
|
if (!result.success) {
|
|
29
29
|
throw new RegistryValidationError(result.error.issues);
|
|
30
30
|
}
|
|
31
|
+
// Zod validates the shape but its output type is the schema's, which has
|
|
32
|
+
// already forgotten the literals `const T` captured. Same object, narrower
|
|
33
|
+
// description of it — the assertion carries the literals across.
|
|
31
34
|
return result.data;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4EAA4E;AAC5E,yEAAyE;AAEzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,aAAa,CAAC;AAGrB,wEAAwE;AACxE,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACpB;IAA5B,YAA4B,MAAoB;QAC9C,KAAK,CAAC,kCAAkC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QADtC,WAAM,GAAN,MAAM,CAAc;QAE9C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;SAC/D,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/core/registry.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,4EAA4E;AAC5E,yEAAyE;AAEzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,aAAa,CAAC;AAGrB,wEAAwE;AACxE,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACpB;IAA5B,YAA4B,MAAoB;QAC9C,KAAK,CAAC,kCAAkC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QADtC,WAAM,GAAN,MAAM,CAAc;QAE9C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;SAC/D,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAiDD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAgC,KAAQ;IACxE,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,uBAAuB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzD,CAAC;IACD,yEAAyE;IACzE,2EAA2E;IAC3E,iEAAiE;IACjE,OAAO,MAAM,CAAC,IAA0B,CAAC;AAC3C,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,CAAgB;IACpC,OAAO,CAAC,CAAC;AACX,CAAC"}
|
package/dist/core/validator.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ import type { AttestPlan, Issue, ParamRef, Registry } from './types.js';
|
|
|
4
4
|
* - orphan-test: a scenario covers an unknown requirement id
|
|
5
5
|
* - uncovered-requirement: a requirement has no scenario
|
|
6
6
|
* - unbound-param: a statement placeholder has no matching param
|
|
7
|
+
*
|
|
8
|
+
* and one WARNING:
|
|
9
|
+
* - rationale-placeholder: a `{name}` in a rationale, which is never interpolated
|
|
7
10
|
*/
|
|
8
11
|
export declare function validateStructure(registry: Registry, plan: AttestPlan): Issue[];
|
|
9
12
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAkB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAExF
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAkB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAExF;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,KAAK,EAAE,CA0E/E;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,QAAQ,EAAE,GACf,KAAK,EAAE,CA+BT"}
|
package/dist/core/validator.js
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* - orphan-test: a scenario covers an unknown requirement id
|
|
6
6
|
* - uncovered-requirement: a requirement has no scenario
|
|
7
7
|
* - unbound-param: a statement placeholder has no matching param
|
|
8
|
+
*
|
|
9
|
+
* and one WARNING:
|
|
10
|
+
* - rationale-placeholder: a `{name}` in a rationale, which is never interpolated
|
|
8
11
|
*/
|
|
9
12
|
export function validateStructure(registry, plan) {
|
|
10
13
|
const issues = [];
|
|
@@ -51,6 +54,29 @@ export function validateStructure(registry, plan) {
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
}
|
|
57
|
+
// rationale-placeholder: `{name}` written in a rationale, which render does
|
|
58
|
+
// not interpolate (it substitutes into the statement and nothing else). Both
|
|
59
|
+
// spellings are reported, and the declared one is the reason this is not an
|
|
60
|
+
// extension of unbound-param: an author who declares `maxAttempts` and then
|
|
61
|
+
// writes it into the rationale has made no binding mistake at all, yet the
|
|
62
|
+
// braces still reach the document reviewers and audit read. Fixing render to
|
|
63
|
+
// interpolate here would change the bytes of every existing rendering, so
|
|
64
|
+
// this reports instead. WARNING, deliberately below `hasError`: an existing
|
|
65
|
+
// green registry gains a line of output and keeps its exit code.
|
|
66
|
+
for (const [id, req] of Object.entries(registry)) {
|
|
67
|
+
// Code spans are dropped first: a rationale is rendered as Markdown, so a
|
|
68
|
+
// backticked `{toString}` is a quoted token, not a placeholder its author
|
|
69
|
+
// misfiled — and render leaves a code span exactly as written. Attest's own
|
|
70
|
+
// ATX-14 is that case, which is how this exclusion was found.
|
|
71
|
+
for (const m of req.rationale.replace(/`[^`]*`/g, ' ').matchAll(/\{(\w+)\}/g)) {
|
|
72
|
+
issues.push({
|
|
73
|
+
level: 'WARNING',
|
|
74
|
+
code: 'rationale-placeholder',
|
|
75
|
+
reqId: id,
|
|
76
|
+
message: `Requirement "${id}" writes {${m[1]}} in its rationale, but only the statement is interpolated — the braces reach the rendering verbatim. Move the placeholder into the statement, or write the value out as prose.`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
54
80
|
return issues;
|
|
55
81
|
}
|
|
56
82
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,8EAA8E;AAI9E
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { requirement, scenario } from './runtime.js';
|
|
2
2
|
export { defineRequirements, delta } from './core/registry.js';
|
|
3
|
-
export type { RegistryDelta } from './core/registry.js';
|
|
3
|
+
export type { RegistryDelta, DefinedRegistry } from './core/registry.js';
|
|
4
4
|
export type { Requirement, Registry, ParsedScenario, AttestPlan, Level, Issue, } from './core/types.js';
|
|
5
5
|
export type { JsonReport, JsonSummary, JsonCommand } from './cli/json.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACzE,YAAY,EACV,WAAW,EACX,QAAQ,EACR,cAAc,EACd,UAAU,EACV,KAAK,EACL,KAAK,GACN,MAAM,iBAAiB,CAAC;AAIzB,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@am_shork/attest",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "TDD-native spec framework: tests are the source of truth for verification, ID-bound requirements the source of truth for intent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
"scripts": {
|
|
65
65
|
"build": "tsc -p tsconfig.json",
|
|
66
66
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
67
|
+
"typecheck:all": "tsc -p tsconfig.typecheck.json",
|
|
67
68
|
"test": "vitest run",
|
|
68
69
|
"test:watch": "vitest",
|
|
69
70
|
"test:consumer": "pnpm run build && vitest run --config vitest.consumer.config.ts",
|