@volter/twin-standard 1.0.34 → 1.0.35

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.
@@ -526,7 +526,10 @@ export async function createPack(args) {
526
526
  console.log(`create-pack: wrote ${join(dir, 'src', 'fetch.ts')}`);
527
527
  // a pack's own index (a lane's is the vendor's to name): the descriptor with what the kernel derives from the surface
528
528
  if (existsSync(join(dir, 'package.json'))) {
529
- const vendor = parseExactJson(readFileSync(join(dir, 'package.json'), 'utf8')).name.replace(/^@volter\/twin-/, '');
529
+ const { manifest } = await import(__rewriteRelativeImportExtension(join(dir, 'src', 'manifest.ts')));
530
+ const vendor = manifest?.vendor;
531
+ if (!vendor || !/^[a-z][a-z0-9-]*$/.test(vendor))
532
+ throw new Error('Pack manifest must declare its vendor identity independently of the npm package name');
530
533
  writeFileSync(join(dir, 'src', 'index.ts'), packIndexFile(dir, vendor));
531
534
  console.log(`create-pack: wrote ${join(dir, 'src', 'index.ts')}`);
532
535
  // what the grade's typecheck compiles: a pack made before init wrote it gets it here
@@ -6,7 +6,7 @@ export type PublishedGate = {
6
6
  failures: string[];
7
7
  }>;
8
8
  };
9
- /** The vendor a package twins: its name without its scope and the `twin-` prefix (`@volter/twin-supabase` is supabase). */
9
+ /** Conventional-name fallback for artifacts predating generated identity facts; not an independent package identity. */
10
10
  export declare const vendorOfPackage: (name: string) => string;
11
11
  /** The conformance of `spec` as the registry serves it: the published tarball with its own dependencies installed,
12
12
  * served and read against the kernel (kernelDir). */
@@ -8,7 +8,7 @@ import { tmpdir } from 'node:os';
8
8
  import { dirname, join } from 'node:path';
9
9
  import { conformance } from "./conformance.js";
10
10
  import { p3Gate } from "./gate.js";
11
- /** The vendor a package twins: its name without its scope and the `twin-` prefix (`@volter/twin-supabase` is supabase). */
11
+ /** Conventional-name fallback for artifacts predating generated identity facts; not an independent package identity. */
12
12
  export const vendorOfPackage = (name) => name.replace(/^@[^/]+\//, '').replace(/^twin-/, '');
13
13
  /** `spec` (`<name>@<version>`) as the registry serves it, unpacked under its vendor's name in a scratch directory, handed
14
14
  * to `use`; throws when it cannot be fetched or unpacked. */
@@ -23,7 +23,15 @@ async function withPublished(spec, opts, use) {
23
23
  if (untar.status !== 0)
24
24
  throw new Error(`${spec}: the tarball does not unpack (${String(untar.stderr).trim()})`);
25
25
  const name = JSON.parse(readFileSync(join(tmp, 'package', 'package.json'), 'utf8')).name;
26
- const dir = join(tmp, vendorOfPackage(name));
26
+ const factsFile = join(tmp, 'package', 'generated', 'pack-facts.json');
27
+ const facts = existsSync(factsFile) ? JSON.parse(readFileSync(factsFile, 'utf8')) : undefined;
28
+ const vendors = Object.keys(facts?.packs ?? {});
29
+ if (facts && vendors.length !== 1)
30
+ throw new Error(`${spec}: generated facts must identify one vendor`);
31
+ const vendor = facts ? vendors[0] : vendorOfPackage(name);
32
+ if (!/^[a-z][a-z0-9-]*$/.test(vendor))
33
+ throw new Error(`${spec}: invalid vendor identity`);
34
+ const dir = join(tmp, vendor);
27
35
  renameSync(join(tmp, 'package'), dir);
28
36
  return await use(dir, tmp);
29
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/twin-standard",
3
- "version": "1.0.34",
3
+ "version": "1.0.35",
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",
@@ -70,7 +70,7 @@
70
70
  "yaml": "2.9.0"
71
71
  },
72
72
  "peerDependencies": {
73
- "@volter/world-core": "3.0.42",
73
+ "@volter/world-core": "3.0.43",
74
74
  "@volter/world-runtime": "*",
75
75
  "playwright": "^1.63.0"
76
76
  },
@@ -488,7 +488,9 @@ export async function createPack(args: string[]): Promise<void> {
488
488
  console.log(`create-pack: wrote ${join(dir, 'src', 'fetch.ts')}`);
489
489
  // a pack's own index (a lane's is the vendor's to name): the descriptor with what the kernel derives from the surface
490
490
  if (existsSync(join(dir, 'package.json'))) {
491
- const vendor = (parseExactJson(readFileSync(join(dir, 'package.json'), 'utf8')) as { name: string }).name.replace(/^@volter\/twin-/, '');
491
+ const { manifest } = await import(join(dir, 'src', 'manifest.ts')) as { manifest?: { vendor?: string } };
492
+ const vendor = manifest?.vendor;
493
+ if (!vendor || !/^[a-z][a-z0-9-]*$/.test(vendor)) throw new Error('Pack manifest must declare its vendor identity independently of the npm package name');
492
494
  writeFileSync(join(dir, 'src', 'index.ts'), packIndexFile(dir, vendor));
493
495
  console.log(`create-pack: wrote ${join(dir, 'src', 'index.ts')}`);
494
496
  // what the grade's typecheck compiles: a pack made before init wrote it gets it here
package/src/published.ts CHANGED
@@ -11,7 +11,7 @@ import { p3Gate } from './gate.ts';
11
11
 
12
12
  export type PublishedGate = { spec: string; failures: Array<{ unit: string; failures: string[] }> };
13
13
 
14
- /** The vendor a package twins: its name without its scope and the `twin-` prefix (`@volter/twin-supabase` is supabase). */
14
+ /** Conventional-name fallback for artifacts predating generated identity facts; not an independent package identity. */
15
15
  export const vendorOfPackage = (name: string): string => name.replace(/^@[^/]+\//, '').replace(/^twin-/, '');
16
16
 
17
17
  /** `spec` (`<name>@<version>`) as the registry serves it, unpacked under its vendor's name in a scratch directory, handed
@@ -25,7 +25,13 @@ async function withPublished<T>(spec: string, opts: { registry?: string }, use:
25
25
  const untar = spawnSync('tar', ['-xzf', join(tmp, tarball), '-C', tmp], { encoding: 'utf8' });
26
26
  if (untar.status !== 0) throw new Error(`${spec}: the tarball does not unpack (${String(untar.stderr).trim()})`);
27
27
  const name = (JSON.parse(readFileSync(join(tmp, 'package', 'package.json'), 'utf8')) as { name: string }).name;
28
- const dir = join(tmp, vendorOfPackage(name));
28
+ const factsFile = join(tmp, 'package', 'generated', 'pack-facts.json');
29
+ const facts = existsSync(factsFile) ? JSON.parse(readFileSync(factsFile, 'utf8')) as { packs?: Record<string, unknown> } : undefined;
30
+ const vendors = Object.keys(facts?.packs ?? {});
31
+ if (facts && vendors.length !== 1) throw new Error(`${spec}: generated facts must identify one vendor`);
32
+ const vendor = facts ? vendors[0]! : vendorOfPackage(name);
33
+ if (!/^[a-z][a-z0-9-]*$/.test(vendor)) throw new Error(`${spec}: invalid vendor identity`);
34
+ const dir = join(tmp, vendor);
29
35
  renameSync(join(tmp, 'package'), dir);
30
36
  return await use(dir, tmp);
31
37
  } finally {