@reqvire-org/ads 0.3.21 → 0.3.24

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.
@@ -152,6 +152,13 @@ cannot be established. Registered paint consumers list their allowed binding IDs
152
152
  borrowing a peer's family or private token remains invalid. Bindings are scoped
153
153
  to their actual root; portals outside it need deliberate project integration.
154
154
 
155
+ A registered binding producer may combine two accessible color references as
156
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
157
+ both branches and their observed effect in the active color scheme. Raw colors,
158
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
159
+ This derived binding form does not widen public paint-input types; use constrained
160
+ references for each theme input and verify both color schemes in browser checks.
161
+
155
162
  The App audit checks current mounted instances, accessible values, local SVG
156
163
  resources and computed paint-property responses. Visibility and complete rendered
157
164
  output still need assertions in the registered browser checks. It rejects missing/duplicate IDs and reports unobserved written values separately. It is bounded to 100 families, 20 instances per family, 100 keys
@@ -238,7 +245,10 @@ MCP before replacing a package used by a running server. Then:
238
245
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
246
 
240
247
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
248
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
249
+ development entry as `Scenario.tsx`, even without a production entry or owner
250
+ contract. Explicit flat IDs and existing flat peer families remain separate.
251
+ An optional static `scenario.id` preserves a legacy
242
252
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
253
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
254
  in legacy registration with a note until deliberately resolved. Unknown runner
@@ -28,6 +28,16 @@ as passing evidence for the live project.
28
28
  draft argument. There is no dedicated selected-check runner for drafts yet.
29
29
  Use a dry-run transaction for genuinely coupled draft patches.
30
30
 
31
+ Build notifications are deferred until the showcase finishes initial discovery;
32
+ a preview cannot be opened with an incomplete tool list. A missing App tool is a
33
+ host-startup failure, not evidence that component behavior failed. Preserve the
34
+ draft and inspect the host diagnostic.
35
+
36
+ Registered project scripts default to 60 seconds each. A guarded configuration
37
+ change can set `mcp.mutationCheckTimeoutMs` (100–300000 ms) after measuring build
38
+ duration and contention. Timeouts name the command, budget and elapsed time;
39
+ behavior-profile budgets are separate. Do not drop checks to fit either budget.
40
+
31
41
  Behavior-run performance belongs to both orchestration and project checks. ADS
32
42
  selects affected owners, filters registered Playwright case tags and shares one
33
43
  candidate host per run. The project owns assertions, browser setup, worker count,
@@ -152,6 +152,13 @@ cannot be established. Registered paint consumers list their allowed binding IDs
152
152
  borrowing a peer's family or private token remains invalid. Bindings are scoped
153
153
  to their actual root; portals outside it need deliberate project integration.
154
154
 
155
+ A registered binding producer may combine two accessible color references as
156
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
157
+ both branches and their observed effect in the active color scheme. Raw colors,
158
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
159
+ This derived binding form does not widen public paint-input types; use constrained
160
+ references for each theme input and verify both color schemes in browser checks.
161
+
155
162
  The App audit checks current mounted instances, accessible values, local SVG
156
163
  resources and computed paint-property responses. Visibility and complete rendered
157
164
  output still need assertions in the registered browser checks. It rejects missing/duplicate IDs and reports unobserved written values separately. It is bounded to 100 families, 20 instances per family, 100 keys
@@ -238,7 +245,10 @@ MCP before replacing a package used by a running server. Then:
238
245
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
246
 
240
247
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
248
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
249
+ development entry as `Scenario.tsx`, even without a production entry or owner
250
+ contract. Explicit flat IDs and existing flat peer families remain separate.
251
+ An optional static `scenario.id` preserves a legacy
242
252
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
253
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
254
  in legacy registration with a note until deliberately resolved. Unknown runner
@@ -28,6 +28,16 @@ as passing evidence for the live project.
28
28
  draft argument. There is no dedicated selected-check runner for drafts yet.
29
29
  Use a dry-run transaction for genuinely coupled draft patches.
30
30
 
31
+ Build notifications are deferred until the showcase finishes initial discovery;
32
+ a preview cannot be opened with an incomplete tool list. A missing App tool is a
33
+ host-startup failure, not evidence that component behavior failed. Preserve the
34
+ draft and inspect the host diagnostic.
35
+
36
+ Registered project scripts default to 60 seconds each. A guarded configuration
37
+ change can set `mcp.mutationCheckTimeoutMs` (100–300000 ms) after measuring build
38
+ duration and contention. Timeouts name the command, budget and elapsed time;
39
+ behavior-profile budgets are separate. Do not drop checks to fit either budget.
40
+
31
41
  Behavior-run performance belongs to both orchestration and project checks. ADS
32
42
  selects affected owners, filters registered Playwright case tags and shares one
33
43
  candidate host per run. The project owns assertions, browser setup, worker count,
@@ -152,6 +152,13 @@ cannot be established. Registered paint consumers list their allowed binding IDs
152
152
  borrowing a peer's family or private token remains invalid. Bindings are scoped
153
153
  to their actual root; portals outside it need deliberate project integration.
154
154
 
155
+ A registered binding producer may combine two accessible color references as
156
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
157
+ both branches and their observed effect in the active color scheme. Raw colors,
158
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
159
+ This derived binding form does not widen public paint-input types; use constrained
160
+ references for each theme input and verify both color schemes in browser checks.
161
+
155
162
  The App audit checks current mounted instances, accessible values, local SVG
156
163
  resources and computed paint-property responses. Visibility and complete rendered
157
164
  output still need assertions in the registered browser checks. It rejects missing/duplicate IDs and reports unobserved written values separately. It is bounded to 100 families, 20 instances per family, 100 keys
@@ -238,7 +245,10 @@ MCP before replacing a package used by a running server. Then:
238
245
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
246
 
240
247
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
248
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
249
+ development entry as `Scenario.tsx`, even without a production entry or owner
250
+ contract. Explicit flat IDs and existing flat peer families remain separate.
251
+ An optional static `scenario.id` preserves a legacy
242
252
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
253
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
254
  in legacy registration with a note until deliberately resolved. Unknown runner
@@ -28,6 +28,16 @@ as passing evidence for the live project.
28
28
  draft argument. There is no dedicated selected-check runner for drafts yet.
29
29
  Use a dry-run transaction for genuinely coupled draft patches.
30
30
 
31
+ Build notifications are deferred until the showcase finishes initial discovery;
32
+ a preview cannot be opened with an incomplete tool list. A missing App tool is a
33
+ host-startup failure, not evidence that component behavior failed. Preserve the
34
+ draft and inspect the host diagnostic.
35
+
36
+ Registered project scripts default to 60 seconds each. A guarded configuration
37
+ change can set `mcp.mutationCheckTimeoutMs` (100–300000 ms) after measuring build
38
+ duration and contention. Timeouts name the command, budget and elapsed time;
39
+ behavior-profile budgets are separate. Do not drop checks to fit either budget.
40
+
31
41
  Behavior-run performance belongs to both orchestration and project checks. ADS
32
42
  selects affected owners, filters registered Playwright case tags and shares one
33
43
  candidate host per run. The project owns assertions, browser setup, worker count,
@@ -152,6 +152,13 @@ cannot be established. Registered paint consumers list their allowed binding IDs
152
152
  borrowing a peer's family or private token remains invalid. Bindings are scoped
153
153
  to their actual root; portals outside it need deliberate project integration.
154
154
 
155
+ A registered binding producer may combine two accessible color references as
156
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
157
+ both branches and their observed effect in the active color scheme. Raw colors,
158
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
159
+ This derived binding form does not widen public paint-input types; use constrained
160
+ references for each theme input and verify both color schemes in browser checks.
161
+
155
162
  The App audit checks current mounted instances, accessible values, local SVG
156
163
  resources and computed paint-property responses. Visibility and complete rendered
157
164
  output still need assertions in the registered browser checks. It rejects missing/duplicate IDs and reports unobserved written values separately. It is bounded to 100 families, 20 instances per family, 100 keys
@@ -238,7 +245,10 @@ MCP before replacing a package used by a running server. Then:
238
245
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
246
 
240
247
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
248
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
249
+ development entry as `Scenario.tsx`, even without a production entry or owner
250
+ contract. Explicit flat IDs and existing flat peer families remain separate.
251
+ An optional static `scenario.id` preserves a legacy
242
252
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
253
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
254
  in legacy registration with a note until deliberately resolved. Unknown runner
@@ -28,6 +28,16 @@ as passing evidence for the live project.
28
28
  draft argument. There is no dedicated selected-check runner for drafts yet.
29
29
  Use a dry-run transaction for genuinely coupled draft patches.
30
30
 
31
+ Build notifications are deferred until the showcase finishes initial discovery;
32
+ a preview cannot be opened with an incomplete tool list. A missing App tool is a
33
+ host-startup failure, not evidence that component behavior failed. Preserve the
34
+ draft and inspect the host diagnostic.
35
+
36
+ Registered project scripts default to 60 seconds each. A guarded configuration
37
+ change can set `mcp.mutationCheckTimeoutMs` (100–300000 ms) after measuring build
38
+ duration and contention. Timeouts name the command, budget and elapsed time;
39
+ behavior-profile budgets are separate. Do not drop checks to fit either budget.
40
+
31
41
  Behavior-run performance belongs to both orchestration and project checks. ADS
32
42
  selects affected owners, filters registered Playwright case tags and shares one
33
43
  candidate host per run. The project owns assertions, browser setup, worker count,
@@ -152,6 +152,13 @@ cannot be established. Registered paint consumers list their allowed binding IDs
152
152
  borrowing a peer's family or private token remains invalid. Bindings are scoped
153
153
  to their actual root; portals outside it need deliberate project integration.
154
154
 
155
+ A registered binding producer may combine two accessible color references as
156
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
157
+ both branches and their observed effect in the active color scheme. Raw colors,
158
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
159
+ This derived binding form does not widen public paint-input types; use constrained
160
+ references for each theme input and verify both color schemes in browser checks.
161
+
155
162
  The App audit checks current mounted instances, accessible values, local SVG
156
163
  resources and computed paint-property responses. Visibility and complete rendered
157
164
  output still need assertions in the registered browser checks. It rejects missing/duplicate IDs and reports unobserved written values separately. It is bounded to 100 families, 20 instances per family, 100 keys
@@ -238,7 +245,10 @@ MCP before replacing a package used by a running server. Then:
238
245
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
246
 
240
247
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
248
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
249
+ development entry as `Scenario.tsx`, even without a production entry or owner
250
+ contract. Explicit flat IDs and existing flat peer families remain separate.
251
+ An optional static `scenario.id` preserves a legacy
242
252
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
253
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
254
  in legacy registration with a note until deliberately resolved. Unknown runner
@@ -28,6 +28,16 @@ as passing evidence for the live project.
28
28
  draft argument. There is no dedicated selected-check runner for drafts yet.
29
29
  Use a dry-run transaction for genuinely coupled draft patches.
30
30
 
31
+ Build notifications are deferred until the showcase finishes initial discovery;
32
+ a preview cannot be opened with an incomplete tool list. A missing App tool is a
33
+ host-startup failure, not evidence that component behavior failed. Preserve the
34
+ draft and inspect the host diagnostic.
35
+
36
+ Registered project scripts default to 60 seconds each. A guarded configuration
37
+ change can set `mcp.mutationCheckTimeoutMs` (100–300000 ms) after measuring build
38
+ duration and contention. Timeouts name the command, budget and elapsed time;
39
+ behavior-profile budgets are separate. Do not drop checks to fit either budget.
40
+
31
41
  Behavior-run performance belongs to both orchestration and project checks. ADS
32
42
  selects affected owners, filters registered Playwright case tags and shares one
33
43
  candidate host per run. The project owns assertions, browser setup, worker count,
package/dist/units.mjs CHANGED
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import ts from "typescript";
4
4
  import postcss from "postcss";
5
- import { adsFileRole, isDevelopmentFile, isInside } from "./config.mjs";
5
+ import { adsFileRole, isDevelopmentFile, isInside, scenarioIdentity } from "./config.mjs";
6
6
  import { importResolver } from "./boundaries.mjs";
7
7
  import { documentationFilePolicy, isProjectDocument, projectDocumentFiles } from "./project-documents.mjs";
8
8
  import { foundationFiles, foundationImportTarget } from "./token-policy.mjs";
@@ -98,8 +98,33 @@ export function inspectUnits(options) {
98
98
  // Runtime entry conventions keep directory ownership stable when an optional
99
99
  // preview is removed. A flat scenario family still denotes separate owners.
100
100
  const sameName = name => name.replace(/[-_]/g, "").toLowerCase();
101
- const flatFamilies = new Set(files.filter(file => !adsFileRole(file) && /\.scenario\.[cm]?[jt]sx?$/.test(file)).map(file => path.posix.dirname(file)));
101
+ const legacyFlatFamilies = new Set(files.filter(file => !adsFileRole(file) && /\.scenario\.[cm]?[jt]sx?$/.test(file)).map(file => path.posix.dirname(file)));
102
+ const canonicalDefaults = new Set();
102
103
  const directories = new Set(files.filter(file => /(?:^|\/)Scenario\.[cm]?[jt]sx?$/.test(file)).map(file => slash(path.dirname(file))));
104
+ // A canonical marked default is the development entry of the same directory
105
+ // owner as Scenario.tsx. It needs no production module or empty contract to
106
+ // retain that boundary. Preserve explicit flat IDs and existing peer families.
107
+ for (const file of files.filter(file => adsFileRole(file) === "scenario")) {
108
+ const directory = path.posix.dirname(file);
109
+ if (legacyFlatFamilies.has(directory) || scenarioIdentity(path.join(dsRoot,file),dsRoot) !== directory) continue;
110
+ const ast = ts.createSourceFile(file,readFileSync(path.join(dsRoot,file),"utf8"),ts.ScriptTarget.Latest,true);
111
+ const declaration = ast.statements.filter(ts.isVariableStatement).flatMap(statement=>statement.declarationList.declarations)
112
+ .find(declaration=>ts.isIdentifier(declaration.name)&&declaration.name.text==="scenario");
113
+ let metadata = declaration?.initializer;
114
+ while (metadata && (ts.isAsExpression(metadata)||ts.isSatisfiesExpression(metadata)||ts.isParenthesizedExpression(metadata))) metadata=metadata.expression;
115
+ if (!metadata || !ts.isObjectLiteralExpression(metadata)) continue;
116
+ const id = metadata.properties.find(property=>property.name && (ts.isIdentifier(property.name)||ts.isStringLiteralLike(property.name)) && property.name.text==="id");
117
+ if (id && (!ts.isPropertyAssignment(id)||!ts.isStringLiteralLike(id.initializer)||id.initializer.text!==directory)) continue;
118
+ // An unresolved spread/computed key may supply or overwrite an explicit ID.
119
+ if (metadata.properties.some((property,index)=>ts.isSpreadAssignment(property) && (!id || index>metadata.properties.indexOf(id))
120
+ || property.name && ts.isComputedPropertyName(property.name))) continue;
121
+ directories.add(directory);
122
+ canonicalDefaults.add(directory);
123
+ }
124
+ // Marked flat siblings still outrank a directory index/runtime barrel. Losing
125
+ // the final legacy spelling must not merge otherwise unrelated peer owners.
126
+ const flatFamilies = new Set(files.filter(file => /\.scenario\.[cm]?[jt]sx?$/.test(file)
127
+ && (!adsFileRole(file) || !canonicalDefaults.has(path.posix.dirname(file)))).map(file => path.posix.dirname(file)));
103
128
  for (const file of files.filter(file => /^(?:components|patterns)\/.+\/tokens\.json$/.test(file))) directories.add(path.posix.dirname(file));
104
129
  for (const file of files.filter(file => /\.ads\.contract\.[cm]?ts$/.test(file))) {
105
130
  const directory=path.posix.dirname(file);
@@ -17,6 +17,8 @@ function auditPaintBindings({ container = document.getElementById("root"), bindi
17
17
  const resolved = view.getComputedStyle(node).getPropertyValue(name).trim();
18
18
  return !!resolved && view.CSS.supports("color", resolved);
19
19
  }
20
+ const themed = /^light-dark\(\s*(var\(\s*--[\w-]+\s*\)|currentColor)\s*,\s*(var\(\s*--[\w-]+\s*\)|currentColor)\s*\)$/.exec(value);
21
+ if (themed) return view.CSS.supports("color", value) && reference(themed[1], node, descriptor, seen) && reference(themed[2], node, descriptor, seen);
20
22
  const resource = /^url\(\s*(["']?)#([^\s"'()#\\\p{Cc}]+)\1\s*\)$/u.exec(value);
21
23
  if (resource && view.CSS.supports("fill", value)) {
22
24
  const candidates = [...document2.querySelectorAll("[id]")].filter((item) => item.id === resource[2]);
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.3.24
6
+
7
+ - Audit derived `light-dark()` bindings when both branches are accessible
8
+ constrained color references; verify both schemes without allowing raw colors.
9
+
10
+ - Defer showcase build notifications until initial discovery completes, preventing
11
+ false missing-App-tool startup failures in candidate verification.
12
+ - Allow a bounded, explicit `mcp.mutationCheckTimeoutMs` for registered project
13
+ scripts; retain the 60-second default and report command/budget/elapsed time.
14
+
15
+ ## 0.3.23
16
+
17
+ - Preserve directory ownership when its last legacy composition/scenario entries
18
+ migrate to canonical `.ads.` roles. Require no artificial runtime entry or
19
+ empty contract; retain explicit flat IDs and existing flat peer families.
20
+ - Keep fully migrated flat scenario siblings separate beside directory export
21
+ barrels. Version 0.3.22 was tagged; publication was cancelled before these
22
+ additional full-migration checks completed.
23
+
5
24
  ## 0.3.21
6
25
 
7
26
  - Add statically read TypeScript owner contracts and canonical `.ads.` development
package/docs/CONTRACTS.md CHANGED
@@ -238,7 +238,10 @@ MCP before replacing a package used by a running server. Then:
238
238
  5. Dry-run/apply with `ads_apply_patch`, or a genuinely coupled transaction.
239
239
 
240
240
  Migration never edits live source or bypasses gates. It retains stable scenario
241
- IDs and check case IDs. An optional static `scenario.id` preserves a legacy
241
+ IDs, check case IDs and directory ownership. A canonical `<Owner>.ads.scenario.tsx` is the same
242
+ development entry as `Scenario.tsx`, even without a production entry or owner
243
+ contract. Explicit flat IDs and existing flat peer families remain separate.
244
+ An optional static `scenario.id` preserves a legacy
242
245
  identity when a renamed filename would otherwise be ambiguous; it must stay
243
246
  inside the owning unit and be unique. Whole-file or unimportable private behavior subjects stay
244
247
  in legacy registration with a note until deliberately resolved. Unknown runner
package/docs/GUIDE.md CHANGED
@@ -403,7 +403,9 @@ input/configuration or execution errors.
403
403
 
404
404
  Guarded MCP editing is opt-in. Its mandatory checks and optional project
405
405
  `mcp.mutationChecks` scripts run in a temporary project copy with installed
406
- dependencies. See the [editing contract](MCP.md#guarded-editing) for unit ownership,
406
+ dependencies. Project scripts default to 60 seconds each; use the explicit
407
+ `mcp.mutationCheckTimeoutMs` budget (100–300000 ms) for measured slower builds.
408
+ Behavior profiles have a separate whole-run budget. See the [editing contract](MCP.md#guarded-editing) for unit ownership,
407
409
  Git patches, bounded reads and preview review. Keep normal build gates enabled
408
410
  for edits made by other tools.
409
411
 
package/docs/MCP.md CHANGED
@@ -547,7 +547,7 @@ rules, including warnings. By default it also runs available `lint:project`
547
547
  additional list through project-owned configuration:
548
548
 
549
549
  ```json
550
- { "mcp": { "mutationChecks": ["lint", "typecheck", "build:mcp-previews"] } }
550
+ { "mcp": { "mutationChecks": ["lint", "typecheck", "build:mcp-previews"], "mutationCheckTimeoutMs": 120000 } }
551
551
  ```
552
552
 
553
553
  Every listed script must exist. An empty list still runs mandatory ADS and Oxlint
@@ -557,8 +557,11 @@ sandbox. An explicit `configuration` patch can change project commands, register
557
557
  rules and reviewed exceptions; validation runs the proposed configuration and
558
558
  scripts. Mandatory core and generated Oxlint checks still run on every write.
559
559
  Configuration changes cannot bundle unrelated component edits. Checks that
560
- rewrite source are rejected. Each command has a 60-second limit; the diagnostic
561
- explorer allows up to 15 minutes for the complete request.
560
+ rewrite source are rejected. Each registered project script defaults to a
561
+ 60-second limit. `mcp.mutationCheckTimeoutMs` sets its explicit budget
562
+ (100–300000 ms); it does not change mandatory gates or behavior-profile budgets.
563
+ Timeout diagnostics identify the command, configured budget and elapsed time.
564
+ The diagnostic explorer allows up to 15 minutes for the complete request.
562
565
 
563
566
  Ordinary source and asset files owned by the selected unit are editable. Generated
564
567
  outputs, dependency directories, Git metadata and symlink/hardlink targets are
@@ -1084,3 +1087,10 @@ then use the existing diff and guarded dry-run/apply workflow. It does not write
1084
1087
  live source, loosen policy or add a second contract-editing protocol. See
1085
1088
  [CONTRACTS.md](CONTRACTS.md) for the static schema, compatibility and browser audits.
1086
1089
  The same guide is available at `ads://guides/contracts`.
1090
+
1091
+ A registered binding producer may combine two accessible color references as
1092
+ `light-dark(var(--light-token), var(--dark-token))`. The App paint audit checks
1093
+ both branches and their observed effect in the active color scheme. Raw colors,
1094
+ unknown/private tokens and SVG URLs inside this color function remain invalid.
1095
+ This derived binding form does not widen public paint-input types; use constrained
1096
+ references for each theme input and verify both color schemes in browser checks.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reqvire-org/ads",
3
- "version": "0.3.21",
3
+ "version": "0.3.24",
4
4
  "type": "module",
5
5
  "description": "A design system your agent can see and shape. Your components. Your look. Your code.",
6
6
  "repository": {