diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index ecbdde7..8135a2a 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -42,6 +42,8 @@ jobs: node -c scripts/test-validate-governance.mjs node -c scripts/validate-domains.mjs node -c scripts/test-validate-domains.mjs + node -c scripts/validate-design-terminology.mjs + node -c scripts/test-validate-design-terminology.mjs node -c scripts/validate-consumer-reference.mjs node -c scripts/test-validate-consumer-reference.mjs node -c scripts/consumer-reference-case-runner.mjs @@ -118,6 +120,8 @@ jobs: run: | node scripts/validate-domains.mjs --json node scripts/test-validate-domains.mjs + node scripts/validate-design-terminology.mjs --json + node scripts/test-validate-design-terminology.mjs - name: Unity organization compressed wiki check run: | diff --git a/AGENTS.md b/AGENTS.md index a742fd5..64f3019 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,7 @@ description: Rules coding agents must follow when editing this governed multi-do # Agent Instructions -This repository is StyleGallery: a governed gallery with Layout, Motion, Design Engineering, Game UI, and Platform Guides domains. Read [StyleGallery Domains](DOMAINS.md) before adding a domain, changing a domain boundary, or adapting an external source. +This repository is StyleGallery: a governed gallery with Layout, Motion, Design Engineering, Game UI, Platform Guides, and Design Terminology domains. Read [StyleGallery Domains](DOMAINS.md) before adding a domain, changing a domain boundary, or adapting an external source. Before editing generated artifacts, validators, lifecycle state, or ownership policy, read [Governance, Lifecycle, And Docs-As-Code](GOVERNANCE.md). @@ -18,6 +18,7 @@ Before editing generated artifacts, validators, lifecycle state, or ownership po - Treat `consumer-reference/` as shared non-domain schema, provenance, routing, and evidence infrastructure; it owns no profile values, visual defaults, component implementation, or product CSS. - Keep dependency direction consumer/profile -> Layout. Do not import consumer-reference records, profile data, tokens, or decorative values into `layout/**`, `patterns/**`, `scripts/pattern-data.mjs`, or `CATALOG.md`. - Include the consumer-reference handoff field in implementation handoffs. For this repository-wide agent surface use `consumer_reference: consumer-reference/agent-native/registry.json`; otherwise use one normalized repository-relative JSON record or `not_applicable` with a sentence reason. +- When an implementation handoff relies on design-terminology records, declare the term identifiers and relation types used and whether the named sources were re-checked in the session; unverified reliance must be marked as such. - Keep material v2, v1 trust/conformance, CLI/MCP transport, and A2A/AG-UI extension planes separate. Material admission never imports profiles, source code, fixtures, schemas, tests, `.omo`, or visual defaults. - Validate canonical evidence v2 against its recorded immutable Git revision. Use current-authoring source checks only when creating or finalizing new capture evidence; do not recapture merely because later repository changes differ. - Treat `consumer-reference/policies/lifecycle-dispositions.json` as the lifecycle index. Preserve named owners, caller status `unknown`, deadlines, extension dispositions, and immutable archive bindings until their machine gate authorizes a transition. diff --git a/DOMAINS.md b/DOMAINS.md index 03198b8..2626bf6 100644 --- a/DOMAINS.md +++ b/DOMAINS.md @@ -19,20 +19,22 @@ This manifest is the source of truth for top-level StyleGallery domains. A domai | Design Engineering | [Design Engineering](design-engineering/index.md) | `experimental` | Product-layer craft questions and evidence-bearing decisions. | A second shared principle system or taste as proof. | Design Engineering domain owner | | Game UI | [Game UI](game-ui/index.md) | `experimental` | Game-interface classification, hierarchy, reference records, and implementation guides nested by engine. | Reusable Layout CSS or claims that one engine structure is universal. | Game UI domain owner | | Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` | Comparative references for a named platform and version context. | Affiliation, brand imitation, or authority over web standards. | Platform Guides domain owner | +| Design Terminology | [Design Terminology](design-terminology/index.md) | `experimental` | Source-kind classification, concept-family classification, typed term relations, and cross-system conflict cases for named vocabulary sources. | StyleGallery's own controlled vocabulary, motion terminology, visual token values, universal naming prescriptions, or authority over external vocabularies. | Design Terminology domain owner | ## Page Manifest | Domain | Manual hub | Governed leaves | | --- | --- | --- | | Layout | `layout/index.md` | Existing `GUIDE.md`, Layout-specific `guides/*.md`, and `recipes/*.md`; generated `patterns/**/*.md` and `CATALOG.md` remain at current paths. Shared `quality/**/*.md` infrastructure governs every domain without becoming a Layout leaf. | -| Motion | `motion/index.md` | `motion/vocabulary.md`, `motion/review-workflow.md`, `motion/practice-reference.md` | -| Design Engineering | `design-engineering/index.md` | `design-engineering/interface-craft.md`, `design-engineering/consumer-migration-readiness.md`, `design-engineering/reference-profiles/index.md`, `design-engineering/reference-profiles/governed-local/index.md`, `design-engineering/reference-profiles/external-adaptation/index.md` | -| Game UI | `game-ui/index.md` | `game-ui/classification.md`, `game-ui/screen-hierarchy.md`, `game-ui/reference-record.md`, `game-ui/unity/architecture.md`, `game-ui/unity/ui-systems.md`, `game-ui/unity/cli-loop.md`, `game-ui/unity/repository-map.md`, `game-ui/unity/org-wiki.md` | -| Platform Guides | `platform-guides/index.md` | `platform-guides/apple-interaction.md` | +| Motion | `motion/index.md` | `motion/vocabulary.md`, `motion/review-workflow.md`, `motion/practice-reference.md`, `motion/decision-tree.md`, `motion/motion-brief.md`, `motion/interaction-recipes.md` | +| Design Engineering | `design-engineering/index.md` | `design-engineering/interface-craft.md`, `design-engineering/consumer-migration-readiness.md`, `design-engineering/reference-profiles/index.md`, `design-engineering/reference-profiles/governed-local/index.md`, `design-engineering/reference-profiles/external-adaptation/index.md`, `design-engineering/decision-tree.md`, `design-engineering/component-contract.md`, `design-engineering/worked-examples.md` | +| Game UI | `game-ui/index.md` | `game-ui/classification.md`, `game-ui/screen-hierarchy.md`, `game-ui/reference-record.md`, `game-ui/unity/architecture.md`, `game-ui/unity/ui-systems.md`, `game-ui/unity/cli-loop.md`, `game-ui/unity/repository-map.md`, `game-ui/unity/org-wiki.md`, `game-ui/decision-tree.md`, `game-ui/screen-recipes.md`, `game-ui/verification-workflow.md` | +| Platform Guides | `platform-guides/index.md` | `platform-guides/apple-interaction.md`, `platform-guides/adaptation-workflow.md`, `platform-guides/android-interaction.md`, `platform-guides/windows-interaction.md`, `platform-guides/compatibility-matrix.md` | +| Design Terminology | `design-terminology/index.md` | `design-terminology/source-kinds.md`, `design-terminology/source-vocabularies.md`, `design-terminology/concept-families.md`, `design-terminology/relation-types.md`, `design-terminology/conflict-cases.md`, `design-terminology/comparison-workflow.md` | ## Shared Non-Domain Infrastructure -[Consumer Reference](consumer-reference/index.md) is shared schema, provenance, routing, evidence, lifecycle, and machine-retrieval infrastructure outside the five-domain contract. Its source-bound material v2 index classifies admitted pages by these five domains but does not own their prose. It owns no profile implementation, visual values, or product CSS and cannot add a sixth domain row. Consumer or profile records may depend on Layout; Layout and its generated corpus cannot import consumer-reference, profile, material-registry, or transport records. +[Consumer Reference](consumer-reference/index.md) is shared schema, provenance, routing, evidence, lifecycle, and machine-retrieval infrastructure outside the six-domain contract. Its source-bound material v2 index classifies admitted pages by these six domains but does not own their prose. It owns no profile implementation, visual values, or product CSS and cannot add a seventh domain row. Consumer or profile records may depend on Layout; Layout and its generated corpus cannot import consumer-reference, profile, material-registry, or transport records. ## External Adaptation Contract @@ -45,7 +47,9 @@ The initial five domain leaves are independent method rewrites inspired by [emil - If recognizable upstream expression is added later, preserve the full upstream MIT notice and record the copied material separately before merge. - Tracked repository documents must not depend on `.omo/`; stable upstream blob links and tracked repository contracts carry contributor-facing provenance. -`design-engineering/consumer-migration-readiness.md` is the separately declared StyleGallery-local leaf. It uses `provenance_kind: local`, carries no external source fields, and remains experimental. Its presence does not change the external-adaptation inventory or make its consumer-local method universal policy. +The workflow, brief, contract, recipe, and comparison leaves added under the five non-Layout domains are StyleGallery-local synthesis with `provenance_kind: local`; their worked scenarios are proposals, not captured product evidence. The domain indexes route selection, authoring, application, and verification. + +`design-engineering/consumer-migration-readiness.md` is a separately declared StyleGallery-local leaf. It uses `provenance_kind: local`, carries no external source fields, and remains experimental. Its presence does not change the external-adaptation inventory or make its consumer-local method universal policy. ## Lifecycle And Staleness diff --git a/GOVERNANCE.md b/GOVERNANCE.md index 0281f8b..fe6d91e 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -42,11 +42,18 @@ Use this file before editing repository documentation. It names which file is au | Design Engineering domain guidance | `design-engineering/*.md` | Manual | None | `experimental` | Upstream revision, evidence boundary, or guidance changes. | `scripts/validate-domains.mjs` | Design Engineering domain owner | | Game UI domain guidance | `game-ui/**/*.md` | Manual | None | `experimental` | Classification, hierarchy, engine implementation, evidence boundary, or route changes. | `scripts/validate-domains.mjs` | Game UI domain owner | | Platform Guides domain guidance | `platform-guides/*.md` | Manual | None | `experimental` | Platform version, upstream revision, evidence boundary, or guidance changes. | `scripts/validate-domains.mjs` | Platform Guides domain owner | +| Design Terminology domain guidance | `design-terminology/*.md` | Manual; term and relation tables remain authoring sources | None | `experimental` | Source-kind, source-vocabulary, concept-family, relation-model, or conflict-case changes. | `scripts/validate-domains.mjs`, `scripts/validate-design-terminology.mjs` | Design Terminology domain owner | | Pattern data and examples | `scripts/pattern-data.mjs` | Manual data source | `patterns/**/*.md`, `patterns/**/index.md`, `patterns/index.md`, `CATALOG.md` | `generated` output from `stable` source | Source-lineage URL changes, generated drift, category changes, or pattern count changes. | `scripts/validate-patterns.mjs`, `scripts/validate-catalog.mjs`, `scripts/validate-governance.mjs` | Pattern-data owner | | Pattern generator | `scripts/generate-patterns.mjs` | Manual code source | `patterns/**/*.md`, `patterns/**/index.md`, `patterns/index.md`, `CATALOG.md` | `stable` generator, `generated` output | Generated structure changes, generated-warning changes, or generated metadata changes. | `node -c scripts/generate-patterns.mjs`, generated drift check, `scripts/validate-governance.mjs` | Pattern-data owner | | Validation scripts | `scripts/validate-*.mjs`, `scripts/test-validate-*.mjs` | Manual code source | CI validation output | `stable` | Validator scope changes, fixture changes, or CI parity changes. | `node -c`, matching fixture tests, `.github/workflows/validate.yml` | Validation owner | | CI workflows | `.github/workflows/validate.yml`, `.github/workflows/evidence-freshness.yml` | Manual | GitHub Actions runs and audit artifacts | `stable` | Validation step, explicit-deadline schedule, generated drift policy, or owner changes. | GitHub Actions, `scripts/validate-governance.mjs` | Repository governance owner | +## Domain Workflow Verification Boundary + +The non-Layout hubs route selection, briefs/contracts, applied recipes or cases, and verification. Their local leaves declare `provenance_kind: local` and remain `experimental`. Worked examples contain expected outcomes, not captured product or engine evidence. `scripts/validate-domains.mjs` checks declared membership, provenance, sections, and routes; it does not execute those examples. + +The Design Terminology Markdown tables additionally require directly located sources, labels, valid dates, explicit comparison scope and direction, and consistent relation graphs. `scripts/validate-design-terminology.mjs` and its negative fixtures check those record invariants; semantic accuracy and independent promotion review remain human judgments. Material v2 indexes only the admitted Markdown bytes. Changing the allowed document set requires updating its closed inventory, digest, package exposure, and generated registry together, without admitting code, schemas, profiles, or fixtures as material. + ## Generated Artifact Policy Generated files are not source of truth. Do not hand-edit generated artifacts to change pattern content or catalog structure. @@ -98,7 +105,7 @@ Use these states in reviews and governance notes. Do not invent new lifecycle la Default lifecycle: - Root docs, guides, recipes, quality docs, validators, and CI are `stable` unless a page explicitly says otherwise. -- `DOMAINS.md`, the scope decision, and `layout/index.md` are `stable`; domain leaves under `motion/`, `design-engineering/`, `game-ui/`, and `platform-guides/` begin `experimental`. +- `DOMAINS.md`, the scope decision, and `layout/index.md` are `stable`; domain leaves under `motion/`, `design-engineering/`, `game-ui/`, `platform-guides/`, and `design-terminology/` begin `experimental`. - Generated pattern docs, generated pattern indexes, and `CATALOG.md` are `generated`. - Draft research artifacts under `.omo/` are `draft` or `experimental` and are not contributor-facing source of truth. @@ -125,6 +132,7 @@ Consumer-reference ownership records the current truth as `owner.enforcement: "p | `tests/**`, `playwright.config.mjs`, `consumer-reference/baselines/**`, `scripts/*baseline*.mjs`, `scripts/*sentinel*.mjs`, `scripts/*renderer-purity.mjs` | Repository governance owner with Validation owner | Pure rendering, computed semantics before screenshots, immutable browser pins, required consumer-conformance semantics, optional raster capture, calibration cardinality, and pending owner approval. | | `game-ui/**` | Game UI domain owner | Player-task classification, hierarchy responsibility, reference records, engine-specific subtrees, and cross-engine boundaries. | | `platform-guides/**` | Platform Guides domain owner | Platform/source/version limits, comparison boundaries, and stale review. | +| `design-terminology/**` | Design Terminology domain owner | Term-family classification, comparative system definitions, conflict-case boundaries, and external vocabulary citations. | | `scripts/validate-*.mjs`, `scripts/test-validate-*.mjs`, `.github/workflows/validate.yml`, `.github/workflows/evidence-freshness.yml` | Validation owner | Validator scope, negative fixtures, blocking/advisory boundaries, CI parity. | ## Shared Promotion Governance diff --git a/README.md b/README.md index 33f9378..7be3dd8 100644 --- a/README.md +++ b/README.md @@ -7,18 +7,18 @@ description: Governed gallery of portable interface knowledge organized by domai # StyleGallery

- StyleGallery infographic connecting five governed interface-knowledge domains to shared consumer and agent infrastructure + StyleGallery infographic connecting six governed interface-knowledge domains to shared consumer and agent infrastructure

-StyleGallery is a governed gallery of portable interface knowledge. It separates reusable spatial patterns, product-layer motion guidance, design-engineering practice, and platform-specific references into explicit domains with different evidence and ownership boundaries. +StyleGallery is a governed gallery of portable interface knowledge. It separates reusable spatial patterns, product-layer motion guidance, design-engineering practice, platform-specific references, and comparative design terminology into explicit domains with different evidence and ownership boundaries. Primary role: repository guide. The existing Layout corpus remains a gallery of minimal, portable CSS layout patterns at its current paths. Each pattern documents one primary spatial problem and the smallest robust HTML/CSS structure that solves it. Motion, visual treatment, and platform guidance do not expand reusable Layout pattern CSS; they live in their own domains and carry explicit evidence boundaries. -[Consumer Reference](consumer-reference/index.md) is shared non-domain infrastructure for optional consumer-owned reference handoffs. It carries schema, routing, provenance, and evidence metadata without owning profiles, visual values, components, or a sixth domain. +[Consumer Reference](consumer-reference/index.md) is shared non-domain infrastructure for optional consumer-owned reference handoffs. It carries schema, routing, provenance, and evidence metadata without owning profiles, visual values, components, or a seventh domain. -[Agent-Native StyleGallery](consumer-reference/agent-native/README.md) is the machine-facing entry point over that governed knowledge. Frozen v1 provides claim/evidence/governance records through `sg` and its MCP; isolated material v2 indexes admitted Markdown and exposes `sg-material` plus a separate read-only MCP. Lifecycle records own extension and archive dispositions. These material, trust/conformance, transport, and extension planes do not create a sixth domain, replace the Markdown corpus, permit mutation, or feed visual defaults back into Layout. +[Agent-Native StyleGallery](consumer-reference/agent-native/README.md) is the machine-facing entry point over that governed knowledge. Frozen v1 provides claim/evidence/governance records through `sg` and its MCP; isolated material v2 indexes admitted Markdown and exposes `sg-material` plus a separate read-only MCP. Lifecycle records own extension and archive dispositions. These material, trust/conformance, transport, and extension planes do not create a seventh domain, replace the Markdown corpus, permit mutation, or feed visual defaults back into Layout. ## Quick Start @@ -115,9 +115,24 @@ CLI와 MCP의 상세 사용법은 [Agent-Native StyleGallery 가이드](consumer | [Design Engineering](design-engineering/index.md) | Product-layer craft decisions and verification questions. | A second universal principle set or taste as evidence. | | [Game UI](game-ui/index.md) | Game-interface classification, hierarchy, reference records, and engine-specific implementation guides. | Reusable Layout CSS or claims that one engine structure is universal. | | [Platform Guides](platform-guides/index.md) | Bounded comparison with named platform conventions. | Affiliation, imitation, or authority over web and accessibility contracts. | +| [Design Terminology](design-terminology/index.md) | Comparative design-term definitions, term families, and cross-system conflict cases for named systems. | StyleGallery's own vocabulary, motion terminology, visual token values, or authority over external vocabularies. | The canonical domain manifest and provenance policy are in [StyleGallery Domains](DOMAINS.md). +## Practical Domain Workflows + +| Task | Start | Apply and verify | +| --- | --- | --- | +| Design a transition | [Motion Decision Tree](motion/decision-tree.md) | [Brief](motion/motion-brief.md), [interaction recipes](motion/interaction-recipes.md), and [review](motion/review-workflow.md) | +| Build a product interaction | [Design Engineering Decision Tree](design-engineering/decision-tree.md) | [Component contract](design-engineering/component-contract.md) and [worked examples](design-engineering/worked-examples.md) | +| Compose a game screen | [Game UI Decision Tree](game-ui/decision-tree.md) | [Screen recipes](game-ui/screen-recipes.md) and [verification workflow](game-ui/verification-workflow.md) | +| Adapt a platform convention | [Platform Adaptation Workflow](platform-guides/adaptation-workflow.md) | [Apple](platform-guides/apple-interaction.md), [Android](platform-guides/android-interaction.md), [Windows](platform-guides/windows-interaction.md), and [compatibility matrix](platform-guides/compatibility-matrix.md) | +| Resolve a terminology conflict | [Design Term Comparison Workflow](design-terminology/comparison-workflow.md) | [Directly sourced term cases](design-terminology/conflict-cases.md) and [relation rules](design-terminology/relation-types.md) | + +Layout 외 도메인도 선택 절차, 작성 양식, 적용 사례, 검증 경로를 제공합니다. 예제의 기대 결과는 실제 실행 증거와 구분하며, 공식 출처를 확인한 날짜와 적용 범위는 각 문서에 기록합니다. 문서 확충만으로 `experimental` 상태가 자동 승격되지는 않습니다. + +[Interaction Lab](examples/domain-interactions/README.md)은 저장·검색·중첩 팝업·보상·입력 사례를 실행할 수 있는 브라우저 예제입니다. [검증 기록](examples/domain-interactions/verification.md)은 실제 Mac 브라우저에서 관찰한 결과와 모바일·네이티브 엔진 미검증 범위를 구분합니다. + ## Repository Entry Roles Use each root hub for one primary job. @@ -137,6 +152,7 @@ Use each root hub for one primary job. | [Design Engineering](design-engineering/index.md) | Design Engineering domain hub | You need product-level interface-craft decision guidance. | | [Game UI](game-ui/index.md) | Game UI domain hub | You need to classify a game interface or understand its screen hierarchy. | | [Platform Guides](platform-guides/index.md) | Platform Guides domain hub | You need a bounded platform comparison. | +| [Design Terminology](design-terminology/index.md) | Design Terminology domain hub | You need to compare how named design systems define or classify design terms. | ## Task Routes @@ -151,6 +167,7 @@ Each common task has one primary route. Use secondary links only after the prima | `compare adversarial consumer identities` | [Reference Profiles](design-engineering/reference-profiles/index.md) | It keeps non-default product values in related Design Engineering examples over one pinned Layout source. | | `classify a game interface or map it to an engine` | [Game UI](game-ui/index.md) | It separates engine-neutral roles from implementation-specific guidance. | | `compare a named platform convention` | [Platform Guides](platform-guides/index.md) | It requires platform and evidence boundaries before adaptation. | +| `compare how design systems define a term` | [Design Terminology](design-terminology/index.md) | It separates external terminology comparison from StyleGallery's own controlled vocabulary. | | `turn raw content into a homepage or ordinary webpage` | [Webpage Generation Workflow](guides/webpage-generation-workflow.md) | It starts with use case, content-to-layout fit, harmony, and handoff. | | `plan a screen before the layout problem is obvious` | [Layout Planning Guide](GUIDE.md) | It sequences task, content, scroll, recipe, and verification choices. | | `choose a pattern when the name is unknown` | [Decision Tree](guides/decision-tree.md) | It routes from constraints to pattern categories. | @@ -177,7 +194,7 @@ Each common task has one primary route. Use secondary links only after the prima ## How To Use This Repository - Start with [StyleGallery Domains](DOMAINS.md) when the owning domain is not already clear. -- Use [Layout](layout/index.md), [Motion](motion/index.md), [Design Engineering](design-engineering/index.md), [Game UI](game-ui/index.md), or [Platform Guides](platform-guides/index.md) as the domain-local entry point. +- Use [Layout](layout/index.md), [Motion](motion/index.md), [Design Engineering](design-engineering/index.md), [Game UI](game-ui/index.md), [Platform Guides](platform-guides/index.md), or [Design Terminology](design-terminology/index.md) as the domain-local entry point. - Start with [Layout Planning Guide](GUIDE.md) when you are designing a screen before a layout problem is obvious. - Use the [Webpage Generation Workflow](guides/webpage-generation-workflow.md) when raw content needs to become a homepage or ordinary webpage before a layout recipe is obvious. - Use the [Documentation Mode Taxonomy](guides/documentation-mode-taxonomy.md) when adding or reviewing docs so each page has a clear primary reading mode. diff --git a/consumer-reference/agent-native/README.md b/consumer-reference/agent-native/README.md index c531d9a..ce79ee1 100644 --- a/consumer-reference/agent-native/README.md +++ b/consumer-reference/agent-native/README.md @@ -10,7 +10,7 @@ Primary role: machine interface guide. Agent-Native StyleGallery lets a person, script, or agent inspect the governed StyleGallery knowledge graph without learning repository paths first. The Markdown corpus remains the human-readable source material; the agent-native layer gives its governed fixture records stable identities, closed schemas, deterministic operations, and protocol-specific projections. -This is shared non-domain infrastructure. It does not add a sixth StyleGallery domain, make example profiles canonical, or allow an MCP client to mutate repository knowledge. +This is shared non-domain infrastructure. It does not add a seventh StyleGallery domain, make example profiles canonical, or allow an MCP client to mutate repository knowledge. ## Mental Model @@ -56,6 +56,17 @@ All machine-mode results are deterministic JSON on stdout. A failed request retu | `context ` | Build a deterministic, bounded context package with a snapshot, member manifest, policy, and cache key. | | `ops` | List all operation specifications, including internal governed mutations and their exposure metadata. | +## Governed Material v2 + +Material v2 is an isolated, read-only interface over admitted Markdown. Use `sg-material discover`, `search`, `get`, and `context`, or the equivalent `material-*` tools exposed by `stylegallery-material-mcp`. It does not merge material with v1 trust records or expand the admission policy. + +Search keeps the fixed field weights `title: 16`, `path: 8`, and `body: 1`. For a multi-token query, each field contribution is multiplied by `ceil(material_count / max(1, token_document_frequency))` so a specific, uncommon term such as `sticky` is not outranked by a corpus-wide term such as `layout`. Results expose the document frequency and multiplier for every normalized query token; ties remain ordered by projected StableRef. `--paths-only` preserves the same ranking while returning repository-relative paths. + +```sh +sg-material search --query "sticky layout" --paths-only --limit 5 +stylegallery-material search --query "design terminology source kinds" --paths-only --limit 5 +``` + ## MCP Start the stdio MCP server with: diff --git a/consumer-reference/agent-native/v2/admission-policy.json b/consumer-reference/agent-native/v2/admission-policy.json index 0c04911..66e0570 100644 --- a/consumer-reference/agent-native/v2/admission-policy.json +++ b/consumer-reference/agent-native/v2/admission-policy.json @@ -49,11 +49,21 @@ "domain": "shared", "lifecycle": "stable" }, + { + "repository_path": "design-engineering/component-contract.md", + "domain": "design-engineering", + "lifecycle": "experimental" + }, { "repository_path": "design-engineering/consumer-migration-readiness.md", "domain": "design-engineering", "lifecycle": "experimental" }, + { + "repository_path": "design-engineering/decision-tree.md", + "domain": "design-engineering", + "lifecycle": "experimental" + }, { "repository_path": "design-engineering/index.md", "domain": "design-engineering", @@ -64,11 +74,56 @@ "domain": "design-engineering", "lifecycle": "experimental" }, + { + "repository_path": "design-engineering/worked-examples.md", + "domain": "design-engineering", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/comparison-workflow.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/concept-families.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/conflict-cases.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/index.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/relation-types.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/source-kinds.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, + { + "repository_path": "design-terminology/source-vocabularies.md", + "domain": "design-terminology", + "lifecycle": "experimental" + }, { "repository_path": "game-ui/classification.md", "domain": "game-ui", "lifecycle": "experimental" }, + { + "repository_path": "game-ui/decision-tree.md", + "domain": "game-ui", + "lifecycle": "experimental" + }, { "repository_path": "game-ui/index.md", "domain": "game-ui", @@ -84,6 +139,11 @@ "domain": "game-ui", "lifecycle": "experimental" }, + { + "repository_path": "game-ui/screen-recipes.md", + "domain": "game-ui", + "lifecycle": "experimental" + }, { "repository_path": "game-ui/unity/architecture.md", "domain": "game-ui", @@ -109,6 +169,11 @@ "domain": "game-ui", "lifecycle": "experimental" }, + { + "repository_path": "game-ui/verification-workflow.md", + "domain": "game-ui", + "lifecycle": "experimental" + }, { "repository_path": "guides/decision-tree.md", "domain": "layout", @@ -149,11 +214,26 @@ "domain": "shared", "lifecycle": "stable" }, + { + "repository_path": "motion/decision-tree.md", + "domain": "motion", + "lifecycle": "experimental" + }, { "repository_path": "motion/index.md", "domain": "motion", "lifecycle": "experimental" }, + { + "repository_path": "motion/interaction-recipes.md", + "domain": "motion", + "lifecycle": "experimental" + }, + { + "repository_path": "motion/motion-brief.md", + "domain": "motion", + "lifecycle": "experimental" + }, { "repository_path": "motion/practice-reference.md", "domain": "motion", @@ -449,16 +529,41 @@ "domain": "layout", "lifecycle": "generated" }, + { + "repository_path": "platform-guides/adaptation-workflow.md", + "domain": "platform-guides", + "lifecycle": "experimental" + }, + { + "repository_path": "platform-guides/android-interaction.md", + "domain": "platform-guides", + "lifecycle": "experimental" + }, { "repository_path": "platform-guides/apple-interaction.md", "domain": "platform-guides", "lifecycle": "experimental" }, + { + "repository_path": "platform-guides/compatibility-matrix.md", + "domain": "platform-guides", + "lifecycle": "experimental" + }, { "repository_path": "platform-guides/index.md", "domain": "platform-guides", "lifecycle": "experimental" }, + { + "repository_path": "platform-guides/windows-interaction.md", + "domain": "platform-guides", + "lifecycle": "experimental" + }, + { + "repository_path": "quality/claim-records/design-terminology-domain-scope.md", + "domain": "shared", + "lifecycle": "stable" + }, { "repository_path": "quality/claim-records/index.md", "domain": "shared", @@ -712,5 +817,5 @@ "code": "material_path_internal_excluded" } ], - "version_id": "sg:policy/material-admission-v2@sha256:017b5de61c5e98779ec9b32880b3cd897c5f7012e726bdb73392572800b1f837" + "version_id": "sg:policy/material-admission-v2@sha256:3bc645aa9b84393a404612ebc4d757aada288ef88f57bb2d2fca03022b4d201d" } diff --git a/consumer-reference/agent-native/v2/material-registry.json b/consumer-reference/agent-native/v2/material-registry.json index 6ebcebe..32b185c 100644 --- a/consumer-reference/agent-native/v2/material-registry.json +++ b/consumer-reference/agent-native/v2/material-registry.json @@ -1 +1 @@ -{"admission_policy_ref":"sg:policy/material-admission-v2","admission_policy_version_id":"sg:policy/material-admission-v2@sha256:017b5de61c5e98779ec9b32880b3cd897c5f7012e726bdb73392572800b1f837","materials":[{"byte_length":3583,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/page-grid.md","schema_version":"2.0","source_sha256":"a5b73ad6e01e85a93f2f585f520ea7e02f8b3677fa286236c20011873d4e7b9b","stable_ref":"sg:material/path-sha256-002803d65d057faaa4e8c1bb3e32ef3f41032b011251fc9f0f7b1db907b01ceb","version_id":"sg:material/path-sha256-002803d65d057faaa4e8c1bb3e32ef3f41032b011251fc9f0f7b1db907b01ceb@sha256:a5b73ad6e01e85a93f2f585f520ea7e02f8b3677fa286236c20011873d4e7b9b"},{"byte_length":3464,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/pagination.md","schema_version":"2.0","source_sha256":"a7afa87a24aae9797f299a7e4b4b96e2ca26d511a7ba2dcdbe1dc78600532a5b","stable_ref":"sg:material/path-sha256-00ae3be01fcc4add55bd98eff34737037c54c0a7f2f128239a2afbe698936c8f","version_id":"sg:material/path-sha256-00ae3be01fcc4add55bd98eff34737037c54c0a7f2f128239a2afbe698936c8f@sha256:a7afa87a24aae9797f299a7e4b4b96e2ca26d511a7ba2dcdbe1dc78600532a5b"},{"byte_length":4786,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/samples.md","schema_version":"2.0","source_sha256":"c2a3acefcad07f0ace47c9d054b601da0f4447a0fc8d5ee0ef272dd45075e81b","stable_ref":"sg:material/path-sha256-021f96adf1d1647d17f99011af6b1e7fa370dddbbad96b384731ed0256f74984","version_id":"sg:material/path-sha256-021f96adf1d1647d17f99011af6b1e7fa370dddbbad96b384731ed0256f74984@sha256:c2a3acefcad07f0ace47c9d054b601da0f4447a0fc8d5ee0ef272dd45075e81b"},{"byte_length":858,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/index.md","schema_version":"2.0","source_sha256":"05da91c5514d03e82c19a03c494fdad21a92a2ba7b88ec6dca5e7836c1f133a2","stable_ref":"sg:material/path-sha256-040de79bdf5af768663bf1aaa9d7451aa0d79bfaa0d5e982cceec4058f7715e4","version_id":"sg:material/path-sha256-040de79bdf5af768663bf1aaa9d7451aa0d79bfaa0d5e982cceec4058f7715e4@sha256:05da91c5514d03e82c19a03c494fdad21a92a2ba7b88ec6dca5e7836c1f133a2"},{"byte_length":5367,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/interface-craft.md","schema_version":"2.0","source_sha256":"ba71e914027abd783e9769a5b91efb764cc7335a6479c69ca4e70ab05a64e941","stable_ref":"sg:material/path-sha256-04afb6013755c328be25b08637961e5f20fa67705cfcbd6e996ba6ada944f571","version_id":"sg:material/path-sha256-04afb6013755c328be25b08637961e5f20fa67705cfcbd6e996ba6ada944f571@sha256:ba71e914027abd783e9769a5b91efb764cc7335a6479c69ca4e70ab05a64e941"},{"byte_length":501,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/index.md","schema_version":"2.0","source_sha256":"9b60182a25c4c07b7b482b3981dec17d515f95915cc618411282f988dca4ada2","stable_ref":"sg:material/path-sha256-04fa96b121ed2a48be80851efc72289752d1c4c12bd6433c2d5002d6d82a54ed","version_id":"sg:material/path-sha256-04fa96b121ed2a48be80851efc72289752d1c4c12bd6433c2d5002d6d82a54ed@sha256:9b60182a25c4c07b7b482b3981dec17d515f95915cc618411282f988dca4ada2"},{"byte_length":6853,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/vocabulary.md","schema_version":"2.0","source_sha256":"b2796979aaa1b194ff3006469cbeaec71cbd80d1484e3a5089e03295a43b464d","stable_ref":"sg:material/path-sha256-07b5ed44416e4d40efd213a7e944f214a338aa83201e52ba58c6dcf2a81e5675","version_id":"sg:material/path-sha256-07b5ed44416e4d40efd213a7e944f214a338aa83201e52ba58c6dcf2a81e5675@sha256:b2796979aaa1b194ff3006469cbeaec71cbd80d1484e3a5089e03295a43b464d"},{"byte_length":1619,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/visual-evidence.md","schema_version":"2.0","source_sha256":"17f7430f1cd1847c74c737ee9341120be6b49e827ec4228be5b6868669d27fd3","stable_ref":"sg:material/path-sha256-085c94936dece089fd31864c482d1a19e4da562951adbaa7d459e0126486d149","version_id":"sg:material/path-sha256-085c94936dece089fd31864c482d1a19e4da562951adbaa7d459e0126486d149@sha256:17f7430f1cd1847c74c737ee9341120be6b49e827ec4228be5b6868669d27fd3"},{"byte_length":54,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/index.md","schema_version":"2.0","source_sha256":"b9bb90f0928f7f408c615ce2dc323425640ef4b83b62de0c0dee6dcd4bf7e3bb","stable_ref":"sg:material/path-sha256-08c3095acfdc040b75071e94644db6a32b655817c4b79eabfa4339b59c9f0b22","version_id":"sg:material/path-sha256-08c3095acfdc040b75071e94644db6a32b655817c4b79eabfa4339b59c9f0b22@sha256:b9bb90f0928f7f408c615ce2dc323425640ef4b83b62de0c0dee6dcd4bf7e3bb"},{"byte_length":4089,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/harmony-evaluation.md","schema_version":"2.0","source_sha256":"efee2c0ff6a662bc3efb360ee8c80defc5113a00d8b36e1c36c45eb63d330270","stable_ref":"sg:material/path-sha256-0a43f2af49d24f33b8ff06829d431f9e7608de57760c3f2c7de8c3e4126869f3","version_id":"sg:material/path-sha256-0a43f2af49d24f33b8ff06829d431f9e7608de57760c3f2c7de8c3e4126869f3@sha256:efee2c0ff6a662bc3efb360ee8c80defc5113a00d8b36e1c36c45eb63d330270"},{"byte_length":3804,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/scroll-body-shell.md","schema_version":"2.0","source_sha256":"f9f8269f42afdc453f2e226a03c1ea23566b4b9362939a4f485aee20d150cee8","stable_ref":"sg:material/path-sha256-10f553c3d6a39c31ca1a5b8f56db6afb75709d8706d125c6f0d891f46b1f11b4","version_id":"sg:material/path-sha256-10f553c3d6a39c31ca1a5b8f56db6afb75709d8706d125c6f0d891f46b1f11b4@sha256:f9f8269f42afdc453f2e226a03c1ea23566b4b9362939a4f485aee20d150cee8"},{"byte_length":4959,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/homepage.md","schema_version":"2.0","source_sha256":"09203c0de8824db3a8f678add95b0de363035ead7cfe5d44ae79353ef36b1193","stable_ref":"sg:material/path-sha256-14e127a7c719ee8494096a98b25b32d26363c1845bddcd912f50f6b1e2b84b46","version_id":"sg:material/path-sha256-14e127a7c719ee8494096a98b25b32d26363c1845bddcd912f50f6b1e2b84b46@sha256:09203c0de8824db3a8f678add95b0de363035ead7cfe5d44ae79353ef36b1193"},{"byte_length":3430,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/overlay-stack.md","schema_version":"2.0","source_sha256":"ffe57e891cbaa2eefcd3f642818d6f955b9f51f9028eed48ca2769e1ad75fd89","stable_ref":"sg:material/path-sha256-15dd8f3d84fb50f1442bd8c9732356759849f7d87f1d66b004eeb5d9ea75a4a9","version_id":"sg:material/path-sha256-15dd8f3d84fb50f1442bd8c9732356759849f7d87f1d66b004eeb5d9ea75a4a9@sha256:ffe57e891cbaa2eefcd3f642818d6f955b9f51f9028eed48ca2769e1ad75fd89"},{"byte_length":901,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/design-rationale.md","schema_version":"2.0","source_sha256":"f2215fa79133af7f7282fff9a2da490d1a5dd58dd3ea0fc56255872268fbd163","stable_ref":"sg:material/path-sha256-162d7fd4521ddaf5ee59166c9cb56d8cbcb7d3b9bacaf9cd75883c1586108369","version_id":"sg:material/path-sha256-162d7fd4521ddaf5ee59166c9cb56d8cbcb7d3b9bacaf9cd75883c1586108369@sha256:f2215fa79133af7f7282fff9a2da490d1a5dd58dd3ea0fc56255872268fbd163"},{"byte_length":3452,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/breadcrumb.md","schema_version":"2.0","source_sha256":"666bf05329f85a0a19d8ee42fd91b6149895d7c1ed62528f3b36051015210b9c","stable_ref":"sg:material/path-sha256-16eeb4385f9c3ed3ee536baa50271a5afda69eb267e6e240f45eea88c675c9cc","version_id":"sg:material/path-sha256-16eeb4385f9c3ed3ee536baa50271a5afda69eb267e6e240f45eea88c675c9cc@sha256:666bf05329f85a0a19d8ee42fd91b6149895d7c1ed62528f3b36051015210b9c"},{"byte_length":3426,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/cluster.md","schema_version":"2.0","source_sha256":"39a8b4e529fa82338de96528ed1f7ec0a1646286243dfb7df71be3666c46ed82","stable_ref":"sg:material/path-sha256-176a6bff0fef909def0e8d71cb7c567b867a180ff8ff11dc71f96187e6fb4b75","version_id":"sg:material/path-sha256-176a6bff0fef909def0e8d71cb7c567b867a180ff8ff11dc71f96187e6fb4b75@sha256:39a8b4e529fa82338de96528ed1f7ec0a1646286243dfb7df71be3666c46ed82"},{"byte_length":935,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/index.md","schema_version":"2.0","source_sha256":"5cfb5a5586709a5c32f6f01e8d0e768850b57111c0a653363ced0eeddbca4f88","stable_ref":"sg:material/path-sha256-1bbc62c02480ddef71cbe2b8723ae3da595efdfcfcf8f0bbbfd4dad8d417d2a7","version_id":"sg:material/path-sha256-1bbc62c02480ddef71cbe2b8723ae3da595efdfcfcf8f0bbbfd4dad8d417d2a7@sha256:5cfb5a5586709a5c32f6f01e8d0e768850b57111c0a653363ced0eeddbca4f88"},{"byte_length":3725,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/split-screen.md","schema_version":"2.0","source_sha256":"a6c48700334e6e3e611acee525be7a89e6aa73c0df0494d5f4a5555790d237a8","stable_ref":"sg:material/path-sha256-1c3948243f01f30bcd55ac3cb3c9935bce15060224b1837fdf1b3be2684ecc74","version_id":"sg:material/path-sha256-1c3948243f01f30bcd55ac3cb3c9935bce15060224b1837fdf1b3be2684ecc74@sha256:a6c48700334e6e3e611acee525be7a89e6aa73c0df0494d5f4a5555790d237a8"},{"byte_length":3334,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/box.md","schema_version":"2.0","source_sha256":"d64aedd87ff612e6bb50293653cf5076ed952c1d4833abc54416b1bc60ef8680","stable_ref":"sg:material/path-sha256-1c4c0582a35fac69c8274a72f86ad5075a755d30f0924adbc3ff66fc616d9430","version_id":"sg:material/path-sha256-1c4c0582a35fac69c8274a72f86ad5075a755d30f0924adbc3ff66fc616d9430@sha256:d64aedd87ff612e6bb50293653cf5076ed952c1d4833abc54416b1bc60ef8680"},{"byte_length":3380,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/stack.md","schema_version":"2.0","source_sha256":"0e9d1bd2fb0345bd28efc04502c88fb64f6cdb721a5792473d2822907de1baa1","stable_ref":"sg:material/path-sha256-1f6bb0dc8098df4cb643ddb7941fc7997bfc34e8c4c4ba8b473ebd19b43da69e","version_id":"sg:material/path-sha256-1f6bb0dc8098df4cb643ddb7941fc7997bfc34e8c4c4ba8b473ebd19b43da69e@sha256:0e9d1bd2fb0345bd28efc04502c88fb64f6cdb721a5792473d2822907de1baa1"},{"byte_length":386,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/index.md","schema_version":"2.0","source_sha256":"a32cdbff417ba8cf4333a15c7799bb1b1907c4334d0bcee052220af46b87973a","stable_ref":"sg:material/path-sha256-1fc22b9f0d7d72c1dcc9b54db927b44a791c091736efbc2dcff08b9f5097f00c","version_id":"sg:material/path-sha256-1fc22b9f0d7d72c1dcc9b54db927b44a791c091736efbc2dcff08b9f5097f00c@sha256:a32cdbff417ba8cf4333a15c7799bb1b1907c4334d0bcee052220af46b87973a"},{"byte_length":2010,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/design-claim.md","schema_version":"2.0","source_sha256":"bdf92087f69f1d55d1d8f5efa8fdc794824bd9f40d794e617e6a06db0a16ef81","stable_ref":"sg:material/path-sha256-21480e86104dfaab3408304f300dc7cc570eab3e747a1a3931785951544f8372","version_id":"sg:material/path-sha256-21480e86104dfaab3408304f300dc7cc570eab3e747a1a3931785951544f8372@sha256:bdf92087f69f1d55d1d8f5efa8fdc794824bd9f40d794e617e6a06db0a16ef81"},{"byte_length":3461,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/super-center.md","schema_version":"2.0","source_sha256":"80ca126c59d0a5947707b01875c17487dfad7e4fc51920ad02649108971e0c55","stable_ref":"sg:material/path-sha256-21ffb3e535a16bcba5817e15c784b9d2500b32cb50f86c1b3c033c652193cc00","version_id":"sg:material/path-sha256-21ffb3e535a16bcba5817e15c784b9d2500b32cb50f86c1b3c033c652193cc00@sha256:80ca126c59d0a5947707b01875c17487dfad7e4fc51920ad02649108971e0c55"},{"byte_length":3504,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/fluid-styles.md","schema_version":"2.0","source_sha256":"652bd2d6b33e8c1c4dc5eb7175f65c1c0c13a6268aa72ac330ef6b3cf303b5cb","stable_ref":"sg:material/path-sha256-239a2e2ec1f881ea5ae0e4f852980adaa058a8c7943fe83d8c90d8b51e02abb5","version_id":"sg:material/path-sha256-239a2e2ec1f881ea5ae0e4f852980adaa058a8c7943fe83d8c90d8b51e02abb5@sha256:652bd2d6b33e8c1c4dc5eb7175f65c1c0c13a6268aa72ac330ef6b3cf303b5cb"},{"byte_length":3506,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/ram-grid.md","schema_version":"2.0","source_sha256":"b15856b240152a9da700abb4cdd611a1f9d41cad353582eeaad79459c13f277b","stable_ref":"sg:material/path-sha256-23ce75202642f0f8901b6a413fd2a269a70166058d62e90ca4403e7a3b34cf69","version_id":"sg:material/path-sha256-23ce75202642f0f8901b6a413fd2a269a70166058d62e90ca4403e7a3b34cf69@sha256:b15856b240152a9da700abb4cdd611a1f9d41cad353582eeaad79459c13f277b"},{"byte_length":3364,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/tab-strip.md","schema_version":"2.0","source_sha256":"c154f4a8cfd4d17d60f929bf363a632ca4bacedc4a5e55c891870a2a75ccd628","stable_ref":"sg:material/path-sha256-2567793e03725c0bb9b1b4cd1524b38c8240253b4989e3413b7985cfccfb4453","version_id":"sg:material/path-sha256-2567793e03725c0bb9b1b4cd1524b38c8240253b4989e3413b7985cfccfb4453@sha256:c154f4a8cfd4d17d60f929bf363a632ca4bacedc4a5e55c891870a2a75ccd628"},{"byte_length":3735,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/list-detail.md","schema_version":"2.0","source_sha256":"cbb8c05e85605aa2217027a946aae1fd7d3ed7c3981d7f15b2207c7dee8f9c6d","stable_ref":"sg:material/path-sha256-26867cd73e9ea9a732763de098fa0e99861d6bd15deba26359727ef68417e331","version_id":"sg:material/path-sha256-26867cd73e9ea9a732763de098fa0e99861d6bd15deba26359727ef68417e331@sha256:cbb8c05e85605aa2217027a946aae1fd7d3ed7c3981d7f15b2207c7dee8f9c6d"},{"byte_length":3827,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/sticky-aside.md","schema_version":"2.0","source_sha256":"69bd3b575b0c2aca46858e887cc5fbccbf5f772e4678ac305257307c70a378ab","stable_ref":"sg:material/path-sha256-27b1e5216a098387ab5e1de9d8997391ae2e8b3388331c221e14ed5946734415","version_id":"sg:material/path-sha256-27b1e5216a098387ab5e1de9d8997391ae2e8b3388331c221e14ed5946734415@sha256:69bd3b575b0c2aca46858e887cc5fbccbf5f772e4678ac305257307c70a378ab"},{"byte_length":3972,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/fixed-sidenav-shell.md","schema_version":"2.0","source_sha256":"4889d7aaf9a7ab4687b56e19987782afdc40def1935882213510958d4c747560","stable_ref":"sg:material/path-sha256-29d4e1dee690708b4218d8b195f08e1135f76b279ebaadbafd08aa74286daa28","version_id":"sg:material/path-sha256-29d4e1dee690708b4218d8b195f08e1135f76b279ebaadbafd08aa74286daa28@sha256:4889d7aaf9a7ab4687b56e19987782afdc40def1935882213510958d4c747560"},{"byte_length":3636,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/switcher.md","schema_version":"2.0","source_sha256":"f9e24b044790472cee533fe85da5d0b14e252c5119a0b532f5ff00be2f74ca4d","stable_ref":"sg:material/path-sha256-2dd9316398e52cf61361bfae39e601e73eb411b74ddc09cadf131183e6c18093","version_id":"sg:material/path-sha256-2dd9316398e52cf61361bfae39e601e73eb411b74ddc09cadf131183e6c18093@sha256:f9e24b044790472cee533fe85da5d0b14e252c5119a0b532f5ff00be2f74ca4d"},{"byte_length":1783,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/sources.md","schema_version":"2.0","source_sha256":"655c4c304f1dae83e56e5f3f19838db7b9681a600b161532cc4389574594fde8","stable_ref":"sg:material/path-sha256-31c57866c230c6e93dd2b4636e6e892eeff33521ef07ed24cde34094c2d9c939","version_id":"sg:material/path-sha256-31c57866c230c6e93dd2b4636e6e892eeff33521ef07ed24cde34094c2d9c939@sha256:655c4c304f1dae83e56e5f3f19838db7b9681a600b161532cc4389574594fde8"},{"byte_length":2906,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/command-surface.md","schema_version":"2.0","source_sha256":"b52b18adcaf95110d9ba7780289c2c2e6e4b128327290e18da1723b019261f02","stable_ref":"sg:material/path-sha256-33c5ebfda703b62fe98e750cf800d6a690eb3c5e02c0089d0fd91d987b2b5f8f","version_id":"sg:material/path-sha256-33c5ebfda703b62fe98e750cf800d6a690eb3c5e02c0089d0fd91d987b2b5f8f@sha256:b52b18adcaf95110d9ba7780289c2c2e6e4b128327290e18da1723b019261f02"},{"byte_length":3479,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/sticky-header.md","schema_version":"2.0","source_sha256":"3a5aeacbaa7f9ea443c92848667b7a6d362bd5f4481c304b0bb312549d330a94","stable_ref":"sg:material/path-sha256-3901860520475e0bf9a7a0d9a7684ce518e7f2c96d22f3aefb66fe40c524558d","version_id":"sg:material/path-sha256-3901860520475e0bf9a7a0d9a7684ce518e7f2c96d22f3aefb66fe40c524558d@sha256:3a5aeacbaa7f9ea443c92848667b7a6d362bd5f4481c304b0bb312549d330a94"},{"byte_length":14817,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/ui-systems.md","schema_version":"2.0","source_sha256":"fc9baf57a82a393d5f7b189fa7798d1023757d2bc9ed769fb6cbab7b9bbb5c40","stable_ref":"sg:material/path-sha256-3a18eb0e207f57d2657185e6e09afddd94b8d9722418d78d39122b6bb06b7098","version_id":"sg:material/path-sha256-3a18eb0e207f57d2657185e6e09afddd94b8d9722418d78d39122b6bb06b7098@sha256:fc9baf57a82a393d5f7b189fa7798d1023757d2bc9ed769fb6cbab7b9bbb5c40"},{"byte_length":579,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/index.md","schema_version":"2.0","source_sha256":"90f2d5973bf08cfd7ba55523176d8bb76bff441a8a3b9e69c3a520118db3e101","stable_ref":"sg:material/path-sha256-3bf8fac99ec13ef32824ded352565692d56cc7c54e5392b7985df262ba35e760","version_id":"sg:material/path-sha256-3bf8fac99ec13ef32824ded352565692d56cc7c54e5392b7985df262ba35e760@sha256:90f2d5973bf08cfd7ba55523176d8bb76bff441a8a3b9e69c3a520118db3e101"},{"byte_length":4405,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/screen-hierarchy.md","schema_version":"2.0","source_sha256":"a186fd1ff27b84394fdf31011eee733d5b5cc40e6e83069dc4df41b52809f552","stable_ref":"sg:material/path-sha256-3d5fe3355a6206218a13433abbd642bc623d90ee2bcb48dbf488a592bec8fb17","version_id":"sg:material/path-sha256-3d5fe3355a6206218a13433abbd642bc623d90ee2bcb48dbf488a592bec8fb17@sha256:a186fd1ff27b84394fdf31011eee733d5b5cc40e6e83069dc4df41b52809f552"},{"byte_length":3466,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/dense-grid.md","schema_version":"2.0","source_sha256":"5c99ebab2a33fe1827fee2810e340fc44867439352462dc453ec352f78e34e52","stable_ref":"sg:material/path-sha256-3d9a239e6bc90b85b6d15102c961f1ca0615094fe1df289c6e4d6a418af1801a","version_id":"sg:material/path-sha256-3d9a239e6bc90b85b6d15102c961f1ca0615094fe1df289c6e4d6a418af1801a@sha256:5c99ebab2a33fe1827fee2810e340fc44867439352462dc453ec352f78e34e52"},{"byte_length":2608,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/reference-record.md","schema_version":"2.0","source_sha256":"f43c57cf386b787c73c6e2974044b21c4ad0e1c05dd080003a3f6e268f63f4c9","stable_ref":"sg:material/path-sha256-3e5f771aba328b1394ddd2e529e322ecb8fe2259c33b92448c0c71161e3a5ff9","version_id":"sg:material/path-sha256-3e5f771aba328b1394ddd2e529e322ecb8fe2259c33b92448c0c71161e3a5ff9@sha256:f43c57cf386b787c73c6e2974044b21c4ad0e1c05dd080003a3f6e268f63f4c9"},{"byte_length":873,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/index.md","schema_version":"2.0","source_sha256":"89729f69e1a879742421b2d583dcf67f8a9a94ed90a198e5b7b9e40b856a404e","stable_ref":"sg:material/path-sha256-44cd370aff03553cea434398290dfe059d49fd316157face88e54035c050b5f5","version_id":"sg:material/path-sha256-44cd370aff03553cea434398290dfe059d49fd316157face88e54035c050b5f5@sha256:89729f69e1a879742421b2d583dcf67f8a9a94ed90a198e5b7b9e40b856a404e"},{"byte_length":2697,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/dashboard.md","schema_version":"2.0","source_sha256":"8ee1c7c8b70bfd63144fbdd5f3a55f8736ce4626c35a391f4a722b579ec2232d","stable_ref":"sg:material/path-sha256-463cfb73f926bbdf90d68b3aee7af299b388384e6b5e51e1c7a5ef2cd33aef83","version_id":"sg:material/path-sha256-463cfb73f926bbdf90d68b3aee7af299b388384e6b5e51e1c7a5ef2cd33aef83@sha256:8ee1c7c8b70bfd63144fbdd5f3a55f8736ce4626c35a391f4a722b579ec2232d"},{"byte_length":15345,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/architecture.md","schema_version":"2.0","source_sha256":"026af25031c537dd074e7bc91f00fa91e1dcaecbefe6a9c6a574e05a662adff4","stable_ref":"sg:material/path-sha256-49ac4d11b609a7dd49ecd0d397a7a5401595c3e2835958e35b430be5883d7592","version_id":"sg:material/path-sha256-49ac4d11b609a7dd49ecd0d397a7a5401595c3e2835958e35b430be5883d7592@sha256:026af25031c537dd074e7bc91f00fa91e1dcaecbefe6a9c6a574e05a662adff4"},{"byte_length":3538,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/grid-wrapper.md","schema_version":"2.0","source_sha256":"55c90e01efd81fe7f338ab8e6535d731df8f0ce1c00751d8ba4ddde780963b29","stable_ref":"sg:material/path-sha256-4a8a96f82fbd1527cc6f7ee248ef7a8ab8d47289a31dfb521f865d49f0376afb","version_id":"sg:material/path-sha256-4a8a96f82fbd1527cc6f7ee248ef7a8ab8d47289a31dfb521f865d49f0376afb@sha256:55c90e01efd81fe7f338ab8e6535d731df8f0ce1c00751d8ba4ddde780963b29"},{"byte_length":3678,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/imposter.md","schema_version":"2.0","source_sha256":"4f71b8e9164daf01d1c977c0a7ebb18576185138068a06df5d67e89d3bf7ad1c","stable_ref":"sg:material/path-sha256-4c3aeb4771622f79b0f3efdeb40e0f59064925f4bd60e63186452c0a79941a3e","version_id":"sg:material/path-sha256-4c3aeb4771622f79b0f3efdeb40e0f59064925f4bd60e63186452c0a79941a3e@sha256:4f71b8e9164daf01d1c977c0a7ebb18576185138068a06df5d67e89d3bf7ad1c"},{"byte_length":3458,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/center.md","schema_version":"2.0","source_sha256":"8abae0c076bf8c3eeeefd8920dff8c9d767c5c59ef926265b960940bab8310da","stable_ref":"sg:material/path-sha256-4fb5bdea440d75d58bcb66874cdb2930ee9cd5d17768bba1ea95e4c3c547ebd5","version_id":"sg:material/path-sha256-4fb5bdea440d75d58bcb66874cdb2930ee9cd5d17768bba1ea95e4c3c547ebd5@sha256:8abae0c076bf8c3eeeefd8920dff8c9d767c5c59ef926265b960940bab8310da"},{"byte_length":6061,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/practice-reference.md","schema_version":"2.0","source_sha256":"1096eae09dd6a90ae83c9979728c5774c4242dae68f71ee12e97496c87d0ba2d","stable_ref":"sg:material/path-sha256-50b685f66086b3f2362d97feb7e001bd2f208e6ea33c52174edf66fbe8287265","version_id":"sg:material/path-sha256-50b685f66086b3f2362d97feb7e001bd2f208e6ea33c52174edf66fbe8287265@sha256:1096eae09dd6a90ae83c9979728c5774c4242dae68f71ee12e97496c87d0ba2d"},{"byte_length":3428,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/clamped-card.md","schema_version":"2.0","source_sha256":"14e9700b95e01bdbf22be445ec79245209be097cfcff92c33a0aa37bcf2d564b","stable_ref":"sg:material/path-sha256-52157f6d777be20078f71c3c850955175151fdbe04fad86368b8f0e382280631","version_id":"sg:material/path-sha256-52157f6d777be20078f71c3c850955175151fdbe04fad86368b8f0e382280631@sha256:14e9700b95e01bdbf22be445ec79245209be097cfcff92c33a0aa37bcf2d564b"},{"byte_length":7878,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/contract.md","schema_version":"2.0","source_sha256":"b914920989ff2ce08ebc67fa3167d0da766c260c93f03257a9144c6093ff6713","stable_ref":"sg:material/path-sha256-52494ee56bf5c837ead0782244d579ea0aba9e63e95a02c10f6d0b566e4d62d9","version_id":"sg:material/path-sha256-52494ee56bf5c837ead0782244d579ea0aba9e63e95a02c10f6d0b566e4d62d9@sha256:b914920989ff2ce08ebc67fa3167d0da766c260c93f03257a9144c6093ff6713"},{"byte_length":8606,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/search-metadata-polyhierarchy.md","schema_version":"2.0","source_sha256":"53ea6fddbf9c446a2b35ca6d975200c274ba3a713a2298ff62c8253d6c8a49d7","stable_ref":"sg:material/path-sha256-59a41c8893a1ad96d4b5abe1cfb6e381273ce32030b84b06cdbd2ac8be24dc74","version_id":"sg:material/path-sha256-59a41c8893a1ad96d4b5abe1cfb6e381273ce32030b84b06cdbd2ac8be24dc74@sha256:53ea6fddbf9c446a2b35ca6d975200c274ba3a713a2298ff62c8253d6c8a49d7"},{"byte_length":3490,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/columns.md","schema_version":"2.0","source_sha256":"eda07657f498d69a734749ba4c94a6fd35e4b1f61cf312324460e0b4e491d324","stable_ref":"sg:material/path-sha256-5a76c5ad4c7daff2cbf3fbf8d8968f56204322f508b999f77e87bcbe6274a8de","version_id":"sg:material/path-sha256-5a76c5ad4c7daff2cbf3fbf8d8968f56204322f508b999f77e87bcbe6274a8de@sha256:eda07657f498d69a734749ba4c94a6fd35e4b1f61cf312324460e0b4e491d324"},{"byte_length":12162,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/org-wiki.md","schema_version":"2.0","source_sha256":"b6fcdef8d5b6524111cabfef7a0b86e2f899659e5d7d7e81e8ebd521e79dd131","stable_ref":"sg:material/path-sha256-5de69acbec858ebe75c9483c1b4474ea8d48778aedc3cc654a26552b3a49a5f5","version_id":"sg:material/path-sha256-5de69acbec858ebe75c9483c1b4474ea8d48778aedc3cc654a26552b3a49a5f5@sha256:b6fcdef8d5b6524111cabfef7a0b86e2f899659e5d7d7e81e8ebd521e79dd131"},{"byte_length":876,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/tokens.md","schema_version":"2.0","source_sha256":"9f6849985944fea6c660c6ce8f1a962b1b3fe4aa195e72ef2d2293b27fac80f0","stable_ref":"sg:material/path-sha256-5e265c863940f92cadc3da208c4c09c4aacd7da3425332edc401bbb461383e30","version_id":"sg:material/path-sha256-5e265c863940f92cadc3da208c4c09c4aacd7da3425332edc401bbb461383e30@sha256:9f6849985944fea6c660c6ce8f1a962b1b3fe4aa195e72ef2d2293b27fac80f0"},{"byte_length":537,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/index.md","schema_version":"2.0","source_sha256":"93635d8fec49e448550ac671d0fe2510ecc017467ff79203bf10bc3e9b32a9d4","stable_ref":"sg:material/path-sha256-5e7498d507fe35d8607873d31efa80b8e4634fa59aa68fdb3cc10fcd99df20c6","version_id":"sg:material/path-sha256-5e7498d507fe35d8607873d31efa80b8e4634fa59aa68fdb3cc10fcd99df20c6@sha256:93635d8fec49e448550ac671d0fe2510ecc017467ff79203bf10bc3e9b32a9d4"},{"byte_length":3682,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/deconstructed-pancake.md","schema_version":"2.0","source_sha256":"81a69e4a12a2f967a0ecff31d02c3beb365bf6c9055acc86cda4f6355f70adbe","stable_ref":"sg:material/path-sha256-651d978327dca78d036202b232058a85e240ada94d07dd7461bc894f9f83e5e2","version_id":"sg:material/path-sha256-651d978327dca78d036202b232058a85e240ada94d07dd7461bc894f9f83e5e2@sha256:81a69e4a12a2f967a0ecff31d02c3beb365bf6c9055acc86cda4f6355f70adbe"},{"byte_length":3735,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/main-with-rail.md","schema_version":"2.0","source_sha256":"ba1cfc18e294563b48fbaa2cb427dc431b4586d55a157818a541cba25d0a0160","stable_ref":"sg:material/path-sha256-653b926534bf6d8d074f03173f13f475bada8dfa566852e272470fc17b8e58d4","version_id":"sg:material/path-sha256-653b926534bf6d8d074f03173f13f475bada8dfa566852e272470fc17b8e58d4@sha256:ba1cfc18e294563b48fbaa2cb427dc431b4586d55a157818a541cba25d0a0160"},{"byte_length":3910,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/media-object.md","schema_version":"2.0","source_sha256":"26f218d8b2138e7a7f4585e21d33d6f640d5b67993a64e182bdef9b4628d7dae","stable_ref":"sg:material/path-sha256-69e5cbcca6fba542020d47eeb31222d719c39624ec41749d591d17aa175c5f3a","version_id":"sg:material/path-sha256-69e5cbcca6fba542020d47eeb31222d719c39624ec41749d591d17aa175c5f3a@sha256:26f218d8b2138e7a7f4585e21d33d6f640d5b67993a64e182bdef9b4628d7dae"},{"byte_length":1163,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/index.md","schema_version":"2.0","source_sha256":"304f07851551513750ee3d00e4023ad2b5500944c8c504587b3e14856179fd3c","stable_ref":"sg:material/path-sha256-6c243b28fd8f4564a96217bcceabc75a5651ecd21ac41abfbdd4716adc60aa72","version_id":"sg:material/path-sha256-6c243b28fd8f4564a96217bcceabc75a5651ecd21ac41abfbdd4716adc60aa72@sha256:304f07851551513750ee3d00e4023ad2b5500944c8c504587b3e14856179fd3c"},{"byte_length":6999,"domain":"shared","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/agent-native/README.md","schema_version":"2.0","source_sha256":"959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e","stable_ref":"sg:material/path-sha256-6cda345129c13188719d0116beef1e7d8e672f951f21295bc3b2ccf490a4a81d","version_id":"sg:material/path-sha256-6cda345129c13188719d0116beef1e7d8e672f951f21295bc3b2ccf490a4a81d@sha256:959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e"},{"byte_length":3146,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"log.md","schema_version":"2.0","source_sha256":"ebbaf9b22d6924714a1bb6069bab4622ffe9fd0aad76c6cf718cd76cff7b2eb9","stable_ref":"sg:material/path-sha256-7204c0a4f935b2563fdb9fcf74d71a2e8621bf1b53f9da1b6eab41597a5fbc38","version_id":"sg:material/path-sha256-7204c0a4f935b2563fdb9fcf74d71a2e8621bf1b53f9da1b6eab41597a5fbc38@sha256:ebbaf9b22d6924714a1bb6069bab4622ffe9fd0aad76c6cf718cd76cff7b2eb9"},{"byte_length":3574,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/reel.md","schema_version":"2.0","source_sha256":"57a66f71da9293c1037d325a3d98d95938b7a7534e42cc8f3d1149ef63ab5480","stable_ref":"sg:material/path-sha256-72616dfa2b53176365ef81dd6954260a8a96051f3c47100505ece70816871c11","version_id":"sg:material/path-sha256-72616dfa2b53176365ef81dd6954260a8a96051f3c47100505ece70816871c11@sha256:57a66f71da9293c1037d325a3d98d95938b7a7534e42cc8f3d1149ef63ab5480"},{"byte_length":3614,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/sticky-footer.md","schema_version":"2.0","source_sha256":"4103c4b74e4b143705a656f11662ec03721b40802c980e4527331f97b09c21df","stable_ref":"sg:material/path-sha256-7412ca94f2f7e6e9b81ec40ccbaee7ccab5a773e48d7fc14055baccd8d059d42","version_id":"sg:material/path-sha256-7412ca94f2f7e6e9b81ec40ccbaee7ccab5a773e48d7fc14055baccd8d059d42@sha256:4103c4b74e4b143705a656f11662ec03721b40802c980e4527331f97b09c21df"},{"byte_length":14420,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/documentation-mode-taxonomy.md","schema_version":"2.0","source_sha256":"872594fdfa78c4196bad9eae4aa6bab3cde82b4f73803ef049a60c6a7db329c2","stable_ref":"sg:material/path-sha256-78dcee9e03982b489be85a59bb522877c94bb01b2624af09e5ef5e3bc3bbbffc","version_id":"sg:material/path-sha256-78dcee9e03982b489be85a59bb522877c94bb01b2624af09e5ef5e3bc3bbbffc@sha256:872594fdfa78c4196bad9eae4aa6bab3cde82b4f73803ef049a60c6a7db329c2"},{"byte_length":2791,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/list-detail.md","schema_version":"2.0","source_sha256":"26c00df6db757fa392dd285eb910de9c13eae39c78ab97c44dda55cea9047899","stable_ref":"sg:material/path-sha256-7b47a26ca3030528440849547a9a39dcd489581ebdb0b3c85f3204cf066acaa8","version_id":"sg:material/path-sha256-7b47a26ca3030528440849547a9a39dcd489581ebdb0b3c85f3204cf066acaa8@sha256:26c00df6db757fa392dd285eb910de9c13eae39c78ab97c44dda55cea9047899"},{"byte_length":3687,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/line-up.md","schema_version":"2.0","source_sha256":"34ccb96fb46cbfe6567ffb74a8f01fd79ac3baf0ea4ed93e54cab83ac45473dc","stable_ref":"sg:material/path-sha256-7c2f9831fd891304724438057614dab34b1fff1da4eb2f0d86803115be5a3ce5","version_id":"sg:material/path-sha256-7c2f9831fd891304724438057614dab34b1fff1da4eb2f0d86803115be5a3ce5@sha256:34ccb96fb46cbfe6567ffb74a8f01fd79ac3baf0ea4ed93e54cab83ac45473dc"},{"byte_length":11419,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/cli-loop.md","schema_version":"2.0","source_sha256":"bfc9596a0b981bbb31470f4c8a87578d401f775fa1f9b4dc6da1e0f967ca3f1b","stable_ref":"sg:material/path-sha256-7c4697a9eca2beda5a21f7edd84648e7e67643b3f67b771434ed123c424a2d1a","version_id":"sg:material/path-sha256-7c4697a9eca2beda5a21f7edd84648e7e67643b3f67b771434ed123c424a2d1a@sha256:bfc9596a0b981bbb31470f4c8a87578d401f775fa1f9b4dc6da1e0f967ca3f1b"},{"byte_length":4740,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/review-workflow.md","schema_version":"2.0","source_sha256":"5219296be498f37f9d9b69ba4723f2ce7d12b5d326fec20045b2aedcc6c90746","stable_ref":"sg:material/path-sha256-7df8e54fd5935c4a2a9aace117d43253e7c0fe32448fd31984a531a134192a83","version_id":"sg:material/path-sha256-7df8e54fd5935c4a2a9aace117d43253e7c0fe32448fd31984a531a134192a83@sha256:5219296be498f37f9d9b69ba4723f2ce7d12b5d326fec20045b2aedcc6c90746"},{"byte_length":2625,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/form-flow.md","schema_version":"2.0","source_sha256":"ff6cee7485991ff766a7d3d0780a133da5a636639aa9ff4a43e4d3bb0499a538","stable_ref":"sg:material/path-sha256-7e60233e663192c6172a4cebabf93da3b047c42bbaddee206fa27644d8d821e9","version_id":"sg:material/path-sha256-7e60233e663192c6172a4cebabf93da3b047c42bbaddee206fa27644d8d821e9@sha256:ff6cee7485991ff766a7d3d0780a133da5a636639aa9ff4a43e4d3bb0499a538"},{"byte_length":8688,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/vocabulary.md","schema_version":"2.0","source_sha256":"8b5d68d428b12ce2d2b399cddf98aef0b0761189838cac223bbfbac4d2c10da8","stable_ref":"sg:material/path-sha256-7ec7a08ac14b5af0def43c817f1b32765f93312bb997e17663313c0fd4516a1f","version_id":"sg:material/path-sha256-7ec7a08ac14b5af0def43c817f1b32765f93312bb997e17663313c0fd4516a1f@sha256:8b5d68d428b12ce2d2b399cddf98aef0b0761189838cac223bbfbac4d2c10da8"},{"byte_length":5787,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/decision-tree.md","schema_version":"2.0","source_sha256":"5811d48b577a0d9472c64b94cb91341f45e5b5408402455f0aa9cd356fa15c5d","stable_ref":"sg:material/path-sha256-7fada8e2c9a6ab17c122f51121605bc9d4c64c9a7ef60d946813129f91474016","version_id":"sg:material/path-sha256-7fada8e2c9a6ab17c122f51121605bc9d4c64c9a7ef60d946813129f91474016@sha256:5811d48b577a0d9472c64b94cb91341f45e5b5408402455f0aa9cd356fa15c5d"},{"byte_length":7930,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/layout-brief.md","schema_version":"2.0","source_sha256":"0e87d9d8f51ab6f3960b8e160abd9663be0d501e801a3184686b27c9a1debbf5","stable_ref":"sg:material/path-sha256-8305d3db8a3a860213c04b8cef5a4ed463a109f558be8df51ff1c5af21d749e1","version_id":"sg:material/path-sha256-8305d3db8a3a860213c04b8cef5a4ed463a109f558be8df51ff1c5af21d749e1@sha256:0e87d9d8f51ab6f3960b8e160abd9663be0d501e801a3184686b27c9a1debbf5"},{"byte_length":8203,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/pattern-contract-audit.md","schema_version":"2.0","source_sha256":"35926d5a3313f1918035ae906844722bbe56c7494eff9e5b22a2306a681893af","stable_ref":"sg:material/path-sha256-871ee653f2589835e85184dba2e5ef403fc064d0d49a2b2b85f0b8996d351fc6","version_id":"sg:material/path-sha256-871ee653f2589835e85184dba2e5ef403fc064d0d49a2b2b85f0b8996d351fc6@sha256:35926d5a3313f1918035ae906844722bbe56c7494eff9e5b22a2306a681893af"},{"byte_length":11836,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/webpage-generation-workflow.md","schema_version":"2.0","source_sha256":"92de1966d23f3d12625f9cc22fb256eb8c4761bd4371a96ba69ca5235a23c7d4","stable_ref":"sg:material/path-sha256-87436c736fec1b7b05f6f0a824b06c852e9295daca92298163e02024fbb0451b","version_id":"sg:material/path-sha256-87436c736fec1b7b05f6f0a824b06c852e9295daca92298163e02024fbb0451b@sha256:92de1966d23f3d12625f9cc22fb256eb8c4761bd4371a96ba69ca5235a23c7d4"},{"byte_length":3615,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/frame.md","schema_version":"2.0","source_sha256":"649d3da72d9af6e6be2cdcd63561da9acb5521a0f44e46cc3210f02ece211104","stable_ref":"sg:material/path-sha256-882d5f2d004ba4375887b0489d4c452e3a6b3cfaea23561ba59e4e56821da256","version_id":"sg:material/path-sha256-882d5f2d004ba4375887b0489d4c452e3a6b3cfaea23561ba59e4e56821da256@sha256:649d3da72d9af6e6be2cdcd63561da9acb5521a0f44e46cc3210f02ece211104"},{"byte_length":3419,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/feed.md","schema_version":"2.0","source_sha256":"7f79317d1cb795bf3c407fabe5b4a894a2645dd4c732856f1bc07b05cb620e53","stable_ref":"sg:material/path-sha256-88b6e0985d823e16fad9888dd2133bb5e3c2a2203e3a1623a705ac883ea4a00c","version_id":"sg:material/path-sha256-88b6e0985d823e16fad9888dd2133bb5e3c2a2203e3a1623a705ac883ea4a00c@sha256:7f79317d1cb795bf3c407fabe5b4a894a2645dd4c732856f1bc07b05cb620e53"},{"byte_length":936,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/index.md","schema_version":"2.0","source_sha256":"973dabb4a682d02c0a60d611ae73c2b531f38fb2a3e3d2682f37a385c3f2f726","stable_ref":"sg:material/path-sha256-8a81d81ebc22075986a7fe5af4720c2779c2a456382fc0a3e74c1bfc8bb0f958","version_id":"sg:material/path-sha256-8a81d81ebc22075986a7fe5af4720c2779c2a456382fc0a3e74c1bfc8bb0f958@sha256:973dabb4a682d02c0a60d611ae73c2b531f38fb2a3e3d2682f37a385c3f2f726"},{"byte_length":3397,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/icon-frame.md","schema_version":"2.0","source_sha256":"09f79480d11a25c4ec7a9fbcdda2b62fa89ddf0da7142545841c3648078aa569","stable_ref":"sg:material/path-sha256-9100c52308320464deed2d7e13eb9857e485784f12f2dc1de28e8b73bc8f936b","version_id":"sg:material/path-sha256-9100c52308320464deed2d7e13eb9857e485784f12f2dc1de28e8b73bc8f936b@sha256:09f79480d11a25c4ec7a9fbcdda2b62fa89ddf0da7142545841c3648078aa569"},{"byte_length":6658,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/apple-interaction.md","schema_version":"2.0","source_sha256":"e4013b5498a2ff7b0613b9c17a8fd6a31e1cb799c08f062dfbb2bf540e713cea","stable_ref":"sg:material/path-sha256-9247a878dcd0a0977374938c50eeb9a622ad6203847c1169beaf81d0493ebb5b","version_id":"sg:material/path-sha256-9247a878dcd0a0977374938c50eeb9a622ad6203847c1169beaf81d0493ebb5b@sha256:e4013b5498a2ff7b0613b9c17a8fd6a31e1cb799c08f062dfbb2bf540e713cea"},{"byte_length":4774,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/classification.md","schema_version":"2.0","source_sha256":"3ad0db32a74ddfcd4061cd35ee30cda764b9d1074599942001067f7a80b8f623","stable_ref":"sg:material/path-sha256-92725878c1f37c55731de2baf9c14a768fbd24ca839b82830c89f4aed7b66dce","version_id":"sg:material/path-sha256-92725878c1f37c55731de2baf9c14a768fbd24ca839b82830c89f4aed7b66dce@sha256:3ad0db32a74ddfcd4061cd35ee30cda764b9d1074599942001067f7a80b8f623"},{"byte_length":3457,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/wrap-row.md","schema_version":"2.0","source_sha256":"214d9e3d94366841f37f90c4c62096302c36f218843668e72c9a8850f6675920","stable_ref":"sg:material/path-sha256-94d8cf97bb7801865552f7d2b317b556ed6b643d53b73fad134de89186263585","version_id":"sg:material/path-sha256-94d8cf97bb7801865552f7d2b317b556ed6b643d53b73fad134de89186263585@sha256:214d9e3d94366841f37f90c4c62096302c36f218843668e72c9a8850f6675920"},{"byte_length":2502,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/families.md","schema_version":"2.0","source_sha256":"0e80ebefdc5a7c266c46f48342a9c6389eb5390d5f8c0f6f162f852c4b596690","stable_ref":"sg:material/path-sha256-956ab860e593d435b6682540b04365917b3736deb47207b5812065776734de0b","version_id":"sg:material/path-sha256-956ab860e593d435b6682540b04365917b3736deb47207b5812065776734de0b@sha256:0e80ebefdc5a7c266c46f48342a9c6389eb5390d5f8c0f6f162f852c4b596690"},{"byte_length":3678,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/badge-list.md","schema_version":"2.0","source_sha256":"aec85df4d5ddcfc08e9c052c5fdf60c0d4a73dbe8fea5a95b78b90c9871f1984","stable_ref":"sg:material/path-sha256-96fc7d48dad3399ab0cbedfdf8cb508b1732f57dc96cd15911e50a3a1654c9b1","version_id":"sg:material/path-sha256-96fc7d48dad3399ab0cbedfdf8cb508b1732f57dc96cd15911e50a3a1654c9b1@sha256:aec85df4d5ddcfc08e9c052c5fdf60c0d4a73dbe8fea5a95b78b90c9871f1984"},{"byte_length":952,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/visual-qa.md","schema_version":"2.0","source_sha256":"9fdfd9acdcd4fefd4f2d3ef51ba6170e3235d4ae97cc6c739a0f1123e1825f74","stable_ref":"sg:material/path-sha256-970cc2193de22b50bd91099cd6f8e5f52069ccd3360306d17e6eacf4ed1343ae","version_id":"sg:material/path-sha256-970cc2193de22b50bd91099cd6f8e5f52069ccd3360306d17e6eacf4ed1343ae@sha256:9fdfd9acdcd4fefd4f2d3ef51ba6170e3235d4ae97cc6c739a0f1123e1825f74"},{"byte_length":9489,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/primitive-to-recipe-matrix.md","schema_version":"2.0","source_sha256":"0e8b3b90651c8820a0c0463c32bf410e40abb7503a26e9c90b1fdb456d4ad7b3","stable_ref":"sg:material/path-sha256-99427f2ded107b0d7be95e3a768ac836b917b22c8736fb7f31028b33a333836d","version_id":"sg:material/path-sha256-99427f2ded107b0d7be95e3a768ac836b917b22c8736fb7f31028b33a333836d@sha256:0e8b3b90651c8820a0c0463c32bf410e40abb7503a26e9c90b1fdb456d4ad7b3"},{"byte_length":3743,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/supporting-pane.md","schema_version":"2.0","source_sha256":"bbffaf1bcf0daa4d30f5d269fda79759778b23c2f7c388d95d0ca45e0512c962","stable_ref":"sg:material/path-sha256-9a82e011fc565919a7334610d427c1ec662e2b89034c6da9a2b135dc398444da","version_id":"sg:material/path-sha256-9a82e011fc565919a7334610d427c1ec662e2b89034c6da9a2b135dc398444da@sha256:bbffaf1bcf0daa4d30f5d269fda79759778b23c2f7c388d95d0ca45e0512c962"},{"byte_length":3664,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/panel-layout.md","schema_version":"2.0","source_sha256":"1e373e1e0a03296d3262d2df4caa0a0c907693c6dfdad19d8d608b574e1ae123","stable_ref":"sg:material/path-sha256-9c016feea05fe406dddaf432e9137d8d56c71df33fb77450e538d21c9871e85f","version_id":"sg:material/path-sha256-9c016feea05fe406dddaf432e9137d8d56c71df33fb77450e538d21c9871e85f@sha256:1e373e1e0a03296d3262d2df4caa0a0c907693c6dfdad19d8d608b574e1ae123"},{"byte_length":2378,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/saas-settings.md","schema_version":"2.0","source_sha256":"f66665f62f1ac1242965326e47bd7a021ec9ed812e98155147f82be0bc00c5ad","stable_ref":"sg:material/path-sha256-9dfe65b7582876aed144b8b79ad8ffbde14182c8b9c082c6916057782509cd0e","version_id":"sg:material/path-sha256-9dfe65b7582876aed144b8b79ad8ffbde14182c8b9c082c6916057782509cd0e@sha256:f66665f62f1ac1242965326e47bd7a021ec9ed812e98155147f82be0bc00c5ad"},{"byte_length":2169,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/article-page.md","schema_version":"2.0","source_sha256":"e68b1049e6e2e0dd08e87c1b5dd8ef36f42350c161aa6d056f5ddcdbb091d28d","stable_ref":"sg:material/path-sha256-a0c4596e930ce74c5bf8f890a6e037abbd07463c1e1aa0b35c40a0c2009ba011","version_id":"sg:material/path-sha256-a0c4596e930ce74c5bf8f890a6e037abbd07463c1e1aa0b35c40a0c2009ba011@sha256:e68b1049e6e2e0dd08e87c1b5dd8ef36f42350c161aa6d056f5ddcdbb091d28d"},{"byte_length":3306,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"index.md","schema_version":"2.0","source_sha256":"24db0f026c37844f3e379021798152f17c850beb39159c7f368253524ebe7ff8","stable_ref":"sg:material/path-sha256-a48746cae70c44e7e105b594aad338ddd105c93c1cb445a40ba6aab785ba69e5","version_id":"sg:material/path-sha256-a48746cae70c44e7e105b594aad338ddd105c93c1cb445a40ba6aab785ba69e5@sha256:24db0f026c37844f3e379021798152f17c850beb39159c7f368253524ebe7ff8"},{"byte_length":10562,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/repository-map.md","schema_version":"2.0","source_sha256":"aa6535fe435bc831a819f9f82ed29ad593ec133cc4f84be231355879ce145f9e","stable_ref":"sg:material/path-sha256-a4f5bfbc74a2b756b0661004893a21d81b1007879d2e2c4aaa4b73f1b083d434","version_id":"sg:material/path-sha256-a4f5bfbc74a2b756b0661004893a21d81b1007879d2e2c4aaa4b73f1b083d434@sha256:aa6535fe435bc831a819f9f82ed29ad593ec133cc4f84be231355879ce145f9e"},{"byte_length":8721,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"AGENTS.md","schema_version":"2.0","source_sha256":"67571ee3b85430f17999189a52fc3ed871aab135e7e5127f63ee57b2ce11cd19","stable_ref":"sg:material/path-sha256-a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9","version_id":"sg:material/path-sha256-a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9@sha256:67571ee3b85430f17999189a52fc3ed871aab135e7e5127f63ee57b2ce11cd19"},{"byte_length":3493,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/card-grid.md","schema_version":"2.0","source_sha256":"e2489c93d8f312b0104e14cd54d92940f2b094e7c7a1310b6be4e0653b2729a4","stable_ref":"sg:material/path-sha256-a5e3ff6fe0948ebbaf30def7866421563073877df12336c5f66eba3d2d6667a5","version_id":"sg:material/path-sha256-a5e3ff6fe0948ebbaf30def7866421563073877df12336c5f66eba3d2d6667a5@sha256:e2489c93d8f312b0104e14cd54d92940f2b094e7c7a1310b6be4e0653b2729a4"},{"byte_length":1194,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/index.md","schema_version":"2.0","source_sha256":"c52bbc8df395ff56e4cad12ced76ba5ee55f4a95c49efaf53825d13c32feab49","stable_ref":"sg:material/path-sha256-a7987410bcf408a5b4edc0ae7719d3f57f1f04a4efaaa7a756c870677307fd85","version_id":"sg:material/path-sha256-a7987410bcf408a5b4edc0ae7719d3f57f1f04a4efaaa7a756c870677307fd85@sha256:c52bbc8df395ff56e4cad12ced76ba5ee55f4a95c49efaf53825d13c32feab49"},{"byte_length":886,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/index.md","schema_version":"2.0","source_sha256":"8687d8285459805273e27f5ca9b5fcd10fbd0899786443445666155630bbf4bb","stable_ref":"sg:material/path-sha256-aa41c9d5c021c9d6a6e06df6c53297c0d271f71b3a299303d8a330644f6998f1","version_id":"sg:material/path-sha256-aa41c9d5c021c9d6a6e06df6c53297c0d271f71b3a299303d8a330644f6998f1@sha256:8687d8285459805273e27f5ca9b5fcd10fbd0899786443445666155630bbf4bb"},{"byte_length":2510,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/stylegallery-multidomain-scope.md","schema_version":"2.0","source_sha256":"fb5f0cebaaea0998c5dd05721b2e3818a2f91e2407628c740da08877d5b94a19","stable_ref":"sg:material/path-sha256-abaaac8db5d4ad334a6b84253118bdd282aba92b9a55daf5710b2b6d6d14c399","version_id":"sg:material/path-sha256-abaaac8db5d4ad334a6b84253118bdd282aba92b9a55daf5710b2b6d6d14c399@sha256:fb5f0cebaaea0998c5dd05721b2e3818a2f91e2407628c740da08877d5b94a19"},{"byte_length":17580,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"README.md","schema_version":"2.0","source_sha256":"2ce02c5d9adec638ec8d0fb0ea91a23f698cce5218123c553550d0577cfccb50","stable_ref":"sg:material/path-sha256-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5","version_id":"sg:material/path-sha256-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5@sha256:2ce02c5d9adec638ec8d0fb0ea91a23f698cce5218123c553550d0577cfccb50"},{"byte_length":29668,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"GOVERNANCE.md","schema_version":"2.0","source_sha256":"b892e0df464b0527b50b201830db7ab87507069862281e7781ad1eecb56f77b7","stable_ref":"sg:material/path-sha256-b60c6a93e9f74ee52e71bf33781c2870b8395c8c5a34f00f61305343cb8d8447","version_id":"sg:material/path-sha256-b60c6a93e9f74ee52e71bf33781c2870b8395c8c5a34f00f61305343cb8d8447@sha256:b892e0df464b0527b50b201830db7ab87507069862281e7781ad1eecb56f77b7"},{"byte_length":1474,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/index.md","schema_version":"2.0","source_sha256":"5ce4bd76f73388cdc252b28ee19fd7f41445064ad1278fd24591226aa94a6fac","stable_ref":"sg:material/path-sha256-b6b2ce37f6c04566c4dc6a18252e1d89fc387c7e79f4463406deff3e8b54a81f","version_id":"sg:material/path-sha256-b6b2ce37f6c04566c4dc6a18252e1d89fc387c7e79f4463406deff3e8b54a81f@sha256:5ce4bd76f73388cdc252b28ee19fd7f41445064ad1278fd24591226aa94a6fac"},{"byte_length":2699,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/accessibility-evidence.md","schema_version":"2.0","source_sha256":"fa07b1354ee7973317512b2f84d37d1f3965465962df74e9e1ee21a47f66ae4e","stable_ref":"sg:material/path-sha256-b7de05a789ffd0312cd9e9b1828ce113b1fcc3dcf5a87b73295a09e1004bfbe3","version_id":"sg:material/path-sha256-b7de05a789ffd0312cd9e9b1828ce113b1fcc3dcf5a87b73295a09e1004bfbe3@sha256:fa07b1354ee7973317512b2f84d37d1f3965465962df74e9e1ee21a47f66ae4e"},{"byte_length":6672,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"CATALOG.md","schema_version":"2.0","source_sha256":"6902e0b03d958816abc142a950cedb51a9a623c1acc5b1a7a94cc4f38a70eb8a","stable_ref":"sg:material/path-sha256-bb476268db5ed6523e97a56f61d3ec99765899bf3269949ee1aac390f48f1b99","version_id":"sg:material/path-sha256-bb476268db5ed6523e97a56f61d3ec99765899bf3269949ee1aac390f48f1b99@sha256:6902e0b03d958816abc142a950cedb51a9a623c1acc5b1a7a94cc4f38a70eb8a"},{"byte_length":3837,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/sidebar.md","schema_version":"2.0","source_sha256":"75edbf6107702e2c44f8ebdd724ec9b40ec8362729441c0ef1e073444c9ddb8e","stable_ref":"sg:material/path-sha256-bd2be8d5407fa6cf6a9bfaacf5d35e3b08eadea21e394cb0951a4e22290720a2","version_id":"sg:material/path-sha256-bd2be8d5407fa6cf6a9bfaacf5d35e3b08eadea21e394cb0951a4e22290720a2@sha256:75edbf6107702e2c44f8ebdd724ec9b40ec8362729441c0ef1e073444c9ddb8e"},{"byte_length":2932,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/consumer-migration-evidence.md","schema_version":"2.0","source_sha256":"71ad54bf72f5c968b8a0c5bd02b988660c6f441dbda13f9142d57842be498e6a","stable_ref":"sg:material/path-sha256-bd5e2b1ee33580f11a3a67b5306df57a54a539d5e944331511eb72fa9fe4e8f9","version_id":"sg:material/path-sha256-bd5e2b1ee33580f11a3a67b5306df57a54a539d5e944331511eb72fa9fe4e8f9@sha256:71ad54bf72f5c968b8a0c5bd02b988660c6f441dbda13f9142d57842be498e6a"},{"byte_length":3601,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/cover.md","schema_version":"2.0","source_sha256":"c78423cba85c44acfe985b44f7da72dfa52fdb20de2c87beb9d085062b451b6f","stable_ref":"sg:material/path-sha256-bf39299bae7cfb1c999e3d86ab9106128c573c2a83c8f2f08f14572a94f0c5a7","version_id":"sg:material/path-sha256-bf39299bae7cfb1c999e3d86ab9106128c573c2a83c8f2f08f14572a94f0c5a7@sha256:c78423cba85c44acfe985b44f7da72dfa52fdb20de2c87beb9d085062b451b6f"},{"byte_length":3660,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/twelve-span-grid.md","schema_version":"2.0","source_sha256":"7747b78dbe22604d9d4944f32ad89b8337961f76d2a8f2775c9efb7fe67ba879","stable_ref":"sg:material/path-sha256-c0d7d6f086cfa95c3163b3cf7692cee97e3e16dba0de964706bee174841d2094","version_id":"sg:material/path-sha256-c0d7d6f086cfa95c3163b3cf7692cee97e3e16dba0de964706bee174841d2094@sha256:7747b78dbe22604d9d4944f32ad89b8337961f76d2a8f2775c9efb7fe67ba879"},{"byte_length":3405,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/step-nav.md","schema_version":"2.0","source_sha256":"1b74a5b72ab2352f35f40247da26ab0eb3cecdc8a75754a071cacf263537a438","stable_ref":"sg:material/path-sha256-c1d82e696f9b42772a53643bf7ac7fbddc964e528aa09fb7f155b442660b6262","version_id":"sg:material/path-sha256-c1d82e696f9b42772a53643bf7ac7fbddc964e528aa09fb7f155b442660b6262@sha256:1b74a5b72ab2352f35f40247da26ab0eb3cecdc8a75754a071cacf263537a438"},{"byte_length":18957,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/executable-evidence.md","schema_version":"2.0","source_sha256":"a0ae7f2c355ab26293cdb9e96b31d91d50a024ed404aa0c8297a65b91af73a33","stable_ref":"sg:material/path-sha256-c609296f2ae6b1d6234dbb3497f9d6a45208ba0470a3d8b4a861be79bae797c8","version_id":"sg:material/path-sha256-c609296f2ae6b1d6234dbb3497f9d6a45208ba0470a3d8b4a861be79bae797c8@sha256:a0ae7f2c355ab26293cdb9e96b31d91d50a024ed404aa0c8297a65b91af73a33"},{"byte_length":6703,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"DOMAINS.md","schema_version":"2.0","source_sha256":"e1191677c19e33d96085de45f57d8cda9384ed1353dacb2d8c86bfc3ef0d49f3","stable_ref":"sg:material/path-sha256-d190306dc8097b7ef0ec2a57ed020076a9f325b48f083aba3f62de5e886af5ab","version_id":"sg:material/path-sha256-d190306dc8097b7ef0ec2a57ed020076a9f325b48f083aba3f62de5e886af5ab@sha256:e1191677c19e33d96085de45f57d8cda9384ed1353dacb2d8c86bfc3ef0d49f3"},{"byte_length":910,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/index.md","schema_version":"2.0","source_sha256":"fecba190f4bcb2f3e7fbce19c02181fae7613fc51da6b20539a17ef5d37e78f2","stable_ref":"sg:material/path-sha256-d312b8ccb45a40e38e38e6d6d1e95ee074d50714cdcf872de9afd4e4254a4301","version_id":"sg:material/path-sha256-d312b8ccb45a40e38e38e6d6d1e95ee074d50714cdcf872de9afd4e4254a4301@sha256:fecba190f4bcb2f3e7fbce19c02181fae7613fc51da6b20539a17ef5d37e78f2"},{"byte_length":3707,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/split-nav.md","schema_version":"2.0","source_sha256":"b797721ee74570f537fd79fbdec6077048764723f176c995341f5b8b8b1de432","stable_ref":"sg:material/path-sha256-d657fc87c00278cd49d87fb6a43b8596834943cf85f71d7cc873c102e56a5587","version_id":"sg:material/path-sha256-d657fc87c00278cd49d87fb6a43b8596834943cf85f71d7cc873c102e56a5587@sha256:b797721ee74570f537fd79fbdec6077048764723f176c995341f5b8b8b1de432"},{"byte_length":2821,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/index.md","schema_version":"2.0","source_sha256":"9402e16d92bf5f17df39d7ccfd2eb4328113e02a155abd02524a2e5482fd3d68","stable_ref":"sg:material/path-sha256-db7c4f17ca762b1169e43401710a0d95c03161ec7e38143c65fd8e888236f1e6","version_id":"sg:material/path-sha256-db7c4f17ca762b1169e43401710a0d95c03161ec7e38143c65fd8e888236f1e6@sha256:9402e16d92bf5f17df39d7ccfd2eb4328113e02a155abd02524a2e5482fd3d68"},{"byte_length":3944,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/consumer-migration.md","schema_version":"2.0","source_sha256":"a9e61500abbce740ca43f941aeb15a7bfebad46585584e0a45da59ce94334f29","stable_ref":"sg:material/path-sha256-ddc1d0e9544d4a08bb43703f230dcdfea087f2faf90d9a49e4aa22695b07178a","version_id":"sg:material/path-sha256-ddc1d0e9544d4a08bb43703f230dcdfea087f2faf90d9a49e4aa22695b07178a@sha256:a9e61500abbce740ca43f941aeb15a7bfebad46585584e0a45da59ce94334f29"},{"byte_length":2741,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/principles.md","schema_version":"2.0","source_sha256":"1834b852ae156c7362d4f9b223b4d72dc6b708a1f2a2964022955940a9c1fdc4","stable_ref":"sg:material/path-sha256-deba5ef88dc8bdc60813a398130b8a3ca3a8d01124f45823f5834ebda967996c","version_id":"sg:material/path-sha256-deba5ef88dc8bdc60813a398130b8a3ca3a8d01124f45823f5834ebda967996c@sha256:1834b852ae156c7362d4f9b223b4d72dc6b708a1f2a2964022955940a9c1fdc4"},{"byte_length":3655,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/index.md","schema_version":"2.0","source_sha256":"6c3fbad093a7becb9f2ca52a344a65dd02b3da51f49a915af6426a61f2a06208","stable_ref":"sg:material/path-sha256-df7a6343d7be1e9be37c6f618a7e72b0ac51be6143f64f419b4520e5f37c2b6b","version_id":"sg:material/path-sha256-df7a6343d7be1e9be37c6f618a7e72b0ac51be6143f64f419b4520e5f37c2b6b@sha256:6c3fbad093a7becb9f2ca52a344a65dd02b3da51f49a915af6426a61f2a06208"},{"byte_length":338,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/index.md","schema_version":"2.0","source_sha256":"b7125eb4c4d705a1bb2d57ac7e9d4cf140627473aac687331573bf30b0decd30","stable_ref":"sg:material/path-sha256-e1319590d4485778ddb92cc3c1f781b4f7e06d934d5849336f96588ee3592aa8","version_id":"sg:material/path-sha256-e1319590d4485778ddb92cc3c1f781b4f7e06d934d5849336f96588ee3592aa8@sha256:b7125eb4c4d705a1bb2d57ac7e9d4cf140627473aac687331573bf30b0decd30"},{"byte_length":3536,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/content-limiter.md","schema_version":"2.0","source_sha256":"505df6aac4ab3b5a9041cedaa04e74c2253ce2f8b9a12abf3d8835d2a9ce169c","stable_ref":"sg:material/path-sha256-e1c9957e26f0e3ee1235a070fbe69d31ed5974bce8c4fe14c63537909991a750","version_id":"sg:material/path-sha256-e1c9957e26f0e3ee1235a070fbe69d31ed5974bce8c4fe14c63537909991a750@sha256:505df6aac4ab3b5a9041cedaa04e74c2253ce2f8b9a12abf3d8835d2a9ce169c"},{"byte_length":3595,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/masonry-approx.md","schema_version":"2.0","source_sha256":"a176ffb2966ea5ed8b3ad22d013ed2fdd82e54a904be057a9e391087d4ad6654","stable_ref":"sg:material/path-sha256-e277a76f0335dd426d8b64001be63fd56ab91a03c4ade0526ea10c4631251abb","version_id":"sg:material/path-sha256-e277a76f0335dd426d8b64001be63fd56ab91a03c4ade0526ea10c4631251abb@sha256:a176ffb2966ea5ed8b3ad22d013ed2fdd82e54a904be057a9e391087d4ad6654"},{"byte_length":8104,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/consumer-migration-readiness.md","schema_version":"2.0","source_sha256":"86dc5148b052b372b0132d159d2c3ab819a859b5f210e3a1a994c29c7478b276","stable_ref":"sg:material/path-sha256-e2d4ce07445db974a7f32e5eec810897cfb565df619df52961f3eefa5a9c3fd4","version_id":"sg:material/path-sha256-e2d4ce07445db974a7f32e5eec810897cfb565df619df52961f3eefa5a9c3fd4@sha256:86dc5148b052b372b0132d159d2c3ab819a859b5f210e3a1a994c29c7478b276"},{"byte_length":1081,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/hci-evaluation.md","schema_version":"2.0","source_sha256":"9deeeeb4c0fc9b24d79e68b6e38236f2993da2544ecc0d130256136d2b062aae","stable_ref":"sg:material/path-sha256-e5f16e01f3fb13f94a214c8a9edf9b5c31c4ebca963802dfc624e8863e98f8da","version_id":"sg:material/path-sha256-e5f16e01f3fb13f94a214c8a9edf9b5c31c4ebca963802dfc624e8863e98f8da@sha256:9deeeeb4c0fc9b24d79e68b6e38236f2993da2544ecc0d130256136d2b062aae"},{"byte_length":5311,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/index.md","schema_version":"2.0","source_sha256":"3a69c67f9d4ab36a1bf741332fae02f3960414a610243c343281f934503e8c1a","stable_ref":"sg:material/path-sha256-e678b2e7915fc4abf6a019c86f8a7d74b8939a60220cb08a810900e1b5cbc2bc","version_id":"sg:material/path-sha256-e678b2e7915fc4abf6a019c86f8a7d74b8939a60220cb08a810900e1b5cbc2bc@sha256:3a69c67f9d4ab36a1bf741332fae02f3960414a610243c343281f934503e8c1a"},{"byte_length":2742,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claims.md","schema_version":"2.0","source_sha256":"8f28f2a42891946bf2929fb2bf5b122bfe63edb8b47a0b926183760d2bc9b15c","stable_ref":"sg:material/path-sha256-ec031d838419829b80465b2f31de260e70117bdd283988e0653441d439a65114","version_id":"sg:material/path-sha256-ec031d838419829b80465b2f31de260e70117bdd283988e0653441d439a65114@sha256:8f28f2a42891946bf2929fb2bf5b122bfe63edb8b47a0b926183760d2bc9b15c"},{"byte_length":2727,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/accessibility.md","schema_version":"2.0","source_sha256":"cc5a68a5e1721914fd00537b66aecb4e58c92c89962cc5fabd5ed0fc39930e95","stable_ref":"sg:material/path-sha256-eeea8e16127c63b10e90f626430df368a97fac8108b419c1cba89805b6014ce7","version_id":"sg:material/path-sha256-eeea8e16127c63b10e90f626430df368a97fac8108b419c1cba89805b6014ce7@sha256:cc5a68a5e1721914fd00537b66aecb4e58c92c89962cc5fabd5ed0fc39930e95"},{"byte_length":6696,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"layout/index.md","schema_version":"2.0","source_sha256":"03bba4cd15b3f507ae44094c472c8839e4b1f875ded63d9f13ec868ee8e184b2","stable_ref":"sg:material/path-sha256-f05a4c57bb475ff014a22abaa9120b04f05bc02d8bbe11f57677bd7662276f54","version_id":"sg:material/path-sha256-f05a4c57bb475ff014a22abaa9120b04f05bc02d8bbe11f57677bd7662276f54@sha256:03bba4cd15b3f507ae44094c472c8839e4b1f875ded63d9f13ec868ee8e184b2"},{"byte_length":3844,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"GUIDE.md","schema_version":"2.0","source_sha256":"f105ff6ed3c6923ea43dacc4c40632affee4874e086a333b9ce3fa2a786234da","stable_ref":"sg:material/path-sha256-f0d91300831f8bc350b2883e8adf82bdbcb79f482585168420831991e320ade7","version_id":"sg:material/path-sha256-f0d91300831f8bc350b2883e8adf82bdbcb79f482585168420831991e320ade7@sha256:f105ff6ed3c6923ea43dacc4c40632affee4874e086a333b9ce3fa2a786234da"},{"byte_length":1051,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/index.md","schema_version":"2.0","source_sha256":"936722e26c4157e4408bdf61ad13778fc7500885f177967348abbe6c17a77da3","stable_ref":"sg:material/path-sha256-f56daa946060f9e1f75d42246e0fa7a288093bf6d902cc9705a2c5b13c65310f","version_id":"sg:material/path-sha256-f56daa946060f9e1f75d42246e0fa7a288093bf6d902cc9705a2c5b13c65310f@sha256:936722e26c4157e4408bdf61ad13778fc7500885f177967348abbe6c17a77da3"},{"byte_length":1748,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/layout.md","schema_version":"2.0","source_sha256":"e7306ec2101bcbc1f27153160796ef56ba7846d6c7e5219d92e56b77e0703882","stable_ref":"sg:material/path-sha256-f62872ebce1ea7ffc61cd5522572c6d0f6aecd782c9e30df376bdcd96c7e73d3","version_id":"sg:material/path-sha256-f62872ebce1ea7ffc61cd5522572c6d0f6aecd782c9e30df376bdcd96c7e73d3@sha256:e7306ec2101bcbc1f27153160796ef56ba7846d6c7e5219d92e56b77e0703882"},{"byte_length":347,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/index.md","schema_version":"2.0","source_sha256":"24fa906c939cad71b0f175aab12ec75a16718c66446a31bedfcd3d1d46a67ae6","stable_ref":"sg:material/path-sha256-f77cbae09754bece5a3217dbf7cf766189bb5302d6296fab69bd6f5b3d6e495e","version_id":"sg:material/path-sha256-f77cbae09754bece5a3217dbf7cf766189bb5302d6296fab69bd6f5b3d6e495e@sha256:24fa906c939cad71b0f175aab12ec75a16718c66446a31bedfcd3d1d46a67ae6"},{"byte_length":1550,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/rationale.md","schema_version":"2.0","source_sha256":"875771978927372959dea499fba00bf1fd0d0d2426d35601aa3e418698ccd1ab","stable_ref":"sg:material/path-sha256-f797bc85a767e4a6ea1339cf7cc91d2504c722f3a02614d6174e59978db906a6","version_id":"sg:material/path-sha256-f797bc85a767e4a6ea1339cf7cc91d2504c722f3a02614d6174e59978db906a6@sha256:875771978927372959dea499fba00bf1fd0d0d2426d35601aa3e418698ccd1ab"},{"byte_length":4183,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/holy-grail.md","schema_version":"2.0","source_sha256":"b5b1335b55674e703636d1d205b80f8da8e99768ed7de9505f99afe233449031","stable_ref":"sg:material/path-sha256-f968729fb5885c124f8e1cab2c273f7e3b6fefd858be7f71d1b3958b48f4f2a9","version_id":"sg:material/path-sha256-f968729fb5885c124f8e1cab2c273f7e3b6fefd858be7f71d1b3958b48f4f2a9@sha256:b5b1335b55674e703636d1d205b80f8da8e99768ed7de9505f99afe233449031"}],"record_kind":"material_manifest","schema_version":"2.0","stable_ref":"sg:manifest/material-admission-v2","version_id":"sg:manifest/material-admission-v2@sha256:2e38696a6316b2141654b40c670361406a446fad695033a1efc48b38fd99da2a"} \ No newline at end of file +{"admission_policy_ref":"sg:policy/material-admission-v2","admission_policy_version_id":"sg:policy/material-admission-v2@sha256:3bc645aa9b84393a404612ebc4d757aada288ef88f57bb2d2fca03022b4d201d","materials":[{"byte_length":3583,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/page-grid.md","schema_version":"2.0","source_sha256":"a5b73ad6e01e85a93f2f585f520ea7e02f8b3677fa286236c20011873d4e7b9b","stable_ref":"sg:material/path-sha256-002803d65d057faaa4e8c1bb3e32ef3f41032b011251fc9f0f7b1db907b01ceb","version_id":"sg:material/path-sha256-002803d65d057faaa4e8c1bb3e32ef3f41032b011251fc9f0f7b1db907b01ceb@sha256:a5b73ad6e01e85a93f2f585f520ea7e02f8b3677fa286236c20011873d4e7b9b"},{"byte_length":3464,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/pagination.md","schema_version":"2.0","source_sha256":"a7afa87a24aae9797f299a7e4b4b96e2ca26d511a7ba2dcdbe1dc78600532a5b","stable_ref":"sg:material/path-sha256-00ae3be01fcc4add55bd98eff34737037c54c0a7f2f128239a2afbe698936c8f","version_id":"sg:material/path-sha256-00ae3be01fcc4add55bd98eff34737037c54c0a7f2f128239a2afbe698936c8f@sha256:a7afa87a24aae9797f299a7e4b4b96e2ca26d511a7ba2dcdbe1dc78600532a5b"},{"byte_length":4786,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/samples.md","schema_version":"2.0","source_sha256":"c2a3acefcad07f0ace47c9d054b601da0f4447a0fc8d5ee0ef272dd45075e81b","stable_ref":"sg:material/path-sha256-021f96adf1d1647d17f99011af6b1e7fa370dddbbad96b384731ed0256f74984","version_id":"sg:material/path-sha256-021f96adf1d1647d17f99011af6b1e7fa370dddbbad96b384731ed0256f74984@sha256:c2a3acefcad07f0ace47c9d054b601da0f4447a0fc8d5ee0ef272dd45075e81b"},{"byte_length":858,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/index.md","schema_version":"2.0","source_sha256":"05da91c5514d03e82c19a03c494fdad21a92a2ba7b88ec6dca5e7836c1f133a2","stable_ref":"sg:material/path-sha256-040de79bdf5af768663bf1aaa9d7451aa0d79bfaa0d5e982cceec4058f7715e4","version_id":"sg:material/path-sha256-040de79bdf5af768663bf1aaa9d7451aa0d79bfaa0d5e982cceec4058f7715e4@sha256:05da91c5514d03e82c19a03c494fdad21a92a2ba7b88ec6dca5e7836c1f133a2"},{"byte_length":5367,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/interface-craft.md","schema_version":"2.0","source_sha256":"ba71e914027abd783e9769a5b91efb764cc7335a6479c69ca4e70ab05a64e941","stable_ref":"sg:material/path-sha256-04afb6013755c328be25b08637961e5f20fa67705cfcbd6e996ba6ada944f571","version_id":"sg:material/path-sha256-04afb6013755c328be25b08637961e5f20fa67705cfcbd6e996ba6ada944f571@sha256:ba71e914027abd783e9769a5b91efb764cc7335a6479c69ca4e70ab05a64e941"},{"byte_length":501,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/index.md","schema_version":"2.0","source_sha256":"9b60182a25c4c07b7b482b3981dec17d515f95915cc618411282f988dca4ada2","stable_ref":"sg:material/path-sha256-04fa96b121ed2a48be80851efc72289752d1c4c12bd6433c2d5002d6d82a54ed","version_id":"sg:material/path-sha256-04fa96b121ed2a48be80851efc72289752d1c4c12bd6433c2d5002d6d82a54ed@sha256:9b60182a25c4c07b7b482b3981dec17d515f95915cc618411282f988dca4ada2"},{"byte_length":6853,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/vocabulary.md","schema_version":"2.0","source_sha256":"b2796979aaa1b194ff3006469cbeaec71cbd80d1484e3a5089e03295a43b464d","stable_ref":"sg:material/path-sha256-07b5ed44416e4d40efd213a7e944f214a338aa83201e52ba58c6dcf2a81e5675","version_id":"sg:material/path-sha256-07b5ed44416e4d40efd213a7e944f214a338aa83201e52ba58c6dcf2a81e5675@sha256:b2796979aaa1b194ff3006469cbeaec71cbd80d1484e3a5089e03295a43b464d"},{"byte_length":1619,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/visual-evidence.md","schema_version":"2.0","source_sha256":"17f7430f1cd1847c74c737ee9341120be6b49e827ec4228be5b6868669d27fd3","stable_ref":"sg:material/path-sha256-085c94936dece089fd31864c482d1a19e4da562951adbaa7d459e0126486d149","version_id":"sg:material/path-sha256-085c94936dece089fd31864c482d1a19e4da562951adbaa7d459e0126486d149@sha256:17f7430f1cd1847c74c737ee9341120be6b49e827ec4228be5b6868669d27fd3"},{"byte_length":5672,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/component-contract.md","schema_version":"2.0","source_sha256":"eca88467a55968ed9ccd2f86b9b18c15e597dfff17789ea86f8c91ac4bb60ac4","stable_ref":"sg:material/path-sha256-08adbcce8042dbb84d03e0903f204eb9f799d464a2035c84db9ffab8aebcc278","version_id":"sg:material/path-sha256-08adbcce8042dbb84d03e0903f204eb9f799d464a2035c84db9ffab8aebcc278@sha256:eca88467a55968ed9ccd2f86b9b18c15e597dfff17789ea86f8c91ac4bb60ac4"},{"byte_length":54,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/index.md","schema_version":"2.0","source_sha256":"b9bb90f0928f7f408c615ce2dc323425640ef4b83b62de0c0dee6dcd4bf7e3bb","stable_ref":"sg:material/path-sha256-08c3095acfdc040b75071e94644db6a32b655817c4b79eabfa4339b59c9f0b22","version_id":"sg:material/path-sha256-08c3095acfdc040b75071e94644db6a32b655817c4b79eabfa4339b59c9f0b22@sha256:b9bb90f0928f7f408c615ce2dc323425640ef4b83b62de0c0dee6dcd4bf7e3bb"},{"byte_length":4089,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/harmony-evaluation.md","schema_version":"2.0","source_sha256":"efee2c0ff6a662bc3efb360ee8c80defc5113a00d8b36e1c36c45eb63d330270","stable_ref":"sg:material/path-sha256-0a43f2af49d24f33b8ff06829d431f9e7608de57760c3f2c7de8c3e4126869f3","version_id":"sg:material/path-sha256-0a43f2af49d24f33b8ff06829d431f9e7608de57760c3f2c7de8c3e4126869f3@sha256:efee2c0ff6a662bc3efb360ee8c80defc5113a00d8b36e1c36c45eb63d330270"},{"byte_length":3804,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/scroll-body-shell.md","schema_version":"2.0","source_sha256":"f9f8269f42afdc453f2e226a03c1ea23566b4b9362939a4f485aee20d150cee8","stable_ref":"sg:material/path-sha256-10f553c3d6a39c31ca1a5b8f56db6afb75709d8706d125c6f0d891f46b1f11b4","version_id":"sg:material/path-sha256-10f553c3d6a39c31ca1a5b8f56db6afb75709d8706d125c6f0d891f46b1f11b4@sha256:f9f8269f42afdc453f2e226a03c1ea23566b4b9362939a4f485aee20d150cee8"},{"byte_length":4959,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/homepage.md","schema_version":"2.0","source_sha256":"09203c0de8824db3a8f678add95b0de363035ead7cfe5d44ae79353ef36b1193","stable_ref":"sg:material/path-sha256-14e127a7c719ee8494096a98b25b32d26363c1845bddcd912f50f6b1e2b84b46","version_id":"sg:material/path-sha256-14e127a7c719ee8494096a98b25b32d26363c1845bddcd912f50f6b1e2b84b46@sha256:09203c0de8824db3a8f678add95b0de363035ead7cfe5d44ae79353ef36b1193"},{"byte_length":3430,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/overlay-stack.md","schema_version":"2.0","source_sha256":"ffe57e891cbaa2eefcd3f642818d6f955b9f51f9028eed48ca2769e1ad75fd89","stable_ref":"sg:material/path-sha256-15dd8f3d84fb50f1442bd8c9732356759849f7d87f1d66b004eeb5d9ea75a4a9","version_id":"sg:material/path-sha256-15dd8f3d84fb50f1442bd8c9732356759849f7d87f1d66b004eeb5d9ea75a4a9@sha256:ffe57e891cbaa2eefcd3f642818d6f955b9f51f9028eed48ca2769e1ad75fd89"},{"byte_length":901,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/design-rationale.md","schema_version":"2.0","source_sha256":"f2215fa79133af7f7282fff9a2da490d1a5dd58dd3ea0fc56255872268fbd163","stable_ref":"sg:material/path-sha256-162d7fd4521ddaf5ee59166c9cb56d8cbcb7d3b9bacaf9cd75883c1586108369","version_id":"sg:material/path-sha256-162d7fd4521ddaf5ee59166c9cb56d8cbcb7d3b9bacaf9cd75883c1586108369@sha256:f2215fa79133af7f7282fff9a2da490d1a5dd58dd3ea0fc56255872268fbd163"},{"byte_length":3452,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/breadcrumb.md","schema_version":"2.0","source_sha256":"666bf05329f85a0a19d8ee42fd91b6149895d7c1ed62528f3b36051015210b9c","stable_ref":"sg:material/path-sha256-16eeb4385f9c3ed3ee536baa50271a5afda69eb267e6e240f45eea88c675c9cc","version_id":"sg:material/path-sha256-16eeb4385f9c3ed3ee536baa50271a5afda69eb267e6e240f45eea88c675c9cc@sha256:666bf05329f85a0a19d8ee42fd91b6149895d7c1ed62528f3b36051015210b9c"},{"byte_length":3426,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/cluster.md","schema_version":"2.0","source_sha256":"39a8b4e529fa82338de96528ed1f7ec0a1646286243dfb7df71be3666c46ed82","stable_ref":"sg:material/path-sha256-176a6bff0fef909def0e8d71cb7c567b867a180ff8ff11dc71f96187e6fb4b75","version_id":"sg:material/path-sha256-176a6bff0fef909def0e8d71cb7c567b867a180ff8ff11dc71f96187e6fb4b75@sha256:39a8b4e529fa82338de96528ed1f7ec0a1646286243dfb7df71be3666c46ed82"},{"byte_length":935,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/index.md","schema_version":"2.0","source_sha256":"5cfb5a5586709a5c32f6f01e8d0e768850b57111c0a653363ced0eeddbca4f88","stable_ref":"sg:material/path-sha256-1bbc62c02480ddef71cbe2b8723ae3da595efdfcfcf8f0bbbfd4dad8d417d2a7","version_id":"sg:material/path-sha256-1bbc62c02480ddef71cbe2b8723ae3da595efdfcfcf8f0bbbfd4dad8d417d2a7@sha256:5cfb5a5586709a5c32f6f01e8d0e768850b57111c0a653363ced0eeddbca4f88"},{"byte_length":3725,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/split-screen.md","schema_version":"2.0","source_sha256":"a6c48700334e6e3e611acee525be7a89e6aa73c0df0494d5f4a5555790d237a8","stable_ref":"sg:material/path-sha256-1c3948243f01f30bcd55ac3cb3c9935bce15060224b1837fdf1b3be2684ecc74","version_id":"sg:material/path-sha256-1c3948243f01f30bcd55ac3cb3c9935bce15060224b1837fdf1b3be2684ecc74@sha256:a6c48700334e6e3e611acee525be7a89e6aa73c0df0494d5f4a5555790d237a8"},{"byte_length":3334,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/box.md","schema_version":"2.0","source_sha256":"d64aedd87ff612e6bb50293653cf5076ed952c1d4833abc54416b1bc60ef8680","stable_ref":"sg:material/path-sha256-1c4c0582a35fac69c8274a72f86ad5075a755d30f0924adbc3ff66fc616d9430","version_id":"sg:material/path-sha256-1c4c0582a35fac69c8274a72f86ad5075a755d30f0924adbc3ff66fc616d9430@sha256:d64aedd87ff612e6bb50293653cf5076ed952c1d4833abc54416b1bc60ef8680"},{"byte_length":3380,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/stack.md","schema_version":"2.0","source_sha256":"0e9d1bd2fb0345bd28efc04502c88fb64f6cdb721a5792473d2822907de1baa1","stable_ref":"sg:material/path-sha256-1f6bb0dc8098df4cb643ddb7941fc7997bfc34e8c4c4ba8b473ebd19b43da69e","version_id":"sg:material/path-sha256-1f6bb0dc8098df4cb643ddb7941fc7997bfc34e8c4c4ba8b473ebd19b43da69e@sha256:0e9d1bd2fb0345bd28efc04502c88fb64f6cdb721a5792473d2822907de1baa1"},{"byte_length":386,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/index.md","schema_version":"2.0","source_sha256":"a32cdbff417ba8cf4333a15c7799bb1b1907c4334d0bcee052220af46b87973a","stable_ref":"sg:material/path-sha256-1fc22b9f0d7d72c1dcc9b54db927b44a791c091736efbc2dcff08b9f5097f00c","version_id":"sg:material/path-sha256-1fc22b9f0d7d72c1dcc9b54db927b44a791c091736efbc2dcff08b9f5097f00c@sha256:a32cdbff417ba8cf4333a15c7799bb1b1907c4334d0bcee052220af46b87973a"},{"byte_length":7416,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/relation-types.md","schema_version":"2.0","source_sha256":"4f2e601edf167fa435296fca43156845a003d2b680e0e8c13ac0d687b909bdb8","stable_ref":"sg:material/path-sha256-20446da61add8150ac93ec91e23ad403d7f7e4b1b322024a8c488e4324f47533","version_id":"sg:material/path-sha256-20446da61add8150ac93ec91e23ad403d7f7e4b1b322024a8c488e4324f47533@sha256:4f2e601edf167fa435296fca43156845a003d2b680e0e8c13ac0d687b909bdb8"},{"byte_length":4671,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/motion-brief.md","schema_version":"2.0","source_sha256":"01320d26e6ffb269e9ef30638a2c724d8118ec801ce787f607cc2fad50bfcdcf","stable_ref":"sg:material/path-sha256-205e6fc7f07a049703f1de0d741836c512fdfa12f9e10cf9bf4c75bdba550137","version_id":"sg:material/path-sha256-205e6fc7f07a049703f1de0d741836c512fdfa12f9e10cf9bf4c75bdba550137@sha256:01320d26e6ffb269e9ef30638a2c724d8118ec801ce787f607cc2fad50bfcdcf"},{"byte_length":2010,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/design-claim.md","schema_version":"2.0","source_sha256":"bdf92087f69f1d55d1d8f5efa8fdc794824bd9f40d794e617e6a06db0a16ef81","stable_ref":"sg:material/path-sha256-21480e86104dfaab3408304f300dc7cc570eab3e747a1a3931785951544f8372","version_id":"sg:material/path-sha256-21480e86104dfaab3408304f300dc7cc570eab3e747a1a3931785951544f8372@sha256:bdf92087f69f1d55d1d8f5efa8fdc794824bd9f40d794e617e6a06db0a16ef81"},{"byte_length":3461,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/super-center.md","schema_version":"2.0","source_sha256":"80ca126c59d0a5947707b01875c17487dfad7e4fc51920ad02649108971e0c55","stable_ref":"sg:material/path-sha256-21ffb3e535a16bcba5817e15c784b9d2500b32cb50f86c1b3c033c652193cc00","version_id":"sg:material/path-sha256-21ffb3e535a16bcba5817e15c784b9d2500b32cb50f86c1b3c033c652193cc00@sha256:80ca126c59d0a5947707b01875c17487dfad7e4fc51920ad02649108971e0c55"},{"byte_length":3504,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/fluid-styles.md","schema_version":"2.0","source_sha256":"652bd2d6b33e8c1c4dc5eb7175f65c1c0c13a6268aa72ac330ef6b3cf303b5cb","stable_ref":"sg:material/path-sha256-239a2e2ec1f881ea5ae0e4f852980adaa058a8c7943fe83d8c90d8b51e02abb5","version_id":"sg:material/path-sha256-239a2e2ec1f881ea5ae0e4f852980adaa058a8c7943fe83d8c90d8b51e02abb5@sha256:652bd2d6b33e8c1c4dc5eb7175f65c1c0c13a6268aa72ac330ef6b3cf303b5cb"},{"byte_length":3506,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/ram-grid.md","schema_version":"2.0","source_sha256":"b15856b240152a9da700abb4cdd611a1f9d41cad353582eeaad79459c13f277b","stable_ref":"sg:material/path-sha256-23ce75202642f0f8901b6a413fd2a269a70166058d62e90ca4403e7a3b34cf69","version_id":"sg:material/path-sha256-23ce75202642f0f8901b6a413fd2a269a70166058d62e90ca4403e7a3b34cf69@sha256:b15856b240152a9da700abb4cdd611a1f9d41cad353582eeaad79459c13f277b"},{"byte_length":3364,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/tab-strip.md","schema_version":"2.0","source_sha256":"c154f4a8cfd4d17d60f929bf363a632ca4bacedc4a5e55c891870a2a75ccd628","stable_ref":"sg:material/path-sha256-2567793e03725c0bb9b1b4cd1524b38c8240253b4989e3413b7985cfccfb4453","version_id":"sg:material/path-sha256-2567793e03725c0bb9b1b4cd1524b38c8240253b4989e3413b7985cfccfb4453@sha256:c154f4a8cfd4d17d60f929bf363a632ca4bacedc4a5e55c891870a2a75ccd628"},{"byte_length":3735,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/list-detail.md","schema_version":"2.0","source_sha256":"cbb8c05e85605aa2217027a946aae1fd7d3ed7c3981d7f15b2207c7dee8f9c6d","stable_ref":"sg:material/path-sha256-26867cd73e9ea9a732763de098fa0e99861d6bd15deba26359727ef68417e331","version_id":"sg:material/path-sha256-26867cd73e9ea9a732763de098fa0e99861d6bd15deba26359727ef68417e331@sha256:cbb8c05e85605aa2217027a946aae1fd7d3ed7c3981d7f15b2207c7dee8f9c6d"},{"byte_length":3827,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/sticky-aside.md","schema_version":"2.0","source_sha256":"69bd3b575b0c2aca46858e887cc5fbccbf5f772e4678ac305257307c70a378ab","stable_ref":"sg:material/path-sha256-27b1e5216a098387ab5e1de9d8997391ae2e8b3388331c221e14ed5946734415","version_id":"sg:material/path-sha256-27b1e5216a098387ab5e1de9d8997391ae2e8b3388331c221e14ed5946734415@sha256:69bd3b575b0c2aca46858e887cc5fbccbf5f772e4678ac305257307c70a378ab"},{"byte_length":3972,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/fixed-sidenav-shell.md","schema_version":"2.0","source_sha256":"4889d7aaf9a7ab4687b56e19987782afdc40def1935882213510958d4c747560","stable_ref":"sg:material/path-sha256-29d4e1dee690708b4218d8b195f08e1135f76b279ebaadbafd08aa74286daa28","version_id":"sg:material/path-sha256-29d4e1dee690708b4218d8b195f08e1135f76b279ebaadbafd08aa74286daa28@sha256:4889d7aaf9a7ab4687b56e19987782afdc40def1935882213510958d4c747560"},{"byte_length":3636,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/switcher.md","schema_version":"2.0","source_sha256":"f9e24b044790472cee533fe85da5d0b14e252c5119a0b532f5ff00be2f74ca4d","stable_ref":"sg:material/path-sha256-2dd9316398e52cf61361bfae39e601e73eb411b74ddc09cadf131183e6c18093","version_id":"sg:material/path-sha256-2dd9316398e52cf61361bfae39e601e73eb411b74ddc09cadf131183e6c18093@sha256:f9e24b044790472cee533fe85da5d0b14e252c5119a0b532f5ff00be2f74ca4d"},{"byte_length":5802,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/verification-workflow.md","schema_version":"2.0","source_sha256":"3454a389851219adbcbf2192c9bdec8f248b20271bad818bbf93433ed4b8f7a7","stable_ref":"sg:material/path-sha256-301be971141f154cb524caa0760e2ab925bf311a1461c055b7d44bc5a26a345d","version_id":"sg:material/path-sha256-301be971141f154cb524caa0760e2ab925bf311a1461c055b7d44bc5a26a345d@sha256:3454a389851219adbcbf2192c9bdec8f248b20271bad818bbf93433ed4b8f7a7"},{"byte_length":1783,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/sources.md","schema_version":"2.0","source_sha256":"655c4c304f1dae83e56e5f3f19838db7b9681a600b161532cc4389574594fde8","stable_ref":"sg:material/path-sha256-31c57866c230c6e93dd2b4636e6e892eeff33521ef07ed24cde34094c2d9c939","version_id":"sg:material/path-sha256-31c57866c230c6e93dd2b4636e6e892eeff33521ef07ed24cde34094c2d9c939@sha256:655c4c304f1dae83e56e5f3f19838db7b9681a600b161532cc4389574594fde8"},{"byte_length":2906,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/command-surface.md","schema_version":"2.0","source_sha256":"b52b18adcaf95110d9ba7780289c2c2e6e4b128327290e18da1723b019261f02","stable_ref":"sg:material/path-sha256-33c5ebfda703b62fe98e750cf800d6a690eb3c5e02c0089d0fd91d987b2b5f8f","version_id":"sg:material/path-sha256-33c5ebfda703b62fe98e750cf800d6a690eb3c5e02c0089d0fd91d987b2b5f8f@sha256:b52b18adcaf95110d9ba7780289c2c2e6e4b128327290e18da1723b019261f02"},{"byte_length":3479,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/sticky-header.md","schema_version":"2.0","source_sha256":"3a5aeacbaa7f9ea443c92848667b7a6d362bd5f4481c304b0bb312549d330a94","stable_ref":"sg:material/path-sha256-3901860520475e0bf9a7a0d9a7684ce518e7f2c96d22f3aefb66fe40c524558d","version_id":"sg:material/path-sha256-3901860520475e0bf9a7a0d9a7684ce518e7f2c96d22f3aefb66fe40c524558d@sha256:3a5aeacbaa7f9ea443c92848667b7a6d362bd5f4481c304b0bb312549d330a94"},{"byte_length":14817,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/ui-systems.md","schema_version":"2.0","source_sha256":"fc9baf57a82a393d5f7b189fa7798d1023757d2bc9ed769fb6cbab7b9bbb5c40","stable_ref":"sg:material/path-sha256-3a18eb0e207f57d2657185e6e09afddd94b8d9722418d78d39122b6bb06b7098","version_id":"sg:material/path-sha256-3a18eb0e207f57d2657185e6e09afddd94b8d9722418d78d39122b6bb06b7098@sha256:fc9baf57a82a393d5f7b189fa7798d1023757d2bc9ed769fb6cbab7b9bbb5c40"},{"byte_length":579,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/index.md","schema_version":"2.0","source_sha256":"90f2d5973bf08cfd7ba55523176d8bb76bff441a8a3b9e69c3a520118db3e101","stable_ref":"sg:material/path-sha256-3bf8fac99ec13ef32824ded352565692d56cc7c54e5392b7985df262ba35e760","version_id":"sg:material/path-sha256-3bf8fac99ec13ef32824ded352565692d56cc7c54e5392b7985df262ba35e760@sha256:90f2d5973bf08cfd7ba55523176d8bb76bff441a8a3b9e69c3a520118db3e101"},{"byte_length":4405,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/screen-hierarchy.md","schema_version":"2.0","source_sha256":"a186fd1ff27b84394fdf31011eee733d5b5cc40e6e83069dc4df41b52809f552","stable_ref":"sg:material/path-sha256-3d5fe3355a6206218a13433abbd642bc623d90ee2bcb48dbf488a592bec8fb17","version_id":"sg:material/path-sha256-3d5fe3355a6206218a13433abbd642bc623d90ee2bcb48dbf488a592bec8fb17@sha256:a186fd1ff27b84394fdf31011eee733d5b5cc40e6e83069dc4df41b52809f552"},{"byte_length":3466,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/dense-grid.md","schema_version":"2.0","source_sha256":"5c99ebab2a33fe1827fee2810e340fc44867439352462dc453ec352f78e34e52","stable_ref":"sg:material/path-sha256-3d9a239e6bc90b85b6d15102c961f1ca0615094fe1df289c6e4d6a418af1801a","version_id":"sg:material/path-sha256-3d9a239e6bc90b85b6d15102c961f1ca0615094fe1df289c6e4d6a418af1801a@sha256:5c99ebab2a33fe1827fee2810e340fc44867439352462dc453ec352f78e34e52"},{"byte_length":2608,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/reference-record.md","schema_version":"2.0","source_sha256":"f43c57cf386b787c73c6e2974044b21c4ad0e1c05dd080003a3f6e268f63f4c9","stable_ref":"sg:material/path-sha256-3e5f771aba328b1394ddd2e529e322ecb8fe2259c33b92448c0c71161e3a5ff9","version_id":"sg:material/path-sha256-3e5f771aba328b1394ddd2e529e322ecb8fe2259c33b92448c0c71161e3a5ff9@sha256:f43c57cf386b787c73c6e2974044b21c4ad0e1c05dd080003a3f6e268f63f4c9"},{"byte_length":4381,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/decision-tree.md","schema_version":"2.0","source_sha256":"8c225109dc349a7c351bf6c194c31568723c4e12c16438727fa710d53c98b94f","stable_ref":"sg:material/path-sha256-40a62d0c8d3666e3383f68652dbcd92841189eb4d3045ccbc5ba51d317faa103","version_id":"sg:material/path-sha256-40a62d0c8d3666e3383f68652dbcd92841189eb4d3045ccbc5ba51d317faa103@sha256:8c225109dc349a7c351bf6c194c31568723c4e12c16438727fa710d53c98b94f"},{"byte_length":873,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/index.md","schema_version":"2.0","source_sha256":"89729f69e1a879742421b2d583dcf67f8a9a94ed90a198e5b7b9e40b856a404e","stable_ref":"sg:material/path-sha256-44cd370aff03553cea434398290dfe059d49fd316157face88e54035c050b5f5","version_id":"sg:material/path-sha256-44cd370aff03553cea434398290dfe059d49fd316157face88e54035c050b5f5@sha256:89729f69e1a879742421b2d583dcf67f8a9a94ed90a198e5b7b9e40b856a404e"},{"byte_length":2697,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/dashboard.md","schema_version":"2.0","source_sha256":"8ee1c7c8b70bfd63144fbdd5f3a55f8736ce4626c35a391f4a722b579ec2232d","stable_ref":"sg:material/path-sha256-463cfb73f926bbdf90d68b3aee7af299b388384e6b5e51e1c7a5ef2cd33aef83","version_id":"sg:material/path-sha256-463cfb73f926bbdf90d68b3aee7af299b388384e6b5e51e1c7a5ef2cd33aef83@sha256:8ee1c7c8b70bfd63144fbdd5f3a55f8736ce4626c35a391f4a722b579ec2232d"},{"byte_length":15345,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/architecture.md","schema_version":"2.0","source_sha256":"026af25031c537dd074e7bc91f00fa91e1dcaecbefe6a9c6a574e05a662adff4","stable_ref":"sg:material/path-sha256-49ac4d11b609a7dd49ecd0d397a7a5401595c3e2835958e35b430be5883d7592","version_id":"sg:material/path-sha256-49ac4d11b609a7dd49ecd0d397a7a5401595c3e2835958e35b430be5883d7592@sha256:026af25031c537dd074e7bc91f00fa91e1dcaecbefe6a9c6a574e05a662adff4"},{"byte_length":3538,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/grid-wrapper.md","schema_version":"2.0","source_sha256":"55c90e01efd81fe7f338ab8e6535d731df8f0ce1c00751d8ba4ddde780963b29","stable_ref":"sg:material/path-sha256-4a8a96f82fbd1527cc6f7ee248ef7a8ab8d47289a31dfb521f865d49f0376afb","version_id":"sg:material/path-sha256-4a8a96f82fbd1527cc6f7ee248ef7a8ab8d47289a31dfb521f865d49f0376afb@sha256:55c90e01efd81fe7f338ab8e6535d731df8f0ce1c00751d8ba4ddde780963b29"},{"byte_length":5815,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/compatibility-matrix.md","schema_version":"2.0","source_sha256":"924d2747c86f662d4dc1467388293d4cb916caf256a4640afe9ebeef17c6f671","stable_ref":"sg:material/path-sha256-4c2db02298ea0b264c459e4c2b368dc67795c8a301786f1192bb61feb56c1c85","version_id":"sg:material/path-sha256-4c2db02298ea0b264c459e4c2b368dc67795c8a301786f1192bb61feb56c1c85@sha256:924d2747c86f662d4dc1467388293d4cb916caf256a4640afe9ebeef17c6f671"},{"byte_length":3678,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/overlay-exception/imposter.md","schema_version":"2.0","source_sha256":"4f71b8e9164daf01d1c977c0a7ebb18576185138068a06df5d67e89d3bf7ad1c","stable_ref":"sg:material/path-sha256-4c3aeb4771622f79b0f3efdeb40e0f59064925f4bd60e63186452c0a79941a3e","version_id":"sg:material/path-sha256-4c3aeb4771622f79b0f3efdeb40e0f59064925f4bd60e63186452c0a79941a3e@sha256:4f71b8e9164daf01d1c977c0a7ebb18576185138068a06df5d67e89d3bf7ad1c"},{"byte_length":3458,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/center.md","schema_version":"2.0","source_sha256":"8abae0c076bf8c3eeeefd8920dff8c9d767c5c59ef926265b960940bab8310da","stable_ref":"sg:material/path-sha256-4fb5bdea440d75d58bcb66874cdb2930ee9cd5d17768bba1ea95e4c3c547ebd5","version_id":"sg:material/path-sha256-4fb5bdea440d75d58bcb66874cdb2930ee9cd5d17768bba1ea95e4c3c547ebd5@sha256:8abae0c076bf8c3eeeefd8920dff8c9d767c5c59ef926265b960940bab8310da"},{"byte_length":6061,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/practice-reference.md","schema_version":"2.0","source_sha256":"1096eae09dd6a90ae83c9979728c5774c4242dae68f71ee12e97496c87d0ba2d","stable_ref":"sg:material/path-sha256-50b685f66086b3f2362d97feb7e001bd2f208e6ea33c52174edf66fbe8287265","version_id":"sg:material/path-sha256-50b685f66086b3f2362d97feb7e001bd2f208e6ea33c52174edf66fbe8287265@sha256:1096eae09dd6a90ae83c9979728c5774c4242dae68f71ee12e97496c87d0ba2d"},{"byte_length":3428,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/clamped-card.md","schema_version":"2.0","source_sha256":"14e9700b95e01bdbf22be445ec79245209be097cfcff92c33a0aa37bcf2d564b","stable_ref":"sg:material/path-sha256-52157f6d777be20078f71c3c850955175151fdbe04fad86368b8f0e382280631","version_id":"sg:material/path-sha256-52157f6d777be20078f71c3c850955175151fdbe04fad86368b8f0e382280631@sha256:14e9700b95e01bdbf22be445ec79245209be097cfcff92c33a0aa37bcf2d564b"},{"byte_length":7878,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/contract.md","schema_version":"2.0","source_sha256":"b914920989ff2ce08ebc67fa3167d0da766c260c93f03257a9144c6093ff6713","stable_ref":"sg:material/path-sha256-52494ee56bf5c837ead0782244d579ea0aba9e63e95a02c10f6d0b566e4d62d9","version_id":"sg:material/path-sha256-52494ee56bf5c837ead0782244d579ea0aba9e63e95a02c10f6d0b566e4d62d9@sha256:b914920989ff2ce08ebc67fa3167d0da766c260c93f03257a9144c6093ff6713"},{"byte_length":8606,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/search-metadata-polyhierarchy.md","schema_version":"2.0","source_sha256":"53ea6fddbf9c446a2b35ca6d975200c274ba3a713a2298ff62c8253d6c8a49d7","stable_ref":"sg:material/path-sha256-59a41c8893a1ad96d4b5abe1cfb6e381273ce32030b84b06cdbd2ac8be24dc74","version_id":"sg:material/path-sha256-59a41c8893a1ad96d4b5abe1cfb6e381273ce32030b84b06cdbd2ac8be24dc74@sha256:53ea6fddbf9c446a2b35ca6d975200c274ba3a713a2298ff62c8253d6c8a49d7"},{"byte_length":3490,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/columns.md","schema_version":"2.0","source_sha256":"eda07657f498d69a734749ba4c94a6fd35e4b1f61cf312324460e0b4e491d324","stable_ref":"sg:material/path-sha256-5a76c5ad4c7daff2cbf3fbf8d8968f56204322f508b999f77e87bcbe6274a8de","version_id":"sg:material/path-sha256-5a76c5ad4c7daff2cbf3fbf8d8968f56204322f508b999f77e87bcbe6274a8de@sha256:eda07657f498d69a734749ba4c94a6fd35e4b1f61cf312324460e0b4e491d324"},{"byte_length":12162,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/org-wiki.md","schema_version":"2.0","source_sha256":"b6fcdef8d5b6524111cabfef7a0b86e2f899659e5d7d7e81e8ebd521e79dd131","stable_ref":"sg:material/path-sha256-5de69acbec858ebe75c9483c1b4474ea8d48778aedc3cc654a26552b3a49a5f5","version_id":"sg:material/path-sha256-5de69acbec858ebe75c9483c1b4474ea8d48778aedc3cc654a26552b3a49a5f5@sha256:b6fcdef8d5b6524111cabfef7a0b86e2f899659e5d7d7e81e8ebd521e79dd131"},{"byte_length":876,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/tokens.md","schema_version":"2.0","source_sha256":"9f6849985944fea6c660c6ce8f1a962b1b3fe4aa195e72ef2d2293b27fac80f0","stable_ref":"sg:material/path-sha256-5e265c863940f92cadc3da208c4c09c4aacd7da3425332edc401bbb461383e30","version_id":"sg:material/path-sha256-5e265c863940f92cadc3da208c4c09c4aacd7da3425332edc401bbb461383e30@sha256:9f6849985944fea6c660c6ce8f1a962b1b3fe4aa195e72ef2d2293b27fac80f0"},{"byte_length":537,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/index.md","schema_version":"2.0","source_sha256":"93635d8fec49e448550ac671d0fe2510ecc017467ff79203bf10bc3e9b32a9d4","stable_ref":"sg:material/path-sha256-5e7498d507fe35d8607873d31efa80b8e4634fa59aa68fdb3cc10fcd99df20c6","version_id":"sg:material/path-sha256-5e7498d507fe35d8607873d31efa80b8e4634fa59aa68fdb3cc10fcd99df20c6@sha256:93635d8fec49e448550ac671d0fe2510ecc017467ff79203bf10bc3e9b32a9d4"},{"byte_length":3682,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/deconstructed-pancake.md","schema_version":"2.0","source_sha256":"81a69e4a12a2f967a0ecff31d02c3beb365bf6c9055acc86cda4f6355f70adbe","stable_ref":"sg:material/path-sha256-651d978327dca78d036202b232058a85e240ada94d07dd7461bc894f9f83e5e2","version_id":"sg:material/path-sha256-651d978327dca78d036202b232058a85e240ada94d07dd7461bc894f9f83e5e2@sha256:81a69e4a12a2f967a0ecff31d02c3beb365bf6c9055acc86cda4f6355f70adbe"},{"byte_length":3735,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/main-with-rail.md","schema_version":"2.0","source_sha256":"ba1cfc18e294563b48fbaa2cb427dc431b4586d55a157818a541cba25d0a0160","stable_ref":"sg:material/path-sha256-653b926534bf6d8d074f03173f13f475bada8dfa566852e272470fc17b8e58d4","version_id":"sg:material/path-sha256-653b926534bf6d8d074f03173f13f475bada8dfa566852e272470fc17b8e58d4@sha256:ba1cfc18e294563b48fbaa2cb427dc431b4586d55a157818a541cba25d0a0160"},{"byte_length":3910,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/media-object.md","schema_version":"2.0","source_sha256":"26f218d8b2138e7a7f4585e21d33d6f640d5b67993a64e182bdef9b4628d7dae","stable_ref":"sg:material/path-sha256-69e5cbcca6fba542020d47eeb31222d719c39624ec41749d591d17aa175c5f3a","version_id":"sg:material/path-sha256-69e5cbcca6fba542020d47eeb31222d719c39624ec41749d591d17aa175c5f3a@sha256:26f218d8b2138e7a7f4585e21d33d6f640d5b67993a64e182bdef9b4628d7dae"},{"byte_length":1918,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/index.md","schema_version":"2.0","source_sha256":"885ca1dc8bb79fac2a6b32bedb6963646cbcc97dc0abc535f59365718abfb2e5","stable_ref":"sg:material/path-sha256-6c243b28fd8f4564a96217bcceabc75a5651ecd21ac41abfbdd4716adc60aa72","version_id":"sg:material/path-sha256-6c243b28fd8f4564a96217bcceabc75a5651ecd21ac41abfbdd4716adc60aa72@sha256:885ca1dc8bb79fac2a6b32bedb6963646cbcc97dc0abc535f59365718abfb2e5"},{"byte_length":8008,"domain":"shared","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/agent-native/README.md","schema_version":"2.0","source_sha256":"6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e","stable_ref":"sg:material/path-sha256-6cda345129c13188719d0116beef1e7d8e672f951f21295bc3b2ccf490a4a81d","version_id":"sg:material/path-sha256-6cda345129c13188719d0116beef1e7d8e672f951f21295bc3b2ccf490a4a81d@sha256:6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e"},{"byte_length":7030,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"log.md","schema_version":"2.0","source_sha256":"524b2225be95f0408e4842b146755d36b09dc01527312fa0b12b8a6e95032fac","stable_ref":"sg:material/path-sha256-7204c0a4f935b2563fdb9fcf74d71a2e8621bf1b53f9da1b6eab41597a5fbc38","version_id":"sg:material/path-sha256-7204c0a4f935b2563fdb9fcf74d71a2e8621bf1b53f9da1b6eab41597a5fbc38@sha256:524b2225be95f0408e4842b146755d36b09dc01527312fa0b12b8a6e95032fac"},{"byte_length":3574,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/reel.md","schema_version":"2.0","source_sha256":"57a66f71da9293c1037d325a3d98d95938b7a7534e42cc8f3d1149ef63ab5480","stable_ref":"sg:material/path-sha256-72616dfa2b53176365ef81dd6954260a8a96051f3c47100505ece70816871c11","version_id":"sg:material/path-sha256-72616dfa2b53176365ef81dd6954260a8a96051f3c47100505ece70816871c11@sha256:57a66f71da9293c1037d325a3d98d95938b7a7534e42cc8f3d1149ef63ab5480"},{"byte_length":3614,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/sticky-footer.md","schema_version":"2.0","source_sha256":"4103c4b74e4b143705a656f11662ec03721b40802c980e4527331f97b09c21df","stable_ref":"sg:material/path-sha256-7412ca94f2f7e6e9b81ec40ccbaee7ccab5a773e48d7fc14055baccd8d059d42","version_id":"sg:material/path-sha256-7412ca94f2f7e6e9b81ec40ccbaee7ccab5a773e48d7fc14055baccd8d059d42@sha256:4103c4b74e4b143705a656f11662ec03721b40802c980e4527331f97b09c21df"},{"byte_length":4985,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/android-interaction.md","schema_version":"2.0","source_sha256":"a2178943bc6265f7c35d58b5a48d7646b7a4f04aaad073382dc9c84783066332","stable_ref":"sg:material/path-sha256-788bb5b0cd715989c0a984075c80a1d185b207deda5b50f58280030d928a5f89","version_id":"sg:material/path-sha256-788bb5b0cd715989c0a984075c80a1d185b207deda5b50f58280030d928a5f89@sha256:a2178943bc6265f7c35d58b5a48d7646b7a4f04aaad073382dc9c84783066332"},{"byte_length":14420,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/documentation-mode-taxonomy.md","schema_version":"2.0","source_sha256":"872594fdfa78c4196bad9eae4aa6bab3cde82b4f73803ef049a60c6a7db329c2","stable_ref":"sg:material/path-sha256-78dcee9e03982b489be85a59bb522877c94bb01b2624af09e5ef5e3bc3bbbffc","version_id":"sg:material/path-sha256-78dcee9e03982b489be85a59bb522877c94bb01b2624af09e5ef5e3bc3bbbffc@sha256:872594fdfa78c4196bad9eae4aa6bab3cde82b4f73803ef049a60c6a7db329c2"},{"byte_length":2791,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/list-detail.md","schema_version":"2.0","source_sha256":"26c00df6db757fa392dd285eb910de9c13eae39c78ab97c44dda55cea9047899","stable_ref":"sg:material/path-sha256-7b47a26ca3030528440849547a9a39dcd489581ebdb0b3c85f3204cf066acaa8","version_id":"sg:material/path-sha256-7b47a26ca3030528440849547a9a39dcd489581ebdb0b3c85f3204cf066acaa8@sha256:26c00df6db757fa392dd285eb910de9c13eae39c78ab97c44dda55cea9047899"},{"byte_length":3687,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/line-up.md","schema_version":"2.0","source_sha256":"34ccb96fb46cbfe6567ffb74a8f01fd79ac3baf0ea4ed93e54cab83ac45473dc","stable_ref":"sg:material/path-sha256-7c2f9831fd891304724438057614dab34b1fff1da4eb2f0d86803115be5a3ce5","version_id":"sg:material/path-sha256-7c2f9831fd891304724438057614dab34b1fff1da4eb2f0d86803115be5a3ce5@sha256:34ccb96fb46cbfe6567ffb74a8f01fd79ac3baf0ea4ed93e54cab83ac45473dc"},{"byte_length":11419,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/cli-loop.md","schema_version":"2.0","source_sha256":"bfc9596a0b981bbb31470f4c8a87578d401f775fa1f9b4dc6da1e0f967ca3f1b","stable_ref":"sg:material/path-sha256-7c4697a9eca2beda5a21f7edd84648e7e67643b3f67b771434ed123c424a2d1a","version_id":"sg:material/path-sha256-7c4697a9eca2beda5a21f7edd84648e7e67643b3f67b771434ed123c424a2d1a@sha256:bfc9596a0b981bbb31470f4c8a87578d401f775fa1f9b4dc6da1e0f967ca3f1b"},{"byte_length":4740,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/review-workflow.md","schema_version":"2.0","source_sha256":"5219296be498f37f9d9b69ba4723f2ce7d12b5d326fec20045b2aedcc6c90746","stable_ref":"sg:material/path-sha256-7df8e54fd5935c4a2a9aace117d43253e7c0fe32448fd31984a531a134192a83","version_id":"sg:material/path-sha256-7df8e54fd5935c4a2a9aace117d43253e7c0fe32448fd31984a531a134192a83@sha256:5219296be498f37f9d9b69ba4723f2ce7d12b5d326fec20045b2aedcc6c90746"},{"byte_length":2625,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/form-flow.md","schema_version":"2.0","source_sha256":"ff6cee7485991ff766a7d3d0780a133da5a636639aa9ff4a43e4d3bb0499a538","stable_ref":"sg:material/path-sha256-7e60233e663192c6172a4cebabf93da3b047c42bbaddee206fa27644d8d821e9","version_id":"sg:material/path-sha256-7e60233e663192c6172a4cebabf93da3b047c42bbaddee206fa27644d8d821e9@sha256:ff6cee7485991ff766a7d3d0780a133da5a636639aa9ff4a43e4d3bb0499a538"},{"byte_length":8708,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/vocabulary.md","schema_version":"2.0","source_sha256":"b9bf48c95052bb35bc509f0a37d6c03a97ede41fa615b241f16b9694d0636b4f","stable_ref":"sg:material/path-sha256-7ec7a08ac14b5af0def43c817f1b32765f93312bb997e17663313c0fd4516a1f","version_id":"sg:material/path-sha256-7ec7a08ac14b5af0def43c817f1b32765f93312bb997e17663313c0fd4516a1f@sha256:b9bf48c95052bb35bc509f0a37d6c03a97ede41fa615b241f16b9694d0636b4f"},{"byte_length":5787,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/decision-tree.md","schema_version":"2.0","source_sha256":"5811d48b577a0d9472c64b94cb91341f45e5b5408402455f0aa9cd356fa15c5d","stable_ref":"sg:material/path-sha256-7fada8e2c9a6ab17c122f51121605bc9d4c64c9a7ef60d946813129f91474016","version_id":"sg:material/path-sha256-7fada8e2c9a6ab17c122f51121605bc9d4c64c9a7ef60d946813129f91474016@sha256:5811d48b577a0d9472c64b94cb91341f45e5b5408402455f0aa9cd356fa15c5d"},{"byte_length":6236,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/design-terminology-domain-scope.md","schema_version":"2.0","source_sha256":"33fba7c68d9edd94bf5775ea87b30736038864d20aea8ffd00bd156343d6fcc7","stable_ref":"sg:material/path-sha256-81ac6c1074bdefbb95d68ecad0fd72b45835340e0f6b3353a0d2eb2bb30d3c63","version_id":"sg:material/path-sha256-81ac6c1074bdefbb95d68ecad0fd72b45835340e0f6b3353a0d2eb2bb30d3c63@sha256:33fba7c68d9edd94bf5775ea87b30736038864d20aea8ffd00bd156343d6fcc7"},{"byte_length":7930,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/layout-brief.md","schema_version":"2.0","source_sha256":"0e87d9d8f51ab6f3960b8e160abd9663be0d501e801a3184686b27c9a1debbf5","stable_ref":"sg:material/path-sha256-8305d3db8a3a860213c04b8cef5a4ed463a109f558be8df51ff1c5af21d749e1","version_id":"sg:material/path-sha256-8305d3db8a3a860213c04b8cef5a4ed463a109f558be8df51ff1c5af21d749e1@sha256:0e87d9d8f51ab6f3960b8e160abd9663be0d501e801a3184686b27c9a1debbf5"},{"byte_length":8203,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/pattern-contract-audit.md","schema_version":"2.0","source_sha256":"35926d5a3313f1918035ae906844722bbe56c7494eff9e5b22a2306a681893af","stable_ref":"sg:material/path-sha256-871ee653f2589835e85184dba2e5ef403fc064d0d49a2b2b85f0b8996d351fc6","version_id":"sg:material/path-sha256-871ee653f2589835e85184dba2e5ef403fc064d0d49a2b2b85f0b8996d351fc6@sha256:35926d5a3313f1918035ae906844722bbe56c7494eff9e5b22a2306a681893af"},{"byte_length":11836,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"guides/webpage-generation-workflow.md","schema_version":"2.0","source_sha256":"92de1966d23f3d12625f9cc22fb256eb8c4761bd4371a96ba69ca5235a23c7d4","stable_ref":"sg:material/path-sha256-87436c736fec1b7b05f6f0a824b06c852e9295daca92298163e02024fbb0451b","version_id":"sg:material/path-sha256-87436c736fec1b7b05f6f0a824b06c852e9295daca92298163e02024fbb0451b@sha256:92de1966d23f3d12625f9cc22fb256eb8c4761bd4371a96ba69ca5235a23c7d4"},{"byte_length":3615,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/frame.md","schema_version":"2.0","source_sha256":"649d3da72d9af6e6be2cdcd63561da9acb5521a0f44e46cc3210f02ece211104","stable_ref":"sg:material/path-sha256-882d5f2d004ba4375887b0489d4c452e3a6b3cfaea23561ba59e4e56821da256","version_id":"sg:material/path-sha256-882d5f2d004ba4375887b0489d4c452e3a6b3cfaea23561ba59e4e56821da256@sha256:649d3da72d9af6e6be2cdcd63561da9acb5521a0f44e46cc3210f02ece211104"},{"byte_length":3419,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/feed.md","schema_version":"2.0","source_sha256":"7f79317d1cb795bf3c407fabe5b4a894a2645dd4c732856f1bc07b05cb620e53","stable_ref":"sg:material/path-sha256-88b6e0985d823e16fad9888dd2133bb5e3c2a2203e3a1623a705ac883ea4a00c","version_id":"sg:material/path-sha256-88b6e0985d823e16fad9888dd2133bb5e3c2a2203e3a1623a705ac883ea4a00c@sha256:7f79317d1cb795bf3c407fabe5b4a894a2645dd4c732856f1bc07b05cb620e53"},{"byte_length":936,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/index.md","schema_version":"2.0","source_sha256":"973dabb4a682d02c0a60d611ae73c2b531f38fb2a3e3d2682f37a385c3f2f726","stable_ref":"sg:material/path-sha256-8a81d81ebc22075986a7fe5af4720c2779c2a456382fc0a3e74c1bfc8bb0f958","version_id":"sg:material/path-sha256-8a81d81ebc22075986a7fe5af4720c2779c2a456382fc0a3e74c1bfc8bb0f958@sha256:973dabb4a682d02c0a60d611ae73c2b531f38fb2a3e3d2682f37a385c3f2f726"},{"byte_length":3397,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/icon-frame.md","schema_version":"2.0","source_sha256":"09f79480d11a25c4ec7a9fbcdda2b62fa89ddf0da7142545841c3648078aa569","stable_ref":"sg:material/path-sha256-9100c52308320464deed2d7e13eb9857e485784f12f2dc1de28e8b73bc8f936b","version_id":"sg:material/path-sha256-9100c52308320464deed2d7e13eb9857e485784f12f2dc1de28e8b73bc8f936b@sha256:09f79480d11a25c4ec7a9fbcdda2b62fa89ddf0da7142545841c3648078aa569"},{"byte_length":7646,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/screen-recipes.md","schema_version":"2.0","source_sha256":"34ea7c53ebb21fb1c919301d8c0629b1923233e0944961744add48ae9d0dfffb","stable_ref":"sg:material/path-sha256-91628087b1cd66e6d4f46c8ccd922c32b38660a1eb468fbe1d112ccf72de2461","version_id":"sg:material/path-sha256-91628087b1cd66e6d4f46c8ccd922c32b38660a1eb468fbe1d112ccf72de2461@sha256:34ea7c53ebb21fb1c919301d8c0629b1923233e0944961744add48ae9d0dfffb"},{"byte_length":8158,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/apple-interaction.md","schema_version":"2.0","source_sha256":"d59726ca8d19fd36e58237246e090bd96a4bc92161606665794e8d78c5d9a4b2","stable_ref":"sg:material/path-sha256-9247a878dcd0a0977374938c50eeb9a622ad6203847c1169beaf81d0493ebb5b","version_id":"sg:material/path-sha256-9247a878dcd0a0977374938c50eeb9a622ad6203847c1169beaf81d0493ebb5b@sha256:d59726ca8d19fd36e58237246e090bd96a4bc92161606665794e8d78c5d9a4b2"},{"byte_length":4774,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/classification.md","schema_version":"2.0","source_sha256":"3ad0db32a74ddfcd4061cd35ee30cda764b9d1074599942001067f7a80b8f623","stable_ref":"sg:material/path-sha256-92725878c1f37c55731de2baf9c14a768fbd24ca839b82830c89f4aed7b66dce","version_id":"sg:material/path-sha256-92725878c1f37c55731de2baf9c14a768fbd24ca839b82830c89f4aed7b66dce@sha256:3ad0db32a74ddfcd4061cd35ee30cda764b9d1074599942001067f7a80b8f623"},{"byte_length":3457,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/wrap-row.md","schema_version":"2.0","source_sha256":"214d9e3d94366841f37f90c4c62096302c36f218843668e72c9a8850f6675920","stable_ref":"sg:material/path-sha256-94d8cf97bb7801865552f7d2b317b556ed6b643d53b73fad134de89186263585","version_id":"sg:material/path-sha256-94d8cf97bb7801865552f7d2b317b556ed6b643d53b73fad134de89186263585@sha256:214d9e3d94366841f37f90c4c62096302c36f218843668e72c9a8850f6675920"},{"byte_length":2502,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/families.md","schema_version":"2.0","source_sha256":"0e80ebefdc5a7c266c46f48342a9c6389eb5390d5f8c0f6f162f852c4b596690","stable_ref":"sg:material/path-sha256-956ab860e593d435b6682540b04365917b3736deb47207b5812065776734de0b","version_id":"sg:material/path-sha256-956ab860e593d435b6682540b04365917b3736deb47207b5812065776734de0b@sha256:0e80ebefdc5a7c266c46f48342a9c6389eb5390d5f8c0f6f162f852c4b596690"},{"byte_length":3678,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/badge-list.md","schema_version":"2.0","source_sha256":"aec85df4d5ddcfc08e9c052c5fdf60c0d4a73dbe8fea5a95b78b90c9871f1984","stable_ref":"sg:material/path-sha256-96fc7d48dad3399ab0cbedfdf8cb508b1732f57dc96cd15911e50a3a1654c9b1","version_id":"sg:material/path-sha256-96fc7d48dad3399ab0cbedfdf8cb508b1732f57dc96cd15911e50a3a1654c9b1@sha256:aec85df4d5ddcfc08e9c052c5fdf60c0d4a73dbe8fea5a95b78b90c9871f1984"},{"byte_length":952,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/visual-qa.md","schema_version":"2.0","source_sha256":"9fdfd9acdcd4fefd4f2d3ef51ba6170e3235d4ae97cc6c739a0f1123e1825f74","stable_ref":"sg:material/path-sha256-970cc2193de22b50bd91099cd6f8e5f52069ccd3360306d17e6eacf4ed1343ae","version_id":"sg:material/path-sha256-970cc2193de22b50bd91099cd6f8e5f52069ccd3360306d17e6eacf4ed1343ae@sha256:9fdfd9acdcd4fefd4f2d3ef51ba6170e3235d4ae97cc6c739a0f1123e1825f74"},{"byte_length":9489,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/primitive-to-recipe-matrix.md","schema_version":"2.0","source_sha256":"0e8b3b90651c8820a0c0463c32bf410e40abb7503a26e9c90b1fdb456d4ad7b3","stable_ref":"sg:material/path-sha256-99427f2ded107b0d7be95e3a768ac836b917b22c8736fb7f31028b33a333836d","version_id":"sg:material/path-sha256-99427f2ded107b0d7be95e3a768ac836b917b22c8736fb7f31028b33a333836d@sha256:0e8b3b90651c8820a0c0463c32bf410e40abb7503a26e9c90b1fdb456d4ad7b3"},{"byte_length":3743,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/supporting-pane.md","schema_version":"2.0","source_sha256":"bbffaf1bcf0daa4d30f5d269fda79759778b23c2f7c388d95d0ca45e0512c962","stable_ref":"sg:material/path-sha256-9a82e011fc565919a7334610d427c1ec662e2b89034c6da9a2b135dc398444da","version_id":"sg:material/path-sha256-9a82e011fc565919a7334610d427c1ec662e2b89034c6da9a2b135dc398444da@sha256:bbffaf1bcf0daa4d30f5d269fda79759778b23c2f7c388d95d0ca45e0512c962"},{"byte_length":5032,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/source-kinds.md","schema_version":"2.0","source_sha256":"089db825ae87a2b5660cbe3ff3cd0501864952f6ba4d717ca0d299c524f55912","stable_ref":"sg:material/path-sha256-9bf12d243f458c4641241baed05117806d5865bf05115ebbb49ac44f4f349f4f","version_id":"sg:material/path-sha256-9bf12d243f458c4641241baed05117806d5865bf05115ebbb49ac44f4f349f4f@sha256:089db825ae87a2b5660cbe3ff3cd0501864952f6ba4d717ca0d299c524f55912"},{"byte_length":3664,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/panel-layout.md","schema_version":"2.0","source_sha256":"1e373e1e0a03296d3262d2df4caa0a0c907693c6dfdad19d8d608b574e1ae123","stable_ref":"sg:material/path-sha256-9c016feea05fe406dddaf432e9137d8d56c71df33fb77450e538d21c9871e85f","version_id":"sg:material/path-sha256-9c016feea05fe406dddaf432e9137d8d56c71df33fb77450e538d21c9871e85f@sha256:1e373e1e0a03296d3262d2df4caa0a0c907693c6dfdad19d8d608b574e1ae123"},{"byte_length":2378,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/saas-settings.md","schema_version":"2.0","source_sha256":"f66665f62f1ac1242965326e47bd7a021ec9ed812e98155147f82be0bc00c5ad","stable_ref":"sg:material/path-sha256-9dfe65b7582876aed144b8b79ad8ffbde14182c8b9c082c6916057782509cd0e","version_id":"sg:material/path-sha256-9dfe65b7582876aed144b8b79ad8ffbde14182c8b9c082c6916057782509cd0e@sha256:f66665f62f1ac1242965326e47bd7a021ec9ed812e98155147f82be0bc00c5ad"},{"byte_length":2169,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"recipes/article-page.md","schema_version":"2.0","source_sha256":"e68b1049e6e2e0dd08e87c1b5dd8ef36f42350c161aa6d056f5ddcdbb091d28d","stable_ref":"sg:material/path-sha256-a0c4596e930ce74c5bf8f890a6e037abbd07463c1e1aa0b35c40a0c2009ba011","version_id":"sg:material/path-sha256-a0c4596e930ce74c5bf8f890a6e037abbd07463c1e1aa0b35c40a0c2009ba011@sha256:e68b1049e6e2e0dd08e87c1b5dd8ef36f42350c161aa6d056f5ddcdbb091d28d"},{"byte_length":6749,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/interaction-recipes.md","schema_version":"2.0","source_sha256":"6ec291c97ef82415efe7dbc9a355a405c214400cd61516468d749d98997e6821","stable_ref":"sg:material/path-sha256-a2188f6421d8ce1d9cf926193014f31af7bff1fb6101e42b87ff364c201f9d6e","version_id":"sg:material/path-sha256-a2188f6421d8ce1d9cf926193014f31af7bff1fb6101e42b87ff364c201f9d6e@sha256:6ec291c97ef82415efe7dbc9a355a405c214400cd61516468d749d98997e6821"},{"byte_length":4104,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"index.md","schema_version":"2.0","source_sha256":"7e0109cee873272fbdeeeaa0a7598f24d93bb2a48cdd63b5150132204c6eed1b","stable_ref":"sg:material/path-sha256-a48746cae70c44e7e105b594aad338ddd105c93c1cb445a40ba6aab785ba69e5","version_id":"sg:material/path-sha256-a48746cae70c44e7e105b594aad338ddd105c93c1cb445a40ba6aab785ba69e5@sha256:7e0109cee873272fbdeeeaa0a7598f24d93bb2a48cdd63b5150132204c6eed1b"},{"byte_length":10562,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/unity/repository-map.md","schema_version":"2.0","source_sha256":"aa6535fe435bc831a819f9f82ed29ad593ec133cc4f84be231355879ce145f9e","stable_ref":"sg:material/path-sha256-a4f5bfbc74a2b756b0661004893a21d81b1007879d2e2c4aaa4b73f1b083d434","version_id":"sg:material/path-sha256-a4f5bfbc74a2b756b0661004893a21d81b1007879d2e2c4aaa4b73f1b083d434@sha256:aa6535fe435bc831a819f9f82ed29ad593ec133cc4f84be231355879ce145f9e"},{"byte_length":8971,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"AGENTS.md","schema_version":"2.0","source_sha256":"fb201d32ede32e5f6d6fd27e5cfb0d4c8f9fa616f7d7807872990359a7562595","stable_ref":"sg:material/path-sha256-a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9","version_id":"sg:material/path-sha256-a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9@sha256:fb201d32ede32e5f6d6fd27e5cfb0d4c8f9fa616f7d7807872990359a7562595"},{"byte_length":3493,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/card-grid.md","schema_version":"2.0","source_sha256":"e2489c93d8f312b0104e14cd54d92940f2b094e7c7a1310b6be4e0653b2729a4","stable_ref":"sg:material/path-sha256-a5e3ff6fe0948ebbaf30def7866421563073877df12336c5f66eba3d2d6667a5","version_id":"sg:material/path-sha256-a5e3ff6fe0948ebbaf30def7866421563073877df12336c5f66eba3d2d6667a5@sha256:e2489c93d8f312b0104e14cd54d92940f2b094e7c7a1310b6be4e0653b2729a4"},{"byte_length":1194,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/index.md","schema_version":"2.0","source_sha256":"c52bbc8df395ff56e4cad12ced76ba5ee55f4a95c49efaf53825d13c32feab49","stable_ref":"sg:material/path-sha256-a7987410bcf408a5b4edc0ae7719d3f57f1f04a4efaaa7a756c870677307fd85","version_id":"sg:material/path-sha256-a7987410bcf408a5b4edc0ae7719d3f57f1f04a4efaaa7a756c870677307fd85@sha256:c52bbc8df395ff56e4cad12ced76ba5ee55f4a95c49efaf53825d13c32feab49"},{"byte_length":886,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/index.md","schema_version":"2.0","source_sha256":"8687d8285459805273e27f5ca9b5fcd10fbd0899786443445666155630bbf4bb","stable_ref":"sg:material/path-sha256-aa41c9d5c021c9d6a6e06df6c53297c0d271f71b3a299303d8a330644f6998f1","version_id":"sg:material/path-sha256-aa41c9d5c021c9d6a6e06df6c53297c0d271f71b3a299303d8a330644f6998f1@sha256:8687d8285459805273e27f5ca9b5fcd10fbd0899786443445666155630bbf4bb"},{"byte_length":2510,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claim-records/stylegallery-multidomain-scope.md","schema_version":"2.0","source_sha256":"fb5f0cebaaea0998c5dd05721b2e3818a2f91e2407628c740da08877d5b94a19","stable_ref":"sg:material/path-sha256-abaaac8db5d4ad334a6b84253118bdd282aba92b9a55daf5710b2b6d6d14c399","version_id":"sg:material/path-sha256-abaaac8db5d4ad334a6b84253118bdd282aba92b9a55daf5710b2b6d6d14c399@sha256:fb5f0cebaaea0998c5dd05721b2e3818a2f91e2407628c740da08877d5b94a19"},{"byte_length":6107,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/comparison-workflow.md","schema_version":"2.0","source_sha256":"33746616932fe730285607c0cda5bf8019500884cb5cb67fdce0285ef71af0c4","stable_ref":"sg:material/path-sha256-ae7b1857d77dd0986c8000255f0bb7eeb79e3750bc19cdd426ca7d571f120a6d","version_id":"sg:material/path-sha256-ae7b1857d77dd0986c8000255f0bb7eeb79e3750bc19cdd426ca7d571f120a6d@sha256:33746616932fe730285607c0cda5bf8019500884cb5cb67fdce0285ef71af0c4"},{"byte_length":4989,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/windows-interaction.md","schema_version":"2.0","source_sha256":"f10b6f05b647a2623f0510da2c38e6232809a34c3d19e52fa3f4241724a0b11d","stable_ref":"sg:material/path-sha256-b33142b70ab23f291695fe451ad410aeddc24b3f4853d817a731a26072dc4c32","version_id":"sg:material/path-sha256-b33142b70ab23f291695fe451ad410aeddc24b3f4853d817a731a26072dc4c32@sha256:f10b6f05b647a2623f0510da2c38e6232809a34c3d19e52fa3f4241724a0b11d"},{"byte_length":20266,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"README.md","schema_version":"2.0","source_sha256":"0a761242328def2ebd41f0c2c71282f615f45278713d7d5f004d4a9d754d0c38","stable_ref":"sg:material/path-sha256-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5","version_id":"sg:material/path-sha256-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5@sha256:0a761242328def2ebd41f0c2c71282f615f45278713d7d5f004d4a9d754d0c38"},{"byte_length":7121,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/source-vocabularies.md","schema_version":"2.0","source_sha256":"ac116002c41eb17fd817b0190fdb93fda3262ae38199d74d6e727dba7f22321a","stable_ref":"sg:material/path-sha256-b3c9a665848204252a912ce4a369ccbd4e5b6e63209fa8cd393b0854d3a3b309","version_id":"sg:material/path-sha256-b3c9a665848204252a912ce4a369ccbd4e5b6e63209fa8cd393b0854d3a3b309@sha256:ac116002c41eb17fd817b0190fdb93fda3262ae38199d74d6e727dba7f22321a"},{"byte_length":4802,"domain":"platform-guides","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"platform-guides/adaptation-workflow.md","schema_version":"2.0","source_sha256":"8aea8bc14348b793e25e69cbbe6437e5c1f27a236227a012acb8a9dc5995eece","stable_ref":"sg:material/path-sha256-b59c0c528c094b9299490c7964ed10a188ae059e0bee97688f68c7edbfe8d561","version_id":"sg:material/path-sha256-b59c0c528c094b9299490c7964ed10a188ae059e0bee97688f68c7edbfe8d561@sha256:8aea8bc14348b793e25e69cbbe6437e5c1f27a236227a012acb8a9dc5995eece"},{"byte_length":31273,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"GOVERNANCE.md","schema_version":"2.0","source_sha256":"e5548696eb312be4f64c819c738f4c1116fad774e28b9aac4b44ac993ffb2526","stable_ref":"sg:material/path-sha256-b60c6a93e9f74ee52e71bf33781c2870b8395c8c5a34f00f61305343cb8d8447","version_id":"sg:material/path-sha256-b60c6a93e9f74ee52e71bf33781c2870b8395c8c5a34f00f61305343cb8d8447@sha256:e5548696eb312be4f64c819c738f4c1116fad774e28b9aac4b44ac993ffb2526"},{"byte_length":2082,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/index.md","schema_version":"2.0","source_sha256":"2b4af7651d53a7b08e67a52aa8413c145d7a9dc2f7a057dc5c40025aef200eba","stable_ref":"sg:material/path-sha256-b6b2ce37f6c04566c4dc6a18252e1d89fc387c7e79f4463406deff3e8b54a81f","version_id":"sg:material/path-sha256-b6b2ce37f6c04566c4dc6a18252e1d89fc387c7e79f4463406deff3e8b54a81f@sha256:2b4af7651d53a7b08e67a52aa8413c145d7a9dc2f7a057dc5c40025aef200eba"},{"byte_length":6870,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/worked-examples.md","schema_version":"2.0","source_sha256":"0454f276162f437c479e93278971be7afb99d369cbfcfcd5fdc20df65a39b8a1","stable_ref":"sg:material/path-sha256-b6d27588195494826083fe6ad6f8f08ba0ad8016a0f64a0d442fde1414c0b1a0","version_id":"sg:material/path-sha256-b6d27588195494826083fe6ad6f8f08ba0ad8016a0f64a0d442fde1414c0b1a0@sha256:0454f276162f437c479e93278971be7afb99d369cbfcfcd5fdc20df65a39b8a1"},{"byte_length":4657,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/concept-families.md","schema_version":"2.0","source_sha256":"d44d8782dc1c373757baf46064d8f5b44cd226025e4bad269006141e50be8c2f","stable_ref":"sg:material/path-sha256-b73e23057d4ca2412792354487c8709f1bcfe844eaf3c154fec167b48c80bd16","version_id":"sg:material/path-sha256-b73e23057d4ca2412792354487c8709f1bcfe844eaf3c154fec167b48c80bd16@sha256:d44d8782dc1c373757baf46064d8f5b44cd226025e4bad269006141e50be8c2f"},{"byte_length":2699,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/accessibility-evidence.md","schema_version":"2.0","source_sha256":"fa07b1354ee7973317512b2f84d37d1f3965465962df74e9e1ee21a47f66ae4e","stable_ref":"sg:material/path-sha256-b7de05a789ffd0312cd9e9b1828ce113b1fcc3dcf5a87b73295a09e1004bfbe3","version_id":"sg:material/path-sha256-b7de05a789ffd0312cd9e9b1828ce113b1fcc3dcf5a87b73295a09e1004bfbe3@sha256:fa07b1354ee7973317512b2f84d37d1f3965465962df74e9e1ee21a47f66ae4e"},{"byte_length":4646,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/decision-tree.md","schema_version":"2.0","source_sha256":"4282cfbc372755a2aa043a1579df1a80d2c82fa2ea5d6f17a6327d22b8c859bb","stable_ref":"sg:material/path-sha256-b87b58f118ff70b806e2b1834e5a03e43a877d489f4af3f55ebfb4ab4a9fc8fa","version_id":"sg:material/path-sha256-b87b58f118ff70b806e2b1834e5a03e43a877d489f4af3f55ebfb4ab4a9fc8fa@sha256:4282cfbc372755a2aa043a1579df1a80d2c82fa2ea5d6f17a6327d22b8c859bb"},{"byte_length":6672,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"CATALOG.md","schema_version":"2.0","source_sha256":"6902e0b03d958816abc142a950cedb51a9a623c1acc5b1a7a94cc4f38a70eb8a","stable_ref":"sg:material/path-sha256-bb476268db5ed6523e97a56f61d3ec99765899bf3269949ee1aac390f48f1b99","version_id":"sg:material/path-sha256-bb476268db5ed6523e97a56f61d3ec99765899bf3269949ee1aac390f48f1b99@sha256:6902e0b03d958816abc142a950cedb51a9a623c1acc5b1a7a94cc4f38a70eb8a"},{"byte_length":3837,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/split-sidebar/sidebar.md","schema_version":"2.0","source_sha256":"75edbf6107702e2c44f8ebdd724ec9b40ec8362729441c0ef1e073444c9ddb8e","stable_ref":"sg:material/path-sha256-bd2be8d5407fa6cf6a9bfaacf5d35e3b08eadea21e394cb0951a4e22290720a2","version_id":"sg:material/path-sha256-bd2be8d5407fa6cf6a9bfaacf5d35e3b08eadea21e394cb0951a4e22290720a2@sha256:75edbf6107702e2c44f8ebdd724ec9b40ec8362729441c0ef1e073444c9ddb8e"},{"byte_length":2932,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/consumer-migration-evidence.md","schema_version":"2.0","source_sha256":"71ad54bf72f5c968b8a0c5bd02b988660c6f441dbda13f9142d57842be498e6a","stable_ref":"sg:material/path-sha256-bd5e2b1ee33580f11a3a67b5306df57a54a539d5e944331511eb72fa9fe4e8f9","version_id":"sg:material/path-sha256-bd5e2b1ee33580f11a3a67b5306df57a54a539d5e944331511eb72fa9fe4e8f9@sha256:71ad54bf72f5c968b8a0c5bd02b988660c6f441dbda13f9142d57842be498e6a"},{"byte_length":3601,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/cover.md","schema_version":"2.0","source_sha256":"c78423cba85c44acfe985b44f7da72dfa52fdb20de2c87beb9d085062b451b6f","stable_ref":"sg:material/path-sha256-bf39299bae7cfb1c999e3d86ab9106128c573c2a83c8f2f08f14572a94f0c5a7","version_id":"sg:material/path-sha256-bf39299bae7cfb1c999e3d86ab9106128c573c2a83c8f2f08f14572a94f0c5a7@sha256:c78423cba85c44acfe985b44f7da72dfa52fdb20de2c87beb9d085062b451b6f"},{"byte_length":3660,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/twelve-span-grid.md","schema_version":"2.0","source_sha256":"7747b78dbe22604d9d4944f32ad89b8337961f76d2a8f2775c9efb7fe67ba879","stable_ref":"sg:material/path-sha256-c0d7d6f086cfa95c3163b3cf7692cee97e3e16dba0de964706bee174841d2094","version_id":"sg:material/path-sha256-c0d7d6f086cfa95c3163b3cf7692cee97e3e16dba0de964706bee174841d2094@sha256:7747b78dbe22604d9d4944f32ad89b8337961f76d2a8f2775c9efb7fe67ba879"},{"byte_length":3405,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/stacking/step-nav.md","schema_version":"2.0","source_sha256":"1b74a5b72ab2352f35f40247da26ab0eb3cecdc8a75754a071cacf263537a438","stable_ref":"sg:material/path-sha256-c1d82e696f9b42772a53643bf7ac7fbddc964e528aa09fb7f155b442660b6262","version_id":"sg:material/path-sha256-c1d82e696f9b42772a53643bf7ac7fbddc964e528aa09fb7f155b442660b6262@sha256:1b74a5b72ab2352f35f40247da26ab0eb3cecdc8a75754a071cacf263537a438"},{"byte_length":18956,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/executable-evidence.md","schema_version":"2.0","source_sha256":"fb441412dabc0b57aeac8355f92321a9873aa67612e489e3137953d7680312b1","stable_ref":"sg:material/path-sha256-c609296f2ae6b1d6234dbb3497f9d6a45208ba0470a3d8b4a861be79bae797c8","version_id":"sg:material/path-sha256-c609296f2ae6b1d6234dbb3497f9d6a45208ba0470a3d8b4a861be79bae797c8@sha256:fb441412dabc0b57aeac8355f92321a9873aa67612e489e3137953d7680312b1"},{"byte_length":8221,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"DOMAINS.md","schema_version":"2.0","source_sha256":"cdd0de68ce95ba3517f8fa4d05272086b01ab8fe330fc5049e5139cd467d002c","stable_ref":"sg:material/path-sha256-d190306dc8097b7ef0ec2a57ed020076a9f325b48f083aba3f62de5e886af5ab","version_id":"sg:material/path-sha256-d190306dc8097b7ef0ec2a57ed020076a9f325b48f083aba3f62de5e886af5ab@sha256:cdd0de68ce95ba3517f8fa4d05272086b01ab8fe330fc5049e5139cd467d002c"},{"byte_length":910,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/index.md","schema_version":"2.0","source_sha256":"fecba190f4bcb2f3e7fbce19c02181fae7613fc51da6b20539a17ef5d37e78f2","stable_ref":"sg:material/path-sha256-d312b8ccb45a40e38e38e6d6d1e95ee074d50714cdcf872de9afd4e4254a4301","version_id":"sg:material/path-sha256-d312b8ccb45a40e38e38e6d6d1e95ee074d50714cdcf872de9afd4e4254a4301@sha256:fecba190f4bcb2f3e7fbce19c02181fae7613fc51da6b20539a17ef5d37e78f2"},{"byte_length":3707,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/in-line-grouping/split-nav.md","schema_version":"2.0","source_sha256":"b797721ee74570f537fd79fbdec6077048764723f176c995341f5b8b8b1de432","stable_ref":"sg:material/path-sha256-d657fc87c00278cd49d87fb6a43b8596834943cf85f71d7cc873c102e56a5587","version_id":"sg:material/path-sha256-d657fc87c00278cd49d87fb6a43b8596834943cf85f71d7cc873c102e56a5587@sha256:b797721ee74570f537fd79fbdec6077048764723f176c995341f5b8b8b1de432"},{"byte_length":3433,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/index.md","schema_version":"2.0","source_sha256":"e9180d2a1480ce6c2e17d809e9d3e004acda1e09143bdaf71839d49f47a8da99","stable_ref":"sg:material/path-sha256-db7c4f17ca762b1169e43401710a0d95c03161ec7e38143c65fd8e888236f1e6","version_id":"sg:material/path-sha256-db7c4f17ca762b1169e43401710a0d95c03161ec7e38143c65fd8e888236f1e6@sha256:e9180d2a1480ce6c2e17d809e9d3e004acda1e09143bdaf71839d49f47a8da99"},{"byte_length":3944,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/consumer-migration.md","schema_version":"2.0","source_sha256":"a9e61500abbce740ca43f941aeb15a7bfebad46585584e0a45da59ce94334f29","stable_ref":"sg:material/path-sha256-ddc1d0e9544d4a08bb43703f230dcdfea087f2faf90d9a49e4aa22695b07178a","version_id":"sg:material/path-sha256-ddc1d0e9544d4a08bb43703f230dcdfea087f2faf90d9a49e4aa22695b07178a@sha256:a9e61500abbce740ca43f941aeb15a7bfebad46585584e0a45da59ce94334f29"},{"byte_length":2741,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/principles.md","schema_version":"2.0","source_sha256":"1834b852ae156c7362d4f9b223b4d72dc6b708a1f2a2964022955940a9c1fdc4","stable_ref":"sg:material/path-sha256-deba5ef88dc8bdc60813a398130b8a3ca3a8d01124f45823f5834ebda967996c","version_id":"sg:material/path-sha256-deba5ef88dc8bdc60813a398130b8a3ca3a8d01124f45823f5834ebda967996c@sha256:1834b852ae156c7362d4f9b223b4d72dc6b708a1f2a2964022955940a9c1fdc4"},{"byte_length":3655,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"consumer-reference/index.md","schema_version":"2.0","source_sha256":"6c3fbad093a7becb9f2ca52a344a65dd02b3da51f49a915af6426a61f2a06208","stable_ref":"sg:material/path-sha256-df7a6343d7be1e9be37c6f618a7e72b0ac51be6143f64f419b4520e5f37c2b6b","version_id":"sg:material/path-sha256-df7a6343d7be1e9be37c6f618a7e72b0ac51be6143f64f419b4520e5f37c2b6b@sha256:6c3fbad093a7becb9f2ca52a344a65dd02b3da51f49a915af6426a61f2a06208"},{"byte_length":338,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/centering/index.md","schema_version":"2.0","source_sha256":"b7125eb4c4d705a1bb2d57ac7e9d4cf140627473aac687331573bf30b0decd30","stable_ref":"sg:material/path-sha256-e1319590d4485778ddb92cc3c1f781b4f7e06d934d5849336f96588ee3592aa8","version_id":"sg:material/path-sha256-e1319590d4485778ddb92cc3c1f781b4f7e06d934d5849336f96588ee3592aa8@sha256:b7125eb4c4d705a1bb2d57ac7e9d4cf140627473aac687331573bf30b0decd30"},{"byte_length":3536,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/containment/content-limiter.md","schema_version":"2.0","source_sha256":"505df6aac4ab3b5a9041cedaa04e74c2253ce2f8b9a12abf3d8835d2a9ce169c","stable_ref":"sg:material/path-sha256-e1c9957e26f0e3ee1235a070fbe69d31ed5974bce8c4fe14c63537909991a750","version_id":"sg:material/path-sha256-e1c9957e26f0e3ee1235a070fbe69d31ed5974bce8c4fe14c63537909991a750@sha256:505df6aac4ab3b5a9041cedaa04e74c2253ce2f8b9a12abf3d8835d2a9ce169c"},{"byte_length":3595,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/grid-repetition/masonry-approx.md","schema_version":"2.0","source_sha256":"a176ffb2966ea5ed8b3ad22d013ed2fdd82e54a904be057a9e391087d4ad6654","stable_ref":"sg:material/path-sha256-e277a76f0335dd426d8b64001be63fd56ab91a03c4ade0526ea10c4631251abb","version_id":"sg:material/path-sha256-e277a76f0335dd426d8b64001be63fd56ab91a03c4ade0526ea10c4631251abb@sha256:a176ffb2966ea5ed8b3ad22d013ed2fdd82e54a904be057a9e391087d4ad6654"},{"byte_length":8104,"domain":"design-engineering","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-engineering/consumer-migration-readiness.md","schema_version":"2.0","source_sha256":"86dc5148b052b372b0132d159d2c3ab819a859b5f210e3a1a994c29c7478b276","stable_ref":"sg:material/path-sha256-e2d4ce07445db974a7f32e5eec810897cfb565df619df52961f3eefa5a9c3fd4","version_id":"sg:material/path-sha256-e2d4ce07445db974a7f32e5eec810897cfb565df619df52961f3eefa5a9c3fd4@sha256:86dc5148b052b372b0132d159d2c3ab819a859b5f210e3a1a994c29c7478b276"},{"byte_length":1081,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/hci-evaluation.md","schema_version":"2.0","source_sha256":"9deeeeb4c0fc9b24d79e68b6e38236f2993da2544ecc0d130256136d2b062aae","stable_ref":"sg:material/path-sha256-e5f16e01f3fb13f94a214c8a9edf9b5c31c4ebca963802dfc624e8863e98f8da","version_id":"sg:material/path-sha256-e5f16e01f3fb13f94a214c8a9edf9b5c31c4ebca963802dfc624e8863e98f8da@sha256:9deeeeb4c0fc9b24d79e68b6e38236f2993da2544ecc0d130256136d2b062aae"},{"byte_length":5333,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/index.md","schema_version":"2.0","source_sha256":"cfd3973a2e472f1e9d53ea9fa89f00f991fbe5d0e5fb0e4778ebd7477da9c7ed","stable_ref":"sg:material/path-sha256-e678b2e7915fc4abf6a019c86f8a7d74b8939a60220cb08a810900e1b5cbc2bc","version_id":"sg:material/path-sha256-e678b2e7915fc4abf6a019c86f8a7d74b8939a60220cb08a810900e1b5cbc2bc@sha256:cfd3973a2e472f1e9d53ea9fa89f00f991fbe5d0e5fb0e4778ebd7477da9c7ed"},{"byte_length":9887,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/conflict-cases.md","schema_version":"2.0","source_sha256":"cdf592866d054278d6c53fff603f4a67e0cd846194fef8b897a6ea94baaf5dcf","stable_ref":"sg:material/path-sha256-ebd0ba0ee0bdb5529496beddce60a4e78b65d94c9650c57ed7499427d417aa19","version_id":"sg:material/path-sha256-ebd0ba0ee0bdb5529496beddce60a4e78b65d94c9650c57ed7499427d417aa19@sha256:cdf592866d054278d6c53fff603f4a67e0cd846194fef8b897a6ea94baaf5dcf"},{"byte_length":2742,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/claims.md","schema_version":"2.0","source_sha256":"8f28f2a42891946bf2929fb2bf5b122bfe63edb8b47a0b926183760d2bc9b15c","stable_ref":"sg:material/path-sha256-ec031d838419829b80465b2f31de260e70117bdd283988e0653441d439a65114","version_id":"sg:material/path-sha256-ec031d838419829b80465b2f31de260e70117bdd283988e0653441d439a65114@sha256:8f28f2a42891946bf2929fb2bf5b122bfe63edb8b47a0b926183760d2bc9b15c"},{"byte_length":2727,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/evidence/accessibility.md","schema_version":"2.0","source_sha256":"cc5a68a5e1721914fd00537b66aecb4e58c92c89962cc5fabd5ed0fc39930e95","stable_ref":"sg:material/path-sha256-eeea8e16127c63b10e90f626430df368a97fac8108b419c1cba89805b6014ce7","version_id":"sg:material/path-sha256-eeea8e16127c63b10e90f626430df368a97fac8108b419c1cba89805b6014ce7@sha256:cc5a68a5e1721914fd00537b66aecb4e58c92c89962cc5fabd5ed0fc39930e95"},{"byte_length":6696,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"layout/index.md","schema_version":"2.0","source_sha256":"03bba4cd15b3f507ae44094c472c8839e4b1f875ded63d9f13ec868ee8e184b2","stable_ref":"sg:material/path-sha256-f05a4c57bb475ff014a22abaa9120b04f05bc02d8bbe11f57677bd7662276f54","version_id":"sg:material/path-sha256-f05a4c57bb475ff014a22abaa9120b04f05bc02d8bbe11f57677bd7662276f54@sha256:03bba4cd15b3f507ae44094c472c8839e4b1f875ded63d9f13ec868ee8e184b2"},{"byte_length":3844,"domain":"layout","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"GUIDE.md","schema_version":"2.0","source_sha256":"f105ff6ed3c6923ea43dacc4c40632affee4874e086a333b9ce3fa2a786234da","stable_ref":"sg:material/path-sha256-f0d91300831f8bc350b2883e8adf82bdbcb79f482585168420831991e320ade7","version_id":"sg:material/path-sha256-f0d91300831f8bc350b2883e8adf82bdbcb79f482585168420831991e320ade7@sha256:f105ff6ed3c6923ea43dacc4c40632affee4874e086a333b9ce3fa2a786234da"},{"byte_length":1668,"domain":"motion","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"motion/index.md","schema_version":"2.0","source_sha256":"f762182ff0cb3fcb96ccc357b439eff1185a3af7487e9171e50bbf1f38a6f538","stable_ref":"sg:material/path-sha256-f56daa946060f9e1f75d42246e0fa7a288093bf6d902cc9705a2c5b13c65310f","version_id":"sg:material/path-sha256-f56daa946060f9e1f75d42246e0fa7a288093bf6d902cc9705a2c5b13c65310f@sha256:f762182ff0cb3fcb96ccc357b439eff1185a3af7487e9171e50bbf1f38a6f538"},{"byte_length":1748,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/layout.md","schema_version":"2.0","source_sha256":"e7306ec2101bcbc1f27153160796ef56ba7846d6c7e5219d92e56b77e0703882","stable_ref":"sg:material/path-sha256-f62872ebce1ea7ffc61cd5522572c6d0f6aecd782c9e30df376bdcd96c7e73d3","version_id":"sg:material/path-sha256-f62872ebce1ea7ffc61cd5522572c6d0f6aecd782c9e30df376bdcd96c7e73d3@sha256:e7306ec2101bcbc1f27153160796ef56ba7846d6c7e5219d92e56b77e0703882"},{"byte_length":347,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/media-fit/index.md","schema_version":"2.0","source_sha256":"24fa906c939cad71b0f175aab12ec75a16718c66446a31bedfcd3d1d46a67ae6","stable_ref":"sg:material/path-sha256-f77cbae09754bece5a3217dbf7cf766189bb5302d6296fab69bd6f5b3d6e495e","version_id":"sg:material/path-sha256-f77cbae09754bece5a3217dbf7cf766189bb5302d6296fab69bd6f5b3d6e495e@sha256:24fa906c939cad71b0f175aab12ec75a16718c66446a31bedfcd3d1d46a67ae6"},{"byte_length":1550,"domain":"shared","lifecycle":"stable","media_type":"text/markdown","record_kind":"material","repository_path":"quality/gates/rationale.md","schema_version":"2.0","source_sha256":"875771978927372959dea499fba00bf1fd0d0d2426d35601aa3e418698ccd1ab","stable_ref":"sg:material/path-sha256-f797bc85a767e4a6ea1339cf7cc91d2504c722f3a02614d6174e59978db906a6","version_id":"sg:material/path-sha256-f797bc85a767e4a6ea1339cf7cc91d2504c722f3a02614d6174e59978db906a6@sha256:875771978927372959dea499fba00bf1fd0d0d2426d35601aa3e418698ccd1ab"},{"byte_length":4183,"domain":"layout","lifecycle":"generated","media_type":"text/markdown","record_kind":"material","repository_path":"patterns/viewport-shell/holy-grail.md","schema_version":"2.0","source_sha256":"b5b1335b55674e703636d1d205b80f8da8e99768ed7de9505f99afe233449031","stable_ref":"sg:material/path-sha256-f968729fb5885c124f8e1cab2c273f7e3b6fefd858be7f71d1b3958b48f4f2a9","version_id":"sg:material/path-sha256-f968729fb5885c124f8e1cab2c273f7e3b6fefd858be7f71d1b3958b48f4f2a9@sha256:b5b1335b55674e703636d1d205b80f8da8e99768ed7de9505f99afe233449031"},{"byte_length":6167,"domain":"design-terminology","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"design-terminology/index.md","schema_version":"2.0","source_sha256":"9a9e449f00bbf9e39b88fdc91260d4ff3669042f8e0afe64ed59e837d6e5c9c1","stable_ref":"sg:material/path-sha256-fa36065f2020c60e811e07b08ff9ab0969520183389a14652d456f7cf7364d55","version_id":"sg:material/path-sha256-fa36065f2020c60e811e07b08ff9ab0969520183389a14652d456f7cf7364d55@sha256:9a9e449f00bbf9e39b88fdc91260d4ff3669042f8e0afe64ed59e837d6e5c9c1"},{"byte_length":4863,"domain":"game-ui","lifecycle":"experimental","media_type":"text/markdown","record_kind":"material","repository_path":"game-ui/decision-tree.md","schema_version":"2.0","source_sha256":"d5341432032b42da8de47aed0c63810ec8716bca503571b6d556c7cc314f7df4","stable_ref":"sg:material/path-sha256-fb069274a780d16a4be2cfa1d345e1200d3018997c88f4ee40ba494e682a3d15","version_id":"sg:material/path-sha256-fb069274a780d16a4be2cfa1d345e1200d3018997c88f4ee40ba494e682a3d15@sha256:d5341432032b42da8de47aed0c63810ec8716bca503571b6d556c7cc314f7df4"}],"record_kind":"material_manifest","schema_version":"2.0","stable_ref":"sg:manifest/material-admission-v2","version_id":"sg:manifest/material-admission-v2@sha256:9a1444f71f6a6868a7139f24060322b151477949493a08d25ca6d7e4a9676c02"} \ No newline at end of file diff --git a/consumer-reference/agent-native/v2/schema/admission-policy.schema.json b/consumer-reference/agent-native/v2/schema/admission-policy.schema.json index 43915a1..e3228ee 100644 --- a/consumer-reference/agent-native/v2/schema/admission-policy.schema.json +++ b/consumer-reference/agent-native/v2/schema/admission-policy.schema.json @@ -13,15 +13,15 @@ "media_type": { "const": "text/markdown" }, "allowed_materials": { "type": "array", - "minItems": 126, - "maxItems": 126, + "minItems": 147, + "maxItems": 147, "items": { "type": "object", "additionalProperties": false, "required": ["repository_path", "domain", "lifecycle"], "properties": { "repository_path": { "type": "string", "pattern": "^(?!/)(?!.*(?:^|/)\\.{1,2}(?:/|$))[A-Za-z0-9._ -]+(?:/[A-Za-z0-9._ -]+)*\\.md$" }, - "domain": { "enum": ["layout", "motion", "design-engineering", "game-ui", "platform-guides", "shared"] }, + "domain": { "enum": ["layout", "motion", "design-engineering", "game-ui", "platform-guides", "design-terminology", "shared"] }, "lifecycle": { "enum": ["draft", "stable", "deprecated", "experimental", "generated"] } } } diff --git a/consumer-reference/agent-native/v2/schema/material-record.schema.json b/consumer-reference/agent-native/v2/schema/material-record.schema.json index 365f566..f5dae9b 100644 --- a/consumer-reference/agent-native/v2/schema/material-record.schema.json +++ b/consumer-reference/agent-native/v2/schema/material-record.schema.json @@ -15,6 +15,6 @@ "source_sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }, "byte_length": { "type": "integer", "minimum": 0 }, "lifecycle": { "enum": ["draft", "stable", "deprecated", "experimental", "generated"] }, - "domain": { "enum": ["layout", "motion", "design-engineering", "game-ui", "platform-guides", "shared"] } + "domain": { "enum": ["layout", "motion", "design-engineering", "game-ui", "platform-guides", "design-terminology", "shared"] } } } diff --git a/consumer-reference/policies/lifecycle-a2a-extension.json b/consumer-reference/policies/lifecycle-a2a-extension.json index c2e334a..c173f65 100644 --- a/consumer-reference/policies/lifecycle-a2a-extension.json +++ b/consumer-reference/policies/lifecycle-a2a-extension.json @@ -94,8 +94,8 @@ "scripts/test-lifecycle-disposition.mjs", "scripts/validate-lifecycle-disposition.mjs" ], - "scanned_file_count": 404, - "scanned_paths_content_id": "sha256:f703200abad74add6fa9be06d1a6cc767726113cdd5ac4b92e6dadc9c354cee0" + "scanned_file_count": 434, + "scanned_paths_content_id": "sha256:367fba8ff91535f0d13ea9e95bb5b53d17874cda8c48bf5fa62b22d28d1d92b6" }, "implementation": { "path": "scripts/agent-native/v2/extensions/a2a-projection.mjs", @@ -113,12 +113,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 157 + "end": 168 }, - "file_sha256": "959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", - "content_id": "sha256:959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", + "file_sha256": "6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", + "content_id": "sha256:6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", "reference_lines": [ - 130 + 141 ], "reference_kinds": [ "documentation_reference" @@ -145,13 +145,13 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 253 + "end": 274 }, - "file_sha256": "55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", - "content_id": "sha256:55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", + "file_sha256": "73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", + "content_id": "sha256:73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", "reference_lines": [ - 170, - 186 + 191, + 207 ], "reference_kinds": [ "forwarder_path", @@ -262,12 +262,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 129 + "end": 142 }, - "file_sha256": "567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", - "content_id": "sha256:567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", + "file_sha256": "4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", + "content_id": "sha256:4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", "reference_lines": [ - 77 + 86 ], "reference_kinds": [ "forwarder_path", @@ -279,12 +279,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 209 + "end": 256 }, - "file_sha256": "897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", - "content_id": "sha256:897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", + "file_sha256": "92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", + "content_id": "sha256:92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", "reference_lines": [ - 48 + 53 ], "reference_kinds": [ "forwarder_path", @@ -379,20 +379,20 @@ "role": "projection_adapter_conformance_test", "lines": { "start": 1, - "end": 129 + "end": 142 }, - "file_sha256": "567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", - "content_id": "sha256:567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982" + "file_sha256": "4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", + "content_id": "sha256:4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27" }, { "path": "scripts/agent-native/v2/test-sg-material-package.mjs", "role": "projection_adapter_conformance_test", "lines": { "start": 1, - "end": 209 + "end": 256 }, - "file_sha256": "897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", - "content_id": "sha256:897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c" + "file_sha256": "92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", + "content_id": "sha256:92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af" } ], "docs_and_registry": [ @@ -401,10 +401,10 @@ "role": "documentation", "lines": { "start": 1, - "end": 157 + "end": 168 }, - "file_sha256": "959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", - "content_id": "sha256:959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e" + "file_sha256": "6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", + "content_id": "sha256:6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e" }, { "path": "consumer-reference/agent-native/registry.json", @@ -432,10 +432,10 @@ "role": "installed_package_exposure", "lines": { "start": 1, - "end": 253 + "end": 274 }, - "file_sha256": "55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", - "content_id": "sha256:55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca" + "file_sha256": "73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", + "content_id": "sha256:73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d" }, "forwarding": { "path": "scripts/agent-native/a2a-projection.mjs", diff --git a/consumer-reference/policies/lifecycle-ag-ui-extension.json b/consumer-reference/policies/lifecycle-ag-ui-extension.json index e57256b..53684cf 100644 --- a/consumer-reference/policies/lifecycle-ag-ui-extension.json +++ b/consumer-reference/policies/lifecycle-ag-ui-extension.json @@ -94,8 +94,8 @@ "scripts/test-lifecycle-disposition.mjs", "scripts/validate-lifecycle-disposition.mjs" ], - "scanned_file_count": 404, - "scanned_paths_content_id": "sha256:f703200abad74add6fa9be06d1a6cc767726113cdd5ac4b92e6dadc9c354cee0" + "scanned_file_count": 434, + "scanned_paths_content_id": "sha256:367fba8ff91535f0d13ea9e95bb5b53d17874cda8c48bf5fa62b22d28d1d92b6" }, "implementation": { "path": "scripts/agent-native/v2/extensions/agui-projection.mjs", @@ -113,12 +113,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 165 + "end": 166 }, - "file_sha256": "67571ee3b85430f17999189a52fc3ed871aab135e7e5127f63ee57b2ce11cd19", - "content_id": "sha256:67571ee3b85430f17999189a52fc3ed871aab135e7e5127f63ee57b2ce11cd19", + "file_sha256": "fb201d32ede32e5f6d6fd27e5cfb0d4c8f9fa616f7d7807872990359a7562595", + "content_id": "sha256:fb201d32ede32e5f6d6fd27e5cfb0d4c8f9fa616f7d7807872990359a7562595", "reference_lines": [ - 21 + 22 ], "reference_kinds": [ "documentation_reference" @@ -129,14 +129,14 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 223 + "end": 231 }, - "file_sha256": "b892e0df464b0527b50b201830db7ab87507069862281e7781ad1eecb56f77b7", - "content_id": "sha256:b892e0df464b0527b50b201830db7ab87507069862281e7781ad1eecb56f77b7", + "file_sha256": "e5548696eb312be4f64c819c738f4c1116fad774e28b9aac4b44ac993ffb2526", + "content_id": "sha256:e5548696eb312be4f64c819c738f4c1116fad774e28b9aac4b44ac993ffb2526", "reference_lines": [ 28, - 82, - 84 + 89, + 91 ], "reference_kinds": [ "documentation_reference" @@ -147,16 +147,16 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 157 + "end": 168 }, - "file_sha256": "959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", - "content_id": "sha256:959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", + "file_sha256": "6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", + "content_id": "sha256:6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", "reference_lines": [ 25, - 128, - 131, - 132, - 144 + 139, + 142, + 143, + 155 ], "reference_kinds": [ "documentation_reference" @@ -183,12 +183,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 57 + "end": 80 }, - "file_sha256": "ebbaf9b22d6924714a1bb6069bab4622ffe9fd0aad76c6cf718cd76cff7b2eb9", - "content_id": "sha256:ebbaf9b22d6924714a1bb6069bab4622ffe9fd0aad76c6cf718cd76cff7b2eb9", + "file_sha256": "524b2225be95f0408e4842b146755d36b09dc01527312fa0b12b8a6e95032fac", + "content_id": "sha256:524b2225be95f0408e4842b146755d36b09dc01527312fa0b12b8a6e95032fac", "reference_lines": [ - 13 + 36 ], "reference_kinds": [ "documentation_reference" @@ -199,13 +199,13 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 253 + "end": 274 }, - "file_sha256": "55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", - "content_id": "sha256:55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", + "file_sha256": "73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", + "content_id": "sha256:73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", "reference_lines": [ - 171, - 187 + 192, + 208 ], "reference_kinds": [ "forwarder_path", @@ -306,12 +306,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 129 + "end": 142 }, - "file_sha256": "567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", - "content_id": "sha256:567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", + "file_sha256": "4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", + "content_id": "sha256:4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", "reference_lines": [ - 78 + 87 ], "reference_kinds": [ "forwarder_path", @@ -323,12 +323,12 @@ "role": "repository_reference", "lines": { "start": 1, - "end": 209 + "end": 256 }, - "file_sha256": "897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", - "content_id": "sha256:897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", + "file_sha256": "92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", + "content_id": "sha256:92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", "reference_lines": [ - 49 + 54 ], "reference_kinds": [ "forwarder_path", @@ -422,20 +422,20 @@ "role": "projection_adapter_conformance_test", "lines": { "start": 1, - "end": 129 + "end": 142 }, - "file_sha256": "567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982", - "content_id": "sha256:567a55b72d1133fba49f81d3e2ece3352e7687a0081cbf0a80803005b7a7e982" + "file_sha256": "4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27", + "content_id": "sha256:4d589470e789d637a7f690c24e4ae6eab2ca3cf785fa1b2f85859dea5dcf1d27" }, { "path": "scripts/agent-native/v2/test-sg-material-package.mjs", "role": "projection_adapter_conformance_test", "lines": { "start": 1, - "end": 209 + "end": 256 }, - "file_sha256": "897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c", - "content_id": "sha256:897b2d4ea14dc8ab3b06b5a0a2bbf4aa22f3e9e33b2602bd82ca46ea5405033c" + "file_sha256": "92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af", + "content_id": "sha256:92cc9cb0913cd86d23fc46de6e7989d01cc2a56ece7610ba1baf8bc75f2124af" } ], "docs_and_registry": [ @@ -444,10 +444,10 @@ "role": "documentation", "lines": { "start": 1, - "end": 157 + "end": 168 }, - "file_sha256": "959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", - "content_id": "sha256:959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e" + "file_sha256": "6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", + "content_id": "sha256:6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e" }, { "path": "consumer-reference/agent-native/registry.json", @@ -475,10 +475,10 @@ "role": "installed_package_exposure", "lines": { "start": 1, - "end": 253 + "end": 274 }, - "file_sha256": "55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca", - "content_id": "sha256:55a7787aa01b8d954782a24efd1df197231c67b776312fde861046aedafa9bca" + "file_sha256": "73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d", + "content_id": "sha256:73fa498c2ae3fe0f4e5665cc46e75fee3f89d8a82fc97613236f359e57a23d7d" }, "forwarding": { "path": "scripts/agent-native/agui-projection.mjs", diff --git a/consumer-reference/policies/lifecycle-page-evidence-adoption.json b/consumer-reference/policies/lifecycle-page-evidence-adoption.json index a03a483..c696956 100644 --- a/consumer-reference/policies/lifecycle-page-evidence-adoption.json +++ b/consumer-reference/policies/lifecycle-page-evidence-adoption.json @@ -39,8 +39,8 @@ "workflow": { "path": ".github/workflows/validate.yml", "mode": "100644", - "active_sha256": "846417a45a462a51ba28028621ff9fe82cf018be15b8a433a661d7d0d7af3017", - "retired_sha256": "e68fe15654d5830d918e8adfda4b8dcedcb0340b286d6e42058831c1d1c44f58", + "active_sha256": "b7aac452ac49ec1bc287ef3d75efe3806895eb147172b106634394f413a520fc", + "retired_sha256": "5f709d829e5008b9a0b101ac519454a64cb938b40b0c03cf645ee1d779e8038b", "job_id": "consumer-page-evidence", "job_name": "Consumer page-evidence raster capture (nonblocking)", "job_sha256": "11d0fe7ea2880c5d32d32bb419493600afdfd221aef728f3c0e36e22cf52b116", @@ -163,7 +163,7 @@ { "path": "quality/evidence/executable-evidence.md", "mode": "100644", - "sha256": "a0ae7f2c355ab26293cdb9e96b31d91d50a024ed404aa0c8297a65b91af73a33", + "sha256": "fb441412dabc0b57aeac8355f92321a9873aa67612e489e3137953d7680312b1", "role": "archive_and_retrieval_documentation" }, { diff --git a/consumer-reference/policies/lifecycle-sentinel-calibration.json b/consumer-reference/policies/lifecycle-sentinel-calibration.json index 8ac1ef8..0c29580 100644 --- a/consumer-reference/policies/lifecycle-sentinel-calibration.json +++ b/consumer-reference/policies/lifecycle-sentinel-calibration.json @@ -53,8 +53,8 @@ "workflow": { "path": ".github/workflows/validate.yml", "mode": "100644", - "active_sha256": "846417a45a462a51ba28028621ff9fe82cf018be15b8a433a661d7d0d7af3017", - "retired_sha256": "421c63222db3dfb5af03630c437a4b8b0f755a6146abec4e5d213eb2b0369620", + "active_sha256": "b7aac452ac49ec1bc287ef3d75efe3806895eb147172b106634394f413a520fc", + "retired_sha256": "e1d2cc248efdad81267326fdf2706335a7d4e6f4e271f05a37904102313b347b", "job_id": "chromium-calibration", "job_name": "Chromium 20-run calibration (nonblocking)", "job_sha256": "86228e7fb44c2ba5d0abe160d6bd3c4f5228e7c1ec40189b3b4f528acfd45e62", diff --git a/design-engineering/component-contract.md b/design-engineering/component-contract.md new file mode 100644 index 0000000..9591f39 --- /dev/null +++ b/design-engineering/component-contract.md @@ -0,0 +1,98 @@ +--- +type: Domain Guide +title: Component Contract +description: Define product component semantics, states, events, asynchronous ownership, and verification before visual treatment. +domain: design-engineering +lifecycle: experimental +provenance_kind: local +--- + +# Component Contract + +Primary role: product component implementation handoff. + +## Repository Boundary + +This contract describes consumer-owned behavior. It does not create a shared component library, new Layout primitive, or default visual values. Existing profile records have their own closed schema; this planning template cannot substitute for their evidence records. + +## Reusable Method + +Start with semantic HTML or the platform's native control. Name the public inputs, emitted events, internal state, and owner of persisted data. Then describe each transition and its observable outcome. Use the [Worked Examples](worked-examples.md) to check common failure paths. + +## Contract Template + +| Field | Required answer | +| --- | --- | +| Task | The user action and the outcome the component supports | +| Semantics | Element/control, accessible name, description, value, relationships | +| Inputs | Data and callbacks, required/optional values, identity and revision | +| Outputs | Events, payload meaning, when they are emitted, who commits the result | +| State | Initial, active, selected, disabled, pending, empty, error, completed as applicable | +| State ownership | Controlled inputs versus internal temporary state; reconciliation rule | +| Input and focus | Keyboard, pointer, touch, focus entry/return and unavailable actions | +| Async ownership | Request identity, duplicate action policy, stale result handling, cancellation | +| Content | Empty, long, localized, unbroken and unavailable data | +| Spatial composition | Layout source, parent constraints, scroll owner and overflow behavior | +| Presentation | Product-owned values, density, visual hierarchy and optional motion brief | +| Lifecycle | Creation, navigation, rerender, removal, event/listener cleanup | +| Evidence | Expected behavior, actual result, runtime, source revision and artifacts | +| Handoff | `consumer_reference` record or `not_applicable` with a reason | + +## Worked Contract: Save Action + +Task: persist the current editable document. The form owns the draft; the save operation owns a submitted snapshot; the server owns the persisted result. A success for snapshot A must not mark newer draft B as saved. + +| Current state | Event | Next state | Required effect | +| --- | --- | --- | --- | +| Clean | Edit | Dirty | Keep entered values; mark unsaved changes | +| Dirty | Submit valid draft A | Saving A | Capture A and a request identity; acknowledge pending | +| Saving A | Submit again | Saving A | Apply the declared duplicate policy; this example ignores the duplicate | +| Saving A | Edit to B | Saving A with dirty B | Preserve B and distinguish it from submitted A | +| Saving A | Matching success | Clean if draft still A; otherwise dirty B | Record persisted A without discarding B | +| Saving A | Matching failure | Dirty current draft with error | Keep values and offer retry | +| Any | Stale response | Unchanged | Ignore responses outside the active operation | +| Any | Unmount/navigation | Disposed | Stop UI updates; cancellation does not imply the server rolled back | + +Implementation sketch, independent of framework: + +```text +on submit: + if a request is active: return + validate the current draft + copy the draft into submittedSnapshot + create requestIdentity + start persistence(requestIdentity, submittedSnapshot) +on result(identity, result): + if disposed or identity is not active: return + clear the active request + if successful: set persistedSnapshot to submittedSnapshot + else: expose a recoverable error + derive dirty state by comparing current draft with persistedSnapshot +``` + +A real application also defines revision conflicts, server normalization, and retry semantics. The sketch is not a distributed consistency protocol. Its handoff is `consumer_reference: not_applicable` because this fictional example selects no consumer profile or conformance record. + +## Opinionated Guidance + +Use state names that expose meaningful differences. Two booleans can accidentally permit “saved and failed”; a state transition table helps reveal impossible combinations. Do not merge input validity, request state, and persisted revision into one visual status. + +## Platform-Specific Guidance + +For web forms, preserve native label and form relationships. Validate custom semantics against the applicable [accessibility evidence gate](../quality/gates/accessibility-evidence.md). Framework scheduling, request abort behavior, and server idempotency require separate implementation evidence. + +## Unsupported Absolutes + +A state table does not prove accessibility, successful persistence, race freedom, or device coverage. Cancelling a client request does not prove its remote side effects stopped. + +## Verification Contract + +Resolve responses out of order, edit during saving, fail then retry, activate repeatedly, and remove the component before completion. Inspect both persisted and displayed values. Include keyboard-only operation, long content, and constrained parents. Record actual outcomes; the table above is an unexecuted reference contract. Review when a public input, event, or state meaning changes. + +## Source, License, And Attribution + +Locally authored contract and pseudocode; no framework or upstream implementation is copied. Shared quality gates own evidence admissibility. + +## IA Navigation + +Parent: [Design Engineering](index.md). +Next: [Design Engineering Worked Examples](worked-examples.md). diff --git a/design-engineering/decision-tree.md b/design-engineering/decision-tree.md new file mode 100644 index 0000000..812ade7 --- /dev/null +++ b/design-engineering/decision-tree.md @@ -0,0 +1,69 @@ +--- +type: Domain Guide +title: Design Engineering Decision Tree +description: Route product craft work from the uncertain decision to a contract, example, and appropriate evidence. +domain: design-engineering +lifecycle: experimental +provenance_kind: local +--- + +# Design Engineering Decision Tree + +Primary role: product implementation planning route. + +## Repository Boundary + +This route turns a product request into a bounded implementation decision. It owns neither shared quality policy nor a default design system. Use the existing Layout corpus for geometry and Motion for temporal behavior. + +## Reusable Method + +1. Write the user's action and the expected result in one sentence. +2. Identify what is uncertain: content, structure, state, identity, platform behavior, or perception. +3. Select the route below and produce its named artifact. +4. Implement the smallest slice containing the risky state, including failure and recovery. +5. Verify the observable and record the remaining limitation using [Interface Craft Decisions](interface-craft.md). + +## Task Routes + +| Uncertain decision | Primary route | Artifact to produce | +| --- | --- | --- | +| What should this screen contain? | [Webpage Generation Workflow](../guides/webpage-generation-workflow.md) | Content inventory and task model | +| What owns size, flow, and scroll? | [Layout Planning Guide](../GUIDE.md) | Layout brief and pattern composition | +| What happens after activation or failure? | [Component Contract](component-contract.md) | State, event, focus, and asynchronous ownership tables | +| How should a form, search, or destructive action recover? | [Worked Examples](worked-examples.md) | Scenario-specific acceptance cases | +| Does a product detail serve the task? | [Interface Craft Decisions](interface-craft.md) | Claim with an observable and evidence boundary | +| How do distinct identities use one Layout contract? | [Reference Profiles](reference-profiles/index.md) | Explicit profile selection and value ownership | +| Will an existing consumer survive migration? | [Consumer Migration Readiness](consumer-migration-readiness.md) | Thirteen-dimension consumer-owned conformance record | +| What should move and why? | [Motion Decision Tree](../motion/decision-tree.md) | Motion brief with interruption policy | +| Is a platform convention transferable? | [Platform Adaptation Workflow](../platform-guides/adaptation-workflow.md) | Native fact, web mapping, fallback, and runtime matrix | + +## Worked Intake + +Request: “Make saving settings feel responsive.” The risky decision is whether acknowledgement means persistence. Begin with a component contract: clean, dirty, saving, saved, and failed. A saving label acknowledges submission; the saved state waits for the persistence response. Preserve unsaved edits when requests fail. Only then evaluate a completion treatment through Motion. This order exposes duplicate writes and lost edits before visual review. + +An acceptance statement can be: “A failed save leaves the entered values available for retry.” “Feels responsive” remains a human perception hypothesis until measured in the relevant task. + +## Opinionated Guidance + +Prototype the uncertain state rather than an entire polished screen. A good first slice includes the initiating action, its failure, and a recovery path. Add complexity when it resolves an observed limitation. + +## Platform-Specific Guidance + +Distinguish browser, OS, assistive technology, framework, and component library versions in evidence. A library's state name is an implementation detail, not the user's task definition. + +## Unsupported Absolutes + +No selected framework, profile, token set, or prototype proves product quality. Component completion does not demonstrate migration readiness for an entire consumer. + +## Verification Contract + +The route succeeds when a reviewer can find the decision owner, artifact, failure case, and evidence needed without guessing. Verify one ordinary, one exceptional, and one interrupted task. Revisit when a route sends the reader to the wrong domain or cannot produce a testable acceptance statement. + +## Source, License, And Attribution + +Locally authored routing and settings example. Linked repository documents remain authoritative for their own contracts. + +## IA Navigation + +Parent: [Design Engineering](index.md). +Next: [Component Contract](component-contract.md). diff --git a/design-engineering/index.md b/design-engineering/index.md index a1e115c..5b94e4d 100644 --- a/design-engineering/index.md +++ b/design-engineering/index.md @@ -8,6 +8,16 @@ In scope: purpose, frequency, interaction detail, implementation review, prototy Out of scope: a second universal principle set, unsupported claims of beauty or adoption, and overrides of semantic, accessibility, Layout, or shared quality contracts. +## Start Here + +| Task | Route | +| --- | --- | +| Route the uncertain product decision. | [Design Engineering Decision Tree](decision-tree.md) | +| Specify semantics, state, requests, and focus. | [Component Contract](component-contract.md) | +| Apply settings, search, and destructive-action contracts. | [Design Engineering Worked Examples](worked-examples.md) | + +These workflows and worked cases are usable experimental guidance. Expected-result tables are test designs; actual product, engine, and reader evidence must be recorded separately. Review on a failed task, a source change, or a changed ownership contract. + ## Documents - [Interface Craft Decisions](interface-craft.md) connects product purpose, implementation detail, and verification without treating taste as proof. @@ -25,4 +35,4 @@ See [StyleGallery Domains](../DOMAINS.md) for lifecycle, provenance, page member ## IA Navigation Parent: [StyleGallery](../index.md). -Next: [Consumer Migration Readiness](consumer-migration-readiness.md). +Next: [Design Engineering Decision Tree](decision-tree.md). diff --git a/design-engineering/worked-examples.md b/design-engineering/worked-examples.md new file mode 100644 index 0000000..e763c61 --- /dev/null +++ b/design-engineering/worked-examples.md @@ -0,0 +1,105 @@ +--- +type: Domain Guide +title: Design Engineering Worked Examples +description: Apply component contracts to settings, asynchronous search, and destructive list actions with explicit recovery cases. +domain: design-engineering +lifecycle: experimental +provenance_kind: local +--- + +# Design Engineering Worked Examples + +Primary role: product interaction recipe collection. + +## Repository Boundary + +These fictional examples connect decisions to expected behavior. They are neither shipped components nor captured product evidence. Values and presentation belong to the consumer; the referenced Layout recipes retain their spatial boundaries. + +The separate [Interaction Lab](../examples/domain-interactions/README.md) implements the save and search contracts as a local web prototype. Its [browser observations](../examples/domain-interactions/verification.md) apply to that exact example and source snapshot; they do not prove a consumer backend or the destructive-action recipe below. + +## Reusable Method + +Choose a matching user task, adapt its state ownership through the [Component Contract](component-contract.md), and execute the listed failure cases in the consuming application. The decision is incomplete until expected and actual results are recorded separately. + +## Settings With Explicit Save + +Task: edit preferences, inspect changes, and save intentionally. Compose the [SaaS Settings recipe](../recipes/saas-settings.md); let its selected patterns own page structure and scrolling. The form owns the editable draft, the operation owns the submitted snapshot, and persistence determines success. + +Keep field errors beside their inputs and provide a route to the first relevant error. On network failure, retain all entered values. A successful save of an older snapshot must leave subsequent edits dirty. If leaving the screen can lose changes, define discard/cancel/save behavior and what happens if saving fails. + +| Test | Expected behavior | +| --- | --- | +| Submit missing required input | Expose the error and retain other values | +| Submit, edit again, then receive success | Confirm the submitted snapshot; preserve later edits | +| Fail and retry | Keep the draft; issue the retry under the declared request policy | +| Cancel navigation with dirty data | Stay on the form with the same draft and a usable focus target | + +Evidence still needed: keyboard/error announcement, persistence responses, and source-bound runtime capture. A prototype cannot prove real data was saved. + +## Search With Detail Selection + +Task: search a collection and inspect an item without losing the search context. Compose [List Detail](../recipes/list-detail.md). Separate query text, submitted query, active request, results, and selected item identity. Displayed detail must name the selected item even when the result set refreshes. + +Keep typing responsive; a request for an older query cannot replace a newer result. Distinguish “no results” from loading and failure. On a tight surface, preserve selection and query when navigating between list and detail. If the selected item disappears, choose a documented empty detail or next-item policy instead of silently showing stale data. + +| Test | Expected behavior | +| --- | --- | +| Submit A, then B; resolve B before A | Results remain for B after A arrives | +| Receive zero results | Show the submitted query and a recovery action | +| Resize with detail selected | Preserve selection and query; keep focus on a logical available target | +| Remove the selected item remotely | Explain its unavailability or choose the documented next target | + +Evidence still needed: out-of-order response trace, selection identity, tight/wide rendered states, and input coverage. Motion is optional; use [Reorder and Filter](../motion/interaction-recipes.md#reorder-and-filter) only when it communicates stable identity. + +## Destructive Action In A List + +Task: remove a selected item with understandable consequences. Separate the initiating control, decision surface, pending operation, and final list update. Choose confirmation or undo from actual reversibility and product requirements. Do not offer undo when the backend cannot restore the item. + +Name the affected item and scope. During pending deletion, prevent unintended duplicate operations according to the contract. Failure preserves the item and a recovery path. On success, return focus to an appropriate neighboring item or list heading if the invoker was removed. A dialog's visual exit must not leave a blocker behind. + +| Test | Expected behavior | +| --- | --- | +| Cancel confirmation | No deletion; return to the invoker | +| Fail the operation | Explain failure and preserve the item | +| Succeed while filters change | Remove by stable identity, not old row position | +| Remove the final item | Present an empty state and a logical focus destination | + +Evidence still needed: actual operation result, focus trace, dialog semantics, and recovery behavior. Use [Modal Transition](../motion/interaction-recipes.md#modal-transition) only for optional presentation. + +## Implementation Handoff + +```yaml +example: # settings-save, search-detail, or destructive-list-action +consumer_reference: not_applicable +consumer_reference_reason: These fictional examples select no consumer-owned profile or evidence record. +layout_source: # the selected recipe and the consumer's pinned revision +state_owner: # component, screen, and persistence responsibilities +acceptance_cases: # adapted rows above +observed_results: not_run +remaining_evidence: # actual runtime, input, device, and user evidence +``` + +## Opinionated Guidance + +Preserve the user's work across recoverable failures. Status text should explain the real operation; motion and color alone are insufficient descriptions of what happened. + +## Platform-Specific Guidance + +Native navigation, browser history, component libraries, and platform controls differ. Record the exact implementation of cancellation and focus return rather than copying a screenshot's apparent behavior. + +## Unsupported Absolutes + +Confirmation is not always safer than undo. Optimistic updates are not always appropriate. A worked example does not certify a consumer migration or establish universal usability. + +## Verification Contract + +Execute all adapted acceptance rows plus long text, empty content, relevant constraints and preferences, and every claimed input method. For a migration use the larger [Migration Readiness](consumer-migration-readiness.md) contract. Review these examples when an observed failure lacks an owner or recovery action. + +## Source, License, And Attribution + +Locally authored scenarios and expected-result tables. Repository links provide spatial and evidence contracts, not proof that these scenarios have run. + +## IA Navigation + +Parent: [Design Engineering](index.md). +Next: [Interface Craft Decisions](interface-craft.md). diff --git a/design-terminology/comparison-workflow.md b/design-terminology/comparison-workflow.md new file mode 100644 index 0000000..b9904bc --- /dev/null +++ b/design-terminology/comparison-workflow.md @@ -0,0 +1,98 @@ +--- +type: Domain Guide +title: Design Term Comparison Workflow +description: Resolve source-specific terminology questions with a scoped relation, explicit uncertainty, and a reusable handoff. +domain: design-terminology +lifecycle: experimental +provenance_kind: local +--- + +# Design Term Comparison Workflow + +Primary role: terminology lookup, authoring, and handoff route. + +## Repository Boundary + +This workflow answers what two named sources mean and how those meanings relate. Internal naming still belongs to [Controlled Vocabulary](../guides/vocabulary.md). Implementation behavior belongs to its owning domain. Document retrieval does not execute a structured terminology query. + +## Reusable Method + +1. Capture the exact question, both labels, intended audience, and comparison scope. +2. Identify each named source and [source kind](source-kinds.md). If either source is missing, report insufficient context. +3. Check [Recorded Sources](source-vocabularies.md) and open the direct term locators in [Term Cases](conflict-cases.md). +4. Record each label, concept, status, and version independently. Classify through [Concept Families](concept-families.md). +5. Select a [relation type](relation-types.md), direction, and non-trivial boundary. A composed-of relationship is not automatically subtyping. +6. Return the scoped result, term IDs, source recheck status, and a counterexample or missing observation. +7. For a new record, update the source inventory and term/relation tables, then run their validator and fixtures. + +## Decision Table + +| Situation | Result to produce | +| --- | --- | +| Identical labels, distinct meanings in two named sources | `same_label_different_meaning`, both meanings and the confusion risk | +| Shared region but source-specific features on both sides | `partial_overlap`, intersection and each side's difference | +| One form stores or consumes another concept | `implementation_representation`, representation first and the loss/addition boundary | +| Genuine set inclusion with a counterexample | `broader_than` or `narrower_than`, explicit direction | +| Meaning overlaps across versions or systems | `near_equivalent`, declared symmetry and the divergence axis | +| One source records a dated label replacement | `renamed_to`, same source and verifiable event | +| The proposed comparison uses incompatible axes | `not_comparable`, the axis mismatch | +| Source, scope, or meaning cannot be established | No relation recorded; say what evidence is missing | + +## Handoff Template + +```yaml +question: # the consumer's actual terminology question +term_ids: # exact identifiers from conflict-cases.md +relation_types: # closed types actually relied on +scope: # the recorded comparison scope +answer: # locally written scoped conclusion +boundary: # where substitution breaks +sources_rechecked: # date and source locators, or unverified +unknowns: # missing evidence, or none within the recorded scope +consumer_reference: not_applicable +consumer_reference_reason: This blank terminology template selects no consumer record. +``` + +## Worked Handoff + +Question: can a CSS custom property be called the same thing as an interchange token? + +Term identifiers: `css.custom-property`, `dtcg.token`. Relation type: `implementation_representation`, from the CSS representation to the token concept, in scope `token-to-css-output`. Answer: a custom property can consume a translated token value, but the runtime slot does not carry the full interchange record and can also store other values. Sources rechecked: the direct CSSWG and DTCG 2025.10 locators in [Term Cases](conflict-cases.md), 2026-09-08. Consumer reference: `not_applicable`, because this is a terminology explanation with no selected consumer record. + +This judgment does not prove any actual converter preserves aliases, types, or metadata. + +## Reader Verification Tasks + +| Task | Expected result | Failure signal | +| --- | --- | --- | +| Compare Figma and Carbon “Component” | Two source-specific records and `same_label_different_meaning` | One merged definition | +| Compare variable, token, and custom property | `partial_overlap` plus representation-first mapping | Equivalence or reversed representation direction | +| Compare the second DTCG draft with 2025.10 | Historical/current version scopes and no invented rename | Treating the draft as the current implementation contract | +| Compare “style guide” and “design system” without organizations | Insufficient context; request the two sources | Universal history or deprecation claim | + +These are expected lookup outcomes. A maintainer records actual reader task results and participant identity separately before claiming findability evidence. Reader tasks are not a domain lifecycle prerequisite. + +## Opinionated Guidance + +Resolve ambiguity explicitly; a qualified answer is more useful than an unsupported winner. Retain historical records with their own scopes when a current reading changes. + +## Platform-Specific Guidance + +Direct source authority is limited to its named platform, system, tool, or specification. A platform terminology comparison does not establish a target's support for the named feature. + +## Unsupported Absolutes + +Do not infer equivalence from an absent relation, source popularity, or shared spelling. A passing record validator cannot determine whether a semantic judgment is persuasive. + +## Verification Contract + +Verify table consistency mechanically and meaning against both sources. Run the reader tasks for an actual findability claim. Re-review when either source revises its term or a reader encounters an unresolved ambiguity. The [domain lifecycle review](index.md#promotion-to-stable) follows the repository-owner policy separately from reader evidence. + +## Source, License, And Attribution + +Locally authored workflow relying on the term identifiers and relation types declared above. Named sources were rechecked through the direct locators in Term Cases on 2026-09-08. No upstream definitional prose is reproduced. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Cross-System Term Cases](conflict-cases.md). diff --git a/design-terminology/concept-families.md b/design-terminology/concept-families.md new file mode 100644 index 0000000..a0bccab --- /dev/null +++ b/design-terminology/concept-families.md @@ -0,0 +1,78 @@ +--- +type: Domain Guide +title: Design Concept Families +description: Classification of design terms into foundation, interface-artifact, guidance, governance, consumption, and tooling-construct concept families. +domain: design-terminology +lifecycle: experimental +--- + +# Design Concept Families + +Primary role: design-term concept-family classification guide. + +## Repository Boundary + +This guide classifies design terms by the decision each term serves, as a property of the term's concept, independent of what kind of source uses it. A system's name for itself is not a concept family; see [Design Source Kinds](source-kinds.md). The families are review tools, not a universal ontology, and they never rename StyleGallery's own terms. + +## Reusable Method + +1. Capture the term inside its native source context with a named source. +2. Identify the underlying concept, then assign one primary concept family. +3. Record scope: whole system, one library, or a single artifact. +4. Record audience and medium: designer-facing, engineer-facing, or tool-layer. +5. Express relations to other terms only through the typed model in [Design Term Relations](relation-types.md). +6. Cite the named source and document surface; never generalize from one source's usage. + +## Concept Families + +| Family | Question it answers | Typical terms | +| --- | --- | --- | +| `foundation` | What are the smallest reusable inputs? | token, design token, variable, primitive, core, base | +| `interface-artifact` | What are the built interface units? | component, element, control, block, module, variant, state | +| `guidance` | How is intent communicated? | principle, guideline, heuristic, standard, specification, recipe | +| `governance` | How does the system change? | contribution, deprecation, versioning, adoption, migration, maturity | +| `consumption` | Who uses which form? | package, library, kit, theme, plugin, preset | +| `tooling-construct` | What does a tool's data model expose? | design-tool variable, mode, tool component, library file | + +`pattern` is recorded as `guidance` or `interface-artifact` depending on the cited source's own scope, never both at once. + +## Classification Cases + +| Case | Rule | Example | +| --- | --- | --- | +| Same term at different scope | Classify by the scope the source actually defines | `pattern` as workflow guidance in Carbon versus a spatial arrangement in a pattern library | +| Same term for different audiences | Record audience as a separate axis before comparing | `token` in design tooling versus in generated CSS | +| Era shift | Classify by current source usage; note the older meaning as history | `style guide` narrowed as `design system` broadened | +| Tool layer versus system layer | A tool construct is `tooling-construct`, not the system's term for the same concept | A tool's variables versus a system's published token format | +| Local override | A product may rename a family term locally; the family is shared, the authority is not | A product calling patterns `blocks` | + +## Opinionated Guidance + +- Classify the term as the named source uses it today, then compare through relations; never build one merged definition first. +- Keep family and scope separate: `component` stays `interface-artifact` whether it names a button or a page region. +- Prefer the narrowest scope the source supports; widen only with a second cited source. +- Treat missing terms as gaps in that source's vocabulary, not omissions to fill by inference. + +## Platform-Specific Guidance + +Record the named source, its kind, and the review date for every classification. Route platform convention comparison to [Platform Guides](../platform-guides/index.md), motion terms to Motion, and StyleGallery's own term decisions to the [Controlled Vocabulary](../guides/vocabulary.md). + +## Unsupported Absolutes + +- One source's family structure is not a universal taxonomy. +- A term's popularity does not establish its definition. +- A tool vendor's feature name does not define the industry term. +- Absence of a term in one source does not invalidate its use in another. + +## Verification Contract + +For every classified term, verify the named source still uses the term in the recorded family, scope, audience, and medium; re-check era-shifted terms against the current source; and confirm every cross-source claim carries a typed relation with a boundary. + +## Source, License, And Attribution + +This page is a locally authored, project-neutral proposed taxonomy. It cites named systems only as usage evidence and reproduces no upstream definitional prose. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Design Term Relations](relation-types.md). diff --git a/design-terminology/conflict-cases.md b/design-terminology/conflict-cases.md new file mode 100644 index 0000000..e1765c1 --- /dev/null +++ b/design-terminology/conflict-cases.md @@ -0,0 +1,109 @@ +--- +type: Domain Guide +title: Cross-System Term Cases +description: Directly sourced terms and scoped relations for tool values, runtime representations, components, patterns, and historical formats. +domain: design-terminology +lifecycle: experimental +--- + +# Cross-System Term Cases + +Primary role: applied cross-system term relation record. + +## Repository Boundary + +This page applies the typed relation model to recorded term records and conflict scenarios. It does not rename StyleGallery's own terms, and its relations are working judgments with boundaries, not claims that one source's definition is correct. V0.1 records these as Markdown; the structured registry is a promotion prerequisite. + +## Reusable Method + +1. Name the sources in tension and the shared term. +2. Record each side as a term record with source, kind, concept, status, and scope. +3. Assign one relation type per pair per explicit scope and declare its direction. +4. Write the non-equivalence boundary: where substitution breaks. +5. Stamp `reviewed_on`; re-verify when any involved source revises its term. + +## Term Records + +| Term | Label | Source (kind) | Concept | Status | Scope | Reviewed on | +| --- | --- | --- | --- | --- | --- | --- | +| `figma.variable` | Variable | [Figma](https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes) (`design-tool`) | named-design-value | current | variable collection; dated help page | 2026-09-08 | +| `figma.mode` | Mode | [Figma](https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes) (`design-tool`) | value-context | current | values selected within a collection | 2026-09-08 | +| `figma.collection` | Collection | [Figma](https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes) (`design-tool`) | variable-organization | current | collection containing variables and modes | 2026-09-08 | +| `figma.component` | Component | [Figma](https://help.figma.com/hc/en-us/articles/360038662654-Guide-to-components-in-Figma) (`design-tool`) | tool-instance-model | current | reusable design object and its instances | 2026-09-08 | +| `dtcg.token` | Token | [DTCG](https://www.w3.org/community/reports/design-tokens/CG-FINAL-format-20251028/#design-token) (`specification`) | interchange-record | current | Format Module 2025.10 | 2026-09-08 | +| `dtcg.group` | Group | [DTCG](https://www.w3.org/community/reports/design-tokens/CG-FINAL-format-20251028/#groups) (`specification`) | token-organization | current | Format Module 2025.10 | 2026-09-08 | +| `dtcg.token.draft2` | Token | [DTCG](https://www.designtokens.org/tr/second-editors-draft/format/#design-token) (`specification`) | interchange-record | historical | Second Editors' Draft, 2022-06-14 | 2026-09-08 | +| `css.custom-property` | Custom property | [CSSWG](https://www.w3.org/TR/css-variables-1/#defining-variables) (`web-platform`) | runtime-value-slot | current | CSS Custom Properties Level 1 | 2026-09-08 | +| `carbon.component` | Component | [Carbon](https://carbondesignsystem.com/all-about-carbon/what-is-carbon/) (`design-system`) | published-ui-building-block | current | Carbon design and implementation resources | 2026-09-08 | +| `carbon.pattern` | Pattern | [Carbon](https://carbondesignsystem.com/patterns/overview/) (`design-system`) | workflow-guidance | current | Carbon patterns catalog | 2026-09-08 | +| `stylegallery.pattern` | Pattern | [StyleGallery](../layout/index.md) (`pattern-library`) | spatial-primitive | current | repository Layout corpus | 2026-09-08 | + +The external locators and local Layout contract were rechecked on the dates shown. Current status is bounded by the named source/version, not a promise about every later release. Concept labels are local classification summaries. + +## Recorded Relations + +| From | To | Type | Scope | Direction | Boundary | Reviewed on | +| --- | --- | --- | --- | --- | --- | --- | +| `figma.variable` | `dtcg.token` | `partial_overlap` | value-interchange | symmetric | Exportable design values overlap; Figma prototype values need not be tokens, while the format has composite structures not supplied by one scalar variable | 2026-09-08 | +| `css.custom-property` | `dtcg.token` | `implementation_representation` | token-to-css-output | directional | A custom property can consume a translated token value; it also holds non-design values and does not preserve the entire token record | 2026-09-08 | +| `figma.collection` | `dtcg.group` | `partial_overlap` | value-organization | symmetric | Both organize named values; a Figma collection includes modes, while a format group can nest groups and carry format-specific metadata | 2026-09-08 | +| `figma.mode` | `dtcg.group` | `not_comparable` | context-versus-containment | symmetric | A mode selects value context; a group organizes token records. Containment alone does not choose the active context | 2026-09-08 | +| `figma.component` | `carbon.component` | `same_label_different_meaning` | handoff-artifact-identity | symmetric | A reusable tool object and a system-published UI unit share a label; a design instance is not by itself the system's implementation contract | 2026-09-08 | +| `carbon.pattern` | `stylegallery.pattern` | `partial_overlap` | reusable-interface-guidance | symmetric | Both describe reusable interface arrangements; Carbon includes task sequences and flows, while StyleGallery Layout covers spatial constraints without those interaction contracts | 2026-09-08 | +| `carbon.component` | `carbon.pattern` | `not_comparable` | catalog-unit-subtyping | symmetric | Composition is not set containment: a workflow can use components without being a broader class whose instances include component instances | 2026-09-08 | +| `dtcg.token.draft2` | `dtcg.token` | `near_equivalent` | versioned-token-concept | symmetric | The named-value interchange concept overlaps; the 2022 draft and 2025.10 format have different conformance details, so historical files need version-specific validation | 2026-09-08 | + +## Scenario A: Component Versus Pattern + +Query phrasing: `component versus pattern terminology`, `difference between component and pattern across design systems`. + +Distinguish Figma's design object from Carbon's published component before comparing either with a pattern. `figma.component` and `carbon.component` use `same_label_different_meaning`. Within Carbon, components participate in patterns; composition does not establish the set-theoretic `broader_than` relation. Carbon and StyleGallery patterns have `partial_overlap` within reusable interface guidance, with different behavioral boundaries. + +## Scenario B: Variable, Design Token, And CSS Custom Property + +Query phrasing: `figma variable design token custom property`. + +These are different labels from three source kinds. Their relation is not the same-label case. `figma.variable` and `dtcg.token` have `partial_overlap`; `css.custom-property` → `dtcg.token` is `implementation_representation`, with the representation first. A tool-to-code binding requires a consumer-owned translation; it does not establish equivalence or guarantee a lossless round trip. + +## Scenario C: Historical And Current Token Formats + +Query phrasing: `historical design token format`, `DTCG second editors draft versus 2025.10`. + +The retained 2022 source describes a historical draft. The versioned 2025.10 source describes an intended-for-implementation format. Both remain records; a common label does not make their file contracts identical. The relation is `near_equivalent` for the concept, not `renamed_to`: the label did not change. Neither Community Group report is a W3C Recommendation. + +## Scenario D: Style Guide Versus Design System + +Query phrasing: `style guide versus design system`. + +Result: insufficient context until an organization and dated source are named on both sides. “Industry history” cannot stand in for a specific historical style guide. Do not create a universal rename or deprecation event; request the two sources and then use the [Comparison Workflow](comparison-workflow.md). + +## Opinionated Guidance + +- Resolve a conflict only after naming every source involved; silent resolution creates the next conflict. +- Prefer surface-prefixed translations over merged definitions when handing off. +- StyleGallery's own [Controlled Vocabulary](../guides/vocabulary.md) stays authoritative inside this repository. +- Add a case only with at least two named, cited sources in genuine tension. + +## Platform-Specific Guidance + +When a case involves a platform guideline source, cite that platform's surface and route deeper convention comparison to [Platform Guides](../platform-guides/index.md); engine terms route to Game UI; motion terms to Motion. + +## Unsupported Absolutes + +- A working relation is not a standard. +- One source's revision does not obligate others to follow. +- A recorded case does not close the conflict outside its boundary. +- Tool feature names do not settle system-layer definitions. + +## Verification Contract + +Run `node scripts/validate-design-terminology.mjs --json` and its fixtures after editing. Verify both direct source locators, the comparison scope, direction, and boundary. The validator checks record shape and graph invariants; semantic accuracy still requires source review. Re-review when a named source changes the cited meaning. + +## Source, License, And Attribution + +Locally authored summaries and judgments, with direct source links per term. Rechecked 2026-09-08: Figma variables/components, DTCG 2025.10 and second draft, CSS Custom Properties Level 1, Carbon system/pattern pages, and the local Layout hub. No source prose or code samples are copied. This is an author source review, not independent semantic approval. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Design Term Comparison Workflow](comparison-workflow.md). diff --git a/design-terminology/index.md b/design-terminology/index.md new file mode 100644 index 0000000..73d5b2d --- /dev/null +++ b/design-terminology/index.md @@ -0,0 +1,73 @@ +# Design Terminology + +Design Terminology owns the decision surface that binds design terms to their named sources, classifies them by source kind and concept family, and judges typed semantic relations and conflicts between them. + +## Scope Boundary + +In scope: source-kind classification for named vocabulary sources, concept-family classification for design terms, a typed relation model between terms from different sources, source-bounded vocabulary inventories with freshness fields, and cross-system conflict cases. + +Out of scope: StyleGallery's own canonical naming, actual UI behavior or implementation methods, accessibility rules, platform-specific interaction adaptation, universal prescriptions about which term is generally better, and authority over any external vocabulary. + +This domain decides: which source a term belongs to, what kind of source that is, which concept family the term serves, and what typed relation holds between two terms with its boundary. It does not decide what StyleGallery calls things internally, whether an implementation is correct, or which external definition wins. + +## Evidence And Research Boundary + +V0.1 is a Markdown-only browsing and verification stage. Term records and typed relations are authored and reviewed as Markdown tables in [Cross-System Term Cases](conflict-cases.md); a machine-readable term, concept, source, and relation registry is a prerequisite for promotion beyond `experimental`. Material v2 currently exposes these pages through document search only; it does not answer structured crosswalk queries. + +Representative questions this domain answers: are Figma's variable, the DTCG design token, and the CSS custom property the same thing; is a component a pattern; is a style guide the same as a design system; which of two clashing labels came from which source. + +## Promotion To Stable + +Domain lifecycle decisions follow the [repository-owner policy](../DOMAINS.md#lifecycle-and-staleness). The following source, ownership, and machine-contract checks inform a proposed transition beyond `experimental`: + +- A named review owner, secondary reviewer, freshness owner, and dispute resolver are recorded. +- A machine-readable registry with schema exists for terms, concepts, sources, and relations; until then `scripts/validate-design-terminology.mjs` enforces record consistency on the Markdown tables. +- A relation invariant validator derived from the forbidden error states in [Design Term Relations](relation-types.md) passes. +- Every term carries a direct source locator. +- Every relation names both sources and a non-trivial boundary. +- Representative findability queries return a target document or record. +- Unresolved semantic disputes: zero. +- Stale sources beyond their re-review trigger: zero. + +Reader tasks, user studies, adoption counts, and attestations are neither required nor sufficient for a domain lifecycle change. Reader-task observations may support a separately scoped findability claim. + +## Content Review Contract + +Record consistency is enforced mechanically from v0.1 by `scripts/validate-design-terminology.mjs`, which parses the term and relation tables and rejects unknown types, duplicate or unrecorded terms, missing source locators, empty boundaries/scopes, conflicting directions, containment cycles, impossible calendar dates, invalid temporal relations, label mismatches, and orphan terms. Source meaning and authority remain review judgments. Human semantic review is a **stable-promotion gate only**, not a merge gate for `experimental` content; it covers every term and relation (not a sample) against this checklist: + +- Is the source kind correct for each cited source? +- Does each term description match what its source actually supports? +- Is each relation type appropriate for its pair? +- Is each relation boundary sufficient? +- Are both terms compared at the same abstraction level? +- Is official-source authority overstated anywhere? +- Is each historical/current status correct? + +The review result is recorded as: terms reviewed, relations reviewed, counts of accepted, revised, and unresolved items, reviewer name, and review date. Author self-audit alone does not satisfy promotion. + +This domain is a working method template: consumers may fork it and re-record their own sources, terms, and relations. Forked records are consumer-owned and never feed values back into StyleGallery. + +## Start Here + +| Task | Route | +| --- | --- | +| Resolve a source-specific question and produce a scoped handoff. | [Design Term Comparison Workflow](comparison-workflow.md) | + +These workflows and worked cases are usable experimental guidance. Expected-result tables are test designs; actual product, engine, and reader evidence must be recorded separately. Review on a failed task, a source change, or a changed ownership contract. + +## Available Guides + +- [Design Source Kinds](source-kinds.md) classifies what kind of thing a vocabulary source is before its terms are read. +- [Design Source Vocabularies](source-vocabularies.md) inventories named sources with kind, version boundary, status, and review date. +- [Design Concept Families](concept-families.md) classifies design terms by the decision each term serves. +- [Design Term Relations](relation-types.md) defines the typed relation model and the term record shape. +- [Cross-System Term Cases](conflict-cases.md) applies typed relations to recorded term records and conflict scenarios. + +## Domain Contract + +[Vocabulary](../guides/vocabulary.md) owns StyleGallery's canonical internal word set; Design Terminology compares the meanings and relations of terms used by external named sources. Platform Guides compares platform interaction conventions, not terminology; Motion owns motion terminology. Naming rationale: topology suggests a relation graph this domain does not yet provide; terminology is the accurate name for comparing definitions, usage scope, and conflicts. Scope decision: [Design Terminology Domain Scope Decision](../quality/claim-records/design-terminology-domain-scope.md). + +## IA Navigation + +Parent: [StyleGallery](../index.md). +Next: [Design Term Comparison Workflow](comparison-workflow.md). diff --git a/design-terminology/relation-types.md b/design-terminology/relation-types.md new file mode 100644 index 0000000..a4e1708 --- /dev/null +++ b/design-terminology/relation-types.md @@ -0,0 +1,109 @@ +--- +type: Domain Guide +title: Design Term Relations +description: Typed semantic relation model between design terms from different named sources, and the term record shape. +domain: design-terminology +lifecycle: experimental +--- + +# Design Term Relations + +Primary role: typed term relation model. + +## Repository Boundary + +This guide defines the closed set of typed relations used to judge how two design terms relate, and the shape of a term record. It does not decide which external definition is correct, and its types never rename StyleGallery's own terms. Relations are judgments recorded with evidence, not standards. + +## Reusable Method + +1. Record both terms with their sources, kinds, and concepts. +2. Choose exactly one relation type from the closed set below. +3. Write the boundary statement: the specific scope in which the relation holds and where it breaks. +4. Stamp `reviewed_on`; a relation without a date is unverified. +5. Re-verify the relation whenever either source revises the term. + +## Relation Types + +| Relation type | Meaning | Invariants | Required boundary statement | +| --- | --- | --- | --- | +| `equivalent_within_scope` | The two terms denote the same concept inside one named scope | Symmetric; a named scope must exist and be recorded | The scope, and what changes outside it | +| `near_equivalent` | Mostly overlapping meaning with known divergences | Symmetry must be declared per record; the axis creating the divergence must be named | The divergences and their axis | +| `partial_overlap` | Some instances satisfy both terms; others satisfy only one | Symmetric; both the common region and each non-common region must be recorded | Which instances fall on each side | +| `broader_than` | The first term's extension properly contains the second's | Directional; the reverse side must hold `narrower_than` when recorded from the other term; a counterexample direction must exist | The contained region and a counterexample direction | +| `narrower_than` | Inverse of `broader_than` | Directional; must be the inverse of the paired `broader_than` record | Same as above, inverted | +| `implementation_representation` | One term is a way the other is serialized, stored, or consumed | Directional and fixed: the from-term is the representation, the to-term is the semantic concept; the direction must not flip between records of the same pair | The representation direction and what is lost or added | +| `renamed_to` | A source replaced one label with another | Intra-source temporal: both terms must belong to one named source, with a dated or versioned rename event | The rename event and both statuses | +| `deprecated_in_favor_of` | A source withdrew one term in favor of another | Requires a deprecation basis and a replacement source of record | The withdrawal scope and migration note | +| `same_label_different_meaning` | Identical labels, distinct concepts | Requires evidence that label is identical while concept or scope differs | Both meanings and the confusion risk | +| `not_comparable` | No meaningful relation holds at the cited scopes | Symmetric; the comparison axis that fails must be named | Why comparison fails | + +### Forbidden Error States + +A relation record is invalid when any of the following holds: + +- The same term pair records `broader_than` and `narrower_than` simultaneously in one direction (these are inverse views, not two facts). +- The same pair and scope records `equivalent_within_scope` and `not_comparable` (or any other contradiction) at once. +- `renamed_to` lacks a time or version basis for the rename event. +- Either term lacks an official, named source. +- The boundary field is empty or restates the type without adding scope. + +The Markdown validator enforces unique source-qualified term IDs, direct source locators, actual calendar dates, explicit scope and direction, identical labels for `same_label_different_meaning`, temporal status/event requirements, inverse consistency, and acyclic containment within each scope. It ignores fenced examples and HTML comments. Locators must be HTTPS or existing repository documents; the validator does not authenticate source ownership or evaluate semantic truth. + +The term table has seven columns: identifier, label, source/kind with direct locator, concept, status, scope, and reviewed date. The relation table has seven: from, to, type, scope, direction, boundary, and reviewed date. Scope is a non-empty kebab-case comparison identifier. One directed pair has one relation per scope; a separately recorded inverse must agree. Symmetric types use `symmetric`; representation, containment, and temporal relations use `directional`; `near_equivalent` declares either explicitly. Self-relations are invalid. Boundaries must contain a substantive sentence; a length check can reject blanks but cannot establish semantic adequacy. + +## Term Record Shape + +```yaml +term_id: figma.variable +label: Variable +source: figma # named source from source-vocabularies +source_url: https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes +source_kind: design-tool # from source-kinds +concept: named-design-value +status: current # current | deprecated | historical | unknown +scope: file-or-collection-bound +reviewed_on: 2026-09-08 +relations: + - target: dtcg.token + type: partial_overlap + scope: value-interchange + direction: symmetric + reviewed_on: 2026-09-08 + boundary: > + Exportable design values overlap; prototype values need not be + tokens, and one scalar variable does not provide every composite + structure in the 2025.10 format. +``` + +In v0.1 this shape is authored as the Markdown tables in [Cross-System Term Cases](conflict-cases.md). A machine-readable registry holding terms, concepts, sources, and relations is a prerequisite for promoting this domain beyond `experimental`; until then Material v2 answers document search only, not structured crosswalk queries. + +## Opinionated Guidance + +- One relation type per pair, per scope; two relations for the same pair require two named scopes. +- `partial_overlap` with a stated boundary beats an unqualified equivalence. +- A relation between different source kinds must say what the kind difference contributes. +- Reject a recorded relation whose boundary restates the type without adding scope. + +## Platform-Specific Guidance + +Relations involving a platform guideline source cite that platform's surface; deeper convention comparison routes to [Platform Guides](../platform-guides/index.md). + +## Unsupported Absolutes + +- A relation is not a standard and binds no source. +- Popularity does not decide `broader_than`. +- Tool-layer feature names do not settle system-layer relations. +- Absence of a relation between two terms is not evidence of equivalence. + +## Verification Contract + +Every recorded relation names two term records, one type from the closed set, a non-trivial boundary, and a review date; verify both sources still use the terms as recorded before promotion. + +## Source, License, And Attribution + +This page is a locally authored model. The illustrative `figma.variable` and `dtcg.token` relation uses `partial_overlap`; its named sources were rechecked on 2026-09-08 as recorded in [Term Cases](conflict-cases.md). No upstream prose is reproduced. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Cross-System Term Cases](conflict-cases.md). diff --git a/design-terminology/source-kinds.md b/design-terminology/source-kinds.md new file mode 100644 index 0000000..944d9bb --- /dev/null +++ b/design-terminology/source-kinds.md @@ -0,0 +1,77 @@ +--- +type: Domain Guide +title: Design Source Kinds +description: Classification of vocabulary sources into design system, platform guideline, specification, design tool, pattern library, and brand style guide kinds. +domain: design-terminology +lifecycle: experimental +--- + +# Design Source Kinds + +Primary role: vocabulary source-kind classification guide. + +## Repository Boundary + +This guide classifies what kind of thing a vocabulary source is before any of its terms are read or compared. Source kind is a property of the source, not of a term; a term inherits its source's kind for reading rules only. The kinds are review tools for comparing sources, not a ranking of authority. + +## Reusable Method + +1. Identify the named source and its official link. +2. Assign one primary source kind. +3. Record what the kind implies for reading its terms: audience, stability, and versioning behavior. +4. Record the version boundary: specification version, product version, OS release cycle, or a dated review set for living sites. +5. Re-classify when a source restructures, such as a design tool publishing a system layer. +6. Never compare terms across kinds as though the kinds were identical. + +## Source Kinds + +| Source kind | What it is | How to read its terms | Examples | +| --- | --- | --- | --- | +| `design-system` | A maintained, layered collection of foundations, components, and guidance, usually with code | Terms name layers of one system's current release; expect drift across releases | Material 3, Fluent 2, Carbon, Polaris | +| `platform-guideline` | A platform owner's rules for software on that platform | Terms are scoped to the platform's release cycle and certification context | Apple Human Interface Guidelines | +| `specification` | A versioned interchange or conformance document | Terms are defined exactly for the version; meaning changes require a new version | W3C Design Tokens Format | +| `design-tool` | A product whose data model exposes tool constructs | Terms name tool features, not industry definitions; product versions rename freely | Figma variables, modes, components | +| `web-platform` | A browser or platform runtime mechanism | Terms name runtime behavior standardized across vendors, not one system's vocabulary | CSS custom properties | +| `pattern-library` | A curated collection of reusable solutions, with or without a full system | Terms name the collection's own units; scope is the collection, not an organization | StyleGallery Layout patterns | +| `brand-style-guide` | An organization's visual and voice governance document | Terms govern expression, not interface structure; often narrower than a design system | Historical print-lineage style guides | + +## Classification Cases + +| Case | Rule | Example | +| --- | --- | --- | +| Platform guideline mistaken for a design system | A platform guideline binds a platform release; a design system versions itself | HIG is a platform guideline even though it looks system-like | +| Specification mistaken for a system | A specification defines an interchange shape; it ships no components or guidance | DTCG Format defines the token data model, not a token set | +| Tool feature mistaken for an industry term | A tool construct is evidence of the tool's model, not a universal definition | Figma `variables` is a feature name | +| Pattern library inside a system | A library can be part of a system; classify by what is being cited | Citing Carbon patterns cites the system's library layer | +| Brand guide that grew into a system | Classify by what the cited source governs today, and record the history | An org guide that now ships tokens and code | + +## Opinionated Guidance + +- Record source kind before recording any term from that source. +- Treat kind and authority as separate: an official source of any kind is authoritative only for itself. +- Prefer the narrowest kind that fits the cited surface. +- Date every kind assignment; sources restructure. + +## Platform-Specific Guidance + +Platform guideline sources are recorded here only for terminology. Bounded comparison of their interaction conventions belongs to [Platform Guides](../platform-guides/index.md); engine vocabulary belongs to Game UI. + +## Unsupported Absolutes + +- Source kind does not imply quality or maturity. +- One system's layer structure is not a template for other kinds. +- A tool's market share does not convert its feature names into industry terms. +- A specification's precision does not extend to systems that consume it. + +## Verification Contract + +For every recorded source, verify the official link resolves, the source kind still fits the cited surface, the version boundary is stated, and the review date is current enough for the claim being made. + +## Source, License, And Attribution + +This page is a locally authored, project-neutral classification. Named sources are cited only as examples of their kind; no upstream definitional prose is reproduced. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Design Source Vocabularies](source-vocabularies.md). diff --git a/design-terminology/source-vocabularies.md b/design-terminology/source-vocabularies.md new file mode 100644 index 0000000..2c87c0d --- /dev/null +++ b/design-terminology/source-vocabularies.md @@ -0,0 +1,93 @@ +--- +type: Domain Guide +title: Design Source Vocabularies +description: Freshness-bounded inventory of named vocabulary sources with source kind, vocabulary surface, version boundary, and review status. +domain: design-terminology +lifecycle: experimental +--- + +# Design Source Vocabularies + +Primary role: named vocabulary source inventory. + +## Repository Boundary + +This page inventories the named sources whose terms this domain records, with the fields needed to re-verify each reading later. It records which surfaces each source publishes, not what any surface should contain. It does not adjudicate a universal definition of `design system` or rank sources. + +## Reusable Method + +1. Name the source and its owner. +2. Assign the source kind using [Design Source Kinds](source-kinds.md). +3. Record the published vocabulary surfaces as verbatim layer names. +4. Record the version boundary and status, and stamp `reviewed_on` and `retrieved_on`. +5. Re-verify before any promotion beyond `experimental`, and record what changed. + +## Recorded Sources + +| Source | Owner | Source kind | Vocabulary surface | Version boundary | Status | Reviewed on | +| --- | --- | --- | --- | --- | --- | --- | +| [Material 3](https://m3.material.io/foundations) | Google | `design-system` | `foundations`, `components`, `styles`, `design tokens` | Living site; reviewed page set below | current | 2026-08-18 | +| [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) | Apple | `platform-guideline` | `components`, `materials`, `layout`, patterns | OS release cycle; reviewed page set | current | 2026-08-18 | +| [Fluent 2](https://fluent2.microsoft.design/) | Microsoft | `design-system` | `foundations`, `components`, `patterns`, tokens | Living site; reviewed page set | current | 2026-08-18 | +| [Carbon](https://carbondesignsystem.com/) | IBM | `design-system` | `foundations` including tokens, `components`, `patterns` | Living site; reviewed page set | current | 2026-08-18 | +| [Polaris](https://polaris.shopify.com/) | Shopify | `design-system` | `foundations` including design tokens, `components`, `patterns`, `icons` | Living site; package versions for code | current | 2026-08-18 | +| [Design Tokens Format](https://www.w3.org/community/reports/design-tokens/CG-FINAL-format-20251028/) | Design Tokens Community Group | `specification` | `token`, `group`, `alias` data model | Format Module 2025.10; Community Group report, not a W3C Recommendation | current | 2026-09-08 | +| [Figma](https://help.figma.com/hc/en-us) | Figma | `design-tool` | `variables`, `modes`, `components` as tool constructs | Product and help-center version | current | 2026-08-18 | + +All entries cite official first-party URLs (`authority: official`); `retrieved_on` equals the corresponding `reviewed_on`. Entries retaining 2026-08-18 are prior bounded readings, not rechecked claims for the current session. + +## Direct Sources For Current Term Records + +The [Term Cases](conflict-cases.md) use this narrower source set, rechecked 2026-09-08. Locators in the term table point to the exact document or section, not a general vendor home page. + +| Named source | Source kind | Reviewed surface and version | Re-review trigger | +| --- | --- | --- | --- | +| Figma | `design-tool` | [Variables, collections, modes](https://help.figma.com/hc/en-us/articles/14506821864087-Overview-of-variables-collections-and-modes) and [components](https://help.figma.com/hc/en-us/articles/360038662654-Guide-to-components-in-Figma); dated help pages | Tool data model or cited help meaning changes | +| DTCG | `specification` | [2025.10 Format](https://www.w3.org/community/reports/design-tokens/CG-FINAL-format-20251028/) and [Second Editors' Draft, 2022-06-14](https://www.designtokens.org/tr/second-editors-draft/format/) | A comparison changes version; retain the historical scope | +| CSSWG | `web-platform` | [CSS Custom Properties Level 1](https://www.w3.org/TR/css-variables-1/#defining-variables) | The cited runtime-value definition changes | +| Carbon | `design-system` | [What is Carbon](https://carbondesignsystem.com/all-about-carbon/what-is-carbon/) and [patterns overview](https://carbondesignsystem.com/patterns/overview/) | Component or pattern scope changes | +| StyleGallery | `pattern-library` | Local [Layout hub](../layout/index.md) and its repository contract | Layout ownership or pattern contract changes | + +The DTCG 2022 reading is historical evidence of a draft, not an implementation recommendation. A direct locator and a recorded reading establish provenance for the local summary; independent semantic approval remains separate. + +## Freshness Policy + +Every recorded source carries: `source_url`, `source_kind`, a version boundary (specification version, product version, OS cycle, or dated reviewed page set), `status` in `current` / `deprecated` / `historical` / `unknown`, `reviewed_on`, and `retrieved_on`. Living sites without publishable versions record the reviewed page set and a re-review trigger. Terms with era history additionally record `introduced_in`, `deprecated_in`, `renamed_to`, and `historical_scope` in [Cross-System Term Cases](conflict-cases.md). + +## Reading The Inventory + +- Four of the seven broad browse sources are design systems; HIG is a platform guideline, DTCG is a specification, Figma is a tool. Horizontal comparison is valid only within a kind, or through typed relations with boundaries. +- `foundations` labels are near-equivalent as layer names, but each system decides what the layer contains. +- The DTCG row records an interchange format, not a published token set. +- Dates above are the reading bound; any later restructure is new evidence, not a back-fill. + +## Opinionated Guidance + +- Cite surfaces verbatim; do not translate one source's layer names into another's inside a record. +- Add a source only when its vocabulary surface is public, named, and officially linkable. +- Record doc-surface and code-package vocabulary separately when they diverge. +- Treat a renamed surface as new evidence with a new review date. + +## Platform-Specific Guidance + +Platform-owned sources appear here only for terminology records; interaction-convention comparison routes to [Platform Guides](../platform-guides/index.md). + +## Unsupported Absolutes + +- A source's layer count is not a maturity measure. +- Absence of a surface does not mean the source lacks that capability. +- This inventory does not verify any link resolves today beyond its recorded review date. +- Inclusion here is not an endorsement for product adoption. + +## Verification Contract + +Before promotion or material edit, re-verify each cited surface still exists and still publishes the recorded layer names; update `status` and `reviewed_on`; confirm no entry quotes upstream definitional text. + +## Source, License, And Attribution + +This page is locally authored. Every cited source remains the authority on its own vocabulary; links are usage evidence, and no upstream prose, tables, or code samples are reproduced. + +## IA Navigation + +Parent: [Design Terminology](index.md). +Next: [Design Concept Families](concept-families.md). diff --git a/examples/domain-interactions/README.md b/examples/domain-interactions/README.md new file mode 100644 index 0000000..6d7459d --- /dev/null +++ b/examples/domain-interactions/README.md @@ -0,0 +1,72 @@ +--- +type: Worked Example +title: Domain Interaction Lab +description: Executable browser examples with local, source-bound observations for state, interruption, recovery, and keyboard behavior. +--- + +# Domain Interaction Lab + +This standalone browser example applies the [component contract](../../design-engineering/component-contract.md), [Motion recipes](../../motion/interaction-recipes.md), [Game UI verification](../../game-ui/verification-workflow.md), and [platform target matrix](../../platform-guides/compatibility-matrix.md). Product implementation belongs to Design Engineering; the inventory and reward scenarios are web adaptations of Game UI tasks. No native engine project is implied. + +The lab has five sections: explicit save, search/detail, nested inventory dialogs, reward reveal, and disclosure/range input. Responses are manually resolved in the interface so failures and out-of-order completion are reproducible. Data exists only in memory and resets on reload. + +## Run + +From the repository root, start a loopback-only static server on an available port: + +```sh +python3 -m http.server 0 --bind 127.0.0.1 --directory . +``` + +Open `/examples/domain-interactions/` on the printed address. No build, service account, dependency installation, or real purchase is required. + +## Repeat Browser Verification + +Follow the repository's `aside-browser` skill, including `aside guide` and `aside guide repl`. Start `aside repl`, inspect existing tabs, and open this example if it is not already open. Read `snapshot(page)` before running [the QA source](qa.aside.js). + +Inside the REPL, with the interaction lab selected: + +```js +const qaBase = page.url().replace(/[?#].*$/, ""); +const qaSource = await (await fetch(qaBase + "qa.aside.js")).text(); +await eval("(async () => {" + qaSource + "\n})()"); +``` + +This executes the repository-authored QA source in Aside's browser session. It uses visible controls and keyboard/pointer events, reads a fresh snapshot after each action, and records expected and actual DOM states. Only the RTL content fixture changes document direction directly. Viewport and media-preference overrides use the tab's Aside CDP connection and are cleared on completion. The report and viewport screenshots are saved in the printed Aside `artifacts/domain-interactions-*` directory. + +Before recording a new run after a source change, update [sources.json](evidence/sources.json) with the SHA-256 and byte length of the four named files. It is a working-tree source snapshot, not an immutable Git capture receipt. Keep the browser report with the exact source version it tested; do not silently relabel old observations after changing code. + +## Acceptance Coverage + +| Concern | Executed scenario | +| --- | --- | +| Save state | Submit A, edit B, ignore duplicate Enter, confirm A, fail/retry B, validate empty input | +| Search identity | Submit A then B, resolve B first, ignore late A, remove selected result, recover from empty/failure | +| Navigation | Select detail, resize, return to the invoking result, browser history forward | +| Modal ownership | One Escape closes one layer, Tab/Shift+Tab stay in the top dialog, repeated open/close restores focus | +| Delayed equipment | Request A, select B, close the view, resolve A, reopen with B selected and A equipped; failure retains equipment | +| Reward lifecycle | Grant once before reveal, skip without another grant, switch reduced motion during reveal, start with reduced motion | +| Native controls | Enter/Space disclosure, arrow-key range input, pointer preview followed by Escape and release | +| Content and surface | 320/375/768/1024/1440 CSS-pixel widths, 300-character unbroken Korean content, RTL at 320 | + +## Evidence Boundary + +[Verification notes](verification.md) identify the observed runtime, results, fixes, artifacts, and missing coverage. These are local observations of this example. Mock response controls do not prove a backend, real persistence, commerce, network cancellation, or game-engine teardown. Automated keyboard and pointer events do not prove manual human usability or assistive-technology announcements. + +The smaller viewports run inside the Mac browser; they are not Android/iPhone hardware tests. The existing immutable consumer-reference evidence, lifecycle records, v1 trust records, and domain promotion state remain separate. Example code and artifacts are excluded from material admission and the npm package. + +## Implementation Handoff + +- `consumer_reference: consumer-reference/agent-native/registry.json` +- Owning domain: Design Engineering product example, with explicit Motion and Game UI adaptations and Platform Guides verification axes. +- Semantics: native forms, labels, buttons, details/summary, range/radio inputs, and dialog elements. +- Spatial owner: example-local CSS; normal document scroll, modal overflow owned by the open dialog. +- Constraints: `65rem` content maximum, `40rem` list/detail change point, intrinsic wrapping, `90dvh` modal maximum. +- Product presentation: local colors, focus outline, and optional opacity feedback; no new reusable Layout pattern or visual defaults. +- Source identity: individual file hashes in `evidence/sources.json`; uncommitted working tree explicitly declared. +- Terminology records: no design-terminology term/relation records are used by this implementation. + +## Navigation + +Parent: [Design Engineering worked examples](../../design-engineering/worked-examples.md). +Next: [Verification notes](verification.md). diff --git a/examples/domain-interactions/app.mjs b/examples/domain-interactions/app.mjs new file mode 100644 index 0000000..7c2df36 --- /dev/null +++ b/examples/domain-interactions/app.mjs @@ -0,0 +1,276 @@ +// The example owns its product state. No profile or Layout source is mutated. +const byId = (id) => document.getElementById(id); +const motion = matchMedia("(prefers-reduced-motion: reduce)"); +const animations = new Set(); +function present(element) { + if (motion.matches) return; + const animation = element.animate([{ opacity: .4 }, { opacity: 1 }], { duration: 240 }); + animations.add(animation); + // Cancellation is expected, including a preference change during playback. + animation.finished.catch(() => {}).finally(() => animations.delete(animation)); +} +function motionChanged() { + byId("motion-preference").textContent = motion.matches ? "Motion: reduced. Status changes immediately." : "Motion: normal. Status changes immediately."; + if (motion.matches) { + for (const animation of animations) animation.cancel(); + finishReveal(); + } +} + +// Draft, submitted snapshot, and persisted value have different owners. +let persisted = "Original"; +let saveRequest = null; +let saveError = ""; +function renderSave() { + const dirty = byId("draft").value !== persisted; + byId("save").disabled = Boolean(saveRequest) || !dirty; + byId("save-success").disabled = !saveRequest; + byId("save-failure").disabled = !saveRequest; + byId("persisted").textContent = persisted; + byId("save-error").textContent = saveError; + byId("save-status").textContent = saveRequest + ? `Saving “${saveRequest.value}”.${byId("draft").value !== saveRequest.value ? " Later edits are unsaved." : ""}` + : dirty ? "Unsaved changes." : "All changes saved."; +} +byId("draft").addEventListener("input", () => { + saveError = ""; + byId("draft").removeAttribute("aria-invalid"); + renderSave(); +}); +byId("save-form").addEventListener("submit", (event) => { + event.preventDefault(); + if (saveRequest || byId("draft").value === persisted) return; + if (!byId("draft").value.trim()) { + saveError = "Enter a display name."; + byId("draft").setAttribute("aria-invalid", "true"); + renderSave(); + byId("draft").focus(); + return; + } + saveError = ""; + saveRequest = { value: byId("draft").value }; + renderSave(); +}); +function resolveSave(ok) { + if (!saveRequest) return; + if (ok) persisted = saveRequest.value; + saveError = ok ? "" : "Save failed. Your draft is retained; try again."; + saveRequest = null; + renderSave(); + present(byId("save-status")); +} +byId("save-success").addEventListener("click", () => resolveSave(true)); +byId("save-failure").addEventListener("click", () => resolveSave(false)); + +let searchSequence = 0; +let selectedResult = null; +let results = []; +const narrow = matchMedia("(max-width: 40rem)"); +function renderSelection({ focus = false } = {}) { + const item = results.find(({ id }) => id === selectedResult); + byId("detail").hidden = !item; + byId("search-panes").dataset.view = item ? "detail" : "list"; + if (item) { + byId("detail-heading").textContent = item.label; + byId("detail-description").textContent = `Details for ${item.label}. Query and selection survive window resizing.`; + if (focus) byId("detail-heading").focus(); + } +} +function selectResult(id) { + selectedResult = id; + history.pushState({ result: id }, "", `#result=${encodeURIComponent(id)}`); + renderSelection({ focus: true }); +} +function renderResults() { + const hadResultFocus = byId("results").contains(document.activeElement) || byId("detail").contains(document.activeElement); + byId("results").replaceChildren(...results.map((item) => { + const li = document.createElement("li"); + const button = document.createElement("button"); + button.textContent = item.label; + button.dataset.result = item.id; + button.addEventListener("click", () => selectResult(item.id)); + li.append(button); + return li; + })); + if (selectedResult && !results.some(({ id }) => id === selectedResult)) { + selectedResult = null; + history.replaceState(null, "", location.pathname); + byId("search-status").textContent += " Previous selection is unavailable."; + } + renderSelection(); + if (hadResultFocus) (selectedResult ? byId("detail-heading") : byId("query")).focus(); +} +function returnToResults() { + const previous = selectedResult; + selectedResult = null; + renderSelection(); + const button = [...byId("results").querySelectorAll("button")].find((node) => node.dataset.result === previous); + (button || byId("query")).focus(); +} +byId("back-results").addEventListener("click", () => { + // An in-session detail entry has a known parent. Direct entry stays local. + if (history.state?.result) history.back(); + else returnToResults(); +}); +window.addEventListener("popstate", (event) => { + if (event.state?.result && results.some(({ id }) => id === event.state.result)) { + selectedResult = event.state.result; + renderSelection({ focus: true }); + } else returnToResults(); +}); +narrow.addEventListener("change", () => { + if (narrow.matches && selectedResult && byId("search-list").contains(document.activeElement)) byId("detail-heading").focus(); +}); +byId("search-form").addEventListener("submit", (event) => { + event.preventDefault(); + const query = byId("query").value.trim(); + if (!query) return; + const request = ++searchSequence; + byId("search-status").textContent = `Searching “${query}”.`; + const controls = document.createElement("div"); + controls.className = "actions"; + for (const outcome of ["results", "empty", "failure"]) { + const button = document.createElement("button"); + button.textContent = `Resolve ${request} (${query}): ${outcome}`; + button.addEventListener("click", () => { + controls.remove(); + if (request === searchSequence) { + if (outcome === "failure") { + byId("search-status").textContent = `Search “${query}” failed. Previous results retained; retry the search.`; + } else { + results = outcome === "empty" ? [] : [1, 2].map((n) => ({ id: `${request}-${n}`, label: `${query} · ${n}` })); + byId("search-status").textContent = results.length ? `Results for “${query}”.` : `No results for “${query}”. Try another query.`; + renderResults(); + } + } + // Removing a focused response control must leave a useful focus target. + byId("query").focus(); + }); + controls.append(button); + } + byId("search-responses").append(controls); +}); + +// Session data outlives either modal view; responses target captured identities. +let selectedItem = "A"; +let equippedItem = null; +let equipTarget = null; +let equipRequest = null; +let equipMessage = "Equipped: none."; +const inventory = byId("inventory-dialog"); +const decision = byId("equip-dialog"); +for (const dialog of [inventory, decision]) dialog.addEventListener("keydown", (event) => { + if (event.key !== "Tab" || (dialog === inventory && decision.open)) return; + const controls = [...dialog.querySelectorAll("button, input, [tabindex]")].filter((node) => + !node.disabled && node.tabIndex >= 0 && node.getClientRects().length + && (node.type !== "radio" || node.checked)); + const destination = event.shiftKey ? controls.at(-1) : controls[0]; + const boundary = event.shiftKey ? controls[0] : controls.at(-1); + if (destination && (document.activeElement === boundary || !dialog.contains(document.activeElement))) { + event.preventDefault(); + destination.focus(); + } +}); +function renderInventory() { + byId("equipment-status").textContent = equipMessage; + byId("equip-success").disabled = !equipRequest; + byId("equip-failure").disabled = !equipRequest; + if (!inventory.open) return; + byId("inventory-status").textContent = `Selected: ${selectedItem}. Equipped: ${equippedItem || "none"}.${equipRequest ? ` Pending: ${equipRequest.item}.` : ""}`; + byId("equip-item").disabled = Boolean(equipRequest); +} +byId("open-inventory").addEventListener("click", () => { + inventory.showModal(); + renderInventory(); + inventory.querySelector("input:checked").focus(); +}); +for (const radio of inventory.querySelectorAll("input[name='item']")) radio.addEventListener("change", () => { + selectedItem = radio.value; + renderInventory(); +}); +byId("equip-item").addEventListener("click", () => { + equipTarget = selectedItem; + byId("equip-title").textContent = `Equip item ${equipTarget}?`; + byId("equip-status").textContent = "This changes the equipped item."; + byId("confirm-equip").disabled = false; + decision.showModal(); + byId("cancel-equip").focus(); + present(decision); +}); +function closeDecision() { + decision.close(); + if (inventory.open) inventory.querySelector("input:checked").focus(); +} +decision.addEventListener("cancel", (event) => { event.preventDefault(); closeDecision(); }); +byId("cancel-equip").addEventListener("click", closeDecision); +function closeInventory() { + if (decision.open) decision.close(); + inventory.close(); + byId("open-inventory").focus(); +} +inventory.addEventListener("cancel", (event) => { event.preventDefault(); closeInventory(); }); +byId("close-inventory").addEventListener("click", closeInventory); +byId("confirm-equip").addEventListener("click", () => { + if (equipRequest) return; + equipRequest = { item: equipTarget }; + equipMessage = `Equipment request pending: ${equipTarget}.`; + byId("confirm-equip").disabled = true; + byId("equip-status").textContent = "Pending. Closing this view does not cancel the operation."; + renderInventory(); +}); +function resolveEquipment(ok) { + if (!equipRequest) return; + if (ok) equippedItem = equipRequest.item; + equipMessage = ok ? `Equipped: ${equippedItem}.` : `Equipment request failed. Equipped: ${equippedItem || "none"}. Reopen inventory to retry.`; + equipRequest = null; + renderInventory(); +} +byId("equip-success").addEventListener("click", () => resolveEquipment(true)); +byId("equip-failure").addEventListener("click", () => resolveEquipment(false)); + +let rewardGranted = false; +let revealTimer = null; +function finishReveal() { + if (revealTimer !== null) clearTimeout(revealTimer); + revealTimer = null; + if (rewardGranted) byId("reward-status").textContent = "Reward received."; + // Keep focus useful when a focused skip command becomes unavailable. + if (document.activeElement === byId("skip-reveal")) { + byId("reward-status").tabIndex = -1; + byId("reward-status").focus(); + } + byId("skip-reveal").disabled = true; +} +byId("claim-reward").addEventListener("click", () => { + if (rewardGranted) return; + rewardGranted = true; + byId("claim-reward").disabled = true; + byId("reward-count").textContent = "Rewards granted: 1"; + byId("reward-status").textContent = "Reward received. Revealing…"; + byId("skip-reveal").disabled = false; + if (motion.matches) finishReveal(); + else { + present(byId("reward-count")); + revealTimer = setTimeout(finishReveal, 1500); + } +}); +byId("skip-reveal").addEventListener("click", finishReveal); + +const position = byId("position"); +let committedPosition = position.value; +position.addEventListener("input", () => { byId("position-status").textContent = `Preview position: ${position.value}. Committed: ${committedPosition}.`; }); +position.addEventListener("change", () => { + committedPosition = position.value; + byId("position-status").textContent = `Committed position: ${committedPosition}`; +}); +position.addEventListener("keydown", (event) => { + if (event.key !== "Escape") return; + event.preventDefault(); + position.value = committedPosition; + byId("position-status").textContent = `Committed position: ${committedPosition}`; + position.blur(); + position.focus(); +}); +motion.addEventListener("change", motionChanged); +motionChanged(); +renderSave(); diff --git a/examples/domain-interactions/evidence/detail-375.png b/examples/domain-interactions/evidence/detail-375.png new file mode 100644 index 0000000..0275cb8 Binary files /dev/null and b/examples/domain-interactions/evidence/detail-375.png differ diff --git a/examples/domain-interactions/evidence/long-rtl-320.png b/examples/domain-interactions/evidence/long-rtl-320.png new file mode 100644 index 0000000..a0ad207 Binary files /dev/null and b/examples/domain-interactions/evidence/long-rtl-320.png differ diff --git a/examples/domain-interactions/evidence/manifest.json b/examples/domain-interactions/evidence/manifest.json new file mode 100644 index 0000000..2164f9c --- /dev/null +++ b/examples/domain-interactions/evidence/manifest.json @@ -0,0 +1,48 @@ +{ + "kind": "local-browser-artifact-manifest", + "host": { + "hardware_id": "Mac16,8", + "architecture": "arm64", + "os": "macOS 26.5.1", + "build": "25F80" + }, + "started": "2026-09-08T02:06:57.911Z", + "finished": "2026-09-08T02:07:11.475Z", + "files": [ + { + "path": "sources.json", + "sha256": "08948cf9802120ba1e7f77e3d71abd1c93b6d77c640d8be845640d61469a3a18", + "bytes": 852 + }, + { + "path": "report.json", + "sha256": "e7293474a2defafaaf3caeff7cd9732649d0be403a667ffe795a0b37a090f66c", + "bytes": 247335 + }, + { + "path": "native-desktop.png", + "sha256": "65d6c673f35c57d9bd908a30d118c7e7c67655b8ecba8cbc50f8a1b41e3624ea", + "bytes": 146262 + }, + { + "path": "detail-375.png", + "sha256": "2625c9ee709c447e11e4a23d3929ecf07e25de6b8df297b88ac90195a27966c8", + "bytes": 106435 + }, + { + "path": "nested-dialogs.png", + "sha256": "8f4ca0089b1255a6f57a6957a4568939767590883f9e0c8286c57e0bc8e6791d", + "bytes": 156467 + }, + { + "path": "long-rtl-320.png", + "sha256": "b1ae71d42ef75c1a039ba85d432279ab828eb704680a036e808c2634ced827cb", + "bytes": 103423 + }, + { + "path": "reduced-motion-320.png", + "sha256": "adbe3f645b79abec61681508cf8c204328f03fdd7b312710c8435d4bc28a8595", + "bytes": 109100 + } + ] +} diff --git a/examples/domain-interactions/evidence/native-desktop.png b/examples/domain-interactions/evidence/native-desktop.png new file mode 100644 index 0000000..6434cd3 Binary files /dev/null and b/examples/domain-interactions/evidence/native-desktop.png differ diff --git a/examples/domain-interactions/evidence/nested-dialogs.png b/examples/domain-interactions/evidence/nested-dialogs.png new file mode 100644 index 0000000..6db0a34 Binary files /dev/null and b/examples/domain-interactions/evidence/nested-dialogs.png differ diff --git a/examples/domain-interactions/evidence/reduced-motion-320.png b/examples/domain-interactions/evidence/reduced-motion-320.png new file mode 100644 index 0000000..5b28735 Binary files /dev/null and b/examples/domain-interactions/evidence/reduced-motion-320.png differ diff --git a/examples/domain-interactions/evidence/report.json b/examples/domain-interactions/evidence/report.json new file mode 100644 index 0000000..2be1579 --- /dev/null +++ b/examples/domain-interactions/evidence/report.json @@ -0,0 +1,3592 @@ +{ + "kind": "local-browser-observation", + "started": "2026-09-08T02:06:57.911Z", + "finished": "2026-09-08T02:07:11.475Z", + "runtime": { + "protocolVersion": "1.3", + "product": "Chrome/151.0.7922.171", + "revision": "@cc5584af0df9786f00efdb71f666c6664f836c2d", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36", + "jsVersion": "15.1.206.21" + }, + "sources": { + "kind": "working-tree-source-snapshot", + "base_revision": "d8bdf0bd5b5aec2fbc38e322a9ac7a1d31fd1332", + "uncommitted_sources": true, + "files": [ + { + "path": "examples/domain-interactions/index.html", + "sha256": "4c6280a9f720b546c2c6bc6c252dd8603764c71868b1cc3df091de39651228ab", + "bytes": 4922 + }, + { + "path": "examples/domain-interactions/styles.css", + "sha256": "016f98025a98cb612f3730e3df013f8f6b4aebe467db9fb4464b9b37d7b923cd", + "bytes": 1832 + }, + { + "path": "examples/domain-interactions/app.mjs", + "sha256": "d802165599b917fc8d9bebf38e4f62d733552c44de47dc988ca6e64041f26eb9", + "bytes": 11538 + }, + { + "path": "examples/domain-interactions/qa.aside.js", + "sha256": "dfda27544710f975eccab6aeb7bb51f38aff3e0bab9b7381b3fa41472c49e070", + "bytes": 15750 + } + ] + }, + "inputs": [ + "automated keyboard events", + "automated pointer events" + ], + "emulation": "Viewport sizes and media preferences only; no mobile hardware emulation or touch claim.", + "checks": [ + { + "id": "native-desktop-start", + "at": "2026-09-08T02:06:58.100Z", + "expected": { + "persisted": "Original", + "saveDisabled": true, + "overflow": false + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "save-edit-A", + "at": "2026-09-08T02:06:58.171Z", + "expected": { + "saveDisabled": false + }, + "actual": { + "draft": "A", + "persisted": "Original", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2]: \"Original\"\n+ - textbox \"Display name\" [ref=e2] [focused]: \"A\"\n@@ -13,2 +13,2 @@\n- - button \"Save name\" [ref=e3] [disabled]\n- - status: \"All changes saved.\"\n+ - button \"Save name\" [ref=e3]\n+ - status: \"Unsaved changes.\"\n", + "ok": true + }, + { + "id": "save-submit-A", + "at": "2026-09-08T02:06:58.423Z", + "expected": { + "saveDisabled": true, + "saveStatus": "Saving “A”." + }, + "actual": { + "draft": "A", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "Saving “A”.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n Saving “A”.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2] [focused]: \"A\"\n+ - textbox \"Display name\" [ref=e2]: \"A\"\n@@ -13,2 +13,2 @@\n- - button \"Save name\" [ref=e3]\n- - status: \"Unsaved changes.\"\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"Saving “A”.\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6] [disabled]\n- - button \"Fail save\" [ref=e7] [disabled]\n+ - button \"Confirm save\" [ref=e6]\n+ - button \"Fail save\" [ref=e7]\n@@ -52,0 +52 @@\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "save-edit-B-during-A", + "at": "2026-09-08T02:06:58.432Z", + "expected": { + "saveStatus": "Saving “A”. Later edits are unsaved." + }, + "actual": { + "draft": "B", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "Saving “A”. Later edits are unsaved.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2]: \"A\"\n+ - textbox \"Display name\" [ref=e2] [focused]: \"B\"\n@@ -14 +14 @@\n- - status: \"Saving “A”.\"\n+ - status: \"Saving “A”. Later edits are unsaved.\"\n@@ -52 +52 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "save-ignore-duplicate", + "at": "2026-09-08T02:06:58.437Z", + "expected": { + "saveStatus": "Saving “A”. Later edits are unsaved." + }, + "actual": { + "draft": "B", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "Saving “A”. Later edits are unsaved.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "save-A-preserves-B", + "at": "2026-09-08T02:06:58.740Z", + "expected": { + "persisted": "A", + "draft": "B", + "saveStatus": "Unsaved changes.", + "saveDisabled": false + }, + "actual": { + "draft": "B", + "persisted": "A", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n Unsaved changes.\n Confirmed name: A\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2] [focused]: \"B\"\n+ - textbox \"Display name\" [ref=e2]: \"B\"\n@@ -13,3 +13,3 @@\n- - button \"Save name\" [ref=e3] [disabled]\n- - status: \"Saving “A”. Later edits are unsaved.\"\n- - text: \"Confirmed name: Original\"\n+ - button \"Save name\" [ref=e3]\n+ - status: \"Unsaved changes.\"\n+ - text: \"Confirmed name: A\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6]\n- - button \"Fail save\" [ref=e7]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n@@ -52 +52 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "save-B-submit", + "at": "2026-09-08T02:06:59.069Z", + "expected": { + "saveStatus": "Saving “B”." + }, + "actual": { + "draft": "B", + "persisted": "A", + "saveDisabled": true, + "saveStatus": "Saving “B”.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n Saving “B”.\n Confirmed name: A\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -13,2 +13,2 @@\n- - button \"Save name\" [ref=e3]\n- - status: \"Unsaved changes.\"\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"Saving “B”.\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6] [disabled]\n- - button \"Fail save\" [ref=e7] [disabled]\n+ - button \"Confirm save\" [ref=e6]\n+ - button \"Fail save\" [ref=e7]\n", + "ok": true + }, + { + "id": "save-failure-retains-draft", + "at": "2026-09-08T02:06:59.380Z", + "expected": { + "persisted": "A", + "draft": "B", + "saveError": "Save failed. Your draft is retained; try again." + }, + "actual": { + "draft": "B", + "persisted": "A", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "Save failed. Your draft is retained; try again.", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n Save failed. Your draft is retained; try again.\n Save name\n \n Unsaved changes.\n Confirmed name: A\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -12,3 +12,3 @@\n- - alert\n- - button \"Save name\" [ref=e3] [disabled]\n- - status: \"Saving “B”.\"\n+ - alert: \"Save failed. Your draft is retained; try again.\"\n+ - button \"Save name\" [ref=e3]\n+ - status: \"Unsaved changes.\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6]\n- - button \"Fail save\" [ref=e7]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n", + "ok": true + }, + { + "id": "save-retry", + "at": "2026-09-08T02:06:59.702Z", + "expected": { + "saveStatus": "Saving “B”.", + "saveError": "" + }, + "actual": { + "draft": "B", + "persisted": "A", + "saveDisabled": true, + "saveStatus": "Saving “B”.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n Saving “B”.\n Confirmed name: A\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -12,3 +12,3 @@\n- - alert: \"Save failed. Your draft is retained; try again.\"\n- - button \"Save name\" [ref=e3]\n- - status: \"Unsaved changes.\"\n+ - alert\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"Saving “B”.\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6] [disabled]\n- - button \"Fail save\" [ref=e7] [disabled]\n+ - button \"Confirm save\" [ref=e6]\n+ - button \"Fail save\" [ref=e7]\n", + "ok": true + }, + { + "id": "save-retry-success", + "at": "2026-09-08T02:07:00.018Z", + "expected": { + "persisted": "B", + "draft": "B", + "saveDisabled": true + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -14,2 +14,2 @@\n- - status: \"Saving “B”.\"\n- - text: \"Confirmed name: A\"\n+ - status: \"All changes saved.\"\n+ - text: \"Confirmed name: B\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6]\n- - button \"Fail save\" [ref=e7]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n", + "ok": true + }, + { + "id": "save-empty", + "at": "2026-09-08T02:07:00.026Z", + "expected": {}, + "actual": { + "draft": "", + "persisted": "B", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2]: \"B\"\n+ - textbox \"Display name\" [ref=e2] [focused]\n@@ -13,2 +13,2 @@\n- - button \"Save name\" [ref=e3] [disabled]\n- - status: \"All changes saved.\"\n+ - button \"Save name\" [ref=e3]\n+ - status: \"Unsaved changes.\"\n@@ -52 +52 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "save-required-error", + "at": "2026-09-08T02:07:00.332Z", + "expected": { + "active": "draft", + "saveError": "Enter a display name.", + "persisted": "B" + }, + "actual": { + "draft": "", + "persisted": "B", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "Enter a display name.", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -12 +12 @@\n- - alert\n+ - alert: \"Enter a display name.\"\n@@ -52 +52 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "save-recover-validity", + "at": "2026-09-08T02:07:00.340Z", + "expected": { + "saveError": "", + "saveDisabled": true + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11,4 +11,4 @@\n- - textbox \"Display name\" [ref=e2] [focused]\n- - alert: \"Enter a display name.\"\n- - button \"Save name\" [ref=e3]\n- - status: \"Unsaved changes.\"\n+ - textbox \"Display name\" [ref=e2] [focused]: \"B\"\n+ - alert\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"All changes saved.\"\n", + "ok": true + }, + { + "id": "search-query-A", + "at": "2026-09-08T02:07:00.347Z", + "expected": {}, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "A", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2] [focused]: \"B\"\n+ - textbox \"Display name\" [ref=e2]: \"B\"\n@@ -24 +24 @@\n- - textbox \"Search query\" [ref=e9]\n+ - textbox \"Search query\" [ref=e9] [focused]: \"A\"\n", + "ok": true + }, + { + "id": "search-submit-A", + "at": "2026-09-08T02:07:00.354Z", + "expected": { + "searchStatus": "Searching “A”." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "A", + "searchStatus": "Searching “A”.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -26 +26 @@\n- - status: \"Enter a query.\"\n+ - status: \"Searching “A”.\"\n@@ -29 +29,5 @@\n- - generic \"Search response controls\" [ref=e12]\n+ - generic [ref=e11]:\n+ - generic \"Search response controls\" [ref=e12]\n+ - button \"Resolve 1 (A): results\" [ref=e26]\n+ - button \"Resolve 1 (A): empty\" [ref=e27]\n+ - button \"Resolve 1 (A): failure\" [ref=e28]\n@@ -52 +56 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "search-query-B", + "at": "2026-09-08T02:07:00.360Z", + "expected": {}, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "B", + "searchStatus": "Searching “A”.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -24 +24 @@\n- - textbox \"Search query\" [ref=e9] [focused]: \"A\"\n+ - textbox \"Search query\" [ref=e9] [focused]: \"B\"\n", + "ok": true + }, + { + "id": "search-submit-B", + "at": "2026-09-08T02:07:00.369Z", + "expected": { + "searchStatus": "Searching “B”." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "B", + "searchStatus": "Searching “B”.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -26 +26 @@\n- - status: \"Searching “A”.\"\n+ - status: \"Searching “B”.\"\n@@ -34,0 +34,3 @@\n+ - button \"Resolve 2 (B): results\" [ref=e29]\n+ - button \"Resolve 2 (B): empty\" [ref=e30]\n+ - button \"Resolve 2 (B): failure\" [ref=e31]\n", + "ok": true + }, + { + "id": "search-B-before-A", + "at": "2026-09-08T02:07:00.684Z", + "expected": { + "results": [ + "B · 1", + "B · 2" + ] + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11,0 @@\n- - textbox \"Display name\" [ref=e2]: \"B\"\n@@ -26 +25 @@\n- - status: \"Searching “B”.\"\n+ - status: \"Results for “B”.\"\n@@ -28 +27,5 @@\n- - list\n+ - list:\n+ - listitem \"B · 1\" [ref=e32]:\n+ - button \"B · 1\" [ref=e33]\n+ - listitem \"B · 2\" [ref=e34]:\n+ - button \"B · 2\" [ref=e35]\n@@ -34,3 +37,0 @@\n- - button \"Resolve 2 (B): results\" [ref=e29]\n- - button \"Resolve 2 (B): empty\" [ref=e30]\n- - button \"Resolve 2 (B): failure\" [ref=e31]\n@@ -59 +59 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "search-stale-A-ignored", + "at": "2026-09-08T02:07:00.999Z", + "expected": { + "results": [ + "B · 1", + "B · 2" + ], + "searchStatus": "Results for “B”." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -32,5 +32 @@\n- - generic [ref=e11]:\n- - generic \"Search response controls\" [ref=e12]\n- - button \"Resolve 1 (A): results\" [ref=e26]\n- - button \"Resolve 1 (A): empty\" [ref=e27]\n- - button \"Resolve 1 (A): failure\" [ref=e28]\n+ - generic \"Search response controls\" [ref=e12]\n", + "ok": true + }, + { + "id": "search-select-detail", + "at": "2026-09-08T02:07:01.823Z", + "expected": { + "detail": "B · 2", + "active": "detail-heading" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -1 +1,59 @@\n-\n+- banner:\n+ - text: \"StyleGallery · executable examples\"\n+ - heading \"Interaction lab\" [level=1]\n+ - text: \"Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\"\n+ - status: \"Motion: normal. Status changes immediately.\"\n+- main:\n+ - region \"1. Save without losing later edits\" [ref=e1]:\n+ - heading \"1. Save without losing later edits\" [level=2]\n+ - form:\n+ - label: \"Display name\"\n+ - alert\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"All changes saved.\"\n+ - text: \"Confirmed name: B\"\n+ - generic [ref=e4]:\n+ - generic \"Save response controls\" [ref=e5]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n+ - region \"2. Search and return to the same item\" [ref=e8]:\n+ - heading \"2. Search and return to the same item\" [level=2]\n+ - form:\n+ - label: \"Search query\"\n+ - textbox \"Search query\" [ref=e9]: \"B\"\n+ - button \"Search items\" [ref=e10]\n+ - status: \"Results for “B”.\"\n+ - heading \"Results\" [level=3]\n+ - list:\n+ - listitem \"B · 1\" [ref=e32]:\n+ - button \"B · 1\" [ref=e33]\n+ - listitem \"B · 2\" [ref=e34]:\n+ - button \"B · 2\" [ref=e35]\n+ - article \"B · 2\" [ref=e36]:\n+ - heading \"B · 2\" [level=3] [focused]\n+ - text: \"Details for B · 2. Query and selection survive window resizing.\"\n+ - button \"Back to results\" [ref=e37]\n+ - generic \"Search response controls\" [ref=e12]\n+ - region \"3. Inventory and nested decisions\" [ref=e13]:\n+ - heading \"3. Inventory and nested decisions\" [level=2]\n+ - button \"Open inventory\" [ref=e14]\n+ - status: \"Equipped: none.\"\n+ - generic [ref=e15]:\n+ - generic \"Equipment response controls\" [ref=e16]\n+ - button \"Confirm equipment request\" [ref=e17] [disabled]\n+ - button \"Fail equipment request\" [ref=e18] [disabled]\n+ - region \"4. A reward independent of its reveal\" [ref=e19]:\n+ - heading \"4. A reward independent of its reveal\" [level=2]\n+ - button \"Claim reward\" [ref=e20]\n+ - button \"Skip reveal\" [ref=e21] [disabled]\n+ - status: \"Reward ready.\"\n+ - text: \"Rewards granted: 0\"\n+ - region \"5. Disclosure and direct manipulation\" [ref=e22]:\n+ - heading \"5. Disclosure and direct manipulation\" [level=2]\n+ - generic \"Delivery restrictions\" [ref=e24]\n+ - label: \"Preview position\"\n+ - textbox \"Preview position\" [ref=e25]: \"50\"\n+ - text: \"Drag or use arrow keys. Release commits; Escape cancels an active preview.\"\n+ - status: \"Committed position: 50\"\n+- contentinfo: \"Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\"\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "selected-detail-320", + "at": "2026-09-08T02:07:01.831Z", + "expected": { + "viewport": 320, + "query": "B", + "detail": "B · 2", + "active": "detail-heading", + "listVisible": false, + "overflow": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": false, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "@@ -26,6 +26,0 @@\n- - heading \"Results\" [level=3]\n- - list:\n- - listitem \"B · 1\" [ref=e32]:\n- - button \"B · 1\" [ref=e33]\n- - listitem \"B · 2\" [ref=e34]:\n- - button \"B · 2\" [ref=e35]\n", + "ok": true + }, + { + "id": "selected-detail-375", + "at": "2026-09-08T02:07:01.837Z", + "expected": { + "viewport": 375, + "query": "B", + "detail": "B · 2", + "active": "detail-heading", + "listVisible": false, + "overflow": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": false, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 375, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "selected-detail-768", + "at": "2026-09-08T02:07:01.890Z", + "expected": { + "viewport": 768, + "query": "B", + "detail": "B · 2", + "active": "detail-heading", + "listVisible": true, + "overflow": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 768, + "overflow": false + }, + "snapshot": "@@ -26,0 +26,6 @@\n+ - heading \"Results\" [level=3]\n+ - list:\n+ - listitem \"B · 1\" [ref=e32]:\n+ - button \"B · 1\" [ref=e33]\n+ - listitem \"B · 2\" [ref=e34]:\n+ - button \"B · 2\" [ref=e35]\n", + "ok": true + }, + { + "id": "selected-detail-1024", + "at": "2026-09-08T02:07:01.896Z", + "expected": { + "viewport": 1024, + "query": "B", + "detail": "B · 2", + "active": "detail-heading", + "listVisible": true, + "overflow": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1024, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "selected-detail-1440", + "at": "2026-09-08T02:07:01.902Z", + "expected": { + "viewport": 1440, + "query": "B", + "detail": "B · 2", + "active": "detail-heading", + "listVisible": true, + "overflow": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "detail-parent-return", + "at": "2026-09-08T02:07:02.717Z", + "expected": { + "detail": null, + "activeText": "B · 2" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31,5 +31 @@\n- - button \"B · 2\" [ref=e35]\n- - article \"B · 2\" [ref=e36]:\n- - heading \"B · 2\" [level=3] [focused]\n- - text: \"Details for B · 2. Query and selection survive window resizing.\"\n- - button \"Back to results\" [ref=e37]\n+ - button \"B · 2\" [ref=e35] [focused]\n", + "ok": true + }, + { + "id": "detail-browser-forward", + "at": "2026-09-08T02:07:02.728Z", + "expected": { + "detail": "B · 2", + "active": "detail-heading" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "detail-heading", + "activeText": "B · 2", + "query": "B", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -1 +1,59 @@\n-\n+- banner:\n+ - text: \"StyleGallery · executable examples\"\n+ - heading \"Interaction lab\" [level=1]\n+ - text: \"Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\"\n+ - status: \"Motion: normal. Status changes immediately.\"\n+- main:\n+ - region \"1. Save without losing later edits\" [ref=e1]:\n+ - heading \"1. Save without losing later edits\" [level=2]\n+ - form:\n+ - label: \"Display name\"\n+ - alert\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"All changes saved.\"\n+ - text: \"Confirmed name: B\"\n+ - generic [ref=e4]:\n+ - generic \"Save response controls\" [ref=e5]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n+ - region \"2. Search and return to the same item\" [ref=e8]:\n+ - heading \"2. Search and return to the same item\" [level=2]\n+ - form:\n+ - label: \"Search query\"\n+ - textbox \"Search query\" [ref=e9]: \"B\"\n+ - button \"Search items\" [ref=e10]\n+ - status: \"Results for “B”.\"\n+ - heading \"Results\" [level=3]\n+ - list:\n+ - listitem \"B · 1\" [ref=e32]:\n+ - button \"B · 1\" [ref=e33]\n+ - listitem \"B · 2\" [ref=e34]:\n+ - button \"B · 2\" [ref=e35]\n+ - article \"B · 2\" [ref=e36]:\n+ - heading \"B · 2\" [level=3] [focused]\n+ - text: \"Details for B · 2. Query and selection survive window resizing.\"\n+ - button \"Back to results\" [ref=e37]\n+ - generic \"Search response controls\" [ref=e12]\n+ - region \"3. Inventory and nested decisions\" [ref=e13]:\n+ - heading \"3. Inventory and nested decisions\" [level=2]\n+ - button \"Open inventory\" [ref=e14]\n+ - status: \"Equipped: none.\"\n+ - generic [ref=e15]:\n+ - generic \"Equipment response controls\" [ref=e16]\n+ - button \"Confirm equipment request\" [ref=e17] [disabled]\n+ - button \"Fail equipment request\" [ref=e18] [disabled]\n+ - region \"4. A reward independent of its reveal\" [ref=e19]:\n+ - heading \"4. A reward independent of its reveal\" [level=2]\n+ - button \"Claim reward\" [ref=e20]\n+ - button \"Skip reveal\" [ref=e21] [disabled]\n+ - status: \"Reward ready.\"\n+ - text: \"Rewards granted: 0\"\n+ - region \"5. Disclosure and direct manipulation\" [ref=e22]:\n+ - heading \"5. Disclosure and direct manipulation\" [level=2]\n+ - generic \"Delivery restrictions\" [ref=e24]\n+ - label: \"Preview position\"\n+ - textbox \"Preview position\" [ref=e25]: \"50\"\n+ - text: \"Drag or use arrow keys. Release commits; Escape cancels an active preview.\"\n+ - status: \"Committed position: 50\"\n+- contentinfo: \"Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\"\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "search-empty-query", + "at": "2026-09-08T02:07:02.751Z", + "expected": {}, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "empty", + "searchStatus": "Results for “B”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -23 +23 @@\n- - textbox \"Search query\" [ref=e9]: \"B\"\n+ - textbox \"Search query\" [ref=e9] [focused]: \"empty\"\n@@ -33 +33 @@\n- - heading \"B · 2\" [level=3] [focused]\n+ - heading \"B · 2\" [level=3]\n@@ -59 +59 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "search-empty-submit", + "at": "2026-09-08T02:07:02.760Z", + "expected": { + "searchStatus": "Searching “empty”." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "empty", + "searchStatus": "Searching “empty”.", + "results": [ + "B · 1", + "B · 2" + ], + "detail": "B · 2", + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -25 +25 @@\n- - status: \"Results for “B”.\"\n+ - status: \"Searching “empty”.\"\n@@ -36 +36,5 @@\n- - generic \"Search response controls\" [ref=e12]\n+ - generic [ref=e11]:\n+ - generic \"Search response controls\" [ref=e12]\n+ - button \"Resolve 3 (empty): results\" [ref=e38]\n+ - button \"Resolve 3 (empty): empty\" [ref=e39]\n+ - button \"Resolve 3 (empty): failure\" [ref=e40]\n", + "ok": true + }, + { + "id": "search-selection-removed", + "at": "2026-09-08T02:07:03.577Z", + "expected": { + "results": [], + "detail": null, + "active": "query", + "searchStatus": "No results for “empty”. Try another query. Previous selection is unavailable." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "empty", + "searchStatus": "No results for “empty”. Try another query. Previous selection is unavailable.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -25 +25 @@\n- - status: \"Searching “empty”.\"\n+ - status: \"No results for “empty”. Try another query. Previous selection is unavailable.\"\n@@ -27,14 +27,2 @@\n- - list:\n- - listitem \"B · 1\" [ref=e32]:\n- - button \"B · 1\" [ref=e33]\n- - listitem \"B · 2\" [ref=e34]:\n- - button \"B · 2\" [ref=e35]\n- - article \"B · 2\" [ref=e36]:\n- - heading \"B · 2\" [level=3]\n- - text: \"Details for B · 2. Query and selection survive window resizing.\"\n- - button \"Back to results\" [ref=e37]\n- - generic [ref=e11]:\n- - generic \"Search response controls\" [ref=e12]\n- - button \"Resolve 3 (empty): results\" [ref=e38]\n- - button \"Resolve 3 (empty): empty\" [ref=e39]\n- - button \"Resolve 3 (empty): failure\" [ref=e40]\n+ - list\n+ - generic \"Search response controls\" [ref=e12]\n@@ -63 +51,3 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n+- iframe:\n+ - button \"Open selection tools\" [ref=f1e1]\n", + "ok": true + }, + { + "id": "search-retry-submit", + "at": "2026-09-08T02:07:03.585Z", + "expected": { + "searchStatus": "Searching “empty”." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "empty", + "searchStatus": "Searching “empty”.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -25 +25 @@\n- - status: \"No results for “empty”. Try another query. Previous selection is unavailable.\"\n+ - status: \"Searching “empty”.\"\n@@ -28 +28,5 @@\n- - generic \"Search response controls\" [ref=e12]\n+ - generic [ref=e11]:\n+ - generic \"Search response controls\" [ref=e12]\n+ - button \"Resolve 4 (empty): results\" [ref=e41]\n+ - button \"Resolve 4 (empty): empty\" [ref=e42]\n+ - button \"Resolve 4 (empty): failure\" [ref=e43]\n", + "ok": true + }, + { + "id": "search-failure", + "at": "2026-09-08T02:07:03.895Z", + "expected": { + "results": [], + "searchStatus": "Search “empty” failed. Previous results retained; retry the search." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -25 +25 @@\n- - status: \"Searching “empty”.\"\n+ - status: \"Search “empty” failed. Previous results retained; retry the search.\"\n@@ -28,5 +28 @@\n- - generic [ref=e11]:\n- - generic \"Search response controls\" [ref=e12]\n- - button \"Resolve 4 (empty): results\" [ref=e41]\n- - button \"Resolve 4 (empty): empty\" [ref=e42]\n- - button \"Resolve 4 (empty): failure\" [ref=e43]\n+ - generic \"Search response controls\" [ref=e12]\n", + "ok": true + }, + { + "id": "inventory-open", + "at": "2026-09-08T02:07:04.206Z", + "expected": { + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -23 +23 @@\n- - textbox \"Search query\" [ref=e9] [focused]: \"empty\"\n+ - textbox \"Search query\" [ref=e9]: \"empty\"\n@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44] [checked] [focused]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45]\n+ - text: \"Item B\"\n+- text: \"Selected: A. Equipped: none.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "decision-open", + "at": "2026-09-08T02:07:04.519Z", + "expected": { + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "active": "cancel-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "cancel-equip", + "activeText": "Close decision", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -53 +53 @@\n- - radio \"Item A\" [ref=e44] [checked] [focused]\n+ - radio \"Item A\" [ref=e44] [checked]\n@@ -61,0 +61,4 @@\n+- heading \"Equip item A?\" [level=2]\n+- text: \"This changes the equipped item.\"\n+- button \"Start equipment request\" [ref=e48]\n+- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "decision-tab-wrap", + "at": "2026-09-08T02:07:04.526Z", + "expected": { + "active": "confirm-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "confirm-equip", + "activeText": "Start equipment request", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -63,2 +63,2 @@\n-- button \"Start equipment request\" [ref=e48]\n-- button \"Close decision\" [ref=e49] [focused]\n+- button \"Start equipment request\" [ref=e48] [focused]\n+- button \"Close decision\" [ref=e49]\n", + "ok": true + }, + { + "id": "decision-reverse-wrap", + "at": "2026-09-08T02:07:04.533Z", + "expected": { + "active": "cancel-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "cancel-equip", + "activeText": "Close decision", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -63,2 +63,2 @@\n-- button \"Start equipment request\" [ref=e48] [focused]\n-- button \"Close decision\" [ref=e49]\n+- button \"Start equipment request\" [ref=e48]\n+- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "cancel-one-layer", + "at": "2026-09-08T02:07:04.614Z", + "expected": { + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -53 +53 @@\n- - radio \"Item A\" [ref=e44] [checked]\n+ - radio \"Item A\" [ref=e44] [checked] [focused]\n@@ -61,4 +61,0 @@\n-- heading \"Equip item A?\" [level=2]\n-- text: \"This changes the equipped item.\"\n-- button \"Start equipment request\" [ref=e48]\n-- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "cancel-second-layer", + "at": "2026-09-08T02:07:04.620Z", + "expected": { + "openDialogs": [], + "active": "open-inventory" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44] [checked] [focused]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45]\n- - text: \"Item B\"\n-- text: \"Selected: A. Equipped: none.\"\n-- button \"Equip selected item\" [ref=e46]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "inventory-reopen", + "at": "2026-09-08T02:07:04.928Z", + "expected": { + "openDialogs": [ + "inventory-dialog" + ] + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n+ - button \"Open inventory\" [ref=e14]\n@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44] [checked] [focused]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45]\n+ - text: \"Item B\"\n+- text: \"Selected: A. Equipped: none.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "equipment-A-decision", + "at": "2026-09-08T02:07:05.239Z", + "expected": { + "active": "cancel-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "cancel-equip", + "activeText": "Close decision", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none.", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -53 +53 @@\n- - radio \"Item A\" [ref=e44] [checked] [focused]\n+ - radio \"Item A\" [ref=e44] [checked]\n@@ -61,0 +61,4 @@\n+- heading \"Equip item A?\" [level=2]\n+- text: \"This changes the equipped item.\"\n+- button \"Start equipment request\" [ref=e48]\n+- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "equipment-A-request", + "at": "2026-09-08T02:07:05.554Z", + "expected": { + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request pending: A.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: A. Equipped: none. Pending: A.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item A?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none. Pending: A.", + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -32 +32 @@\n- - status: \"Equipped: none.\"\n+ - status: \"Equipment request pending: A.\"\n@@ -35,2 +35,2 @@\n- - button \"Confirm equipment request\" [ref=e17] [disabled]\n- - button \"Fail equipment request\" [ref=e18] [disabled]\n+ - button \"Confirm equipment request\" [ref=e17]\n+ - button \"Fail equipment request\" [ref=e18]\n@@ -58,2 +58,2 @@\n-- text: \"Selected: A. Equipped: none.\"\n-- button \"Equip selected item\" [ref=e46]\n+- text: \"Selected: A. Equipped: none. Pending: A.\"\n+- button \"Equip selected item\" [ref=e46] [disabled]\n@@ -62,3 +62,3 @@\n-- text: \"This changes the equipped item.\"\n-- button \"Start equipment request\" [ref=e48]\n-- button \"Close decision\" [ref=e49] [focused]\n+- text: \"Pending. Closing this view does not cancel the operation.\"\n+- button \"Start equipment request\" [ref=e48] [disabled]\n+- button \"Close decision\" [ref=e49]\n", + "ok": true + }, + { + "id": "pending-dialog-tab", + "at": "2026-09-08T02:07:05.564Z", + "expected": { + "active": "cancel-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "cancel-equip", + "activeText": "Close decision", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none. Pending: A.", + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -64 +64 @@\n-- button \"Close decision\" [ref=e49]\n+- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "equipment-close-decision-pending", + "at": "2026-09-08T02:07:05.571Z", + "expected": { + "openDialogs": [ + "inventory-dialog" + ] + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "A", + "inventoryStatus": "Selected: A. Equipped: none. Pending: A.", + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -53 +53 @@\n- - radio \"Item A\" [ref=e44] [checked]\n+ - radio \"Item A\" [ref=e44] [checked] [focused]\n@@ -61,4 +61,0 @@\n-- heading \"Equip item A?\" [level=2]\n-- text: \"Pending. Closing this view does not cancel the operation.\"\n-- button \"Start equipment request\" [ref=e48] [disabled]\n-- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "select-B-while-A-pending", + "at": "2026-09-08T02:07:05.841Z", + "expected": { + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: none. Pending: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: none. Pending: A.", + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -53 +53 @@\n- - radio \"Item A\" [ref=e44] [checked] [focused]\n+ - radio \"Item A\" [ref=e44]\n@@ -56 +56 @@\n- - radio \"Item B\" [ref=e45]\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n@@ -58 +58 @@\n-- text: \"Selected: A. Equipped: none. Pending: A.\"\n+- text: \"Selected: B. Equipped: none. Pending: A.\"\n", + "ok": true + }, + { + "id": "close-before-response", + "at": "2026-09-08T02:07:06.152Z", + "expected": { + "openDialogs": [], + "active": "open-inventory" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: none. Pending: A.", + "equipmentStatus": "Equipment request pending: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n- - text: \"Item B\"\n-- text: \"Selected: B. Equipped: none. Pending: A.\"\n-- button \"Equip selected item\" [ref=e46] [disabled]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "equipment-A-after-close", + "at": "2026-09-08T02:07:06.465Z", + "expected": { + "openDialogs": [], + "selected": "B", + "equipmentStatus": "Equipped: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: A.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: none. Pending: A.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item A?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: none. Pending: A.", + "equipmentStatus": "Equipped: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31,2 +31,2 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n- - status: \"Equipment request pending: A.\"\n+ - button \"Open inventory\" [ref=e14]\n+ - status: \"Equipped: A.\"\n@@ -35,2 +35,2 @@\n- - button \"Confirm equipment request\" [ref=e17]\n- - button \"Fail equipment request\" [ref=e18]\n+ - button \"Confirm equipment request\" [ref=e17] [disabled]\n+ - button \"Fail equipment request\" [ref=e18] [disabled]\n", + "ok": true + }, + { + "id": "equipment-reconcile", + "at": "2026-09-08T02:07:06.776Z", + "expected": { + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipped: A.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n+ - text: \"Item B\"\n+- text: \"Selected: B. Equipped: A.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "equipment-B-decision", + "at": "2026-09-08T02:07:07.090Z", + "expected": { + "active": "cancel-equip" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "cancel-equip", + "activeText": "Close decision", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipped: A.", + "equipDisabled": false, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -56 +56 @@\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n+ - radio \"Item B\" [ref=e45] [checked]\n@@ -61,0 +61,4 @@\n+- heading \"Equip item B?\" [level=2]\n+- text: \"This changes the equipped item.\"\n+- button \"Start equipment request\" [ref=e48]\n+- button \"Close decision\" [ref=e49] [focused]\n", + "ok": true + }, + { + "id": "equipment-B-request", + "at": "2026-09-08T02:07:07.419Z", + "expected": { + "equipmentStatus": "Equipment request pending: B." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request pending: B.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: A. Pending: B.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item B?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog", + "equip-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A. Pending: B.", + "equipmentStatus": "Equipment request pending: B.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -32 +32 @@\n- - status: \"Equipped: A.\"\n+ - status: \"Equipment request pending: B.\"\n@@ -35,2 +35,2 @@\n- - button \"Confirm equipment request\" [ref=e17] [disabled]\n- - button \"Fail equipment request\" [ref=e18] [disabled]\n+ - button \"Confirm equipment request\" [ref=e17]\n+ - button \"Fail equipment request\" [ref=e18]\n@@ -58,2 +58,2 @@\n-- text: \"Selected: B. Equipped: A.\"\n-- button \"Equip selected item\" [ref=e46]\n+- text: \"Selected: B. Equipped: A. Pending: B.\"\n+- button \"Equip selected item\" [ref=e46] [disabled]\n@@ -62,3 +62,3 @@\n-- text: \"This changes the equipped item.\"\n-- button \"Start equipment request\" [ref=e48]\n-- button \"Close decision\" [ref=e49] [focused]\n+- text: \"Pending. Closing this view does not cancel the operation.\"\n+- button \"Start equipment request\" [ref=e48] [disabled]\n+- button \"Close decision\" [ref=e49]\n", + "ok": true + }, + { + "id": "equipment-B-close-decision", + "at": "2026-09-08T02:07:07.427Z", + "expected": { + "openDialogs": [ + "inventory-dialog" + ] + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A. Pending: B.", + "equipmentStatus": "Equipment request pending: B.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -56 +56 @@\n- - radio \"Item B\" [ref=e45] [checked]\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n@@ -61,4 +61,0 @@\n-- heading \"Equip item B?\" [level=2]\n-- text: \"Pending. Closing this view does not cancel the operation.\"\n-- button \"Start equipment request\" [ref=e48] [disabled]\n-- button \"Close decision\" [ref=e49]\n", + "ok": true + }, + { + "id": "equipment-B-close-inventory", + "at": "2026-09-08T02:07:07.435Z", + "expected": { + "openDialogs": [] + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A. Pending: B.", + "equipmentStatus": "Equipment request pending: B.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n- - text: \"Item B\"\n-- text: \"Selected: B. Equipped: A. Pending: B.\"\n-- button \"Equip selected item\" [ref=e46] [disabled]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "equipment-failure-retains-A", + "at": "2026-09-08T02:07:07.742Z", + "expected": { + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request failed. Equipped: A. Reopen inventory to retry.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward ready.\n Rewards granted: 0\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: A. Pending: B.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item B?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A. Pending: B.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31,2 +31,2 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n- - status: \"Equipment request pending: B.\"\n+ - button \"Open inventory\" [ref=e14]\n+ - status: \"Equipment request failed. Equipped: A. Reopen inventory to retry.\"\n@@ -35,2 +35,2 @@\n- - button \"Confirm equipment request\" [ref=e17]\n- - button \"Fail equipment request\" [ref=e18]\n+ - button \"Confirm equipment request\" [ref=e17] [disabled]\n+ - button \"Fail equipment request\" [ref=e18] [disabled]\n", + "ok": true + }, + { + "id": "repeated-inventory-open-1", + "at": "2026-09-08T02:07:08.055Z", + "expected": { + "inventoryStatus": "Selected: B. Equipped: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n+ - text: \"Item B\"\n+- text: \"Selected: B. Equipped: A.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "repeated-inventory-close-1", + "at": "2026-09-08T02:07:08.063Z", + "expected": { + "openDialogs": [], + "active": "open-inventory" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n- - text: \"Item B\"\n-- text: \"Selected: B. Equipped: A.\"\n-- button \"Equip selected item\" [ref=e46]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "repeated-inventory-open-2", + "at": "2026-09-08T02:07:08.384Z", + "expected": { + "inventoryStatus": "Selected: B. Equipped: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n+ - button \"Open inventory\" [ref=e14]\n@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n+ - text: \"Item B\"\n+- text: \"Selected: B. Equipped: A.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "repeated-inventory-close-2", + "at": "2026-09-08T02:07:08.390Z", + "expected": { + "openDialogs": [], + "active": "open-inventory" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n- - text: \"Item B\"\n-- text: \"Selected: B. Equipped: A.\"\n-- button \"Equip selected item\" [ref=e46]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "repeated-inventory-open-3", + "at": "2026-09-08T02:07:08.700Z", + "expected": { + "inventoryStatus": "Selected: B. Equipped: A." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [ + "inventory-dialog" + ], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n+ - button \"Open inventory\" [ref=e14]\n@@ -50,0 +50,11 @@\n+- heading \"Inventory\" [level=2]\n+- text: \"Selected item\"\n+- label:\n+ - radio \"Item A\" [ref=e44]\n+ - text: \"Item A\"\n+- label:\n+ - radio \"Item B\" [ref=e45] [checked] [focused]\n+ - text: \"Item B\"\n+- text: \"Selected: B. Equipped: A.\"\n+- button \"Equip selected item\" [ref=e46]\n+- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "repeated-inventory-close-3", + "at": "2026-09-08T02:07:08.707Z", + "expected": { + "openDialogs": [], + "active": "open-inventory" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "open-inventory", + "activeText": "Open inventory", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward ready.", + "rewardCount": "Rewards granted: 0", + "claimDisabled": false, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14]\n+ - button \"Open inventory\" [ref=e14] [focused]\n@@ -50,11 +50,0 @@\n-- heading \"Inventory\" [level=2]\n-- text: \"Selected item\"\n-- label:\n- - radio \"Item A\" [ref=e44]\n- - text: \"Item A\"\n-- label:\n- - radio \"Item B\" [ref=e45] [checked] [focused]\n- - text: \"Item B\"\n-- text: \"Selected: B. Equipped: A.\"\n-- button \"Equip selected item\" [ref=e46]\n-- button \"Close inventory\" [ref=e47]\n", + "ok": true + }, + { + "id": "reward-granted-before-reveal", + "at": "2026-09-08T02:07:09.033Z", + "expected": { + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request failed. Equipped: A. Reopen inventory to retry.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received. Revealing…\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: A.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item B?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received. Revealing…", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": false, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -31 +31 @@\n- - button \"Open inventory\" [ref=e14] [focused]\n+ - button \"Open inventory\" [ref=e14]\n@@ -39,4 +39,4 @@\n- - button \"Claim reward\" [ref=e20]\n- - button \"Skip reveal\" [ref=e21] [disabled]\n- - status: \"Reward ready.\"\n- - text: \"Rewards granted: 0\"\n+ - button \"Claim reward\" [ref=e20] [disabled]\n+ - button \"Skip reveal\" [ref=e21]\n+ - status: \"Reward received. Revealing…\"\n+ - text: \"Rewards granted: 1\"\n", + "ok": true + }, + { + "id": "reward-skip-once", + "at": "2026-09-08T02:07:09.342Z", + "expected": { + "rewardCount": "Rewards granted: 1", + "rewardStatus": "Reward received.", + "skipDisabled": true, + "active": "reward-status" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "reward-status", + "activeText": "Reward received.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -40,2 +40,2 @@\n- - button \"Skip reveal\" [ref=e21]\n- - status: \"Reward received. Revealing…\"\n+ - button \"Skip reveal\" [ref=e21] [disabled]\n+ - status [focused]: \"Reward received.\"\n", + "ok": true + }, + { + "id": "disclosure-enter", + "at": "2026-09-08T02:07:09.351Z", + "expected": { + "disclosure": true + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "Delivery restrictions", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": true, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -23 +23,0 @@\n- - textbox \"Search query\" [ref=e9]: \"empty\"\n@@ -41 +40 @@\n- - status [focused]: \"Reward received.\"\n+ - status: \"Reward received.\"\n@@ -45 +44 @@\n- - generic \"Delivery restrictions\" [ref=e24]\n+ - generic \"Delivery restrictions Some destinations need an additional delivery day.\" [ref=e23]\n", + "ok": true + }, + { + "id": "disclosure-space", + "at": "2026-09-08T02:07:09.357Z", + "expected": { + "disclosure": false + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "Delivery restrictions", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -44 +44 @@\n- - generic \"Delivery restrictions Some destinations need an additional delivery day.\" [ref=e23]\n+ - generic \"Delivery restrictions\" [ref=e24] [focused]\n", + "ok": true + }, + { + "id": "range-keyboard", + "at": "2026-09-08T02:07:09.365Z", + "expected": { + "position": "51", + "positionStatus": "Committed position: 51" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "position", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -44 +44 @@\n- - generic \"Delivery restrictions\" [ref=e24] [focused]\n+ - generic \"Delivery restrictions\" [ref=e24]\n@@ -46 +46 @@\n- - textbox \"Preview position\" [ref=e25]: \"50\"\n+ - textbox \"Preview position\" [ref=e25] [focused]: \"51\"\n@@ -48 +48 @@\n- - status: \"Committed position: 50\"\n+ - status: \"Committed position: 51\"\n", + "ok": true + }, + { + "id": "range-pointer-start", + "at": "2026-09-08T02:07:09.386Z", + "expected": { + "position": "51" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "position", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "range-pointer-preview", + "at": "2026-09-08T02:07:09.402Z", + "expected": { + "position": "75", + "positionStatus": "Preview position: 75. Committed: 51." + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "position", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "75", + "positionStatus": "Preview position: 75. Committed: 51.", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -46 +46 @@\n- - textbox \"Preview position\" [ref=e25] [focused]: \"51\"\n+ - textbox \"Preview position\" [ref=e25] [focused]: \"75\"\n@@ -48 +48 @@\n- - status: \"Committed position: 51\"\n+ - status: \"Preview position: 75. Committed: 51.\"\n", + "ok": true + }, + { + "id": "range-cancel-preview", + "at": "2026-09-08T02:07:09.408Z", + "expected": { + "position": "51", + "positionStatus": "Committed position: 51" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "position", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -46 +46 @@\n- - textbox \"Preview position\" [ref=e25] [focused]: \"75\"\n+ - textbox \"Preview position\" [ref=e25] [focused]: \"51\"\n@@ -48 +48 @@\n- - status: \"Preview position: 75. Committed: 51.\"\n+ - status: \"Committed position: 51\"\n", + "ok": true + }, + { + "id": "range-release-after-cancel", + "at": "2026-09-08T02:07:09.413Z", + "expected": { + "position": "51", + "positionStatus": "Committed position: 51" + }, + "actual": { + "draft": "B", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "position", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "long-draft", + "at": "2026-09-08T02:07:09.421Z", + "expected": {}, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "B", + "saveDisabled": false, + "saveStatus": "Unsaved changes.", + "saveError": "", + "active": "draft", + "activeText": "", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11,0 +11 @@\n+ - textbox \"Display name\" [ref=e2] [focused]: \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n@@ -12,2 +13,2 @@\n- - button \"Save name\" [ref=e3] [disabled]\n- - status: \"All changes saved.\"\n+ - button \"Save name\" [ref=e3]\n+ - status: \"Unsaved changes.\"\n@@ -23,0 +24 @@\n+ - textbox \"Search query\" [ref=e9]: \"empty\"\n@@ -46 +48 @@\n- - textbox \"Preview position\" [ref=e25] [focused]: \"51\"\n+ - textbox \"Preview position\" [ref=e25]: \"51\"\n@@ -50 +52 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "long-draft-submit", + "at": "2026-09-08T02:07:09.729Z", + "expected": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름" + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "B", + "saveDisabled": true, + "saveStatus": "Saving “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n Saving “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\n Confirmed name: B\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request failed. Equipped: A. Reopen inventory to retry.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 51\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: A.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item B?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11 @@\n- - textbox \"Display name\" [ref=e2] [focused]: \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n+ - textbox \"Display name\" [ref=e2]: \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n@@ -13,2 +13,2 @@\n- - button \"Save name\" [ref=e3]\n- - status: \"Unsaved changes.\"\n+ - button \"Save name\" [ref=e3] [disabled]\n+ - status: \"Saving “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6] [disabled]\n- - button \"Fail save\" [ref=e7] [disabled]\n+ - button \"Confirm save\" [ref=e6]\n+ - button \"Fail save\" [ref=e7]\n@@ -52 +52 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "long-draft-confirm", + "at": "2026-09-08T02:07:10.039Z", + "expected": { + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름" + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: 긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Search “empty” failed. Previous results retained; retry the search.\n \n Results\n \n B · 2\n Details for B · 2. Query and selection survive window resizing.\n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipment request failed. Equipped: A. Reopen inventory to retry.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 51\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n Selected: B. Equipped: A.\n \n Equip selected item\n Close inventory\n \n \n \n Equip item B?\n Pending. Closing this view does not cancel the operation.\n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n1Password menu is available. Press down arrow to select.", + "query": "empty", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -14,2 +14,2 @@\n- - status: \"Saving “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\"\n- - text: \"Confirmed name: B\"\n+ - status: \"All changes saved.\"\n+ - text: \"Confirmed name: 긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n@@ -18,2 +18,2 @@\n- - button \"Confirm save\" [ref=e6]\n- - button \"Fail save\" [ref=e7]\n+ - button \"Confirm save\" [ref=e6] [disabled]\n+ - button \"Fail save\" [ref=e7] [disabled]\n", + "ok": true + }, + { + "id": "long-query", + "at": "2026-09-08T02:07:10.048Z", + "expected": {}, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Search “empty” failed. Previous results retained; retry the search.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -24 +24 @@\n- - textbox \"Search query\" [ref=e9]: \"empty\"\n+ - textbox \"Search query\" [ref=e9] [focused]: \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n@@ -52 +52 @@\n-- status: \"1Password menu is available. Press down arrow to select.\"\n+- status\n", + "ok": true + }, + { + "id": "long-query-submit", + "at": "2026-09-08T02:07:10.057Z", + "expected": {}, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Searching “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -26 +26 @@\n- - status: \"Search “empty” failed. Previous results retained; retry the search.\"\n+ - status: \"Searching “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\"\n@@ -29 +29,5 @@\n- - generic \"Search response controls\" [ref=e12]\n+ - generic [ref=e11]:\n+ - generic \"Search response controls\" [ref=e12]\n+ - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e50]\n+ - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e51]\n+ - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e52]\n", + "ok": true + }, + { + "id": "long-query-results", + "at": "2026-09-08T02:07:10.387Z", + "expected": { + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ] + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "@@ -11 +11,0 @@\n- - textbox \"Display name\" [ref=e2]: \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름\"\n@@ -26 +25 @@\n- - status: \"Searching “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\"\n+ - status: \"Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.\"\n@@ -28,6 +27,6 @@\n- - list\n- - generic [ref=e11]:\n- - generic \"Search response controls\" [ref=e12]\n- - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e50]\n- - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e51]\n- - button \"Resolve 5 (긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이\" [ref=e52]\n+ - list:\n+ - listitem \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴\" [ref=e53]:\n+ - button \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴\" [ref=e54]\n+ - listitem \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴\" [ref=e55]:\n+ - button \"긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴\" [ref=e56]\n+ - generic \"Search response controls\" [ref=e12]\n@@ -56 +55 @@\n-- status\n+- status: \"1Password menu is available. Press down arrow to select.\"\n", + "ok": true + }, + { + "id": "long-content-320", + "at": "2026-09-08T02:07:10.399Z", + "expected": { + "viewport": 320, + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "long-content-375", + "at": "2026-09-08T02:07:10.408Z", + "expected": { + "viewport": 375, + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 375, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "long-content-768", + "at": "2026-09-08T02:07:10.416Z", + "expected": { + "viewport": 768, + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 768, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "long-content-1024", + "at": "2026-09-08T02:07:10.422Z", + "expected": { + "viewport": 1024, + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1024, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "long-content-1440", + "at": "2026-09-08T02:07:10.427Z", + "expected": { + "viewport": 1440, + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 1440, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "rtl-320", + "at": "2026-09-08T02:07:10.436Z", + "expected": { + "overflow": false + }, + "actual": { + "draft": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "persisted": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "query", + "activeText": "", + "query": "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름", + "searchStatus": "Results for “긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름”.", + "results": [ + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 1", + "긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름긴이름 · 2" + ], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "B", + "inventoryStatus": "Selected: B. Equipped: A.", + "equipmentStatus": "Equipment request failed. Equipped: A. Reopen inventory to retry.", + "equipDisabled": true, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "51", + "positionStatus": "Committed position: 51", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + }, + { + "id": "motion-reveal-start", + "at": "2026-09-08T02:07:10.962Z", + "expected": { + "rewardStatus": "Reward received. Revealing…", + "skipDisabled": false + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received. Revealing…\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward received. Revealing…", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": false, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 1, + "viewport": 320, + "overflow": false + }, + "snapshot": "@@ -11 +11,0 @@\n- - textbox \"Display name\" [ref=e2]: \"Original\"\n@@ -24 +23,0 @@\n- - textbox \"Search query\" [ref=e9]\n@@ -40,4 +38,4 @@\n- - button \"Claim reward\" [ref=e20]\n- - button \"Skip reveal\" [ref=e21] [disabled]\n- - status: \"Reward ready.\"\n- - text: \"Rewards granted: 0\"\n+ - button \"Claim reward\" [ref=e20] [disabled]\n+ - button \"Skip reveal\" [ref=e21]\n+ - status: \"Reward received. Revealing…\"\n+ - text: \"Rewards granted: 1\"\n", + "ok": true + }, + { + "id": "motion-preference-during-reveal", + "at": "2026-09-08T02:07:11.007Z", + "expected": { + "motion": "Motion: reduced. Status changes immediately.", + "animations": 0, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "skipDisabled": true + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: reduced. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: reduced. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "@@ -5 +5 @@\n- - status: \"Motion: normal. Status changes immediately.\"\n+ - status: \"Motion: reduced. Status changes immediately.\"\n@@ -39,2 +39,2 @@\n- - button \"Skip reveal\" [ref=e21]\n- - status: \"Reward received. Revealing…\"\n+ - button \"Skip reveal\" [ref=e21] [disabled]\n+ - status: \"Reward received.\"\n", + "ok": true + }, + { + "id": "reduced-motion-from-entry", + "at": "2026-09-08T02:07:11.400Z", + "expected": { + "animations": 0, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "skipDisabled": true + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: reduced. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: reduced. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "@@ -11 +11,0 @@\n- - textbox \"Display name\" [ref=e2]: \"Original\"\n@@ -24 +23,0 @@\n- - textbox \"Search query\" [ref=e9]\n@@ -40 +38 @@\n- - button \"Claim reward\" [ref=e20]\n+ - button \"Claim reward\" [ref=e20] [disabled]\n@@ -42,2 +40,2 @@\n- - status: \"Reward ready.\"\n- - text: \"Rewards granted: 0\"\n+ - status: \"Reward received.\"\n+ - text: \"Rewards granted: 1\"\n", + "ok": true + }, + { + "id": "preference-return-to-normal", + "at": "2026-09-08T02:07:11.470Z", + "expected": { + "motion": "Motion: normal. Status changes immediately.", + "rewardCount": "Rewards granted: 1" + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "@@ -5 +5 @@\n- - status: \"Motion: reduced. Status changes immediately.\"\n+ - status: \"Motion: normal. Status changes immediately.\"\n", + "ok": true + }, + { + "id": "no-runtime-errors", + "at": "2026-09-08T02:07:11.474Z", + "expected": { + "openDialogs": [], + "overflow": false + }, + "actual": { + "draft": "Original", + "persisted": "Original", + "saveDisabled": true, + "saveStatus": "All changes saved.", + "saveError": "", + "active": "", + "activeText": "\n \n StyleGallery · executable examples\n Interaction lab\n Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.\n Motion: normal. Status changes immediately.\n \n \n \n 1. Save without losing later edits\n \n Display name\n \n \n Save name\n \n All changes saved.\n Confirmed name: Original\n \n Save response controls\n \n Confirm save\n Fail save\n \n \n \n \n 2. Search and return to the same item\n \n Search query\n \n Search items\n \n Enter a query.\n \n Results\n \n \n \n Back to results\n \n \n \n Search response controls\n \n \n \n \n 3. Inventory and nested decisions\n Open inventory\n Equipped: none.\n \n Equipment response controls\n \n Confirm equipment request\n Fail equipment request\n \n \n \n \n 4. A reward independent of its reveal\n \n Claim reward\n Skip reveal\n \n Reward received.\n Rewards granted: 1\n \n \n 5. Disclosure and direct manipulation\n \n Delivery restrictions\n Some destinations need an additional delivery day.\n \n Preview position\n \n Drag or use arrow keys. Release commits; Escape cancels an active preview.\n Committed position: 50\n \n \n \n Inventory\n \n Selected item\n Item A\n Item B\n \n \n \n Equip selected item\n Close inventory\n \n \n \n \n \n \n Start equipment request\n Close decision\n \n \n Example only. Reload resets data. Browser behavior is distinct from native engine and service behavior.\n\n\n", + "query": "", + "searchStatus": "Enter a query.", + "results": [], + "detail": null, + "listVisible": true, + "openDialogs": [], + "selected": "A", + "inventoryStatus": "", + "equipmentStatus": "Equipped: none.", + "equipDisabled": false, + "rewardStatus": "Reward received.", + "rewardCount": "Rewards granted: 1", + "claimDisabled": true, + "skipDisabled": true, + "disclosure": false, + "position": "50", + "positionStatus": "Committed position: 50", + "motion": "Motion: normal. Status changes immediately.", + "animations": 0, + "viewport": 320, + "overflow": false + }, + "snapshot": "No changes detected\n", + "ok": true + } + ], + "errors": [], + "captures": [ + "native-desktop.png", + "detail-375.png", + "nested-dialogs.png", + "long-rtl-320.png", + "reduced-motion-320.png" + ], + "captureMetrics": [ + { + "file": "native-desktop.png", + "cssViewport": { + "x": 0, + "y": 0, + "width": 1440, + "height": 900 + }, + "pixels": { + "width": 2880, + "height": 1800 + } + }, + { + "file": "detail-375.png", + "cssViewport": { + "x": 0, + "y": 800.5, + "width": 375, + "height": 900 + }, + "pixels": { + "width": 750, + "height": 1800 + } + }, + { + "file": "nested-dialogs.png", + "cssViewport": { + "x": 0, + "y": 779, + "width": 1440, + "height": 900 + }, + "pixels": { + "width": 2880, + "height": 1800 + } + }, + { + "file": "long-rtl-320.png", + "cssViewport": { + "x": 0, + "y": 1352, + "width": 320, + "height": 900 + }, + "pixels": { + "width": 640, + "height": 1800 + } + }, + { + "file": "reduced-motion-320.png", + "cssViewport": { + "x": 0, + "y": 1347.5, + "width": 320, + "height": 900 + }, + "pixels": { + "width": 640, + "height": 1800 + } + } + ], + "failure": null, + "ok": true +} \ No newline at end of file diff --git a/examples/domain-interactions/evidence/sources.json b/examples/domain-interactions/evidence/sources.json new file mode 100644 index 0000000..a658a92 --- /dev/null +++ b/examples/domain-interactions/evidence/sources.json @@ -0,0 +1,27 @@ +{ + "kind": "working-tree-source-snapshot", + "base_revision": "d8bdf0bd5b5aec2fbc38e322a9ac7a1d31fd1332", + "uncommitted_sources": true, + "files": [ + { + "path": "examples/domain-interactions/index.html", + "sha256": "4c6280a9f720b546c2c6bc6c252dd8603764c71868b1cc3df091de39651228ab", + "bytes": 4922 + }, + { + "path": "examples/domain-interactions/styles.css", + "sha256": "016f98025a98cb612f3730e3df013f8f6b4aebe467db9fb4464b9b37d7b923cd", + "bytes": 1832 + }, + { + "path": "examples/domain-interactions/app.mjs", + "sha256": "d802165599b917fc8d9bebf38e4f62d733552c44de47dc988ca6e64041f26eb9", + "bytes": 11538 + }, + { + "path": "examples/domain-interactions/qa.aside.js", + "sha256": "dfda27544710f975eccab6aeb7bb51f38aff3e0bab9b7381b3fa41472c49e070", + "bytes": 15750 + } + ] +} diff --git a/examples/domain-interactions/index.html b/examples/domain-interactions/index.html new file mode 100644 index 0000000..0f98b38 --- /dev/null +++ b/examples/domain-interactions/index.html @@ -0,0 +1,114 @@ + + + + + + StyleGallery interaction lab + + + + + +
+

StyleGallery · executable examples

+

Interaction lab

+

Explore state, interruption, and recovery. All data stays in memory; response controls simulate a service.

+

+
+
+
+

1. Save without losing later edits

+
+ + + + +
+

+

Confirmed name:

+
+ Save response controls +
+ + +
+
+
+
+

2. Search and return to the same item

+
+ + + +
+

Enter a query.

+
+

Results

    + +
    +
    + Search response controls +
    +
    +
    +
    +

    3. Inventory and nested decisions

    + +

    Equipped: none.

    +
    + Equipment response controls +
    + + +
    +
    +
    +
    +

    4. A reward independent of its reveal

    +
    + + +
    +

    Reward ready.

    +

    Rewards granted: 0

    +
    +
    +

    5. Disclosure and direct manipulation

    +
    + Delivery restrictions +

    Some destinations need an additional delivery day.

    +
    + + +

    Drag or use arrow keys. Release commits; Escape cancels an active preview.

    +

    Committed position: 50

    +
    +
    + +

    Inventory

    +
    + Selected item + + +
    +

    +
    + + +
    +
    + +

    +

    +
    + + +
    +
    + + + diff --git a/examples/domain-interactions/qa.aside.js b/examples/domain-interactions/qa.aside.js new file mode 100644 index 0000000..e06f99e --- /dev/null +++ b/examples/domain-interactions/qa.aside.js @@ -0,0 +1,199 @@ +// Execute inside Aside REPL after opening this example and reading its snapshot. +// This uses the real browser tab. Size/preference overrides are scoped to that tab. +async function runInteractionQA() { + if (!/\/examples\/domain-interactions\/(?:[?#].*)?$/.test(page.url())) throw Error("Open the interaction lab first."); + const started = new Date().toISOString(); + const checks = []; + const errors = []; + const captures = []; + const captureMetrics = []; + const onError = (error) => errors.push(String(error)); + page.on("pageerror", onError); + const cdp = async (method, params = {}) => page.cdp.send(method, params, await page.resolveSessionId()); + const runtime = await cdp("Browser.getVersion"); + const base = page.url().replace(/[?#].*$/, ""); + const sources = await (await fetch(`${base}evidence/sources.json`)).json(); + const artifactRoot = `artifacts/domain-interactions-${Date.now()}`; + await fs.mkdir(artifactRoot, { recursive: true }); + const state = () => page.evaluate(() => { + const e = (id) => document.getElementById(id); + return { + draft: e("draft").value, persisted: e("persisted").textContent, + saveDisabled: e("save").disabled, saveStatus: e("save-status").textContent, saveError: e("save-error").textContent, + active: document.activeElement.id, activeText: document.activeElement.textContent, + query: e("query").value, searchStatus: e("search-status").textContent, + results: [...e("results").querySelectorAll("button")].map((b) => b.textContent), + detail: e("detail").hidden ? null : e("detail-heading").textContent, + listVisible: getComputedStyle(e("search-list")).display !== "none", + openDialogs: [...document.querySelectorAll("dialog[open]")].map((d) => d.id), + selected: document.querySelector("input[name=item]:checked").value, + inventoryStatus: e("inventory-status").textContent, equipmentStatus: e("equipment-status").textContent, + equipDisabled: e("confirm-equip").disabled, + rewardStatus: e("reward-status").textContent, rewardCount: e("reward-count").textContent, + claimDisabled: e("claim-reward").disabled, skipDisabled: e("skip-reveal").disabled, + disclosure: e("delivery").open, position: e("position").value, positionStatus: e("position-status").textContent, + motion: e("motion-preference").textContent, animations: document.getAnimations().length, + viewport: innerWidth, overflow: document.documentElement.scrollWidth > document.documentElement.clientWidth, + }; + }); + const check = async (id, action, expected) => { + await action(); + const view = await snapshot(page); + console.log(view.diff); + const actual = await state(); + const mismatches = Object.keys(expected).filter((key) => JSON.stringify(actual[key]) !== JSON.stringify(expected[key])); + checks.push({ id, at: new Date().toISOString(), expected, actual, snapshot: view.diff, ok: mismatches.length === 0 }); + console.log(JSON.stringify({ id, ok: mismatches.length === 0, mismatches })); + if (mismatches.length) throw Error(`${id}: ${JSON.stringify({ expected, actual })}`); + }; + const click = (id, target, expected) => check(id, () => page.locator(target).click(), expected); + const fill = (id, target, value, expected = {}) => check(id, () => page.locator(target).fill(value), expected); + const key = (id, target, value, expected) => check(id, () => page.locator(target).press(value), expected); + const escape = (id, expected) => check(id, () => page.keyboard.press("Escape"), expected); + const result = (id, name, expected) => check(id, () => page.getByRole("button", { name, exact: true }).click(), expected); + const size = (width, height = 900) => cdp("Emulation.setDeviceMetricsOverride", { width, height, deviceScaleFactor: 1, mobile: false }); + const preference = async (value) => { + await cdp("Emulation.setEmulatedMedia", { features: [{ name: "prefers-reduced-motion", value }] }); + // CDP acknowledges the override before the browser dispatches matchMedia's change. + await page.evaluate(() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve())))); + }; + const reset = async () => { + await page.goto(base); + await page.waitForSelector("#save:disabled"); + console.log((await snapshot(page)).tree); + }; + const capture = async (name) => { + // Explicit bounds avoid capturing the native backing surface after a size override. + const clip = await page.evaluate(() => ({ x: scrollX, y: scrollY, width: innerWidth, height: innerHeight })); + const bytes = await page.screenshot({ path: `${artifactRoot}/${name}.png`, clip }); + const pixels = { width: bytes.readUInt32BE(16), height: bytes.readUInt32BE(20) }; + if (Math.abs(pixels.width / clip.width - pixels.height / clip.height) > .01) throw Error("Screenshot dimensions do not match the observed viewport."); + captures.push(`${name}.png`); + captureMetrics.push({ file: `${name}.png`, cssViewport: clip, pixels }); + }; + let failure = null; + try { + await preference("no-preference"); + await cdp("Emulation.clearDeviceMetricsOverride"); + await reset(); + await check("native-desktop-start", async () => {}, { persisted: "Original", saveDisabled: true, overflow: false }); + await capture("native-desktop"); + await fill("save-edit-A", "#draft", "A", { saveDisabled: false }); + await click("save-submit-A", "#save", { saveDisabled: true, saveStatus: "Saving “A”." }); + await fill("save-edit-B-during-A", "#draft", "B", { saveStatus: "Saving “A”. Later edits are unsaved." }); + await key("save-ignore-duplicate", "#draft", "Enter", { saveStatus: "Saving “A”. Later edits are unsaved." }); + await click("save-A-preserves-B", "#save-success", { persisted: "A", draft: "B", saveStatus: "Unsaved changes.", saveDisabled: false }); + await click("save-B-submit", "#save", { saveStatus: "Saving “B”." }); + await click("save-failure-retains-draft", "#save-failure", { persisted: "A", draft: "B", saveError: "Save failed. Your draft is retained; try again." }); + await click("save-retry", "#save", { saveStatus: "Saving “B”.", saveError: "" }); + await click("save-retry-success", "#save-success", { persisted: "B", draft: "B", saveDisabled: true }); + await fill("save-empty", "#draft", ""); + await click("save-required-error", "#save", { active: "draft", saveError: "Enter a display name.", persisted: "B" }); + await fill("save-recover-validity", "#draft", "B", { saveError: "", saveDisabled: true }); + + await fill("search-query-A", "#query", "A"); + await key("search-submit-A", "#query", "Enter", { searchStatus: "Searching “A”." }); + await fill("search-query-B", "#query", "B"); + await key("search-submit-B", "#query", "Enter", { searchStatus: "Searching “B”." }); + await result("search-B-before-A", "Resolve 2 (B): results", { results: ["B · 1", "B · 2"] }); + await result("search-stale-A-ignored", "Resolve 1 (A): results", { results: ["B · 1", "B · 2"], searchStatus: "Results for “B”." }); + await result("search-select-detail", "B · 2", { detail: "B · 2", active: "detail-heading" }); + for (const width of [320, 375, 768, 1024, 1440]) { + await check(`selected-detail-${width}`, () => size(width), { viewport: width, query: "B", detail: "B · 2", active: "detail-heading", listVisible: width > 640, overflow: false }); + if (width === 375) await capture("detail-375"); + } + await click("detail-parent-return", "#back-results", { detail: null, activeText: "B · 2" }); + await check("detail-browser-forward", async () => { + // Aside's navigation waiter expects a load event, but this is same-document history. + const history = await cdp("Page.getNavigationHistory"); + const next = history.entries[history.currentIndex + 1]; + if (!next) throw Error("Missing forward history entry."); + await cdp("Page.navigateToHistoryEntry", { entryId: next.id }); + }, { detail: "B · 2", active: "detail-heading" }); + await fill("search-empty-query", "#query", "empty"); + await key("search-empty-submit", "#query", "Enter", { searchStatus: "Searching “empty”." }); + await result("search-selection-removed", "Resolve 3 (empty): empty", { results: [], detail: null, active: "query", searchStatus: "No results for “empty”. Try another query. Previous selection is unavailable." }); + await key("search-retry-submit", "#query", "Enter", { searchStatus: "Searching “empty”." }); + await result("search-failure", "Resolve 4 (empty): failure", { results: [], searchStatus: "Search “empty” failed. Previous results retained; retry the search." }); + + await click("inventory-open", "#open-inventory", { openDialogs: ["inventory-dialog"], selected: "A" }); + await click("decision-open", "#equip-item", { openDialogs: ["inventory-dialog", "equip-dialog"], active: "cancel-equip" }); + await key("decision-tab-wrap", "#cancel-equip", "Tab", { active: "confirm-equip" }); + await key("decision-reverse-wrap", "#confirm-equip", "Shift+Tab", { active: "cancel-equip" }); + await capture("nested-dialogs"); + await escape("cancel-one-layer", { openDialogs: ["inventory-dialog"], selected: "A" }); + await escape("cancel-second-layer", { openDialogs: [], active: "open-inventory" }); + await click("inventory-reopen", "#open-inventory", { openDialogs: ["inventory-dialog"] }); + await click("equipment-A-decision", "#equip-item", { active: "cancel-equip" }); + await click("equipment-A-request", "#confirm-equip", { equipmentStatus: "Equipment request pending: A.", equipDisabled: true }); + await key("pending-dialog-tab", "#cancel-equip", "Tab", { active: "cancel-equip" }); + await escape("equipment-close-decision-pending", { openDialogs: ["inventory-dialog"] }); + await check("select-B-while-A-pending", () => page.getByRole("radio", { name: "Item B", exact: true }).check(), { selected: "B", inventoryStatus: "Selected: B. Equipped: none. Pending: A." }); + await click("close-before-response", "#close-inventory", { openDialogs: [], active: "open-inventory" }); + await click("equipment-A-after-close", "#equip-success", { openDialogs: [], selected: "B", equipmentStatus: "Equipped: A." }); + await click("equipment-reconcile", "#open-inventory", { selected: "B", inventoryStatus: "Selected: B. Equipped: A." }); + await click("equipment-B-decision", "#equip-item", { active: "cancel-equip" }); + await click("equipment-B-request", "#confirm-equip", { equipmentStatus: "Equipment request pending: B." }); + await escape("equipment-B-close-decision", { openDialogs: ["inventory-dialog"] }); + await escape("equipment-B-close-inventory", { openDialogs: [] }); + await click("equipment-failure-retains-A", "#equip-failure", { equipmentStatus: "Equipment request failed. Equipped: A. Reopen inventory to retry." }); + for (let n = 1; n <= 3; n++) { + await click(`repeated-inventory-open-${n}`, "#open-inventory", { inventoryStatus: "Selected: B. Equipped: A." }); + await escape(`repeated-inventory-close-${n}`, { openDialogs: [], active: "open-inventory" }); + } + + await click("reward-granted-before-reveal", "#claim-reward", { rewardCount: "Rewards granted: 1", claimDisabled: true, skipDisabled: false }); + await click("reward-skip-once", "#skip-reveal", { rewardCount: "Rewards granted: 1", rewardStatus: "Reward received.", skipDisabled: true, active: "reward-status" }); + await key("disclosure-enter", "#delivery summary", "Enter", { disclosure: true }); + // Explicit key code is needed for Space's native default action in Aside. + await check("disclosure-space", async () => { + await cdp("Input.dispatchKeyEvent", { type: "keyDown", key: " ", code: "Space", windowsVirtualKeyCode: 32, text: " " }); + await cdp("Input.dispatchKeyEvent", { type: "keyUp", key: " ", code: "Space", windowsVirtualKeyCode: 32 }); + }, { disclosure: false }); + await key("range-keyboard", "#position", "ArrowRight", { position: "51", positionStatus: "Committed position: 51" }); + const range = await page.locator("#position").boundingBox(); + await check("range-pointer-start", async () => { await page.mouse.move(range.x + range.width * .51, range.y + range.height / 2); await page.mouse.down(); }, { position: "51" }); + await check("range-pointer-preview", () => page.mouse.move(range.x + range.width * .75, range.y + range.height / 2), { position: "75", positionStatus: "Preview position: 75. Committed: 51." }); + await escape("range-cancel-preview", { position: "51", positionStatus: "Committed position: 51" }); + await check("range-release-after-cancel", () => page.mouse.up(), { position: "51", positionStatus: "Committed position: 51" }); + + const longLabel = "긴이름".repeat(100); + await fill("long-draft", "#draft", longLabel); + await click("long-draft-submit", "#save", { draft: longLabel }); + await click("long-draft-confirm", "#save-success", { persisted: longLabel }); + await fill("long-query", "#query", longLabel); + await key("long-query-submit", "#query", "Enter", {}); + await check("long-query-results", async () => { + const response = page.locator("#search-responses > div:last-child > button:first-child"); + if (await response.textContent() !== `Resolve 5 (${longLabel}): results`) throw Error("Unexpected long-query response control."); + await response.click(); + }, { results: [`${longLabel} · 1`, `${longLabel} · 2`] }); + for (const width of [320, 375, 768, 1024, 1440]) await check(`long-content-${width}`, () => size(width), { viewport: width, overflow: false }); + await check("rtl-320", async () => { + await size(320); + // A declared content-fixture mutation, not an interaction shortcut. + await page.evaluate(() => { document.documentElement.dir = "rtl"; }); + }, { overflow: false }); + await capture("long-rtl-320"); + + await reset(); + await click("motion-reveal-start", "#claim-reward", { rewardStatus: "Reward received. Revealing…", skipDisabled: false }); + await check("motion-preference-during-reveal", () => preference("reduce"), { motion: "Motion: reduced. Status changes immediately.", animations: 0, rewardStatus: "Reward received.", rewardCount: "Rewards granted: 1", skipDisabled: true }); + await reset(); + await click("reduced-motion-from-entry", "#claim-reward", { animations: 0, rewardStatus: "Reward received.", rewardCount: "Rewards granted: 1", skipDisabled: true }); + await capture("reduced-motion-320"); + await check("preference-return-to-normal", () => preference("no-preference"), { motion: "Motion: normal. Status changes immediately.", rewardCount: "Rewards granted: 1" }); + await check("no-runtime-errors", async () => { if (errors.length) throw Error(JSON.stringify(errors)); }, { openDialogs: [], overflow: false }); + } catch (error) { + failure = String(error); + } finally { + await cdp("Emulation.clearDeviceMetricsOverride"); + await cdp("Emulation.setEmulatedMedia", { features: [] }); + page.off("pageerror", onError); + const report = { kind: "local-browser-observation", started, finished: new Date().toISOString(), runtime, sources, inputs: ["automated keyboard events", "automated pointer events"], emulation: "Viewport sizes and media preferences only; no mobile hardware emulation or touch claim.", checks, errors, captures, captureMetrics, failure, ok: !failure && errors.length === 0 && checks.every((entry) => entry.ok) }; + await fs.writeFile(`${artifactRoot}/report.json`, JSON.stringify(report, null, 2)); + console.log(JSON.stringify({ artifactRoot, checks: checks.length, ok: report.ok, failure })); + } + if (failure) throw Error(failure); +} +await runInteractionQA(); diff --git a/examples/domain-interactions/styles.css b/examples/domain-interactions/styles.css new file mode 100644 index 0000000..2a4f5b4 --- /dev/null +++ b/examples/domain-interactions/styles.css @@ -0,0 +1,46 @@ +/* Product-layer demonstration styles; not reusable Layout pattern CSS. */ +:root { + color: #182331; + background: #f3f5f7; + font: 100%/1.5 system-ui, sans-serif; +} +* { box-sizing: border-box; } +body { margin: 0; padding: 1rem; } +header, main, footer { margin-inline: auto; max-inline-size: 65rem; } +h1 { font-size: clamp(2rem, 5vw, 3.5rem); line-height: 1.1; } +h2 { font-size: 1.35rem; } +section, dialog { + background: white; + border: 1px solid #9eaebe; + border-radius: .5rem; + margin-block: 1rem; + padding: 1rem; +} +section, article, p, strong, button { overflow-wrap: anywhere; } +form, fieldset { display: grid; gap: .65rem; } +input, button, summary { font: inherit; } +input:not([type="radio"]), button { min-block-size: 2.75rem; } +input:not([type="radio"]) { inline-size: 100%; min-inline-size: 0; } +button { + background: #173f69; + border: 1px solid #173f69; + border-radius: .25rem; + color: white; + cursor: pointer; + padding: .5rem .9rem; +} +button:disabled { background: #e0e6ed; border-color: #788b9e; color: #3a4857; cursor: default; } +:focus-visible { outline: 3px solid #a23c00; outline-offset: 3px; } +summary { cursor: pointer; padding-block: .65rem; } +.actions { display: flex; flex-wrap: wrap; gap: .75rem; } +.search-panes { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } +.search-panes > * { min-inline-size: 0; } +ul { display: grid; gap: .5rem; padding-inline-start: 1.5rem; } +dialog { margin: auto; max-block-size: 90dvh; max-inline-size: min(34rem, calc(100% - 2rem)); overflow: auto; } +dialog::backdrop { background: rgb(15 25 40 / 55%); } +[hidden] { display: none !important; } +[role="alert"] { color: #9d270a; } +@media (max-width: 40rem) { + .search-panes { grid-template-columns: minmax(0, 1fr); } + .search-panes[data-view="detail"] #search-list { display: none; } +} diff --git a/examples/domain-interactions/verification.md b/examples/domain-interactions/verification.md new file mode 100644 index 0000000..e6b185c --- /dev/null +++ b/examples/domain-interactions/verification.md @@ -0,0 +1,80 @@ +--- +type: Verification Record +title: Interaction Lab Local Browser Verification +description: Source-bound observations from a real Mac browser, with explicit mock-service and native-device limitations. +--- + +# Interaction Lab Local Browser Verification + +The [Interaction Lab](README.md) completed 84 action/observation checkpoints on 2026-09-08 with all expected-state comparisons passing and zero observed JavaScript runtime errors. [report.json](evidence/report.json) contains the ordered actions, expected and actual states, snapshots, runtime identity, and capture dimensions. This is a local browser observation of an uncommitted example, not a canonical consumer-reference capture or independent attestation. + +The final run finished at `2026-09-08T02:07:11.475Z` (`11:07:11` KST). The [artifact manifest](evidence/manifest.json) records the host inventory and the hashes and byte lengths of the report, source snapshot, and five screenshots. + +## Environment And Source + +| Field | Observed value | +| --- | --- | +| Physical host | Local Mac, hardware identifier `Mac16,8`, `arm64` | +| Host OS | macOS `26.5.1`, build `25F80`, read with `sw_vers` | +| Browser | Aside-controlled Chrome `151.0.7922.171`, JavaScript `15.1.206.21` | +| Tooling | Aside CLI `1.26.906.1630`; repository-required `aside-browser` skill | +| Input | Automated keyboard and pointer events in the real browser tab | +| Initial surface | Native desktop browser viewport; exact observed width is in the first report checkpoint | +| Size fixtures | 320, 375, 768, 1024, 1440 CSS pixels in the same desktop browser | +| Preferences | Tab-scoped reduced-motion media override, changed during an active reward reveal and before entry | +| Data | In-memory mock responses, no external service or persistence | +| Source | [sources.json](evidence/sources.json): base Git revision plus SHA-256/byte length for HTML, CSS, application, and QA source | + +The browser's reduced User-Agent string reports Intel/macOS 10.15.7; that is not the hardware/OS inventory above. Small viewport fixtures do not turn this run into an iPhone or Android device test. Media emulation verifies the web preference handler, not the operating system's settings UI. + +## Results + +| Behavior | Actual observation | +| --- | --- | +| Draft and persistence separation | A completed while draft B remained editable and unsaved; failure retained B; retry persisted B; invalid empty input focused its error field | +| Search identity | B results survived a late A response; empty results removed the selected detail; failure exposed a recovery status | +| Detail navigation | Query, selection, and logical focus survived all five sizes; parent return focused the previous result; browser forward restored detail | +| Nested modality | Tab and reverse Tab stayed in the upper dialog; one Escape closed one layer; final dismissal restored the invoker | +| Equipment lifetime | A request completed after both views closed; reopening preserved B selection and showed A equipped; a failed B request kept A | +| Repeated opening | Three additional open/close cycles retained correct selection and left no open dialog | +| Reward and preference | Exactly one local grant before reveal; skip preserved the count; reduced-motion changes completed the reveal and left zero running animations | +| Native controls | Enter and Space toggled disclosure; arrow-key range input committed; pointer preview cancelled with Escape and remained cancelled after release | +| Content | Unbroken 300-character Korean values produced no document-level horizontal overflow at all five widths; RTL at 320 also passed | + +## Issue Found And Fixed + +The initial nested dialog allowed Tab from its final button to leave the dialog. The example now handles the tab boundary in the currently active dialog, skips disabled and unchecked radio controls, and wraps forward/reverse traversal. The final run includes both directions and the pending state, where only the dismissal command remains available. + +Tooling adjustments preserve actual browser actions: Space uses an explicit CDP key code; same-document Forward uses the browser history entry because Aside's generic navigation waiter expects a document load; the long-label response control is checked by exact DOM text before activation. Screenshots use explicit observed viewport bounds and record their PNG dimensions. Unbounded captures repeated the backing surface after a size override and were rejected; they are not the retained evidence. + +## Artifacts + +- [Native desktop entry](evidence/native-desktop.png) +- [Selected detail at 375 CSS pixels](evidence/detail-375.png) +- [Nested dialog and visible focus](evidence/nested-dialogs.png) +- [Long content, RTL, 320 CSS pixels](evidence/long-rtl-320.png) +- [Reduced-motion result at 320 CSS pixels](evidence/reduced-motion-320.png) + +Raster images are viewport observations, not complete-page visual certification. The DOM report supplies states and relationships that a screenshot cannot show. The application source hashes were checked again against the report after capture. + +## Not Run + +Android hardware, iPhone/iPad hardware, Safari, Windows-native APIs, Unity/player builds, controller or touch input, VoiceOver/screen readers, haptics/audio, native predictive Back, safe-area hardware behavior, performance profiling, and real network/persistence operations were not run. No Android debugging bridge or Xcode device tools were available, and the host USB inventory listed no attached devices. Browser results cannot fill those evidence cells. + +The fictional native-engine workflow and unimplemented recipes retain their existing `not_run` status. Domain lifecycle remains `experimental`; no consumer adoption or lifecycle transition is claimed. Existing immutable evidence was not recaptured or edited. + +## README Compatibility Repair + +The shared agent-native README changed in commit `d8bdf0bd5b5aec2fbc38e322a9ac7a1d31fd1332` to add Material v2 guidance and correct the domain count. The v1 compatibility test still required its earlier digest. The test now separately pins that reviewed documentation revision to `6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e`. + +All 21 original core/source digests, six CLI byte-output goldens, registry records, schemas, and runtime interfaces retain their previous values. `npm run test:agent-native` passed after the repair. The README content itself was not rewritten to satisfy the old hash. + +Implementation handoff: `consumer_reference: consumer-reference/agent-native/registry.json`. No design-terminology term/relation records are used by this runtime implementation. + +Consumer reference: declared +Consumer reference record: consumer-reference/agent-native/registry.json + +## Navigation + +Parent: [Interaction Lab](README.md). +Next: [Game UI verification workflow](../../game-ui/verification-workflow.md). diff --git a/game-ui/decision-tree.md b/game-ui/decision-tree.md new file mode 100644 index 0000000..de91f48 --- /dev/null +++ b/game-ui/decision-tree.md @@ -0,0 +1,81 @@ +--- +type: Domain Guide +title: Game UI Decision Tree +description: Select player-task recipes, ownership boundaries, and engine routes from the screen's purpose. +domain: game-ui +lifecycle: experimental +provenance_kind: local +--- + +# Game UI Decision Tree + +Primary role: game screen planning route. + +## Repository Boundary + +This route selects game-interface responsibilities independently of engine and art direction. The [Classification](classification.md) remains the local taxonomy; the [Screen Hierarchy](screen-hierarchy.md) defines ownership roles. + +## Reusable Method + +1. Write the player's question while the interface is visible. +2. Choose one primary task class from the table below. +3. Decide whether play continues and which input actions must be blocked. +4. Assign lifetime, focus, sorting, and state ownership. +5. Adapt a [Screen Recipe](screen-recipes.md), then run the [Verification Workflow](verification-workflow.md). + +## Player Task Route + +| Player question | Primary class | Recipe | +| --- | --- | --- | +| What is happening during play? | `hud` | [Play status and input](screen-recipes.md#play-status-and-input) | +| How do I perform an action? | `input-surface` | [Play status and input](screen-recipes.md#play-status-and-input) | +| Where can I go, pause, or leave? | `navigation` | [Pause and navigation](screen-recipes.md#pause-and-navigation) | +| What decision requires attention? | `dialog` | [Blocking decisions and connection](screen-recipes.md#blocking-decisions-and-connection) | +| Is the game ready or connected? | `system-status` | [Blocking decisions and connection](screen-recipes.md#blocking-decisions-and-connection) | +| What can I equip or compare? | `inventory` | [Inventory and comparison](screen-recipes.md#inventory-and-comparison) | +| What have I earned or unlocked? | `progression` | [Results and progression](screen-recipes.md#results-and-progression) | +| What can I obtain, and at what cost? | `commerce` | [Offers and acquisition](screen-recipes.md#offers-and-acquisition) | +| What should I learn next? | `tutorial` | [Teaching and narrative](screen-recipes.md#teaching-and-narrative) | +| What story is being presented? | `narrative` | [Teaching and narrative](screen-recipes.md#teaching-and-narrative) | + +If a screen contains several tasks, classify regions independently. A purchase confirmation inside an inventory screen is a dialog owned by a commerce operation; it is not another inventory slot. + +## Ownership Decisions + +| Decision | Record before implementing | +| --- | --- | +| Lifetime | Application, session, scene, screen, entity, or one operation | +| Play relationship | Continues, pauses locally, or requests a networked pause; identify authority | +| Input | Active action map, focus owner, pointer/gamepad coexistence, cancellation | +| Ordering | Screen, HUD, world-linked, modal, or transient host; name competing hosts | +| Data | Authoritative state versus preview, selection, pending operation and stale data | +| Exit | What is restored, destroyed, retained, or reconciled | + +## Worked Selection + +A loadout screen shows owned equipment, character attributes, and a purchase button for an unavailable slot. Inventory is primary; comparison is a supporting region. The purchase flow is commerce and any confirmation is a modal decision. Closing the modal returns to the same slot. Losing connection updates operation status without clearing the loadout selection. A server response after the screen closes belongs to the operation owner, not a destroyed view. + +## Opinionated Guidance + +Separate the player's task from visual genre. Assign one cancellation owner for each active layer so the same Back/Cancel input does not dismiss a dialog and its parent screen together. + +## Platform-Specific Guidance + +For Unity, select the [UI System](unity/ui-systems.md), map [Architecture](unity/architecture.md), then use the [CLI Loop](unity/cli-loop.md) for the declared stack. Other engines retain these role contracts but require their own verified API mapping; no cross-engine runtime equivalence is claimed. + +## Unsupported Absolutes + +A pause menu does not imply multiplayer simulation can pause. Hierarchy order does not prove input blocking, focus, or sorting. A taxonomy label does not establish rendered behavior. + +## Verification Contract + +Check one ordinary screen, one overlay composition, and one unexpected interruption such as disconnection or scene teardown. Every active layer needs a named lifetime, input, sorting, and exit owner. Revisit the route if a real player task cannot be classified without forcing unrelated responsibilities together. + +## Source, License, And Attribution + +Locally authored route and fictional loadout case. It imports no game assets, third-party hierarchy, or engine code. + +## IA Navigation + +Parent: [Game UI](index.md). +Next: [Game UI Screen Recipes](screen-recipes.md). diff --git a/game-ui/index.md b/game-ui/index.md index 8df8815..d03d789 100644 --- a/game-ui/index.md +++ b/game-ui/index.md @@ -14,6 +14,16 @@ The player-task classes and classification axes are a local taxonomy proposed fo Interface In Game was reviewed on 2026-07-14 through its [home page](https://interfaceingame.com/), [games index](https://interfaceingame.com/games/), and representative records for [Team Fortress 2](https://interfaceingame.com/games/team-fortress-2/), [Genshin Impact (Mobile)](https://interfaceingame.com/games/genshin-impact-mobile/), and [Gris](https://interfaceingame.com/games/gris/). In this bounded sample, the site exposed site-local facets such as Genres, Themes, and Platforms, while screenshots used Elements. The sample informs the local separation of player task from other axes; it does not cover the archive or establish the site's full information model. +## Start Here + +| Task | Route | +| --- | --- | +| Choose by player task and ownership. | [Game UI Decision Tree](decision-tree.md) | +| Compose all ten player-task classes with failure cases. | [Game UI Screen Recipes](screen-recipes.md) | +| Record input, state, hierarchy, and teardown evidence. | [Game UI Verification Workflow](verification-workflow.md) | + +These workflows and worked cases are usable experimental guidance. Expected-result tables are test designs; actual product, engine, and reader evidence must be recorded separately. Review on a failed task, a source change, or a changed ownership contract. + ## Available Guides - [Game UI Classification](classification.md) separates player purpose from visual language, input, state, and motion. @@ -32,4 +42,4 @@ Game UI describes interface purpose, screen composition, and how named engines c ## IA Navigation Parent: [StyleGallery](../index.md). -Next: [Game UI Classification](classification.md). +Next: [Game UI Decision Tree](decision-tree.md). diff --git a/game-ui/screen-recipes.md b/game-ui/screen-recipes.md new file mode 100644 index 0000000..fef11b8 --- /dev/null +++ b/game-ui/screen-recipes.md @@ -0,0 +1,101 @@ +--- +type: Domain Guide +title: Game UI Screen Recipes +description: Engine-neutral screen compositions with player task, lifetime, input, state, recovery, and acceptance cases. +domain: game-ui +lifecycle: experimental +provenance_kind: local +--- + +# Game UI Screen Recipes + +Primary role: game screen composition catalog. + +## Repository Boundary + +These are fictional compositions of [Screen Hierarchy](screen-hierarchy.md) roles. They prescribe no engine tree, artwork, or reusable Layout CSS. Use the [Decision Tree](decision-tree.md) to select by player task; record real references with the [Reference Record](reference-record.md). + +## Reusable Method + +For the selected recipe, name the persistent owner, screen or entity owner, active input recipient, exceptional states, and exit behavior. Each acceptance case below is an expected result awaiting consumer execution. + +## Play Status And Input + +Primary classes: `hud` and separately classified `input-surface` regions. A session-owned HUD presents player status, objectives, and contextual prompts. Entity-linked markers follow entity lifetime; virtual controls own their active press/drag state. HUD data observes gameplay authority rather than predicting confirmed rewards or inventory changes. + +Keep critical state understandable when an effect is absent. Distinguish zero value from unavailable data. Record how spectator, respawn, controller disconnection, and menus change visibility and input routing. + +Acceptance case: open a blocking menu while an action is held; release the action, close the menu, and confirm no stuck input remains. Destroy a marked entity and confirm its marker and subscriptions are removed. + +## Pause And Navigation + +Primary class: `navigation`. A screen host owns destinations; a pause overlay owns its focus scope and return target. The simulation/session owner decides whether play pauses. Audio, background input, and timers have explicit policies. + +Preserve navigation selection when opening settings and returning. Loading a new destination invalidates old screen callbacks. Cancel should consume one active layer at a time. + +Acceptance case: pause → settings → confirmation → cancel three times. Verify each step closes only the intended layer and restores the previous selection. For network play, verify the UI does not claim the world is paused when it continues. + +## Blocking Decisions And Connection + +Primary classes: `dialog` or `system-status`. A modal host owns blocking and focus; a connection service owns retry state. Keep message, available actions, retry state, and outcome distinct. Only block input that conflicts with the required decision. + +Reconnection success must reconcile the current screen, which may differ from the screen present at failure. A retry response from an earlier attempt cannot dismiss a newer failure. Define whether a system notice supersedes, queues behind, or composes with an existing modal. + +Acceptance case: lose connection during an inventory operation, open a system notice, then receive an old retry response. The current error/operation state remains authoritative and dismissal leaves no invisible blocker. + +## Inventory And Comparison + +Primary class: `inventory`. A screen owns filters, selection, and focus history. The data service owns item identity and confirmed equipment; a detail region owns the selected item's presentation. List/grid cells receive explicit data and selection state. + +Compare by stable item identity, not cell position. Separate selected, equipped, unavailable, pending, and failed states. Preserve selection where possible after filtering or sorting; document a fallback when the item disappears. + +Acceptance case: select item A, request equip, select B, then resolve A. A's result updates inventory truth while detail remains on B. Test empty inventory, maximum content, long localized attributes, and a disabled first item. + +## Results And Progression + +Primary class: `progression`. The completed-match/session record owns final values; presentation may stage reveal of those values. Reveal completion does not grant rewards. Skip reveals the confirmed final state once; replaying a presentation cannot duplicate a grant. + +Distinguish provisional, confirmed, and unavailable results. Preserve a readable result summary after a flourish. A disconnected client must not present an unconfirmed reward as owned. + +Acceptance case: skip twice, navigate away, and reopen results. The grant count stays unchanged, and the same authoritative result is shown. Test zero rewards and a reward list longer than the visible region. + +## Offers And Acquisition + +Primary class: `commerce`. The catalog owns offer identity, the purchase service owns transaction outcome, and the UI owns selection and acknowledgement. Show the item, total cost, currency, and eligibility before commitment. Pending, rejected, cancelled, expired, and fulfilled are different states. + +Do not derive success from a button effect or optimistic currency subtraction. Reconcile price/availability changes before accepting a commitment. Duplicate input must follow the transaction contract. + +Acceptance case: change availability between selection and submission, fail a request, and retry. The UI explains the current offer and never reports an unconfirmed acquisition. Actual payments and platform purchasing rules require consumer-specific verification. + +## Teaching And Narrative + +Primary classes: `tutorial` or `narrative`. A step/story controller owns progress; presentation owns text, highlight, voice/subtitle synchronization, and skip controls. Identify whether gameplay continues and whether a teaching step intentionally restricts input. + +A tutorial must explain a usable alternative when the expected device is absent. Narrative skip semantics distinguish advancing one line, finishing a scene, and suppressing future presentation. Progress must not depend only on a reveal animation finishing. + +Acceptance case: switch input mode midway through a tutorial, interrupt dialogue with a system modal, and return. Prompts match the current input, the story/step index remains correct, and required instructions can still be read. + +## Opinionated Guidance + +Keep screens thin enough that authoritative data survives their teardown when needed. Give each modal, transient effect, and world marker an explicit owner even when they share visual treatment. + +## Platform-Specific Guidance + +Map roles through the engine-specific guides. Safe areas, scaling, text shaping, controller focus, and accessibility capabilities require the actual engine, version, and target platform. A browser prototype is not evidence of console or engine behavior. + +## Unsupported Absolutes + +These recipes are not a universal game UX taxonomy, tested architecture, or proof of accessibility. A successful screenshot cannot prove operation integrity, input isolation, or teardown. + +## Verification Contract + +Run the chosen acceptance case with every declared input, target aspect ratios/safe areas, long localization, error/empty states, and interruptions. Record observed results in the [Verification Workflow](verification-workflow.md). `consumer_reference: not_applicable` applies here because these fictional compositions select no consumer record. Review when a runtime observation contradicts an ownership or recovery rule. + +## Source, License, And Attribution + +Locally authored fictional recipes with no copied game assets or implementation. Player classes and hierarchy roles come from this domain's local contracts. + +## IA Navigation + +Parent: [Game UI](index.md). +Next: [Game UI Verification Workflow](verification-workflow.md). diff --git a/game-ui/verification-workflow.md b/game-ui/verification-workflow.md new file mode 100644 index 0000000..d67b848 --- /dev/null +++ b/game-ui/verification-workflow.md @@ -0,0 +1,100 @@ +--- +type: Domain Guide +title: Game UI Verification Workflow +description: Convert a screen recipe into repeatable input, state, hierarchy, and teardown evidence. +domain: game-ui +lifecycle: experimental +provenance_kind: local +--- + +# Game UI Verification Workflow + +Primary role: game-interface acceptance and evidence procedure. + +## Repository Boundary + +This workflow verifies a declared game-interface contract on a named runtime. It does not authenticate third-party captures or convert a hypothetical recipe into a real gallery reference. Shared [Quality Gates](../quality/index.md) determine what a claim's evidence can support. + +## Reusable Method + +1. Select a [Screen Recipe](screen-recipes.md), build/version, scene, starting data, and supported inputs. +2. Record the active hierarchy's lifetime, input, sorting, focus, and teardown owners. +3. Reset to known state before each scenario. Name any non-resettable external dependency. +4. Execute actions in order, including an exception or interruption. +5. Compare expected and actual state, selection, input recipient, and surviving objects. +6. Save artifacts with source/build identity; classify pass, fail, not-run, or not-applicable with a reason. + +## Minimum Scenario Matrix + +| Dimension | Scenario | Inspect | +| --- | --- | --- | +| Entry | Open by each supported input | Correct screen and initial focus/selection | +| Navigation | Visit first, middle, last, and unavailable actions | Predictable order, visible target, no unreachable required action | +| Modality | Open overlay above a screen, then another interruption | Exactly the intended input recipient; world input policy | +| Cancellation | Back/Cancel during entry, request, and exit | One-layer dismissal; no click-through or stale blocker | +| Content | Empty, long localized text, unbroken identifiers, many rows | Readable critical information and reachable actions | +| Surface | Target aspect ratios, safe areas, scaled UI, constrained window | No obscured controls or accidental scroll ownership | +| Data | Delay, fail, supersede, and complete requests out of order | Current identities and truthful operation status | +| Device | Switch/disconnect a claimed input device | Updated prompts and a viable recovery action | +| Lifetime | Reopen repeatedly and change scene/session | No duplicate handlers, surviving blockers, or stale view updates | + +This is a selection matrix. A title that supports no touch input records touch as not applicable; it does not claim a touch pass. + +## Worked Scenario: Inventory With Confirmation + +Precondition: local fictional test data has two items, A and B. The inventory is open with A selected; no real commerce operation is involved. + +| Step | Action | Expected observation | +| --- | --- | --- | +| 1 | Navigate to B and open its action dialog | B remains selected beneath the dialog; focus enters the dialog | +| 2 | Press Cancel once | Only the dialog closes; focus/selection returns to B | +| 3 | Reopen and trigger a delayed operation | Dialog exposes pending state and the declared duplicate-input behavior | +| 4 | Close/change the screen, then resolve the operation | Data owner reconciles the result; destroyed views do not update | +| 5 | Reopen inventory | Confirmed data appears; selection follows the documented restore policy | + +Actual result: `not_run`. This procedure is a test design, not engine execution evidence. + +A separate [web inventory adaptation](../examples/domain-interactions/README.md) exercises nested dismissal, delayed equipment responses after view closure, selection restoration, and reward reveal. Its [local browser results](../examples/domain-interactions/verification.md) are browser evidence only. The native-engine scenario above remains `not_run`. + +## Evidence Record Template + +```yaml +scenario: inventory-dialog-return +build_revision: # immutable source/build identity +runtime: # engine, UI stack, packages, OS, device +surface: # resolution, aspect ratio, safe area, UI scale, locale +input: # exercised mode and device +precondition: # scene, data, selection, connectivity +actions: # ordered, reproducible steps +expected: # visible state plus hierarchy/input assertions +actual: not_run +artifacts: # capture, recording, hierarchy trace, operation log +limitations: # missing channels, device scope, mocked dependencies +consumer_reference: not_applicable +consumer_reference_reason: This blank procedure selects no consumer-owned reference record. +``` + +## Opinionated Guidance + +Capture hierarchy and input evidence together when a screenshot could hide the failure. A visually dismissed overlay with an active blocker is a failed dismissal, regardless of its appearance. + +## Platform-Specific Guidance + +For Unity use the source-pinned [CLI Loop](unity/cli-loop.md) and its UI-stack-specific capabilities. If a runner cannot inspect focus or controller routing, mark those checks not-run and collect them on the real engine surface. + +## Unsupported Absolutes + +A successful editor inspection does not prove player-build behavior. Mocked operation responses do not prove a live service works. Device and accessibility coverage must be named explicitly. + +## Verification Contract + +A completed record binds actions and actual outcomes to a build and runtime, includes exceptional-state evidence, and lists missing coverage. Failed required cases need remediation and rerun. A real gallery entry must also satisfy the [Reference Record](reference-record.md). Review when input routing, engine version, hierarchy ownership, or the recipe changes. + +## Source, License, And Attribution + +Locally authored test procedure and fictional inventory scenario. No real game reference, asset license, or runtime result is implied. + +## IA Navigation + +Parent: [Game UI](index.md). +Next: [Game UI Reference Record](reference-record.md). diff --git a/guides/vocabulary.md b/guides/vocabulary.md index e740018..898bb6d 100644 --- a/guides/vocabulary.md +++ b/guides/vocabulary.md @@ -15,7 +15,7 @@ Primary role: vocabulary and scannability contract. - Canonical: `domain` - Concept: top-level knowledge ownership - Definition: A governed StyleGallery decision surface with a named scope, exclusions, lifecycle, source-of-truth, validator, and review owner. - - Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, root routing, and `domain` frontmatter on governed leaves. + - Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, Design Terminology, root routing, and `domain` frontmatter on governed leaves. - Canonical: `category` - Concept: domain-local browse placement - Definition: A canonical grouping inside one domain; it cannot change the owning domain or its evidence boundary. diff --git a/index.md b/index.md index 7b36d1a..d4b21f5 100644 --- a/index.md +++ b/index.md @@ -4,7 +4,7 @@ okf_version: "0.1" # StyleGallery -StyleGallery is an OKF-style knowledge bundle organized into governed interface-knowledge domains. Existing Layout paths remain canonical while Motion, Design Engineering, Game UI, and Platform Guides own separate product and reference boundaries. +StyleGallery is an OKF-style knowledge bundle organized into governed interface-knowledge domains. Existing Layout paths remain canonical while Motion, Design Engineering, Game UI, Platform Guides, and Design Terminology own separate product and reference boundaries. Primary role: OKF bundle map. @@ -16,6 +16,7 @@ Primary role: OKF bundle map. - [Design Engineering](design-engineering/index.md) - Product-layer interface-craft decisions and verification questions. - [Game UI](game-ui/index.md) - Game-interface classification, hierarchy, reference records, and named engine implementation guides. - [Platform Guides](platform-guides/index.md) - Bounded comparative references for named platforms. +- [Design Terminology](design-terminology/index.md) - Source-kind and concept-family classification, typed term relations, and cross-system conflict cases for named vocabulary sources. - [Consumer reference](consumer-reference/index.md) - Shared non-domain receiver contract for declared repository-local JSON records or reasoned non-applicability. - [Agent-Native StyleGallery](consumer-reference/agent-native/README.md) - Machine-facing identity, retrieval, operation, CLI, read-only MCP, task projection, and governed-learning contracts. - [Consumer migration readiness](design-engineering/consumer-migration-readiness.md) - Experimental Design Engineering method for consumer-owned conformance, runtime proof, and source-bound page evidence. @@ -34,3 +35,11 @@ Primary role: OKF bundle map. - [Quality gates](quality/index.md) - Principle-backed gates for admissible layout and design evidence claims. - [Consumer migration evidence gate](quality/gates/consumer-migration-evidence.md) - Blocking contract for declared migration evidence. - [Update log](log.md) - Bundle update history. + +## Applied Workflows + +- [Motion Decision Tree](motion/decision-tree.md) - Choose a behavior from the user task. +- [Design Engineering Decision Tree](design-engineering/decision-tree.md) - Route the uncertain product decision. +- [Game UI Decision Tree](game-ui/decision-tree.md) - Choose by player task and ownership. +- [Platform Adaptation Workflow](platform-guides/adaptation-workflow.md) - Record native facts, target decisions, and fallbacks. +- [Design Term Comparison Workflow](design-terminology/comparison-workflow.md) - Resolve a source-specific question and produce a scoped handoff. diff --git a/log.md b/log.md index e64b689..cbe23cd 100644 --- a/log.md +++ b/log.md @@ -1,7 +1,30 @@ # StyleGallery Log +## 2026-09-08 + +- Added fourteen local guides across the five non-Layout domains: task selection, motion briefs and recipes, component contracts and worked examples, game screen recipes and verification, Apple/Android/Windows adaptation, and terminology comparison. +- Connected the guides through domain hubs and root routes, declared their membership/provenance, and included them in the closed 147-document material index and npm package. Layout retains its existing 46 patterns and spatial boundaries. +- Replaced unsupported aggregate term records with directly sourced records; corrected representation direction and the confusion between composition and set containment. The Markdown validator now checks dates, source locators, labels, scoped direction, temporal relations, inverse consistency, and containment cycles with negative fixtures. +- Examples remain expected behavior rather than claimed runtime evidence. Domain leaves remain `experimental`; no lifecycle promotion or consumer adoption is claimed. + +- Follow-up runtime work added the [Interaction Lab](examples/domain-interactions/README.md), a standalone web adaptation with explicit mock responses. Its [verification notes](examples/domain-interactions/verification.md) bind actual browser observations to local source hashes and separate desktop execution from simulated viewport sizes, untested mobile devices, and untested native engines. Fixed the lab's modal Tab boundary after observing focus escape in the real browser. +- Fixed the v1 compatibility suite's stale README digest. Commit `d8bdf0bd5b5aec2fbc38e322a9ac7a1d31fd1332` had added material-v2 guidance and corrected the domain count without updating the test. The exact reviewed documentation digest is now checked separately; all 21 original core/source pins and six CLI output goldens remain unchanged. `npm run test:agent-native` passes. +- Integrated the current domain lifecycle policy from `main`: reader tasks and adoption counts do not authorize or block domain promotion. Refreshed active workflow/document seals and source-generated protocol inventories for the added validation and documentation; preserved job bytes, lifecycle decisions, external caller status, deadlines, and immutable archive bindings. + +Implementation handoff: `consumer_reference: consumer-reference/agent-native/registry.json`. + +Consumer reference: declared +Consumer reference record: consumer-reference/agent-native/registry.json + +Terminology reliance: `figma.variable`, `figma.mode`, `figma.collection`, `figma.component`, `dtcg.token`, `dtcg.group`, `dtcg.token.draft2`, `css.custom-property`, `carbon.component`, `carbon.pattern`, and `stylegallery.pattern`. Relation types used in the records: `partial_overlap`, `implementation_representation`, `not_comparable`, `same_label_different_meaning`, and `near_equivalent`. Their named Figma, DTCG, CSSWG, Carbon, and local Layout sources were rechecked on 2026-09-08; this is an author review, not independent semantic approval. Direct locators and comparison boundaries are in [Term Cases](design-terminology/conflict-cases.md). + ## 2026-08-18 +- Added Design Terminology as the sixth governed domain: source-kind and concept-family classification separated as distinct axes, a typed term relation model, freshness-bounded source vocabularies, and cross-system conflict cases with three representative scenarios. +- Added the Design Terminology domain scope decision record comparing four placement alternatives and defining the domain's independent decision surface. +- Recorded six-domain scope in the domain manifest, root routes, quality scope, controlled vocabulary domain list, and governance rows; recorded sealed-cardinality duplication as accepted technical debt in the scope decision. +- Admitted the new domain pages and scope decision into material v2 and regenerated the material registry without modifying the git index. + - Added the StyleGallery homepage example planned from a clean npm installation and verified across desktop, tablet, and mobile Chrome CDP viewports. - Added pinned Pretext text-layout measurement as an npm-installed verification dependency while keeping browser Canvas execution outside the Node CLI and MCP surfaces. - Added deterministic hero-heading line-count, DOM overflow, accessibility, console, request, and screenshot checks. diff --git a/motion/decision-tree.md b/motion/decision-tree.md new file mode 100644 index 0000000..c5e833c --- /dev/null +++ b/motion/decision-tree.md @@ -0,0 +1,68 @@ +--- +type: Domain Guide +title: Motion Decision Tree +description: Choose a motion responsibility from a user task, state change, and failure case. +domain: motion +lifecycle: experimental +provenance_kind: local +--- + +# Motion Decision Tree + +Primary role: motion selection workflow. + +## Repository Boundary + +Use this route to decide whether a product interaction needs motion and which behavior contract to write. Layout continues to own final geometry, semantic order, and scrolling. This route selects a responsibility, not a timing preset. + +## Reusable Method + +1. Write the before and after state without animation. If either is unusable, fix that state first. +2. Name the information motion would add: acknowledgement, continuity, progress, or guidance. If none is needed, use an immediate update. +3. Choose the first matching responsibility below; compose only when one transition has multiple explicit jobs. +4. Complete the [Motion Brief](motion-brief.md), including interruption and a reduced-motion path. +5. Use an [Interaction Recipe](interaction-recipes.md) and verify through the [Review Workflow](review-workflow.md). + +## Selection Table + +| Observed task | Choose | Failure to prevent | First verification | +| --- | --- | --- | --- | +| Explain an already rendered effect | [Vocabulary](vocabulary.md) | Inferring an API from appearance | Exact, ambiguous, and unknown observations | +| Acknowledge a command | [Action feedback](interaction-recipes.md#action-feedback) | Decorative feedback mistaken for successful completion | Pending, success, failure, repeated activation | +| Show or hide supporting content | [Disclosure](interaction-recipes.md#disclosure) | Hidden content retaining focus or delayed access to content | Keyboard activation and reversal | +| Enter or dismiss a modal task | [Modal transition](interaction-recipes.md#modal-transition) | Focus or input blocking tied to an animation timer | Focus entry, cancellation, return | +| Preserve identity when items move | [Reorder and filter](interaction-recipes.md#reorder-and-filter) | Visual movement changing logical reading order | Stable identity and focused-item removal | +| Explain an operation that takes time | [Progress and completion](interaction-recipes.md#progress-and-completion) | An invented percentage or success before confirmation | Delayed result, cancellation, failure | +| Follow direct manipulation | [Drag and settle](interaction-recipes.md#drag-and-settle) | A cancelled gesture committing data | Release, reversal, cancellation, alternative input | +| Decorate an idle surface | [Practice Reference](practice-reference.md) | Repetition competing with the user's task | Compare against removal and reduced motion | + +## Worked Selection + +A search result list changes after a filter selection. The task is to understand which results remain; it is not to watch every row arrive. Choose reorder/filter only if stable result identities can be preserved. Keep the filter control focused. Announce the resulting count separately from any visual interpolation. When no results remain, present an actionable empty state immediately. If identity cannot be mapped reliably, replace the list without implying continuity. + +The decision record is a proposal until tested on the consuming product. It does not establish that motion improves search comprehension. + +## Opinionated Guidance + +Prefer one explanatory event over a sequence of unrelated effects. Evaluate high-frequency interactions with realistic repetition; a first-use recording can hide accumulated cost. + +## Platform-Specific Guidance + +Choose implementation APIs only after the behavior contract. Native gestures, browser navigation, scroll timelines, and animation libraries have different cancellation and lifetime behavior. Platform adaptation starts at [Platform Guides](../platform-guides/index.md). + +## Unsupported Absolutes + +An immediate update is a valid outcome. A recipe name does not imply a spring, compositor execution, fixed duration, or proven usability improvement. + +## Verification Contract + +For the selected row, verify normal completion, interruption, repeated input, the reduced-motion path, and a failed or empty result where relevant. Record the actual outcome separately from the expected outcome. Revisit this route when a task cannot find a suitable contract or two recipes imply conflicting ownership. + +## Source, License, And Attribution + +Locally authored selection workflow based on this domain's existing vocabulary and review contracts. No external code or expressive examples are adapted. + +## IA Navigation + +Parent: [Motion](index.md). +Next: [Motion Brief](motion-brief.md). diff --git a/motion/index.md b/motion/index.md index f572eda..63c8579 100644 --- a/motion/index.md +++ b/motion/index.md @@ -8,6 +8,16 @@ In scope: naming observable motion, reviewing declared behavior, distinguishing Out of scope: universal timing or easing rules, unmeasured performance claims, and permission to add animation or decorative properties to reusable Layout pattern CSS. +## Start Here + +| Task | Route | +| --- | --- | +| Choose a behavior from the user task. | [Motion Decision Tree](decision-tree.md) | +| Record states, owners, interruption, and evidence. | [Motion Brief](motion-brief.md) | +| Apply feedback, disclosure, modal, reorder, progress, and drag contracts. | [Motion Interaction Recipes](interaction-recipes.md) | + +These workflows and worked cases are usable experimental guidance. Expected-result tables are test designs; actual product, engine, and reader evidence must be recorded separately. Review on a failed task, a source change, or a changed ownership contract. + ## Documents - [Motion Vocabulary](vocabulary.md) maps observed behavior to implementation-neutral terms while preserving ambiguity. @@ -21,4 +31,4 @@ See [StyleGallery Domains](../DOMAINS.md) for lifecycle, provenance, page member ## IA Navigation Parent: [StyleGallery](../index.md). -Next: [Motion Vocabulary](vocabulary.md). +Next: [Motion Decision Tree](decision-tree.md). diff --git a/motion/interaction-recipes.md b/motion/interaction-recipes.md new file mode 100644 index 0000000..f4f0059 --- /dev/null +++ b/motion/interaction-recipes.md @@ -0,0 +1,90 @@ +--- +type: Domain Guide +title: Motion Interaction Recipes +description: State-based product motion recipes for feedback, disclosure, modal transitions, rearrangement, progress, and dragging. +domain: motion +lifecycle: experimental +provenance_kind: local +--- + +# Motion Interaction Recipes + +Primary role: motion behavior catalog. + +## Repository Boundary + +These recipes describe product behavior and failure cases. They compose with Layout instead of supplying reusable spatial CSS or visual defaults. Start with a [Motion Brief](motion-brief.md); use [Vocabulary](vocabulary.md) for the visual effect's name. + +## Reusable Method + +Choose the task below, assign semantic and presentation owners, implement the immediate state change first, and then test any visual interpolation against that baseline. The traces below are expected behavior, not evidence of a tested implementation. + +### Action Feedback + +Use for a command whose acknowledgement and completion are different events. + +`ready → pending → success | error`; a retry is a new request. Press feedback may acknowledge input immediately, but a success treatment waits for actual confirmation. Decide explicitly whether repeated activation is ignored, queued, or replaces the request. Keep essential status available without motion. Test delayed completion, duplicate input, failure, and a response arriving after navigation. + +### Disclosure + +Use for optional content controlled by a nearby trigger. A native `details`/`summary` baseline can be enough: + +```html +
    + Delivery restrictions +

    Some destinations need an additional delivery day.

    +
    +``` + +If a custom disclosure is necessary, keep the trigger's expanded state consistent with content availability. The [APG disclosure contract](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) describes button activation and state semantics. When closing while focus is inside, move focus to an available logical target before hiding it. Test repeated toggle, long content, and removal of the trigger. Avoid fixed maximum heights that clip real content; Layout owns intrinsic sizing. + +### Modal Transition + +Use when a temporary task must block the surrounding interface. Assign one owner to opening, focus placement, blocking, cancellation, and focus return. An entrance effect may decorate this change; semantic availability must not wait for an arbitrary timeout. If exit animation is retained, define whether the dialog remains modal until cleanup and how reopening supersedes a pending close. + +The [APG modal dialog guidance](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/) supplies the web interaction baseline. Test close during entry, reopen during exit, nested overlays, trigger removal, and reduced motion. After final close there must be no surviving blocker or focus trap. + +### Reorder And Filter + +Use when the same identifiable items move or are removed. Commit the intended logical order, retain stable item keys, and interpolate presentation only where the source/destination mapping is valid. Preserve focused items; if one disappears, choose a documented neighboring item or controlling filter. Do not reorder DOM solely to produce a pleasing stagger. + +Trace: filter A → filter B → late A data → B remains current. Test empty results, long item labels, list updates during movement, keyboard navigation, and a focused item's removal. An immediate redraw is the fallback when continuity cannot be established. + +### Progress And Completion + +Use when an ongoing operation needs visible status. Show determinate progress only when backed by a meaningful measurement; otherwise use a pending state. Completion, failure, and cancellation come from the operation, independently of the progress decoration. + +Trace: pending → cancellation requested → confirmed cancelled or completed; do not promise cancellation succeeded before the operation confirms it. Essential information persists beyond a transient flourish. Use urgent alerts sparingly; [APG alert guidance](https://www.w3.org/WAI/ARIA/apg/patterns/alert/) distinguishes announcements from focus-taking dialogs. + +### Drag And Settle + +Use when direct manipulation previews a change before commitment. Separate the preview value from the committed value. Release on a valid target commits; cancellation restores or reconciles with the current model. A new gesture retargets from the presented position where continuity is intended. Provide a task-equivalent non-drag operation. + +Test release inside/outside, cancellation, pointer loss, a changing destination, and repeated reversal. Focus and the selected item must remain traceable while visual position changes. The engine or browser adapter owns gesture events; the product owns acceptance of the new value. + +## Opinionated Guidance + +For frequent operations, compare with removing motion before increasing its complexity. When two recipes compose, one controller must arbitrate the shared state rather than letting competing completion callbacks decide it. + +## Platform-Specific Guidance + +For the web, [`prefers-reduced-motion`](https://www.w3.org/TR/mediaqueries-5/#prefers-reduced-motion) is a preference signal. Define the alternative per recipe and respond to preference changes during use. API support, native gesture physics, and rendering performance require the exact target runtime. + +## Unsupported Absolutes + +These recipes establish no universal duration, spring configuration, frame rate, device coverage, or aesthetic result. A static snippet does not prove animated or assistive-technology behavior. + +## Verification Contract + +For each implemented recipe record before, intermediate, interrupted, and final states; logical order and focus; reduced-motion behavior; and completion/error cleanup. Source inspection can check declared ownership. Rendered interaction and assistive-technology behavior require the consuming application. Review when an API changes or a trace fails. + +The [Interaction Lab](../examples/domain-interactions/README.md) provides a bounded web implementation of feedback, native disclosure, modal dismissal, stale search results, reward reveal, and range-input preview. Its [verification notes](../examples/domain-interactions/verification.md) record exercised states and preferences; they do not establish coverage for every possible implementation of these recipes. + +## Source, License, And Attribution + +Locally authored recipes and HTML. The linked W3C APG pages and Media Queries Level 5 were rechecked on 2026-09-08 for the specific semantics and preference signal above. No upstream examples or timing prescriptions are copied. + +## IA Navigation + +Parent: [Motion](index.md). +Next: [Motion Review Workflow](review-workflow.md). diff --git a/motion/motion-brief.md b/motion/motion-brief.md new file mode 100644 index 0000000..f8c6c51 --- /dev/null +++ b/motion/motion-brief.md @@ -0,0 +1,89 @@ +--- +type: Domain Guide +title: Motion Brief +description: Author a product-owned transition contract with interruption, preference, and evidence requirements. +domain: motion +lifecycle: experimental +provenance_kind: local +--- + +# Motion Brief + +Primary role: motion implementation handoff template. + +## Repository Boundary + +This brief records one product-owned behavior. Its timings, distances, and treatments never become reusable Layout values. Use the [Decision Tree](decision-tree.md) before filling it in. + +## Reusable Method + +Complete every field, using `unknown` for missing observations and a reason for non-applicability. A blank field is not an accepted exception. + +```yaml +interaction: # a user action and the state it changes +purpose: # the information motion adds +frequency: # observed or estimated, with its basis +trigger: # input, data event, navigation, or scroll progress +semantic_owner: # who commits the real application state +presentation_owner: # who starts, retargets, cancels, and disposes motion +layout_owner: # final geometry and scroll responsibility +states: # initial, in-flight, completed, failed, cancelled +identity: # stable object or item key, if continuity is claimed +parameters: # product-local values and why they are being tried +interruption: # reverse, retarget, finish, or cancel, and from which state +focus_and_input: # entry, availability during motion, exit, fallback target +reduced_motion: # equivalent state/feedback without unnecessary movement +teardown: # navigation, removal, preference change, and stale callbacks +verification: # exact actions, expected outcomes, runtime and artifacts +observed_result: # not_run until evidence exists +boundary: # what those observations cannot establish +review_trigger: # source/API change, a failed case, or reader task +consumer_reference: not_applicable +consumer_reference_reason: This blank template selects no consumer reference record. +``` + +## Filled Example: Search Status Feedback + +| Field | Example decision | +| --- | --- | +| Interaction and purpose | Submit a search; distinguish waiting, zero results, results, and failure | +| Frequency | Unknown; measure in the consuming search task | +| Semantic owner | Search controller; only the active request may replace results | +| Presentation owner | Status component; progress decoration may stop independently | +| Layout owner | Consumer's result region; [Feed](../patterns/stacking/feed.md) can own vertical repetition | +| Transition | Idle → pending → results/empty/error; a new query supersedes the old request | +| Parameters | No movement needed for the baseline; a loading treatment is an optional later hypothesis | +| Interruption | Query B supersedes query A; A's late completion is ignored | +| Focus | Remains on the initiating control unless the user moves it | +| Reduced motion | Static pending text and the same final result or error | +| Teardown | Abort where supported and reject stale completion by request identity | +| Verification | Submit A, submit B, resolve B, then resolve A; B remains presented | +| Observed result | `not_run`: illustrative contract, not captured product evidence | +| Review trigger | The product changes its request lifecycle, navigation, or status announcement | + +Example handoff: `consumer_reference: not_applicable` because no profile or consumer evidence record is selected. A real consumer replaces this with its applicable repository-relative record or its own reason. + +## Opinionated Guidance + +Write cancellation before tuning curves. An animation completion callback should report presentation completion; it should not be the sole authority for network success, focus cleanup, or saving data. + +## Platform-Specific Guidance + +Record actual browser, OS, input mode, and relevant animation-library version in the consumer's verification record. A preference query indicates a requested behavior; it does not prove the implemented alternative is comfortable. + +## Unsupported Absolutes + +No fixed timing, animation technology, or one reduced-motion treatment works for every brief. A filled template is not executed evidence. + +## Verification Contract + +The brief is ready to implement when every state has an owner, every interruption has a resulting state, and every acceptance claim names an observable. Execution must add artifacts and pass/fail results. Use the [Review Workflow](review-workflow.md) for findings and retesting. + +## Source, License, And Attribution + +Locally authored template and fictional search scenario. The existing domain contracts provide its evidence boundary. + +## IA Navigation + +Parent: [Motion](index.md). +Next: [Motion Interaction Recipes](interaction-recipes.md). diff --git a/package.json b/package.json index 619e632..cb47ecd 100644 --- a/package.json +++ b/package.json @@ -47,21 +47,34 @@ "consumer-reference/agent-native/v2/schema/material-record.schema.json", "consumer-reference/contract.md", "consumer-reference/index.md", + "design-engineering/component-contract.md", "design-engineering/consumer-migration-readiness.md", + "design-engineering/decision-tree.md", "design-engineering/index.md", "design-engineering/interface-craft.md", "design-engineering/reference-profiles/governed-local/editorial/profile.json", "design-engineering/reference-profiles/governed-local/index.md", "design-engineering/reference-profiles/index.md", + "design-engineering/worked-examples.md", + "design-terminology/comparison-workflow.md", + "design-terminology/concept-families.md", + "design-terminology/conflict-cases.md", + "design-terminology/index.md", + "design-terminology/relation-types.md", + "design-terminology/source-kinds.md", + "design-terminology/source-vocabularies.md", "game-ui/classification.md", + "game-ui/decision-tree.md", "game-ui/index.md", "game-ui/reference-record.md", "game-ui/screen-hierarchy.md", + "game-ui/screen-recipes.md", "game-ui/unity/architecture.md", "game-ui/unity/cli-loop.md", "game-ui/unity/org-wiki.md", "game-ui/unity/repository-map.md", "game-ui/unity/ui-systems.md", + "game-ui/verification-workflow.md", "guides/decision-tree.md", "guides/documentation-mode-taxonomy.md", "guides/layout-brief.md", @@ -70,7 +83,10 @@ "index.md", "layout/index.md", "log.md", + "motion/decision-tree.md", "motion/index.md", + "motion/interaction-recipes.md", + "motion/motion-brief.md", "motion/practice-reference.md", "motion/review-workflow.md", "motion/vocabulary.md", @@ -130,8 +146,13 @@ "patterns/viewport-shell/scroll-body-shell.md", "patterns/viewport-shell/sticky-footer.md", "patterns/viewport-shell/sticky-header.md", + "platform-guides/adaptation-workflow.md", + "platform-guides/android-interaction.md", "platform-guides/apple-interaction.md", + "platform-guides/compatibility-matrix.md", "platform-guides/index.md", + "platform-guides/windows-interaction.md", + "quality/claim-records/design-terminology-domain-scope.md", "quality/claim-records/index.md", "quality/claim-records/samples.md", "quality/claim-records/stylegallery-multidomain-scope.md", diff --git a/platform-guides/adaptation-workflow.md b/platform-guides/adaptation-workflow.md new file mode 100644 index 0000000..2cee689 --- /dev/null +++ b/platform-guides/adaptation-workflow.md @@ -0,0 +1,76 @@ +--- +type: Domain Guide +title: Platform Adaptation Workflow +description: Compare a native convention with a target implementation through source, capability, fallback, and evidence records. +domain: platform-guides +lifecycle: experimental +provenance_kind: local +--- + +# Platform Adaptation Workflow + +Primary role: platform comparison planning and handoff. + +## Repository Boundary + +Use a platform convention as a sourced comparison for a named task. The native platform owns its convention; the target's standards and actual runtime determine the adaptation. This workflow does not make a visual imitation equivalent to native behavior. + +## Reusable Method + +1. Name the task and target: native application, browser, embedded web view, or game engine. +2. Select [Apple](apple-interaction.md), [Android](android-interaction.md), or [Windows](windows-interaction.md) by source platform. +3. Record an official source, exact page section, version or dated reading, and re-review trigger. +4. Separate the observed/native fact from the transferable interaction question. +5. Choose an adaptation and an explicit fallback using the [Compatibility Matrix](compatibility-matrix.md). +6. Execute the target-specific acceptance cases and record what was not tested. + +## Adaptation Record + +| Field | Required content | +| --- | --- | +| Task | The user action, intended outcome, and affected state | +| Source context | Platform, OS/API or documentation version, source URL/section, review date | +| Source claim | The precise native fact supported by that source | +| Target context | Browser/OS/framework/device/input and relevant versions | +| Transferable question | What problem the convention helps investigate | +| Target decision | Implement, adapt, omit, or defer with a reason | +| Capability gap | Missing API, different input model, permission, or semantic difference | +| Fallback | A complete task path when the preferred capability is absent | +| Verification | Actions, expected and actual behavior, artifacts, source/build identity | +| Freshness | Source/API change or failed observation that triggers re-review | +| Handoff | `consumer_reference` record or `not_applicable` with a reason | + +## Worked Comparison: Returning From Detail + +Native source: Android's [predictive Back documentation](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture), reviewed 2026-09-08, describes gesture preview and cancellation. Transferable question: can a person understand and cancel a return before committing it? + +Web decision: use the application's documented list/detail route and normal browser history. Restore the list's selection and relevant search state on return. Provide a visible return link where the task needs it. Do not intercept browser/system gestures merely to reproduce a preview. + +Fallback: direct entry to a detail URL has no assumed prior list history; its visible parent link goes to the known collection route. Verification cases: navigate from a filtered list, return with browser Back, enter detail directly, cancel a local dialog before leaving, and return after the selected item is removed. + +Actual result: `not_run`; this is a fictional adaptation proposal. `consumer_reference: not_applicable` because no consumer record is selected. The comparison claims neither native gesture support nor tested browser history restoration. + +## Opinionated Guidance + +Preserve the task and recovery path before reproducing the native effect. When a capability is absent, document an intentional complete alternative rather than a partially functioning control. + +## Platform-Specific Guidance + +The source platform and target platform are separate fields even when both run on the same device. A browser on Android does not expose every Android application API. A web view's embedding host may own navigation and permissions. + +## Unsupported Absolutes + +An official source establishes its own guidance, not target conformance. Similar appearance, shared vocabulary, or a matching API name is insufficient evidence of equivalent behavior. + +## Verification Contract + +A completed adaptation distinguishes source fact, local inference, target implementation, and actual observation. Verify unavailable capabilities, interrupted navigation, relevant preferences, and all claimed inputs. Re-review on a source change, target API change, or failed acceptance case; a review date alone is not proof of continuing support. + +## Source, License, And Attribution + +Locally authored comparison method and fictional example. The linked Android source was rechecked on 2026-09-08; prose and examples are independently written. Source access does not establish device execution. + +## IA Navigation + +Parent: [Platform Guides](index.md). +Next: [Platform Compatibility Matrix](compatibility-matrix.md). diff --git a/platform-guides/android-interaction.md b/platform-guides/android-interaction.md new file mode 100644 index 0000000..84a1fe4 --- /dev/null +++ b/platform-guides/android-interaction.md @@ -0,0 +1,74 @@ +--- +type: Domain Guide +title: Android Interaction As A Comparative Reference +description: Source-bounded Android Back and adaptive-window guidance with explicit web translation and failure cases. +domain: platform-guides +lifecycle: experimental +provenance_kind: local +platform: Android applications +platform_version: dated official documentation; target OS and AndroidX versions required +reviewed_on: 2026-09-08 +--- + +# Android Interaction As A Comparative Reference + +Primary role: Android platform comparison guide. + +## Repository Boundary + +This guide compares Android application behavior with a consumer's target. It does not equate Android APIs with browser APIs or prescribe Material visual treatment. Record the actual OS, AndroidX/UI stack, and target device before implementation. + +## Reusable Method + +Use the [Adaptation Workflow](adaptation-workflow.md). Choose a specific native concern below, inspect its source, then write the target behavior and fallback independently of native visuals. + +## Source-Bounded Conventions + +| Concern | Official source and bounded fact | Transferable question | +| --- | --- | --- | +| Back preview | [Predictive Back](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) describes previewing a destination and cancelling a gesture; custom handling depends on the application stack | Is the destination understandable, and does cancelling preserve the current state? | +| Back ownership | The same source describes enabled callbacks and one recipient for a Back gesture | Which active layer consumes Back, and when does control return to the outer navigation owner? | +| Window adaptation | [Window size classes](https://developer.android.com/develop/adaptive-apps/guides/use-window-size-classes) classify available application window space for adaptive decisions | Does the screen adapt to its available space while preserving selection and task state? | +| Navigation transformation | [Responsive navigation](https://developer.android.com/develop/ui/views/layout/build-responsive-navigation) discusses changing navigation presentation with window conditions | Can the user reach the same destinations after presentation changes? | + +These pages were read on 2026-09-08. They are a dated documentation set, not a pin of every Android release or package. Verify the implementation details for the selected runtime. + +## Worked Adaptation: Compact List And Expanded Detail + +Task: inspect a collection on a resizable surface. Native comparison: available window space can change the presentation. Target web decision: compose [List Detail](../recipes/list-detail.md), retain selected identity in application state, and let the Layout owner choose the fit constraint. Android's native units and class boundaries are not CSS breakpoints. + +On a tight surface, the detail route can replace the list visually while preserving the query and selection. On a roomy surface, both can be visible. Returning must resolve a missing selected item explicitly. Changing presentation must not duplicate the current route or save unrelated navigation history entries. + +| Action | Expected target behavior | +| --- | --- | +| Resize with item B selected | B remains the selected detail | +| Return to the list | Previous query remains available | +| Cancel an inner dialog | Dialog closes once; outer route stays put | +| Open detail directly | Parent navigation works without assuming prior history | + +This is an unexecuted web proposal, not evidence of an Android build. + +## Opinionated Guidance + +Map Back, Up/parent navigation, dialog dismissal, and operation cancellation separately. They may share an icon or button position while changing different state. + +## Platform-Specific Guidance + +Android gesture progress, callback dispatch, activities, and AndroidX navigation belong to native or embedding-host code. A browser adaptation should use its supported navigation semantics. Record any web-view host integration as a separate implementation dependency. + +## Unsupported Absolutes + +Android window classes are not universal web breakpoints. A browser Back action is not necessarily an application's parent destination. A cancel animation does not prove the underlying operation was cancelled. + +## Verification Contract + +Test gesture completion/cancellation on the declared native device when claiming native behavior. For a web adaptation, test actual browser history, direct links, resizes, input modes, and dialog focus independently. Review when any cited convention or target navigation implementation changes. + +## Source, License, And Attribution + +Locally authored synthesis of the official Android pages linked above, rechecked 2026-09-08. No source code, tables, or native visual assets are reproduced. `consumer_reference: not_applicable` because this reference guide selects no consumer implementation record. + +## IA Navigation + +Parent: [Platform Guides](index.md). +Next: [Platform Compatibility Matrix](compatibility-matrix.md). diff --git a/platform-guides/apple-interaction.md b/platform-guides/apple-interaction.md index 796abd4..2fa5172 100644 --- a/platform-guides/apple-interaction.md +++ b/platform-guides/apple-interaction.md @@ -9,7 +9,7 @@ source_path: skills/apple-design/SKILL.md source_revision: 220e8607c90b17337d210125777b7b695f26c221 platform: Apple platforms platform_version: verify-current -reviewed_on: 2026-07-11 +reviewed_on: 2026-09-08 --- # Apple Interaction As A Comparative Reference @@ -33,6 +33,14 @@ For each proposed comparison: 5. Define the web adaptation, including unavailable or materially different capabilities. 6. Verify the adapted behavior on its real surface and record what remains unproven. +## Official Source Review And Worked Adaptation + +Official [HIG Motion](https://developer.apple.com/design/human-interface-guidelines/motion) and [HIG Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility) were rechecked on 2026-09-08 through Apple's documentation data for [Motion](https://developer.apple.com/tutorials/data/design/human-interface-guidelines/motion.json) and [Accessibility](https://developer.apple.com/tutorials/data/design/human-interface-guidelines/accessibility.json). This is a dated living-document review, not a pin of shipped OS behavior. The motion guidance supports purposeful, optional motion and cancellation; it does not supply universal web animation parameters. + +Worked proposal: a web settings disclosure opens immediately and keeps its trigger operable. Optional movement communicates the revealed region. Under reduced motion, the same content and controls remain available without unnecessary movement. Use [Motion Disclosure](../motion/interaction-recipes.md#disclosure) for the behavior contract and the [Adaptation Workflow](adaptation-workflow.md) for the source/target record. + +Expected cases: open and close by keyboard, reverse while opening, enlarge the text, hide content while focus is inside, and change the motion preference. Actual result: `not_run`; this proposal is not a tested Apple or browser implementation. `consumer_reference: not_applicable` because the worked proposal selects no consumer-owned record. + ## Comparative Questions | Theme | Question to investigate | Required evidence | Boundary | diff --git a/platform-guides/compatibility-matrix.md b/platform-guides/compatibility-matrix.md new file mode 100644 index 0000000..c66db8e --- /dev/null +++ b/platform-guides/compatibility-matrix.md @@ -0,0 +1,85 @@ +--- +type: Domain Guide +title: Platform Compatibility Matrix +description: Separate transferable interaction intent from platform capabilities, target fallbacks, and required evidence. +domain: platform-guides +lifecycle: experimental +provenance_kind: local +--- + +# Platform Compatibility Matrix + +Primary role: adaptation comparison and verification checklist. + +## Repository Boundary + +This matrix compares responsibilities, not API support versions. It is not a browser compatibility database. A row's target behavior is a proposed adaptation until verified on the consumer's named runtime. + +## Reusable Method + +Choose the relevant concern, read its platform source guide, record native facts and target decisions separately, and execute both the preferred and fallback paths. Use the [Adaptation Workflow](adaptation-workflow.md) for the handoff. + +## Comparison Matrix + +| Concern | Source route | Transferable intent | Target boundary and fallback | Required observation | +| --- | --- | --- | --- | --- | +| Motion preference | [Apple](apple-interaction.md) | Essential information remains available with less motion | Web preference handling belongs to [Motion recipes](../motion/interaction-recipes.md); retain static status | Change preference and interrupt an active transition | +| Return navigation | [Android](android-interaction.md) | Understand destination and preserve recoverable state | Browser history, parent links, and host Back are distinct; direct entry needs a known parent route | Normal return, direct entry, cancellation, missing prior item | +| Adaptive presentation | [Android](android-interaction.md) | Preserve the task as available space changes | Native units/class cutoffs do not define Layout breakpoints; use the target's content constraints | Resize without losing query, selection, or focus | +| Keyboard traversal | [Windows](windows-interaction.md) | Reach actions and move predictably within controls | Follow the chosen web semantic pattern; visible controls remain operable | Tab/reverse traversal, inner navigation, editing, dismissal | +| Shortcuts | [Windows](windows-interaction.md) | Efficient access to a named command | OS/browser-reserved keys may be unavailable; retain a visible command | Reserved key path, disabled command, active text editor | +| Multimodal feedback | [Apple](apple-interaction.md) | Communicate cause and result through available channels | Haptics/audio may be unavailable or inappropriate; retain essential visual/text feedback | Muted/unavailable channels and the actual target device | +| Translucent treatment | [Apple](apple-interaction.md) | Keep foreground hierarchy understandable | Native materials do not translate to CSS equivalence; an opaque treatment is a candidate fallback | Actual contrast/readability across backgrounds and preferences | + +## Target Evidence Matrix + +| Axis | Record | What a missing check means | +| --- | --- | --- | +| Runtime | Exact browser/app engine, OS, relevant library/SDK versions | No claim beyond the exercised runtime | +| Input | Keyboard, pointer, touch, controller, assistive technology as claimed | An untested mode is `not_run`, not a pass | +| Preferences | Motion, contrast, text sizing, other relevant settings | Source support does not prove local handling | +| Navigation | Direct entry, return, cancellation, nested overlays | A successful happy path leaves recovery unproven | +| Capability | Available, unavailable, denied, interrupted where relevant | Fallback behavior must be exercised independently | +| State | Normal, pending, failed, empty, stale or removed data | A screenshot of default state is insufficient | + +## Example Record + +```yaml +concern: keyboard-traversal +source_guide: platform-guides/windows-interaction.md +target: # actual browser, OS, widget semantics and versions +decision: # the target interaction contract +fallback: # complete visible operation path +source_rechecked: # date and exact official locator +actual_result: not_run +limitations: # untested inputs, runtimes, and capabilities +consumer_reference: not_applicable +consumer_reference_reason: This blank comparison selects no consumer record. +``` + +## Opinionated Guidance + +Test fallback paths deliberately rather than waiting for accidental unsupported hardware. A successful fallback should preserve the task, though its presentation may differ. + +## Platform-Specific Guidance + +Apple, Android, and Windows guide pages own their dated official-source sets. Recheck them for native claims and separately verify the target runtime. Game-engine adaptation routes to [Game UI](../game-ui/index.md). + +## Unsupported Absolutes + +No row claims visual, semantic, accessibility, or performance equivalence between platforms. No generic “mobile” or “desktop” label replaces the actual runtime/input matrix. + +## Verification Contract + +An adaptation is reviewable when each selected row has a target decision, fallback, observed result, and limitation. Missing capability or runtime evidence stays explicit. Review when a linked source, target capability, or failed user task changes the mapping. + +The [Interaction Lab verification](../examples/domain-interactions/verification.md) records a macOS browser target for keyboard traversal, modal cancellation, history, content resizing, and reduced-motion preference changes. Small browser viewports are not mobile-device evidence; Android, iOS/iPadOS, Windows-native APIs, haptics, controllers, and assistive technology remain outside that run. + +## Source, License, And Attribution + +Locally authored comparison matrix derived from this domain's linked source reviews. Platform owners retain authority over their own conventions; no upstream table is reproduced. + +## IA Navigation + +Parent: [Platform Guides](index.md). +Next: [Platform Adaptation Workflow](adaptation-workflow.md). diff --git a/platform-guides/index.md b/platform-guides/index.md index 888d5bb..bcc9c51 100644 --- a/platform-guides/index.md +++ b/platform-guides/index.md @@ -8,6 +8,17 @@ In scope: comparative vocabulary, interaction questions, current official-source Out of scope: affiliation, brand imitation, unsupported platform equivalence, and authority over web standards, accessibility, or Layout contracts. +## Start Here + +| Task | Route | +| --- | --- | +| Record native facts, target decisions, and fallbacks. | [Platform Adaptation Workflow](adaptation-workflow.md) | +| Compare Back and adaptive window behavior. | [Android Interaction As A Comparative Reference](android-interaction.md) | +| Compare keyboard, focus, and commands. | [Windows Interaction As A Comparative Reference](windows-interaction.md) | +| Select target and fallback verification cases. | [Platform Compatibility Matrix](compatibility-matrix.md) | + +These workflows and worked cases are usable experimental guidance. Expected-result tables are test designs; actual product, engine, and reader evidence must be recorded separately. Review on a failed task, a source change, or a changed ownership contract. + ## Available Guides - [Apple Interaction As A Comparative Reference](apple-interaction.md) turns selected interaction themes into questions for web adaptation without claiming platform equivalence. @@ -23,4 +34,4 @@ See [StyleGallery Domains](../DOMAINS.md) for lifecycle, provenance, page member ## IA Navigation Parent: [StyleGallery](../index.md). -Next: [Apple Interaction As A Comparative Reference](apple-interaction.md). +Next: [Platform Adaptation Workflow](adaptation-workflow.md). diff --git a/platform-guides/windows-interaction.md b/platform-guides/windows-interaction.md new file mode 100644 index 0000000..230f430 --- /dev/null +++ b/platform-guides/windows-interaction.md @@ -0,0 +1,75 @@ +--- +type: Domain Guide +title: Windows Interaction As A Comparative Reference +description: Source-bounded Windows keyboard, focus, and command guidance with web adaptation cases. +domain: platform-guides +lifecycle: experimental +provenance_kind: local +platform: Windows applications and WinUI +platform_version: dated Microsoft Learn documentation; target Windows App SDK version required +reviewed_on: 2026-09-08 +--- + +# Windows Interaction As A Comparative Reference + +Primary role: Windows platform comparison guide. + +## Repository Boundary + +This guide compares keyboard and command behavior in Windows application guidance. It supplies no Fluent visual defaults and does not imply that WinUI focus APIs exist in the browser. The consumer records its actual Windows, SDK, browser, and control-library versions. + +## Reusable Method + +Start with the [Adaptation Workflow](adaptation-workflow.md). Identify the command, navigation group, and focus scope before choosing a shortcut or implementation API. + +## Source-Bounded Conventions + +| Concern | Official source and bounded fact | Transferable question | +| --- | --- | --- | +| Sequential and inner navigation | [Keyboard interactions](https://learn.microsoft.com/en-us/windows/apps/design/input/keyboard-interactions) distinguishes moving between controls from moving within some composite controls | Is the key moving between tasks, among items, or editing a value? | +| Initial focus | The same source discusses logical starting focus and avoiding an initially focused destructive action | Does the entry target help the intended task without accidental destructive activation? | +| Focus movement | [Focus navigation](https://learn.microsoft.com/en-us/windows/apps/develop/input/focus-navigation) documents native focus navigation and control behavior | Can focus reach every required action, and where does it return after dismissal? | +| Commands | [Keyboard accelerators](https://learn.microsoft.com/en-us/windows/apps/develop/input/keyboard-accelerators) describes command invocation and scoping in Windows applications | Does a shortcut invoke the same command and availability rules as its visible control? | + +Source set reviewed 2026-09-08. These are platform guidance and API documentation, not evidence that a consumer implements them. + +## Worked Adaptation: Searchable Command Surface + +Task: find and invoke commands without a pointer. Begin with the [Command Surface recipe](../recipes/command-surface.md) for spatial composition. Use the correct web widget semantics for the chosen design; a native control's tab-stop policy should not be copied onto unrelated HTML elements. + +Define the opening control, query input, result navigation, selected command, disabled-command explanation, and dismissal target. Command buttons and shortcuts share one operation owner. Editing text must not accidentally invoke a global command. A shortcut is supplemental: the visible action remains available when that key combination is reserved by the browser or OS. + +| Test | Expected target behavior | +| --- | --- | +| Open with keyboard | Focus reaches the declared entry target | +| Search to zero results | Query remains editable and dismissal remains available | +| Attempt an unavailable command | No operation; availability is explained consistently | +| Dismiss after invoker removal | Focus reaches a documented surviving target | +| Use a reserved/unavailable shortcut | The visible control still performs the task | + +Actual result: `not_run`. This is a fictional web adaptation contract. + +## Opinionated Guidance + +Centralize command availability so menu, button, and shortcut do not disagree. Do not add shortcuts before checking focus, text editing, and the complete visible operation path. + +## Platform-Specific Guidance + +WinUI accelerators and focus APIs have native routing rules. Web controls use HTML, the selected ARIA pattern where necessary, browser defaults, and the application's focus scope. See the [shared accessibility evidence gate](../quality/gates/accessibility-evidence.md) for the required evidence boundary. + +## Unsupported Absolutes + +Arrow keys are not a replacement for Tab in every UI. A Windows shortcut is not safe to intercept globally in every browser. A working pointer flow does not prove keyboard operation. + +## Verification Contract + +Verify entry, traversal, command invocation, text editing, cancellation, disabled state, and focus restoration on every claimed runtime/input. Include a missing invoker and nested surface. Review on Windows SDK, browser, source guidance, or command-routing changes. + +## Source, License, And Attribution + +Locally authored synthesis of the official Microsoft sources linked above, rechecked 2026-09-08. No upstream examples, control code, or visual assets are copied. `consumer_reference: not_applicable` because no consumer implementation record is selected. + +## IA Navigation + +Parent: [Platform Guides](index.md). +Next: [Platform Compatibility Matrix](compatibility-matrix.md). diff --git a/quality/claim-records/design-terminology-domain-scope.md b/quality/claim-records/design-terminology-domain-scope.md new file mode 100644 index 0000000..3f7b8ff --- /dev/null +++ b/quality/claim-records/design-terminology-domain-scope.md @@ -0,0 +1,57 @@ +--- +type: Decision Record +title: Design Terminology Domain Scope Decision +description: Decision to add Design Terminology as the sixth StyleGallery domain, with four placement alternatives compared and the domain's independent decision surface defined. +--- + +# Design Terminology Domain Scope Decision + +## Decision + +StyleGallery adds Design Terminology as a sixth explicit domain. The domain's independent decision surface, in one sentence: + +> Design Terminology binds design terms to their named sources, classifies them by source kind and concept family, and judges typed semantic relations and conflicts between terms from different sources. + +Concretely, this domain and only this domain decides: which named source a term belongs to, what kind of source that is, which concept family the term serves, and which typed relation with which boundary holds between two terms. The five existing domains keep their boundaries unchanged. + +The domain does not own: StyleGallery's internal canonical naming (the [Controlled Vocabulary](../../guides/vocabulary.md) keeps it), actual UI behavior or implementation methods, accessibility rules, platform-specific interaction adaptation (Platform Guides keeps it), and any universal prescription about which term is generally better. + +## Alternatives Compared + +| Candidate | Strength | Weakness | Disposition | +| --- | --- | --- | --- | +| Extend `guides/vocabulary.md` | Close to existing terminology stewardship | Mixes StyleGallery's internal canonical word set with external systems' term meanings on one authoritative page; the vocabulary would then compete with external definitions it is supposed to route around | Rejected: internal canonical control and external comparative meaning are different decisions with different evidence and freshness rules | +| `platform-guides/terminology/` | Reuses an existing comparative domain | Tools (Figma), specifications (DTCG Format), and pattern libraries are not platforms; hosting them under Platform Guides would erase the source-kind axis this domain depends on | Rejected: source kind, not platform comparison, is the primary axis | +| Shared non-domain `terminology/` | Easy to reference across domains | No named owner, lifecycle, validator, or review authority; consumer-reference already carries the no-second-authority rule for shared infrastructure | Rejected: ungoverned placement reproduces the silent-collision problem the content exists to solve | +| New sixth domain `design-terminology/` | Owns an independent lifecycle, review owner, validator coverage, and experimental-to-stable promotion path | Widest infrastructure blast radius: manifest, validators, schemas, sealed material cardinality, and package inventory all change | Adopted, with the conditions below | + +Adoption conditions: content starts `experimental`; a machine-readable term/concept/source/relation registry is a promotion prerequisite; every external meaning claim carries an official source and review date; typed relations replace plain term-pair tables. + +## Naming + +Terminology, not topology: topology suggests a formal relation graph or ontology that this domain does not yet provide; v0.1 compares definitions, usage scope, and conflicts. Terminology, not vocabulary: the [Controlled Vocabulary](../../guides/vocabulary.md) owns StyleGallery's canonical internal word set; this domain compares the meanings and relations of terms used by external named sources. + +## Context + +Named design systems, platform guidelines, specifications, and design tools define overlapping terms differently, and handoffs between them fail on silent term collisions. Recording these definitions inside Layout would violate the pattern boundary; the controlled vocabulary page is for internal canonical terms; Platform Guides compares interaction conventions rather than terminology. + +## Warrant + +A separate domain lets terminology comparison name its own evidence boundary: cited official sources, dated structural readings, typed relations with boundaries, and working translations that never override repository policy. + +## Consequences + +- `design-terminology/**` begins `experimental` with a named review owner and validator coverage. +- The domain manifest, root routes, quality scope, vocabulary domain list, and governance rows record six domains; Consumer Reference remains shared infrastructure and still cannot add a domain row. +- Record consistency is machine-enforced from v0.1 by `scripts/validate-design-terminology.mjs` (closed relation types, recorded terms on both sides, non-trivial boundaries, contradiction pairs, date and status shape, no orphan terms). Human semantic review is required at stable promotion only, per the repository promotion rules; it is not a merge gate for `experimental` content. +- Domain identity and cardinality are currently sealed in multiple surfaces (closed schema enums, identity sets, discover cardinality, package inventory, snapshot tests) requiring synchronized manual edits when a domain is added. This is recorded technical debt, not tamper evidence alone: one author changing all copies in one commit weakens duplication as independent evidence while keeping drift risk. Revisit triggers: a seventh domain id is added, manual-change sites exceed twelve, a cardinality drift incident occurs, or registry generation changes. Target structure when triggered: one canonical domain registry generating enums, lists, and package inventory, with an independently reviewed sealed digest as the tamper check. Named review owner for this debt: the Design Terminology domain owner until a governance owner is designated. +- Term relations recorded by the domain are working judgments, not repository policy for other domains. + +## Boundary Or Limitation + +This decision establishes ownership and governance only. It does not verify that any cited external vocabulary is current beyond each record's review date, does not make any external definition authoritative for product implementation, and does not claim the typed relation model is complete beyond the recorded cases. + +## IA Navigation + +Parent: [Claim Records](index.md) in [Quality Gates](../index.md). +Next: [StyleGallery Domains](../../DOMAINS.md) for the active domain manifest. diff --git a/quality/evidence/executable-evidence.md b/quality/evidence/executable-evidence.md index 9295380..1ffb6b3 100644 --- a/quality/evidence/executable-evidence.md +++ b/quality/evidence/executable-evidence.md @@ -32,7 +32,7 @@ Executable evidence identifies which claims are machine-enforced, which are only | Markdown links resolve inside the repository. | `scripts/validate-links.mjs` | `node scripts/validate-links.mjs --json` | All checked Markdown links resolve to local files or are intentionally external or anchors. | A local link that escapes the repository or points at a missing file must fail. | Proves link targets exist, not that the target content supports a claim. | | Catalog and generated pattern indexes match the pattern data source. | `scripts/validate-catalog.mjs` | `node scripts/validate-catalog.mjs --json` | `CATALOG.md`, category indexes, and expected pattern files match `scripts/pattern-data.mjs`. | Missing, unexpected, or unlisted pattern files must fail. | Proves catalog consistency, not pattern usefulness. | | Governance, lifecycle, generated-file, ownership, and stale-content policy remain discoverable and CI-enforced. | `scripts/validate-governance.mjs` and `scripts/test-validate-governance.mjs` | `node scripts/validate-governance.mjs --json`; `node scripts/test-validate-governance.mjs --json` | `GOVERNANCE.md`, `.github/CODEOWNERS`, generated warnings, generated metadata, root link targets, lifecycle states, `scheduled_stale_audit` metadata, and CI wiring are present. | Missing governance file, generated warning, generated metadata, CODEOWNERS coverage, or stale policy fixtures must fail. Preferred governance prose and link labels emit warnings. | Proves governance policy is present and linked, not that CODEOWNERS users have verified repository write access. | -| Domain topology, metadata, provenance, scope boundaries, and root routes remain enforced. | `scripts/validate-domains.mjs` and `scripts/test-validate-domains.mjs` | `node scripts/validate-domains.mjs --json`; `node scripts/test-validate-domains.mjs` | Five governed domains and their declared leaves are reachable and attributed. | Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail. | A full SHA proves content identity syntax, not publisher authenticity, source ownership, or local quality. | +| Domain topology, metadata, provenance, scope boundaries, and root routes remain enforced. | `scripts/validate-domains.mjs` and `scripts/test-validate-domains.mjs` | `node scripts/validate-domains.mjs --json`; `node scripts/test-validate-domains.mjs` | Six governed domains and their declared leaves are reachable and attributed. | Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail. | A full SHA proves content identity syntax, not publisher authenticity, source ownership, or local quality. | | Consumer-reference handoffs, schema/runtime parity, repository-local record paths, lifecycle separation, ownership truth, and dependency direction remain enforced. | `scripts/validate-consumer-reference.mjs` and `scripts/test-validate-consumer-reference.mjs` | `node scripts/validate-consumer-reference.mjs --json`; `node scripts/test-validate-consumer-reference.mjs --json` | Declared and reasoned-not-applicable fixtures exit zero, every shipped schema rule has accepted/rejected parity coverage, all repository handoffs declare applicability, fixtures remain related, and ownership discloses placeholder single-account review. | Unknown top-level or nested properties, invalid schema fields, missing handoff or reason, stable with ended support, boolean independence, unresolved/absolute/scheme/network/parent/item-or-record-symlink/non-JSON paths, scaffold success, sixth-domain classification, literal or supported computed reverse imports, and repository handoff omissions must fail with named finding codes and non-zero child exit. | Proves receiver-contract consistency, bounded static dependency detection, and path containment, not general JavaScript data-flow safety, visual quality, independent adoption, verified owner permissions, or consumer implementation conformance. | | Promotion governance remains a closed JSON-only, invariant-scoped, deferred example contract. | `scripts/validate-promotion-rfc.mjs` and `scripts/test-validate-promotion-rfc.mjs` | `node scripts/validate-promotion-rfc.mjs --json`; `node scripts/test-validate-promotion-rfc.mjs --json` | The manifest-declared policy and two canonical examples pass with deferred decisions, zero attestations, exact support commitment, and no promotion claim. | Manifest-declared invalid fixtures plus forged, unregistered, duplicate, path, extension, support, evidence, canonical-drift, and lifecycle mutations exit non-zero with named findings. | Synthetic validation does not authenticate adoption, organizations, owners, support capacity, provenance, or a promotion decision; the current canonical inventory supplies no real independent consumers. | | Portable token source and generated CSS agree through the pinned restricted adapter. | `scripts/build-reference-artifacts.mjs`, `scripts/validate-reference-artifacts.mjs`, and `scripts/test-reference-adapters.mjs` | Build with `--fail-on-warning`, validate the generated manifest, then run the adapter fixture harness. | Dimension, color, duration, tested border values, and whole-token curly aliases emit nonzero CSS declarations with matching counts and hashes; output references remain CSS variable references. | `$extends`, JSON Pointer, resolver/modifier/theme documents, unknown reserved fields, non-string descriptions, adapter-unsafe path segments, untested type/unit, partial/dangling/cyclic/type-mismatched aliases, missing output, zero count, warning, scaffold/unknown manifest fields, missing/duplicate declaration, object sentinel, unresolved or forged value, and count drift must fail with named findings and non-zero child exit. | Proves the pinned adapter preserves this tested subset and that committed artifacts independently rebuild from their canonical source, not that tokens are product defaults, portable beyond the tested adapters, visually suitable, or adopted by a consumer. | diff --git a/quality/index.md b/quality/index.md index f477c05..2e0c3ed 100644 --- a/quality/index.md +++ b/quality/index.md @@ -1,6 +1,6 @@ # Quality Gates -`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, and Platform Guides claims are admissible. +`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, Platform Guides, and Design Terminology claims are admissible. This shared layer does not make the repository a visual design system. Layout pattern files still own spatial structure only; domain guidance cannot bypass these gates. Quality gates explain how claims are framed, what evidence can support them, and when review or debt is required. @@ -48,7 +48,7 @@ Use this script for lightweight tree tests: | Name an observed motion effect. | [README](../README.md) | [Motion Vocabulary](../motion/vocabulary.md) | The first selected route is Motion and the term reference is reached within two hops. | | Review product-level interface craft. | [README](../README.md) | [Interface Craft Decisions](../design-engineering/interface-craft.md) | The first selected route is Design Engineering and shared quality gates remain visible. | | Compare an Apple interaction convention. | [README](../README.md) | [Apple Interaction](../platform-guides/apple-interaction.md) | The first selected route is Platform Guides and source/version limits are reached within two hops. | -| Declare whether a consumer reference applies. | [README](../README.md) | [Consumer Reference](../consumer-reference/index.md) | The handoff reaches the shared contract without classifying it as a sixth domain. | +| Declare whether a consumer reference applies. | [README](../README.md) | [Consumer Reference](../consumer-reference/index.md) | The handoff reaches the shared contract without classifying it as a seventh domain. | | Prove a consumer migration preserves declared behavior. | [README](../README.md) | [Consumer Migration Readiness](../design-engineering/consumer-migration-readiness.md) | The reader reaches the Design Engineering method and its evidence gate within two hops. | | Find the authority route for uGUI, UI Toolkit, or NGUI. | [README](../README.md) | [Unity UI Systems](../game-ui/unity/ui-systems.md) | The first selected route is Game UI, and the system-specific source and version boundary is reached within three hops. | diff --git a/scripts/agent-native/v2/material-admission.mjs b/scripts/agent-native/v2/material-admission.mjs index 6b6d77e..8df5cb9 100644 --- a/scripts/agent-native/v2/material-admission.mjs +++ b/scripts/agent-native/v2/material-admission.mjs @@ -17,7 +17,7 @@ const MANIFEST_REF = "sg:manifest/material-admission-v2"; const MATERIAL_REF_PATTERN = /^sg:material\/path-sha256-[a-f0-9]{64}$/; const MATERIAL_VERSION_PATTERN = /^sg:material\/path-sha256-[a-f0-9]{64}@sha256:[a-f0-9]{64}$/; const HASH_PATTERN = /^[a-f0-9]{64}$/; -const DOMAINS = new Set(["layout", "motion", "design-engineering", "game-ui", "platform-guides", "shared"]); +const DOMAINS = new Set(["layout", "motion", "design-engineering", "game-ui", "platform-guides", "design-terminology", "shared"]); const LIFECYCLES = new Set(["draft", "stable", "deprecated", "experimental", "generated"]); const RECORD_KEYS = new Set(["schema_version", "record_kind", "stable_ref", "version_id", "repository_path", "media_type", "source_sha256", "byte_length", "lifecycle", "domain"]); const MANIFEST_KEYS = new Set(["schema_version", "record_kind", "stable_ref", "version_id", "admission_policy_ref", "admission_policy_version_id", "materials"]); diff --git a/scripts/agent-native/v2/material-identity.mjs b/scripts/agent-native/v2/material-identity.mjs index 02bb993..3e4d0b8 100644 --- a/scripts/agent-native/v2/material-identity.mjs +++ b/scripts/agent-native/v2/material-identity.mjs @@ -6,7 +6,7 @@ export const MATERIAL_STABLE_REF_KINDS = Object.freeze(["domain", "page", "patte const KIND_SET = new Set(MATERIAL_STABLE_REF_KINDS); const KEBAB = /^[a-z0-9]+(?:-[a-z0-9]+)*$/; const PATH_ID = /^path-sha256-[a-f0-9]{64}$/; -const DOMAIN_IDS = new Set(["layout", "motion", "design-engineering", "game-ui", "platform-guides"]); +const DOMAIN_IDS = new Set(["layout", "motion", "design-engineering", "game-ui", "platform-guides", "design-terminology"]); const MATERIAL_ID = PATH_ID; export class MaterialIdentityError extends TypeError { @@ -56,7 +56,7 @@ export function materialIdentityForRecord(record) { if (typeof repositoryPath !== "string") fail("material_record_identity_invalid", "record has no bound source path"); let kind = "page"; let id = `path-sha256-${sha256(Buffer.from(repositoryPath, "utf8"))}`; - const domainMatch = /^(layout|motion|design-engineering|game-ui|platform-guides)\/index\.md$/.exec(repositoryPath); + const domainMatch = /^(layout|motion|design-engineering|game-ui|platform-guides|design-terminology)\/index\.md$/.exec(repositoryPath); if (domainMatch) { kind = "domain"; id = domainMatch[1]; } else if (/^patterns\/[^/]+\/[^/]+\.md$/.test(repositoryPath)) kind = "pattern"; return deepFreeze({ diff --git a/scripts/agent-native/v2/material-mcp-adapter.mjs b/scripts/agent-native/v2/material-mcp-adapter.mjs index 6c78643..11bbd0f 100644 --- a/scripts/agent-native/v2/material-mcp-adapter.mjs +++ b/scripts/agent-native/v2/material-mcp-adapter.mjs @@ -16,7 +16,7 @@ const manifestPath = path.join(repositoryRoot, "consumer-reference", "agent-nati const exposedNames = new Set(["material-context", "material-discover", "material-get", "material-search"]); const descriptions = Object.freeze({ "material-context": "Build a deterministic, provenance-bound material context within a token budget.", - "material-discover": "Discover the five governed StyleGallery domain entries.", + "material-discover": "Discover the six governed StyleGallery domain entries.", "material-get": "Read bounded UTF-8 bytes for one canonical v2 material StableRef.", "material-search": "Search admitted material deterministically, optionally returning only repository-relative paths.", }); diff --git a/scripts/agent-native/v2/material-queries.mjs b/scripts/agent-native/v2/material-queries.mjs index 514b82f..1e3e9ac 100644 --- a/scripts/agent-native/v2/material-queries.mjs +++ b/scripts/agent-native/v2/material-queries.mjs @@ -310,11 +310,36 @@ function titleOf(text) { return /^#{1,6}\s+(.+?)\s*$/m.exec(text)?.[1] ?? ""; } function fieldMembership(fieldTokens, queryTokens) { - const members = new Set(fieldTokens); let count = 0; - for (const token of queryTokens) if (members.has(token)) count += 1; + for (const token of queryTokens) if (fieldTokens.has(token)) count += 1; return count; } +function queryTokenMembership(value, queryTokenSet) { + const matches = new Set(); + for (const token of tokenizeMaterialText(value)) { + if (queryTokenSet.has(token)) matches.add(token); + } + return matches; +} +function rarityWeightsFor(documents, queryTokens) { + return queryTokens.map((token) => { + const documentFrequency = documents.reduce((count, document) => count + Number( + document.titleTokens.has(token) || document.pathTokens.has(token) || document.bodyTokens.has(token), + ), 0); + return { + document_frequency: documentFrequency, + multiplier: Math.ceil(documents.length / Math.max(1, documentFrequency)), + token, + }; + }); +} +function weightedFieldMembership(fieldTokens, rarityByToken, fieldWeight) { + let score = 0; + for (const [token, multiplier] of rarityByToken) { + if (fieldTokens.has(token)) score += multiplier * fieldWeight; + } + return score; +} function sourceIdentity(record) { return { stable_ref: record.stable_ref, version_id: record.version_id, source_sha256: record.source_sha256, byte_length: record.byte_length }; } @@ -325,7 +350,7 @@ export function materialDiscover({ repositoryRoot, fileSystem = fs }) { .filter(({ identity }) => identity.kind === "domain") .map(({ record, identity }) => ({ identity, source: sourceIdentity(record), lifecycle: record.lifecycle })) .sort((left, right) => compare(left.identity.stable_ref, right.identity.stable_ref)); - if (domains.length !== 5) fail("material_domain_set_invalid", "material manifest does not contain the five governed domains"); + if (domains.length !== 6) fail("material_domain_set_invalid", "material manifest does not contain the six governed domains"); return deepFreeze({ schema_version: "2.0", manifest_version_id: manifest.version_id, domains }); } @@ -334,20 +359,19 @@ export function materialSearch({ repositoryRoot, input, fileSystem = fs, sourceR const state = snapshot ? requireSnapshot(snapshot) : loadMetadata(repositoryRoot, fileSystem); const { root, manifest } = state; const beforeInventory = snapshot ? state.inventory : trackedInventory(repositoryRoot, gitRunner); - const ranked = []; + const queryTokenSet = new Set(normalized.scoringTokens); + const documents = []; for (const record of manifest.materials) { const bytes = readRecord({ repositoryRoot, root, record, fileSystem, sourceReader, gitRunner, inventory: beforeInventory }); let body; try { body = utf8Fatal.decode(bytes); } catch { fail("material_source_utf8_invalid", "material source is not valid UTF-8"); } const title = titleOf(body); - const titleCount = fieldMembership(tokenizeMaterialText(title), normalized.scoringTokens); - const pathCount = fieldMembership(tokenizeMaterialText(record.repository_path), normalized.scoringTokens); - const bodyCount = fieldMembership(tokenizeMaterialText(body), normalized.scoringTokens); - const score = titleCount * MATERIAL_SEARCH_WEIGHTS.title + pathCount * MATERIAL_SEARCH_WEIGHTS.path + bodyCount * MATERIAL_SEARCH_WEIGHTS.body; - if (score === 0) continue; - ranked.push({ - repositoryPath: record.repository_path, - result: { identity: materialIdentityForRecord(record), source: sourceIdentity(record), title, score, match_counts: { title: titleCount, path: pathCount, body: bodyCount } }, + documents.push({ + bodyTokens: queryTokenMembership(body, queryTokenSet), + pathTokens: queryTokenMembership(record.repository_path, queryTokenSet), + record, + title, + titleTokens: queryTokenMembership(title, queryTokenSet), }); } const afterInventory = trackedInventory(repositoryRoot, gitRunner); @@ -355,6 +379,28 @@ export function materialSearch({ repositoryRoot, input, fileSystem = fs, sourceR assertTracked(record, afterInventory); if (canonicalize(beforeInventory.get(record.repository_path)) !== canonicalize(afterInventory.get(record.repository_path))) fail("material_source_race", "material source tracking changed during read"); } + const rarityWeights = rarityWeightsFor(documents, normalized.scoringTokens); + const rarityByToken = new Map(rarityWeights.map(({ token, multiplier }) => [token, multiplier])); + const ranked = []; + for (const document of documents) { + const titleCount = fieldMembership(document.titleTokens, normalized.scoringTokens); + const pathCount = fieldMembership(document.pathTokens, normalized.scoringTokens); + const bodyCount = fieldMembership(document.bodyTokens, normalized.scoringTokens); + const score = weightedFieldMembership(document.titleTokens, rarityByToken, MATERIAL_SEARCH_WEIGHTS.title) + + weightedFieldMembership(document.pathTokens, rarityByToken, MATERIAL_SEARCH_WEIGHTS.path) + + weightedFieldMembership(document.bodyTokens, rarityByToken, MATERIAL_SEARCH_WEIGHTS.body); + if (score === 0) continue; + ranked.push({ + repositoryPath: document.record.repository_path, + result: { + identity: materialIdentityForRecord(document.record), + source: sourceIdentity(document.record), + title: document.title, + score, + match_counts: { title: titleCount, path: pathCount, body: bodyCount }, + }, + }); + } ranked.sort((left, right) => right.result.score - left.result.score || compare(left.result.identity.stable_ref, right.result.identity.stable_ref)); const selected = ranked.slice(0, normalized.limit); const envelope = { @@ -362,6 +408,8 @@ export function materialSearch({ repositoryRoot, input, fileSystem = fs, sourceR normalization: "Unicode NFKC; ECMAScript locale-independent lowercase; Letter/Number-led Unicode words retaining attached Marks; unique query-token field membership", query: normalized.query.normalize("NFKC").toLowerCase(), tokens: normalized.tokens, scoring_tokens: normalized.scoringTokens, weights: MATERIAL_SEARCH_WEIGHTS, + rarity_weighting: "ceil(material_count / max(1, token_document_frequency))", + rarity_weights: rarityWeights, }; if (normalized.pathsOnly) return deepFreeze({ ...envelope, paths_only: true, paths: selected.map(({ repositoryPath }) => repositoryPath), total_matches: ranked.length }); return deepFreeze({ ...envelope, results: selected.map(({ result }) => result), total_matches: ranked.length }); diff --git a/scripts/agent-native/v2/test-agent-v1-compatibility.mjs b/scripts/agent-native/v2/test-agent-v1-compatibility.mjs index dbc7894..7957680 100644 --- a/scripts/agent-native/v2/test-agent-v1-compatibility.mjs +++ b/scripts/agent-native/v2/test-agent-v1-compatibility.mjs @@ -12,7 +12,6 @@ import { agentNativeRegistry } from "../registry.mjs"; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../.."); const expectedFiles = Object.freeze({ - "consumer-reference/agent-native/README.md": "959509d4539f4b7bb7d193bfdfb949b4cf25ab53317e072aaad7657f04b8779e", "consumer-reference/agent-native/registry.json": "70107a28225ee893b0d32df8e2a3c69bed747992bf7e92a0ca5431df4605d8b0", "consumer-reference/agent-native/schema/agent-native.schema.json": "0675d61d57a8d12c724f6a97160f6bc4cf2f8abf91663adae0593e7a5a221871", "consumer-reference/agent-native/schema/epistemic.schema.json": "ddfdd88692897b4cc17057fc7b0cb6222f69d078956ffb0344d288025cbab9d2", @@ -35,6 +34,16 @@ const expectedFiles = Object.freeze({ "scripts/test-agent-mcp.mjs": "8ee6726f2ad811e32b9c7304ef3e2ab5755e261a68fffbc3c03f872355fe5740", "scripts/test-sg-cli.mjs": "a120d23ae0a244b0694f1ef24068e7a629bfd400eb83031447b76a82067fb67f", }); +// The shared guide gained material-v2 instructions and the six-domain correction +// in this reviewed documentation revision. That update did not change v1 bytes. +// Keep its exact digest explicit, separately from the original Todo2 core pins; +// never derive either baseline from the working tree at test time. +const expectedDocumentation = Object.freeze({ + "consumer-reference/agent-native/README.md": { + revision: "d8bdf0bd5b5aec2fbc38e322a9ac7a1d31fd1332", + sha256: "6e59c913b175039819143b53078817630e3664db1c0342f89545038d0e53a52e", + }, +}); const expectedCli = Object.freeze([ ["discover", ["discover", "--format", "json"], 12748, "a8980754604d800a979bfdd7ae9bb78f755405989df4152e8f7293854e409719"], ["resolve", ["resolve", "sg:profile/editorial-reference-profile", "--format", "json"], 668, "8d34b81a31fdc1df5c73e1f7e012eb00b0ab9c90816e951323afedca0566fb4e"], @@ -80,6 +89,9 @@ const snapshot = { assert.deepEqual(checkSnapshot(snapshot), []); for (const [file, digest] of Object.entries(expectedFiles)) assert.equal(sha(fs.readFileSync(path.join(root, file))), digest, `${file} changed from Todo2`); +for (const [file, { revision, sha256 }] of Object.entries(expectedDocumentation)) { + assert.equal(sha(fs.readFileSync(path.join(root, file))), sha256, `${file} changed from reviewed documentation revision ${revision}`); +} for (const file of ["fixture.mjs", "identity.mjs", "queries.mjs", "registry.mjs", "cli-adapter.mjs", "mcp-adapter.mjs", "self-description.mjs"]) { const source = fs.readFileSync(path.join(root, "scripts/agent-native", file), "utf8"); assert.doesNotMatch(source, /(?:from|import\s*\()[^\n]*(?:extensions\/|a2a-projection|agui-projection|material-)/, `v1 core imports an extension/material plane: ${file}`); @@ -120,6 +132,7 @@ for (const [changed, code] of perturbations) assert.ok(checkSnapshot(changed).in process.stdout.write(`${JSON.stringify({ ok: true, todo2_source_digests: Object.keys(expectedFiles).length, + reviewed_documentation: expectedDocumentation, frozen_cli_goldens: parsed, fixture_records: snapshot.recordCount, stable_ref_kinds: snapshot.kinds.length, diff --git a/scripts/agent-native/v2/test-material-admission.mjs b/scripts/agent-native/v2/test-material-admission.mjs index a686c26..c837a25 100644 --- a/scripts/agent-native/v2/test-material-admission.mjs +++ b/scripts/agent-native/v2/test-material-admission.mjs @@ -27,8 +27,8 @@ const v1SchemaDirectory = path.join(repositoryRoot, "consumer-reference", "agent const v2Directory = path.join(repositoryRoot, "consumer-reference", "agent-native", "v2"); const temporaryRoots = new Set(); const sha256 = (bytes) => createHash("sha256").update(bytes).digest("hex"); -const EXPECTED_PATH_COUNT = 126; -const EXPECTED_PATHS_NEWLINE_SHA256 = "897c48cb3dec29fdb210e99c91d1fdfe24ea70562ba182143495b476909d2744"; +const EXPECTED_PATH_COUNT = 147; +const EXPECTED_PATHS_NEWLINE_SHA256 = "54139a980e6ad0b9558b033f741d89cd8bafa8e44389beaf90e0bd0781871a43"; function run(command, args, options = {}) { return spawnSync(command, args, { encoding: "utf8", maxBuffer: 8 * 1024 * 1024, timeout: 30_000, ...options }); @@ -111,7 +111,7 @@ function policyVersion(policy) { test.after(() => { for (const root of temporaryRoots) fs.rmSync(root, { force: true, recursive: true }); }); -test("policy is closed, versioned, exact, and seals all 126 current paths", () => { +test("policy is closed, versioned, exact, and seals all 147 current paths", () => { const policySchema = JSON.parse(fs.readFileSync(path.join(v2Directory, "schema", "admission-policy.schema.json"), "utf8")); const ajv = new Ajv2020({ allErrors: true, strict: true }); assert.equal(ajv.validate(policySchema, materialAdmissionPolicy), true, JSON.stringify(ajv.errors)); @@ -127,7 +127,7 @@ test("policy is closed, versioned, exact, and seals all 126 current paths", () = assert.equal(Object.hasOwn(materialAdmissionPolicy, "public_roots"), false); }); -test("actual repository manifest admits exactly 126 paths with deterministic identities and source versions", () => { +test("actual repository manifest admits exactly 147 paths with deterministic identities and source versions", () => { const materials = materialAdmissionPolicy.allowed_materials.map(({ repository_path }) => sourceRecord(repositoryRoot, repository_path)); const manifest = createMaterialManifest(materials); const result = validateMaterialManifest({ repositoryRoot, manifest }); diff --git a/scripts/agent-native/v2/test-material-mcp-stdio.mjs b/scripts/agent-native/v2/test-material-mcp-stdio.mjs index 5d27137..2bc7b28 100644 --- a/scripts/agent-native/v2/test-material-mcp-stdio.mjs +++ b/scripts/agent-native/v2/test-material-mcp-stdio.mjs @@ -115,7 +115,7 @@ async function rawProtocolProbe(script, cwd) { const afterMalformed = next((message) => message.id === 61, "post-malformed response"); send("{malformed-json"); send({ jsonrpc: "2.0", id: 61, method: "resources/list", params: {} }); - assert.equal((await afterMalformed).result.resources.length, 126); + assert.equal((await afterMalformed).result.resources.length, 147); assert.equal(allMessages.filter((message) => message.id === undefined).length, 0); } finally { child.stdin.end(); @@ -242,7 +242,7 @@ try { assert.deepEqual(Object.keys(material.client.getServerCapabilities()).sort(), ["resources", "tools"]); const tools = (await deadline(material.client.listTools(), "list tools")).tools; assert.deepEqual(tools.map(({ name }) => name), ["material-context", "material-discover", "material-get", "material-search"]); - assert.equal((await deadline(material.client.listResources(), "list resources")).resources.length, 126); + assert.equal((await deadline(material.client.listResources(), "list resources")).resources.length, 147); assert.deepEqual((await deadline(material.client.listResourceTemplates(), "list templates")).resourceTemplates.map(({ uriTemplate }) => uriTemplate), ["sg://v2/material/{reference}"]); const calls = [ @@ -291,7 +291,7 @@ try { await rejected(() => v1.client.readResource({ uri: materialResourceUri(selected[0].stable_ref) }), /not found|resource/i); await rejected(() => material.client.readResource({ uri: "sg://self" }), /not found|resource/i); - process.stdout.write(`${JSON.stringify({ ok: true, transport: "stdio", cwd_with_spaces: true, direct_run: { real_path: true, symlink_with_spaces: true }, import_guard: importGuard, tools: 4, resources: 126, domains: 5, generated: selected[5].stable_ref, source_hashes_verified: 6, concurrent_requests: 8, raw_protocol: rawProtocol, frame_boundaries: frameBoundaries, oversized_frame: oversizedFrame, epipe, v1_tools: v1Tools, stderr_empty: true }, null, 2)}\n`); + process.stdout.write(`${JSON.stringify({ ok: true, transport: "stdio", cwd_with_spaces: true, direct_run: { real_path: true, symlink_with_spaces: true }, import_guard: importGuard, tools: 4, resources: 147, domains: 6, generated: selected[5].stable_ref, source_hashes_verified: 6, concurrent_requests: 8, raw_protocol: rawProtocol, frame_boundaries: frameBoundaries, oversized_frame: oversizedFrame, epipe, v1_tools: v1Tools, stderr_empty: true }, null, 2)}\n`); } finally { if (v1) { await deadline(v1.client.close(), "v1 shutdown"); diff --git a/scripts/agent-native/v2/test-material-mcp.mjs b/scripts/agent-native/v2/test-material-mcp.mjs index 9de0758..d5f4a72 100755 --- a/scripts/agent-native/v2/test-material-mcp.mjs +++ b/scripts/agent-native/v2/test-material-mcp.mjs @@ -106,7 +106,7 @@ try { assert.equal(nullPrototypeResponse.structuredContent?.ok, true); const resources = (await client.listResources()).resources; - assert.equal(resources.length, 126); + assert.equal(resources.length, 147); assert.deepEqual((await client.listResourceTemplates()).resourceTemplates.map(({ uriTemplate }) => uriTemplate), ["sg://v2/material/{reference}"]); assert.ok(resources.every(({ uri }) => uri === materialResourceUri(resources.find((entry) => entry.uri === uri).name))); @@ -123,9 +123,9 @@ try { assert.deepEqual(envelope(response), executeMaterialCli(cliArgs)); } - const domainRecords = manifest.materials.filter(({ repository_path }) => ["layout/index.md", "motion/index.md", "design-engineering/index.md", "game-ui/index.md", "platform-guides/index.md"].includes(repository_path)); + const domainRecords = manifest.materials.filter(({ repository_path }) => ["layout/index.md", "motion/index.md", "design-engineering/index.md", "game-ui/index.md", "platform-guides/index.md", "design-terminology/index.md"].includes(repository_path)); const generated = manifest.materials.find(({ domain, lifecycle }) => domain === "layout" && lifecycle === "generated"); - assert.equal(domainRecords.length, 5); + assert.equal(domainRecords.length, 6); for (const record of [...domainRecords, generated]) { const response = await client.readResource({ uri: materialResourceUri(record.stable_ref) }); const payload = JSON.parse(response.contents[0].text); diff --git a/scripts/agent-native/v2/test-material-query.mjs b/scripts/agent-native/v2/test-material-query.mjs index ad25a82..c42d3d3 100644 --- a/scripts/agent-native/v2/test-material-query.mjs +++ b/scripts/agent-native/v2/test-material-query.mjs @@ -100,13 +100,13 @@ test("v2 identity grammar is closed and v1 rejects every v2 kind", () => { assert.throws(() => parseMaterialStableRef({ schema_version: "1.0", stable_ref: "sg:domain/layout" }), { code: "material_identity_version_invalid" }); }); -test("material-discover returns exactly the five governed domains and deterministic projected identities", () => { +test("material-discover returns exactly the six governed domains and deterministic projected identities", () => { const first = invoke("material-discover"); const second = invoke("material-discover"); assert.equal(first.ok, true); assert.equal(canonicalize(first), canonicalize(second)); assert.deepEqual(first.result.domains.map(({ identity }) => identity.stable_ref), [ - "sg:domain/design-engineering", "sg:domain/game-ui", "sg:domain/layout", "sg:domain/motion", "sg:domain/platform-guides", + "sg:domain/design-engineering", "sg:domain/design-terminology", "sg:domain/game-ui", "sg:domain/layout", "sg:domain/motion", "sg:domain/platform-guides", ]); const layout = recordForPath("layout/index.md"); const page = recordForPath("patterns/index.md"); @@ -138,10 +138,13 @@ test("search normalization preserves attached Unicode marks and delimits standal assert.equal(canonicalize(plain.result.results), canonicalize(normalized.result.results)); }); -test("known Layout ranking uses title=16 path=8 body=1 unique-token field membership", () => { +test("known Layout ranking uses rarity-weighted title=16 path=8 body=1 unique-token field membership", () => { const response = invoke("material-search", { query: "Layout", limit: 100 }); assert.equal(response.ok, true); assert.deepEqual(response.result.weights, MATERIAL_SEARCH_WEIGHTS); + assert.equal(response.result.rarity_weighting, "ceil(material_count / max(1, token_document_frequency))"); + assert.equal(response.result.rarity_weights.length, 1); + assert.equal(response.result.rarity_weights[0].token, "layout"); assert.equal(response.result.results[0].identity.stable_ref, "sg:domain/layout"); const layout = response.result.results.find(({ identity }) => identity.stable_ref === "sg:domain/layout"); const source = fs.readFileSync(path.join(repositoryRoot, "layout/index.md"), "utf8"); @@ -149,11 +152,24 @@ test("known Layout ranking uses title=16 path=8 body=1 unique-token field member const expected = Number(new Set(tokenizeMaterialText(title)).has("layout")) * 16 + Number(new Set(tokenizeMaterialText("layout/index.md")).has("layout")) * 8 + Number(new Set(tokenizeMaterialText(source)).has("layout")); - assert.equal(layout.score, expected); - assert.equal(layout.score, 25); + assert.equal(layout.score, expected * response.result.rarity_weights[0].multiplier); assert.deepEqual(layout.match_counts, { title: 1, path: 1, body: 1 }); }); +test("rarity weighting ranks the specific sticky intent above generic Layout hubs", () => { + const response = invoke("material-search", { query: "sticky layout", limit: 5, paths_only: true }); + assert.equal(response.ok, true); + assert.deepEqual(response.result.paths.slice(0, 3), [ + "patterns/split-sidebar/sticky-aside.md", + "patterns/viewport-shell/sticky-header.md", + "patterns/viewport-shell/sticky-footer.md", + ]); + const sticky = response.result.rarity_weights.find(({ token }) => token === "sticky"); + const layout = response.result.rarity_weights.find(({ token }) => token === "layout"); + assert.ok(sticky.document_frequency < layout.document_frequency); + assert.ok(sticky.multiplier > layout.multiplier); +}); + test("paths-only search preserves ranking while projecting repository-relative paths", () => { const standard = invoke("material-search", { query: "Layout", limit: 5 }); const projected = invoke("material-search", { query: "Layout", limit: 5, paths_only: true }); @@ -179,6 +195,12 @@ test("public domain leaf queries resolve to npm-portable repository paths", () = ["unity cli loop", "game-ui/unity/cli-loop.md"], ["motion review workflow", "motion/review-workflow.md"], ["Apple interaction", "platform-guides/apple-interaction.md"], + ["motion interaction recipes", "motion/interaction-recipes.md"], + ["component contract", "design-engineering/component-contract.md"], + ["game ui screen recipes", "game-ui/screen-recipes.md"], + ["android interaction", "platform-guides/android-interaction.md"], + ["windows interaction", "platform-guides/windows-interaction.md"], + ["design term comparison workflow", "design-terminology/comparison-workflow.md"], ]; for (const [query, expected] of cases) { const response = invoke("material-search", { query, limit: 5, paths_only: true }); @@ -201,10 +223,11 @@ test("synthetic equal scores tie strictly by projected StableRef", () => { const paths = ["motion/index.md", "game-ui/index.md"]; for (const repositoryPath of paths) fs.appendFileSync(path.join(root, repositoryPath), "\nzzztietoken\nzzztietoken\n"); rebindSources(root, paths); - const results = createMaterialOperationRegistry({ repositoryRoot: root }).invoke("material-search", { query: "zzztietoken", limit: 10 }).result.results; + const result = createMaterialOperationRegistry({ repositoryRoot: root }).invoke("material-search", { query: "zzztietoken", limit: 10 }).result; + const results = result.results; assert.equal(results.length, 2); - assert.equal(results[0].score, 1); - assert.equal(results[1].score, 1); + assert.equal(results[0].score, result.rarity_weights[0].multiplier); + assert.equal(results[1].score, result.rarity_weights[0].multiplier); assert.ok(results[0].identity.stable_ref < results[1].identity.stable_ref); } finally { fs.rmSync(root, { recursive: true, force: true }); } }); diff --git a/scripts/agent-native/v2/test-material-registry.mjs b/scripts/agent-native/v2/test-material-registry.mjs index 556db04..c5f707c 100644 --- a/scripts/agent-native/v2/test-material-registry.mjs +++ b/scripts/agent-native/v2/test-material-registry.mjs @@ -85,7 +85,7 @@ test.after(() => { for (const root of temporaryRoots) fs.rmSync(root, { recursiv test("generated registry is canonical, exact, source-bound, complete, and v1-isolated", () => { const beforeV1 = fs.readFileSync(v1RegistryPath); const generated = generateMaterialRegistry({ repositoryRoot }); - assert.equal(generated.materials.length, 126); + assert.equal(generated.materials.length, 147); assert.deepEqual(validateMaterialRegistry({ repositoryRoot, manifest: generated }), { ok: true, failures: [], materials: generated.materials }); assert.equal(generated.version_id, recomputeManifestVersion(generated)); assert.equal(generated.admission_policy_ref, materialAdmissionPolicy.stable_ref); diff --git a/scripts/agent-native/v2/test-sg-material-package.mjs b/scripts/agent-native/v2/test-sg-material-package.mjs index a54b851..2e41e68 100644 --- a/scripts/agent-native/v2/test-sg-material-package.mjs +++ b/scripts/agent-native/v2/test-sg-material-package.mjs @@ -29,6 +29,11 @@ const sentinels = [ "scripts/sg-mcp-shadow.mjs", ]; const mandatory = ["README.md", "package.json"]; +const stickyPaths = [ + "patterns/split-sidebar/sticky-aside.md", + "patterns/viewport-shell/sticky-header.md", + "patterns/viewport-shell/sticky-footer.md", +]; function relativeImports(source) { const imports = []; @@ -70,6 +75,10 @@ async function bounded(promise, label) { ]).finally(() => clearTimeout(timer)); } +function toolEnvelope(response) { + return response.structuredContent ?? JSON.parse(response.content.find(({ type }) => type === "text").text); +} + function copyPackage(source, destination) { fs.cpSync(source, destination, { recursive: true, @@ -156,6 +165,15 @@ try { }); assert.equal(install.status, 0, install.stderr || install.stdout); const installedRoot = path.join(installedProject, "node_modules", packageJson.name); + const materialCliPath = path.join(installedRoot, "scripts", "sg-material.mjs"); + const installedCliSearch = spawnSync(process.execPath, [materialCliPath, "search", "--query", "sticky layout", "--paths-only", "--limit", "5"], { + cwd: externalCwd, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, + }); + assert.equal(installedCliSearch.status, 0, installedCliSearch.stderr || installedCliSearch.stdout); + assert.equal(installedCliSearch.stderr, ""); + const installedCliReport = JSON.parse(installedCliSearch.stdout); + assert.equal(installedCliReport.ok, true); + assert.deepEqual(installedCliReport.result.paths.slice(0, 3), stickyPaths); const serverPath = path.join(installedRoot, "scripts", "sg-mcp.mjs"); assert.ok(fs.statSync(serverPath).isFile(), "installed v1 MCP entrypoint must exist"); const transport = new StdioClientTransport({ command: process.execPath, args: [serverPath], cwd: externalCwd, stderr: "pipe" }); @@ -181,8 +199,34 @@ try { try { await bounded(materialClient.connect(materialTransport), "installed material MCP initialize"); assert.deepEqual((await bounded(materialClient.listTools(), "installed material MCP tools")).tools.map(({ name }) => name), ["material-context", "material-discover", "material-get", "material-search"]); - assert.equal((await bounded(materialClient.listResources(), "installed material MCP resources")).resources.length, 126); + assert.equal((await bounded(materialClient.listResources(), "installed material MCP resources")).resources.length, 147); assert.deepEqual((await bounded(materialClient.listResourceTemplates(), "installed material MCP templates")).resourceTemplates.map(({ uriTemplate }) => uriTemplate), ["sg://v2/material/{reference}"]); + const installedMcpSearch = toolEnvelope(await bounded(materialClient.callTool({ + name: "material-search", + arguments: { query: "design terminology source kinds", paths_only: true, limit: 5 }, + }), "installed material MCP search")); + assert.equal(installedMcpSearch.ok, true); + assert.equal(installedMcpSearch.result.paths[0], "design-terminology/source-kinds.md"); + const domainWorkflows = [ + ["motion interaction recipes", "motion/interaction-recipes.md"], + ["component contract", "design-engineering/component-contract.md"], + ["game ui screen recipes", "game-ui/screen-recipes.md"], + ["android interaction", "platform-guides/android-interaction.md"], + ["windows interaction", "platform-guides/windows-interaction.md"], + ["design term comparison workflow", "design-terminology/comparison-workflow.md"], + ]; + for (const [query, expectedPath] of domainWorkflows) { + const cli = spawnSync(process.execPath, [materialCliPath, "search", "--query", query, "--paths-only", "--limit", "5"], { + cwd: externalCwd, encoding: "utf8", timeout: 30_000, + }); + assert.equal(cli.status, 0, cli.stderr || cli.stdout); + assert.equal(JSON.parse(cli.stdout).result.paths[0], expectedPath, query); + const mcp = toolEnvelope(await bounded(materialClient.callTool({ + name: "material-search", arguments: { query, paths_only: true, limit: 5 }, + }), `installed domain search: ${query}`)); + assert.equal(mcp.ok, true); + assert.equal(mcp.result.paths[0], expectedPath, query); + } } finally { await bounded(materialClient.close(), "installed material MCP shutdown"); } @@ -201,7 +245,10 @@ try { bins_executable: true, declared_runtime_roots_derived: true, installed_v1_mcp_official_sdk: true, + installed_material_cli_search: true, installed_material_mcp_official_sdk: true, + installed_material_mcp_search: true, + installed_non_layout_workflow_searches: 6, installed_external_spaced_cwd: true, }, null, 2)}\n`); } finally { diff --git a/scripts/governance-test-fixture.mjs b/scripts/governance-test-fixture.mjs index 74c29db..0bf2072 100644 --- a/scripts/governance-test-fixture.mjs +++ b/scripts/governance-test-fixture.mjs @@ -39,7 +39,7 @@ export const files = { "index.md": "# StyleGallery\n\n- [Governance, lifecycle, and docs-as-code](GOVERNANCE.md)\n- [StyleGallery Domains](DOMAINS.md)\n", "DOMAINS.md": "# StyleGallery Domains\n\n### Consumer Reference Promotion\n\nConsumer-reference promotion does not add a domain. See the [canonical promotion contract](consumer-reference/contract.md#promotion-boundary) for the full human-readable rules and the [canonical JSON promotion policy](consumer-reference/policies/shared-experimental.json) for machine policy.\n", "consumer-reference/contract.md": `## Promotion Boundary\n\nThe [shared-experimental promotion policy](policies/shared-experimental.json) is the canonical machine-readable policy, and the [promotion RFC schema](schema/promotion-rfc.schema.json) owns the RFC record shape.\nThe StyleGallery-local \`>=2\` independent-consumer gateway applies only to consumer-local → shared-experimental invariant eligibility. Shared stable has no numeric adoption threshold. Normative correctness may waive adoption count only.\nThey are not accepted or promoted RFCs. Synthetic examples have zero adopter attestations and record no promotion. A stable contract whose evidence later fails cannot be silently relabeled experimental.\nReview truth uses one enum; boolean aliases are invalid.\n${sentinelProvenanceClauses.join("\n")}\n`, - "consumer-reference/index.md": "Consumer Reference is outside the five-domain contract.\n[Promotion RFC schema](schema/promotion-rfc.schema.json)\n[Shared-experimental promotion policy](policies/shared-experimental.json)\n", + "consumer-reference/index.md": "Consumer Reference is outside the six-domain contract.\n[Promotion RFC schema](schema/promotion-rfc.schema.json)\n[Shared-experimental promotion policy](policies/shared-experimental.json)\n", "consumer-reference/fixtures/promotion/manifest.json": '{"id": "promotion-fixture-inventory"}\n', "consumer-reference/policies/shared-experimental.json": '{"review_independence": "single_account", "promotion_occurred": false, "adopter_attestations": 0, "stable_numeric_threshold": null}\n', "CATALOG.md": `# Layout Pattern Catalog\n\n${generatedWarning}\n`, @@ -59,7 +59,7 @@ export const files = { "quality/evidence/executable-evidence.md": [ "| Claim | Validator or test | CI command | Positive evidence | Negative evidence | Evidence boundary |", "| Governance, lifecycle, generated-file, ownership, and stale-content policy remain discoverable and CI-enforced. | `scripts/validate-governance.mjs` and `scripts/test-validate-governance.mjs` | `node scripts/validate-governance.mjs --json`; `node scripts/test-validate-governance.mjs --json` | `GOVERNANCE.md`, `.github/CODEOWNERS`, generated warnings, generated metadata, root links, lifecycle states, stale-audit decision, and CI wiring are present. | Missing governance file, generated warning, generated metadata, CODEOWNERS coverage, or stale policy fixtures must fail. | Proves governance policy is present and linked, not that CODEOWNERS users have verified repository write access. |", - "| Domain topology, metadata, provenance, scope boundaries, and root routes remain enforced. | `scripts/validate-domains.mjs` and `scripts/test-validate-domains.mjs` | `node scripts/validate-domains.mjs --json`; `node scripts/test-validate-domains.mjs` | Five governed domains and their declared leaves are reachable and attributed. | Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail. | A full SHA proves content identity syntax, not publisher authenticity or local quality. |", + "| Domain topology, metadata, provenance, scope boundaries, and root routes remain enforced. | `scripts/validate-domains.mjs` and `scripts/test-validate-domains.mjs` | `node scripts/validate-domains.mjs --json`; `node scripts/test-validate-domains.mjs` | Six governed domains and their declared leaves are reachable and attributed. | Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail. | A full SHA proves content identity syntax, not publisher authenticity or local quality. |", "Consumer-reference handoffs, schema/runtime parity, and containment remain enforced; repository handoff omissions must fail.", "Promotion governance remains a closed JSON-only, invariant-scoped, deferred example contract.", "Synthetic validation does not authenticate adoption, organizations, owners, support capacity, provenance, or a promotion decision.", @@ -307,6 +307,7 @@ export const files = { "| Design Engineering domain guidance | `design-engineering/*.md` | Manual | None | `experimental` | Upstream revision, evidence boundary, or guidance changes. | `scripts/validate-domains.mjs` | Design Engineering domain owner |", "| Game UI domain guidance | `game-ui/**/*.md` | Manual | None | `experimental` | Classification, hierarchy, engine implementation, evidence boundary, or route changes. | `scripts/validate-domains.mjs` | Game UI domain owner |", "| Platform Guides domain guidance | `platform-guides/*.md` | Manual | None | `experimental` | Platform version, upstream revision, evidence boundary, or guidance changes. | `scripts/validate-domains.mjs` | Platform Guides domain owner |", + "| Design Terminology domain guidance | `design-terminology/*.md` | Manual | None | `experimental` | Source-kind, source-vocabulary, concept-family, relation-model, or conflict-case changes. | `scripts/validate-domains.mjs`, `scripts/validate-design-terminology.mjs` | Design Terminology domain owner |", "| Pattern data and examples | `scripts/pattern-data.mjs` | Manual data source | `patterns/**/*.md` | `generated` output from `stable` source | Source-lineage URL changes, generated drift, category changes, or pattern count changes. | `scripts/validate-patterns.mjs`, `scripts/validate-catalog.mjs`, `scripts/validate-governance.mjs` | Pattern-data owner |", "| Pattern generator | `scripts/generate-patterns.mjs` | Manual code source | `patterns/**/*.md` | `stable` generator, `generated` output | Generated structure changes, generated-warning changes, or generated metadata changes. | `node -c scripts/generate-patterns.mjs` | Pattern-data owner |", "| Validation scripts | `scripts/validate-*.mjs`, `scripts/test-validate-*.mjs` | Manual code source | CI validation output | `node -c` | Validation owner |", diff --git a/scripts/test-validate-design-terminology.mjs b/scripts/test-validate-design-terminology.mjs new file mode 100644 index 0000000..739b3ac --- /dev/null +++ b/scripts/test-validate-design-terminology.mjs @@ -0,0 +1,91 @@ +#!/usr/bin/env node + +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { validateDesignTerminology } from "./validate-design-terminology.mjs"; + +// Synthetic sources test invariants only. They make no real terminology claims. +const term = (id, label, status = "current", source = "Example") => `| \`sample.${id}\` | ${label} | [${source}](https://example.org/terms/${id}) (\`design-system\`) | concept-${id} | ${status} | version 2025.10 | 2026-09-08 |`; +const relation = (from, to, type, scope = "catalog", direction = "directional", boundary = "The declared sample scope includes this mapping and excludes unrelated instances.") => `| \`sample.${from}\` | \`sample.${to}\` | \`${type}\` | ${scope} | ${direction} | ${boundary} | 2026-09-08 |`; +const terms = [term("a", "Alpha"), term("b", "Beta"), term("c", "Gamma"), term("d", "Delta")]; +const relations = [relation("a", "b", "broader_than"), relation("b", "c", "broader_than"), relation("c", "d", "implementation_representation", "output")]; +const base = [ + "# Synthetic terms", "", "## Term Records", "", + "| Term | Label | Source (kind) | Concept | Status | Scope | Reviewed on |", + "| --- | --- | --- | --- | --- | --- | --- |", ...terms, "", + "## Recorded Relations", "", + "| From | To | Type | Scope | Direction | Boundary | Reviewed on |", + "| --- | --- | --- | --- | --- | --- | --- |", ...relations, "", +].join("\n"); +const change = (before, after) => (content) => { + assert.ok(content.includes(before), `fixture mutation target missing: ${before}`); + const changed = content.replace(before, after); + assert.notEqual(changed, content, "fixture mutation must change bytes"); + return changed; +}; +const add = (row) => (content) => `${content}${row}\n`; +const temporal = (content) => content.replace(terms[0], term("a", "Alpha", "historical")) + .replace(relations[0], relation("a", "b", "renamed_to", "rename", "directional", "Example replaced Alpha with Beta in version 2025.10; the old label is historical.")); + +const cases = [ + { name: "valid", expected: null }, + { name: "valid_inverse", mutate: add(relation("b", "a", "narrower_than")), expected: null }, + { name: "separate_scope", mutate: add(relation("b", "a", "broader_than", "other-scope")), expected: null }, + { name: "valid_temporal", mutate: temporal, expected: null }, + { name: "valid_leap_date", mutate: change("2026-09-08", "2024-02-29"), expected: null }, + { name: "duplicate_term", mutate: change(terms[0], `${terms[0]}\n${terms[0]}`), expected: "duplicate term" }, + { name: "missing_label", mutate: change("| Alpha |", "| |"), expected: "missing label" }, + { name: "aggregate_source", mutate: change("[Example](https://example.org/terms/a) (`design-system`)", "multiple systems"), expected: "source must name one" }, + { name: "bad_source_kind", mutate: change("`design-system`", "`cool-tool`"), expected: "source must name one" }, + { name: "unsafe_source", mutate: change("https://example.org/terms/a", "javascript:alert"), expected: "source locator" }, + { name: "local_source_missing", mutate: change("https://example.org/terms/a", "missing.md"), expected: "source locator" }, + { name: "local_source_escape", mutate: change("https://example.org/terms/a", "../../outside.md"), expected: "source locator" }, + { name: "bad_status", mutate: change("| current |", "| maybe |"), expected: "status must be" }, + { name: "bad_date", mutate: change("2026-09-08", "Sep 8"), expected: "real YYYY-MM-DD" }, + { name: "impossible_day", mutate: change("2026-09-08", "2026-02-30"), expected: "real YYYY-MM-DD" }, + { name: "non_leap_day", mutate: change("2026-09-08", "2025-02-29"), expected: "real YYYY-MM-DD" }, + { name: "historical_scope_missing", mutate: change(terms[0], term("a", "Alpha", "historical").replace("version 2025.10", "unspecified era")), expected: "historical term requires" }, + { name: "unknown_relation", mutate: change("`broader_than`", "`overlaps`"), expected: "unknown relation type" }, + { name: "unrecorded_term", mutate: change(relations[0], relations[0].replace("`sample.b`", "`sample.ghost`")), expected: "to-term must be" }, + { name: "orphan_term", mutate: change(terms[0], `${terms[0]}\n${term("unused", "Unused")}`), expected: "orphan term" }, + { name: "self_relation", mutate: add(relation("a", "a", "broader_than")), expected: "self relation" }, + { name: "empty_boundary", mutate: change(relations[0], relation("a", "b", "broader_than", "catalog", "directional", "")), expected: "non-trivial scope" }, + { name: "empty_scope", mutate: change("| catalog |", "| |"), expected: "scope must be" }, + { name: "bad_direction", mutate: change("| directional |", "| symmetric |"), expected: "invalid direction" }, + { name: "duplicate_relation", mutate: add(relations[0]), expected: "duplicate or contradictory" }, + { name: "same_direction_contradiction", mutate: add(relation("a", "b", "narrower_than")), expected: "duplicate or contradictory" }, + { name: "reverse_contradiction", mutate: add(relation("b", "a", "broader_than")), expected: "conflicting reverse" }, + { name: "cycle_three_nodes", mutate: add(relation("c", "a", "broader_than")), expected: "containment cycle" }, + { name: "reverse_representation", mutate: add(relation("d", "c", "implementation_representation", "output")), expected: "conflicting reverse" }, + { name: "same_label_mismatch", mutate: change(relations[0], relation("a", "b", "same_label_different_meaning", "labels", "symmetric")), expected: "requires identical labels" }, + { name: "rename_without_event", mutate: (content) => temporal(content).replace("Example replaced Alpha with Beta in version 2025.10; the old label is historical.", "The source replaced this label at an unspecified point in its history."), expected: "time or version basis" }, + { name: "rename_across_sources", mutate: (content) => temporal(content).replace("[Example](https://example.org/terms/b)", "[Other](https://example.org/terms/b)"), expected: "one named source" }, + { name: "rename_current_source", mutate: (content) => temporal(content).replace("| historical |", "| current |"), expected: "temporal relation requires" }, + { name: "deprecation_status", mutate: (content) => temporal(content).replace("`renamed_to`", "`deprecated_in_favor_of`"), expected: "deprecation requires" }, + { name: "records_only_in_fence", mutate: (content) => `\x60\x60\x60md\n${content}\x60\x60\x60\n`, expected: "expected exactly one section" }, + { name: "records_only_in_comment", mutate: (content) => ``, expected: "expected exactly one section" }, + { name: "wrong_heading_level", mutate: change("## Term Records", "### Term Records"), expected: "expected exactly one section" }, + { name: "inline_heading", mutate: change("## Term Records", "text ## Term Records"), expected: "expected exactly one section" }, + { name: "duplicate_section", mutate: (content) => `${content}\n## Term Records\n`, expected: "expected exactly one section" }, + { name: "invalid_header", mutate: change("| From | To |", "| Start | End |"), expected: "unexpected table header" }, + { name: "empty_records", mutate: (content) => content.replace(terms.join("\n"), ""), expected: "missing records" }, +]; + +const results = []; +for (const testCase of cases) { + const root = fs.mkdtempSync(path.join(os.tmpdir(), `sg-term-${testCase.name}-`)); + try { + fs.mkdirSync(path.join(root, "design-terminology")); + fs.writeFileSync(path.join(root, "design-terminology/conflict-cases.md"), testCase.mutate ? testCase.mutate(base) : base); + const result = validateDesignTerminology({ root }); + const ok = testCase.expected === null ? result.ok : !result.ok && result.failures.some((failure) => failure.includes(testCase.expected)); + results.push({ name: testCase.name, ok, ...(!ok ? { actual: result.failures } : {}) }); + } finally { fs.rmSync(root, { recursive: true, force: true }); } +} +const corpus = validateDesignTerminology(); +results.push({ name: "current_corpus", ok: corpus.ok, ...(!corpus.ok ? { actual: corpus.failures } : {}) }); +const report = { ok: results.every(({ ok }) => ok), cases: results.length, failures: results.filter(({ ok }) => !ok) }; +console.log(JSON.stringify(report, null, 2)); +process.exitCode = report.ok ? 0 : 1; diff --git a/scripts/test-validate-domains.mjs b/scripts/test-validate-domains.mjs index 3d8bc8b..b5cd975 100644 --- a/scripts/test-validate-domains.mjs +++ b/scripts/test-validate-domains.mjs @@ -12,11 +12,11 @@ const revision = "220e8607c90b17337d210125777b7b695f26c221"; const repository = "https://github.com/emilkowalski/skills"; const unityCliLoopRepository = "https://github.com/hatayama/unity-cli-loop"; const unityCliLoopRevision = "61a0fe6d7da0aa9d0bcbc6d95944dd069c483ff0"; -const vocabularyDomainList = "Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, root routing, and `domain` frontmatter on governed leaves."; -const qualityDomainList = "`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, and Platform Guides claims are admissible."; -const readmeConsumerReferenceBoundary = "without owning profiles, visual values, components, or a sixth domain"; -const qualityConsumerReferenceBoundary = "without classifying it as a sixth domain"; -const executableEvidenceDomainCoverage = "Five governed domains and their declared leaves are reachable and attributed."; +const vocabularyDomainList = "Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, Design Terminology, root routing, and `domain` frontmatter on governed leaves."; +const qualityDomainList = "`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, Platform Guides, and Design Terminology claims are admissible."; +const readmeConsumerReferenceBoundary = "without owning profiles, visual values, components, or a seventh domain"; +const qualityConsumerReferenceBoundary = "without classifying it as a seventh domain"; +const executableEvidenceDomainCoverage = "Six governed domains and their declared leaves are reachable and attributed."; const gameUiFindabilityScenario = "| Find the authority route for uGUI, UI Toolkit, or NGUI. | [README](../README.md) | [Unity UI Systems](../game-ui/unity/ui-systems.md) | The first selected route is Game UI, and the system-specific source and version boundary is reached within three hops. |"; function indexPage(title, links) { @@ -121,8 +121,8 @@ const localLeaf = leafPage({ }); const baseFiles = { - "README.md": `# StyleGallery\n\nConsumer Reference is shared non-domain infrastructure ${readmeConsumerReferenceBoundary}.\n\n- [Layout](layout/index.md)\n- [Motion](motion/index.md)\n- [Design Engineering](design-engineering/index.md)\n- [Game UI](game-ui/index.md)\n- [Platform Guides](platform-guides/index.md)\n`, - "index.md": "# StyleGallery\n\n- [Layout](layout/index.md)\n- [Motion](motion/index.md)\n- [Design Engineering](design-engineering/index.md)\n- [Game UI](game-ui/index.md)\n- [Platform Guides](platform-guides/index.md)\n", + "README.md": `# StyleGallery\n\nConsumer Reference is shared non-domain infrastructure ${readmeConsumerReferenceBoundary}.\n\n- [Layout](layout/index.md)\n- [Motion](motion/index.md)\n- [Design Engineering](design-engineering/index.md)\n- [Game UI](game-ui/index.md)\n- [Platform Guides](platform-guides/index.md)\n- [Design Terminology](design-terminology/index.md)\n`, + "index.md": "# StyleGallery\n\n- [Layout](layout/index.md)\n- [Motion](motion/index.md)\n- [Design Engineering](design-engineering/index.md)\n- [Game UI](game-ui/index.md)\n- [Platform Guides](platform-guides/index.md)\n- [Design Terminology](design-terminology/index.md)\n", "DOMAINS.md": [ "# StyleGallery Domains", "", @@ -135,6 +135,7 @@ const baseFiles = { "| Design Engineering | [Design Engineering](design-engineering/index.md) | `experimental` |", "| Game UI | [Game UI](game-ui/index.md) | `experimental` |", "| Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` |", + "| Design Terminology | [Design Terminology](design-terminology/index.md) | `experimental` |", "", "## Page Manifest", "", @@ -145,12 +146,13 @@ const baseFiles = { "| Design Engineering | `design-engineering/index.md` | `design-engineering/interface-craft.md`, `design-engineering/consumer-migration-readiness.md`, `design-engineering/reference-profiles/index.md`, `design-engineering/reference-profiles/governed-local/index.md`, `design-engineering/reference-profiles/external-adaptation/index.md` |", "| Game UI | `game-ui/index.md` | `game-ui/classification.md`, `game-ui/screen-hierarchy.md`, `game-ui/reference-record.md`, `game-ui/unity/architecture.md`, `game-ui/unity/ui-systems.md`, `game-ui/unity/cli-loop.md`, `game-ui/unity/repository-map.md`, `game-ui/unity/org-wiki.md` |", "| Platform Guides | `platform-guides/index.md` | `platform-guides/apple-interaction.md` |", + "| Design Terminology | `design-terminology/index.md` | `design-terminology/source-kinds.md`, `design-terminology/source-vocabularies.md`, `design-terminology/concept-families.md`, `design-terminology/relation-types.md`, `design-terminology/conflict-cases.md` |", "", `Source snapshot \`${revision}\`.`, "", "## Shared Non-Domain Infrastructure", "", - "[Consumer Reference](consumer-reference/index.md) is shared infrastructure outside the five-domain contract and cannot add a sixth domain row.", + "[Consumer Reference](consumer-reference/index.md) is shared infrastructure outside the six-domain contract and cannot add a seventh domain row.", "", "## Lifecycle And Staleness", "", @@ -194,6 +196,12 @@ const baseFiles = { "game-ui/unity/org-wiki.md": leafPage({ title: "Unity Organization Compressed Wiki", domain: "game-ui", parent: "../index.md", next: "../../platform-guides/index.md" }), "platform-guides/index.md": indexPage("Platform Guides", [["Apple Interaction", "apple-interaction.md"]]), "platform-guides/apple-interaction.md": leafPage({ title: "Apple Interaction", domain: "platform-guides", sourcePath: "skills/apple-design/SKILL.md", parent: "index.md", next: "../layout/index.md" }), + "design-terminology/index.md": indexPage("Design Terminology", [["Design Source Kinds", "source-kinds.md"], ["Design Source Vocabularies", "source-vocabularies.md"], ["Design Concept Families", "concept-families.md"], ["Design Term Relations", "relation-types.md"], ["Cross-System Term Cases", "conflict-cases.md"]]), + "design-terminology/source-kinds.md": leafPage({ title: "Design Source Kinds", domain: "design-terminology", parent: "index.md", next: "source-vocabularies.md" }), + "design-terminology/source-vocabularies.md": leafPage({ title: "Design Source Vocabularies", domain: "design-terminology", parent: "index.md", next: "concept-families.md" }), + "design-terminology/concept-families.md": leafPage({ title: "Design Concept Families", domain: "design-terminology", parent: "index.md", next: "relation-types.md" }), + "design-terminology/relation-types.md": leafPage({ title: "Design Term Relations", domain: "design-terminology", parent: "index.md", next: "conflict-cases.md" }), + "design-terminology/conflict-cases.md": leafPage({ title: "Cross-System Term Cases", domain: "design-terminology", parent: "index.md", next: "../layout/index.md" }), "quality/claim-records/stylegallery-multidomain-scope.md": "# Scope Decision\n\nStyleGallery supersedes the layout-only repository identity.\n", "guides/vocabulary.md": `# Controlled Vocabulary\n\n- Canonical: \`domain\`\n - ${vocabularyDomainList}\n`, "quality/index.md": `# Quality Gates\n\n${qualityDomainList}\n\nThe handoff reaches the shared contract ${qualityConsumerReferenceBoundary}.\n\n${gameUiFindabilityScenario}\n`, @@ -201,11 +209,89 @@ const baseFiles = { "CATALOG.md": "# Catalog\n", }; +const additionalLocalLeaves = { + "motion": [ + [ + "decision-tree.md", + "Motion Decision Tree" + ], + [ + "motion-brief.md", + "Motion Brief" + ], + [ + "interaction-recipes.md", + "Motion Interaction Recipes" + ] + ], + "design-engineering": [ + [ + "decision-tree.md", + "Design Engineering Decision Tree" + ], + [ + "component-contract.md", + "Component Contract" + ], + [ + "worked-examples.md", + "Design Engineering Worked Examples" + ] + ], + "game-ui": [ + [ + "decision-tree.md", + "Game UI Decision Tree" + ], + [ + "screen-recipes.md", + "Game UI Screen Recipes" + ], + [ + "verification-workflow.md", + "Game UI Verification Workflow" + ] + ], + "platform-guides": [ + [ + "adaptation-workflow.md", + "Platform Adaptation Workflow" + ], + [ + "android-interaction.md", + "Android Interaction As A Comparative Reference" + ], + [ + "windows-interaction.md", + "Windows Interaction As A Comparative Reference" + ], + [ + "compatibility-matrix.md", + "Platform Compatibility Matrix" + ] + ], + "design-terminology": [ + [ + "comparison-workflow.md", + "Design Term Comparison Workflow" + ] + ] +}; + +for (const [domain, leaves] of Object.entries(additionalLocalLeaves)) { + for (const [name, title] of leaves) { + baseFiles[`${domain}/${name}`] = leafPage({ title, domain, parent: "index.md", next: "../DOMAINS.md", provenanceKind: "local" }); + baseFiles[`${domain}/index.md`] += `\n- [${title}](${name})\n`; + } + baseFiles["DOMAINS.md"] = baseFiles["DOMAINS.md"].split("\n").map((line) => line.includes(`| \`${domain}/index.md\` |`) + ? `${line.slice(0, -2)}, ${leaves.map(([name]) => `\`${domain}/${name}\``).join(", ")} |` : line).join("\n"); +} + const cases = [ { name: "empty_manifest", mutate: ["DOMAINS.md", baseFiles["DOMAINS.md"], "# Empty manifest\n"], expect: "DOMAINS.md: missing canonical domain contract" }, { name: "manifest_extra_domain", mutate: ["DOMAINS.md", "| Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` |", "| Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` |\n| Other | [Other](other/index.md) | `experimental` |"], expect: "DOMAINS.md: missing canonical domain contract" }, { name: "consumer_reference_sixth_domain", mutate: ["DOMAINS.md", "| Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` |", "| Platform Guides | [Platform Guides](platform-guides/index.md) | `experimental` |\n| Consumer Reference | [Consumer Reference](consumer-reference/index.md) | `stable` |"], expect: "DOMAINS.md: missing canonical domain contract" }, - { name: "consumer_reference_four_domain_contract", mutate: ["DOMAINS.md", "five-domain contract", "four-domain contract"], expect: "DOMAINS.md: missing canonical domain contract" }, + { name: "consumer_reference_wrong_domain_count", mutate: ["DOMAINS.md", "six-domain contract", "five-domain contract"], expect: "DOMAINS.md: missing canonical domain contract" }, { name: "domain_lifecycle_reader_gate", mutate: ["DOMAINS.md", "User studies, reader tasks, adoption counts, and attestations are neither required nor sufficient for a domain lifecycle change.", "User studies and reader tasks are required for a domain lifecycle change."], expect: "DOMAINS.md: missing lifecycle boundary User studies, reader tasks, adoption counts, and attestations are neither required nor sufficient for a domain lifecycle change." }, { name: "consumer_promotion_claims_domain_lifecycle", mutate: ["DOMAINS.md", "does not govern domain or page lifecycle", "also governs domain and page lifecycle"], expect: "DOMAINS.md: missing promotion boundary does not govern domain or page lifecycle" }, { name: "promotion_stable_by_count", mutate: ["DOMAINS.md", "Shared stable has no numeric adoption threshold.", "Shared stable uses a numeric adoption threshold."], expect: "DOMAINS.md: missing promotion boundary Shared stable has no numeric adoption threshold" }, @@ -217,6 +303,8 @@ const cases = [ { name: "missing_domain_index", omit: ["design-engineering/index.md"], expect: "design-engineering/index.md: missing file" }, { name: "missing_domain_leaf", omit: ["motion/vocabulary.md"], expect: "motion/vocabulary.md: missing file" }, { name: "missing_local_domain_leaf", omit: ["game-ui/classification.md"], expect: "game-ui/classification.md: missing file" }, + { name: "missing_design_terminology_hub", omit: ["design-terminology/index.md"], expect: "design-terminology/index.md: missing file" }, + { name: "missing_design_terminology_leaf", omit: ["design-terminology/source-kinds.md"], expect: "design-terminology/source-kinds.md: missing file" }, { name: "missing_unity_ui_systems_leaf", omit: ["game-ui/unity/ui-systems.md"], expect: "game-ui/unity/ui-systems.md: missing file" }, { name: "missing_unity_cli_loop_leaf", omit: ["game-ui/unity/cli-loop.md"], expect: "game-ui/unity/cli-loop.md: missing file" }, { name: "missing_unity_repository_map_leaf", omit: ["game-ui/unity/repository-map.md"], expect: "game-ui/unity/repository-map.md: missing file" }, @@ -241,6 +329,7 @@ const cases = [ }, { name: "undeclared_local_leaf", add: ["design-engineering/rogue-local.md", localLeaf.replace("title: Consumer Migration Readiness", "title: Rogue Local Method")], expect: "design-engineering/rogue-local.md: undeclared governed domain document" }, { name: "undeclared_nested_game_ui_leaf", add: ["game-ui/unity/rogue.md", "# Rogue\n"], expect: "game-ui/unity/rogue.md: undeclared governed domain document" }, + { name: "undeclared_design_terminology_leaf", add: ["design-terminology/rogue.md", "# Rogue\n"], expect: "design-terminology/rogue.md: undeclared governed domain document" }, { name: "unknown_domain", mutate: ["motion/vocabulary.md", "domain: motion", "domain: unknown"], expect: "motion/vocabulary.md: unknown domain unknown" }, { name: "wrong_domain", mutate: ["motion/vocabulary.md", "domain: motion", "domain: platform-guides"], expect: "motion/vocabulary.md: domain platform-guides does not match motion" }, { name: "missing_lifecycle", mutate: ["motion/vocabulary.md", "lifecycle: experimental\n", ""], expect: "motion/vocabulary.md: missing lifecycle" }, @@ -276,12 +365,12 @@ const cases = [ { name: "omo_directory_dependency", mutate: ["motion/vocabulary.md", "Verify the claim on its actual surface.", "Verify with [draft](../.omo)."], expect: "motion/vocabulary.md: tracked document must not depend on .omo" }, { name: "omo_reference_dependency", mutate: ["motion/vocabulary.md", "Verify the claim on its actual surface.", "Verify with [draft][work].\n\n[work]: ../.omo/research.md"], expect: "motion/vocabulary.md: tracked document must not depend on .omo" }, { name: "canonical_while_experimental", mutate: ["motion/vocabulary.md", "Treat practitioner preferences as hypotheses.", "This is canonical universal policy."], expect: "motion/vocabulary.md: experimental document claims canonical authority" }, - { name: "vocabulary_missing_game_ui", mutate: ["guides/vocabulary.md", vocabularyDomainList, vocabularyDomainList.replace("Game UI, ", "")], expect: "guides/vocabulary.md: missing canonical five-domain vocabulary list" }, - { name: "quality_missing_game_ui", mutate: ["quality/index.md", qualityDomainList, qualityDomainList.replace("Game UI, and ", "and ")], expect: "quality/index.md: missing canonical five-domain quality scope" }, + { name: "vocabulary_missing_game_ui", mutate: ["guides/vocabulary.md", vocabularyDomainList, vocabularyDomainList.replace("Game UI, ", "")], expect: "guides/vocabulary.md: missing canonical domain vocabulary list" }, + { name: "quality_missing_game_ui", mutate: ["quality/index.md", qualityDomainList, qualityDomainList.replace("Game UI, ", "")], expect: "quality/index.md: missing canonical domain quality scope" }, { name: "quality_missing_game_ui_findability_scenario", mutate: ["quality/index.md", `${gameUiFindabilityScenario}\n`, ""], expect: "quality/index.md: missing Game UI findability QA scenario" }, - { name: "readme_stale_consumer_reference_ordinal", mutate: ["README.md", "sixth domain", "fifth domain"], expect: "README.md: missing canonical Consumer Reference boundary" }, - { name: "quality_stale_consumer_reference_ordinal", mutate: ["quality/index.md", "sixth domain", "fifth domain"], expect: "quality/index.md: missing canonical Consumer Reference boundary" }, - { name: "executable_evidence_stale_domain_count", mutate: ["quality/evidence/executable-evidence.md", "Five governed domains", "Four governed domains"], expect: "quality/evidence/executable-evidence.md: missing canonical five-domain validator coverage" }, + { name: "readme_stale_consumer_reference_ordinal", mutate: ["README.md", "seventh domain", "sixth domain"], expect: "README.md: missing canonical Consumer Reference boundary" }, + { name: "quality_stale_consumer_reference_ordinal", mutate: ["quality/index.md", "seventh domain", "sixth domain"], expect: "quality/index.md: missing canonical Consumer Reference boundary" }, + { name: "executable_evidence_stale_domain_count", mutate: ["quality/evidence/executable-evidence.md", "Six governed domains", "Five governed domains"], expect: "quality/evidence/executable-evidence.md: missing canonical domain validator coverage" }, { name: "success_path", expect: null }, ]; diff --git a/scripts/validate-design-terminology.mjs b/scripts/validate-design-terminology.mjs new file mode 100644 index 0000000..6206950 --- /dev/null +++ b/scripts/validate-design-terminology.mjs @@ -0,0 +1,162 @@ +#!/usr/bin/env node + +// Markdown remains the term-record source of truth. This checks record and graph +// consistency; it cannot prove the semantics of an external source or judgment. +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { structuralMarkdown } from "./markdown-structure.mjs"; + +const RELATION_TYPES = new Set([ + "equivalent_within_scope", "near_equivalent", "partial_overlap", "broader_than", "narrower_than", + "implementation_representation", "renamed_to", "deprecated_in_favor_of", "same_label_different_meaning", "not_comparable", +]); +const SYMMETRIC_TYPES = new Set(["equivalent_within_scope", "partial_overlap", "same_label_different_meaning", "not_comparable"]); +const SOURCE_KINDS = new Set(["design-system", "platform-guideline", "specification", "design-tool", "pattern-library", "brand-style-guide", "web-platform"]); +const STATUSES = new Set(["current", "deprecated", "historical", "unknown"]); +const TERM_ID = /^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)+$/; +const identifier = (cell) => /^`([^`]+)`$/.exec(cell)?.[1]; +const validDate = (value) => /^20\d\d-\d{2}-\d{2}$/.test(value) + && Number.isFinite(Date.parse(`${value}T00:00:00Z`)) + && new Date(`${value}T00:00:00Z`).toISOString().slice(0, 10) === value; + +function table(content, heading, expectedHeader, failures) { + const sections = content.split(new RegExp(`^## ${heading}\\s*$`, "m")); + if (sections.length !== 2) { + failures.push(`${heading}: expected exactly one section`); + return []; + } + const rows = sections[1].split("\n## ")[0].split("\n") + .filter((line) => /^\|.*\|\s*$/.test(line.trim())) + .map((line) => line.trim().slice(1, -1).split("|").map((cell) => cell.trim())); + if (JSON.stringify(rows[0]) !== JSON.stringify(expectedHeader)) failures.push(`${heading}: unexpected table header`); + if (!rows[1]?.every((cell) => /^:?-+:?$/.test(cell)) || rows[1]?.length !== expectedHeader.length) { + failures.push(`${heading}: missing table separator`); + } + const records = rows.slice(2); + if (records.length === 0) failures.push(`${heading}: missing records`); + return records; +} + +function validLocator(locator, root) { + if (!locator) return false; + if (locator.startsWith("https://")) { + try { + const url = new URL(locator); + return Boolean(url.hostname) && !url.username && !url.password; + } catch { return false; } + } + if (/[\\\s]/.test(locator) || /^[a-z]+:/i.test(locator) || locator.startsWith("/")) return false; + const target = path.resolve(root, "design-terminology", locator.split(/[?#]/)[0]); + return target.startsWith(`${path.resolve(root)}${path.sep}`) && fs.existsSync(target) && fs.statSync(target).isFile(); +} + +function hasCycle(edges) { + const visited = new Set(); + const visiting = new Set(); + function visit(node) { + if (visiting.has(node)) return true; + if (visited.has(node)) return false; + visiting.add(node); + for (const next of edges.get(node) ?? []) if (visit(next)) return true; + visiting.delete(node); + visited.add(node); + return false; + } + return [...edges.keys()].some(visit); +} + +export function validateDesignTerminology({ root = process.cwd() } = {}) { + const failures = []; + const relative = "design-terminology/conflict-cases.md"; + const target = path.join(root, relative); + if (!fs.existsSync(target)) return { ok: false, terms: 0, relations: 0, failures: [`${relative}: missing file`] }; + const content = structuralMarkdown(fs.readFileSync(target, "utf8")); + const termRows = table(content, "Term Records", ["Term", "Label", "Source (kind)", "Concept", "Status", "Scope", "Reviewed on"], failures); + const terms = new Map(); + termRows.forEach((row, index) => { + const location = `${relative} term row ${index + 1}`; + if (row.length !== 7) { failures.push(`${location}: expected 7 columns`); return; } + const [termCell, label, sourceCell, concept, status, scope, reviewed] = row; + const id = identifier(termCell); + const source = /^\[([^\]]+)\]\(([^)]+)\)\s+\(`([^`]+)`\)$/.exec(sourceCell); + if (!id || !TERM_ID.test(id)) failures.push(`${location}: term must carry one source-qualified identifier`); + if (terms.has(id)) failures.push(`${location}: duplicate term ${id}`); + if (!label) failures.push(`${location}: missing label`); + if (!source || !SOURCE_KINDS.has(source[3])) failures.push(`${location}: source must name one closed source kind and direct locator`); + if (!validLocator(source?.[2], root)) failures.push(`${location}: source locator must be HTTPS or an existing repository document`); + if (!concept) failures.push(`${location}: missing concept`); + if (!STATUSES.has(status)) failures.push(`${location}: status must be current, deprecated, historical, or unknown`); + if (!scope) failures.push(`${location}: missing scope`); + if (!validDate(reviewed)) failures.push(`${location}: reviewed_on must be a real YYYY-MM-DD date`); + if (status === "historical" && !/\b(?:19|20)\d{2}\b|\bversion\b|\bdraft\b/i.test(scope)) failures.push(`${location}: historical term requires a dated or versioned scope`); + if (id && !terms.has(id)) terms.set(id, { label, source: source?.[1], concept, scope, status }); + }); + + const relationRows = table(content, "Recorded Relations", ["From", "To", "Type", "Scope", "Direction", "Boundary", "Reviewed on"], failures); + const pairs = new Map(); + const used = new Set(); + const hierarchies = new Map(); + relationRows.forEach((row, index) => { + const location = `${relative} relation row ${index + 1}`; + if (row.length !== 7) { failures.push(`${location}: expected 7 columns`); return; } + const [fromCell, toCell, typeCell, scope, direction, boundary, reviewed] = row; + const from = identifier(fromCell); + const to = identifier(toCell); + const type = identifier(typeCell); + if (!RELATION_TYPES.has(type)) failures.push(`${location}: unknown relation type ${type ?? typeCell}`); + if (!terms.has(from)) failures.push(`${location}: from-term must be a recorded term`); + if (!terms.has(to)) failures.push(`${location}: to-term must be a recorded term`); + if (from && from === to) failures.push(`${location}: self relation is forbidden`); + if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(scope)) failures.push(`${location}: scope must be a non-empty kebab-case identifier`); + const allowedDirections = type === "near_equivalent" ? ["symmetric", "directional"] : [SYMMETRIC_TYPES.has(type) ? "symmetric" : "directional"]; + if (!allowedDirections.includes(direction)) failures.push(`${location}: invalid direction for ${type}`); + if (boundary.length < 20 || boundary.replaceAll("`", "") === type) failures.push(`${location}: boundary must be a non-trivial scope statement`); + if (!validDate(reviewed)) failures.push(`${location}: reviewed_on must be a real YYYY-MM-DD date`); + if (type === "same_label_different_meaning" && terms.has(from) && terms.has(to)) { + const a = terms.get(from); + const b = terms.get(to); + if (a.label !== b.label) failures.push(`${location}: same_label_different_meaning requires identical labels`); + if (a.concept === b.concept && a.scope === b.scope) failures.push(`${location}: same_label_different_meaning requires distinct meaning or scope`); + } + if (type === "renamed_to" || type === "deprecated_in_favor_of") { + if (!/\b(?:19|20)\d{2}\b|\bv\d+\.\d+|\bversion\s+\d/i.test(boundary)) failures.push(`${location}: ${type} requires a time or version basis in the boundary`); + const a = terms.get(from); + const b = terms.get(to); + if (a && b) { + if (!["historical", "deprecated"].includes(a.status) || b.status !== "current") failures.push(`${location}: temporal relation requires historical/deprecated source and current replacement`); + if (type === "deprecated_in_favor_of" && a.status !== "deprecated") failures.push(`${location}: deprecation requires deprecated from-term`); + if (type === "renamed_to" && (a.source !== b.source || a.label === b.label)) failures.push(`${location}: rename requires one named source and different labels`); + } + } + if (!terms.has(from) || !terms.has(to)) return; + used.add(from); + used.add(to); + const key = JSON.stringify([from, to, scope]); + const reverse = pairs.get(JSON.stringify([to, from, scope])); + if (pairs.has(key)) failures.push(`${location}: duplicate or contradictory relation for ${from}->${to} in ${scope}`); + if (reverse) { + const inverse = type === "broader_than" ? "narrower_than" : type === "narrower_than" ? "broader_than" : direction === "symmetric" ? type : null; + if (reverse.type !== inverse || reverse.direction !== direction) failures.push(`${location}: conflicting reverse relation in ${scope}`); + } + pairs.set(key, { type, direction }); + if (type === "broader_than" || type === "narrower_than") { + const graph = hierarchies.get(scope) ?? new Map(); + const [parent, child] = type === "broader_than" ? [from, to] : [to, from]; + graph.set(parent, new Set([...(graph.get(parent) ?? []), child])); + hierarchies.set(scope, graph); + } + }); + for (const [scope, graph] of hierarchies) if (hasCycle(graph)) failures.push(`${relative}: containment cycle in ${scope}`); + for (const id of terms.keys()) if (!used.has(id)) failures.push(`${relative}: orphan term ${id} has no recorded relation`); + return { ok: failures.length === 0, terms: termRows.length, relations: relationRows.length, failures: [...new Set(failures)] }; +} + +const isMain = process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url); +if (isMain) { + const result = validateDesignTerminology(); + if (process.argv.includes("--json")) console.log(JSON.stringify(result, null, 2)); + else if (result.ok) console.log(`ok: ${result.terms} terms, ${result.relations} relations`); + else console.error(result.failures.join("\n")); + process.exitCode = result.ok ? 0 : 1; +} diff --git a/scripts/validate-domains.mjs b/scripts/validate-domains.mjs index e5777dc..5cc1d95 100644 --- a/scripts/validate-domains.mjs +++ b/scripts/validate-domains.mjs @@ -18,28 +18,28 @@ const referenceDocuments = [ const requiredCrossDomainStrings = [ { relative: "guides/vocabulary.md", - required: "Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, root routing, and `domain` frontmatter on governed leaves.", - failure: "guides/vocabulary.md: missing canonical five-domain vocabulary list", + required: "Use for: Layout, Motion, Design Engineering, Game UI, Platform Guides, Design Terminology, root routing, and `domain` frontmatter on governed leaves.", + failure: "guides/vocabulary.md: missing canonical domain vocabulary list", }, { relative: "quality/index.md", - required: "`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, and Platform Guides claims are admissible.", - failure: "quality/index.md: missing canonical five-domain quality scope", + required: "`quality/` is shared StyleGallery infrastructure for deciding whether Layout, Motion, Design Engineering, Game UI, Platform Guides, and Design Terminology claims are admissible.", + failure: "quality/index.md: missing canonical domain quality scope", }, { relative: "README.md", - required: "without owning profiles, visual values, components, or a sixth domain", + required: "without owning profiles, visual values, components, or a seventh domain", failure: "README.md: missing canonical Consumer Reference boundary", }, { relative: "quality/index.md", - required: "without classifying it as a sixth domain", + required: "without classifying it as a seventh domain", failure: "quality/index.md: missing canonical Consumer Reference boundary", }, { relative: "quality/evidence/executable-evidence.md", - required: "Five governed domains and their declared leaves are reachable and attributed.", - failure: "quality/evidence/executable-evidence.md: missing canonical five-domain validator coverage", + required: "Six governed domains and their declared leaves are reachable and attributed.", + failure: "quality/evidence/executable-evidence.md: missing canonical domain validator coverage", }, { relative: "quality/index.md", @@ -57,6 +57,9 @@ export const canonicalDomains = [ { path: "motion/vocabulary.md", provenance: "external", sourcePath: "skills/animation-vocabulary/SKILL.md" }, { path: "motion/review-workflow.md", provenance: "external", sourcePath: "skills/review-animations/SKILL.md" }, { path: "motion/practice-reference.md", provenance: "external", sourcePath: "skills/review-animations/STANDARDS.md" }, + { path: "motion/decision-tree.md", provenance: "local" }, + { path: "motion/motion-brief.md", provenance: "local" }, + { path: "motion/interaction-recipes.md", provenance: "local" }, ], }, { @@ -65,6 +68,9 @@ export const canonicalDomains = [ leaves: [ { path: "design-engineering/interface-craft.md", provenance: "external", sourcePath: "skills/emil-design-eng/SKILL.md" }, { path: "design-engineering/consumer-migration-readiness.md", provenance: "local" }, + { path: "design-engineering/decision-tree.md", provenance: "local" }, + { path: "design-engineering/component-contract.md", provenance: "local" }, + { path: "design-engineering/worked-examples.md", provenance: "local" }, ], referenceDocuments, }, @@ -80,9 +86,34 @@ export const canonicalDomains = [ { path: "game-ui/unity/cli-loop.md", provenance: "external", sourcePath: "README.md" }, { path: "game-ui/unity/repository-map.md", provenance: "repository" }, { path: "game-ui/unity/org-wiki.md", provenance: "repository" }, + { path: "game-ui/decision-tree.md", provenance: "local" }, + { path: "game-ui/screen-recipes.md", provenance: "local" }, + { path: "game-ui/verification-workflow.md", provenance: "local" }, + ], + }, + { + slug: "platform-guides", + label: "Platform Guides", + leaves: [ + { path: "platform-guides/apple-interaction.md", provenance: "external", sourcePath: "skills/apple-design/SKILL.md" }, + { path: "platform-guides/adaptation-workflow.md", provenance: "local" }, + { path: "platform-guides/android-interaction.md", provenance: "local" }, + { path: "platform-guides/windows-interaction.md", provenance: "local" }, + { path: "platform-guides/compatibility-matrix.md", provenance: "local" }, + ], + }, + { + slug: "design-terminology", + label: "Design Terminology", + leaves: [ + { path: "design-terminology/source-kinds.md", provenance: "repository" }, + { path: "design-terminology/source-vocabularies.md", provenance: "repository" }, + { path: "design-terminology/concept-families.md", provenance: "repository" }, + { path: "design-terminology/relation-types.md", provenance: "repository" }, + { path: "design-terminology/conflict-cases.md", provenance: "repository" }, + { path: "design-terminology/comparison-workflow.md", provenance: "local" }, ], }, - { slug: "platform-guides", label: "Platform Guides", leaves: [{ path: "platform-guides/apple-interaction.md", provenance: "external", sourcePath: "skills/apple-design/SKILL.md" }] }, ]; export const domainRegistry = canonicalDomains; @@ -155,8 +186,8 @@ function checkManifest() { && content.includes(`snapshot \`${revision}\``) && content.includes("## Shared Non-Domain Infrastructure") && content.includes("[Consumer Reference](consumer-reference/index.md)") - && content.includes("infrastructure outside the five-domain contract") - && content.includes("cannot add a sixth domain row"); + && content.includes("infrastructure outside the six-domain contract") + && content.includes("cannot add a seventh domain row"); for (const domain of domains) { const domainRow = domainRows.find((row) => row[0] === domain.label); diff --git a/scripts/validate-governance.mjs b/scripts/validate-governance.mjs index a77a9c8..14c21b7 100644 --- a/scripts/validate-governance.mjs +++ b/scripts/validate-governance.mjs @@ -66,6 +66,7 @@ function requireGovernanceMatrix() { "Design Engineering domain guidance", "Game UI domain guidance", "Platform Guides domain guidance", + "Design Terminology domain guidance", "Pattern data and examples", "Pattern generator", "Validation scripts", diff --git a/scripts/validate-lifecycle-disposition.mjs b/scripts/validate-lifecycle-disposition.mjs index ef96d80..fcbc607 100644 --- a/scripts/validate-lifecycle-disposition.mjs +++ b/scripts/validate-lifecycle-disposition.mjs @@ -57,8 +57,8 @@ const OWNER_TRUST_ROOT = Object.freeze({ }); const AUTHORIZED_APPROVAL_COMMITS = Object.freeze([]); const SENTINEL_WORKFLOW_PATH = ".github/workflows/validate.yml"; -const SENTINEL_ACTIVE_WORKFLOW_SHA256 = "846417a45a462a51ba28028621ff9fe82cf018be15b8a433a661d7d0d7af3017"; -const SENTINEL_RETIRED_WORKFLOW_SHA256 = "421c63222db3dfb5af03630c437a4b8b0f755a6146abec4e5d213eb2b0369620"; +const SENTINEL_ACTIVE_WORKFLOW_SHA256 = "b7aac452ac49ec1bc287ef3d75efe3806895eb147172b106634394f413a520fc"; +const SENTINEL_RETIRED_WORKFLOW_SHA256 = "e1d2cc248efdad81267326fdf2706335a7d4e6f4e271f05a37904102313b347b"; const SENTINEL_JOB_SHA256 = "86228e7fb44c2ba5d0abe160d6bd3c4f5228e7c1ec40189b3b4f528acfd45e62"; const SENTINEL_PROTECTED = Object.freeze([ ["consumer-reference/baselines/calibration.json", "b537b0c3acb3ac55e4b926b1d12b41d2cb8050a85de2410ad4b42e1b7b53f88e", "raw_20_run_aggregate_and_provenance"], @@ -80,8 +80,8 @@ const SENTINEL_PROTECTED = Object.freeze([ ["tests/helpers/render-consumer-reference.mjs", "88802a948909d5e40470be6b5481766ce2de498e59c053ac68af370b46e72ca9", "sentinel_renderer_source"], ["tests/snapshots/consumer-reference-card-grid.png", "5528358e957a6115793155e501f62716f7db31dc1c86856d9e1234868d672837", "historical_baseline_bytes"], ]);const PAGE_WORKFLOW_PATH = ".github/workflows/validate.yml"; -const PAGE_ACTIVE_WORKFLOW_SHA256 = "846417a45a462a51ba28028621ff9fe82cf018be15b8a433a661d7d0d7af3017"; -const PAGE_RETIRED_WORKFLOW_SHA256 = "e68fe15654d5830d918e8adfda4b8dcedcb0340b286d6e42058831c1d1c44f58"; +const PAGE_ACTIVE_WORKFLOW_SHA256 = "b7aac452ac49ec1bc287ef3d75efe3806895eb147172b106634394f413a520fc"; +const PAGE_RETIRED_WORKFLOW_SHA256 = "5f709d829e5008b9a0b101ac519454a64cb938b40b0c03cf645ee1d779e8038b"; const PAGE_JOB_SHA256 = "11d0fe7ea2880c5d32d32bb419493600afdfd221aef728f3c0e36e22cf52b116"; const PAGE_SYNTHETIC_REPOSITORIES = Object.freeze(["ark-jo/stylegallery", "changeroa/stylegallery", "example/stylegallery-page-evidence-ci"]); const PAGE_PROTECTED = Object.freeze([ @@ -100,7 +100,7 @@ const PAGE_PROTECTED = Object.freeze([ ["tests/consumer-conformance.spec.mjs", "e19df0d1131b7a65fd6e5b7b79c993d05f4a4559b64a18da673e1beede5421a3", "browser_capture_surface"], ["tests/fixtures/consumer-conformance-scenarios.mjs", "927d185f523e70e7f2e1fccee0013360d126e02aa532c2367670e64cdef43f12", "state_w1024_focus_contract"], ["tests/helpers/render-consumer-conformance.mjs", "6d5db609aaadb2f68fec1a0f1f51af1c17157cf1364631a42b35da2d6c1a0865", "capture_renderer"], - ["quality/evidence/executable-evidence.md", "a0ae7f2c355ab26293cdb9e96b31d91d50a024ed404aa0c8297a65b91af73a33", "archive_and_retrieval_documentation"], + ["quality/evidence/executable-evidence.md", "fb441412dabc0b57aeac8355f92321a9873aa67612e489e3137953d7680312b1", "archive_and_retrieval_documentation"], ["playwright.config.mjs", "7dcc2ae21602ac89af47d2bbf122f5945098f0e8fda9d47db7d33980592e60ae", "pinned_browser_configuration"], ]); const PAGE_ADOPTER_TRUST_ROOTS = Object.freeze([]); @@ -594,6 +594,8 @@ const PAGE_ARCHIVE_PACKET = Object.freeze([ "records/consumer-conformance.json", "provenance/source-commit.txt", ]); const PAGE_ARCHIVE_PROTECTED = Object.freeze(PAGE_PROTECTED.map(([repositoryPath, expectedSha, role]) => { + // Historical archive bytes remain pinned when current authoring documentation changes. + if (repositoryPath === "quality/evidence/executable-evidence.md") return [repositoryPath, "a0ae7f2c355ab26293cdb9e96b31d91d50a024ed404aa0c8297a65b91af73a33", role]; if (repositoryPath === "tests/consumer-conformance.spec.mjs") return [repositoryPath, "a7b7e117fff636830029e9923fc828ed92d1d22ac91f3efde338eb154b0101e7", role]; if (repositoryPath === "tests/fixtures/consumer-conformance-scenarios.mjs") return [repositoryPath, "67aa1931764237ee9485d0e81606c2721297e2c3517a321be4c4e945149fbe58", role]; return [repositoryPath, expectedSha, role];