@volter/twin-standard 1.0.138 → 1.0.140

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.
@@ -1,9 +1,10 @@
1
+ import { type GradeOptions } from './grade.js';
1
2
  /** Every unit of a pack repository: each pack (a directory with a package.json) and each lane in it (a directory with
2
3
  * its own src/manifest.ts and no package.json). */
3
4
  export declare function unitsOf(repo: string): string[];
4
5
  export declare function laneRootFailures(dir: string): string[];
5
6
  /** Each unit's blocking form failures (empty when it may be in the repository). */
6
- export declare function p3Gate(units: string[]): Promise<Array<{
7
+ export declare function p3Gate(units: string[], opts?: Pick<GradeOptions, 'onCriterion'>): Promise<Array<{
7
8
  unit: string;
8
9
  failures: string[];
9
10
  }>>;
package/dist/src/gate.js CHANGED
@@ -96,7 +96,7 @@ export function laneRootFailures(dir) {
96
96
  return beyond.length ? [...failures, `kernel-contract: ${beyond.join('; ')}`] : failures;
97
97
  }
98
98
  /** Each unit's blocking form failures (empty when it may be in the repository). */
99
- export async function p3Gate(units) {
99
+ export async function p3Gate(units, opts = {}) {
100
100
  return withCheckoutFiles(async () => {
101
101
  const out = [];
102
102
  for (const unit of units) {
@@ -107,7 +107,7 @@ export async function p3Gate(units) {
107
107
  out.push({ unit, failures: laneRootFailures(unit) });
108
108
  continue;
109
109
  }
110
- const grades = await grade(unit, { static: true, sections: ['form'] });
110
+ const grades = await grade(unit, { static: true, sections: ['form'], ...opts });
111
111
  const form = Object.values(grades).flatMap((g) => g.criteria).filter((c) => !c.pass);
112
112
  out.push({ unit, failures: form.map((c) => `${c.id}: ${c.reason}`) });
113
113
  }
@@ -16,6 +16,11 @@ export interface StandardGrade {
16
16
  planned: string[];
17
17
  }
18
18
  export type GradeOptions = {
19
+ /** Report which native criterion is being read, without changing its result. */
20
+ onCriterion?: (unit: string, criterion: string, result?: {
21
+ pass: boolean;
22
+ reason: string;
23
+ }) => void;
19
24
  /** only the criteria that read the tree (the executed ones are the pack's typecheck and tests) */
20
25
  static?: boolean;
21
26
  /** only these sections (the catalog grades a submission's `form`) */
package/dist/src/grade.js CHANGED
@@ -20,6 +20,7 @@ export async function grade(dir, opts = {}) {
20
20
  continue;
21
21
  if (opts.sections && !opts.sections.includes(c.section))
22
22
  continue;
23
+ opts.onCriterion?.(name, c.id);
23
24
  let result;
24
25
  try {
25
26
  result = await c.check(unit);
@@ -27,6 +28,7 @@ export async function grade(dir, opts = {}) {
27
28
  catch (e) {
28
29
  result = { pass: false, reason: `the check threw: ${e.message.slice(0, 160)}` };
29
30
  }
31
+ opts.onCriterion?.(name, c.id, result);
30
32
  criteria.push({ id: c.id, section: c.section, asks: c.asks, ...result });
31
33
  }
32
34
  const met = criteria.filter((c) => c.pass).length;
@@ -335,7 +335,9 @@ const criteria = [
335
335
  const m = (await import(__rewriteRelativeImportExtension(join(src, 'manifest.ts')))).manifest;
336
336
  ids = new Set((m?.screens ?? []).map((x) => x.id));
337
337
  }
338
- catch { /* a manifest that does not load fails manifest-data and states-module */ }
338
+ catch (error) {
339
+ outside.push(`(manifest.ts does not load: ${error instanceof Error ? error.message : String(error)})`);
340
+ }
339
341
  // screens/shared.tsx: what two or more of the pack's screens share (its page shell, its skin), itself no screen.
340
342
  // Without the manifest's screen ids no screen file can be judged: that is said, never every screen listed outside.
341
343
  if (ids === undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/twin-standard",
3
- "version": "1.0.138",
3
+ "version": "1.0.140",
4
4
  "description": "The Protocol 3 standard for Volter twin packs: the criteria a pack is graded by, the grader, the gate a pack repository and the twin catalog run on every change and submission, and the spec derivation the grade checks against. Pin a version: every place a pack is judged judges by that standard.",
5
5
  "keywords": [
6
6
  "twin",
@@ -75,7 +75,7 @@
75
75
  "yaml": "2.9.0"
76
76
  },
77
77
  "peerDependencies": {
78
- "@volter/world-core": "3.0.146",
78
+ "@volter/world-core": "3.0.148",
79
79
  "@volter/world-runtime": "*",
80
80
  "playwright": "^1.63.0"
81
81
  },
package/src/gate.ts CHANGED
@@ -16,7 +16,7 @@ import { spawnSync } from 'node:child_process';
16
16
  import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
17
17
  import { join } from 'node:path';
18
18
  import ts from 'typescript';
19
- import { grade } from './grade.ts';
19
+ import { grade, type GradeOptions } from './grade.ts';
20
20
  import { withCheckoutFiles } from './protocol-3.ts';
21
21
  import { isPackArtifact } from './pack-files.ts';
22
22
 
@@ -85,7 +85,7 @@ export function laneRootFailures(dir: string): string[] {
85
85
  }
86
86
 
87
87
  /** Each unit's blocking form failures (empty when it may be in the repository). */
88
- export async function p3Gate(units: string[]): Promise<Array<{ unit: string; failures: string[] }>> {
88
+ export async function p3Gate(units: string[], opts: Pick<GradeOptions, 'onCriterion'> = {}): Promise<Array<{ unit: string; failures: string[] }>> {
89
89
  return withCheckoutFiles(async () => {
90
90
  const out: Array<{ unit: string; failures: string[] }> = [];
91
91
  for (const unit of units) {
@@ -93,7 +93,7 @@ export async function p3Gate(units: string[]): Promise<Array<{ unit: string; fai
93
93
  // front (architecture, "Pack layout", "Other wires: lanes")
94
94
  const lanesOnly = !hasOwnSurface(unit) && readdirSync(unit).some((n) => existsSync(join(unit, n, 'src', 'manifest.ts')));
95
95
  if (lanesOnly || !existsSync(join(unit, 'src', 'manifest.ts'))) { out.push({ unit, failures: laneRootFailures(unit) }); continue; }
96
- const grades = await grade(unit, { static: true, sections: ['form'] });
96
+ const grades = await grade(unit, { static: true, sections: ['form'], ...opts });
97
97
  const form = Object.values(grades).flatMap((g) => g.criteria).filter((c) => !c.pass);
98
98
  out.push({ unit, failures: form.map((c) => `${c.id}: ${c.reason}`) });
99
99
  }
package/src/grade.ts CHANGED
@@ -14,6 +14,8 @@ export interface CriterionGrade { id: string; section: string; asks: string; pas
14
14
  export interface StandardGrade { grade: number; met: number; total: number; criteria: CriterionGrade[]; planned: string[] }
15
15
 
16
16
  export type GradeOptions = {
17
+ /** Report which native criterion is being read, without changing its result. */
18
+ onCriterion?: (unit: string, criterion: string, result?: { pass: boolean; reason: string }) => void;
17
19
  /** only the criteria that read the tree (the executed ones are the pack's typecheck and tests) */
18
20
  static?: boolean;
19
21
  /** only these sections (the catalog grades a submission's `form`) */
@@ -36,8 +38,10 @@ export async function grade(dir: string, opts: GradeOptions = {}): Promise<Recor
36
38
  for (const c of standard.criteria) {
37
39
  if (opts.static && c.executed) continue;
38
40
  if (opts.sections && !opts.sections.includes(c.section)) continue;
41
+ opts.onCriterion?.(name, c.id);
39
42
  let result;
40
43
  try { result = await c.check(unit); } catch (e) { result = { pass: false, reason: `the check threw: ${(e as Error).message.slice(0, 160)}` }; }
44
+ opts.onCriterion?.(name, c.id, result);
41
45
  criteria.push({ id: c.id, section: c.section, asks: c.asks, ...result });
42
46
  }
43
47
  const met = criteria.filter((c) => c.pass).length;
package/src/protocol-3.ts CHANGED
@@ -301,7 +301,7 @@ const criteria: Criterion[] = [
301
301
  try {
302
302
  const m = ((await import(join(src, 'manifest.ts'))) as { manifest?: { screens?: Array<{ id: string }> } }).manifest;
303
303
  ids = new Set((m?.screens ?? []).map((x) => x.id));
304
- } catch { /* a manifest that does not load fails manifest-data and states-module */ }
304
+ } catch (error) { outside.push(`(manifest.ts does not load: ${error instanceof Error ? error.message : String(error)})`); }
305
305
  // screens/shared.tsx: what two or more of the pack's screens share (its page shell, its skin), itself no screen.
306
306
  // Without the manifest's screen ids no screen file can be judged: that is said, never every screen listed outside.
307
307
  if (ids === undefined) outside.push('(src/screens/ unjudged: manifest.ts does not load)');