@orkestrel/scaffold 0.0.87 → 0.0.88

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.
@@ -473,7 +473,7 @@ Direct declaration populations are dense data arrays too. A sparse literal is re
473
473
 
474
474
  The precedence below assumes a readable node. A readable malformed keyword is ignored and widens according to the listed rule; a keyword access, enumeration, or recursive traversal that throws is not malformed schema vocabulary and is refused with `ContractError { code: 'structure', context: { shape: 'schema' } }`.
475
475
 
476
- `schemaToShape`'s precedence, top-down at each node (every keyword read is type-guarded; a malformed keyword is IGNORED, not thrown): (1) `enum` (≥ 1 string/number/boolean entry) → `literalShape`. (2) `oneOf` (≥ 1 record entry) → `oneOfShape` over the recursed variants, PROVIDED the record-entry count is at or under `INFER_BREADTH_LIMIT`; over the cap, building a subset union would be strictly narrower than the schema's full union, so the node widens to `rawShape` instead of sampling a subset. (3) `anyOf` identically → `unionShape`, with the same over-cap widen-to-`rawShape` rule rather than a subset union. (4) `type: 'string'/'number'/'integer'/'boolean'/'null'` → the matching primitive shape, with `minLength`/`maxLength`/`minimum`/`maximum` bounds kept only when well-formed and non-contradictory (a malformed or `min > max` pair drops to unbounded — widening, never narrowing). (5) `type: 'array'` → `arrayShape`, recursing into a record-valued `items` (else `rawShape`), with `minItems`/`maxItems` bounds. (6) `type: 'object'` (or no `type`/`enum`/`oneOf`/`anyOf` but a record `properties`) → `objectShape`: a property not listed in `required` is wrapped `optionalShape`; `additionalProperties: false` closes, a record value recurses into it (`objectShape` validates extras against that shape directly — no widening needed), and `true` / ABSENT / anything malformed leaves it open (`true`) — absent matches JSON Schema's own default, and `valueToSchema` / `samplesToSchema` always emit the keyword explicitly, so an absent value only arises from a hand-written schema. When `properties` has MORE keys than `INFER_BREADTH_LIMIT`, the schema's own `additionalProperties` is OVERRIDDEN and forced open (`true`) regardless of `false` or a record value — a key dropped past the sampling cap was never checked against a closed or record-valued rest shape, so forcing the object open is the only sound widening — mirroring the inferers' own `truncated ? true : !closed` rule. (7) Everything else — `{}`, an unrecognized `type`, exhausted depth (`INFER_DEPTH_LIMIT`), or a cyclic re-encounter — widens to `rawShape` (NOT `jsonShape`: `{}` is JSON Schema’s accept-anything schema, and `rawShape` is its exact inverse — its guard accepts every defined value and it re-emits `{}` verbatim, whereas `jsonShape`’s `isJSONValue` guard would reject the exotic originals (`Map`, `Set`, a class instance, a function, `NaN`) whose inferred schema is exactly `{}`). A `WeakMap` memo (keyed by schema-node identity + remaining depth), mirroring the inferers, guards a shared-reference schema DAG against exponential re-conversion. **Its key does not carry the active-ancestor set, and that is observable**: a node first reached through a CYCLIC path is cached with the shape it widened to at the back-edge, and a later ACYCLIC path is served that cached shape instead of descending further. Two schemas differing only in which sibling holds the cyclic node therefore convert to different shapes. Every such difference is a WIDENING — an accept-anything `rawShape` — so no value is wrongly rejected and the round-trip law is unaffected; what it costs is determinism ACROSS graphs, not within one, since the same input always converts the same way. This is stated as a limit rather than repaired because both repairs (dropping the ancestor set, or threading a cycle-affected flag through three public signatures) change the published surface.
476
+ `schemaToShape`'s precedence, top-down at each node (every keyword read is type-guarded; a malformed keyword is IGNORED, not thrown): (1) `enum` (≥ 1 string/number/boolean entry) → `literalShape`. (2) `oneOf` (≥ 1 record entry) → `oneOfShape` over the recursed variants, PROVIDED the record-entry count is at or under `INFER_BREADTH_LIMIT`; over the cap, building a subset union would be strictly narrower than the schema's full union, so the node widens to `rawShape` instead of sampling a subset. (3) `anyOf` identically → `unionShape`, with the same over-cap widen-to-`rawShape` rule rather than a subset union. (4) An array-valued `type` → `unionShape` over each distinct recognized name, converting `{ ...schema, type: member }` at the same depth so bounds, `items`, `properties`, and `description` apply to each member. A single distinct name returns its shape directly. An empty array or any unrecognized member widens the whole node to `rawShape`, even when `properties` is present; no member is dropped to narrow the union. The distinct-name count is checked against `INFER_BREADTH_LIMIT`; the recognized vocabulary fits below that cap, so repeated names do not exhaust it. This is runtime conversion support: the declared `JSONSchema.type` remains a single name because direct raw-schema validation supports only that vocabulary. (5) `type: 'string'/'number'/'integer'/'boolean'/'null'` → the matching primitive shape, with `minLength`/`maxLength`/`minimum`/`maximum` bounds kept only when well-formed and non-contradictory (a malformed or `min > max` pair drops to unbounded — widening, never narrowing). (6) `type: 'array'` → `arrayShape`, recursing into a record-valued `items` (else `rawShape`), with `minItems`/`maxItems` bounds. (7) `type: 'object'` (or no `type`/`enum`/`oneOf`/`anyOf` but a record `properties`) → `objectShape`: a property not listed in `required` is wrapped `optionalShape`; `additionalProperties: false` closes, a record value recurses into it (`objectShape` validates extras against that shape directly — no widening needed), and `true` / ABSENT / anything malformed leaves it open (`true`) — absent matches JSON Schema's own default, and `valueToSchema` / `samplesToSchema` always emit the keyword explicitly, so an absent value only arises from a hand-written schema. When `properties` has MORE keys than `INFER_BREADTH_LIMIT`, the schema's own `additionalProperties` is OVERRIDDEN and forced open (`true`) regardless of `false` or a record value — a key dropped past the sampling cap was never checked against a closed or record-valued rest shape, so forcing the object open is the only sound widening — mirroring the inferers' own `truncated ? true : !closed` rule. (8) Everything else — `{}`, an unrecognized `type`, exhausted depth (`INFER_DEPTH_LIMIT`), or a cyclic re-encounter — widens to `rawShape` (NOT `jsonShape`: `{}` is JSON Schema’s accept-anything schema, and `rawShape` is its exact inverse — its guard accepts every defined value and it re-emits `{}` verbatim, whereas `jsonShape`’s `isJSONValue` guard would reject the exotic originals (`Map`, `Set`, a class instance, a function, `NaN`) whose inferred schema is exactly `{}`). A `WeakMap` memo (keyed by schema-node identity + remaining depth), mirroring the inferers, guards a shared-reference schema DAG against exponential re-conversion. **Its key does not carry the active-ancestor set, and that is observable**: a node first reached through a CYCLIC path is cached with the shape it widened to at the back-edge, and a later ACYCLIC path is served that cached shape instead of descending further. Two schemas differing only in which sibling holds the cyclic node therefore convert to different shapes. Every such difference is a WIDENING — an accept-anything `rawShape` — so no value is wrongly rejected and the round-trip law is unaffected; what it costs is determinism ACROSS graphs, not within one, since the same input always converts the same way. This is stated as a limit rather than repaired because both repairs (dropping the ancestor set, or threading a cycle-affected flag through three public signatures) change the published surface.
477
477
 
478
478
  **Round-trip law:** for any READABLE value `v` — including `NaN`, `±Infinity`, a `Map`, a `Set`, a class instance, a function, a symbol, a bigint, and readable cyclic hosts — `compileGuard(schemaToShape(valueToSchema(v)))(v) === true`, with widening as the ONLY source of looseness, never narrowing. An unreadable host is refused before the law produces a schema. The law otherwise retains its three limits: JSON absence, `Date` serialization, and unstable reads between inference and validation. A widened node cannot be auto-generated: `createContract(schemaToShape(x)).generate()` throws when the conversion widened anywhere; its parser returns `undefined` for readable invalid input and propagates the shared coded refusal when a required read fails.
479
479
 
@@ -280,7 +280,7 @@
280
280
  "storage": "agents/skills/orkestrel-harden/scripts/discovery.ts",
281
281
  "destination": ".agents/skills/orkestrel-harden/scripts/discovery.ts",
282
282
  "executable": false,
283
- "digest": "fad5a6093f42f02c9fc0ee955d7f94fede22f3c69f8d049c80dfb779cda89f39"
283
+ "digest": "06128d912f79de527522075e7ebb3ccf24be864fad1015f4db5e456744201f7d"
284
284
  },
285
285
  {
286
286
  "storage": "agents/skills/orkestrel-journey/SKILL.md",
@@ -496,7 +496,7 @@
496
496
  "storage": "claude/agents/orkestrel.md",
497
497
  "destination": ".claude/agents/orkestrel.md",
498
498
  "executable": false,
499
- "digest": "02c8bfcfa26ee23e91cef48771e5a3038bdb8d4018f0510bef5cd17db82f5893"
499
+ "digest": "565dee392dced6c3e1e632295739eeb9465ca4828d26c18d02b57f106fdc5f38"
500
500
  },
501
501
  {
502
502
  "storage": "claude/agents/planner.md",
@@ -538,7 +538,7 @@
538
538
  "storage": "claude/rules/architecture.md",
539
539
  "destination": ".claude/rules/architecture.md",
540
540
  "executable": false,
541
- "digest": "6d8936e85dd3c01e915a91a5b7bb9aaafa9b09a899b0cf8ff6bb8f9e8ff8e629"
541
+ "digest": "5fb146c532f74910f5afa88070a7da03fd782c2f420f07d9581d2635d768807b"
542
542
  },
543
543
  {
544
544
  "storage": "claude/rules/browser.md",
@@ -772,7 +772,7 @@
772
772
  "storage": "configs/policy.ts",
773
773
  "destination": "configs/policy.ts",
774
774
  "executable": false,
775
- "digest": "de238996682d2eb35a40941214dc5c1d6427c57159afc3055f243bf93a5e8f83"
775
+ "digest": "bf4ba1f29a04040f9bf953ad4641af08a2b0662e2dd6d6f8f3d7ae8282587158"
776
776
  },
777
777
  {
778
778
  "storage": "cursor/mcp.json",
@@ -862,7 +862,7 @@
862
862
  "storage": "guides/browser.md",
863
863
  "destination": "guides/browser.md",
864
864
  "executable": false,
865
- "digest": "2bd000da61376666df785bb4f51f3e7988ac821f29d9b3174abc8b716d503086"
865
+ "digest": "4dd8f7377b165d840dd3060f0af955458fff193612f833aadd04d37c34734afe"
866
866
  },
867
867
  {
868
868
  "storage": "guides/budget.md",
@@ -886,7 +886,7 @@
886
886
  "storage": "guides/contract.md",
887
887
  "destination": "guides/contract.md",
888
888
  "executable": false,
889
- "digest": "2aa2ebffe3cb466e0c6845a8bbd1cc81f16e526f952f938430e3cfcb700cdee5"
889
+ "digest": "5339c1ba3a1ffe9ffe5415d70bd4868a73f9ef2661c4ce97e22dc8a30054569c"
890
890
  },
891
891
  {
892
892
  "storage": "guides/csv.md",
@@ -1168,7 +1168,7 @@
1168
1168
  "storage": "tests/config.test.ts",
1169
1169
  "destination": "tests/config.test.ts",
1170
1170
  "executable": false,
1171
- "digest": "395ac8782ae05c678c13e460de654e32140125f159fcb882053340ab193bb5f3"
1171
+ "digest": "5cb647597fb27442d2be85a75b446805dd33d05b9ca93808595497ab7587387f"
1172
1172
  },
1173
1173
  {
1174
1174
  "storage": "tests/policy.test.ts",
@@ -2144,5 +2144,5 @@
2144
2144
  ]
2145
2145
  }
2146
2146
  ],
2147
- "digest": "5c7e45000c69dd7340b13478851fcfaeaa972f3f25311e230def9b740dc82e15"
2147
+ "digest": "e53117186fbcf5d34fce9dcecef09fc8581335b11561f9ccd264a0d9f7fb52f3"
2148
2148
  }
File without changes
File without changes
File without changes
File without changes
@@ -1889,6 +1889,12 @@ createSomething({
1889
1889
  code: 'function parseValue(): void {}\nexport { parseValue as coerceValue }',
1890
1890
  errors: [{ messageId: 'parser' }],
1891
1891
  },
1892
+ {
1893
+ name: 'rejects an unprefixed exported import alias [membership: parsers.ts functions whose name does not start with parse]',
1894
+ filename: 'app/edge/parsers.ts',
1895
+ code: 'export import coerceValue = Values.parseValue',
1896
+ errors: [{ messageId: 'parser' }],
1897
+ },
1892
1898
  ],
1893
1899
  })
1894
1900
 
@@ -1924,6 +1930,12 @@ createSomething({
1924
1930
  code: 'function createValue(): void {}\nexport { createValue as buildValue }',
1925
1931
  errors: [{ messageId: 'factory' }],
1926
1932
  },
1933
+ {
1934
+ name: 'rejects an unprefixed exported import alias [membership: factories.ts functions whose name does not start with create]',
1935
+ filename: 'app/edge/factories.ts',
1936
+ code: 'export import buildValue = Values.createValue',
1937
+ errors: [{ messageId: 'factory' }],
1938
+ },
1927
1939
  ],
1928
1940
  })
1929
1941
 
@@ -1954,6 +1966,16 @@ createSomething({
1954
1966
  filename: 'src/edge/plugins.ts',
1955
1967
  code: 'function createModalPlugin(): void {}\nexport { createModalPlugin as createDialogPlugin }',
1956
1968
  },
1969
+ {
1970
+ name: 'accepts an exported import alias in the plugin form',
1971
+ filename: 'src/edge/plugins.ts',
1972
+ code: 'export import createDialogPlugin = Factories.createModalPlugin',
1973
+ },
1974
+ {
1975
+ name: 'accepts an exported import alias outside plugins.ts',
1976
+ filename: 'src/edge/helpers.ts',
1977
+ code: 'export import registerModal = Factories.createModalPlugin',
1978
+ },
1957
1979
  ],
1958
1980
  invalid: [
1959
1981
  {
@@ -2034,6 +2056,18 @@ createSomething({
2034
2056
  code: 'export function createplugin(): void {}',
2035
2057
  errors: [{ messageId: 'plugin' }],
2036
2058
  },
2059
+ {
2060
+ name: 'rejects an underscore in the entity segment [membership: plugins.ts functions whose name is not create…Plugin or create…Plugins]',
2061
+ filename: 'src/edge/plugins.ts',
2062
+ code: 'export function createModal_Plugin(): void {}',
2063
+ errors: [{ messageId: 'plugin' }],
2064
+ },
2065
+ {
2066
+ name: 'rejects an exported import alias outside the plugin form [membership: plugins.ts functions whose name is not create…Plugin or create…Plugins]',
2067
+ filename: 'src/edge/plugins.ts',
2068
+ code: 'export import registerModal = Factories.createModalPlugin',
2069
+ errors: [{ messageId: 'plugin' }],
2070
+ },
2037
2071
  ],
2038
2072
  })
2039
2073
 
@@ -4,7 +4,7 @@ let _orkestrel_template = require("@orkestrel/template");
4
4
  let _orkestrel_emitter = require("@orkestrel/emitter");
5
5
  var package_default = {
6
6
  name: "@orkestrel/scaffold",
7
- version: "0.0.87",
7
+ version: "0.0.88",
8
8
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
9
9
  keywords: [
10
10
  "audit",
@@ -103,7 +103,7 @@ var package_default = {
103
103
  },
104
104
  devDependencies: {
105
105
  "@microsoft/api-extractor": "^7.59.3",
106
- "@orkestrel/browser": "^0.0.20",
106
+ "@orkestrel/browser": "^0.0.21",
107
107
  "@orkestrel/guide": "^0.0.24",
108
108
  "@orkestrel/html": "^0.0.12",
109
109
  "@orkestrel/probe": "^0.0.19",
@@ -900,6 +900,7 @@ function isNamedPlugin(plugin: PluginOption): plugin is { name: string } {
900
900
  instances: [{ browser: 'chromium', headless: true }],
901
901
  },
902
902
  fileParallelism: false,
903
+ sequence: { groupOrder: 1 },
903
904
  },
904
905
  }
905
906
  return mergeOverride(project, override)
@@ -959,6 +960,7 @@ export function srcVue(override?: UserConfig): UserConfig {
959
960
  instances: [{ browser: 'chromium', headless: true }],
960
961
  },
961
962
  fileParallelism: false,
963
+ sequence: { groupOrder: 1 },
962
964
  },
963
965
  }
964
966
  return mergeOverride(project, override)
@@ -1001,6 +1003,7 @@ export function srcBrowser(override?: UserConfig): UserConfig {
1001
1003
  instances: [{ browser: 'chromium', headless: true }],
1002
1004
  },
1003
1005
  fileParallelism: false,
1006
+ sequence: { groupOrder: 1 },
1004
1007
  },
1005
1008
  }
1006
1009
  return mergeOverride(project, override)
@@ -1135,6 +1138,7 @@ export function srcBin(override?: UserConfig): UserConfig {
1135
1138
  instances: [{ browser: 'chromium', headless: true }],
1136
1139
  },
1137
1140
  fileParallelism: false,
1141
+ sequence: { groupOrder: 1 },
1138
1142
  },
1139
1143
  }
1140
1144
  return mergeOverride(project, override)
@@ -1428,6 +1432,7 @@ export function service(override?: UserConfig): UserConfig {
1428
1432
  testTimeout: 120_000,
1429
1433
  hookTimeout: 120_000,
1430
1434
  fileParallelism: false,
1435
+ sequence: { groupOrder: 1 },
1431
1436
  },
1432
1437
  }
1433
1438
  return mergeOverride(project, override)
@@ -1444,6 +1449,7 @@ export function service(override?: UserConfig): UserConfig {
1444
1449
  testTimeout: 120_000,
1445
1450
  hookTimeout: 120_000,
1446
1451
  fileParallelism: false,
1452
+ sequence: { groupOrder: 1 },
1447
1453
  },
1448
1454
  }
1449
1455
  return mergeOverride(project, override)
@@ -1464,6 +1470,7 @@ export function probe(override?: UserConfig): UserConfig {
1464
1470
  environment: 'node',
1465
1471
  browser: { enabled: false },
1466
1472
  fileParallelism: false,
1473
+ sequence: { groupOrder: 1 },
1467
1474
  pool: 'threads',
1468
1475
  benchmark: { include: ['tmp/probes/**/*.test.ts', 'tests/**/*.test.ts'] },
1469
1476
  },