@hyperfixi/testing-framework 2.9.4 → 2.10.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/CHANGELOG.md CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.10.0] - 2026-08-01
11
+
12
+ Full notes: [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases/tag/v2.10.0).
13
+
14
+ Highlights: `swap`/`process`/`morph … using view transition` across all 24
15
+ languages (#870, #873, #875), typed command registration (#869, #871),
16
+ `tell`/`process` parser fixes (#861, #872), the R1 role-fidelity burn-down
17
+ (#864, #867, #868, #874, #878), and guards for the remaining hand-maintained
18
+ CI package lists (#862, #865).
19
+
20
+ ## [2.9.0] - 2026-07-25
21
+
22
+ > **Gap note:** 2.9.1 through 2.9.4 shipped without entries in this file; their
23
+ > details live in [GitHub Releases](https://github.com/codetalcott/hyperfixi/releases).
24
+
10
25
  ### ⚠ BREAKING (types)
11
26
 
12
27
  - **Domain renderers return `string | null`.** `renderSQL`, `renderJSX`, `renderTodo`,
@@ -379,7 +394,12 @@ _Synchronized version release. See git history for details._
379
394
  - npm access token stored in GitHub Secrets
380
395
  - 2FA recommended for npm organization
381
396
 
382
- [Unreleased]: https://github.com/codetalcott/hyperfixi/compare/v2.4.0...HEAD
397
+ [Unreleased]: https://github.com/codetalcott/hyperfixi/compare/v2.10.0...HEAD
398
+ [2.10.0]: https://github.com/codetalcott/hyperfixi/compare/v2.9.0...v2.10.0
399
+ [2.9.0]: https://github.com/codetalcott/hyperfixi/compare/v2.8.0...v2.9.0
400
+ [2.8.0]: https://github.com/codetalcott/hyperfixi/compare/v2.5.1...v2.8.0
401
+ [2.5.1]: https://github.com/codetalcott/hyperfixi/compare/v2.5.0...v2.5.1
402
+ [2.5.0]: https://github.com/codetalcott/hyperfixi/compare/v2.4.0...v2.5.0
383
403
  [2.4.0]: https://github.com/codetalcott/hyperfixi/compare/v2.3.1...v2.4.0
384
404
  [2.3.1]: https://github.com/codetalcott/hyperfixi/compare/v2.3.0...v2.3.1
385
405
  [2.3.0]: https://github.com/codetalcott/hyperfixi/compare/v2.2.1...v2.3.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperfixi/testing-framework",
3
- "version": "2.9.4",
3
+ "version": "2.10.0",
4
4
  "description": "Cross-platform behavior testing suite for LokaScript applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -57,10 +57,10 @@
57
57
  "author": "LokaScript Contributors",
58
58
  "license": "MIT",
59
59
  "dependencies": {
60
- "@hyperfixi/core": "^2.9.4",
61
- "@hyperfixi/patterns-reference": "^2.9.4",
62
- "@lokascript/i18n": "^2.9.4",
63
- "@lokascript/semantic": "^2.9.4",
60
+ "@hyperfixi/core": "^2.10.0",
61
+ "@hyperfixi/patterns-reference": "^2.10.0",
62
+ "@lokascript/i18n": "^2.10.0",
63
+ "@lokascript/semantic": "^2.10.0",
64
64
  "diff": "^8.0.3",
65
65
  "esbuild": "^0.28.0",
66
66
  "happy-dom": "^20.10.6",
@@ -87,16 +87,21 @@ describe('shipped-examples execution gate', () => {
87
87
  }, 240_000);
88
88
 
89
89
  it('walks pages and compares handlers (sanity: extraction and both engines working)', () => {
90
- // Floors well below current values (55 / 333 / 162 / 74) but far above
90
+ // Floors well below current values (48 / 261 / 122 / 52) but far above
91
91
  // zero: a broken walk, extractor, or engine bootstrap fails loudly here
92
92
  // instead of making assertions 2-3 vacuously pass.
93
- expect(result.pages).toBeGreaterThan(40);
94
- expect(result.handlers).toBeGreaterThan(250);
95
- expect(result.compared.length).toBeGreaterThan(120);
93
+ //
94
+ // Calibrated against the git-TRACKED corpus — the sweep ignores untracked
95
+ // examples/ dirs, so these numbers are the same on every machine and in
96
+ // CI. (The original floors were measured on a working tree with four
97
+ // gitignored dirs present and failed every clean checkout — #862.)
98
+ expect(result.pages).toBeGreaterThan(35);
99
+ expect(result.handlers).toBeGreaterThan(200);
100
+ expect(result.compared.length).toBeGreaterThan(90);
96
101
  // Vacuous (empty-vs-empty) pairs are NOT parity evidence — the floor is on
97
102
  // real, non-empty signature matches.
98
103
  const realMatches = result.compared.filter(c => c.match && !c.vacuous).length;
99
- expect(realMatches).toBeGreaterThan(60);
104
+ expect(realMatches).toBeGreaterThan(40);
100
105
  });
101
106
 
102
107
  it('has no NEW divergence from upstream outside the allowlist', () => {
@@ -45,6 +45,7 @@
45
45
 
46
46
  import fs from 'node:fs';
47
47
  import path from 'node:path';
48
+ import { execFileSync } from 'node:child_process';
48
49
  import { createHash } from 'node:crypto';
49
50
  import { createRequire } from 'node:module';
50
51
  import { fileURLToPath, pathToFileURL } from 'node:url';
@@ -168,22 +169,33 @@ export function triggerEventOf(source: string): string | null {
168
169
  return m ? (m[1] ?? null) : null;
169
170
  }
170
171
 
171
- function walkHtml(dir: string, acc: string[] = []): string[] {
172
- let entries: fs.Dirent[];
173
- try {
174
- entries = fs.readdirSync(dir, { withFileTypes: true });
175
- } catch {
176
- return acc;
177
- }
178
- for (const entry of entries) {
179
- if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name.startsWith('.')) {
180
- continue;
181
- }
182
- const full = path.join(dir, entry.name);
183
- if (entry.isDirectory()) walkHtml(full, acc);
184
- else if (entry.name.endsWith('.html')) acc.push(full);
185
- }
186
- return acc;
172
+ /**
173
+ * Git-TRACKED .html files under `root` (repo-relative), as absolute paths.
174
+ *
175
+ * Tracked, not on-disk, because the corpus must be the SHIPPED tree: four
176
+ * `examples/` dirs are gitignored (experiments/, playground/,
177
+ * vite-plugin-test/, vite-plugin-multilingual/), and the disk walk this
178
+ * replaced counted whatever happened to be on the machine. That is how the
179
+ * gate's sanity floors and allowlist got calibrated against handlers that
180
+ * were never shipped — and why it failed on every clean checkout the first
181
+ * time CI ran it (#862). `git ls-files` sees the same corpus everywhere.
182
+ *
183
+ * git being unavailable is a THROW, not a fallback to the disk walk — a
184
+ * silent fallback would resurrect the corpus drift this exists to kill.
185
+ * A tracked file missing from disk (an uncommitted local deletion) is
186
+ * skipped: the working tree is mid-edit, and in CI checkout == index.
187
+ */
188
+ function trackedHtml(repoRoot: string, root: string): string[] {
189
+ const out = execFileSync('git', ['ls-files', '-z', '--', root], {
190
+ cwd: repoRoot,
191
+ encoding: 'utf8',
192
+ maxBuffer: 64 * 1024 * 1024,
193
+ });
194
+ return out
195
+ .split('\0')
196
+ .filter(rel => rel.endsWith('.html'))
197
+ .map(rel => path.join(repoRoot, rel))
198
+ .filter(full => fs.existsSync(full));
187
199
  }
188
200
 
189
201
  /** Extract the page's `[_]` handlers in document order. */
@@ -398,9 +410,9 @@ async function runHandlerOnEngine(
398
410
  }
399
411
 
400
412
  /**
401
- * The sweep: walk `examples/**`, extract handlers, apply the fair-denominator
402
- * filters (each skip reasoned), and execute every eligible handler on both
403
- * engines.
413
+ * The sweep: walk the git-tracked `examples/**` corpus, extract handlers,
414
+ * apply the fair-denominator filters (each skip reasoned), and execute every
415
+ * eligible handler on both engines.
404
416
  */
405
417
  export async function runShippedExamplesExecution(opts?: {
406
418
  roots?: string[];
@@ -417,7 +429,7 @@ export async function runShippedExamplesExecution(opts?: {
417
429
  let handlers = 0;
418
430
 
419
431
  for (const root of roots) {
420
- for (const full of walkHtml(path.join(repoRoot, root))) {
432
+ for (const full of trackedHtml(repoRoot, root)) {
421
433
  const rel = path.relative(repoRoot, full);
422
434
  const html = fs.readFileSync(full, 'utf8');
423
435
  const pageHandlers = extractHandlers(rel, html);