@orkestrel/scaffold 0.0.82 → 0.0.83

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.
@@ -119,7 +119,7 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
119
119
  tests: Readonly<{
120
120
  journey: "import {\n\tACCESSIBLE_ROLES,\n\tcreatePortfolio,\n\texpandCaptures,\n\tisRendered,\n\treadRefusal,\n\treadStyle,\n} from '@orkestrel/test/browser'\n{{imports}}import { page } from 'vitest/browser'\nimport { describe, expect, inject, it } from 'vitest'\n\nconst VARIANT = inject('variant')\nconst VARIANTS = inject('variants')\nconst CAPTURE = inject('capture')\n\ndescribe('{{application}} arrival journey', () => {\n\tit('proves the declared arrival families', async () => {\n\t\tconst families = new Set(['Journey', 'Refusal', 'Matrix', ...(CAPTURE ? ['Capture'] : [])])\n\t\tconst proven = new Set<string>()\n\t\tconst states = ['{{application}}-arrival']\n\t\tconst placed = new Set<string>()\n\t\tconst portfolio = createPortfolio({\n\t\t\tstates,\n\t\t\tvariants: VARIANTS,\n\t\t\tvariant: VARIANT,\n\t\t\tdirectory: '../../../tmp/captures/states',\n\t\t\tenabled: CAPTURE,\n\t\t})\n{{mount}}\t\ttry {\n{{arrival}}\t\t\tconst heading = page\n\t\t\t\t.getByRole('heading', {\n\t\t\t\t\tname: {{heading}},\n\t\t\t\t\texact: true,\n\t\t\t\t\tlevel: 1,\n\t\t\t\t})\n\t\t\t\t.element()\n\t\t\texpect(isRendered(heading)).toBe(true)\n\t\t\tproven.add('Journey')\n\t\t\tawait portfolio.place('{{application}}-arrival')\n\t\t\tplaced.add('{{application}}-arrival')\n\n\t\t\tfor (const role of ACCESSIBLE_ROLES) expect(page.getByRole(role).elements()).toEqual([])\n\t\t\texpect(readRefusal('Continue')).toBe(\n\t\t\t\t'No interactive element has the accessible name \"Continue\"',\n\t\t\t)\n\t\t\tproven.add('Refusal')\n\n\t\t\tconst measured = new Set<string>()\n\t\t\tfor (const variant of VARIANTS) {\n\t\t\t\tawait page.viewport(variant.width, variant.height)\n\t\t\t\texpect(readStyle(heading, 'display')).toBe('block')\n\t\t\t\texpect(window.innerWidth).toBe(variant.width)\n\t\t\t\tmeasured.add(variant.name)\n\t\t\t}\n\t\t\texpect(measured).toEqual(new Set(VARIANTS.map(({ name }) => name)))\n\t\t\tproven.add('Matrix')\n\n\t\t\tconst files = expandCaptures(states, VARIANTS)\n\t\t\texpect(portfolio.files).toEqual(files)\n\t\t\texpect(new Set(files).size).toBe(states.length * VARIANTS.length)\n\t\t\texpect(placed).toEqual(new Set(states))\n\t\t\tconst expected = CAPTURE\n\t\t\t\t? expandCaptures(\n\t\t\t\t\t\tstates,\n\t\t\t\t\t\tVARIANTS.filter(({ name }) => name === VARIANT),\n\t\t\t\t\t)\n\t\t\t\t: []\n\t\t\texpect(portfolio.paths.map((path) => path.replaceAll('\\\\', '/').split('/').at(-1))).toEqual(\n\t\t\t\texpected,\n\t\t\t)\n\t\t\tif (CAPTURE) proven.add('Capture')\n\t\t\texpect(proven).toEqual(families)\n\t\t} finally {\n{{cleanup}}\t\t\tconst variant = VARIANTS.find(({ name }) => name === VARIANT)\n\t\t\tif (variant !== undefined) await page.viewport(variant.width, variant.height)\n\t\t}\n\t})\n})\n";
121
121
  browser: "import type { JourneyVariant } from '@orkestrel/test'\n\ndeclare module 'vitest' {\n\texport interface ProvidedContext {\n\t\treadonly variant: string\n\t\treadonly variants: readonly JourneyVariant[]\n\t\treadonly capture: boolean\n\t}\n}\n";
122
- sheet: "import sheet from '/dist/src/{{name}}/index.css?raw'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from '{{setup}}'\n\ndescribe('{{name}} entry', () => {\n\tit('opens with the declared cascade order', () => {\n\t\tconst adopted = adoptSheet(sheet)\n\t\ttry {\n\t\t\texpect(adopted.sheet.cssRules[0]?.cssText).toBe(\n\t\t\t\t'@layer theme, reset, base, elements, components, utilities;',\n\t\t\t)\n\t\t\texpect(readLayerNames(adopted.sheet).slice(0, 6)).toEqual([\n\t\t\t\t'theme',\n\t\t\t\t'reset',\n\t\t\t\t'base',\n\t\t\t\t'elements',\n\t\t\t\t'components',\n\t\t\t\t'utilities',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n})\n";
122
+ sheet: "import sheet from '{{root}}dist/src/{{name}}/index.css?raw'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from '{{setup}}'\n\ndescribe('{{name}} entry', () => {\n\tit('opens with the declared cascade order', () => {\n\t\tconst adopted = adoptSheet(sheet)\n\t\ttry {\n\t\t\texpect(adopted.sheet.cssRules[0]?.cssText).toBe(\n\t\t\t\t'@layer theme, reset, base, elements, components, utilities;',\n\t\t\t)\n\t\t\texpect(readLayerNames(adopted.sheet).slice(0, 6)).toEqual([\n\t\t\t\t'theme',\n\t\t\t\t'reset',\n\t\t\t\t'base',\n\t\t\t\t'elements',\n\t\t\t\t'components',\n\t\t\t\t'utilities',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n})\n";
123
123
  styles: Readonly<{
124
124
  module: "/** Carries a CSSOM rule and its enclosing layer. */\nexport interface SheetEntry {\n\treadonly rule: CSSRule\n\treadonly layer: string | undefined\n}\n\n/** Describes an adopted stylesheet and its idempotent release operation. */\nexport interface SheetAdoption {\n\treadonly sheet: CSSStyleSheet\n\trelease(): void\n}\n\n/**\n * Adopts CSS text into the document with an idempotent release operation.\n * @param text - The compiled sheet text.\n * @returns The adopted sheet and its release operation.\n * @example\n * ```ts\n * const adopted = adoptSheet('.sample { color: red }')\n * adopted.release()\n * ```\n */\nexport function adoptSheet(text: string): SheetAdoption {\n\tconst sheet = new CSSStyleSheet()\n\tsheet.replaceSync(text)\n\tdocument.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]\n\treturn {\n\t\tsheet,\n\t\trelease: () => {\n\t\t\tdocument.adoptedStyleSheets = document.adoptedStyleSheets.filter(\n\t\t\t\t(candidate) => candidate !== sheet,\n\t\t\t)\n\t\t},\n\t}\n}\n\n/**\n * Reads layer statements and blocks in declaration order, including repeated names.\n * @param sheet - The parsed sheet.\n * @returns Qualified layer names, with an empty name for an anonymous layer.\n * @example\n * ```ts\n * readLayerNames(new CSSStyleSheet()) // []\n * ```\n */\nexport function readLayerNames(sheet: CSSStyleSheet): readonly string[] {\n\tconst pending: SheetEntry[] = Array.from(sheet.cssRules, (rule) => ({\n\t\trule,\n\t\tlayer: undefined,\n\t})).reverse()\n\tconst names: string[] = []\n\twhile (pending.length > 0) {\n\t\tconst entry = pending.pop()\n\t\tif (entry === undefined) break\n\t\tconst { rule, layer } = entry\n\t\tconst declared =\n\t\t\trule instanceof CSSLayerStatementRule\n\t\t\t\t? rule.nameList\n\t\t\t\t: rule instanceof CSSLayerBlockRule\n\t\t\t\t\t? [rule.name]\n\t\t\t\t\t: []\n\t\tfor (const name of declared) names.push(layer === undefined ? name : layer + '.' + name)\n\t\tif (!(rule instanceof CSSGroupingRule)) continue\n\t\tconst parent =\n\t\t\trule instanceof CSSLayerBlockRule\n\t\t\t\t? layer === undefined\n\t\t\t\t\t? rule.name\n\t\t\t\t\t: layer + '.' + rule.name\n\t\t\t\t: layer\n\t\tfor (const child of Array.from(rule.cssRules).reverse()) {\n\t\t\tpending.push({ rule: child, layer: parent })\n\t\t}\n\t}\n\treturn names\n}\n";
125
125
  proof: "import type { SheetAdoption } from './setupStyles.js'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from './setupStyles.js'\n\ndescribe('CSSOM instruments', () => {\n\tit('adopts and releases only its own sheet, including repeated release', () => {\n\t\tconst previous = [...document.adoptedStyleSheets]\n\t\tconst first: SheetAdoption = adoptSheet('.sample { color: red }')\n\t\ttry {\n\t\t\tconst second = adoptSheet('.other { display: block }')\n\t\t\ttry {\n\t\t\t\texpect(document.adoptedStyleSheets).toEqual([...previous, first.sheet, second.sheet])\n\t\t\t\texpect(first.sheet.cssRules.length).toBe(1)\n\t\t\t\tfirst.release()\n\t\t\t\tfirst.release()\n\t\t\t\texpect(document.adoptedStyleSheets).toEqual([...previous, second.sheet])\n\t\t\t} finally {\n\t\t\t\tsecond.release()\n\t\t\t}\n\t\t} finally {\n\t\t\tfirst.release()\n\t\t}\n\t\texpect(document.adoptedStyleSheets).toEqual(previous)\n\t})\n\n\tit('reads statements, blocks, nested conditions, and anonymous layers in order', () => {\n\t\tconst adopted = adoptSheet(\n\t\t\t'@layer first, second; @layer first { @media all { @layer nested {} } } @layer {}',\n\t\t)\n\t\ttry {\n\t\t\texpect(readLayerNames(adopted.sheet)).toEqual([\n\t\t\t\t'first',\n\t\t\t\t'second',\n\t\t\t\t'first',\n\t\t\t\t'first.nested',\n\t\t\t\t'',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n\n\tit('returns no layer names for an empty sheet or an unlayered rule', () => {\n\t\tconst sheet = new CSSStyleSheet()\n\t\texpect(readLayerNames(sheet)).toEqual([])\n\t\tsheet.replaceSync('.sample { color: red }')\n\t\texpect(readLayerNames(sheet)).toEqual([])\n\t})\n})\n";
@@ -375,6 +375,12 @@ export declare function blueprintToConfigArtifacts(blueprint: Blueprint): readon
375
375
  * the peer's floor states what consumers may supply rather than what this workspace
376
376
  * develops against.
377
377
  *
378
+ * A workspace that renders a surface receives {@link BROWSE_DEV_DEPENDENCIES}: a browser
379
+ * environment on either axis, a sheet, or themes. A framework face counts without a clause of
380
+ * its own, because a face is selected only on an axis that carries a browser environment.
381
+ * A browser setup runtime alone receives nothing, because it renders no surface for `browse`
382
+ * to drive.
383
+ *
378
384
  * A peer is declared here as well as under `peerDependencies`, because a peer is
379
385
  * not installed by the workspace that declares it and developing against one
380
386
  * requires it present. A runtime dependency is the opposite case and is removed:
@@ -878,6 +884,16 @@ export declare function blueprintToTestArtifacts(blueprint: Blueprint): readonly
878
884
  */
879
885
  export declare function blueprintToWritableScripts(blueprint: Blueprint): readonly ManifestScript[];
880
886
 
887
+ /**
888
+ * Names the development dependency a browser or styles surface adds.
889
+ *
890
+ * @remarks
891
+ * The package ships the `browse` binary, an MCP server that drives a rendered page and records
892
+ * journeys, and `.claude/rules/quality.md` § Instruments names its registration.
893
+ * `blueprintToDevDependencies` names the blueprints that receive it.
894
+ */
895
+ export declare const BROWSE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
896
+
881
897
  /** Represents a browser framework and its physically occupied axes. */
882
898
  export declare interface BrowserExtension {
883
899
  readonly surface: 'browser';
@@ -119,7 +119,7 @@ export declare const ARTIFACT_TEMPLATES: Readonly<{
119
119
  tests: Readonly<{
120
120
  journey: "import {\n\tACCESSIBLE_ROLES,\n\tcreatePortfolio,\n\texpandCaptures,\n\tisRendered,\n\treadRefusal,\n\treadStyle,\n} from '@orkestrel/test/browser'\n{{imports}}import { page } from 'vitest/browser'\nimport { describe, expect, inject, it } from 'vitest'\n\nconst VARIANT = inject('variant')\nconst VARIANTS = inject('variants')\nconst CAPTURE = inject('capture')\n\ndescribe('{{application}} arrival journey', () => {\n\tit('proves the declared arrival families', async () => {\n\t\tconst families = new Set(['Journey', 'Refusal', 'Matrix', ...(CAPTURE ? ['Capture'] : [])])\n\t\tconst proven = new Set<string>()\n\t\tconst states = ['{{application}}-arrival']\n\t\tconst placed = new Set<string>()\n\t\tconst portfolio = createPortfolio({\n\t\t\tstates,\n\t\t\tvariants: VARIANTS,\n\t\t\tvariant: VARIANT,\n\t\t\tdirectory: '../../../tmp/captures/states',\n\t\t\tenabled: CAPTURE,\n\t\t})\n{{mount}}\t\ttry {\n{{arrival}}\t\t\tconst heading = page\n\t\t\t\t.getByRole('heading', {\n\t\t\t\t\tname: {{heading}},\n\t\t\t\t\texact: true,\n\t\t\t\t\tlevel: 1,\n\t\t\t\t})\n\t\t\t\t.element()\n\t\t\texpect(isRendered(heading)).toBe(true)\n\t\t\tproven.add('Journey')\n\t\t\tawait portfolio.place('{{application}}-arrival')\n\t\t\tplaced.add('{{application}}-arrival')\n\n\t\t\tfor (const role of ACCESSIBLE_ROLES) expect(page.getByRole(role).elements()).toEqual([])\n\t\t\texpect(readRefusal('Continue')).toBe(\n\t\t\t\t'No interactive element has the accessible name \"Continue\"',\n\t\t\t)\n\t\t\tproven.add('Refusal')\n\n\t\t\tconst measured = new Set<string>()\n\t\t\tfor (const variant of VARIANTS) {\n\t\t\t\tawait page.viewport(variant.width, variant.height)\n\t\t\t\texpect(readStyle(heading, 'display')).toBe('block')\n\t\t\t\texpect(window.innerWidth).toBe(variant.width)\n\t\t\t\tmeasured.add(variant.name)\n\t\t\t}\n\t\t\texpect(measured).toEqual(new Set(VARIANTS.map(({ name }) => name)))\n\t\t\tproven.add('Matrix')\n\n\t\t\tconst files = expandCaptures(states, VARIANTS)\n\t\t\texpect(portfolio.files).toEqual(files)\n\t\t\texpect(new Set(files).size).toBe(states.length * VARIANTS.length)\n\t\t\texpect(placed).toEqual(new Set(states))\n\t\t\tconst expected = CAPTURE\n\t\t\t\t? expandCaptures(\n\t\t\t\t\t\tstates,\n\t\t\t\t\t\tVARIANTS.filter(({ name }) => name === VARIANT),\n\t\t\t\t\t)\n\t\t\t\t: []\n\t\t\texpect(portfolio.paths.map((path) => path.replaceAll('\\\\', '/').split('/').at(-1))).toEqual(\n\t\t\t\texpected,\n\t\t\t)\n\t\t\tif (CAPTURE) proven.add('Capture')\n\t\t\texpect(proven).toEqual(families)\n\t\t} finally {\n{{cleanup}}\t\t\tconst variant = VARIANTS.find(({ name }) => name === VARIANT)\n\t\t\tif (variant !== undefined) await page.viewport(variant.width, variant.height)\n\t\t}\n\t})\n})\n";
121
121
  browser: "import type { JourneyVariant } from '@orkestrel/test'\n\ndeclare module 'vitest' {\n\texport interface ProvidedContext {\n\t\treadonly variant: string\n\t\treadonly variants: readonly JourneyVariant[]\n\t\treadonly capture: boolean\n\t}\n}\n";
122
- sheet: "import sheet from '/dist/src/{{name}}/index.css?raw'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from '{{setup}}'\n\ndescribe('{{name}} entry', () => {\n\tit('opens with the declared cascade order', () => {\n\t\tconst adopted = adoptSheet(sheet)\n\t\ttry {\n\t\t\texpect(adopted.sheet.cssRules[0]?.cssText).toBe(\n\t\t\t\t'@layer theme, reset, base, elements, components, utilities;',\n\t\t\t)\n\t\t\texpect(readLayerNames(adopted.sheet).slice(0, 6)).toEqual([\n\t\t\t\t'theme',\n\t\t\t\t'reset',\n\t\t\t\t'base',\n\t\t\t\t'elements',\n\t\t\t\t'components',\n\t\t\t\t'utilities',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n})\n";
122
+ sheet: "import sheet from '{{root}}dist/src/{{name}}/index.css?raw'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from '{{setup}}'\n\ndescribe('{{name}} entry', () => {\n\tit('opens with the declared cascade order', () => {\n\t\tconst adopted = adoptSheet(sheet)\n\t\ttry {\n\t\t\texpect(adopted.sheet.cssRules[0]?.cssText).toBe(\n\t\t\t\t'@layer theme, reset, base, elements, components, utilities;',\n\t\t\t)\n\t\t\texpect(readLayerNames(adopted.sheet).slice(0, 6)).toEqual([\n\t\t\t\t'theme',\n\t\t\t\t'reset',\n\t\t\t\t'base',\n\t\t\t\t'elements',\n\t\t\t\t'components',\n\t\t\t\t'utilities',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n})\n";
123
123
  styles: Readonly<{
124
124
  module: "/** Carries a CSSOM rule and its enclosing layer. */\nexport interface SheetEntry {\n\treadonly rule: CSSRule\n\treadonly layer: string | undefined\n}\n\n/** Describes an adopted stylesheet and its idempotent release operation. */\nexport interface SheetAdoption {\n\treadonly sheet: CSSStyleSheet\n\trelease(): void\n}\n\n/**\n * Adopts CSS text into the document with an idempotent release operation.\n * @param text - The compiled sheet text.\n * @returns The adopted sheet and its release operation.\n * @example\n * ```ts\n * const adopted = adoptSheet('.sample { color: red }')\n * adopted.release()\n * ```\n */\nexport function adoptSheet(text: string): SheetAdoption {\n\tconst sheet = new CSSStyleSheet()\n\tsheet.replaceSync(text)\n\tdocument.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]\n\treturn {\n\t\tsheet,\n\t\trelease: () => {\n\t\t\tdocument.adoptedStyleSheets = document.adoptedStyleSheets.filter(\n\t\t\t\t(candidate) => candidate !== sheet,\n\t\t\t)\n\t\t},\n\t}\n}\n\n/**\n * Reads layer statements and blocks in declaration order, including repeated names.\n * @param sheet - The parsed sheet.\n * @returns Qualified layer names, with an empty name for an anonymous layer.\n * @example\n * ```ts\n * readLayerNames(new CSSStyleSheet()) // []\n * ```\n */\nexport function readLayerNames(sheet: CSSStyleSheet): readonly string[] {\n\tconst pending: SheetEntry[] = Array.from(sheet.cssRules, (rule) => ({\n\t\trule,\n\t\tlayer: undefined,\n\t})).reverse()\n\tconst names: string[] = []\n\twhile (pending.length > 0) {\n\t\tconst entry = pending.pop()\n\t\tif (entry === undefined) break\n\t\tconst { rule, layer } = entry\n\t\tconst declared =\n\t\t\trule instanceof CSSLayerStatementRule\n\t\t\t\t? rule.nameList\n\t\t\t\t: rule instanceof CSSLayerBlockRule\n\t\t\t\t\t? [rule.name]\n\t\t\t\t\t: []\n\t\tfor (const name of declared) names.push(layer === undefined ? name : layer + '.' + name)\n\t\tif (!(rule instanceof CSSGroupingRule)) continue\n\t\tconst parent =\n\t\t\trule instanceof CSSLayerBlockRule\n\t\t\t\t? layer === undefined\n\t\t\t\t\t? rule.name\n\t\t\t\t\t: layer + '.' + rule.name\n\t\t\t\t: layer\n\t\tfor (const child of Array.from(rule.cssRules).reverse()) {\n\t\t\tpending.push({ rule: child, layer: parent })\n\t\t}\n\t}\n\treturn names\n}\n";
125
125
  proof: "import type { SheetAdoption } from './setupStyles.js'\nimport { describe, expect, it } from 'vitest'\nimport { adoptSheet, readLayerNames } from './setupStyles.js'\n\ndescribe('CSSOM instruments', () => {\n\tit('adopts and releases only its own sheet, including repeated release', () => {\n\t\tconst previous = [...document.adoptedStyleSheets]\n\t\tconst first: SheetAdoption = adoptSheet('.sample { color: red }')\n\t\ttry {\n\t\t\tconst second = adoptSheet('.other { display: block }')\n\t\t\ttry {\n\t\t\t\texpect(document.adoptedStyleSheets).toEqual([...previous, first.sheet, second.sheet])\n\t\t\t\texpect(first.sheet.cssRules.length).toBe(1)\n\t\t\t\tfirst.release()\n\t\t\t\tfirst.release()\n\t\t\t\texpect(document.adoptedStyleSheets).toEqual([...previous, second.sheet])\n\t\t\t} finally {\n\t\t\t\tsecond.release()\n\t\t\t}\n\t\t} finally {\n\t\t\tfirst.release()\n\t\t}\n\t\texpect(document.adoptedStyleSheets).toEqual(previous)\n\t})\n\n\tit('reads statements, blocks, nested conditions, and anonymous layers in order', () => {\n\t\tconst adopted = adoptSheet(\n\t\t\t'@layer first, second; @layer first { @media all { @layer nested {} } } @layer {}',\n\t\t)\n\t\ttry {\n\t\t\texpect(readLayerNames(adopted.sheet)).toEqual([\n\t\t\t\t'first',\n\t\t\t\t'second',\n\t\t\t\t'first',\n\t\t\t\t'first.nested',\n\t\t\t\t'',\n\t\t\t])\n\t\t} finally {\n\t\t\tadopted.release()\n\t\t}\n\t})\n\n\tit('returns no layer names for an empty sheet or an unlayered rule', () => {\n\t\tconst sheet = new CSSStyleSheet()\n\t\texpect(readLayerNames(sheet)).toEqual([])\n\t\tsheet.replaceSync('.sample { color: red }')\n\t\texpect(readLayerNames(sheet)).toEqual([])\n\t})\n})\n";
@@ -375,6 +375,12 @@ export declare function blueprintToConfigArtifacts(blueprint: Blueprint): readon
375
375
  * the peer's floor states what consumers may supply rather than what this workspace
376
376
  * develops against.
377
377
  *
378
+ * A workspace that renders a surface receives {@link BROWSE_DEV_DEPENDENCIES}: a browser
379
+ * environment on either axis, a sheet, or themes. A framework face counts without a clause of
380
+ * its own, because a face is selected only on an axis that carries a browser environment.
381
+ * A browser setup runtime alone receives nothing, because it renders no surface for `browse`
382
+ * to drive.
383
+ *
378
384
  * A peer is declared here as well as under `peerDependencies`, because a peer is
379
385
  * not installed by the workspace that declares it and developing against one
380
386
  * requires it present. A runtime dependency is the opposite case and is removed:
@@ -878,6 +884,16 @@ export declare function blueprintToTestArtifacts(blueprint: Blueprint): readonly
878
884
  */
879
885
  export declare function blueprintToWritableScripts(blueprint: Blueprint): readonly ManifestScript[];
880
886
 
887
+ /**
888
+ * Names the development dependency a browser or styles surface adds.
889
+ *
890
+ * @remarks
891
+ * The package ships the `browse` binary, an MCP server that drives a rendered page and records
892
+ * journeys, and `.claude/rules/quality.md` § Instruments names its registration.
893
+ * `blueprintToDevDependencies` names the blueprints that receive it.
894
+ */
895
+ export declare const BROWSE_DEV_DEPENDENCIES: Readonly<Record<string, string>>;
896
+
881
897
  /** Represents a browser framework and its physically occupied axes. */
882
898
  export declare interface BrowserExtension {
883
899
  readonly surface: 'browser';
@@ -3,7 +3,7 @@ import { fillTemplate } from "@orkestrel/template";
3
3
  import { Emitter } from "@orkestrel/emitter";
4
4
  var package_default = {
5
5
  name: "@orkestrel/scaffold",
6
- version: "0.0.82",
6
+ version: "0.0.83",
7
7
  description: "Scaffold workspaces with commands: new, audit, repair, catalog, and overwrite.",
8
8
  keywords: [
9
9
  "audit",
@@ -94,16 +94,17 @@ var package_default = {
94
94
  },
95
95
  dependencies: {
96
96
  "@orkestrel/console": "^0.0.15",
97
- "@orkestrel/contract": "^0.0.18",
97
+ "@orkestrel/contract": "^0.0.19",
98
98
  "@orkestrel/emitter": "^0.0.11",
99
- "@orkestrel/markdown": "^0.0.16",
99
+ "@orkestrel/markdown": "^0.0.17",
100
100
  "@orkestrel/process": "^0.0.14",
101
101
  "@orkestrel/template": "^0.0.9"
102
102
  },
103
103
  devDependencies: {
104
104
  "@microsoft/api-extractor": "^7.59.3",
105
- "@orkestrel/guide": "^0.0.21",
106
- "@orkestrel/html": "^0.0.11",
105
+ "@orkestrel/browser": "^0.0.20",
106
+ "@orkestrel/guide": "^0.0.22",
107
+ "@orkestrel/html": "^0.0.12",
107
108
  "@orkestrel/probe": "^0.0.19",
108
109
  "@orkestrel/test": "^0.0.24",
109
110
  "@types/node": "^26.6.3",
@@ -112,7 +113,7 @@ var package_default = {
112
113
  "oxlint": "^1.86.0",
113
114
  "playwright": "^1.63.0",
114
115
  "typescript": "^6.0.3",
115
- "vite": "^8.3.1",
116
+ "vite": "^8.3.2",
116
117
  "vitest": "^4.1.11"
117
118
  },
118
119
  engines: { "node": ">=22.18.0" }
@@ -661,6 +662,15 @@ var SOURCE_BROWSER_DEV_DEPENDENCIES = Object.freeze({
661
662
  "@vitest/browser-playwright": package_default.devDependencies["@vitest/browser-playwright"],
662
663
  playwright: package_default.devDependencies.playwright
663
664
  });
665
+ /**
666
+ * Names the development dependency a browser or styles surface adds.
667
+ *
668
+ * @remarks
669
+ * The package ships the `browse` binary, an MCP server that drives a rendered page and records
670
+ * journeys, and `.claude/rules/quality.md` § Instruments names its registration.
671
+ * `blueprintToDevDependencies` names the blueprints that receive it.
672
+ */
673
+ var BROWSE_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/browser": package_default.devDependencies["@orkestrel/browser"] });
664
674
  /** Names the development dependency every private `app` environment adds. */
665
675
  var APP_DEV_DEPENDENCIES = Object.freeze({ "@orkestrel/contract": package_default.dependencies["@orkestrel/contract"] });
666
676
  /** Lists the development dependencies a private browser application adds. */
@@ -2301,7 +2311,7 @@ declare module 'vitest' {
2301
2311
  }
2302
2312
  }
2303
2313
  `,
2304
- sheet: `import sheet from '/dist/src/{{name}}/index.css?raw'
2314
+ sheet: `import sheet from '{{root}}dist/src/{{name}}/index.css?raw'
2305
2315
  import { describe, expect, it } from 'vitest'
2306
2316
  import { adoptSheet, readLayerNames } from '{{setup}}'
2307
2317
 
@@ -5634,6 +5644,12 @@ function srcToExports(src) {
5634
5644
  * the peer's floor states what consumers may supply rather than what this workspace
5635
5645
  * develops against.
5636
5646
  *
5647
+ * A workspace that renders a surface receives {@link BROWSE_DEV_DEPENDENCIES}: a browser
5648
+ * environment on either axis, a sheet, or themes. A framework face counts without a clause of
5649
+ * its own, because a face is selected only on an axis that carries a browser environment.
5650
+ * A browser setup runtime alone receives nothing, because it renders no surface for `browse`
5651
+ * to drive.
5652
+ *
5637
5653
  * A peer is declared here as well as under `peerDependencies`, because a peer is
5638
5654
  * not installed by the workspace that declares it and developing against one
5639
5655
  * requires it present. A runtime dependency is the opposite case and is removed:
@@ -5656,8 +5672,10 @@ function srcToExports(src) {
5656
5672
  */
5657
5673
  function blueprintToDevDependencies(blueprint) {
5658
5674
  const sheets = blueprintToSheets(blueprint).length > 0 || blueprint.themes;
5675
+ const rendered = blueprint.src.includes("browser") || blueprint.app.includes("browser") || sheets;
5659
5676
  const merged = {
5660
5677
  ...BASE_DEV_DEPENDENCIES,
5678
+ ...rendered ? BROWSE_DEV_DEPENDENCIES : {},
5661
5679
  ...sheets ? STYLES_DEV_DEPENDENCIES : {},
5662
5680
  ...blueprint.src.length > 0 || blueprint.bin ? DECLARATION_DEV_DEPENDENCIES : {},
5663
5681
  ...blueprint.src.includes("browser") || blueprint.setup.includes("browser") || sheets ? SOURCE_BROWSER_DEV_DEPENDENCIES : {},
@@ -6718,16 +6736,20 @@ function blueprintToTestArtifacts(blueprint) {
6718
6736
  origin: "template",
6719
6737
  content: ARTIFACT_TEMPLATES.tests.styles.proof
6720
6738
  });
6721
- for (const name of sheets) artifacts.push({
6722
- path: `tests/src/${name}/index.test.ts`,
6723
- group: "tests",
6724
- ownership: "birth",
6725
- origin: "template",
6726
- content: fillTemplate(ARTIFACT_TEMPLATES.tests.sheet, {
6727
- name,
6728
- setup: name === "styles/themes" ? "../../../setupStyles.js" : "../../setupStyles.js"
6729
- })
6730
- });
6739
+ for (const name of sheets) {
6740
+ const tests = "../".repeat(name.split("/").length + 1);
6741
+ artifacts.push({
6742
+ path: `tests/src/${name}/index.test.ts`,
6743
+ group: "tests",
6744
+ ownership: "birth",
6745
+ origin: "template",
6746
+ content: fillTemplate(ARTIFACT_TEMPLATES.tests.sheet, {
6747
+ name,
6748
+ root: `${tests}../`,
6749
+ setup: `${tests}setupStyles.js`
6750
+ })
6751
+ });
6752
+ }
6731
6753
  if (blueprintToMachinery(blueprint).browser) artifacts.push({
6732
6754
  path: "tests/setupBrowser.ts",
6733
6755
  group: "tests",
@@ -8397,6 +8419,6 @@ var Compiler = class {
8397
8419
  }
8398
8420
  };
8399
8421
  //#endregion
8400
- export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, AXES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONFIG_TEMPLATES, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_PATTERN, FRAMEWORKS, FRAMEWORK_MATRIX, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_INVENTORY_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, JOURNEY_CONFIG_PATH, MANIFEST_PATH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_SCRIPT_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, MINIMUM_NODE_VERSION, MINIMUM_NPM_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, PRINT_WIDTH, REFERENCE_PATHS, RELEASE_PROOF_COMMAND, RESERVED_SHEET_NAMES, SEED_GUIDE_PATHS, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHEET_ENTRY_NAME, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SHOWCASE_PAGES_PATH, SKILLS_CONFIG_PATH, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, STYLES_DEV_DEPENDENCIES, STYLES_ENTRY_PATH, SURFACES, ScaffoldError, TAB_WIDTH, TARGET_SKILL_NAMES, THEMES_BARREL_PATH, THEMES_ENTRY_PATH, VERSION_PATTERN, WORKSPACE_DEV_ENGINES, WORKSPACE_OWNED_PATHS, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToExports, blueprintToFaces, blueprintToGuideArtifacts, blueprintToHostArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToProjects, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSheets, blueprintToSourceArtifacts, blueprintToTestArtifacts, blueprintToWritableScripts, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, dependenciesToQuestions, extractRangeMajor, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isBrowserExtension, isCanonPath, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDeferredPath, isDependency, isDependencyName, isEnvironment, isExtension, isFinding, isFloorPath, isGroup, isGroups, isHex, isManifestScript, isMirror, isOverride, isPath, isPlan, isQuestion, isRetainedPath, isScaffoldError, isSheetName, isSnapshot, isStylesExtension, isSurface, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesPrintWidth, matchesRange, nameToGuide, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseExtension, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, renderSkillPointer, replaceManifestRanges, replaceManifestScripts, replacePlanRanges, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
8422
+ export { APP_BROWSER_DEV_DEPENDENCIES, APP_DEV_DEPENDENCIES, APP_MATRIX, APP_SERVER_DEV_DEPENDENCIES, ARTIFACT_TEMPLATES, AXES, BASE_DEV_DEPENDENCIES, BIN_CONFIGS, BIN_ENTRY_PATH, BROWSE_DEV_DEPENDENCIES, CANON_PATHS, CATALOG_AGENT_PATH, CATALOG_CLOSING_MARKER, CATALOG_OPENING_MARKER, CONFIG_TEMPLATES, CONFORMANCE_TEST_PATH, CONTROL_CHARACTER_PATTERN, Compiler, DECLARATION_DEV_DEPENDENCIES, DEFAULT_ENGINES, DEFAULT_VERSION, DEPENDENCY_NAME_PATTERN, DISTRIBUTION_TEST_PATH, ENGINES_PATTERN, ENVIRONMENTS, EXECUTABLE_PATHS, EXTRA_RANGE_PATTERN, FLOOR_RANGE_PATTERN, FOREIGN_NAME_PATTERN, FRAMEWORKS, FRAMEWORK_MATRIX, GLOBAL_SETUP_PATH, GROUPS, GUIDES_TEST_PATH, HEX_PATTERN, HOST_INVENTORY_PATH, HOST_PATHS, INTEGRATION_TEST_PATH, INVALID_PATH_CHARACTER_PATTERN, JOURNEY_CONFIG_PATH, MANIFEST_PATH, MAX_ARTIFACT_BYTES, MAX_ARTIFACT_HEX_LENGTH, MAX_AUDIT_FINDINGS, MAX_COLLECTION_ITEMS, MAX_DEPENDENCY_NAME_LENGTH, MAX_MANIFEST_BYTES, MAX_NAME_LENGTH, MAX_PATH_LENGTH, MAX_RANGE_LENGTH, MAX_REGISTRY_BYTES, MAX_SCRIPT_LENGTH, MAX_TOTAL_ARTIFACT_BYTES, MAX_TOTAL_REGISTRY_BYTES, MINIMUM_NODE_VERSION, MINIMUM_NPM_VERSION, NAME_PATTERN, ORCHESTRATION_PATH_NAMES, ORCHESTRATION_PATH_PREFIXES, ORKESTREL_RANGE_PATTERN, PRINT_WIDTH, REFERENCE_PATHS, RELEASE_PROOF_COMMAND, RESERVED_SHEET_NAMES, SEED_GUIDE_PATHS, SERVICE_SCRIPT_PATH, SERVICE_SETUP_PATH, SERVICE_TEST_INCLUDE, SHEET_ENTRY_NAME, SHOWCASE_CONFIG_PATH, SHOWCASE_DEV_DEPENDENCIES, SHOWCASE_PAGES_PATH, SKILLS_CONFIG_PATH, SOURCE_BROWSER_DEV_DEPENDENCIES, SRC_MATRIX, STYLES_DEV_DEPENDENCIES, STYLES_ENTRY_PATH, SURFACES, ScaffoldError, TAB_WIDTH, TARGET_SKILL_NAMES, THEMES_BARREL_PATH, THEMES_ENTRY_PATH, VERSION_PATTERN, WORKSPACE_DEV_ENGINES, WORKSPACE_OWNED_PATHS, applyOverrides, artifactToFinding, artifactToHex, artifactsToQuestions, blueprintToConfigArtifacts, blueprintToDevDependencies, blueprintToDocumentArtifacts, blueprintToExports, blueprintToFaces, blueprintToGuideArtifacts, blueprintToHostArtifacts, blueprintToMachinery, blueprintToManifest, blueprintToOrchestrationArtifacts, blueprintToProjects, blueprintToQuestions, blueprintToRootTsconfig, blueprintToRootVite, blueprintToScripts, blueprintToSheets, blueprintToSourceArtifacts, blueprintToTestArtifacts, blueprintToWritableScripts, bytesToHex, catalogToLayers, cloneValue, compareVersions, computeBytes, computeHash, contentToHex, createBlueprint, dependenciesToQuestions, extractRangeMajor, extractVersion, inferDrift, inferGroup, isArtifact, isAudit, isBlueprint, isBrowserExtension, isCanonPath, isCatalogEntry, isCollection, isCompilerHooks, isCompilerOptions, isContent, isDeferredPath, isDependency, isDependencyName, isEnvironment, isExtension, isFinding, isFloorPath, isGroup, isGroups, isHex, isManifestScript, isMirror, isOverride, isPath, isPlan, isQuestion, isRetainedPath, isScaffoldError, isSheetName, isSnapshot, isStylesExtension, isSurface, manifestToDependencies, manifestToName, matchesDriftReachability, matchesEngines, matchesOrchestrationPath, matchesPrintWidth, matchesRange, nameToGuide, overridesToQuestions, parseBlueprint, parseCompilerOptions, parseExtension, parseGroups, parseSnapshot, pathToCondition, planToFindings, planToHash, planToSummary, renderSkillPointer, replaceManifestRanges, replaceManifestScripts, replacePlanRanges, selectGroups, selectHostPaths, serializeTypeScriptString, srcToEntry, srcToExports, srcToRoot };
8401
8423
 
8402
8424
  //# sourceMappingURL=index.js.map