@reqvire-org/ads 0.3.5 → 0.3.6
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/README.md +5 -1
- package/dist/bootstrap-ds/ADS.md +9 -3
- package/dist/bootstrap-ds/README.md +10 -0
- package/dist/boundaries.mjs +3 -0
- package/dist/check.mjs +13 -0
- package/dist/config.mjs +6 -2
- package/dist/mcp/build-status.mjs +7 -4
- package/dist/mcp/context.mjs +2 -2
- package/dist/mcp/edit-preparation.mjs +111 -0
- package/dist/mcp/mutations.mjs +54 -38
- package/dist/mcp/preview-watch.mjs +10 -4
- package/dist/mcp/server.mjs +32 -22
- package/dist/mcp/text-diff.mjs +19 -0
- package/dist/preview-resources.mjs +45 -8
- package/dist/preview-scope.mjs +30 -0
- package/dist/scenarios-compiler.mjs +24 -17
- package/dist/scenarios.mjs +46 -4
- package/dist/scoped-tokens.mjs +57 -0
- package/dist/skills/ads-break-ui/SKILL.md +4 -2
- package/dist/skills/ads-break-ui/references/guarded-editing.md +44 -0
- package/dist/skills/ads-break-ui/references/verification.md +6 -0
- package/dist/skills/ads-designer/SKILL.md +4 -2
- package/dist/skills/ads-designer/assets/bootstrap-ds/ADS.md +9 -3
- package/dist/skills/ads-designer/assets/bootstrap-ds/README.md +10 -0
- package/dist/skills/ads-designer/references/guarded-editing.md +44 -0
- package/dist/skills/ads-import/SKILL.md +4 -2
- package/dist/skills/ads-import/references/guarded-editing.md +44 -0
- package/dist/skills/ads-import/references/tokens.md +4 -2
- package/dist/skills/ads-migrate/SKILL.md +4 -2
- package/dist/skills/ads-migrate/references/guarded-editing.md +44 -0
- package/dist/skills/ads-motion/SKILL.md +4 -2
- package/dist/skills/ads-motion/references/guarded-editing.md +44 -0
- package/dist/token-fixtures.mjs +30 -0
- package/dist/tokens.mjs +8 -2
- package/dist/units.mjs +15 -0
- package/dist/verification.mjs +1 -1
- package/docs/ADS.md +45 -2
- package/docs/ARCHITECTURE.md +21 -0
- package/docs/BEHAVIORS.md +11 -0
- package/docs/CHANGELOG.md +20 -0
- package/docs/GUIDE.md +8 -3
- package/docs/MCP.md +60 -5
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Advanced guarded editing
|
|
2
|
+
|
|
3
|
+
Use `ads_apply_patch` for independent owner edits. `ads_prepare_patch` can create a
|
|
4
|
+
local draft of one owner and its companions; edit that directory with local file
|
|
5
|
+
tools, request `action:"diff"`, then apply the returned patchFile. Discard the
|
|
6
|
+
draft afterward. Remote clients can keep sending inline Git diffs. Neither draft
|
|
7
|
+
preparation nor diff generation validates or changes live source.
|
|
8
|
+
|
|
9
|
+
For genuinely coupled changes, `ads_apply_transaction` accepts 2–8 distinct owner
|
|
10
|
+
patches (32 distinct files and 16 MiB combined). Each patch keeps its ownership and
|
|
11
|
+
companion restrictions. Patches apply in order; later shared-entry hunks match the
|
|
12
|
+
earlier candidate. All guards, registered checks and affected behavior checks run
|
|
13
|
+
on the final candidate before live source is written. Dry-run first. Rejection,
|
|
14
|
+
conflict and cancellation publish nothing. Dependency installation remains local;
|
|
15
|
+
the candidate uses installed node_modules. Never bypass a rejected gate directly.
|
|
16
|
+
|
|
17
|
+
A component/pattern can own constants without expanding the shared vocabulary:
|
|
18
|
+
colocate `tokens.json` with `{ "schemaVersion":1, "namespace":"--<owner>-" }`
|
|
19
|
+
and a definition-only `tokens.css`, imported by its runtime source. Flat owners use
|
|
20
|
+
`<Owner>.tokens.json`/`<Owner>.tokens.css`. Namespaces are unique and cannot overlap
|
|
21
|
+
shared or --ds-/--ux-/--showcase- variables. Only that owner consumes/defines its
|
|
22
|
+
local tokens; aliases can use shared or own tokens. UI styles stay in Linaria.
|
|
23
|
+
Add a colocated token scenario with `kind:"tokens"`, real fixture `samples` and a
|
|
24
|
+
public review pattern. These inputs belong to the same owner and need real sample
|
|
25
|
+
coverage. Manifests and fixtures stay out of the product bundle.
|
|
26
|
+
|
|
27
|
+
`ads_prepare_token_samples({id, bindings?})` preserves existing project samples,
|
|
28
|
+
removes undeclared names and returns an owner patchFile. Supply explicit
|
|
29
|
+
`{token,property,probe}` bindings for new samples; unresolved tokens stay reported.
|
|
30
|
+
ADS does not infer visual meaning or fabricate renderers. Apply through the guard,
|
|
31
|
+
then inspect the actual App sample effects.
|
|
32
|
+
|
|
33
|
+
An empty .gitkeep can be deleted alongside new source beneath it in the selected
|
|
34
|
+
owner. Nonempty markers and other hidden files stay protected. A redundant
|
|
35
|
+
Scenario.tsx can be deleted when real coverage remains elsewhere; removing a
|
|
36
|
+
scenario does not erase ownership of the unit's runtime source.
|
|
37
|
+
|
|
38
|
+
Keep contextual public parts public when they are intended consumer API. Demonstrate
|
|
39
|
+
them through their actual public composition/customization path and list their real
|
|
40
|
+
render references in covers. Do not count internal production renders as public API
|
|
41
|
+
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
42
|
+
Scenario controls still use public UI; native link/button markup belongs in an
|
|
43
|
+
owned public primitive/pattern or an owner-local test, including polymorphic/slot
|
|
44
|
+
adaptation. Do not add demo-only component props or global styles for review glue.
|
|
@@ -26,6 +26,12 @@ The showcase keeps a notification stream open. Wait for document loading and the
|
|
|
26
26
|
selected App's ready/error state; `networkidle` is not a readiness condition.
|
|
27
27
|
For tall previews, scroll the App document to its last example and verify it is
|
|
28
28
|
reachable without the host shell scrolling or clipping the preview.
|
|
29
|
+
Compare references under equivalent framing. With `content-visibility`, App
|
|
30
|
+
readiness can precede off-screen layout: bring measured content into view and
|
|
31
|
+
wait for observable geometry to settle. Record initial placeholder behavior
|
|
32
|
+
separately when relevant; a framed/top-level difference alone does not identify
|
|
33
|
+
an ADS defect. Wait for actual focus/positioning readiness for keyboard checks;
|
|
34
|
+
exercise rapid input as a separate case instead of adding arbitrary delays.
|
|
29
35
|
Capture the fixture, viewport/container size, theme, zoom, and actions alongside
|
|
30
36
|
each failure. CSS viewport emulation is useful; it is not evidence of real
|
|
31
37
|
mobile keyboard, browser chrome, or assistive-technology behavior.
|
|
@@ -68,8 +68,8 @@ and `boundaries.styleWrites` entries together with its source. Unused permission
|
|
|
68
68
|
fail the core checks; do not pre-register a boundary without its implementation.
|
|
69
69
|
Use `dryRun: true` to
|
|
70
70
|
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
71
|
-
owner.
|
|
72
|
-
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
71
|
+
owner. Use `ads_apply_transaction` for genuinely coupled owner patches;
|
|
72
|
+
never bypass a rejection with direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
73
73
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
74
74
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
75
75
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -77,6 +77,8 @@ ADS gates. For binary/large assets, generate `git diff --binary --full-index` in
|
|
|
77
77
|
`.ds/patches/<name>.patch` and send `patchFile` instead of inline `patch`, so bytes
|
|
78
78
|
stay out of model context. Binary changes require Git. When editing is disabled,
|
|
79
79
|
use the client's normal source-editing tools.
|
|
80
|
+
For owner drafts, token-sample reconciliation, coupled transactions and local
|
|
81
|
+
constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
|
|
80
82
|
|
|
81
83
|
Controllers are UI behavior owners: private helpers stay with their component or
|
|
82
84
|
pattern; reusable controllers use discovered `controllers/<Name>` units. Use the
|
|
@@ -36,8 +36,14 @@ Projects sharing this ADS use the same token names, meanings, and value types;
|
|
|
36
36
|
their concrete values and theme overrides can differ. Reuse existing local values
|
|
37
37
|
when importing components/patterns, add missing shared definitions, and import
|
|
38
38
|
source token values only when adopting that theme is requested.
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
Shared token names and prefixes follow the ADS contract. A component/pattern may
|
|
40
|
+
register one unique local namespace in colocated `tokens.json` and define it in
|
|
41
|
+
`tokens.css`, imported by its runtime. Flat owners use `<Owner>.tokens.json` and
|
|
42
|
+
`<Owner>.tokens.css`. These definition-only sheets contain root/theme custom
|
|
43
|
+
properties, not UI selectors or ordinary styles. Other owners consume shared
|
|
44
|
+
tokens; they cannot override or consume a peer's local namespace. A colocated
|
|
45
|
+
`kind:"tokens"` scenario needs real samples for every local token. Shared
|
|
46
|
+
assignments remain in the shared token files. Components own
|
|
41
47
|
`--ds-*`, patterns `--ux-*`, and the showcase `--showcase-*`; token files cannot
|
|
42
48
|
assign those local variables or override component state.
|
|
43
49
|
|
|
@@ -183,7 +189,7 @@ mounting, correct props, every branch/state or visual parity. The older
|
|
|
183
189
|
|
|
184
190
|
`token-scenario-reference` rejects undeclared token names in metadata and reachable
|
|
185
191
|
inputs. `token-scenario-render` rejects claimed tokens with no reachable input
|
|
186
|
-
reference; `token-scenario-coverage` requires every discovered
|
|
192
|
+
reference; `token-scenario-coverage` requires every discovered shared or owner-local token
|
|
187
193
|
to have coverage. A new or removed token therefore needs a scenario/fixture
|
|
188
194
|
update. All three are errors in `ads check`, run by `lint:ds` and the build.
|
|
189
195
|
Coverage is static reachability, not proof that every branch actually renders
|
|
@@ -62,6 +62,10 @@ the public `TokenPreview` pattern owns their presentation and applies the real C
|
|
|
62
62
|
variables. Add/remove samples alongside token definitions. `ads check` rejects
|
|
63
63
|
missing coverage and invented names; the App verifies the declared CSS bindings
|
|
64
64
|
in the browser. Extend or replace the project-owned pattern as your tokens evolve.
|
|
65
|
+
`ads_prepare_token_samples` can prepare a fixture patch from explicit project
|
|
66
|
+
property/probe bindings. It preserves existing samples and reports unmapped tokens;
|
|
67
|
+
it does not guess how a new value should look. Component/pattern constants can use
|
|
68
|
+
the colocated namespace contract in [ADS.md](ADS.md), with their own token scenario.
|
|
65
69
|
|
|
66
70
|
Create a component under `design-system/components/`, export it through `@ds`,
|
|
67
71
|
and colocate `Scenario.tsx` plus `fixture.ts` (or `<Owner>.scenario.tsx` and
|
|
@@ -79,6 +83,8 @@ stale retained output. Switching or rebuilding a scenario unmounts its previous
|
|
|
79
83
|
state. `showcase/mcp/main.tsx` exports `mountScenario(Scenario, container)` and
|
|
80
84
|
returns an unmount callback; it is not the shell. Keep the saved `framework`,
|
|
81
85
|
compiler and mount adapter consistent.
|
|
86
|
+
Managed sessions own their graph output; standalone prebuilds cannot replace it.
|
|
87
|
+
Verified generated graph snapshots preserve warm-start reuse across sessions.
|
|
82
88
|
|
|
83
89
|
The application and previews use the same foundation CSS and Linaria pipeline.
|
|
84
90
|
The source barrel loads the foundation once. The private `build:lib` script uses
|
|
@@ -98,3 +104,7 @@ from a user-selected external repository, preserving revisions and licenses.
|
|
|
98
104
|
inspection builds it automatically, then loads selected entries. Browser review
|
|
99
105
|
still checks layout, accessibility, keyboard/focus, states, themes and motion. A clean
|
|
100
106
|
build or delivered HTML alone does not establish those behaviors.
|
|
107
|
+
Opt-in MCP editing uses owner Git patches. `ads_prepare_patch` creates a temporary
|
|
108
|
+
owner draft/diff; `ads_apply_transaction` validates bounded coupled owner patches
|
|
109
|
+
against one final candidate. Preparation changes no live source. Keep all guards
|
|
110
|
+
and review the rendered result after applying.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Advanced guarded editing
|
|
2
|
+
|
|
3
|
+
Use `ads_apply_patch` for independent owner edits. `ads_prepare_patch` can create a
|
|
4
|
+
local draft of one owner and its companions; edit that directory with local file
|
|
5
|
+
tools, request `action:"diff"`, then apply the returned patchFile. Discard the
|
|
6
|
+
draft afterward. Remote clients can keep sending inline Git diffs. Neither draft
|
|
7
|
+
preparation nor diff generation validates or changes live source.
|
|
8
|
+
|
|
9
|
+
For genuinely coupled changes, `ads_apply_transaction` accepts 2–8 distinct owner
|
|
10
|
+
patches (32 distinct files and 16 MiB combined). Each patch keeps its ownership and
|
|
11
|
+
companion restrictions. Patches apply in order; later shared-entry hunks match the
|
|
12
|
+
earlier candidate. All guards, registered checks and affected behavior checks run
|
|
13
|
+
on the final candidate before live source is written. Dry-run first. Rejection,
|
|
14
|
+
conflict and cancellation publish nothing. Dependency installation remains local;
|
|
15
|
+
the candidate uses installed node_modules. Never bypass a rejected gate directly.
|
|
16
|
+
|
|
17
|
+
A component/pattern can own constants without expanding the shared vocabulary:
|
|
18
|
+
colocate `tokens.json` with `{ "schemaVersion":1, "namespace":"--<owner>-" }`
|
|
19
|
+
and a definition-only `tokens.css`, imported by its runtime source. Flat owners use
|
|
20
|
+
`<Owner>.tokens.json`/`<Owner>.tokens.css`. Namespaces are unique and cannot overlap
|
|
21
|
+
shared or --ds-/--ux-/--showcase- variables. Only that owner consumes/defines its
|
|
22
|
+
local tokens; aliases can use shared or own tokens. UI styles stay in Linaria.
|
|
23
|
+
Add a colocated token scenario with `kind:"tokens"`, real fixture `samples` and a
|
|
24
|
+
public review pattern. These inputs belong to the same owner and need real sample
|
|
25
|
+
coverage. Manifests and fixtures stay out of the product bundle.
|
|
26
|
+
|
|
27
|
+
`ads_prepare_token_samples({id, bindings?})` preserves existing project samples,
|
|
28
|
+
removes undeclared names and returns an owner patchFile. Supply explicit
|
|
29
|
+
`{token,property,probe}` bindings for new samples; unresolved tokens stay reported.
|
|
30
|
+
ADS does not infer visual meaning or fabricate renderers. Apply through the guard,
|
|
31
|
+
then inspect the actual App sample effects.
|
|
32
|
+
|
|
33
|
+
An empty .gitkeep can be deleted alongside new source beneath it in the selected
|
|
34
|
+
owner. Nonempty markers and other hidden files stay protected. A redundant
|
|
35
|
+
Scenario.tsx can be deleted when real coverage remains elsewhere; removing a
|
|
36
|
+
scenario does not erase ownership of the unit's runtime source.
|
|
37
|
+
|
|
38
|
+
Keep contextual public parts public when they are intended consumer API. Demonstrate
|
|
39
|
+
them through their actual public composition/customization path and list their real
|
|
40
|
+
render references in covers. Do not count internal production renders as public API
|
|
41
|
+
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
42
|
+
Scenario controls still use public UI; native link/button markup belongs in an
|
|
43
|
+
owned public primitive/pattern or an owner-local test, including polymorphic/slot
|
|
44
|
+
adaptation. Do not add demo-only component props or global styles for review glue.
|
|
@@ -32,8 +32,8 @@ and `boundaries.styleWrites` entries together with its source. Unused permission
|
|
|
32
32
|
fail the core checks; do not pre-register a boundary without its implementation.
|
|
33
33
|
Use `dryRun: true` to
|
|
34
34
|
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
35
|
-
owner.
|
|
36
|
-
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
35
|
+
owner. Use `ads_apply_transaction` for genuinely coupled owner patches;
|
|
36
|
+
never bypass a rejection with direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
37
37
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
38
38
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
39
39
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -41,6 +41,8 @@ ADS gates. For binary/large assets, generate `git diff --binary --full-index` in
|
|
|
41
41
|
`.ds/patches/<name>.patch` and send `patchFile` instead of inline `patch`, so bytes
|
|
42
42
|
stay out of model context. Binary changes require Git. When editing is disabled,
|
|
43
43
|
use the client's normal source-editing tools.
|
|
44
|
+
For owner drafts, token-sample reconciliation, coupled transactions and local
|
|
45
|
+
constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
|
|
44
46
|
|
|
45
47
|
Controllers are UI behavior owners: private helpers stay with their component or
|
|
46
48
|
pattern; reusable controllers use discovered `controllers/<Name>` units. Use the
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Advanced guarded editing
|
|
2
|
+
|
|
3
|
+
Use `ads_apply_patch` for independent owner edits. `ads_prepare_patch` can create a
|
|
4
|
+
local draft of one owner and its companions; edit that directory with local file
|
|
5
|
+
tools, request `action:"diff"`, then apply the returned patchFile. Discard the
|
|
6
|
+
draft afterward. Remote clients can keep sending inline Git diffs. Neither draft
|
|
7
|
+
preparation nor diff generation validates or changes live source.
|
|
8
|
+
|
|
9
|
+
For genuinely coupled changes, `ads_apply_transaction` accepts 2–8 distinct owner
|
|
10
|
+
patches (32 distinct files and 16 MiB combined). Each patch keeps its ownership and
|
|
11
|
+
companion restrictions. Patches apply in order; later shared-entry hunks match the
|
|
12
|
+
earlier candidate. All guards, registered checks and affected behavior checks run
|
|
13
|
+
on the final candidate before live source is written. Dry-run first. Rejection,
|
|
14
|
+
conflict and cancellation publish nothing. Dependency installation remains local;
|
|
15
|
+
the candidate uses installed node_modules. Never bypass a rejected gate directly.
|
|
16
|
+
|
|
17
|
+
A component/pattern can own constants without expanding the shared vocabulary:
|
|
18
|
+
colocate `tokens.json` with `{ "schemaVersion":1, "namespace":"--<owner>-" }`
|
|
19
|
+
and a definition-only `tokens.css`, imported by its runtime source. Flat owners use
|
|
20
|
+
`<Owner>.tokens.json`/`<Owner>.tokens.css`. Namespaces are unique and cannot overlap
|
|
21
|
+
shared or --ds-/--ux-/--showcase- variables. Only that owner consumes/defines its
|
|
22
|
+
local tokens; aliases can use shared or own tokens. UI styles stay in Linaria.
|
|
23
|
+
Add a colocated token scenario with `kind:"tokens"`, real fixture `samples` and a
|
|
24
|
+
public review pattern. These inputs belong to the same owner and need real sample
|
|
25
|
+
coverage. Manifests and fixtures stay out of the product bundle.
|
|
26
|
+
|
|
27
|
+
`ads_prepare_token_samples({id, bindings?})` preserves existing project samples,
|
|
28
|
+
removes undeclared names and returns an owner patchFile. Supply explicit
|
|
29
|
+
`{token,property,probe}` bindings for new samples; unresolved tokens stay reported.
|
|
30
|
+
ADS does not infer visual meaning or fabricate renderers. Apply through the guard,
|
|
31
|
+
then inspect the actual App sample effects.
|
|
32
|
+
|
|
33
|
+
An empty .gitkeep can be deleted alongside new source beneath it in the selected
|
|
34
|
+
owner. Nonempty markers and other hidden files stay protected. A redundant
|
|
35
|
+
Scenario.tsx can be deleted when real coverage remains elsewhere; removing a
|
|
36
|
+
scenario does not erase ownership of the unit's runtime source.
|
|
37
|
+
|
|
38
|
+
Keep contextual public parts public when they are intended consumer API. Demonstrate
|
|
39
|
+
them through their actual public composition/customization path and list their real
|
|
40
|
+
render references in covers. Do not count internal production renders as public API
|
|
41
|
+
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
42
|
+
Scenario controls still use public UI; native link/button markup belongs in an
|
|
43
|
+
owned public primitive/pattern or an owner-local test, including polymorphic/slot
|
|
44
|
+
adaptation. Do not add demo-only component props or global styles for review glue.
|
|
@@ -47,9 +47,11 @@ overwriting destination theme behavior during an item import.
|
|
|
47
47
|
|
|
48
48
|
## Explicit `tokens` mode imports values
|
|
49
49
|
|
|
50
|
-
ADS token names and prefixes
|
|
50
|
+
Shared ADS token names and prefixes retain their semantics. Owner-local constants
|
|
51
|
+
may use the registered namespace contract described in [guarded-editing.md](guarded-editing.md);
|
|
52
|
+
they do not create a second shared branding vocabulary. New shared definitions follow the existing
|
|
51
53
|
architecture; components use `--ds-*`, patterns `--ux-*`, and owned scenario review layouts
|
|
52
|
-
`--ux-*` (`--showcase-*` is reserved, not permission for fixture CSS).
|
|
54
|
+
`--ux-*` (`--showcase-*` is reserved, not permission for fixture CSS). Keep shared names canonical; owner-local namespaces remain separate, explicit contracts.
|
|
53
55
|
Normalize nonconforming source references to canonical ADS names during import,
|
|
54
56
|
preserving destination values unless this mode explicitly requests changes.
|
|
55
57
|
|
|
@@ -33,8 +33,8 @@ and `boundaries.styleWrites` entries together with its source. Unused permission
|
|
|
33
33
|
fail the core checks; do not pre-register a boundary without its implementation.
|
|
34
34
|
Use `dryRun: true` to
|
|
35
35
|
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
36
|
-
owner.
|
|
37
|
-
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
36
|
+
owner. Use `ads_apply_transaction` for genuinely coupled owner patches;
|
|
37
|
+
never bypass a rejection with direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
38
38
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
39
39
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
40
40
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -42,6 +42,8 @@ ADS gates. For binary/large assets, generate `git diff --binary --full-index` in
|
|
|
42
42
|
`.ds/patches/<name>.patch` and send `patchFile` instead of inline `patch`, so bytes
|
|
43
43
|
stay out of model context. Binary changes require Git. When editing is disabled,
|
|
44
44
|
use the client's normal source-editing tools.
|
|
45
|
+
For owner drafts, token-sample reconciliation, coupled transactions and local
|
|
46
|
+
constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
Controllers are UI behavior owners: private helpers stay with their component or
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Advanced guarded editing
|
|
2
|
+
|
|
3
|
+
Use `ads_apply_patch` for independent owner edits. `ads_prepare_patch` can create a
|
|
4
|
+
local draft of one owner and its companions; edit that directory with local file
|
|
5
|
+
tools, request `action:"diff"`, then apply the returned patchFile. Discard the
|
|
6
|
+
draft afterward. Remote clients can keep sending inline Git diffs. Neither draft
|
|
7
|
+
preparation nor diff generation validates or changes live source.
|
|
8
|
+
|
|
9
|
+
For genuinely coupled changes, `ads_apply_transaction` accepts 2–8 distinct owner
|
|
10
|
+
patches (32 distinct files and 16 MiB combined). Each patch keeps its ownership and
|
|
11
|
+
companion restrictions. Patches apply in order; later shared-entry hunks match the
|
|
12
|
+
earlier candidate. All guards, registered checks and affected behavior checks run
|
|
13
|
+
on the final candidate before live source is written. Dry-run first. Rejection,
|
|
14
|
+
conflict and cancellation publish nothing. Dependency installation remains local;
|
|
15
|
+
the candidate uses installed node_modules. Never bypass a rejected gate directly.
|
|
16
|
+
|
|
17
|
+
A component/pattern can own constants without expanding the shared vocabulary:
|
|
18
|
+
colocate `tokens.json` with `{ "schemaVersion":1, "namespace":"--<owner>-" }`
|
|
19
|
+
and a definition-only `tokens.css`, imported by its runtime source. Flat owners use
|
|
20
|
+
`<Owner>.tokens.json`/`<Owner>.tokens.css`. Namespaces are unique and cannot overlap
|
|
21
|
+
shared or --ds-/--ux-/--showcase- variables. Only that owner consumes/defines its
|
|
22
|
+
local tokens; aliases can use shared or own tokens. UI styles stay in Linaria.
|
|
23
|
+
Add a colocated token scenario with `kind:"tokens"`, real fixture `samples` and a
|
|
24
|
+
public review pattern. These inputs belong to the same owner and need real sample
|
|
25
|
+
coverage. Manifests and fixtures stay out of the product bundle.
|
|
26
|
+
|
|
27
|
+
`ads_prepare_token_samples({id, bindings?})` preserves existing project samples,
|
|
28
|
+
removes undeclared names and returns an owner patchFile. Supply explicit
|
|
29
|
+
`{token,property,probe}` bindings for new samples; unresolved tokens stay reported.
|
|
30
|
+
ADS does not infer visual meaning or fabricate renderers. Apply through the guard,
|
|
31
|
+
then inspect the actual App sample effects.
|
|
32
|
+
|
|
33
|
+
An empty .gitkeep can be deleted alongside new source beneath it in the selected
|
|
34
|
+
owner. Nonempty markers and other hidden files stay protected. A redundant
|
|
35
|
+
Scenario.tsx can be deleted when real coverage remains elsewhere; removing a
|
|
36
|
+
scenario does not erase ownership of the unit's runtime source.
|
|
37
|
+
|
|
38
|
+
Keep contextual public parts public when they are intended consumer API. Demonstrate
|
|
39
|
+
them through their actual public composition/customization path and list their real
|
|
40
|
+
render references in covers. Do not count internal production renders as public API
|
|
41
|
+
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
42
|
+
Scenario controls still use public UI; native link/button markup belongs in an
|
|
43
|
+
owned public primitive/pattern or an owner-local test, including polymorphic/slot
|
|
44
|
+
adaptation. Do not add demo-only component props or global styles for review glue.
|
|
@@ -53,8 +53,8 @@ and `boundaries.styleWrites` entries together with its source. Unused permission
|
|
|
53
53
|
fail the core checks; do not pre-register a boundary without its implementation.
|
|
54
54
|
Use `dryRun: true` to
|
|
55
55
|
inspect validation; applying re-runs the gates. Fix rejected patches in their
|
|
56
|
-
owner.
|
|
57
|
-
direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
56
|
+
owner. Use `ads_apply_transaction` for genuinely coupled owner patches;
|
|
57
|
+
never bypass a rejection with direct source writes. Shared styles/helpers use `foundation`, root guides use
|
|
58
58
|
`documentation`, and branding/fonts use their discovered `assets/*` unit.
|
|
59
59
|
Intentional configuration, rule exceptions, registered guard code and compiler
|
|
60
60
|
changes use `configuration`; validate the proposed settings and keep mandatory
|
|
@@ -62,6 +62,8 @@ ADS gates. For binary/large assets, generate `git diff --binary --full-index` in
|
|
|
62
62
|
`.ds/patches/<name>.patch` and send `patchFile` instead of inline `patch`, so bytes
|
|
63
63
|
stay out of model context. Binary changes require Git. When editing is disabled,
|
|
64
64
|
use the client's normal source-editing tools.
|
|
65
|
+
For owner drafts, token-sample reconciliation, coupled transactions and local
|
|
66
|
+
constant namespaces, read [guarded-editing.md](references/guarded-editing.md).
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
Controllers are UI behavior owners: private helpers stay with their component or
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Advanced guarded editing
|
|
2
|
+
|
|
3
|
+
Use `ads_apply_patch` for independent owner edits. `ads_prepare_patch` can create a
|
|
4
|
+
local draft of one owner and its companions; edit that directory with local file
|
|
5
|
+
tools, request `action:"diff"`, then apply the returned patchFile. Discard the
|
|
6
|
+
draft afterward. Remote clients can keep sending inline Git diffs. Neither draft
|
|
7
|
+
preparation nor diff generation validates or changes live source.
|
|
8
|
+
|
|
9
|
+
For genuinely coupled changes, `ads_apply_transaction` accepts 2–8 distinct owner
|
|
10
|
+
patches (32 distinct files and 16 MiB combined). Each patch keeps its ownership and
|
|
11
|
+
companion restrictions. Patches apply in order; later shared-entry hunks match the
|
|
12
|
+
earlier candidate. All guards, registered checks and affected behavior checks run
|
|
13
|
+
on the final candidate before live source is written. Dry-run first. Rejection,
|
|
14
|
+
conflict and cancellation publish nothing. Dependency installation remains local;
|
|
15
|
+
the candidate uses installed node_modules. Never bypass a rejected gate directly.
|
|
16
|
+
|
|
17
|
+
A component/pattern can own constants without expanding the shared vocabulary:
|
|
18
|
+
colocate `tokens.json` with `{ "schemaVersion":1, "namespace":"--<owner>-" }`
|
|
19
|
+
and a definition-only `tokens.css`, imported by its runtime source. Flat owners use
|
|
20
|
+
`<Owner>.tokens.json`/`<Owner>.tokens.css`. Namespaces are unique and cannot overlap
|
|
21
|
+
shared or --ds-/--ux-/--showcase- variables. Only that owner consumes/defines its
|
|
22
|
+
local tokens; aliases can use shared or own tokens. UI styles stay in Linaria.
|
|
23
|
+
Add a colocated token scenario with `kind:"tokens"`, real fixture `samples` and a
|
|
24
|
+
public review pattern. These inputs belong to the same owner and need real sample
|
|
25
|
+
coverage. Manifests and fixtures stay out of the product bundle.
|
|
26
|
+
|
|
27
|
+
`ads_prepare_token_samples({id, bindings?})` preserves existing project samples,
|
|
28
|
+
removes undeclared names and returns an owner patchFile. Supply explicit
|
|
29
|
+
`{token,property,probe}` bindings for new samples; unresolved tokens stay reported.
|
|
30
|
+
ADS does not infer visual meaning or fabricate renderers. Apply through the guard,
|
|
31
|
+
then inspect the actual App sample effects.
|
|
32
|
+
|
|
33
|
+
An empty .gitkeep can be deleted alongside new source beneath it in the selected
|
|
34
|
+
owner. Nonempty markers and other hidden files stay protected. A redundant
|
|
35
|
+
Scenario.tsx can be deleted when real coverage remains elsewhere; removing a
|
|
36
|
+
scenario does not erase ownership of the unit's runtime source.
|
|
37
|
+
|
|
38
|
+
Keep contextual public parts public when they are intended consumer API. Demonstrate
|
|
39
|
+
them through their actual public composition/customization path and list their real
|
|
40
|
+
render references in covers. Do not count internal production renders as public API
|
|
41
|
+
coverage. Behavioral APIs use exercises and registered guarantees instead.
|
|
42
|
+
Scenario controls still use public UI; native link/button markup belongs in an
|
|
43
|
+
owned public primitive/pattern or an owner-local test, including polymorphic/slot
|
|
44
|
+
adaptation. Do not add demo-only component props or global styles for review glue.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { inspectTokens } from "./tokens.mjs";
|
|
2
|
+
import { inspectScenarios, tokenSampleSource } from "./scenarios.mjs";
|
|
3
|
+
import { inspectUnits } from "./units.mjs";
|
|
4
|
+
import { validTokenSamples } from "./token-samples.mjs";
|
|
5
|
+
import { textDiff } from "./mcp/text-diff.mjs";
|
|
6
|
+
|
|
7
|
+
/** Preserve project bindings; new meanings always need project-selected inputs. */
|
|
8
|
+
export function reconcileTokenSamples(options, {id, bindings = []}) {
|
|
9
|
+
if (bindings.length && !validTokenSamples(bindings)) throw new Error("Bindings need distinct {token, property, probe} CSS samples.");
|
|
10
|
+
const inventory = inspectTokens(options.root), registry = inspectScenarios(options), units = inspectUnits(options);
|
|
11
|
+
const scenario = registry.scenarios.find(entry => entry.id === id && entry.kind === "tokens");
|
|
12
|
+
if (!scenario) throw new Error("Select an exact token scenario ID from ads_scenarios.");
|
|
13
|
+
const owner = units.owner(units.relative(scenario.file));
|
|
14
|
+
const owned = new Set(inventory.tokens.filter(token => token.owner === owner).map(token => token.name));
|
|
15
|
+
if (bindings.some(sample => !owned.has(sample.token))) throw new Error("New sample bindings must name real tokens from this scenario's owner.");
|
|
16
|
+
const removed = scenario.samples.filter(sample => !owned.has(sample.token)).map(sample => sample.token);
|
|
17
|
+
const samples = new Map(scenario.samples.filter(sample => owned.has(sample.token)).map(sample => [`${sample.token}:${sample.property}`, sample]));
|
|
18
|
+
for (const sample of bindings) samples.set(`${sample.token}:${sample.property}`, sample);
|
|
19
|
+
if (!samples.size) throw new Error("A token scenario needs at least one real sample; supply a binding or remove the obsolete scenario with an owner patch.");
|
|
20
|
+
const represented = new Set(registry.scenarios.filter(entry => entry.kind === "tokens" && entry.id !== id).flatMap(entry => entry.samples.map(sample => sample.token)));
|
|
21
|
+
for (const sample of samples.values()) represented.add(sample.token);
|
|
22
|
+
const unresolved = [...owned].filter(name => !represented.has(name));
|
|
23
|
+
const source = tokenSampleSource(options,scenario);
|
|
24
|
+
const list = [...samples.values()];
|
|
25
|
+
const current = scenario.samples;
|
|
26
|
+
const next = JSON.stringify(current) === JSON.stringify(list) ? source.content : source.content.slice(0,source.start) + JSON.stringify(list,null,2) + source.content.slice(source.end);
|
|
27
|
+
return {unit:owner,id,file:source.file,sampleCount:list.length,removed,unresolved,
|
|
28
|
+
patch:textDiff(source.file,source.content,next),
|
|
29
|
+
guidance:"Bindings and probes belong to the project. No token-name/type heuristic chooses a renderer or probe. Apply the proposed owner patch through ads_apply_patch, then verify its real preview."};
|
|
30
|
+
}
|
package/dist/tokens.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { loadConfig, sourceFiles } from "./config.mjs";
|
|
|
6
6
|
import { foundationFiles, isSharedToken, tokenContract } from "./token-policy.mjs";
|
|
7
7
|
import { dimensionValue, numericCssUnit } from "./css-values.mjs";
|
|
8
8
|
import { checkComponentVariable } from "./boundaries.mjs";
|
|
9
|
+
import { scopedTokens, scopedTokenOwner } from "./scoped-tokens.mjs";
|
|
9
10
|
|
|
10
11
|
export { tokenContract };
|
|
11
12
|
|
|
@@ -49,7 +50,10 @@ export function inspectTokens(directory) {
|
|
|
49
50
|
const { root, dsRoot, config } = options;
|
|
50
51
|
const definitions = new Map();
|
|
51
52
|
const diagnostics = [];
|
|
53
|
+
const scoped = scopedTokens(options);
|
|
54
|
+
diagnostics.push(...scoped.diagnostics);
|
|
52
55
|
const files = sourceFiles(path.join(dsRoot, config.tokenDir)).filter((file) => file.endsWith(".css"));
|
|
56
|
+
files.push(...scoped.definitions.map(entry => path.join(root, entry.file)));
|
|
53
57
|
files.sort((a, b) => foundationFiles.indexOf(path.basename(a)) - foundationFiles.indexOf(path.basename(b)) || a.localeCompare(b));
|
|
54
58
|
for (const file of files) {
|
|
55
59
|
let css;
|
|
@@ -68,6 +72,7 @@ export function inspectTokens(directory) {
|
|
|
68
72
|
column: decl.source.start.column,
|
|
69
73
|
scope: context(decl),
|
|
70
74
|
value: decl.value,
|
|
75
|
+
...(scoped.definitions.some(entry => entry.file === path.relative(root, file).replaceAll("\\", "/")) ? { owner:scoped.definitions.find(entry => entry.file === path.relative(root, file).replaceAll("\\", "/")).unit } : {}),
|
|
71
76
|
};
|
|
72
77
|
if (!definitions.has(decl.prop)) definitions.set(decl.prop, []);
|
|
73
78
|
definitions.get(decl.prop).push(definition);
|
|
@@ -107,7 +112,8 @@ export function inspectTokens(directory) {
|
|
|
107
112
|
}
|
|
108
113
|
const resolvedReferences = new Map();
|
|
109
114
|
for (const ref of references(entry.value)) {
|
|
110
|
-
|
|
115
|
+
const local = scopedTokenOwner(options, ref.name);
|
|
116
|
+
if (local ? entry.owner !== local.unit : !isSharedToken(ref.name)) report("token-name", name, entry, `${name} references ${ref.name} outside its shared/owner token contract.`);
|
|
111
117
|
if (!scope.has(ref.name) && !ref.fallback) report("token-reference", name, entry, `${name} references undefined ${ref.name}.`);
|
|
112
118
|
else if (scope.has(ref.name)) resolvedReferences.set(ref.name, resolveAlias(ref.name, [...chain, name]));
|
|
113
119
|
}
|
|
@@ -137,7 +143,7 @@ export function inspectTokens(directory) {
|
|
|
137
143
|
}
|
|
138
144
|
return {
|
|
139
145
|
contractVersion: tokenContract.version,
|
|
140
|
-
tokens: [...definitions].sort(([a], [b]) => a.localeCompare(b)).map(([name, entries]) => ({ name, ...tokenContract.tokens[name], definitions: entries })),
|
|
146
|
+
tokens: [...definitions].sort(([a], [b]) => a.localeCompare(b)).map(([name, entries]) => ({ name, ...tokenContract.tokens[name], ...(scopedTokenOwner(options, name) ? {owner:scopedTokenOwner(options, name).unit, namespace:scopedTokenOwner(options, name).namespace} : {owner:"tokens"}), definitions: entries })),
|
|
141
147
|
diagnostics,
|
|
142
148
|
};
|
|
143
149
|
}
|
package/dist/units.mjs
CHANGED
|
@@ -100,6 +100,7 @@ export function inspectUnits(options) {
|
|
|
100
100
|
const sameName = name => name.replace(/[-_]/g, "").toLowerCase();
|
|
101
101
|
const flatFamilies = new Set(files.filter(file => /\.scenario\.[cm]?[jt]sx?$/.test(file)).map(file => path.posix.dirname(file)));
|
|
102
102
|
const directories = new Set(files.filter(file => /(?:^|\/)Scenario\.[cm]?[jt]sx?$/.test(file)).map(file => slash(path.dirname(file))));
|
|
103
|
+
for (const file of files.filter(file => /^(?:components|patterns)\/.+\/tokens\.json$/.test(file))) directories.add(path.posix.dirname(file));
|
|
103
104
|
for (const file of files) {
|
|
104
105
|
if (!/^(?:components|patterns|controllers|composition)\//.test(file) || !source.test(file)) continue;
|
|
105
106
|
const directory = slash(path.dirname(file)), name = path.basename(file).replace(source, "");
|
|
@@ -145,6 +146,12 @@ export function inspectUnits(options) {
|
|
|
145
146
|
}
|
|
146
147
|
for (const unit of units.values()) if (boundaryCompanion(unit.id)) {
|
|
147
148
|
(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." });
|
|
149
|
+
if (/^(?:components|patterns|controllers|composition)\//.test(unit.id)) {
|
|
150
|
+
for (let directory = unit.id; directory !== "."; directory = path.posix.dirname(directory)) {
|
|
151
|
+
const marker = path.join(dsRoot, directory, ".gitkeep");
|
|
152
|
+
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." });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
148
155
|
}
|
|
149
156
|
return { units: [...units.values()].sort((a, b) => a.id.localeCompare(b.id)), owner, publicEntry, stylesEntry, tokenDir,
|
|
150
157
|
relative: file => slash(path.relative(dsRoot, path.resolve(root, file))) };
|
|
@@ -161,6 +168,14 @@ export function checkUnitFiles(options, unit, changes, inventory = inspectUnits(
|
|
|
161
168
|
validateUnitId(unit);
|
|
162
169
|
for (const change of changes) {
|
|
163
170
|
const relative = inventory.relative(change.path);
|
|
171
|
+
if (path.posix.basename(relative) === ".gitkeep") {
|
|
172
|
+
const directory = path.posix.dirname(relative);
|
|
173
|
+
if (change.originalContent !== "" || change.content !== null || !/^(?:components|patterns|controllers|composition)\//.test(relative)
|
|
174
|
+
|| !(unit === directory || unit.startsWith(directory + "/"))
|
|
175
|
+
|| !changes.some(item => item.originalContent === null && item.content !== null && source.test(item.path)
|
|
176
|
+
&& (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);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
164
179
|
if (allowNew && unit === "configuration") continue; // The candidate must register every setup/extension file.
|
|
165
180
|
if (change.path === "ds.config.json" && boundaryCompanion(unit)) continue; // Validated against only this owner below.
|
|
166
181
|
if (relative === inventory.publicEntry) continue;
|
package/dist/verification.mjs
CHANGED
|
@@ -193,7 +193,7 @@ export function createVerificationController(root) {
|
|
|
193
193
|
if (!current) status = "stale";
|
|
194
194
|
if (signal.aborted) status = "cancelled";
|
|
195
195
|
results.push({ unit: check.unit, check: check.id, file: check.file, case: check.case, profile: profileName, status, current, revision: check.inputRevision, runId, completedAt: new Date().toISOString(),
|
|
196
|
-
previewRevision: profile.mode === "browser" ? readPreviewManifest(options)?.revision ?? null : null,
|
|
196
|
+
previewRevision: profile.mode === "browser" ? host?.previewRevision() ?? readPreviewManifest(options)?.revision ?? null : null,
|
|
197
197
|
message: runnerError?.message ?? (!matches.length ? "The selected case did not execute/report. Missing and skipped cases do not pass." : matches.filter(item => item.status !== "passed").map(item => String(item.message ?? item.status).slice(0, 2000)).join("\n")), report: slash(path.relative(root, report)) });
|
|
198
198
|
}
|
|
199
199
|
if (signal.aborted) break;
|
package/docs/ADS.md
CHANGED
|
@@ -7,7 +7,8 @@ UX, and Skin pillars. [GUIDE.md](GUIDE.md) gives setup and configuration steps.
|
|
|
7
7
|
## Ownership boundary
|
|
8
8
|
|
|
9
9
|
MCP source editing is opt-in through `ads mcp --mutations`. Its write operation
|
|
10
|
-
accepts a Git unified diff for one ADS unit
|
|
10
|
+
accepts a Git unified diff for one ADS unit (or bounded owner patches for coupled
|
|
11
|
+
transactions) and validates its source, scenario and
|
|
11
12
|
fixture changes against core checks, registered Oxlint rules and project checks
|
|
12
13
|
before application. This includes
|
|
13
14
|
foundation, documentation, original assets and an explicit configuration unit for
|
|
@@ -146,7 +147,7 @@ mounting, correct props, every branch/state or visual parity. The older
|
|
|
146
147
|
|
|
147
148
|
`token-scenario-reference` rejects undeclared token names in metadata and reachable
|
|
148
149
|
inputs. `token-scenario-render` rejects claimed tokens with no reachable input
|
|
149
|
-
reference; `token-scenario-coverage` requires every discovered
|
|
150
|
+
reference; `token-scenario-coverage` requires every discovered shared or owner-local token
|
|
150
151
|
to have coverage. A new or removed token therefore needs a scenario/fixture
|
|
151
152
|
update. All three are errors in `ads check`, run by `lint:ds` and the build.
|
|
152
153
|
Coverage is static reachability, not proof that every branch actually renders
|
|
@@ -168,6 +169,48 @@ preview builds; review meaningful states in both themes and sizes.
|
|
|
168
169
|
|
|
169
170
|
## Shared token contract
|
|
170
171
|
|
|
172
|
+
### Owner-local tokens
|
|
173
|
+
|
|
174
|
+
Shared semantics remain in the configured token foundation. Constants specific
|
|
175
|
+
to one component or pattern may live beside it:
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
components/Notice/
|
|
179
|
+
Notice.tsx # imports ./tokens.css; UI styling stays in Linaria
|
|
180
|
+
tokens.json # {"schemaVersion":1,"namespace":"--notice-"}
|
|
181
|
+
tokens.css # :root { --notice-width: 356px; }
|
|
182
|
+
Scenario.tsx
|
|
183
|
+
fixture.ts
|
|
184
|
+
Tokens.scenario.tsx # kind: "tokens", public review pattern + samples
|
|
185
|
+
Tokens.fixture.ts
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Flat owners use `<Owner>.tokens.json` and `<Owner>.tokens.css`. A unit has one
|
|
189
|
+
explicit namespace, unique across owners and separate from shared/runtime-variable
|
|
190
|
+
prefixes. The stylesheet contains only namespaced custom-property definitions
|
|
191
|
+
under root/theme conditions; imports, selectors for UI, ordinary declarations,
|
|
192
|
+
font faces and animations remain outside it. Its runtime owner imports it, so
|
|
193
|
+
product and preview consume the same values. Raw UI styling remains token-backed.
|
|
194
|
+
|
|
195
|
+
Local token aliases may reference shared tokens or their own namespace, with
|
|
196
|
+
undefined references and cycles rejected. Other owners consume shared tokens;
|
|
197
|
+
they cannot redefine, write or directly consume another owner's local namespace.
|
|
198
|
+
Measured runtime variables retain their existing exact `styleWrites` boundary.
|
|
199
|
+
`ads_tokens` returns each token's owner, definitions and local namespace.
|
|
200
|
+
|
|
201
|
+
A colocated scenario sets `kind:"tokens"` and declares real fixture `samples`
|
|
202
|
+
consumed by a public review pattern. Its ID still derives from its source path.
|
|
203
|
+
Every local token needs this real sample coverage, just like shared tokens.
|
|
204
|
+
Definitions, metadata, fixture and token scenario belong to the same edit unit.
|
|
205
|
+
Manifests/fixtures are development inputs; production includes the runtime's
|
|
206
|
+
imported CSS definitions, never the preview adapter or tooling manifest.
|
|
207
|
+
|
|
208
|
+
Use `ads_prepare_token_samples` to propose sample reconciliation from explicit
|
|
209
|
+
project property/probe bindings. The tool preserves project sample meaning and
|
|
210
|
+
reports missing mappings instead of choosing them from token prefixes.
|
|
211
|
+
|
|
212
|
+
### Shared definitions
|
|
213
|
+
|
|
171
214
|
Keep compatible token names, meanings, value types, and alias relationships;
|
|
172
215
|
project values and theme overrides may differ. The
|
|
173
216
|
[Data pillar](ARCHITECTURE.md#data-gives-implementations-a-common-language)
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -205,6 +205,13 @@ scenarios unmounts the previous view while keeping unchanged dependencies cached
|
|
|
205
205
|
Persistence is a host lifecycle choice; a new external widget loads the same
|
|
206
206
|
resources independently. Resource sharing is scoped to an App instance.
|
|
207
207
|
|
|
208
|
+
Managed graph builders publish into a private session directory beside the
|
|
209
|
+
configured manifest. Logical scenario IDs and resource URIs stay unchanged;
|
|
210
|
+
standalone builds retain the configured output and cannot overwrite a live
|
|
211
|
+
session's success record. Verified compiled snapshots form a bounded shared
|
|
212
|
+
warm-start cache. Source, compiler, dependency and output hashes still gate reuse.
|
|
213
|
+
Ordinary shutdown removes owned session output while retaining that cache.
|
|
214
|
+
|
|
208
215
|
```mermaid
|
|
209
216
|
flowchart LR
|
|
210
217
|
Host[Minimal host: navigation and MCP client] --> Proxy[Separate-origin sandbox proxy]
|
|
@@ -342,6 +349,13 @@ replace the managed process while retaining the MCP connection. Normal build gat
|
|
|
342
349
|
remain in place for source changes made through other editors; preview review remains
|
|
343
350
|
necessary after either editing path.
|
|
344
351
|
|
|
352
|
+
For genuinely coupled changes, a bounded transaction accepts one Git patch per
|
|
353
|
+
distinct owner and validates a single complete candidate before publication.
|
|
354
|
+
Each patch retains its ownership and companion rules. Local owner drafts remove
|
|
355
|
+
the need for a separate project mirror; token-sample reconciliation preserves
|
|
356
|
+
project bindings and reports unresolved mappings. Neither preparation changes live
|
|
357
|
+
source or substitutes for guarded application and rendered review.
|
|
358
|
+
|
|
345
359
|
Required shared-entry bookkeeping can accompany its owner: component/pattern
|
|
346
360
|
re-exports, canonical foundation imports for token files created or deleted, and
|
|
347
361
|
only that owner’s style-boundary entries in project configuration in the same
|
|
@@ -391,3 +405,10 @@ review pattern. The App then verifies rendered samples in the actual browser by
|
|
|
391
405
|
probing those bindings and restoring them. The tool supplies no token/property
|
|
392
406
|
classification or visual sample palette. A source build alone is not a rendered
|
|
393
407
|
verification, and the browser check does not judge design quality.
|
|
408
|
+
|
|
409
|
+
An optional owner-local token namespace keeps component/pattern constants beside
|
|
410
|
+
their consumer. Its definition-only stylesheet contains root/theme custom
|
|
411
|
+
properties and is imported by the runtime owner; UI styling remains in Linaria.
|
|
412
|
+
Namespaces, aliases, ownership and actual colocated sample coverage are checked.
|
|
413
|
+
The shared foundation remains the cross-owner vocabulary. See the
|
|
414
|
+
[owner-token contract](ADS.md#owner-local-tokens).
|