@reqvire-org/ads 0.3.16 → 0.3.18
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 +3 -0
- package/dist/atomic-composition.mjs +1 -1
- package/dist/check.mjs +43 -11
- package/dist/evidence.mjs +18 -0
- package/dist/investigations.mjs +101 -0
- package/dist/linaria/preserve-values.cjs +21 -2
- package/dist/mcp/behavior-pages.mjs +36 -0
- package/dist/mcp/context.mjs +3 -1
- package/dist/mcp/execution-results.mjs +146 -0
- package/dist/mcp/mutations.mjs +34 -17
- package/dist/mcp/preview-widget.bundle.js +12 -12
- package/dist/mcp/resource-loader.js +3 -3
- package/dist/mcp/result-pages.mjs +87 -0
- package/dist/mcp/server.mjs +67 -30
- package/dist/property-registrations.mjs +39 -0
- package/dist/scenario-selectors.mjs +140 -0
- package/dist/scenario-trace.mjs +1 -1
- package/dist/scoped-tokens.mjs +6 -0
- package/dist/selector-match.mjs +94 -0
- package/dist/showcase/client.bundle.js +2 -2
- package/dist/skills/ads-break-ui/SKILL.md +8 -3
- package/dist/skills/ads-break-ui/references/atomic-styles.md +48 -0
- package/dist/skills/ads-break-ui/references/captures.md +6 -1
- package/dist/skills/ads-break-ui/references/evidence.md +120 -0
- package/dist/skills/ads-break-ui/references/guarded-editing.md +8 -5
- package/dist/skills/ads-break-ui/references/scenarios.md +32 -0
- package/dist/skills/ads-designer/SKILL.md +8 -3
- package/dist/skills/ads-designer/references/atomic-styles.md +48 -0
- package/dist/skills/ads-designer/references/captures.md +6 -1
- package/dist/skills/ads-designer/references/evidence.md +120 -0
- package/dist/skills/ads-designer/references/guarded-editing.md +8 -5
- package/dist/skills/ads-designer/references/scenarios.md +32 -0
- package/dist/skills/ads-import/SKILL.md +8 -3
- package/dist/skills/ads-import/references/atomic-styles.md +48 -0
- package/dist/skills/ads-import/references/captures.md +6 -1
- package/dist/skills/ads-import/references/evidence.md +120 -0
- package/dist/skills/ads-import/references/guarded-editing.md +8 -5
- package/dist/skills/ads-import/references/scenarios.md +32 -0
- package/dist/skills/ads-migrate/SKILL.md +8 -3
- package/dist/skills/ads-migrate/references/atomic-styles.md +48 -0
- package/dist/skills/ads-migrate/references/captures.md +6 -1
- package/dist/skills/ads-migrate/references/evidence.md +120 -0
- package/dist/skills/ads-migrate/references/guarded-editing.md +8 -5
- package/dist/skills/ads-migrate/references/scenarios.md +32 -0
- package/dist/skills/ads-motion/SKILL.md +8 -3
- package/dist/skills/ads-motion/references/atomic-styles.md +48 -0
- package/dist/skills/ads-motion/references/captures.md +6 -1
- package/dist/skills/ads-motion/references/evidence.md +120 -0
- package/dist/skills/ads-motion/references/guarded-editing.md +8 -5
- package/dist/skills/ads-motion/references/scenarios.md +32 -0
- package/dist/verification/browser.mjs +22 -7
- package/dist/verification/playwright-reporter.cjs +23 -5
- package/dist/verification.mjs +31 -9
- package/docs/ADS.md +10 -0
- package/docs/ARCHITECTURE.md +47 -3
- package/docs/BEHAVIORS.md +30 -0
- package/docs/CHANGELOG.md +30 -0
- package/docs/MCP.md +66 -7
- package/package.json +2 -1
package/dist/verification.mjs
CHANGED
|
@@ -12,6 +12,8 @@ import { inspectUnits, configurationFiles } from "./units.mjs";
|
|
|
12
12
|
import { inspectBehaviors } from "./behaviors.mjs";
|
|
13
13
|
import { inspectScenarios } from "./scenarios.mjs";
|
|
14
14
|
import { readPreviewManifest } from "./preview-resources.mjs";
|
|
15
|
+
import { acceptance, failure, failureCategories } from "./evidence.mjs";
|
|
16
|
+
import { investigationArtifacts, investigationUri, saveInvestigations } from "./investigations.mjs";
|
|
15
17
|
|
|
16
18
|
export const BEHAVIOR_URI = "ads://project/behaviors";
|
|
17
19
|
const hash = bytes => createHash("sha256").update(bytes).digest("hex");
|
|
@@ -123,7 +125,7 @@ export function behaviorInputs(options, contract, check, context = inputContext(
|
|
|
123
125
|
const rows = [...files].sort().map(file => [slash(path.relative(options.root, file)), context.digest(file)]);
|
|
124
126
|
for (const file of ["package-lock.json", "bun.lock", "bun.lockb", "pnpm-lock.yaml", "yarn.lock", "node_modules/.package-lock.json"]) rows.push([file, existsSync(path.join(options.root, file)) ? context.digest(path.join(options.root, file)) : null]);
|
|
125
127
|
rows.push(["profile", JSON.stringify(options.config.mcp.behaviorProfiles[check.profile])], ["node", process.version]);
|
|
126
|
-
for (const file of ["./verification.mjs", "./verification/browser.mjs", "./verification/playwright-reporter.cjs"]) rows.push([`tool:${file}`, hash(readFileSync(new URL(file, import.meta.url)))]);
|
|
128
|
+
for (const file of ["./verification.mjs", "./verification/browser.mjs", "./verification/playwright-reporter.cjs", "./evidence.mjs", "./investigations.mjs"]) rows.push([`tool:${file}`, hash(readFileSync(new URL(file, import.meta.url)))]);
|
|
127
129
|
return { revision: hash(JSON.stringify(rows)), files: rows.map(([file]) => file) };
|
|
128
130
|
}
|
|
129
131
|
|
|
@@ -136,6 +138,11 @@ function saved(root) {
|
|
|
136
138
|
} catch { return {}; }
|
|
137
139
|
}
|
|
138
140
|
const identity = (unit, check) => `${unit}#${check}`;
|
|
141
|
+
function verificationResult(diagnostics, results) {
|
|
142
|
+
const ok=diagnostics.length===0&&results.length>0&&results.every(result=>result.status==="passed"&&result.current);
|
|
143
|
+
return {ok,diagnostics:diagnostics.map(diagnostic=>({...diagnostic,failure:diagnostic.failure??failure("runner","verification",diagnostic.rule)})),results,
|
|
144
|
+
acceptance:acceptance("selected-behavior-checks",ok,results.filter(result=>result.status==="passed"&&result.current).map(result=>`${result.unit}#${result.check}`),["unselected-checks","unasserted-behavior","visual-parity","accessibility-audit"])};
|
|
145
|
+
}
|
|
139
146
|
|
|
140
147
|
export function behaviorStatus(options) {
|
|
141
148
|
const inventory = inspectBehaviors(options), evidence = saved(options.root);
|
|
@@ -223,7 +230,7 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
223
230
|
status: () => ({ running: !!active, ...(active && progress ? { progress: { ...progress, elapsedMs: Date.now() - progress.startedAt } } : {}) }),
|
|
224
231
|
async close() { active?.abort(); await active?.completion; },
|
|
225
232
|
async run({ unit, units, checks, persist = true } = {}, signal, notifyProgress) {
|
|
226
|
-
if (active) return
|
|
233
|
+
if (active) return verificationResult([{ rule: "behavior-busy", message: "A behavior verification is already running." }],[]);
|
|
227
234
|
active = new AbortController();
|
|
228
235
|
const controller = active;
|
|
229
236
|
signal = signal ? AbortSignal.any([signal, active.signal]) : active.signal;
|
|
@@ -232,13 +239,13 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
232
239
|
const results = [], diagnostics = [];
|
|
233
240
|
try {
|
|
234
241
|
const options = loadConfig(root), inventory = inspectBehaviors(options);
|
|
235
|
-
if (inventory.diagnostics.length) return {
|
|
242
|
+
if (inventory.diagnostics.length) return verificationResult(inventory.diagnostics.map(diagnostic=>({...diagnostic,failure:failure("architecture","behavior-contract",diagnostic.rule)})),results);
|
|
236
243
|
const selectedUnits = new Set(units ?? (unit ? [unit] : inventory.contracts.map(item => item.unit)));
|
|
237
244
|
const contracts = inventory.contracts.filter(item => selectedUnits.has(item.unit));
|
|
238
|
-
if (!contracts.length || [...selectedUnits].some(id => !contracts.some(contract => contract.unit === id))) return
|
|
245
|
+
if (!contracts.length || [...selectedUnits].some(id => !contracts.some(contract => contract.unit === id))) return verificationResult([{ rule: "behavior-selection", message: "No behavior contract matches the complete selection. Discover exact owner/check IDs with ads_behaviors." }],results);
|
|
239
246
|
const context = inputContext(options);
|
|
240
247
|
const selection = contracts.flatMap(contract => Object.entries(contract.checks).filter(([id]) => !checks || checks.includes(id)).map(([id, check]) => ({ unit: contract.unit, id, ...check, inputRevision: behaviorInputs(options, contract, check, context).revision, contract })));
|
|
241
|
-
if (!selection.length || checks?.some(id => !selection.some(check => check.id === id))) return
|
|
248
|
+
if (!selection.length || checks?.some(id => !selection.some(check => check.id === id))) return verificationResult([{ rule: "behavior-selection", message: "Unknown check selection. Use check IDs returned by ads_behaviors." }],results);
|
|
242
249
|
for (const profileName of new Set(selection.map(check => check.profile))) {
|
|
243
250
|
const profile = options.config.mcp.behaviorProfiles[profileName];
|
|
244
251
|
const group = selection.filter(check => check.profile === profileName);
|
|
@@ -295,7 +302,11 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
295
302
|
// Unexplained exits, suite errors and interrupted reports grant no pass.
|
|
296
303
|
const caseFailureExit = run?.code === 1 && !runnerError && !suiteErrors.length && !incompleteReport && reportValue?.cases.some(item => item?.status === "failed");
|
|
297
304
|
const runnerFailure = run && (run.code !== 0 || suiteErrors.length || incompleteReport) ? `Registered runner ${profileName} ${run.code !== 0 ? `exited with code ${run.code ?? "unknown"}` : incompleteReport ? "left an incomplete report" : "reported a suite error"}. ${suiteErrors.join("; ") || reportValue?.cases.filter(item => item?.status === "failed").slice(0, 3).map(item => `${item.id}: ${item.message || "failed without a case diagnostic"}`).join("; ") || "Inspect the runner output and verification report."}`.slice(0, 3000) : undefined;
|
|
298
|
-
if (runnerFailure)
|
|
305
|
+
if (runnerFailure) {
|
|
306
|
+
const caseFailures=reportValue?.cases.filter(item=>item.status==="failed"&&failureCategories.has(item.failure?.category)).map(item=>item.failure)??[];
|
|
307
|
+
diagnostics.push({ rule: "behavior-runner", message: runnerFailure, output: run.output?.slice(-4000), profile: profileName,
|
|
308
|
+
failure:caseFailureExit&&caseFailures.length?{...caseFailures[0],phase:"case-results",relatedCategories:[...new Set(caseFailures.map(item=>item.category))]}:failure("runner","profile-execution","ADS_RUNNER_EXIT",{certainty:caseFailureExit?"unclassified":"observed-boundary"}) });
|
|
309
|
+
}
|
|
299
310
|
const afterOptions = loadConfig(root), afterContext = inputContext(afterOptions);
|
|
300
311
|
for (const check of group) {
|
|
301
312
|
const file = slash(path.relative(root, path.resolve(root, path.dirname(check.contract.file), check.file)));
|
|
@@ -307,7 +318,17 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
307
318
|
const current = behaviorInputs(afterOptions, check.contract, check, afterContext).revision === check.inputRevision;
|
|
308
319
|
if (!current) status = "stale";
|
|
309
320
|
if (signal.aborted) status = "cancelled";
|
|
310
|
-
|
|
321
|
+
const caseDetail=matches.find(item=>item.status!=="passed")??matches.at(-1);
|
|
322
|
+
const reportedFailure=caseDetail?.failure;
|
|
323
|
+
const checkFailure=status==="passed"?undefined:status==="stale"||status==="cancelled"?failure("runner","verification",`ADS_${status.toUpperCase()}`):caseDetail?.status==="failed"&&failureCategories.has(reportedFailure?.category)?reportedFailure:blockedRun?failure("runner","profile-execution",runnerError?.reason??"ADS_RUNNER_INCOMPLETE",{certainty:"observed-boundary"}):failure("runner","test-execution","ADS_CASE_UNCLASSIFIED",{certainty:"unclassified"});
|
|
324
|
+
const accepted=acceptance("registered-case",status==="passed"&¤t,status==="passed"&¤t?["registered-case-completed"]:[],["unasserted-behavior","visual-parity","accessibility-audit"]);
|
|
325
|
+
const investigation={unit:check.unit,check:check.id,status,runId,resourceUri:investigationUri({unit:check.unit,check:check.id}),target:root===reportRoot?"project":"candidate",framework:options.config.framework,profile:profileName,mode:profile.mode??"unit",scenario:check.scenario??null,inputRevision:check.inputRevision,inputsCurrentAtCompletion:current,
|
|
326
|
+
source:caseDetail?.source??{file},failingStep:caseDetail?.failingStep??null,viewport:caseDetail?.viewport??null,viewportSource:caseDetail?.viewportSource??null,
|
|
327
|
+
observedPreviewRevision:matches.flatMap(item=>item.diagnostics??[]).findLast(item=>item.kind==="preview-startup")?.previewRevision??null,
|
|
328
|
+
requests:matches.flatMap(item=>item.diagnostics??[]).flatMap(item=>item.requests??[]).slice(0,8),browserErrors:matches.flatMap(item=>item.diagnostics??[]).flatMap(item=>item.errors??[]).slice(0,3),
|
|
329
|
+
artifacts:investigationArtifacts(reportRoot,report,matches.flatMap(item=>item.artifacts??[])),acceptance:accepted,...(checkFailure?{failure:checkFailure}:{}),completedAt:new Date().toISOString()};
|
|
330
|
+
results.push({ unit: check.unit, check: check.id, file: check.file, case: check.case, profile: profileName, status, current, revision: check.inputRevision, runId, completedAt: investigation.completedAt,
|
|
331
|
+
...(checkFailure?{failure:checkFailure}:{}),acceptance:accepted,investigation,
|
|
311
332
|
previewRevision: profile.mode === "browser" ? host?.previewRevision() ?? readPreviewManifest(options)?.revision ?? null : null,
|
|
312
333
|
...(matches.length ? { reportedStatus, durationMs: matches.reduce((sum, item) => sum + (Number.isFinite(item.durationMs) ? Math.max(0, item.durationMs) : 0), 0) } : {}),
|
|
313
334
|
...(matches.some(item => item.diagnostics?.length) ? { startupDiagnostics: matches.flatMap(item => Array.isArray(item.diagnostics) ? item.diagnostics.slice(0, 5) : []).slice(0, 10) } : {}),
|
|
@@ -317,6 +338,7 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
317
338
|
}
|
|
318
339
|
if (signal.aborted) break;
|
|
319
340
|
}
|
|
341
|
+
saveInvestigations(reportRoot,results.map(result=>result.investigation),inventory.contracts.flatMap(contract=>Object.keys(contract.checks).map(id=>identity(contract.unit,id))));
|
|
320
342
|
if (persist) {
|
|
321
343
|
const evidence = saved(root);
|
|
322
344
|
for (const result of results) evidence[identity(result.unit, result.check)] = result;
|
|
@@ -325,8 +347,8 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
325
347
|
if (Buffer.byteLength(content) > 2 * 1024 * 1024) throw new Error("Verification evidence exceeds 2 MiB. Remove obsolete generated evidence and retry.");
|
|
326
348
|
try { writeFileSync(temporary, content); renameSync(temporary, file); } finally { rmSync(temporary, { force: true }); }
|
|
327
349
|
}
|
|
328
|
-
return
|
|
329
|
-
} catch (error) { return
|
|
350
|
+
return verificationResult(diagnostics,results);
|
|
351
|
+
} catch (error) { return verificationResult([{ rule: "behavior-verification", message: error.message }],results); }
|
|
330
352
|
finally { try { await host?.close(); } finally { if (active === controller) { active = undefined; progress = undefined; } finish(); } }
|
|
331
353
|
},
|
|
332
354
|
};
|
package/docs/ADS.md
CHANGED
|
@@ -259,6 +259,16 @@ custom styling in fixture files. The ADS frame pattern uses `--ux-*`. Foreign br
|
|
|
259
259
|
CSS imports the approved token files in order; shared assignments belong in
|
|
260
260
|
those token files, never in consumer styles or component state overrides.
|
|
261
261
|
|
|
262
|
+
Typed custom-property registrations follow the same ownership. Runtime-variable
|
|
263
|
+
`@property` metadata lives in component/pattern Linaria; shared and owner-local
|
|
264
|
+
token registrations live beside real token definitions. Names are document-global:
|
|
265
|
+
unrelated owners and conflicting descriptor sets cannot claim the same name.
|
|
266
|
+
Descriptors have their own CSS grammar and independent literal defaults; normal
|
|
267
|
+
visual styling still uses tokens. Registration does not create token/sample
|
|
268
|
+
coverage, and base resets/font metadata cannot host it. Preserve whole rules with
|
|
269
|
+
the ADS Linaria resolver in product and MCP preview builds. See the portable
|
|
270
|
+
[atomic styling guide](../skills/ads-designer/references/atomic-styles.md).
|
|
271
|
+
|
|
262
272
|
Foundation roles are enforced by `foundation-role`, `foundation-selector` and
|
|
263
273
|
`foundation-import`, alongside the regular token checks. Shared definitions
|
|
264
274
|
belong on the document root or explicit root themes; ordinary declarations belong
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -155,6 +155,19 @@ values; source guards alone cannot establish extraction correctness. The
|
|
|
155
155
|
skill-local [atomic styling guide](../skills/ads-designer/references/atomic-styles.md#preserve-custom-property-arithmetic-during-extraction)
|
|
156
156
|
documents integration and source-workaround semantics.
|
|
157
157
|
|
|
158
|
+
The resolver also preserves complete `@property` registrations and their
|
|
159
|
+
conditional at-rule context for atomic `css`/`styled`. Their descriptors are schema
|
|
160
|
+
metadata, not separate atomic declarations. CSS-tree validates CSS value grammar;
|
|
161
|
+
PostCSS supplies source/at-rule structure. Registered names have one owner and a
|
|
162
|
+
stable schema across its modules, because registration is document-global. Runtime
|
|
163
|
+
variables are registered in owned Linaria; shared or namespaced design tokens are
|
|
164
|
+
registered beside their real value definitions. Base resets and fonts cannot own
|
|
165
|
+
registrations. Descriptor literals are narrowly permitted where CSS requires an
|
|
166
|
+
independent initial value; ordinary visual assignments remain token-governed.
|
|
167
|
+
MCP serves these styles to the sandboxed App document. Registration metadata
|
|
168
|
+
neither creates new token definitions nor replaces token sample coverage.
|
|
169
|
+
Compiled-CSS and browser tests verify interpolation in React and Preact Apps.
|
|
170
|
+
|
|
158
171
|
## Public APIs preserve the boundary
|
|
159
172
|
|
|
160
173
|
The application and project-owned preview scenarios consume a project's public ADS entry. Components
|
|
@@ -322,7 +335,12 @@ styles. This preserves ownership rather than granting scenario styling freedom.
|
|
|
322
335
|
A native element may provide semantics as the single direct child of a public
|
|
323
336
|
runtime slot when source tracing proves it is cloned with that owner's props.
|
|
324
337
|
This preserves polymorphic composition without allowing standalone scenario
|
|
325
|
-
controls, scenario styling or name-based exceptions.
|
|
338
|
+
controls, scenario styling or name-based exceptions. Selector-based composition
|
|
339
|
+
can establish the same ownership through actual returned DOM and attached runtime
|
|
340
|
+
Linaria: a positive native-tag relationship, or a `:has` relationship to a marker
|
|
341
|
+
declared by a real runtime-owned child. Broad selectors and scenario-authored
|
|
342
|
+
lookalikes grant no permission. This source proof does not establish computed
|
|
343
|
+
appearance, keyboard behavior or visual parity; browser checks remain necessary.
|
|
326
344
|
The skill-local [scenario guide](../skills/ads-designer/references/scenarios.md)
|
|
327
345
|
explains evidence, limits and diagnostics.
|
|
328
346
|
|
|
@@ -427,8 +445,34 @@ ADS owns affected-check selection, candidate hosting, progress, evidence freshne
|
|
|
427
445
|
and process cleanup. One profile timeout bounds its entire runner process. Parallel
|
|
428
446
|
workers can share that candidate host with independent App state. Partial outcomes
|
|
429
447
|
remain diagnostic when execution is interrupted; they cannot approve a mutation.
|
|
430
|
-
Passing checks describe their registered assertions, not every natural-language claim.
|
|
431
|
-
|
|
448
|
+
Passing checks describe their registered assertions, not every natural-language claim.
|
|
449
|
+
Results distinguish architecture, project-build, transport, runner and assertion
|
|
450
|
+
boundaries with structured phase/code evidence; an unclassified test exception
|
|
451
|
+
does not become an assertion or a component defect. Acceptance explicitly lists
|
|
452
|
+
established and unverified scope. Verification retains one latest investigation
|
|
453
|
+
per registered check, including isolated candidates: exact input revision,
|
|
454
|
+
observed preview revision, failing step/source, observed startup viewport,
|
|
455
|
+
failed requests and available project-recorded artifacts. MCP exposes bounded
|
|
456
|
+
bundle/index resources and only registered, digest-checked artifact files.
|
|
457
|
+
Another run replaces that check's resource access; candidate evidence never
|
|
458
|
+
certifies live source. Detailed usage lives in the portable skill-local
|
|
459
|
+
[evidence guide](../skills/ads-designer/references/evidence.md).
|
|
460
|
+
|
|
461
|
+
MCP delivery is separate from validation: verification and mutation controllers
|
|
462
|
+
use complete results to decide acceptance. Their MCP replies contain counts,
|
|
463
|
+
bounded acceptance, at most three failure previews and a result ID in at most
|
|
464
|
+
4 KiB of UTF-8 JSON. `ads_results` reads saved outcomes, diagnostics and other
|
|
465
|
+
sections without rerunning checks. Pages have at most 20 rows and 8 KiB of JSON;
|
|
466
|
+
truncated records support bounded text ranges. Discovery and investigation
|
|
467
|
+
sections use the same paging budget. Cursors bind the query and result/revision;
|
|
468
|
+
superseded IDs fail explicitly instead of silently returning another run.
|
|
469
|
+
Only the latest verification and mutation snapshots are retained, each at most
|
|
470
|
+
8 MiB under `.ds/tool-results/`. Oversized reports retain a summary with an
|
|
471
|
+
explicit unavailable-details warning. Storage/notification failure cannot change
|
|
472
|
+
an accepted edit's applied state. These are payload byte budgets, not tokenizer
|
|
473
|
+
estimates; MCP compatibility text may duplicate structured JSON on the wire.
|
|
474
|
+
|
|
475
|
+
Edits stay focused without requiring entire file bodies in model context. Peer units and
|
|
432
476
|
unrelated owners remain outside the selected unit's edit boundary. Shared foundation,
|
|
433
477
|
branding and guides have their own units. Shared credits and text license notices
|
|
434
478
|
belong to the documentation unit, including conventional root notices and shared
|
package/docs/BEHAVIORS.md
CHANGED
|
@@ -272,6 +272,13 @@ publish `complete:true` at completion. Older final reports without `complete`
|
|
|
272
272
|
remain supported after normal process completion. An explicitly incomplete report
|
|
273
273
|
cannot pass even with exit code zero. Partial reports retain the same schema/run
|
|
274
274
|
identity and size limits as final reports.
|
|
275
|
+
Cases may optionally include `failure: {category,phase,code,certainty?}`,
|
|
276
|
+
`source: {file,line,column}`, `failingStep`, `viewport`/`viewportSource`, and
|
|
277
|
+
`artifacts: [{name,mimeType,path}]`. Artifact paths are relative to the report
|
|
278
|
+
directory and must remain under that run's `artifacts/` directory. The built-in
|
|
279
|
+
Playwright reporter supplies these from actual step/startup/attachment evidence.
|
|
280
|
+
Older protocol runners can omit them; ADS preserves that lack of classification
|
|
281
|
+
instead of treating an arbitrary thrown message as an assertion.
|
|
275
282
|
`file` is project-relative. Nonzero process exit, missing cases, skipped cases,
|
|
276
283
|
wrong run IDs and unavailable reports do not pass. Test commands are trusted
|
|
277
284
|
project code; an adapter cannot prove the quality or honesty of their assertions.
|
|
@@ -300,6 +307,29 @@ changes mark results stale; changes during execution prevent a current pass.
|
|
|
300
307
|
Guarantees report passing only when all their checks have current passing evidence.
|
|
301
308
|
Passing applies to those cases and profiles, not every application state.
|
|
302
309
|
|
|
310
|
+
Results expose structured `failure` boundaries and explicit `acceptance` scope.
|
|
311
|
+
MCP execution replies contain counts, bounded acceptance, at most three failure
|
|
312
|
+
previews and a `resultId` (4 KiB UTF-8 JSON maximum). Use `ads_results` to read
|
|
313
|
+
selected `outcomes`, `checks`, `diagnostics` or other sections without execution.
|
|
314
|
+
Pages default to 10 rows, allow at most 20 and stay within 8 KiB; follow
|
|
315
|
+
`nextCursor` with identical selection/status. Truncated records provide
|
|
316
|
+
`recordIndex` for exact `offset`/`chars` ranges. Only the latest verification and
|
|
317
|
+
mutation snapshots are retained, independently, at most 8 MiB each. Replaced IDs
|
|
318
|
+
fail explicitly. Validation still uses complete internal outcomes.
|
|
319
|
+
|
|
320
|
+
Use `ads_investigate({unit,check,runId})` with an outcome's exact IDs for its compact
|
|
321
|
+
summary (4 KiB maximum); details, requests, browser errors and artifact metadata are separate
|
|
322
|
+
paged sections (8 KiB maximum). Truncated records support exact text ranges with
|
|
323
|
+
the recorded run ID. Saved outcomes describe completion time; compare current
|
|
324
|
+
`ads_behaviors` revisions for freshness. It includes isolated dry runs; `ads://project/investigations` lists available entries. Exact
|
|
325
|
+
input and observed preview revisions, failing step/source, startup viewport,
|
|
326
|
+
failed startup requests and available project-recorded artifacts keep diagnosis
|
|
327
|
+
separate from an inferred component defect. No artifact is invented or test
|
|
328
|
+
retried. Each check retains one latest bundle; old artifact resource access is
|
|
329
|
+
superseded. Candidate bundles remain distinct from passing live-source evidence.
|
|
330
|
+
Read the portable [evidence reference](../skills/ads-designer/references/evidence.md)
|
|
331
|
+
for category meanings, collection limits and artifact policy.
|
|
332
|
+
|
|
303
333
|
Revisions include owned files, literal import dependencies, local CSS imports and
|
|
304
334
|
asset URLs, token foundation, project/runner configuration, lockfiles and tooling.
|
|
305
335
|
Computed module selection conservatively includes all ADS owners. Environment,
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.18
|
|
4
|
+
|
|
5
|
+
- Preserve complete typed `@property` registrations through atomic css/styled
|
|
6
|
+
extraction, conditional rules and CSS minification. Validate descriptors with
|
|
7
|
+
CSS-tree, enforce runtime/token ownership and naming conflicts, and retain
|
|
8
|
+
ordinary style-token gates. Verify dummy interpolation in React/Preact MCP Apps.
|
|
9
|
+
- Sync all skill references for registrations and selector-owned native
|
|
10
|
+
composition; keep implementation independent of any imported component library.
|
|
11
|
+
|
|
12
|
+
- Deliver verification and guarded-edit replies as 4 KiB JSON summaries with
|
|
13
|
+
counts, acceptance and result IDs. Page outcomes, diagnostics, logs and captures
|
|
14
|
+
through `ads_results`; retain only the latest verification and mutation snapshots.
|
|
15
|
+
Keep complete internal validation independent of delivery.
|
|
16
|
+
- Page behavior discovery and investigation details; bind cursors to their query
|
|
17
|
+
and recorded run, reject superseded evidence, and document selective retrieval
|
|
18
|
+
in every portable skill. Keep artifacts separate from tool JSON.
|
|
19
|
+
|
|
20
|
+
## 0.3.17
|
|
21
|
+
|
|
22
|
+
- Recognize native semantic composition through source-verified runtime Linaria
|
|
23
|
+
selectors, including runtime-owned part bindings. Keep unrelated controls,
|
|
24
|
+
broad selectors, fabricated markers and custom scenario styling rejected.
|
|
25
|
+
- Distinguish architecture, build, transport, runner and assertion boundaries;
|
|
26
|
+
expose explicit acceptance scope and latest-per-check investigation bundles
|
|
27
|
+
with revisions, source/step, startup viewport, requests and available artifacts.
|
|
28
|
+
Preserve candidate/live-source evidence and independent case outcomes.
|
|
29
|
+
- Add generic React/Preact conformance checks for selector composition, extracted
|
|
30
|
+
CSS, MCP resource recovery and native iframe interaction. Document diagnosis
|
|
31
|
+
through portable skill references without project-specific implementation rules.
|
|
32
|
+
|
|
3
33
|
## 0.3.16
|
|
4
34
|
|
|
5
35
|
- Recover transient showcase MCP resource fetch failures with bounded read-only
|
package/docs/MCP.md
CHANGED
|
@@ -175,8 +175,10 @@ The server supplies agent guidance through its instructions, tool descriptions,
|
|
|
175
175
|
| `ads_show_tokens` | Render a discovered token scenario; legacy compilers retain the definition inspector |
|
|
176
176
|
| `ads_scenarios` | Bounded token/component/pattern/composition scenario discovery |
|
|
177
177
|
| `ads_show_scenario` | Render an exact discovered scenario with its own fixtures |
|
|
178
|
-
| `ads_behaviors` |
|
|
178
|
+
| `ads_behaviors` | Paged owner discovery; select a unit and detail section |
|
|
179
179
|
| `ads_verify` | Execute an owner's registered checks and record revision-bound evidence |
|
|
180
|
+
| `ads_results` | Page saved execution outcomes, diagnostics, logs and captures without rerunning |
|
|
181
|
+
| `ads_investigate` | Read one check's summary, then paged requests/errors/artifacts |
|
|
180
182
|
| `ads_capture` | On-demand PNG of a discovered scenario or named element; replace current and clear candidate |
|
|
181
183
|
| `ads_capture_clear` | Remove generated captures or discard only the candidate |
|
|
182
184
|
| `ads_show_<id>` | Optional explicitly configured grouped App |
|
|
@@ -192,8 +194,9 @@ public exports from `components/`, `patterns/` and `controllers/`; it does not e
|
|
|
192
194
|
guess component props. Read the exported API and owning guide. An export name
|
|
193
195
|
alone does not prove that a preview renders that particular element.
|
|
194
196
|
|
|
195
|
-
`ads://project/status`, `/build`, `/tokens`, `/catalog`, `/scenarios
|
|
196
|
-
detail.
|
|
197
|
+
`ads://project/status`, `/build`, `/tokens`, `/catalog`, `/scenarios` and `/checks`
|
|
198
|
+
carry project JSON detail. Behavior discovery, execution outcomes and investigation
|
|
199
|
+
details are paged; their resource reads use the same bounds as their tools. Allowed project documentation/source and skill files are separate
|
|
197
200
|
resources. No arbitrary filesystem reader is exposed. Prefer bounded tools for
|
|
198
201
|
large catalogues; explicit resource reads can enter model context and a client
|
|
199
202
|
may truncate large payloads.
|
|
@@ -214,6 +217,14 @@ informational limit nor a traced target proves a rendered failure or success.
|
|
|
214
217
|
Bounded check results put warnings before informational limits; the checks
|
|
215
218
|
resource retains complete results.
|
|
216
219
|
|
|
220
|
+
`property-registration` is a blocking architecture diagnostic for invalid or
|
|
221
|
+
conflicting typed CSS registrations. Keep registrations in their runtime owner
|
|
222
|
+
or beside their real token definitions; `base.css` remains a closed reset contract.
|
|
223
|
+
Use `@reqvire-org/ads/linaria` in both product and preview extraction so each
|
|
224
|
+
registration survives intact in the App's CSS resources. Descriptor literals are
|
|
225
|
+
metadata; normal styling still uses tokens. Read `ads://guides/atomic-styles` for
|
|
226
|
+
ownership, valid initial values, browser checks and examples.
|
|
227
|
+
|
|
217
228
|
### Screenshots and candidate comparison
|
|
218
229
|
|
|
219
230
|
`ads_capture({scenario:"<discovered ID>",target?,theme?,viewport?})` renders current
|
|
@@ -248,8 +259,10 @@ limits, target declarations and the guarded review workflow.
|
|
|
248
259
|
|
|
249
260
|
Read `ads://guides/behaviors` or the [behavior guide](BEHAVIORS.md) for the contract
|
|
250
261
|
and runner schema. `ads_behaviors({ "unit": "components/MessageScroller" })`
|
|
251
|
-
|
|
252
|
-
|
|
262
|
+
pages an owner's checks by default; select `section: "subjects"`, `"guarantees"`,
|
|
263
|
+
`"demonstrations"` or `"profiles"` for other details. Without a unit it lists owner
|
|
264
|
+
summaries. Follow `nextCursor` with identical filters. Changed registrations or
|
|
265
|
+
evidence revisions invalidate discovery cursors. `ads_verify({ "unit": "components/MessageScroller", "checks": ["prepend-anchor"] })`
|
|
253
266
|
runs those registered cases. The names here are examples, never built-in cases.
|
|
254
267
|
|
|
255
268
|
`covers` describes rendered UI; optional `exercises` describes public behavioral
|
|
@@ -275,6 +288,51 @@ single failed assertion does not turn the other checks into failures. Overall
|
|
|
275
288
|
verification and guarded application still fail. Suite errors, unexplained exits,
|
|
276
289
|
missing results and interrupted reports cannot certify passing checks.
|
|
277
290
|
|
|
291
|
+
Verification and guarded-edit replies are summaries: counts, acceptance, at most
|
|
292
|
+
three failure previews and `resultId`, within 4096 UTF-8 JSON bytes. Use:
|
|
293
|
+
|
|
294
|
+
```js
|
|
295
|
+
ads_results({resultId: "<returned ID>", section: "outcomes", status: "not_passed"})
|
|
296
|
+
ads_results({resultId: "<returned ID>", section: "outcomes", status: "not_passed", cursor: "<nextCursor>"})
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Each listing defaults to 10 rows, allows at most 20 and stays within 8192 JSON
|
|
300
|
+
bytes. A byte-limited page can contain fewer than `limit` rows; follow
|
|
301
|
+
`nextCursor` with the same result ID, section and status. Other sections are
|
|
302
|
+
`checks`, `advisories`, `warnings`, `changes`, `captures`, `acceptance`,
|
|
303
|
+
`investigation` and `selection`. No page reruns validation. Rows marked
|
|
304
|
+
`detailTruncated` can be read exactly with `recordIndex`, `offset` and `chars`
|
|
305
|
+
(maximum 2000 UTF-16 characters); follow `nextOffset`. Read full logs only for the
|
|
306
|
+
relevant record. JSON also remains available through `ads://results/<resultId>`;
|
|
307
|
+
use matching query parameters for pages or ranges. `ads://project/results` lists
|
|
308
|
+
the latest IDs. Status embeds summaries, not complete runner reports. Saved
|
|
309
|
+
outcomes are completion-time evidence; compare revisions with `ads_behaviors`
|
|
310
|
+
before claiming current source passed.
|
|
311
|
+
|
|
312
|
+
Only the latest verification snapshot and latest mutation snapshot are retained,
|
|
313
|
+
independently, each up to 8 MiB in `.ds/tool-results/`. Replacing a snapshot makes
|
|
314
|
+
its old ID unavailable; do not mix pages across runs. An oversized report retains
|
|
315
|
+
only its summary and an explicit unavailable-details warning. A failed disk write
|
|
316
|
+
keeps details in server memory until shutdown. Neither condition changes guard
|
|
317
|
+
acceptance or whether source was applied. These are logical payload byte limits;
|
|
318
|
+
compatibility text can duplicate structured JSON in the MCP response.
|
|
319
|
+
|
|
320
|
+
For diagnosis, take one outcome's exact `unit`, `check` and `runId` and call
|
|
321
|
+
`ads_investigate`. The run ID rejects superseded evidence. Without a check, it
|
|
322
|
+
lists available investigations with paging. An exact check returns a summary
|
|
323
|
+
within 4096 JSON bytes; `section: "details"`, `"requests"`, `"browserErrors"` or `"artifacts"`
|
|
324
|
+
returns detail pages with the same 10/20-row and 8192-byte limits. Truncated records support
|
|
325
|
+
`recordIndex`/`offset`/`chars` with the exact `runId`; artifact URIs are read
|
|
326
|
+
separately. It never reruns checks, including rejected candidates.
|
|
327
|
+
`ads://project/investigations` lists available bundles; returned resource URIs expose the bundle and available registered
|
|
328
|
+
artifacts. Exact input/observed preview revisions, source/failing step, startup
|
|
329
|
+
viewport and failed requests separate evidence from a suspected cause.
|
|
330
|
+
The summary's `details.failure.category` distinguishes architecture, build,
|
|
331
|
+
transport, runner and assertion boundaries; `acceptance` names established and unverified scope.
|
|
332
|
+
Only the latest bundle per check remains resource-accessible. Read the portable
|
|
333
|
+
[evidence guide](../skills/ads-designer/references/evidence.md) for collection
|
|
334
|
+
limits and project-controlled trace/screenshot recording.
|
|
335
|
+
|
|
278
336
|
Browser profiles start an isolated showcase and verify its sandboxed App using
|
|
279
337
|
the selected candidate's sources. StrictMode profiles need a project React
|
|
280
338
|
development harness. Profiles describe the execution environment, not a proof
|
|
@@ -411,8 +469,9 @@ Pass that `patchFile` to `ads_apply_patch` with `dryRun:true` to validate before
|
|
|
411
469
|
applying. This runs the normal candidate gates, including affected registered
|
|
412
470
|
behavior checks against an isolated candidate and its configured browser preview.
|
|
413
471
|
It writes no live source and does not persist passing evidence for live inputs.
|
|
414
|
-
Read
|
|
415
|
-
|
|
472
|
+
Read the summary, then use its `resultId` with `ads_results` for failing
|
|
473
|
+
`outcomes`, `diagnostics` or named pipeline `checks`; update the draft, diff again
|
|
474
|
+
and repeat as needed. Apply with `dryRun:false` after validation;
|
|
416
475
|
the gates run again. `ads_verify({unit,checks?})` checks current source and accepts
|
|
417
476
|
no draft argument; a selected-check draft runner is not currently exposed.
|
|
418
477
|
Use `action:"discard"` to remove the draft. Remote clients can continue sending
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reqvire-org/ads",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.18",
|
|
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": {
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@modelcontextprotocol/server": "2.3.1",
|
|
55
|
+
"css-tree": "3.2.1",
|
|
55
56
|
"postcss": "^8.5.30",
|
|
56
57
|
"postcss-selector-parser": "^7.1.6",
|
|
57
58
|
"postcss-value-parser": "^4.2.0",
|