@am_shork/attest 0.2.1 → 0.2.2

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 CHANGED
@@ -15,24 +15,67 @@ 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.
18
+ ## [0.2.2] - 2026-07-26
19
+
20
+ A wall of identical diagnostics now says once that it is one cause, and the
21
+ per-issue lines it summarises are unchanged.
22
+
23
+ ### Added
24
+
25
+ - **A report of N issues sharing one `code` now says so once.** The 0.1.1 → 0.2.0
26
+ upgrade printed six `registry-not-static` ERRORs in a row — one per registry
27
+ file, every one caused by the same prose written as `'…' + '…'` and left the
28
+ reader to work out that they were one cause and one mechanical fix. Every
29
+ command that prints issues (`check`, `verify`, `cover`, `render`, `archive`)
30
+ now adds one line above the counts when a code repeats:
31
+
32
+ ```
33
+ Repeated: 6 × ERROR registry-not-static, 4 × WARNING rationale-placeholder
34
+ ```
35
+
36
+ The per-issue lines are untouched — they are what makes a diagnostic
37
+ clickable — and this is the last entry from the skills-manager adoption report
38
+ (0.2.0, 41 requirements / 106 scenarios, plain-TS), so the
39
+ `Under consideration` section is now empty and gone. Five decisions, with the
40
+ reasoning, because each of them could plausibly have gone the other way:
41
+
42
+ **The `code` names the shared cause, and there is no table.** The obvious
43
+ reading of "name the cause" is a `code` → prose map: `registry-not-static` →
44
+ "a registry was built by concatenation". That map would have to be extended
45
+ with every new code, and the failure mode of forgetting is silent — the line
46
+ keeps printing, just vaguer. So the summary states structure only, how many
47
+ issues carry the same code, and leaves the explaining to the per-issue
48
+ `message`s directly above it. A `code` already *is* the stable name of the
49
+ shared rule; `message` is prose and not API, which is exactly why the summary
50
+ quotes neither.
51
+
52
+ **Three, not two.** Two adjacent lines with the same code are not a wall — the
53
+ repetition is visible at a glance, and summarising it would charge every
54
+ ordinary double error a line to state what the reader can already see.
55
+
56
+ **Below the issues, beside the counts, not merged into them.** The clickable
57
+ lines land first and the aggregate reads as a conclusion about them rather than
58
+ a preamble to issues not yet seen. It stays a separate line because
59
+ `— N error, M warning, K info` is a fixed shape and the only stable thing to
60
+ `grep` at the end of a report; a conditional clause inside it would make it
61
+ variable-length.
62
+
63
+ **Every level, grouped by level *and* code.** A pile of `rationale-placeholder`
64
+ WARNINGs is the same reading problem as a pile of ERRORs. The grouping key is
65
+ the pair because a count that silently spanned two levels would give one number
66
+ for two different dispositions — in practice every issue site writes a literal
67
+ level, and the composite key is what makes that not need to be true.
68
+
69
+ **Presentation, not a report change.** `SCHEMA_VERSION` is untouched and
70
+ `--json` is byte-identical: the summary is not an `Issue`, so it carries no
71
+ `code` into `issues[]`, adds nothing to `summary`, and cannot move `ok`. Split
72
+ across two self-requirements (ATX-23, ATX-24) rather than one, because the
73
+ cheapest implementation — push one more `Issue` — satisfies the human half
74
+ completely while breaking the contract half, and at ERROR level would flip the
75
+ verdict of a report that found nothing new. That needs a scenario that fails,
76
+ not a clause in a sentence. `docs/en/attest-design.md` §5.3 is deliberately
77
+ unchanged: it specifies the `Issue` contract and the grading, and documenting a
78
+ terminal nicety there would imply this is part of it.
36
79
 
37
80
  ## [0.2.1] - 2026-07-26
38
81
 
@@ -698,7 +741,8 @@ Initial release.
698
741
  (MIT), whose four-stage engine and diff-first change model Attest's
699
742
  architecture is adapted from (re-implemented from scratch, no source copied).
700
743
 
701
- [Unreleased]: https://gitlab.com/Pseudorca/attest/-/compare/v0.2.1...main
744
+ [Unreleased]: https://gitlab.com/Pseudorca/attest/-/compare/v0.2.2...main
745
+ [0.2.2]: https://gitlab.com/Pseudorca/attest/-/tags/v0.2.2
702
746
  [0.2.1]: https://gitlab.com/Pseudorca/attest/-/tags/v0.2.1
703
747
  [0.2.0]: https://gitlab.com/Pseudorca/attest/-/tags/v0.2.0
704
748
  [0.1.7]: https://gitlab.com/Pseudorca/attest/-/tags/v0.1.7
package/README.md CHANGED
@@ -185,6 +185,17 @@ The gap between the two numbers is worth watching: a spec file whose
185
185
  `requirement()` call Attest cannot see statically is skipped rather than failed,
186
186
  and that is where it shows. The same four numbers are in `--json` under `counts`.
187
187
 
188
+ When three or more issues in one report share a level and a code, one line above
189
+ the counts says so, because a wall of identical codes is one rule and many sites:
190
+
191
+ ```
192
+ Repeated: 6 × ERROR registry-not-static, 4 × WARNING rationale-placeholder
193
+ ```
194
+
195
+ Every per-issue line stays exactly as it is — they are what makes a diagnostic
196
+ clickable — and the summary is terminal output only: it is not an issue, so it
197
+ appears nowhere in `--json`, changes no count, and never moves a verdict.
198
+
188
199
  A run with **no requirements** under the root is an `empty-spec` ERROR, not a
189
200
  pass. "No failing tests" is not the same claim as "the requirements hold", and
190
201
  the case that matters is not the empty directory — it is the repo whose registry
@@ -221,7 +232,7 @@ attest check --json
221
232
  {
222
233
  "tool": "attest",
223
234
  "schemaVersion": 1,
224
- "version": "0.2.1",
235
+ "version": "0.2.2",
225
236
  "command": "check",
226
237
  "ok": false,
227
238
  "summary": { "error": 1, "warning": 0, "info": 0 },
@@ -1,6 +1,23 @@
1
1
  import type { CoverageRow, VerifyCounts } from '../core/pipeline.js';
2
2
  import type { Issue } from '../core/types.js';
3
3
  export declare function formatIssues(issues: Issue[]): string;
4
+ /**
5
+ * A code repeating across files is one rule and many sites, and a reader looking
6
+ * at the wall has to diff the lines to learn that. This says it once.
7
+ *
8
+ * There is deliberately no code → prose table naming the "cause": the `code`
9
+ * already *is* the name of the shared rule, and each site's `message` states the
10
+ * rule in full. A table would also have to be extended with every new code, and
11
+ * forgetting to would degrade this line in silence. So the line states structure
12
+ * only — how many issues carry the same code — and leaves the explaining to the
13
+ * per-site lines above it, which are what makes a diagnostic clickable.
14
+ *
15
+ * Grouped by level *and* code, not code alone: a count that silently spanned two
16
+ * levels would name one number for two different dispositions. Every issue site
17
+ * writes a literal level, so in practice the two groupings agree — the composite
18
+ * key is what makes that not need to be true.
19
+ */
20
+ export declare function formatRepeats(issues: Issue[]): string;
4
21
  export declare function summarize(issues: Issue[], scope?: VerifyCounts): string;
5
22
  /**
6
23
  * The pre-run line for `verify`: how many spec files were located, and how many
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,kBAAkB,CAAC;AAUrD,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAWpD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CASvE;AAID;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAIvD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAW1D"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,kBAAkB,CAAC;AAUrD,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAYpD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAkBrD;AAUD,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,MAAM,CASvE;AAID;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAIvD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,CAW1D"}
@@ -1,6 +1,7 @@
1
1
  // Terminal rendering of graded issues (design §5.3 levels). Pure formatting —
2
2
  // no process side effects — so it stays testable and the CLI stays thin.
3
3
  import chalk from 'chalk';
4
+ import { byCodeUnit } from '../core/order.js';
4
5
  const LEVEL_TAG = {
5
6
  ERROR: (s) => chalk.red.bold(s),
6
7
  WARNING: (s) => chalk.yellow.bold(s),
@@ -18,8 +19,54 @@ export function formatIssues(issues) {
18
19
  lines.push(`${LEVEL_TAG[level](level.padEnd(7))} ${chalk.cyan(i.code)}${loc}\n ${i.message}`);
19
20
  }
20
21
  }
21
- return lines.join('\n');
22
+ const repeats = formatRepeats(issues);
23
+ return repeats ? `${lines.join('\n')}\n${repeats}` : lines.join('\n');
22
24
  }
25
+ /**
26
+ * A code repeating across files is one rule and many sites, and a reader looking
27
+ * at the wall has to diff the lines to learn that. This says it once.
28
+ *
29
+ * There is deliberately no code → prose table naming the "cause": the `code`
30
+ * already *is* the name of the shared rule, and each site's `message` states the
31
+ * rule in full. A table would also have to be extended with every new code, and
32
+ * forgetting to would degrade this line in silence. So the line states structure
33
+ * only — how many issues carry the same code — and leaves the explaining to the
34
+ * per-site lines above it, which are what makes a diagnostic clickable.
35
+ *
36
+ * Grouped by level *and* code, not code alone: a count that silently spanned two
37
+ * levels would name one number for two different dispositions. Every issue site
38
+ * writes a literal level, so in practice the two groupings agree — the composite
39
+ * key is what makes that not need to be true.
40
+ */
41
+ export function formatRepeats(issues) {
42
+ /** `${level} ${code}` -> how many issues carry that pair, and its parts. */
43
+ const groups = new Map();
44
+ for (const i of issues) {
45
+ const key = `${i.level} ${i.code}`;
46
+ const seen = groups.get(key);
47
+ if (seen)
48
+ seen.count++;
49
+ else
50
+ groups.set(key, { level: i.level, code: i.code, count: 1 });
51
+ }
52
+ const repeated = [...groups]
53
+ .filter(([, g]) => g.count >= REPEAT_THRESHOLD)
54
+ // Count first, then the key — by code unit, so the line a reader compares
55
+ // between two runs does not depend on the machine's collation.
56
+ .sort(([aKey, a], [bKey, b]) => b.count - a.count || byCodeUnit(aKey, bKey))
57
+ .map(([, g]) => `${g.count} × ${g.level} ${g.code}`);
58
+ if (repeated.length === 0)
59
+ return '';
60
+ // One line however many codes repeat: the point is to shorten the report.
61
+ return chalk.dim(`Repeated: ${repeated.join(', ')}`);
62
+ }
63
+ /**
64
+ * Two adjacent lines with the same code are not a wall — the repetition is
65
+ * visible at a glance, and summarising it would charge every ordinary double
66
+ * error an extra line to say what the reader already knows. Three is where the
67
+ * repetition stops being obvious.
68
+ */
69
+ const REPEAT_THRESHOLD = 3;
23
70
  export function summarize(issues, scope) {
24
71
  const counts = { ERROR: 0, WARNING: 0, INFO: 0 };
25
72
  for (const i of issues)
@@ -1 +1 @@
1
- {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/cli/report.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,15 @@ export interface GateInputs {
7
7
  /** Executable verification result (design §5.4). */
8
8
  run: RunResult;
9
9
  }
10
+ /**
11
+ * Declared-not-run: a scenario the static plan claims attests a requirement,
12
+ * which the runtime never executed (skipped, or excluded by an `.only`).
13
+ *
14
+ * Exported because `verify` and `archive` both make this call. While each owned
15
+ * a copy, the two verdicts agreed only by transcription — and the whole point of
16
+ * this framework is that agreement should be structural, not clerical.
17
+ */
18
+ export declare function declaredNotRunIssues(plan: AttestPlan, run: RunResult): Issue[];
10
19
  /**
11
20
  * Decide whether a change may be archived. Returns the blocking issues; an
12
21
  * empty array means the gate passes (design §8). Checks, in order:
@@ -18,14 +27,5 @@ export interface GateInputs {
18
27
  * 3. Static coverage vs runtime coverage: every declared scenario actually
19
28
  * ran (catches skip/only false coverage).
20
29
  */
21
- /**
22
- * Declared-not-run: a scenario the static plan claims attests a requirement,
23
- * which the runtime never executed (skipped, or excluded by an `.only`).
24
- *
25
- * Exported because `verify` and `archive` both make this call. While each owned
26
- * a copy, the two verdicts agreed only by transcription — and the whole point of
27
- * this framework is that agreement should be structural, not clerical.
28
- */
29
- export declare function declaredNotRunIssues(plan: AttestPlan, run: RunResult): Issue[];
30
30
  export declare function evaluateGate({ registry, plan, run }: GateInputs): Issue[];
31
31
  //# sourceMappingURL=gate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,EAAE,QAAQ,CAAC;IACnB,8CAA8C;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,GAAG,EAAE,SAAS,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,EAAE,CAe9E;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,CAqBzE"}
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,QAAQ,EAAE,QAAQ,CAAC;IACnB,8CAA8C;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,oDAAoD;IACpD,GAAG,EAAE,SAAS,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,KAAK,EAAE,CAe9E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,UAAU,GAAG,KAAK,EAAE,CAqBzE"}
package/dist/core/gate.js CHANGED
@@ -4,17 +4,6 @@
4
4
  // inputs; the file orchestration (load registry+delta, parse all specs, run)
5
5
  // is wired in the Locate layer / CLI (see pipeline.ts).
6
6
  import { validateStructure } from './validator.js';
7
- /**
8
- * Decide whether a change may be archived. Returns the blocking issues; an
9
- * empty array means the gate passes (design §8). Checks, in order:
10
- * 1. Structural ERRORs on the end-state registry (no orphan / uncovered /
11
- * unbound-param). This is also the design's step-4 final re-validation:
12
- * the registry+plan here are already the applied result, so one pass
13
- * validates the end state.
14
- * 2. Executable: all tests green.
15
- * 3. Static coverage vs runtime coverage: every declared scenario actually
16
- * ran (catches skip/only false coverage).
17
- */
18
7
  /**
19
8
  * Declared-not-run: a scenario the static plan claims attests a requirement,
20
9
  * which the runtime never executed (skipped, or excluded by an `.only`).
@@ -39,6 +28,17 @@ export function declaredNotRunIssues(plan, run) {
39
28
  }
40
29
  return issues;
41
30
  }
31
+ /**
32
+ * Decide whether a change may be archived. Returns the blocking issues; an
33
+ * empty array means the gate passes (design §8). Checks, in order:
34
+ * 1. Structural ERRORs on the end-state registry (no orphan / uncovered /
35
+ * unbound-param). This is also the design's step-4 final re-validation:
36
+ * the registry+plan here are already the applied result, so one pass
37
+ * validates the end state.
38
+ * 2. Executable: all tests green.
39
+ * 3. Static coverage vs runtime coverage: every declared scenario actually
40
+ * ran (catches skip/only false coverage).
41
+ */
42
42
  export function evaluateGate({ registry, plan, run }) {
43
43
  const blocking = [];
44
44
  // 1) Structure (end-state re-validation).
@@ -1 +1 @@
1
- {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iFAAiF;AACjF,4EAA4E;AAC5E,6EAA6E;AAC7E,wDAAwD;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;;;;GAUG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAgB,EAAE,GAAc;IACnE,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,kBAAkB;gBACxB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,aAAa,CAAC,CAAC,IAAI,oCAAoC,CAAC,CAAC,KAAK,2DAA2D;aACnI,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAc;IAC9D,MAAM,QAAQ,GAAY,EAAE,CAAC;IAE7B,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,CACX,GAAG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CACxE,CAAC;IAEF,4BAA4B;IAC5B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wDAAwD;SAClE,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/core/gate.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iFAAiF;AACjF,4EAA4E;AAC5E,6EAA6E;AAC7E,wDAAwD;AAExD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAgB,EAAE,GAAc;IACnE,MAAM,MAAM,GAAY,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK,EAAE,OAAO;gBACd,IAAI,EAAE,kBAAkB;gBACxB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,OAAO,EAAE,aAAa,CAAC,CAAC,IAAI,oCAAoC,CAAC,CAAC,KAAK,2DAA2D;aACnI,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAc;IAC9D,MAAM,QAAQ,GAAY,EAAE,CAAC;IAE7B,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,CACX,GAAG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CACxE,CAAC;IAEF,4BAA4B;IAC5B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC;YACZ,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,wDAAwD;SAClE,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAElD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@am_shork/attest",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
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": {