@reqvire-org/ads 0.3.13 → 0.3.15
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/bootstrap-ds/ADS.md +4 -1
- package/dist/check.mjs +8 -2
- package/dist/mcp/sandbox-host.mjs +1 -1
- package/dist/mcp/widget.bundle.js +14 -14
- package/dist/scenario-slots.mjs +124 -0
- package/dist/showcase/sandbox.bundle.js +1 -0
- package/dist/skills/ads-break-ui/SKILL.md +2 -2
- package/dist/skills/ads-break-ui/references/guarded-editing.md +14 -3
- package/dist/skills/ads-break-ui/references/scenarios.md +46 -1
- package/dist/skills/ads-designer/SKILL.md +2 -2
- package/dist/skills/ads-designer/assets/bootstrap-ds/ADS.md +4 -1
- package/dist/skills/ads-designer/references/guarded-editing.md +14 -3
- package/dist/skills/ads-designer/references/scenarios.md +46 -1
- package/dist/skills/ads-import/SKILL.md +2 -2
- package/dist/skills/ads-import/references/guarded-editing.md +14 -3
- package/dist/skills/ads-import/references/scenarios.md +46 -1
- package/dist/skills/ads-migrate/SKILL.md +2 -2
- package/dist/skills/ads-migrate/references/guarded-editing.md +14 -3
- package/dist/skills/ads-migrate/references/scenarios.md +46 -1
- package/dist/skills/ads-motion/SKILL.md +2 -2
- package/dist/skills/ads-motion/references/guarded-editing.md +14 -3
- package/dist/skills/ads-motion/references/scenarios.md +46 -1
- package/dist/source-values.mjs +2 -1
- package/dist/verification.mjs +8 -3
- package/docs/ADS.md +5 -2
- package/docs/ARCHITECTURE.md +11 -0
- package/docs/BEHAVIORS.md +8 -3
- package/docs/CHANGELOG.md +17 -0
- package/docs/MCP.md +12 -0
- package/package.json +1 -1
- package/dist/showcase/sandbox.js +0 -30
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { isDevelopmentFile } from "./config.mjs";
|
|
3
|
+
import { publicApi } from "./public-api.mjs";
|
|
4
|
+
import { createSourceValues, isFunction, reference, unwrap } from "./source-values.mjs";
|
|
5
|
+
import { uiOperation } from "./ui-framework.mjs";
|
|
6
|
+
|
|
7
|
+
/** A native scenario child may supply semantics to a public runtime slot. The
|
|
8
|
+
* proof follows actual child cloning, never a prop/component/helper spelling. */
|
|
9
|
+
export function createScenarioSlots(program, options) {
|
|
10
|
+
const checker = program.getTypeChecker(), cache = new WeakMap();
|
|
11
|
+
const operation = node => uiOperation(node, checker);
|
|
12
|
+
const values = createSourceValues(program, options, { strict: true, preserveCall: node => ["createElement", "cloneElement", "Children.only"].includes(operation(node)) });
|
|
13
|
+
const { state, next, resolve, get, keys, props, returns, declaration } = values;
|
|
14
|
+
const publicNodes = new Set(publicApi(program, options).filter(item => item.renderable).map(item => resolve(reference(item.declaration.name ?? item.declaration), state())).filter(value => value.kind === "node").map(value => value.node));
|
|
15
|
+
|
|
16
|
+
function element(node, env = new Map(), via = []) {
|
|
17
|
+
if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
18
|
+
const opening = ts.isJsxElement(node) ? node.openingElement : node;
|
|
19
|
+
const attributes = props(opening, env, via);
|
|
20
|
+
const children = ts.isJsxElement(node) ? node.children.filter(child => !ts.isJsxText(child) || child.text.trim()).filter(child => !ts.isJsxExpression(child) || child.expression) : [];
|
|
21
|
+
if (children.length) attributes.layers.push(new Map([["children", children.length === 1 ? reference(children[0], env, via) : { kind: "array", values: children.map(child => reference(child, env, via)) }]]));
|
|
22
|
+
return { tag: reference(opening.tagName, env, via), attributes, intrinsic: ts.isIdentifier(opening.tagName) && /^[a-z]/.test(opening.tagName.text) };
|
|
23
|
+
}
|
|
24
|
+
if (ts.isCallExpression(node) && operation(node.expression) === "createElement") {
|
|
25
|
+
const attributes = { kind: "object", layers: node.arguments[1] && node.arguments[1].kind !== ts.SyntaxKind.NullKeyword ? [reference(node.arguments[1], env, via)] : [] };
|
|
26
|
+
const children = node.arguments.slice(2).map(child => reference(child, env, via));
|
|
27
|
+
if (children.length) attributes.layers.push(new Map([["children", children.length === 1 ? children[0] : { kind: "array", values: children }]]));
|
|
28
|
+
return { tag: reference(node.arguments[0], env, via), attributes, intrinsic: !!node.arguments[0] && ts.isStringLiteralLike(node.arguments[0]) };
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return function nativeSlot(site) {
|
|
34
|
+
if (cache.has(site)) return cache.get(site);
|
|
35
|
+
const reasons = new Set(); let cloned = false, exposed = false, uncertain = false, steps = 0;
|
|
36
|
+
const fail = reason => { uncertain = true; reasons.add(reason); };
|
|
37
|
+
function childValue(input, context) {
|
|
38
|
+
const value = resolve(input, next(context));
|
|
39
|
+
if (value.kind === "node" && ts.isJsxExpression(value.node)) return childValue(reference(value.node.expression, value.env, value.via), next(context));
|
|
40
|
+
if (value.kind === "node" && ts.isCallExpression(value.node) && operation(value.node.expression) === "Children.only") return childValue(reference(value.node.arguments[0], value.env, value.via), next(context));
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
function ownedProps(input, context, seen = new Set()) {
|
|
44
|
+
if (context.depth > 40) return false;
|
|
45
|
+
const value = resolve(input, next(context));
|
|
46
|
+
const opaque = value.kind === "unknown" || value.kind === "union" && value.values.length <= 32 && value.values.every(branch => resolve(branch, next(context)).kind === "unknown");
|
|
47
|
+
if (value.kind === "union" && !opaque) return value.values.length <= 32 && value.values.every(branch => ownedProps(branch, next(context), new Set(seen)));
|
|
48
|
+
if (keys(value, next(context)).some(key => key !== "children")) return true;
|
|
49
|
+
// Local prop mergers may use loops and a ref assignment, beyond the value
|
|
50
|
+
// evaluator. Retain runtime ownership through their actual input props;
|
|
51
|
+
// a known empty result, external call or arbitrary identifier cannot qualify.
|
|
52
|
+
if (!opaque || input.kind !== "node") return false;
|
|
53
|
+
const node = unwrap(input.node), { env, via } = input;
|
|
54
|
+
if (seen.has(node)) return false;
|
|
55
|
+
seen.add(node);
|
|
56
|
+
if (ts.isIdentifier(node)) {
|
|
57
|
+
if (env.has(checker.getSymbolAtLocation(node))) return ownedProps(env.get(checker.getSymbolAtLocation(node)), next(context), seen);
|
|
58
|
+
const binding = declaration(node);
|
|
59
|
+
return !!(binding && ts.isVariableDeclaration(binding) && binding.parent.flags & ts.NodeFlags.Const && binding.initializer && !isDevelopmentFile(binding.getSourceFile().fileName, options) && ownedProps(reference(binding.initializer, env, via), next(context), seen));
|
|
60
|
+
}
|
|
61
|
+
if (ts.isCallExpression(node)) {
|
|
62
|
+
const target = resolve(reference(node.expression, env, via), next(context));
|
|
63
|
+
return target.kind === "node" && isFunction(target.node) && !isDevelopmentFile(target.node.getSourceFile().fileName, options) && node.arguments.some(argument => ownedProps(reference(argument, env, via), next(context), new Set(seen)));
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
function render(input, context) {
|
|
68
|
+
if (++steps > 500 || context.depth > 48) { fail("Slot tracing reached its source work limit."); return; }
|
|
69
|
+
const value = childValue(input, context);
|
|
70
|
+
context = value.context ?? input.context ?? context;
|
|
71
|
+
if (value.kind === "slot-child") { exposed = true; return; }
|
|
72
|
+
if (["union", "array"].includes(value.kind)) {
|
|
73
|
+
if (value.values.length > 32) { fail("Slot tracing reached its alternative limit."); return; }
|
|
74
|
+
for (const child of value.values) render(child, next(context));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (value.kind === "unknown") { fail(value.reason || "The runtime slot's render path could not be traced."); return; }
|
|
78
|
+
if (value.kind !== "node") return;
|
|
79
|
+
const { node, env, via } = value;
|
|
80
|
+
if (ts.isJsxFragment(node)) { for (const child of node.children) render(reference(child, env, via), next(context)); return; }
|
|
81
|
+
if (ts.isArrayLiteralExpression(node)) { for (const child of node.elements) render(reference(ts.isSpreadElement(child) ? child.expression : child, env, via), next(context)); return; }
|
|
82
|
+
if (ts.isCallExpression(node) && operation(node.expression) === "cloneElement") {
|
|
83
|
+
const child = childValue(reference(node.arguments[0], env, via), next(context));
|
|
84
|
+
if (child.kind === "slot-child") {
|
|
85
|
+
if (!node.arguments[1] || !ownedProps(reference(node.arguments[1], env, via), state())) fail("A slot must clone its child with runtime-owned props.");
|
|
86
|
+
else cloned = true;
|
|
87
|
+
} else render(child, next(context));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const view = element(node, env, via);
|
|
91
|
+
if (!view) return;
|
|
92
|
+
function component(input) {
|
|
93
|
+
const target = resolve(input, next(context));
|
|
94
|
+
if (target.kind === "union") {
|
|
95
|
+
if (target.values.length > 32) { fail("Slot tracing reached its alternative limit."); return; }
|
|
96
|
+
for (const branch of target.values) component(branch);
|
|
97
|
+
} else if (view.intrinsic || ["provider", "context"].includes(target.kind) || target.kind === "literal" && typeof target.value === "string") render(get(view.attributes, "children", next(context)), next(context));
|
|
98
|
+
else if (target.kind === "node" && isFunction(target.node) && !isDevelopmentFile(target.node.getSourceFile().fileName, options)) {
|
|
99
|
+
for (const output of returns(target, [view.attributes], next(context), "component")) render(output, next(context));
|
|
100
|
+
} else fail("The runtime slot's component target could not be traced.");
|
|
101
|
+
}
|
|
102
|
+
component(view.tag);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const native = ts.isJsxOpeningElement(site) ? site.parent : site;
|
|
106
|
+
let child = native;
|
|
107
|
+
while (child.parent && (ts.isJsxExpression(child.parent) || ts.isParenthesizedExpression(child.parent) || ts.isAsExpression(child.parent) || ts.isSatisfiesExpression(child.parent) || ts.isNonNullExpression(child.parent))) child = child.parent;
|
|
108
|
+
let parent = child.parent;
|
|
109
|
+
if (parent && ts.isJsxAttribute(parent) && parent.name.text === "children") parent = parent.parent.parent;
|
|
110
|
+
if (parent && ts.isPropertyAssignment(parent) && parent.name.getText().replace(/^["']|["']$/g, "") === "children" && ts.isObjectLiteralExpression(parent.parent) && ts.isCallExpression(parent.parent.parent) && parent.parent.parent.arguments[1] === parent.parent) parent = parent.parent.parent;
|
|
111
|
+
const view = parent && element(parent), context = state();
|
|
112
|
+
if (view) {
|
|
113
|
+
const target = resolve(view.tag, next(context));
|
|
114
|
+
const original = childValue(get(view.attributes, "children", next(context)), next(context));
|
|
115
|
+
if (target.kind === "node" && publicNodes.has(target.node) && original.kind === "node" && original.node === native) {
|
|
116
|
+
view.attributes.layers.push(new Map([["children", { kind: "slot-child" }]]));
|
|
117
|
+
for (const output of returns(target, [view.attributes], next(context), "component")) render(output, next(context));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const result = { ok: cloned && !exposed && !uncertain, reasons: [...reasons].slice(0, 2) };
|
|
121
|
+
cache.set(site, result);
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function c(e,t){let n=new DOMParser().parseFromString(e,"text/html"),r=n.createElement("meta");if(r.httpEquiv="Content-Security-Policy",r.content=t,n.head.prepend(r),!n.querySelector("base[href]")){let i=n.querySelector("base")??n.createElement("base");i.setAttribute("href","about:srcdoc"),r.after(i)}return"<!doctype html>"+n.documentElement.outerHTML}var a=new URL(location.href).searchParams.get("parent"),o;function s(e=[]){return e.filter(t=>/^(?:https?:\/\/[a-z0-9.*:[\]-]+(?::\d+)?|data:|blob:|about:)$/i.test(t)).join(" ")}function d(e={}){let t=s(e.resourceDomains);return`default-src 'none';script-src 'unsafe-inline' ${t};style-src 'unsafe-inline' ${t};img-src data: ${t};font-src ${t||"'none'"};media-src ${t||"'none'"};worker-src ${t||"'none'"};connect-src ${s(e.connectDomains)||"'none'"};frame-src ${s(e.frameDomains)||"'none'"};base-uri about: ${s(e.baseUriDomains)};object-src 'none'`}window.addEventListener("message",e=>{if(e.source===parent&&e.origin===a){let t=e.data;if(t?.method==="ui/notifications/sandbox-resource-ready"){let{html:n,csp:r}=t.params??{};if(typeof n!="string")return;o?.remove(),o=window.document.createElement("iframe"),o.title="Design-system App",o.setAttribute("sandbox","allow-scripts"),window.document.body.append(o),o.srcdoc=c(n,d(r))}else t?.jsonrpc==="2.0"&&!t.method?.startsWith("ui/notifications/sandbox-")&&o?.contentWindow.postMessage(t,"*")}else e.source===o?.contentWindow&&e.data?.jsonrpc==="2.0"&&!e.data.method?.startsWith("ui/notifications/sandbox-")&&parent.postMessage(e.data,a)});parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-ready",params:{}},a);
|
|
@@ -55,8 +55,8 @@ For on-demand current/candidate screenshots and visual dry-run review, read
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
For parent/child `covers`, conditional-control review, reference comparisons,
|
|
58
|
-
public style-helper use
|
|
59
|
-
findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
58
|
+
public style-helper use, fragment-link navigation, or `scenario-render` /
|
|
59
|
+
`showcase-class` findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
60
60
|
examples explain API visibility, reference baselines and state-transition checks.
|
|
61
61
|
Traced parents can cover declared public children; verified public Linaria
|
|
62
62
|
helpers do not grant custom scenario CSS.
|
|
@@ -107,6 +107,17 @@ Keep contextual public parts public when they are intended consumer API. Demonst
|
|
|
107
107
|
them through their actual public composition/customization path and list their real
|
|
108
108
|
render references in covers. Do not count internal production renders as public API
|
|
109
109
|
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
110
|
-
Scenario controls still use public UI
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
Scenario controls still use public UI. A native link/button can supply semantics
|
|
111
|
+
as the single direct child of a public runtime slot when source tracing proves
|
|
112
|
+
that owner clones the child with its props. An `asChild` flag alone is insufficient;
|
|
113
|
+
standalone native controls and custom scenario styling remain rejected. See
|
|
114
|
+
[scenarios.md](scenarios.md) for evidence and limits. Preserve the intended
|
|
115
|
+
composition instead of substituting an unrelated styled control or adding a
|
|
116
|
+
demo-only component prop. Review framing belongs in public layout patterns.
|
|
117
|
+
|
|
118
|
+
A complete runner report containing an ordinary failed assertion preserves each
|
|
119
|
+
passing check as `passed`; the failed check remains `failed`, and overall
|
|
120
|
+
verification still rejects the mutation. Fix the actual failing checks instead of
|
|
121
|
+
assuming every affected owner failed. Suite errors, unexplained runner exits,
|
|
122
|
+
missing results and interrupted runs cannot certify passing guarantees. Use the
|
|
123
|
+
case's `reportedStatus`, message and report to distinguish these conditions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Scenario rendering, token previews and public class helpers
|
|
2
2
|
|
|
3
|
-
Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
|
|
3
|
+
Use this reference for `scenario-render`, `scenario-coverage`, `showcase-control` or `showcase-class`
|
|
4
4
|
diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
|
|
5
5
|
|
|
6
6
|
All preview kinds open at `?scenario=<discovered-id>`. Use the returned showcase
|
|
@@ -23,6 +23,17 @@ on-demand element screenshots. It grants no render/behavior coverage and no extr
|
|
|
23
23
|
styling permission. Use [captures.md](captures.md) for current/candidate review,
|
|
24
24
|
target selection, resource reads and storage lifecycle.
|
|
25
25
|
|
|
26
|
+
## Fragment links inside Apps
|
|
27
|
+
|
|
28
|
+
Keep intended `href="#"` and named fragments in the project API and fixtures.
|
|
29
|
+
ADS's inline-document loader supplies an `about:srcdoc` base when the App has no
|
|
30
|
+
explicit base, preserving native scrolling, events and state. If a fragment
|
|
31
|
+
replaces the App with a sandbox URL or browser error, inspect `location.href`,
|
|
32
|
+
`document.baseURI` and the resolved anchor URL. Report a host loading defect;
|
|
33
|
+
do not add scenario `preventDefault` handlers merely to hide it. Explicit App
|
|
34
|
+
bases retain their declared behavior and CSP requirements; external hosts own
|
|
35
|
+
their document-loading policy. Verify link activation as well as rendering.
|
|
36
|
+
|
|
26
37
|
## Owner-local token previews load their own definitions
|
|
27
38
|
|
|
28
39
|
Keep the registered token sheet imported by its runtime owner for product use.
|
|
@@ -90,6 +101,40 @@ do not export the helper solely for a test. Public/private ownership is a produc
|
|
|
90
101
|
decision, not a coverage workaround. Browser checks verify transitions but do not
|
|
91
102
|
replace the current static `covers` requirement; `exercises` does not waive it.
|
|
92
103
|
|
|
104
|
+
## Native semantics through a public runtime slot
|
|
105
|
+
|
|
106
|
+
A native element can be the direct child of a public runtime component that
|
|
107
|
+
actually clones that child with its own props:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Action asChild>
|
|
111
|
+
<a href={fixture.destination}>Documentation</a>
|
|
112
|
+
</Action>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`Action` and the fixture are illustrative; use the project's intended public API.
|
|
116
|
+
The runtime owner supplies presentation and interaction; the anchor supplies link
|
|
117
|
+
semantics. Keep this composition when it is the product contract. Do not replace
|
|
118
|
+
the anchor with an unrelated styled link, add a demo-only prop, disable the guard
|
|
119
|
+
or write outside MCP merely to silence a diagnostic.
|
|
120
|
+
|
|
121
|
+
ADS follows the selected runtime render path, the exact child and real imported
|
|
122
|
+
React/Preact `cloneElement` operations, including local slot/prop-merging helpers.
|
|
123
|
+
The prop need not be named `asChild`; the spelling alone grants no permission.
|
|
124
|
+
JSX and recognized framework factories follow the same rule. The native element
|
|
125
|
+
must be the single direct child: another native control nested inside it remains
|
|
126
|
+
subject to the ordinary ownership rule. Passing children through a container,
|
|
127
|
+
a scenario-local wrapper or an opaque component does not establish a slot.
|
|
128
|
+
|
|
129
|
+
This grants no scenario styling permission. Inline styles and arbitrary class
|
|
130
|
+
names remain rejected, including on the slotted child. Public style helpers retain
|
|
131
|
+
their own provenance checks. Unknown branches that could render the native child
|
|
132
|
+
directly, multiple children and untraceable replacement props remain blocked.
|
|
133
|
+
If a valid slot contract cannot be traced, keep the intended API and report a
|
|
134
|
+
small reproduction rather than inventing a product workaround. Static proof
|
|
135
|
+
establishes ownership, not correct prop merging, focus, keyboard or navigation
|
|
136
|
+
behavior; verify those in the built App and registered checks.
|
|
137
|
+
|
|
93
138
|
## Scenarios may consume verified public style helpers
|
|
94
139
|
|
|
95
140
|
A deliberately public helper can expose its owner's Linaria treatment:
|
|
@@ -86,8 +86,8 @@ For on-demand current/candidate screenshots and visual dry-run review, read
|
|
|
86
86
|
[captures.md](references/captures.md).
|
|
87
87
|
|
|
88
88
|
For parent/child `covers`, conditional-control review, reference comparisons,
|
|
89
|
-
public style-helper use
|
|
90
|
-
findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
89
|
+
public style-helper use, fragment-link navigation, or `scenario-render` /
|
|
90
|
+
`showcase-class` findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
91
91
|
examples explain API visibility, reference baselines and state-transition checks.
|
|
92
92
|
Traced parents can cover declared public children; verified public Linaria
|
|
93
93
|
helpers do not grant custom scenario CSS.
|
|
@@ -197,7 +197,10 @@ or applies the right CSS property. Browser review still verifies the samples.
|
|
|
197
197
|
|
|
198
198
|
Scenarios and fixture helpers are development-only wherever colocated. Runtime
|
|
199
199
|
source and the public barrel cannot import or re-export them. Showcase/scenario
|
|
200
|
-
code defines no CSS, custom classes or native controls; use public ADS
|
|
200
|
+
code defines no CSS, custom classes or standalone native controls; use public ADS
|
|
201
|
+
APIs. A single direct native child can supply semantics to a public runtime slot
|
|
202
|
+
when source tracing proves that owner clones the exact child with its own props.
|
|
203
|
+
An `asChild` flag alone is not evidence; scenario styling remains forbidden.
|
|
201
204
|
Neither ADS implementations nor scenarios import application code. Live business
|
|
202
205
|
data belongs to application adapters; ADS receives inputs or injected callbacks.
|
|
203
206
|
Direct global `fetch`, XHR, WebSocket and EventSource use is rejected. Renderer
|
|
@@ -107,6 +107,17 @@ Keep contextual public parts public when they are intended consumer API. Demonst
|
|
|
107
107
|
them through their actual public composition/customization path and list their real
|
|
108
108
|
render references in covers. Do not count internal production renders as public API
|
|
109
109
|
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
110
|
-
Scenario controls still use public UI
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
Scenario controls still use public UI. A native link/button can supply semantics
|
|
111
|
+
as the single direct child of a public runtime slot when source tracing proves
|
|
112
|
+
that owner clones the child with its props. An `asChild` flag alone is insufficient;
|
|
113
|
+
standalone native controls and custom scenario styling remain rejected. See
|
|
114
|
+
[scenarios.md](scenarios.md) for evidence and limits. Preserve the intended
|
|
115
|
+
composition instead of substituting an unrelated styled control or adding a
|
|
116
|
+
demo-only component prop. Review framing belongs in public layout patterns.
|
|
117
|
+
|
|
118
|
+
A complete runner report containing an ordinary failed assertion preserves each
|
|
119
|
+
passing check as `passed`; the failed check remains `failed`, and overall
|
|
120
|
+
verification still rejects the mutation. Fix the actual failing checks instead of
|
|
121
|
+
assuming every affected owner failed. Suite errors, unexplained runner exits,
|
|
122
|
+
missing results and interrupted runs cannot certify passing guarantees. Use the
|
|
123
|
+
case's `reportedStatus`, message and report to distinguish these conditions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Scenario rendering, token previews and public class helpers
|
|
2
2
|
|
|
3
|
-
Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
|
|
3
|
+
Use this reference for `scenario-render`, `scenario-coverage`, `showcase-control` or `showcase-class`
|
|
4
4
|
diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
|
|
5
5
|
|
|
6
6
|
All preview kinds open at `?scenario=<discovered-id>`. Use the returned showcase
|
|
@@ -23,6 +23,17 @@ on-demand element screenshots. It grants no render/behavior coverage and no extr
|
|
|
23
23
|
styling permission. Use [captures.md](captures.md) for current/candidate review,
|
|
24
24
|
target selection, resource reads and storage lifecycle.
|
|
25
25
|
|
|
26
|
+
## Fragment links inside Apps
|
|
27
|
+
|
|
28
|
+
Keep intended `href="#"` and named fragments in the project API and fixtures.
|
|
29
|
+
ADS's inline-document loader supplies an `about:srcdoc` base when the App has no
|
|
30
|
+
explicit base, preserving native scrolling, events and state. If a fragment
|
|
31
|
+
replaces the App with a sandbox URL or browser error, inspect `location.href`,
|
|
32
|
+
`document.baseURI` and the resolved anchor URL. Report a host loading defect;
|
|
33
|
+
do not add scenario `preventDefault` handlers merely to hide it. Explicit App
|
|
34
|
+
bases retain their declared behavior and CSP requirements; external hosts own
|
|
35
|
+
their document-loading policy. Verify link activation as well as rendering.
|
|
36
|
+
|
|
26
37
|
## Owner-local token previews load their own definitions
|
|
27
38
|
|
|
28
39
|
Keep the registered token sheet imported by its runtime owner for product use.
|
|
@@ -90,6 +101,40 @@ do not export the helper solely for a test. Public/private ownership is a produc
|
|
|
90
101
|
decision, not a coverage workaround. Browser checks verify transitions but do not
|
|
91
102
|
replace the current static `covers` requirement; `exercises` does not waive it.
|
|
92
103
|
|
|
104
|
+
## Native semantics through a public runtime slot
|
|
105
|
+
|
|
106
|
+
A native element can be the direct child of a public runtime component that
|
|
107
|
+
actually clones that child with its own props:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Action asChild>
|
|
111
|
+
<a href={fixture.destination}>Documentation</a>
|
|
112
|
+
</Action>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`Action` and the fixture are illustrative; use the project's intended public API.
|
|
116
|
+
The runtime owner supplies presentation and interaction; the anchor supplies link
|
|
117
|
+
semantics. Keep this composition when it is the product contract. Do not replace
|
|
118
|
+
the anchor with an unrelated styled link, add a demo-only prop, disable the guard
|
|
119
|
+
or write outside MCP merely to silence a diagnostic.
|
|
120
|
+
|
|
121
|
+
ADS follows the selected runtime render path, the exact child and real imported
|
|
122
|
+
React/Preact `cloneElement` operations, including local slot/prop-merging helpers.
|
|
123
|
+
The prop need not be named `asChild`; the spelling alone grants no permission.
|
|
124
|
+
JSX and recognized framework factories follow the same rule. The native element
|
|
125
|
+
must be the single direct child: another native control nested inside it remains
|
|
126
|
+
subject to the ordinary ownership rule. Passing children through a container,
|
|
127
|
+
a scenario-local wrapper or an opaque component does not establish a slot.
|
|
128
|
+
|
|
129
|
+
This grants no scenario styling permission. Inline styles and arbitrary class
|
|
130
|
+
names remain rejected, including on the slotted child. Public style helpers retain
|
|
131
|
+
their own provenance checks. Unknown branches that could render the native child
|
|
132
|
+
directly, multiple children and untraceable replacement props remain blocked.
|
|
133
|
+
If a valid slot contract cannot be traced, keep the intended API and report a
|
|
134
|
+
small reproduction rather than inventing a product workaround. Static proof
|
|
135
|
+
establishes ownership, not correct prop merging, focus, keyboard or navigation
|
|
136
|
+
behavior; verify those in the built App and registered checks.
|
|
137
|
+
|
|
93
138
|
## Scenarios may consume verified public style helpers
|
|
94
139
|
|
|
95
140
|
A deliberately public helper can expose its owner's Linaria treatment:
|
|
@@ -50,8 +50,8 @@ For on-demand current/candidate screenshots and visual dry-run review, read
|
|
|
50
50
|
[captures.md](references/captures.md).
|
|
51
51
|
|
|
52
52
|
For parent/child `covers`, conditional-control review, reference comparisons,
|
|
53
|
-
public style-helper use
|
|
54
|
-
findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
53
|
+
public style-helper use, fragment-link navigation, or `scenario-render` /
|
|
54
|
+
`showcase-class` findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
55
55
|
examples explain API visibility, reference baselines and state-transition checks.
|
|
56
56
|
Traced parents can cover declared public children; verified public Linaria
|
|
57
57
|
helpers do not grant custom scenario CSS.
|
|
@@ -107,6 +107,17 @@ Keep contextual public parts public when they are intended consumer API. Demonst
|
|
|
107
107
|
them through their actual public composition/customization path and list their real
|
|
108
108
|
render references in covers. Do not count internal production renders as public API
|
|
109
109
|
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
110
|
-
Scenario controls still use public UI
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
Scenario controls still use public UI. A native link/button can supply semantics
|
|
111
|
+
as the single direct child of a public runtime slot when source tracing proves
|
|
112
|
+
that owner clones the child with its props. An `asChild` flag alone is insufficient;
|
|
113
|
+
standalone native controls and custom scenario styling remain rejected. See
|
|
114
|
+
[scenarios.md](scenarios.md) for evidence and limits. Preserve the intended
|
|
115
|
+
composition instead of substituting an unrelated styled control or adding a
|
|
116
|
+
demo-only component prop. Review framing belongs in public layout patterns.
|
|
117
|
+
|
|
118
|
+
A complete runner report containing an ordinary failed assertion preserves each
|
|
119
|
+
passing check as `passed`; the failed check remains `failed`, and overall
|
|
120
|
+
verification still rejects the mutation. Fix the actual failing checks instead of
|
|
121
|
+
assuming every affected owner failed. Suite errors, unexplained runner exits,
|
|
122
|
+
missing results and interrupted runs cannot certify passing guarantees. Use the
|
|
123
|
+
case's `reportedStatus`, message and report to distinguish these conditions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Scenario rendering, token previews and public class helpers
|
|
2
2
|
|
|
3
|
-
Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
|
|
3
|
+
Use this reference for `scenario-render`, `scenario-coverage`, `showcase-control` or `showcase-class`
|
|
4
4
|
diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
|
|
5
5
|
|
|
6
6
|
All preview kinds open at `?scenario=<discovered-id>`. Use the returned showcase
|
|
@@ -23,6 +23,17 @@ on-demand element screenshots. It grants no render/behavior coverage and no extr
|
|
|
23
23
|
styling permission. Use [captures.md](captures.md) for current/candidate review,
|
|
24
24
|
target selection, resource reads and storage lifecycle.
|
|
25
25
|
|
|
26
|
+
## Fragment links inside Apps
|
|
27
|
+
|
|
28
|
+
Keep intended `href="#"` and named fragments in the project API and fixtures.
|
|
29
|
+
ADS's inline-document loader supplies an `about:srcdoc` base when the App has no
|
|
30
|
+
explicit base, preserving native scrolling, events and state. If a fragment
|
|
31
|
+
replaces the App with a sandbox URL or browser error, inspect `location.href`,
|
|
32
|
+
`document.baseURI` and the resolved anchor URL. Report a host loading defect;
|
|
33
|
+
do not add scenario `preventDefault` handlers merely to hide it. Explicit App
|
|
34
|
+
bases retain their declared behavior and CSP requirements; external hosts own
|
|
35
|
+
their document-loading policy. Verify link activation as well as rendering.
|
|
36
|
+
|
|
26
37
|
## Owner-local token previews load their own definitions
|
|
27
38
|
|
|
28
39
|
Keep the registered token sheet imported by its runtime owner for product use.
|
|
@@ -90,6 +101,40 @@ do not export the helper solely for a test. Public/private ownership is a produc
|
|
|
90
101
|
decision, not a coverage workaround. Browser checks verify transitions but do not
|
|
91
102
|
replace the current static `covers` requirement; `exercises` does not waive it.
|
|
92
103
|
|
|
104
|
+
## Native semantics through a public runtime slot
|
|
105
|
+
|
|
106
|
+
A native element can be the direct child of a public runtime component that
|
|
107
|
+
actually clones that child with its own props:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Action asChild>
|
|
111
|
+
<a href={fixture.destination}>Documentation</a>
|
|
112
|
+
</Action>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`Action` and the fixture are illustrative; use the project's intended public API.
|
|
116
|
+
The runtime owner supplies presentation and interaction; the anchor supplies link
|
|
117
|
+
semantics. Keep this composition when it is the product contract. Do not replace
|
|
118
|
+
the anchor with an unrelated styled link, add a demo-only prop, disable the guard
|
|
119
|
+
or write outside MCP merely to silence a diagnostic.
|
|
120
|
+
|
|
121
|
+
ADS follows the selected runtime render path, the exact child and real imported
|
|
122
|
+
React/Preact `cloneElement` operations, including local slot/prop-merging helpers.
|
|
123
|
+
The prop need not be named `asChild`; the spelling alone grants no permission.
|
|
124
|
+
JSX and recognized framework factories follow the same rule. The native element
|
|
125
|
+
must be the single direct child: another native control nested inside it remains
|
|
126
|
+
subject to the ordinary ownership rule. Passing children through a container,
|
|
127
|
+
a scenario-local wrapper or an opaque component does not establish a slot.
|
|
128
|
+
|
|
129
|
+
This grants no scenario styling permission. Inline styles and arbitrary class
|
|
130
|
+
names remain rejected, including on the slotted child. Public style helpers retain
|
|
131
|
+
their own provenance checks. Unknown branches that could render the native child
|
|
132
|
+
directly, multiple children and untraceable replacement props remain blocked.
|
|
133
|
+
If a valid slot contract cannot be traced, keep the intended API and report a
|
|
134
|
+
small reproduction rather than inventing a product workaround. Static proof
|
|
135
|
+
establishes ownership, not correct prop merging, focus, keyboard or navigation
|
|
136
|
+
behavior; verify those in the built App and registered checks.
|
|
137
|
+
|
|
93
138
|
## Scenarios may consume verified public style helpers
|
|
94
139
|
|
|
95
140
|
A deliberately public helper can expose its owner's Linaria treatment:
|
|
@@ -52,8 +52,8 @@ For on-demand current/candidate screenshots and visual dry-run review, read
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
For parent/child `covers`, conditional-control review, reference comparisons,
|
|
55
|
-
public style-helper use
|
|
56
|
-
findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
55
|
+
public style-helper use, fragment-link navigation, or `scenario-render` /
|
|
56
|
+
`showcase-class` findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
57
57
|
examples explain API visibility, reference baselines and state-transition checks.
|
|
58
58
|
Traced parents can cover declared public children; verified public Linaria
|
|
59
59
|
helpers do not grant custom scenario CSS.
|
|
@@ -107,6 +107,17 @@ Keep contextual public parts public when they are intended consumer API. Demonst
|
|
|
107
107
|
them through their actual public composition/customization path and list their real
|
|
108
108
|
render references in covers. Do not count internal production renders as public API
|
|
109
109
|
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
110
|
-
Scenario controls still use public UI
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
Scenario controls still use public UI. A native link/button can supply semantics
|
|
111
|
+
as the single direct child of a public runtime slot when source tracing proves
|
|
112
|
+
that owner clones the child with its props. An `asChild` flag alone is insufficient;
|
|
113
|
+
standalone native controls and custom scenario styling remain rejected. See
|
|
114
|
+
[scenarios.md](scenarios.md) for evidence and limits. Preserve the intended
|
|
115
|
+
composition instead of substituting an unrelated styled control or adding a
|
|
116
|
+
demo-only component prop. Review framing belongs in public layout patterns.
|
|
117
|
+
|
|
118
|
+
A complete runner report containing an ordinary failed assertion preserves each
|
|
119
|
+
passing check as `passed`; the failed check remains `failed`, and overall
|
|
120
|
+
verification still rejects the mutation. Fix the actual failing checks instead of
|
|
121
|
+
assuming every affected owner failed. Suite errors, unexplained runner exits,
|
|
122
|
+
missing results and interrupted runs cannot certify passing guarantees. Use the
|
|
123
|
+
case's `reportedStatus`, message and report to distinguish these conditions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Scenario rendering, token previews and public class helpers
|
|
2
2
|
|
|
3
|
-
Use this reference for `scenario-render`, `scenario-coverage` or `showcase-class`
|
|
3
|
+
Use this reference for `scenario-render`, `scenario-coverage`, `showcase-control` or `showcase-class`
|
|
4
4
|
diagnostics. MCP serves the same guide as `ads://guides/scenarios`.
|
|
5
5
|
|
|
6
6
|
All preview kinds open at `?scenario=<discovered-id>`. Use the returned showcase
|
|
@@ -23,6 +23,17 @@ on-demand element screenshots. It grants no render/behavior coverage and no extr
|
|
|
23
23
|
styling permission. Use [captures.md](captures.md) for current/candidate review,
|
|
24
24
|
target selection, resource reads and storage lifecycle.
|
|
25
25
|
|
|
26
|
+
## Fragment links inside Apps
|
|
27
|
+
|
|
28
|
+
Keep intended `href="#"` and named fragments in the project API and fixtures.
|
|
29
|
+
ADS's inline-document loader supplies an `about:srcdoc` base when the App has no
|
|
30
|
+
explicit base, preserving native scrolling, events and state. If a fragment
|
|
31
|
+
replaces the App with a sandbox URL or browser error, inspect `location.href`,
|
|
32
|
+
`document.baseURI` and the resolved anchor URL. Report a host loading defect;
|
|
33
|
+
do not add scenario `preventDefault` handlers merely to hide it. Explicit App
|
|
34
|
+
bases retain their declared behavior and CSP requirements; external hosts own
|
|
35
|
+
their document-loading policy. Verify link activation as well as rendering.
|
|
36
|
+
|
|
26
37
|
## Owner-local token previews load their own definitions
|
|
27
38
|
|
|
28
39
|
Keep the registered token sheet imported by its runtime owner for product use.
|
|
@@ -90,6 +101,40 @@ do not export the helper solely for a test. Public/private ownership is a produc
|
|
|
90
101
|
decision, not a coverage workaround. Browser checks verify transitions but do not
|
|
91
102
|
replace the current static `covers` requirement; `exercises` does not waive it.
|
|
92
103
|
|
|
104
|
+
## Native semantics through a public runtime slot
|
|
105
|
+
|
|
106
|
+
A native element can be the direct child of a public runtime component that
|
|
107
|
+
actually clones that child with its own props:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
<Action asChild>
|
|
111
|
+
<a href={fixture.destination}>Documentation</a>
|
|
112
|
+
</Action>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`Action` and the fixture are illustrative; use the project's intended public API.
|
|
116
|
+
The runtime owner supplies presentation and interaction; the anchor supplies link
|
|
117
|
+
semantics. Keep this composition when it is the product contract. Do not replace
|
|
118
|
+
the anchor with an unrelated styled link, add a demo-only prop, disable the guard
|
|
119
|
+
or write outside MCP merely to silence a diagnostic.
|
|
120
|
+
|
|
121
|
+
ADS follows the selected runtime render path, the exact child and real imported
|
|
122
|
+
React/Preact `cloneElement` operations, including local slot/prop-merging helpers.
|
|
123
|
+
The prop need not be named `asChild`; the spelling alone grants no permission.
|
|
124
|
+
JSX and recognized framework factories follow the same rule. The native element
|
|
125
|
+
must be the single direct child: another native control nested inside it remains
|
|
126
|
+
subject to the ordinary ownership rule. Passing children through a container,
|
|
127
|
+
a scenario-local wrapper or an opaque component does not establish a slot.
|
|
128
|
+
|
|
129
|
+
This grants no scenario styling permission. Inline styles and arbitrary class
|
|
130
|
+
names remain rejected, including on the slotted child. Public style helpers retain
|
|
131
|
+
their own provenance checks. Unknown branches that could render the native child
|
|
132
|
+
directly, multiple children and untraceable replacement props remain blocked.
|
|
133
|
+
If a valid slot contract cannot be traced, keep the intended API and report a
|
|
134
|
+
small reproduction rather than inventing a product workaround. Static proof
|
|
135
|
+
establishes ownership, not correct prop merging, focus, keyboard or navigation
|
|
136
|
+
behavior; verify those in the built App and registered checks.
|
|
137
|
+
|
|
93
138
|
## Scenarios may consume verified public style helpers
|
|
94
139
|
|
|
95
140
|
A deliberately public helper can expose its owner's Linaria treatment:
|
|
@@ -72,8 +72,8 @@ For on-demand current/candidate screenshots and visual dry-run review, read
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
For parent/child `covers`, conditional-control review, reference comparisons,
|
|
75
|
-
public style-helper use
|
|
76
|
-
findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
75
|
+
public style-helper use, fragment-link navigation, or `scenario-render` /
|
|
76
|
+
`showcase-class` findings, read [scenario contracts](references/scenarios.md). Its verification
|
|
77
77
|
examples explain API visibility, reference baselines and state-transition checks.
|
|
78
78
|
Traced parents can cover declared public children; verified public Linaria
|
|
79
79
|
helpers do not grant custom scenario CSS.
|
|
@@ -107,6 +107,17 @@ Keep contextual public parts public when they are intended consumer API. Demonst
|
|
|
107
107
|
them through their actual public composition/customization path and list their real
|
|
108
108
|
render references in covers. Do not count internal production renders as public API
|
|
109
109
|
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
110
|
-
Scenario controls still use public UI
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
Scenario controls still use public UI. A native link/button can supply semantics
|
|
111
|
+
as the single direct child of a public runtime slot when source tracing proves
|
|
112
|
+
that owner clones the child with its props. An `asChild` flag alone is insufficient;
|
|
113
|
+
standalone native controls and custom scenario styling remain rejected. See
|
|
114
|
+
[scenarios.md](scenarios.md) for evidence and limits. Preserve the intended
|
|
115
|
+
composition instead of substituting an unrelated styled control or adding a
|
|
116
|
+
demo-only component prop. Review framing belongs in public layout patterns.
|
|
117
|
+
|
|
118
|
+
A complete runner report containing an ordinary failed assertion preserves each
|
|
119
|
+
passing check as `passed`; the failed check remains `failed`, and overall
|
|
120
|
+
verification still rejects the mutation. Fix the actual failing checks instead of
|
|
121
|
+
assuming every affected owner failed. Suite errors, unexplained runner exits,
|
|
122
|
+
missing results and interrupted runs cannot certify passing guarantees. Use the
|
|
123
|
+
case's `reportedStatus`, message and report to distinguish these conditions.
|