@reqvire-org/ads 0.3.18 → 0.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/behaviors.mjs +5 -5
- package/dist/bootstrap-ds/ADS.md +2 -2
- package/dist/bootstrap-ds/README.md +1 -1
- package/dist/bootstrap-ds/design-system/index.ts +0 -1
- package/dist/bootstrap-ds/design-system/review/index.ts +1 -0
- package/dist/bootstrap-ds/design-system/tokens/Foundation.scenario.tsx +1 -1
- package/dist/bootstrap-ds/ds.config.json +1 -1
- package/dist/bootstrap-ds/tsconfig.json +18 -3
- package/dist/bootstrap-ds/vite.config.ts +1 -1
- package/dist/boundaries.mjs +4 -2
- package/dist/check.mjs +20 -13
- package/dist/config.mjs +13 -2
- package/dist/init.mjs +17 -14
- package/dist/layers.mjs +288 -0
- package/dist/lint-config.mjs +1 -1
- package/dist/mcp/context.mjs +2 -1
- package/dist/mcp/edit-preparation.mjs +3 -3
- package/dist/mcp/mutations.mjs +1 -1
- package/dist/mcp/prompts.mjs +1 -1
- package/dist/mcp/server.mjs +6 -2
- package/dist/mcp/widget.bundle.js +1 -1
- package/dist/oxlint.mjs +3 -1
- package/dist/preview-resources.mjs +11 -1
- package/dist/public-api.mjs +13 -6
- package/dist/scenario-trace.mjs +6 -6
- package/dist/scenarios-vite.mjs +2 -1
- package/dist/scenarios.mjs +10 -7
- package/dist/showcase/client.bundle.js +1 -1
- package/dist/showcase/sandbox.bundle.js +1 -1
- package/dist/skills/ads-break-ui/SKILL.md +21 -6
- package/dist/skills/ads-break-ui/references/guarded-editing.md +1 -1
- package/dist/skills/ads-break-ui/references/layers.md +123 -0
- package/dist/skills/ads-break-ui/references/review.md +96 -0
- package/dist/skills/ads-break-ui/references/scenarios.md +24 -3
- package/dist/skills/ads-designer/SKILL.md +22 -7
- package/dist/skills/ads-designer/assets/bootstrap-ds/ADS.md +2 -2
- package/dist/skills/ads-designer/assets/bootstrap-ds/README.md +1 -1
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/index.ts +0 -1
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/review/index.ts +1 -0
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/tokens/Foundation.scenario.tsx +1 -1
- package/dist/skills/ads-designer/assets/bootstrap-ds/ds.config.json +1 -1
- package/dist/skills/ads-designer/assets/bootstrap-ds/tsconfig.json +18 -3
- package/dist/skills/ads-designer/assets/bootstrap-ds/vite.config.ts +1 -1
- package/dist/skills/ads-designer/references/guarded-editing.md +1 -1
- package/dist/skills/ads-designer/references/layers.md +123 -0
- package/dist/skills/ads-designer/references/review.md +96 -0
- package/dist/skills/ads-designer/references/scenarios.md +24 -3
- package/dist/skills/ads-import/SKILL.md +21 -6
- package/dist/skills/ads-import/references/guarded-editing.md +1 -1
- package/dist/skills/ads-import/references/layers.md +123 -0
- package/dist/skills/ads-import/references/review.md +96 -0
- package/dist/skills/ads-import/references/scenarios.md +24 -3
- package/dist/skills/ads-migrate/SKILL.md +21 -6
- package/dist/skills/ads-migrate/references/guarded-editing.md +1 -1
- package/dist/skills/ads-migrate/references/layers.md +123 -0
- package/dist/skills/ads-migrate/references/review.md +96 -0
- package/dist/skills/ads-migrate/references/scenarios.md +24 -3
- package/dist/skills/ads-motion/SKILL.md +22 -7
- package/dist/skills/ads-motion/references/audit.md +1 -1
- package/dist/skills/ads-motion/references/guarded-editing.md +1 -1
- package/dist/skills/ads-motion/references/layers.md +123 -0
- package/dist/skills/ads-motion/references/motion-review.md +35 -0
- package/dist/skills/ads-motion/references/review.md +96 -35
- package/dist/skills/ads-motion/references/scenarios.md +24 -3
- package/dist/units.mjs +17 -14
- package/docs/ADS.md +32 -5
- package/docs/ARCHITECTURE.md +37 -4
- package/docs/BEHAVIORS.md +7 -0
- package/docs/CHANGELOG.md +23 -0
- package/docs/GUIDE.md +3 -2
- package/docs/MCP.md +27 -6
- package/package.json +1 -1
- package/dist/bootstrap-ds/design-system/patterns/token-preview/Scenario.tsx +0 -4
- package/dist/bootstrap-ds/design-system/patterns/token-preview/fixture.ts +0 -8
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/patterns/token-preview/Scenario.tsx +0 -4
- package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/patterns/token-preview/fixture.ts +0 -8
- /package/dist/bootstrap-ds/design-system/{patterns → review}/token-preview/TokenPreview.tsx +0 -0
- /package/dist/skills/ads-designer/assets/bootstrap-ds/design-system/{patterns → review}/token-preview/TokenPreview.tsx +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Components, patterns and application adapters
|
|
2
|
+
|
|
3
|
+
Read this when choosing an owner, moving UI between layers, or resolving
|
|
4
|
+
`component-dependency`, `component-contract`, `component-style`, `no-app-import`
|
|
5
|
+
or `showcase-import`. MCP also serves this guide as `ads://guides/layers`.
|
|
6
|
+
|
|
7
|
+
## Choose by responsibility
|
|
8
|
+
|
|
9
|
+
A **component** provides one cohesive UI capability: semantics, input handling,
|
|
10
|
+
focus, accessibility, states and appearance. It may compose other components and
|
|
11
|
+
controllers. A notification using an icon, action button and spinner can still
|
|
12
|
+
be one component.
|
|
13
|
+
|
|
14
|
+
A **pattern** arranges capabilities and content slots into a reusable structure
|
|
15
|
+
or workflow, such as navigation with search/account controls or a report screen.
|
|
16
|
+
Layout parts may arrange `children` without importing several components.
|
|
17
|
+
Patterns may compose other patterns. A native wrapper or a large implementation
|
|
18
|
+
does not decide the layer.
|
|
19
|
+
|
|
20
|
+
An **application adapter** supplies domain data, store access, route state and
|
|
21
|
+
navigation/service callbacks. Domain-shaped inputs are valid in project-owned
|
|
22
|
+
patterns; importing a particular application store/router is not.
|
|
23
|
+
|
|
24
|
+
A **scenario** supplies demonstration inputs, local state and simulated services.
|
|
25
|
+
A component scenario may compose several public components and development review helpers
|
|
26
|
+
to demonstrate its subject. That does not turn its fixture or variant selectors
|
|
27
|
+
into production API. Keep `covers` aligned with the scenario's subject layer.
|
|
28
|
+
|
|
29
|
+
Do not classify by import count, JSX element count, names or file length. Review
|
|
30
|
+
the capability and its consumer contract. Preserve valid APIs when tracing is
|
|
31
|
+
inconclusive; do not make an export private or add a product prop just to pass.
|
|
32
|
+
|
|
33
|
+
## Demonstrate the production implementation
|
|
34
|
+
|
|
35
|
+
Product patterns are reusable application UI, not showcase replicas. A scenario
|
|
36
|
+
imports the same production owner and supplies fixtures through its public API;
|
|
37
|
+
the application supplies live data and callbacks to that API. Keep mock records,
|
|
38
|
+
demo selections and simulated services in development files. Legitimate defaults,
|
|
39
|
+
control labels and the pattern's own interaction logic remain with their owner.
|
|
40
|
+
|
|
41
|
+
Demo framing must not replace a product pattern's styling or behavior. Browser
|
|
42
|
+
checks should exercise both the demonstrated contract and relevant application
|
|
43
|
+
integration; a successful showcase does not establish production parity. A new
|
|
44
|
+
pattern need not already have an application consumer, and import counts cannot
|
|
45
|
+
detect a duplicated implementation. Existing import guards prevent fixture/test
|
|
46
|
+
dependencies; review and browser checks must assess hardcoded mock data and
|
|
47
|
+
unrepresentative rendering that source ownership alone cannot prove.
|
|
48
|
+
|
|
49
|
+
Review framing belongs in development-only `review/`, not production patterns.
|
|
50
|
+
Use the separate review entry and [review.md](review.md) for the migration and
|
|
51
|
+
build contract.
|
|
52
|
+
|
|
53
|
+
## Dependency contracts (blocking)
|
|
54
|
+
|
|
55
|
+
- Component runtime may depend on components, shared controllers and lower-level
|
|
56
|
+
helpers. It cannot depend on patterns or composition, including indirectly
|
|
57
|
+
through aliases, forwarding exports, helpers or literal dynamic imports.
|
|
58
|
+
Type-only pattern references do not introduce runtime dependencies.
|
|
59
|
+
- Patterns consume component symbols published by the configured public entry,
|
|
60
|
+
including intentional public types. A relative import of a public symbol is
|
|
61
|
+
allowed inside the ADS; requiring a self-import through the barrel can create
|
|
62
|
+
cycles. Private state, class blocks and implementation helpers stay internal.
|
|
63
|
+
A public component may use its own private implementation dependencies.
|
|
64
|
+
- Runtime code cannot import review implementations/types/styles, scenarios, fixtures or checks, including through
|
|
65
|
+
forwarding exports. Scenarios also cannot import application source.
|
|
66
|
+
- ADS implementations receive application data/effects through inputs and
|
|
67
|
+
callbacks. Re-exporting application stores, routers or services from a helper
|
|
68
|
+
does not make them part of the ADS.
|
|
69
|
+
|
|
70
|
+
For example, `components/Control → shared/helper → patterns/Navigation` fails
|
|
71
|
+
`component-dependency`. Extract a lower-level capability/controller, or move the
|
|
72
|
+
arrangement to a pattern. `patterns/Navigation → components/Control` is valid
|
|
73
|
+
when `Control` is public. Replacing that import with its private state helper
|
|
74
|
+
fails `component-contract` even through a forwarding module.
|
|
75
|
+
|
|
76
|
+
## Styling contracts (blocking when ownership is established)
|
|
77
|
+
|
|
78
|
+
Components own their control states and appearance. Patterns own arrangement,
|
|
79
|
+
spacing and their own presentation. Use typed component props/variants, an
|
|
80
|
+
intentional public class helper/hook, or registered non-state customization
|
|
81
|
+
variables. Registration does not authorize overriding interaction policy.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
// Component-owned implementation; the marker is not a consumer styling API.
|
|
85
|
+
function Control() {
|
|
86
|
+
return <button><span className="control-private-label">Label</span></button>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Pattern: rejected because it styles the component's private rendered part.
|
|
90
|
+
const wrong = css`
|
|
91
|
+
& .control-private-label { color: var(--text-muted); }
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
// Pattern: its own arrangement remains valid.
|
|
95
|
+
const layout = css`
|
|
96
|
+
display: flex;
|
|
97
|
+
gap: var(--space-4);
|
|
98
|
+
`;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The source guard matches component-emitted class names and unambiguous literal
|
|
102
|
+
data markers to the selector's styled subject, including `:is()`/`:where()`.
|
|
103
|
+
It also rejects reads of known private component variables. It does not treat
|
|
104
|
+
an ancestor predicate or `:has()` query as styling that ancestor/descendant:
|
|
105
|
+
`[data-layout="expanded"] > & { gap: var(--space-4); }` changes the pattern's
|
|
106
|
+
own arrangement. Public hooks and registered non-state variables remain valid.
|
|
107
|
+
Token definitions, namespaces and writes retain their existing guards.
|
|
108
|
+
|
|
109
|
+
Opaque/computed imports, generated selectors, ambiguous shared markers, forwarded
|
|
110
|
+
consumer classes and arbitrary service abstractions are not a complete static
|
|
111
|
+
proof. Passing source checks does not prove that every visual override is safe.
|
|
112
|
+
Review the real rendered states, computed styles, keyboard interactions and
|
|
113
|
+
responsive layouts; use registered browser checks for promised behavior.
|
|
114
|
+
|
|
115
|
+
## Refactoring an owner
|
|
116
|
+
|
|
117
|
+
Move runtime source, its scenarios/fixtures and guides together; update public
|
|
118
|
+
exports, dependent imports and documented scenario IDs. Keep callers on the
|
|
119
|
+
same intentional public API. Navigation stays in an application callback or a
|
|
120
|
+
normal link supplied by the consumer, rather than a hidden router mutation in
|
|
121
|
+
the pattern. Validate the complete migration with project checks, product and
|
|
122
|
+
preview builds, and behavior tests. An existing guard rejection is not permission
|
|
123
|
+
to write around the guarded editing workflow.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Review motion
|
|
2
|
+
|
|
3
|
+
Read the item's local README before treating a choice as accidental. Compare
|
|
4
|
+
the source state machine with actual rendered behavior when a browser is
|
|
5
|
+
available. Mark source-only conclusions and untested performance hypotheses.
|
|
6
|
+
|
|
7
|
+
Assess the following where applicable:
|
|
8
|
+
|
|
9
|
+
| Area | Look for |
|
|
10
|
+
|------|----------|
|
|
11
|
+
| Purpose/frequency | A clear relationship to the action; repeated work is not slowed |
|
|
12
|
+
| Easing | Entry decelerates naturally; continuous movement and elapsed-time motion use suitable curves |
|
|
13
|
+
| Timing | Feedback starts promptly; total choreography fits its distance and task |
|
|
14
|
+
| Origin/distance | Placement and scale point to the real trigger without excessive travel |
|
|
15
|
+
| Continuity | Reversal and repeated updates retarget without snapping or restarting |
|
|
16
|
+
| Lifecycle | Exit, cancellation, unmount, and zero-duration states clean up correctly |
|
|
17
|
+
| Accessibility | Motion preference, focus, hidden content, and keyboard behavior remain correct |
|
|
18
|
+
| Ownership | Motion uses tokens and owner styles; consumers do not override internals |
|
|
19
|
+
| Cost | Measured rendering work matches the problem; no per-frame work is assumed harmless |
|
|
20
|
+
|
|
21
|
+
The upstream guidance favors short transitions, restrained scale, and transform/
|
|
22
|
+
opacity. Apply those as defaults with context. A documented 400 ms stack,
|
|
23
|
+
measured height transition, or necessary loading loop is not inherently broken.
|
|
24
|
+
Likewise, a transition below 300 ms is not automatically good. Verify whether an
|
|
25
|
+
exception preserves the intended experience and has acceptable observed cost.
|
|
26
|
+
|
|
27
|
+
Present only actionable findings. Include file/line, trigger, observed behavior,
|
|
28
|
+
expected behavior, why the difference matters, and a concrete owner-level fix.
|
|
29
|
+
For timing/easing proposals, name the current and proposed token policy and its
|
|
30
|
+
scope. If a token is shared, identify affected neighbors before changing values.
|
|
31
|
+
|
|
32
|
+
Use a before/after/why comparison for implemented fixes. Separate behavior
|
|
33
|
+
defects, visual refinements, and profiling questions so a suspicion is not
|
|
34
|
+
reported as a proved performance failure. If no defect is found, say what was
|
|
35
|
+
checked and what remains unverified. Do not invent findings to fill a checklist.
|
|
@@ -1,35 +1,96 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
Read
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
# Development-only review UI
|
|
2
|
+
|
|
3
|
+
Read this when creating or migrating demo frames, preview sizing helpers, token
|
|
4
|
+
renderers or demonstration controls. MCP serves it as `ads://guides/review`.
|
|
5
|
+
|
|
6
|
+
## Responsibilities and boundaries
|
|
7
|
+
|
|
8
|
+
Components provide cohesive production capabilities. Patterns provide reusable
|
|
9
|
+
application structures/workflows. Both receive variable application data and
|
|
10
|
+
callbacks through their APIs. Their scenarios import the same implementation
|
|
11
|
+
used by the application and supply fixtures; do not create a second implementation
|
|
12
|
+
that only looks correct in the showcase.
|
|
13
|
+
|
|
14
|
+
`design-system/review/` owns development-only presentation: example frames,
|
|
15
|
+
arrangement, demonstration controls, token sample renderers and their styles.
|
|
16
|
+
It remains project-owned. The MCP host shell stays generic; review code executes
|
|
17
|
+
inside the preview App with the project's framework, foundation, fonts and styles.
|
|
18
|
+
Nothing depends on particular helper names or an imported component library.
|
|
19
|
+
|
|
20
|
+
The development entry defaults to `review/index.ts` relative to `dsDir`; configure
|
|
21
|
+
`reviewEntry` for another script inside `review/`. Its import alias is the
|
|
22
|
+
configured `publicAlias` plus `/review`, normally `@ds/review`. Discover the actual
|
|
23
|
+
entry/alias through `ads_status.project.review`. Export helpers there, never from
|
|
24
|
+
the production public barrel. Review implementations, types and styles must not
|
|
25
|
+
enter application, component, pattern or controller dependencies. Tests, fixtures,
|
|
26
|
+
scenarios and preview mounts can consume review code.
|
|
27
|
+
|
|
28
|
+
Review helpers can own Linaria presentation, local state and demo controls. Normal
|
|
29
|
+
style-token, variable ownership, measured-style-write and application separation
|
|
30
|
+
gates still apply. They consume deliberate public component/pattern/controller
|
|
31
|
+
contracts and may reuse local foundation helpers. They cannot target private
|
|
32
|
+
component styles or replace real product behavior. Keep one-off fixture data in
|
|
33
|
+
the scenario; a helper need not become a product API to frame an example.
|
|
34
|
+
|
|
35
|
+
## Scenario and token contracts
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
import { Panel } from "@ds";
|
|
39
|
+
import { ReviewFrame } from "@ds/review";
|
|
40
|
+
import { fixture } from "./Panel.fixture";
|
|
41
|
+
|
|
42
|
+
export const scenario = { title: "Panel", covers: ["Panel"] };
|
|
43
|
+
export default function Scenario() {
|
|
44
|
+
return <ReviewFrame><Panel {...fixture} /></ReviewFrame>;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The names above are illustrative. `covers` names the production subjects actually
|
|
49
|
+
demonstrated, not every review wrapper. A review export has no product catalogue
|
|
50
|
+
entry and needs no standalone catalogue scenario. Keep review unit tests/specs
|
|
51
|
+
beside their owner; optional behavior contracts can verify review guarantees
|
|
52
|
+
through an existing real scenario. They establish no production coverage.
|
|
53
|
+
|
|
54
|
+
A token scenario may name its real review renderer in `covers`, import it from
|
|
55
|
+
the development entry, declare `samples: fixture.samples`, and pass those samples
|
|
56
|
+
into the renderer. Existing real product patterns may also serve as token UI.
|
|
57
|
+
Empty covers, unused samples, fabricated tokens and plain value lists remain
|
|
58
|
+
invalid. The rendered App must still pass token-binding checks. See
|
|
59
|
+
[scenarios.md](scenarios.md) for the full token/render contract.
|
|
60
|
+
|
|
61
|
+
Review class helpers can supply source-proven Linaria classes to a scenario.
|
|
62
|
+
Arbitrary scenario classes/styles remain forbidden. A review wrapper's own native
|
|
63
|
+
controls do not authorize arbitrary native controls in its consuming scenario;
|
|
64
|
+
slot/selector exceptions still need actual production-owner evidence. Keep
|
|
65
|
+
production and review export names distinct where `covers` would be ambiguous.
|
|
66
|
+
|
|
67
|
+
## Build and guarded edits
|
|
68
|
+
|
|
69
|
+
The normal preview plugin registers the exact review alias before broader product
|
|
70
|
+
aliases. Configure the same alias in project TypeScript and any independent
|
|
71
|
+
preview/dev harness. In an ordered bundler alias map, put `@ds/review` before
|
|
72
|
+
`@ds`; the broad `@ds` mapping must not resolve it as `index.ts/review`.
|
|
73
|
+
Production entrypoints never import the development entry. Inspect the product
|
|
74
|
+
bundle for review modules/CSS; passing static checks does not prove bundle parity.
|
|
75
|
+
|
|
76
|
+
Use `ads_units` for `review/<Owner>` units. Scenarios, local specs and helper files
|
|
77
|
+
follow ordinary flat/directory ownership. A review patch may update only its own
|
|
78
|
+
re-exports in the development entry and its own documented style boundaries.
|
|
79
|
+
Product owners retain the separate production entry companion. Use prepared
|
|
80
|
+
patches/dry runs and coupled transactions as described in
|
|
81
|
+
[guarded-editing.md](guarded-editing.md); do not bypass a rejected mutation.
|
|
82
|
+
|
|
83
|
+
For an existing project, identify helpers by responsibility and actual consumers,
|
|
84
|
+
not names or the number of imported components. Preserve real application patterns.
|
|
85
|
+
Move only demo helpers, their styles and relevant guides to `review/`; update
|
|
86
|
+
scenario/preview imports, style-boundary paths, TypeScript/bundler aliases and
|
|
87
|
+
links. Remove their production exports and obsolete standalone product scenarios.
|
|
88
|
+
Do not copy old example fixtures or export demonstration controls as product UI.
|
|
89
|
+
|
|
90
|
+
Upgrade ADS before migrating a consuming project: older versions do not know the
|
|
91
|
+
separate review entry. For staged guarded edits, first add distinctly named review
|
|
92
|
+
exports, migrate consumers in passing owner patches, then remove the old pattern
|
|
93
|
+
exports/owners once unused. Required coupled changes use a transaction. Check
|
|
94
|
+
source gates, typecheck, preview and production builds, real browser rendering,
|
|
95
|
+
registered behaviors and token bindings. A source move alone establishes none
|
|
96
|
+
of those rendered guarantees.
|
|
@@ -34,10 +34,31 @@ do not add scenario `preventDefault` handlers merely to hide it. Explicit App
|
|
|
34
34
|
bases retain their declared behavior and CSP requirements; external hosts own
|
|
35
35
|
their document-loading policy. Verify link activation as well as rendering.
|
|
36
36
|
|
|
37
|
+
## Forms inside Apps
|
|
38
|
+
|
|
39
|
+
Use real form semantics and the runtime owner's intended submit handler. ADS's
|
|
40
|
+
showcase and diagnostic explorer permit `allow-forms` at every iframe layer,
|
|
41
|
+
including legacy widgets. Browser constraint validation, Submit clicks, Enter and
|
|
42
|
+
`requestSubmit()` can reach the normal submit path. Client-side forms call
|
|
43
|
+
`preventDefault()` in their submit handlers; the host does not synthesize clicks
|
|
44
|
+
or submit events. Native action requests are blocked by CSP `form-action 'none'`.
|
|
45
|
+
Submit effects that use tools or resources still follow the MCP bridge.
|
|
46
|
+
|
|
47
|
+
If a click fires but the `submit` handler never runs, inspect the browser's sandbox
|
|
48
|
+
diagnostic and every ancestor iframe's permissions. Distinguish that host problem
|
|
49
|
+
from native constraint validation legitimately preventing submission. Do not add
|
|
50
|
+
scenario click interception to disguise a missing sandbox permission. External
|
|
51
|
+
MCP hosts control their own sandbox/CSP policy.
|
|
52
|
+
|
|
53
|
+
Verify an invalid submit, a valid submit, implicit Enter submission and the promised
|
|
54
|
+
state effects. A working Next button is not evidence that form submission works.
|
|
55
|
+
Keep native action navigation separate from client-side submission behavior;
|
|
56
|
+
`allow-forms` does not grant host DOM access or top-level navigation.
|
|
57
|
+
|
|
37
58
|
## Owner-local token previews load their own definitions
|
|
38
59
|
|
|
39
60
|
Keep the registered token sheet imported by its runtime owner for product use.
|
|
40
|
-
A colocated `kind: "tokens"` scenario may render only the
|
|
61
|
+
A colocated `kind: "tokens"` scenario may render only the development-only review renderer
|
|
41
62
|
with its fixture samples. Discovery adds the registered owner sheet to the
|
|
42
63
|
generated record's `stylesheets`; `previewEntriesPlugin` imports those paths
|
|
43
64
|
into the token preview independently of the runtime component. Custom builders
|
|
@@ -91,7 +112,7 @@ These examples describe verification mistakes, not component-specific rules:
|
|
|
91
112
|
|
|
92
113
|
| Situation | Do not | Do instead |
|
|
93
114
|
|-----------|--------|------------|
|
|
94
|
-
| A reference example sets `width: 15rem`, while the native popup uses its default width. | Remove the reference width and claim the original example now matches. | Keep the baseline intact. Reproduce demo sizing through the project's
|
|
115
|
+
| A reference example sets `width: 15rem`, while the native popup uses its default width. | Remove the reference width and claim the original example now matches. | Keep the baseline intact. Reproduce demo sizing through the project's development-only review helper or supported style helper. If a different native size is intentional, document it. Label any additional normalized comparison separately. |
|
|
95
116
|
| Static tracing cannot prove that a public clear control renders when a value is selected. | Remove its export, drop its required coverage, or change runtime behavior merely to pass the gate. | Preserve the intended public API. Try a meaningful selected-state fixture or another real scenario. If valid rendering remains untraceable, report the tooling limitation with a small reproduction. |
|
|
96
117
|
| A screenshot shows the clear control in a selected state. | Treat its presence as evidence that clearing works. | Add a browser check: start selected, activate Clear, assert the value and selection are empty, verify the control's resulting visibility and documented focus behavior, then select again. |
|
|
97
118
|
|
|
@@ -207,6 +228,6 @@ An `exercises` entry records behavioral use; it never grants styling permission.
|
|
|
207
228
|
Keep helper signatures compatible with the product API. Fix ownership/provenance
|
|
208
229
|
in the runtime owner when genuinely wrong; retain intentional public APIs when
|
|
209
230
|
reporting an unsupported trace. Demo-only sizing, framing and arrangement still
|
|
210
|
-
belong in
|
|
231
|
+
belong in development-only review helpers. A style helper is not permission to
|
|
211
232
|
author a second design in the scenario. For cascade risks and extraction issues,
|
|
212
233
|
read [atomic-styles.md](atomic-styles.md).
|
package/dist/units.mjs
CHANGED
|
@@ -25,7 +25,7 @@ export function configurationFiles(options) {
|
|
|
25
25
|
// fixtures to configuration. Those remain in the behavior owner's patch.
|
|
26
26
|
if (isInside(dsRoot, file) && isDevelopmentFile(file, options)) return;
|
|
27
27
|
if (!entrypoint && isInside(sourceRoot, file) && !isInside(dsRoot, file)) return;
|
|
28
|
-
if (!entrypoint && isInside(dsRoot, file) && /^(?:components|patterns|controllers|composition|tokens)[\\/]/.test(path.relative(dsRoot, file))) {
|
|
28
|
+
if (!entrypoint && isInside(dsRoot, file) && /^(?:components|patterns|controllers|composition|review|tokens)[\\/]/.test(path.relative(dsRoot, file))) {
|
|
29
29
|
if (isInside(path.join(dsRoot, "controllers"), file) || isDevelopmentFile(file, options)) return;
|
|
30
30
|
const folder = path.dirname(file), stem = path.basename(file).split(".")[0];
|
|
31
31
|
const anchored = ["index", path.basename(folder)].some(name => [".ts", ".tsx", ".js", ".jsx", ".mjs", ".mts"].some(extension => existsSync(path.join(folder, name + extension))));
|
|
@@ -102,30 +102,31 @@ export function inspectUnits(options) {
|
|
|
102
102
|
const directories = new Set(files.filter(file => /(?:^|\/)Scenario\.[cm]?[jt]sx?$/.test(file)).map(file => slash(path.dirname(file))));
|
|
103
103
|
for (const file of files.filter(file => /^(?:components|patterns)\/.+\/tokens\.json$/.test(file))) directories.add(path.posix.dirname(file));
|
|
104
104
|
for (const file of files) {
|
|
105
|
-
if (!/^(?:components|patterns|controllers|composition)\//.test(file) || !source.test(file)) continue;
|
|
105
|
+
if (!/^(?:components|patterns|controllers|composition|review)\//.test(file) || !source.test(file)) continue;
|
|
106
106
|
const directory = slash(path.dirname(file)), name = path.basename(file).replace(source, "");
|
|
107
107
|
if (!directory.includes("/") || /\.(?:scenario|fixture|scenario-adapter)$/.test(name)) continue;
|
|
108
108
|
if (flatFamilies.has(directory)) continue;
|
|
109
109
|
if (name === "index" || sameName(name) === sameName(path.posix.basename(directory)) || name === "fixture") directories.add(directory);
|
|
110
110
|
}
|
|
111
111
|
const directoryUnits = [...directories].sort((a, b) => b.length - a.length);
|
|
112
|
-
const flatUnits = [...new Set(files.filter(file => /^(?:components|patterns|controllers|composition)\//.test(file) && source.test(file) && !directoryUnits.some(directory => file.startsWith(directory + "/"))).map(file => {
|
|
112
|
+
const flatUnits = [...new Set(files.filter(file => /^(?:components|patterns|controllers|composition|review)\//.test(file) && source.test(file) && !directoryUnits.some(directory => file.startsWith(directory + "/"))).map(file => {
|
|
113
113
|
const base = path.basename(file).split(".")[0];
|
|
114
114
|
return slash(path.join(path.dirname(file), base));
|
|
115
115
|
}))].sort((a, b) => b.length - a.length);
|
|
116
116
|
const publicEntry = slash(path.relative(dsRoot, path.join(dsRoot, config.publicEntry)));
|
|
117
|
+
const reviewEntry = slash(path.relative(dsRoot, path.join(dsRoot, config.reviewEntry)));
|
|
117
118
|
const tokenDir = slash(path.relative(dsRoot, path.join(dsRoot, config.tokenDir)));
|
|
118
119
|
const stylesEntry = slash(path.relative(dsRoot, path.join(dsRoot, config.stylesEntry)));
|
|
119
120
|
function owner(relative) {
|
|
120
121
|
const projectFile = slash(path.relative(root, path.resolve(dsRoot, relative)));
|
|
121
122
|
if (setup.has(projectFile)) return "configuration";
|
|
122
123
|
if (!isInside(dsRoot, path.resolve(dsRoot, relative))) return isProjectDocument(projectFile) ? "documentation" : null;
|
|
123
|
-
if (relative === publicEntry) return null; // Controlled re-export bookkeeping.
|
|
124
|
+
if (relative === publicEntry || relative === reviewEntry) return null; // Controlled re-export bookkeeping.
|
|
124
125
|
if (relative.startsWith(tokenDir + "/")) return "tokens";
|
|
125
126
|
if (relative.startsWith("assets/")) return relative.split("/").length > 2 ? relative.split("/").slice(0, 2).join("/") : "assets";
|
|
126
127
|
if (isProjectDocument(relative)) return "documentation";
|
|
127
128
|
if (!relative.includes("/")) return /(?:\.(?:md|txt)$|^LICENSE$)/i.test(relative) ? "documentation" : "foundation";
|
|
128
|
-
if (!/^(?:components|patterns|controllers|composition)\//.test(relative)) return relative.split("/")[0] === "documentation" ? null : relative.split("/")[0];
|
|
129
|
+
if (!/^(?:components|patterns|controllers|composition|review)\//.test(relative)) return relative.split("/")[0] === "documentation" ? null : relative.split("/")[0];
|
|
129
130
|
for (const directory of directoryUnits) if (relative.startsWith(directory + "/")) return directory;
|
|
130
131
|
for (const unit of flatUnits) if (relative.startsWith(unit + "/") || relative.startsWith(unit + ".")) return unit;
|
|
131
132
|
const base = path.basename(relative).split(".")[0];
|
|
@@ -146,22 +147,23 @@ export function inspectUnits(options) {
|
|
|
146
147
|
if (!units.get(id).files.includes(file)) units.get(id).files.push(file);
|
|
147
148
|
}
|
|
148
149
|
for (const unit of units.values()) if (boundaryCompanion(unit.id)) {
|
|
150
|
+
if (unit.id.startsWith("review/")) (unit.companionFiles ??= []).push({ path: slash(path.relative(root, path.join(dsRoot, reviewEntry))), allowedChanges: "Only this review owner's re-exports in the separate development entry; never the production public entry." });
|
|
149
151
|
(unit.companionFiles ??= []).push({ path: "ds.config.json", allowedChanges: "Only this owner's inlineStyleFiles and boundaries.styleWrites entries, together with its source change; preserve all other configuration and peer permissions." });
|
|
150
|
-
if (/^(?:components|patterns|controllers|composition)\//.test(unit.id)) {
|
|
152
|
+
if (/^(?:components|patterns|controllers|composition|review)\//.test(unit.id)) {
|
|
151
153
|
for (let directory = unit.id; directory !== "."; directory = path.posix.dirname(directory)) {
|
|
152
154
|
const marker = path.join(dsRoot, directory, ".gitkeep");
|
|
153
155
|
if (existsSync(marker) && readFileSync(marker).length === 0) (unit.companionFiles ??= []).push({ path: slash(path.relative(root, marker)), allowedChanges: "Delete this empty placeholder only while adding real source in the selected owner below it." });
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
|
-
return { units: [...units.values()].sort((a, b) => a.id.localeCompare(b.id)), owner, publicEntry, stylesEntry, tokenDir,
|
|
159
|
+
return { units: [...units.values()].sort((a, b) => a.id.localeCompare(b.id)), owner, publicEntry, reviewEntry, stylesEntry, tokenDir,
|
|
158
160
|
relative: file => slash(path.relative(dsRoot, path.resolve(root, file))) };
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
function boundaryCompanion(unit) { return !["configuration", "documentation", "assets"].includes(unit.split("/")[0]); }
|
|
162
164
|
|
|
163
165
|
export function validateUnitId(unit) {
|
|
164
|
-
if (typeof unit !== "string" || unit.length > 256 || !/^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*$/.test(unit) || ["components", "patterns", "controllers", "composition"].includes(unit)) throw fail("Select one ADS unit ID from ads_units or an unoccupied owner path following its colocation convention.");
|
|
166
|
+
if (typeof unit !== "string" || unit.length > 256 || !/^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_-]+)*$/.test(unit) || ["components", "patterns", "controllers", "composition", "review"].includes(unit)) throw fail("Select one ADS unit ID from ads_units or an unoccupied owner path following its colocation convention.");
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
/** Reject arbitrary file batches, even when every path is inside the ADS. */
|
|
@@ -171,7 +173,7 @@ export function checkUnitFiles(options, unit, changes, inventory = inspectUnits(
|
|
|
171
173
|
const relative = inventory.relative(change.path);
|
|
172
174
|
if (path.posix.basename(relative) === ".gitkeep") {
|
|
173
175
|
const directory = path.posix.dirname(relative);
|
|
174
|
-
if (change.originalContent !== "" || change.content !== null || !/^(?:components|patterns|controllers|composition)\//.test(relative)
|
|
176
|
+
if (change.originalContent !== "" || change.content !== null || !/^(?:components|patterns|controllers|composition|review)\//.test(relative)
|
|
175
177
|
|| !(unit === directory || unit.startsWith(directory + "/"))
|
|
176
178
|
|| !changes.some(item => item.originalContent === null && item.content !== null && source.test(item.path)
|
|
177
179
|
&& (inventory.relative(item.path).startsWith(unit + "/") || inventory.relative(item.path).startsWith(unit + ".")))) throw fail("Only delete an existing empty .gitkeep while adding source in the selected owner beneath it. Other hidden-file changes are not allowed.", change.path);
|
|
@@ -179,7 +181,7 @@ export function checkUnitFiles(options, unit, changes, inventory = inspectUnits(
|
|
|
179
181
|
}
|
|
180
182
|
if (allowNew && unit === "configuration") continue; // The candidate must register every setup/extension file.
|
|
181
183
|
if (change.path === "ds.config.json" && boundaryCompanion(unit)) continue; // Validated against only this owner below.
|
|
182
|
-
if (relative === inventory.publicEntry) continue;
|
|
184
|
+
if (relative === inventory.publicEntry || relative === inventory.reviewEntry) continue;
|
|
183
185
|
if (unit === "tokens" && relative === inventory.stylesEntry) continue; // Controlled foundation import bookkeeping.
|
|
184
186
|
if (allowNew && change.originalContent === null && (relative.startsWith(unit + "/") || relative.startsWith(unit + "."))) continue;
|
|
185
187
|
const owner = inventory.owner(relative);
|
|
@@ -232,13 +234,14 @@ export function checkUnitCandidate(afterOptions, unit, changes, before) {
|
|
|
232
234
|
}
|
|
233
235
|
if (JSON.stringify(unrelated(current)) !== JSON.stringify(unrelated(proposed))) throw fail("Foundation companion patches may change only canonical imports for token files created/deleted in this patch; preserve all other imports and comments.", foundationChange.path);
|
|
234
236
|
}
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
if (!
|
|
237
|
+
for (const entry of [before.publicEntry, before.reviewEntry]) {
|
|
238
|
+
const exportChange = changes.find(change => before.relative(change.path) === entry);
|
|
239
|
+
if (!exportChange) continue;
|
|
240
|
+
if (!(entry === before.reviewEntry ? ["review"] : ["components", "patterns", "controllers"]).includes(unit.split("/")[0])) throw fail("Only its own layer may update re-exports: product owners use the public entry, review owners use the development review entry.", exportChange.path);
|
|
238
241
|
const current = exportChange.originalContent ?? "", proposed = exportChange.content;
|
|
239
242
|
if (proposed === null) throw fail("The shared public entry cannot be deleted.", exportChange.path);
|
|
240
243
|
const resolve = importResolver(afterOptions);
|
|
241
|
-
const file = path.join(afterOptions.dsRoot,
|
|
244
|
+
const file = path.join(afterOptions.dsRoot, entry);
|
|
242
245
|
const original = ts.createSourceFile(file, current, ts.ScriptTarget.Latest, true);
|
|
243
246
|
const candidate = ts.createSourceFile(file, proposed, ts.ScriptTarget.Latest, true);
|
|
244
247
|
const emptyExport = statement => ts.isExportDeclaration(statement) && !statement.moduleSpecifier && statement.exportClause && ts.isNamedExports(statement.exportClause) && !statement.exportClause.elements.length;
|
package/docs/ADS.md
CHANGED
|
@@ -114,7 +114,7 @@ are generated development evidence, outside source ownership and product bundles
|
|
|
114
114
|
See the portable [capture workflow](../skills/ads-designer/references/captures.md).
|
|
115
115
|
Token entries under the configured token directory declare
|
|
116
116
|
`export const scenario = { title: fixture.title, covers: ["TokenSamples"], samples: fixture.samples };`.
|
|
117
|
-
`TokenSamples` is any project-owned
|
|
117
|
+
`TokenSamples` is any project-owned development-only review renderer, not a required name.
|
|
118
118
|
Its colocated fixture declares literal `samples: [{ token, property, probe }]`.
|
|
119
119
|
Each token must exist and have sample coverage; duplicate bindings, missing probes,
|
|
120
120
|
empty covers and value-only inspectors fail. The default entry passes the declared
|
|
@@ -184,6 +184,19 @@ instead of assigning shared tokens in JavaScript. Full application harnesses
|
|
|
184
184
|
belong in application test support. Run ADS/project checks before application,
|
|
185
185
|
preview builds; review meaningful states in both themes and sizes.
|
|
186
186
|
|
|
187
|
+
## Development review layer
|
|
188
|
+
|
|
189
|
+
`review/` contains demo framing, demonstration controls and token renderers.
|
|
190
|
+
It has a separate `reviewEntry` (default `review/index.ts`), imported through
|
|
191
|
+
`${publicAlias}/review` (`@ds/review` by default). Product patterns are production
|
|
192
|
+
application UI. The public production barrel and product catalogue exclude review
|
|
193
|
+
exports; production code cannot depend on their implementation, types or styles.
|
|
194
|
+
Review rendering stays inside the App and retains the normal token/style and
|
|
195
|
+
public product-contract gates. See the portable
|
|
196
|
+
[review guide](../skills/ads-designer/references/review.md) for scenarios, guarded
|
|
197
|
+
owners, build aliases and migration. `ads_status.project.review` discovers the
|
|
198
|
+
connected project's actual entry. Older tooling must be upgraded before migration.
|
|
199
|
+
|
|
187
200
|
## Shared token contract
|
|
188
201
|
|
|
189
202
|
### Owner-local tokens
|
|
@@ -198,7 +211,7 @@ components/Notice/
|
|
|
198
211
|
tokens.css # :root { --notice-width: 356px; }
|
|
199
212
|
Scenario.tsx
|
|
200
213
|
fixture.ts
|
|
201
|
-
Tokens.scenario.tsx # kind: "tokens",
|
|
214
|
+
Tokens.scenario.tsx # kind: "tokens", development-only review renderer + samples
|
|
202
215
|
Tokens.fixture.ts
|
|
203
216
|
```
|
|
204
217
|
|
|
@@ -216,7 +229,7 @@ Measured runtime variables retain their existing exact `styleWrites` boundary.
|
|
|
216
229
|
`ads_tokens` returns each token's owner, definitions and local namespace.
|
|
217
230
|
|
|
218
231
|
A colocated scenario sets `kind:"tokens"` and declares real fixture `samples`
|
|
219
|
-
consumed by a
|
|
232
|
+
consumed by a development-only review renderer. Its ID still derives from its source path.
|
|
220
233
|
Discovery attaches its owner's registered definition sheet as `stylesheets` on
|
|
221
234
|
the generated scenario record; `previewEntriesPlugin` imports it directly into
|
|
222
235
|
that preview's module graph. CSS-only package side effects can then tree-shake
|
|
@@ -294,7 +307,7 @@ layout, component-specific focus rules and hover/disabled skins are rejected.
|
|
|
294
307
|
Shared token definitions belong in value sheets, not `base.css`. No project token
|
|
295
308
|
names are embedded in this policy. A zero-specificity `:where()` wrapper does not
|
|
296
309
|
change ownership. Put component design and animation in Linaria owners, and
|
|
297
|
-
scenario layout variations in typed
|
|
310
|
+
scenario layout variations in typed review-helper props. Browser review
|
|
298
311
|
still checks the effects and accessibility of permitted defaults.
|
|
299
312
|
|
|
300
313
|
|
|
@@ -394,6 +407,8 @@ The checks enforce the architecture's ownership boundaries:
|
|
|
394
407
|
|----------|------------------|
|
|
395
408
|
| Tokens and styles | Fixed token vocabulary, required definitions, declared value types and references, raw visual values, shared-token assignments, foundation import order, and component/pattern namespaces |
|
|
396
409
|
| Public API and dependencies | Consumers use public ADS imports; ADS implementations and showcase do not import application source; runtime code does not import showcase fixtures |
|
|
410
|
+
| Component and pattern layers | Component runtime cannot depend on patterns/composition, including through resolved aliases, re-exports and helpers; patterns consume public component symbols, not implementation helpers/types |
|
|
411
|
+
| Component styling contracts | Patterns cannot target proven private component classes/data markers or read known private component variables; public hooks and registered non-state customization variables remain available; ancestor context for a pattern's own styles is allowed |
|
|
397
412
|
| Interaction policy | Primitive state variables stay inside components; non-state customization hooks require explicit registration |
|
|
398
413
|
| Renderer exceptions | Inline styles and imperative writes require used, narrow configured boundaries; stale entries fail; public props omit inherited style and reject open-ended visual strings |
|
|
399
414
|
| Preview ownership | Scenarios define no CSS, custom classes, or standalone native controls; native slot children require public runtime cloning evidence; all declared tokens and public renderable UI have reachable registered scenarios; token references must exist; legacy catalogue pages are checked when present |
|
|
@@ -418,6 +433,18 @@ tests. Passing static checks establishes only the policies and source formats
|
|
|
418
433
|
they cover. Browser review and behavior tests still verify accessibility,
|
|
419
434
|
interaction, responsive layout, themes, and motion.
|
|
420
435
|
|
|
436
|
+
A component provides one cohesive UI capability; a pattern arranges capabilities
|
|
437
|
+
into a reusable structure or workflow. Component count is not a rule. Components
|
|
438
|
+
may compose components/controllers; layout patterns can arrange content slots;
|
|
439
|
+
component scenarios may use development-only review helpers. Classification is design
|
|
440
|
+
guidance, while `component-dependency`, `component-contract` and `component-style`
|
|
441
|
+
are blocking source-ownership rules. Type-only higher-layer references are not
|
|
442
|
+
runtime edges. Relative component imports inside the ADS are valid when the
|
|
443
|
+
selected symbols are public; a self-import through the root barrel is not required.
|
|
444
|
+
Opaque/computed dependencies and ambiguous/generated style hooks require review.
|
|
445
|
+
See the skill-local [layer guide](../skills/ads-designer/references/layers.md), also
|
|
446
|
+
available through MCP at `ads://guides/layers`.
|
|
447
|
+
|
|
421
448
|
Component-specific usage rules belong to that component in the receiving
|
|
422
449
|
project. Import applicable rules with the item and register them through
|
|
423
450
|
project configuration or maintained tooling integration. Core tooling must
|
|
@@ -448,7 +475,7 @@ Root [bootstrap-ds/](../bootstrap-ds/README.md) is the canonical empty scaffold.
|
|
|
448
475
|
Its identical copy under `skills/ads-designer/assets/bootstrap-ds/` makes the
|
|
449
476
|
skill self-contained. Run `npm run sync:skill-starter` after edits and
|
|
450
477
|
`npm run check:skill-starter` to verify the copy. Both contain empty product component/composition directories and a minimal project-owned
|
|
451
|
-
token review
|
|
478
|
+
token review renderer. The scaffold pattern can be renamed or replaced; the tool
|
|
452
479
|
does not require that name or its styles and ships no product UI catalogue.
|
|
453
480
|
|
|
454
481
|
Tool releases should version contract changes, rules, skills, bootstrap support,
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -67,6 +67,32 @@ state mechanics. Patterns own reusable layout and composition. Application
|
|
|
67
67
|
containers provide domain data, routing, application effects, and callbacks through public
|
|
68
68
|
APIs.
|
|
69
69
|
|
|
70
|
+
A component provides one cohesive UI capability. A pattern arranges capabilities
|
|
71
|
+
into a reusable structure or workflow; a layout part may arrange content slots.
|
|
72
|
+
Components may compose other components/controllers, and patterns may compose
|
|
73
|
+
patterns. Import count, element count and implementation size do not decide the
|
|
74
|
+
layer. Scenarios may compose public UI and development review helpers to demonstrate their
|
|
75
|
+
subject without becoming production patterns.
|
|
76
|
+
|
|
77
|
+
Patterns are production application UI. Development-only framing, demo controls
|
|
78
|
+
and token renderers belong in project-owned `review/`, with a separate
|
|
79
|
+
`reviewEntry` (default `review/index.ts`) and `${publicAlias}/review` import alias.
|
|
80
|
+
They are absent from the product barrel and catalogue. Guards reject production
|
|
81
|
+
dependencies on review code, types and styles; review source keeps normal styling,
|
|
82
|
+
token and public product-contract checks. Scenarios exercise the real production
|
|
83
|
+
implementation through fixtures. The [portable review guide](../skills/ads-designer/references/review.md)
|
|
84
|
+
defines guarded owners, build isolation and migration steps. Review rendering
|
|
85
|
+
stays inside the App iframe; it adds no project execution to the host shell.
|
|
86
|
+
|
|
87
|
+
Core guards reject component runtime dependencies on patterns/composition through
|
|
88
|
+
resolved imports, re-exports and helpers. Patterns consume public component
|
|
89
|
+
contracts rather than private implementation symbols or rendered style hooks;
|
|
90
|
+
documented non-state customization variables remain available. Source tracing
|
|
91
|
+
distinguishes styling a private part from reading ancestor context for the
|
|
92
|
+
pattern's own arrangement. Application and development dependencies retain their
|
|
93
|
+
separate boundaries. The portable skill-local [layer guide](../skills/ads-designer/references/layers.md)
|
|
94
|
+
explains repairs and analysis limits; semantic classification still needs review.
|
|
95
|
+
|
|
70
96
|
The Data pillar describes design values; business data is a separate input to
|
|
71
97
|
the UX contract. Application adapters own live business-data loading,
|
|
72
98
|
authentication, stores, routing, caching and refresh policy. Components and
|
|
@@ -233,6 +259,13 @@ external bases still require declared CSP origins. This belongs to document
|
|
|
233
259
|
loading and changes no project link or scenario handler. External hosts control
|
|
234
260
|
their own document-loading and CSP behavior.
|
|
235
261
|
|
|
262
|
+
The proxy and App sandbox permit native forms (`allow-forms`), including the
|
|
263
|
+
legacy nested widget. This lets browser constraint validation and `submit`
|
|
264
|
+
handlers run for clicks, Enter and `requestSubmit()`. Client-side handlers retain
|
|
265
|
+
their own `preventDefault()` behavior. The App stays opaque; CSP
|
|
266
|
+
`form-action 'none'` blocks native action requests without suppressing submit
|
|
267
|
+
handlers. Hosts outside ADS choose their own sandbox and CSP permissions.
|
|
268
|
+
|
|
236
269
|
The project compiler publishes a versioned dependency graph: shared runtime and
|
|
237
270
|
foundation assets, plus independently addressable scenario modules. Inside the
|
|
238
271
|
App, a resource loader obtains the selected dependency closure through MCP,
|
|
@@ -302,12 +335,12 @@ real public implementation. It mounts independently, without opening a showcase
|
|
|
302
335
|
page or initializing the application's router, store or services first.
|
|
303
336
|
|
|
304
337
|
Scenarios and their fixtures live beside the tokens, component or pattern they exercise.
|
|
305
|
-
Demo framing belongs to
|
|
338
|
+
Demo framing belongs to development-only review helpers; component props describe
|
|
306
339
|
intentional product behavior and visual variants.
|
|
307
340
|
Token scenarios choose real token names and sample inputs; a project-owned
|
|
308
|
-
review
|
|
341
|
+
review renderer applies the foundation variables. The tool contains no project
|
|
309
342
|
token list, sample templates or assumed visual identity. Even an initial token
|
|
310
|
-
scenario uses a
|
|
343
|
+
scenario uses a project-owned development review renderer to apply its declared samples;
|
|
311
344
|
a definitions-only inspector does not establish preview coverage.
|
|
312
345
|
Larger scenarios live under `composition/`. They use the same public screen
|
|
313
346
|
patterns as production: application adapters supply live data and effects;
|
|
@@ -538,7 +571,7 @@ For concrete instructions, use:
|
|
|
538
571
|
|
|
539
572
|
Token preview completeness has two checks. Static guards require explicit fixture
|
|
540
573
|
bindings (`token`, CSS `property`, and project-selected `probe`) consumed by a public
|
|
541
|
-
review
|
|
574
|
+
review renderer. The App then verifies rendered samples in the actual browser by
|
|
542
575
|
probing those bindings and restoring them. The tool supplies no token/property
|
|
543
576
|
classification or visual sample palette. A source build alone is not a rendered
|
|
544
577
|
verification, and the browser check does not judge design quality.
|