elementary-assertions 1.0.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +353 -0
  2. package/LICENSE +21 -0
  3. package/README.md +211 -0
  4. package/bin/elementary-assertions.js +8 -0
  5. package/docs/DEV_TOOLING.md +98 -0
  6. package/docs/NPM_RELEASE.md +177 -0
  7. package/docs/OPERATIONAL.md +159 -0
  8. package/docs/RELEASE_NOTES_TEMPLATE.md +37 -0
  9. package/docs/REPO_WORKFLOWS.md +48 -0
  10. package/package.json +46 -0
  11. package/src/core/accepted-annotations.js +44 -0
  12. package/src/core/assertions.js +2304 -0
  13. package/src/core/determinism.js +95 -0
  14. package/src/core/diagnostics.js +496 -0
  15. package/src/core/ids.js +9 -0
  16. package/src/core/mention-builder.js +272 -0
  17. package/src/core/mention-evidence.js +52 -0
  18. package/src/core/mention-head-resolution.js +108 -0
  19. package/src/core/mention-materialization.js +31 -0
  20. package/src/core/mentions.js +149 -0
  21. package/src/core/output.js +296 -0
  22. package/src/core/projection.js +192 -0
  23. package/src/core/roles.js +164 -0
  24. package/src/core/strings.js +7 -0
  25. package/src/core/tokens.js +53 -0
  26. package/src/core/upstream.js +31 -0
  27. package/src/index.js +6 -0
  28. package/src/render/index.js +5 -0
  29. package/src/render/layouts/compact.js +10 -0
  30. package/src/render/layouts/meaning.js +7 -0
  31. package/src/render/layouts/readable.js +7 -0
  32. package/src/render/layouts/table.js +7 -0
  33. package/src/render/render.js +931 -0
  34. package/src/run.js +278 -0
  35. package/src/schema/seed.elementary-assertions.schema.json +1751 -0
  36. package/src/tools/cli.js +158 -0
  37. package/src/tools/index.js +6 -0
  38. package/src/tools/io.js +55 -0
  39. package/src/validate/ajv.js +20 -0
  40. package/src/validate/coverage.js +215 -0
  41. package/src/validate/determinism.js +115 -0
  42. package/src/validate/diagnostics-strict.js +392 -0
  43. package/src/validate/errors.js +19 -0
  44. package/src/validate/index.js +20 -0
  45. package/src/validate/integrity.js +41 -0
  46. package/src/validate/invariants.js +157 -0
  47. package/src/validate/references.js +110 -0
  48. package/src/validate/schema.js +50 -0
@@ -0,0 +1,98 @@
1
+ # Developer Tooling (Non-Public)
2
+
3
+ This document describes repository developer tooling only.
4
+ It is not part of the npm package contract and can change between releases.
5
+
6
+ ## Scope
7
+
8
+ These scripts are intended for internal quality analysis and regression triage:
9
+
10
+ - `npm run dev:check`
11
+ - `npm run dev:report:metrics`
12
+ - `npm run dev:report:hotspots`
13
+ - `npm run dev:report:maturity`
14
+ - `npm run dev:diagnose:wiki-upstream`
15
+ - `npm run dev:diagnose:wti-wiring`
16
+ - `npm run dev:diagnose:coverage-audit`
17
+ - `npm run dev:reports`
18
+
19
+ They read from committed artifact references under `test/artifacts/*/result-reference/` and emit JSON reports to stdout.
20
+
21
+ `npm run dev:reports` is an aggregate maintainer command that executes:
22
+ - metrics
23
+ - hotspots
24
+ - maturity
25
+ - wikipedia-upstream diagnostics (`dev:diagnose:wiki-upstream`)
26
+ - WTI wiring diagnostics
27
+ - coverage-audit diagnostics
28
+
29
+ `npm run dev:check` runs strict validation (`validateElementaryAssertions(..., { strict: true })`) across:
30
+ - a single file via `--in <path>`, or
31
+ - all artifact golden YAML files under `test/artifacts/` (default).
32
+
33
+ ## Common script options
34
+
35
+ Most `dev:*` scripts support:
36
+ - `--seed <name>` to run on one artifact seed only
37
+ - `--artifacts-root <path>` to override the default `test/artifacts` root
38
+
39
+ `npm run dev:check` additionally supports:
40
+ - `--in <path>` to validate one explicit document instead of artifact references
41
+
42
+ `npm run dev:diagnose:wiki-upstream` additionally supports:
43
+ - `--upstream <path>` (JSON/YAML) to correlate uncovered mentions between EA output and accepted upstream dependency endpoints
44
+
45
+ Wikipedia-upstream diagnostics report depth:
46
+ - upstream wikipedia field-path inventory by object family
47
+ - categorized missing-field samples (`missing_upstream_acceptance` vs `present_upstream_dropped_downstream`)
48
+ - stratified representative samples by role class and mention kind
49
+
50
+ Maintainer triage scope:
51
+ - upstream diagnostics include bounded field-inventory examples and predicate-level coverage summaries
52
+ - `dev:check` is a maintainer triage tool and should emit invariant-family failure context when strict checks fail
53
+
54
+ `npm run dev:diagnose:wiki-upstream` report contracts used for maintainer triage:
55
+ - `correlation.upstream_wikipedia_field_inventory.object_families[*].field_paths[*]` includes:
56
+ - `path`
57
+ - `count`
58
+ - bounded `example`
59
+ - deterministic `example_source_id`
60
+ - `correlation.predicate_wikipedia_coverage_summary` includes:
61
+ - total predicates considered
62
+ - predicates with wikipedia signal
63
+ - predicates missing wikipedia signal
64
+ - cause split:
65
+ - accepted predicate but missing wikipedia payload
66
+ - predicate not present/eligible in accepted relations
67
+
68
+ `npm run dev:check` failure output contract for strict mode:
69
+ - emits deterministic `invariant_family` grouping per failing code family
70
+ - includes minimal reproducer pointer (`seed_id`, `segment_id`, `mention_id`/`assertion_id`)
71
+ - includes deterministic `recommended_next_command` for follow-up diagnostics
72
+
73
+ `npm run dev:diagnose:wti-wiring` additionally supports:
74
+ - `--runtime-probe` to enforce runtime wiring checks
75
+ - `--wti-endpoint <url>` (required in runtime probe mode)
76
+ - `--wti-timeout-ms <ms>` (optional override for runtime probe health timeout)
77
+
78
+ WTI wiring diagnostics report depth:
79
+ - non-probe mode includes explicit wiring attribution:
80
+ - endpoint configured / mandatory endpoint behavior active
81
+ - per-step requested vs observed signal families
82
+ - runtime probe remains authoritative for wiring truth and fail-fast behavior
83
+
84
+ Runtime probe mode intentionally fails on wiring-contract violations (for example missing endpoint or no positive pass-through signals).
85
+
86
+ Fragment hotspot diagnostics report depth:
87
+ - primary lens: clause-local lexical host + evidence containment
88
+ - secondary lens (triage-only): segment-level host availability and containment
89
+
90
+ ## Contract boundary
91
+
92
+ - Public/stable interfaces remain:
93
+ - `require("elementary-assertions")`
94
+ - `require("elementary-assertions/validate")`
95
+ - `require("elementary-assertions/render")`
96
+ - `require("elementary-assertions/tools")`
97
+ - `require("elementary-assertions/schema")`
98
+ - `npm run dev:*` scripts are non-public workflow tooling and are not a compatibility guarantee.
@@ -0,0 +1,177 @@
1
+ # NPM_RELEASE.md
2
+
3
+ This document defines the release flow for `elementary-assertions`.
4
+
5
+ Current distribution status (until npmjs publish is executed): consumers install as a Git dependency pinned to a tag (or commit).
6
+ After npmjs publication: publish to npmjs while keeping Git-tag installs supported.
7
+ `files` is used to keep both Git installs and npm tarballs deterministic.
8
+
9
+ Examples (consumer `package.json`):
10
+
11
+ - SSH:
12
+ - `"elementary-assertions": "git+ssh://git@github.com:svenschaefer/elementary-assertions.git#v1.2.3"`
13
+ - HTTPS:
14
+ - `"elementary-assertions": "git+https://github.com/svenschaefer/elementary-assertions.git#v1.2.3"`
15
+
16
+ Consumers MUST pin to tags or commits, not branches.
17
+
18
+ ## Core rule
19
+
20
+ A release is defined by:
21
+ - version bump in `package.json`
22
+ - a commit on `main`
23
+ - an annotated Git tag `vX.Y.Z` pointing at that commit
24
+
25
+ ## Packaging rule for Git dependencies
26
+
27
+ Even though installs come from Git, the repository MUST remain a valid Node package.
28
+ Golden baseline freeze metadata is maintained in `test/artifacts/README.md`.
29
+
30
+ - `npm pack --dry-run` MUST succeed.
31
+ - `package.json` `files` is the primary packlist control.
32
+ - `.npmignore` is an additional safeguard for local non-package files.
33
+
34
+ ## 0) Preconditions
35
+
36
+ - Working tree clean.
37
+ - `npm test` passes.
38
+ - If `runElementaryAssertions` is used in smoke tests, ensure any required `wikipedia-title-index` endpoint is reachable.
39
+
40
+ ## 1) Prepare release branch
41
+
42
+ ```powershell
43
+ git checkout main
44
+ git pull
45
+ git checkout -b release/vX.Y.Z
46
+ ```
47
+
48
+ ## 2) Implement + test
49
+
50
+ * Make the change.
51
+ * Add/update regression tests.
52
+ * Run:
53
+
54
+ ```powershell
55
+ npm test
56
+ ```
57
+
58
+ ## 3) Bump version (no auto-tag)
59
+
60
+ ```powershell
61
+ npm version X.Y.Z --no-git-tag-version
62
+ ```
63
+
64
+ If a lockfile exists and changes, keep it consistent with your npm version.
65
+
66
+ ## 4) Pack sanity
67
+
68
+ ```powershell
69
+ npm pack --dry-run
70
+ ```
71
+
72
+ Optional: build the tarball locally (not uploaded anywhere):
73
+
74
+ ```powershell
75
+ npm pack
76
+ ```
77
+
78
+ Cleanup after local pack steps:
79
+
80
+ ```powershell
81
+ Remove-Item -Force .\elementary-assertions-*.tgz
82
+ ```
83
+
84
+ ## 5) Smoke install checks (pre-tag)
85
+
86
+ Create a clean workspace and install from the commit hash you intend to tag.
87
+ Use the shared smoke script so API/CLI checks and render parity are enforced together.
88
+ The smoke script verifies parity for `txt/compact`, `md/table`, and `md/meaning`.
89
+
90
+ Smoke workspace rule:
91
+ - Use `C:\code\elementary-assertions-smoke-test\`.
92
+ - Create one folder per clean install.
93
+ - Folder name MUST include the target version and the reason for the install (for example `v1.2.3-pretag-smoke-20260214-113000`).
94
+
95
+ ```powershell
96
+ $SmokeRoot = "C:\code\elementary-assertions-smoke-test\vX.Y.Z-pretag-smoke-$(Get-Date -Format yyyyMMdd-HHmmss)"
97
+ New-Item -ItemType Directory -Path $SmokeRoot -Force | Out-Null
98
+ Set-Location $SmokeRoot
99
+ npm init -y | Out-Null
100
+
101
+ # Replace <COMMIT> with the commit you intend to tag
102
+ npm install "git+ssh://git@github.com:svenschaefer/elementary-assertions.git#<COMMIT>"
103
+
104
+ node C:\code\elementary-assertions\scripts\release-smoke-check.js --repo-root C:\code\elementary-assertions --smoke-root $SmokeRoot --out-root (Join-Path $SmokeRoot "rendered")
105
+ npm ls elementary-assertions
106
+ ```
107
+
108
+ If the smoke test exercises `runElementaryAssertions`, also ensure the environment provides whatever endpoint configuration your CLI/tooling expects for `wikipedia-title-index`.
109
+
110
+ ## 6) Commit + merge to main
111
+
112
+ For release commits, prefer explicit staging paths to avoid unintended additions, for example:
113
+ `git add src docs test scripts package.json README.md CHANGELOG.md`.
114
+
115
+ ```powershell
116
+ Set-Location C:\code\elementary-assertions
117
+ git add src docs test scripts package.json README.md CHANGELOG.md
118
+ git commit -m "release: vX.Y.Z"
119
+ git push -u origin release/vX.Y.Z
120
+ ```
121
+
122
+ Merge the release branch to `main` (PR merge or fast-forward merge), then:
123
+
124
+ ```powershell
125
+ git checkout main
126
+ git pull
127
+ git merge --ff-only release/vX.Y.Z
128
+ git push origin main
129
+ ```
130
+
131
+ ## 7) Tag + push
132
+
133
+ Tag only after the release commit is on `main`:
134
+
135
+ ```powershell
136
+ git tag -a vX.Y.Z -m "vX.Y.Z"
137
+ git push origin vX.Y.Z
138
+ ```
139
+
140
+ ## 8) Post-tag verification (install from tag)
141
+
142
+ ```powershell
143
+ $SmokeRoot = "C:\code\elementary-assertions-smoke-test\vX.Y.Z-posttag-smoke-$(Get-Date -Format yyyyMMdd-HHmmss)"
144
+ New-Item -ItemType Directory -Path $SmokeRoot -Force | Out-Null
145
+ Set-Location $SmokeRoot
146
+ npm init -y | Out-Null
147
+
148
+ npm install "git+ssh://git@github.com:svenschaefer/elementary-assertions.git#vX.Y.Z"
149
+ node C:\code\elementary-assertions\scripts\release-smoke-check.js --repo-root C:\code\elementary-assertions --smoke-root $SmokeRoot --out-root (Join-Path $SmokeRoot "rendered")
150
+ npm ls elementary-assertions
151
+ ```
152
+
153
+ ## 9) npmjs publication step (`1.0.0+` only)
154
+
155
+ When shipping `1.0.0` (or later) to npmjs:
156
+
157
+ - Ensure `package.json` is publishable (`"private": false`).
158
+ - Keep `license`, `files`, and `exports` consistent with package contract tests.
159
+ - Publish from the release commit already tagged on `main`:
160
+
161
+ ```powershell
162
+ npm publish --access public
163
+ npm view elementary-assertions version
164
+ npm view elementary-assertions dist-tags.latest
165
+ ```
166
+
167
+ - Run a clean-install smoke check from npmjs package after publish (same smoke-root naming convention).
168
+
169
+ ## Failure rule
170
+
171
+ If anything is wrong after tagging, do not move or delete the tag.
172
+ Ship a new patch version with a new tag.
173
+
174
+ ## Release notes
175
+
176
+ Create/update release notes using:
177
+ - `docs/RELEASE_NOTES_TEMPLATE.md`
@@ -0,0 +1,159 @@
1
+ # elementary-assertions - Operational Guide
2
+
3
+ This document describes operational usage in the npm package context:
4
+ - CLI commands
5
+ - file I/O behavior
6
+ - service requirements (WTI)
7
+ - rendering defaults
8
+ - determinism rules
9
+ - repository-layout convenience options (seed-id, artifacts-root)
10
+
11
+ The authoritative interface remains the core library API. Tooling is a consumer layer and is view-only.
12
+
13
+ ## Runtime dependencies
14
+
15
+ Upstream linguistic pipeline (`linguistic-enricher`)
16
+ The default run path executes `linguistic-enricher` up to accepted relations (typically `relations_extracted`).
17
+
18
+ Wikipedia Title Index service (WTI)
19
+ A WTI endpoint is required for the default run path (`run --text` / `run --in`).
20
+
21
+ - the endpoint is passed to the upstream pipeline as `services["wikipedia-title-index"].endpoint`
22
+ - a fail-fast `GET /health` check is performed before execution
23
+ - positive upstream WTI evidence is required after pipeline execution (endpoint health alone is insufficient)
24
+ - elementary-assertions performs no Wikipedia lookups itself
25
+ - all wiki title signals are consumed as upstream evidence
26
+
27
+ Endpoint source precedence (CLI):
28
+ 1. `--wti-endpoint`
29
+ 2. environment `WIKIPEDIA_TITLE_INDEX_ENDPOINT`
30
+
31
+ If the endpoint is missing or blank, the CLI fails explicitly.
32
+
33
+ WTI health-check contract (default run path):
34
+ - Request: `GET /health`
35
+ - Success: HTTP `200` only
36
+ - Timeout: `2000` ms default
37
+ - Retries: none (fail-fast)
38
+ - Auth headers: none by default
39
+
40
+ ## CLI
41
+
42
+ The CLI is a thin wrapper around the library plus tooling modules.
43
+ CLI file-origin inputs preserve provenance metadata in output `sources.inputs[]`:
44
+ - `--in` -> `artifact: "seed.txt"` with `origin.kind: "file"`
45
+ - `--relations` -> `artifact: "seed.relations.yaml"` with `origin.kind: "file"`
46
+
47
+ ### Commands
48
+
49
+ - `run` - produce `elementary_assertions` output from text or file input
50
+ - `run` also supports offline/replay from relations input (`--relations`)
51
+ - `validate` - schema + integrity + determinism checks
52
+ - `render` - view-only rendering (txt or md) with layouts
53
+
54
+ Examples:
55
+
56
+ ```bash
57
+ npx elementary-assertions run --text "A webshop is an online store." --wti-endpoint http://localhost:3000 --wti-timeout-ms 2000 --out out.yaml
58
+ npx elementary-assertions run --in input.txt --wti-endpoint http://localhost:3000 --out out.yaml
59
+ npx elementary-assertions run --relations relations.yaml --out out.yaml
60
+ npx elementary-assertions validate --in out.yaml
61
+ npx elementary-assertions render --in out.yaml --format md --layout table --out out.md
62
+ ```
63
+
64
+ ### Generic I/O flags (preferred)
65
+
66
+ Run:
67
+ - exactly one of `--text <string>`, `--in <path>`, or `--relations <path>` is required; providing multiple is an explicit error, and providing none is an explicit error
68
+ - `--out <path>` (optional, defaults to stdout)
69
+ - `--timeout-ms <ms>` (optional)
70
+ - `--wti-endpoint <url>` (required unless env provides it for `--text` / `--in`; not required for `--relations`)
71
+ - `--wti-timeout-ms <ms>` (optional, default: 2000)
72
+
73
+ Validate:
74
+ - `--in <path>`
75
+
76
+ Render:
77
+ - `--in <path>`
78
+ - `--out <path>` (optional, defaults to stdout)
79
+ - `--format <txt|md>`
80
+ - `--layout <compact|readable|table|meaning>`
81
+ - `--segments <true|false>`
82
+ - `--mentions <true|false>`
83
+ - `--coverage <true|false>`
84
+ - `--debug-ids <true|false>`
85
+ - `--normalize-determiners <true|false>` (default: true)
86
+ - `--render-uncovered-delta <true|false>` (default: false)
87
+
88
+ Boolean flag parsing is strict:
89
+ - accepted lexical forms: `true|false` (case-insensitive)
90
+ - internal normalization target: lowercase (`true` or `false`)
91
+ - rejected forms: `1/0`, `yes/no`, and bare flags without explicit values
92
+
93
+ ### Validation error contract
94
+
95
+ - `elementary-assertions/validate` throws `ValidationError` for contract violations.
96
+ - `ValidationError.code` is stable and intended for consumer branching.
97
+ - Consumers should branch on `err.code`, not on free-text message matching.
98
+
99
+ ## Repository layout convenience (optional)
100
+
101
+ If you operate within a repo that follows the conventional seed layout, the CLI may offer convenience flags:
102
+
103
+ - `--seed-id <id>`
104
+ - `--artifacts-root <path>`
105
+
106
+ Conventional paths:
107
+ - input: `artifacts/<seed-id>/seed/seed.txt`
108
+ - output: `artifacts/<seed-id>/seed/seed.elementary-assertions.yaml`
109
+
110
+ These flags are convenience helpers only. They are not required for generic package usage.
111
+
112
+ ## Rendering
113
+
114
+ The renderer is view-only. It does not modify extraction results.
115
+
116
+ Layouts:
117
+ - `compact` - one-line assertions
118
+ - `readable` - multi-line blocks
119
+ - `table` - Markdown-safe table; includes inline evidence
120
+ - `meaning` - grouped semantic display for readability only (non-normative, view-only)
121
+
122
+ Renderer contract-lock scope:
123
+ - Contract-locked by parity tests: `txt/compact`, `md/table`, `md/meaning`.
124
+ - Other layout/format combinations are best-effort and may evolve.
125
+ - Release smoke currently verifies install-time wiring for: `txt/compact`, `md/table`, `md/meaning`.
126
+
127
+ Renderer integrity validation (before emitting output):
128
+ - tokens must exist for all mentions
129
+ - mentions must exist for all assertions
130
+ - evidence references must resolve
131
+ - coverage references must resolve
132
+
133
+ Rendered files are not specifications and carry no authoritative semantics.
134
+
135
+ ## Determinism rules (operational)
136
+
137
+ Deterministic ordering rules are enforced by core + validation tooling.
138
+ Scope:
139
+ - `runFromRelations(...)`: byte-stable for identical input and options within the same `elementary-assertions` version.
140
+ - `run` (upstream-running path): byte-stable only with pinned dependency versions (`elementary-assertions` and `linguistic-enricher`) and stable WTI service state/behavior for identical requests.
141
+
142
+ - Mention token order: by `token.i`
143
+ - Mention order: `(segment_id, span.start, span.end, kind, id)`
144
+ - Assertion order: `(segment_id, predicate head token.i, id)`
145
+ - View slot print order (renderer projection only): `actor`, `theme`, `attr`, `topic`, `location`, `other`
146
+ - Mention text reconstruction: single-space join of `token.surface`
147
+ - Segment text reconstruction: exact `canonical_text` slicing by segment span
148
+ - Identical input + identical flags produce byte-stable output within the determinism scope above
149
+
150
+ ## Non-goals (operational restatement)
151
+
152
+ Tooling and core MUST NOT:
153
+ - normalize into high-level semantic frames
154
+ - perform concept identity mapping
155
+ - convert to normative keywords
156
+ - invent missing roles or attachments
157
+ - use model calls or probabilistic filling
158
+
159
+ This package is the first formal meaning layer, not final semantic normalization.
@@ -0,0 +1,37 @@
1
+ # RELEASE_NOTES_TEMPLATE.md
2
+
3
+ Use this template for each release note entry.
4
+
5
+ ## Release
6
+
7
+ - Version: `vX.Y.Z`
8
+ - Date: `YYYY-MM-DD`
9
+ - Release commit: `<commit-sha>`
10
+ - Tag: `vX.Y.Z`
11
+
12
+ ## CI Evidence
13
+
14
+ - Workflow: `CI`
15
+ - Run id: `<github-actions-run-id>`
16
+ - Result: `success|failure`
17
+
18
+ ## Smoke Evidence
19
+
20
+ - Pre-tag smoke root: `C:\code\elementary-assertions-smoke-test\vX.Y.Z-pretag-smoke-<timestamp>`
21
+ - Post-tag smoke root: `C:\code\elementary-assertions-smoke-test\vX.Y.Z-posttag-smoke-<timestamp>`
22
+ - Pre-tag rendered root: `...\rendered`
23
+ - Post-tag rendered root: `...\rendered`
24
+
25
+ ## Contract Notes
26
+
27
+ - API surface check summary:
28
+ - CLI help check summary:
29
+ - Render parity check summary:
30
+
31
+ ## Changes Summary
32
+
33
+ - Added:
34
+ - Changed:
35
+ - Fixed:
36
+ - Removed:
37
+
@@ -0,0 +1,48 @@
1
+ # Repository Workflow Policies
2
+
3
+ This document defines repository workflow policies. These policies are not part of the npm package contract.
4
+
5
+ ## Timestamp invariants (repository workflow only)
6
+
7
+ When workflow automation writes rendered artifacts next to the YAML output, enforce:
8
+ - `seed.elementary-assertions.md` newer than `seed.elementary-assertions.yaml`
9
+ - `seed.elementary-assertions.meaning.md` newer than `seed.elementary-assertions.yaml`
10
+ - `seed.elementary-assertions.txt` newer than `seed.elementary-assertions.yaml`
11
+
12
+ These constraints apply to repository workflow only and do not define runtime behavior of `elementary-assertions` as a package.
13
+
14
+ ## Performance baseline (manual repo workflow)
15
+
16
+ Use the benchmark helper to keep a coarse local baseline for `runFromRelations` performance:
17
+
18
+ ```powershell
19
+ npm run benchmark:core
20
+ ```
21
+
22
+ Optional iterations override:
23
+
24
+ ```powershell
25
+ npm run benchmark:core -- 1000
26
+ ```
27
+
28
+ Optional dense scenario override:
29
+
30
+ ```powershell
31
+ npm run benchmark:core -- 1000 dense
32
+ ```
33
+
34
+ This benchmark is advisory for repo workflow only (trend watching) and is not a package contract gate.
35
+
36
+ ## CI gates (repo workflow)
37
+
38
+ Current CI workflow gates on:
39
+ - `npm install`
40
+ - `npm test`
41
+ - dev report script execution:
42
+ - `npm run dev:report:metrics`
43
+ - `npm run dev:report:hotspots`
44
+ - `npm run dev:report:maturity`
45
+ - `npm pack --dry-run`
46
+ - packed-tarball clean-install smoke check via `scripts/release-smoke-check.js`
47
+
48
+ These are repository quality gates and release hygiene checks, not package runtime contract.
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "elementary-assertions",
3
+ "version": "1.0.1",
4
+ "license": "MIT",
5
+ "private": false,
6
+ "type": "commonjs",
7
+ "main": "./src/index.js",
8
+ "exports": {
9
+ ".": "./src/index.js",
10
+ "./validate": "./src/validate/index.js",
11
+ "./render": "./src/render/index.js",
12
+ "./tools": "./src/tools/index.js",
13
+ "./schema": "./src/schema/seed.elementary-assertions.schema.json"
14
+ },
15
+ "bin": {
16
+ "elementary-assertions": "bin/elementary-assertions.js"
17
+ },
18
+ "files": [
19
+ "bin/",
20
+ "src/",
21
+ "docs/",
22
+ "README.md",
23
+ "CHANGELOG.md",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "test": "node --test \"test/**/*.test.js\"",
28
+ "test:unit": "node --test \"test/unit/**/*.test.js\"",
29
+ "test:integration": "node --test \"test/integration/**/*.test.js\"",
30
+ "benchmark:core": "node scripts/benchmark-run-from-relations.js",
31
+ "dev:check": "node scripts/dev-check.js",
32
+ "dev:report:metrics": "node scripts/dev-report-metrics.js",
33
+ "dev:report:hotspots": "node scripts/dev-report-fragment-hotspots.js",
34
+ "dev:report:maturity": "node scripts/dev-report-maturity.js",
35
+ "dev:diagnose:wiki-upstream": "node scripts/dev-diagnose-wiki-upstream.js",
36
+ "dev:diagnose:wti-wiring": "node scripts/dev-diagnose-wti-wiring.js",
37
+ "dev:diagnose:coverage-audit": "node scripts/dev-diagnose-coverage-audit.js",
38
+ "dev:reports": "node scripts/dev-reports.js"
39
+ },
40
+ "dependencies": {
41
+ "ajv": "^8.17.1",
42
+ "ajv-formats": "^3.0.1",
43
+ "js-yaml": "^4.1.1",
44
+ "linguistic-enricher": "1.1.35"
45
+ }
46
+ }
@@ -0,0 +1,44 @@
1
+ const { findSelector, normalizeIds } = require("./determinism");
2
+
3
+ function toAnnotationSummary(annotation) {
4
+ const tokenSelector = findSelector(annotation, "TokenSelector");
5
+ const textPos = findSelector(annotation, "TextPositionSelector");
6
+ return {
7
+ id: typeof annotation.id === "string" ? annotation.id : "",
8
+ kind: String(annotation.kind || ""),
9
+ status: String(annotation.status || ""),
10
+ label: typeof annotation.label === "string" ? annotation.label : undefined,
11
+ token_ids: tokenSelector && Array.isArray(tokenSelector.token_ids) ? normalizeIds(tokenSelector.token_ids) : [],
12
+ span:
13
+ textPos && textPos.span && typeof textPos.span.start === "number" && typeof textPos.span.end === "number"
14
+ ? { start: textPos.span.start, end: textPos.span.end }
15
+ : undefined,
16
+ source_names: normalizeIds(
17
+ (Array.isArray(annotation.sources) ? annotation.sources : [])
18
+ .map((s) => (s && typeof s.name === "string" ? s.name : ""))
19
+ .filter(Boolean)
20
+ ),
21
+ };
22
+ }
23
+
24
+ function buildAcceptedAnnotationsInventory(relationsSeed) {
25
+ const annotations = Array.isArray(relationsSeed && relationsSeed.annotations) ? relationsSeed.annotations : [];
26
+ return annotations
27
+ .filter((annotation) => annotation && annotation.status === "accepted")
28
+ .map(toAnnotationSummary)
29
+ .sort((a, b) => {
30
+ if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);
31
+ if ((a.span && a.span.start) !== (b.span && b.span.start)) {
32
+ return (a.span ? a.span.start : -1) - (b.span ? b.span.start : -1);
33
+ }
34
+ if ((a.span && a.span.end) !== (b.span && b.span.end)) {
35
+ return (a.span ? a.span.end : -1) - (b.span ? b.span.end : -1);
36
+ }
37
+ return a.id.localeCompare(b.id);
38
+ });
39
+ }
40
+
41
+ module.exports = {
42
+ toAnnotationSummary,
43
+ buildAcceptedAnnotationsInventory,
44
+ };