@reqvire-org/ads 0.3.15 → 0.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/showcase/client.bundle.js +18 -18
- package/dist/showcase/resource-reader.js +37 -0
- package/dist/skills/ads-break-ui/references/guarded-editing.md +12 -0
- package/dist/skills/ads-designer/references/guarded-editing.md +12 -0
- package/dist/skills/ads-import/references/guarded-editing.md +12 -0
- package/dist/skills/ads-migrate/references/guarded-editing.md +12 -0
- package/dist/skills/ads-motion/references/guarded-editing.md +12 -0
- package/dist/verification/browser.mjs +5 -1
- package/dist/verification/playwright-reporter.cjs +21 -1
- package/dist/verification.mjs +1 -0
- package/docs/ARCHITECTURE.md +9 -0
- package/docs/BEHAVIORS.md +17 -2
- package/docs/CHANGELOG.md +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const retryDelays = [200, 800];
|
|
2
|
+
const networkFailure = error => error?.name === "TypeError" && /^(Failed to fetch|fetch failed|Load failed|NetworkError when attempting to fetch resource\.)$/.test(error.message);
|
|
3
|
+
|
|
4
|
+
function pause(milliseconds, signal) {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
signal?.throwIfAborted();
|
|
7
|
+
const finish = () => { signal?.removeEventListener("abort", abort); resolve(); };
|
|
8
|
+
const timer = setTimeout(finish, milliseconds);
|
|
9
|
+
const abort = () => { clearTimeout(timer); signal.removeEventListener("abort", abort); reject(signal.reason); };
|
|
10
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** Only resources/read is repeatable here; never wrap tool calls or assertions. */
|
|
15
|
+
export function resourceReader(read, { signal, onDiagnostic, wait = pause } = {}) {
|
|
16
|
+
return async input => {
|
|
17
|
+
for (let attempt = 1; ; attempt++) {
|
|
18
|
+
signal?.throwIfAborted();
|
|
19
|
+
try {
|
|
20
|
+
const response = await read(input);
|
|
21
|
+
signal?.throwIfAborted();
|
|
22
|
+
if (attempt > 1) onDiagnostic?.({ state: "recovered", uri: input.uri, attempt });
|
|
23
|
+
return response;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
signal?.throwIfAborted();
|
|
26
|
+
if (!networkFailure(error)) throw error;
|
|
27
|
+
if (attempt > retryDelays.length) {
|
|
28
|
+
onDiagnostic?.({ state: "exhausted", uri: input.uri, attempt, message: error.message });
|
|
29
|
+
throw Object.assign(new Error(`MCP resource transport failed for ${input.uri} after ${attempt} attempts: ${error.message}. Inspect the host connection and browser network diagnostics; this resource-loading error does not establish a component assertion failure.`, { cause: error }), { code: "ADS_RESOURCE_TRANSPORT" });
|
|
30
|
+
}
|
|
31
|
+
const delayMs = retryDelays[attempt - 1];
|
|
32
|
+
onDiagnostic?.({ state: "retry", uri: input.uri, attempt, nextAttempt: attempt + 1, delayMs, message: error.message });
|
|
33
|
+
await wait(delayMs, signal);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -51,6 +51,18 @@ blanket sleeps. Fake clocks suit timer-only guarantees; keep real time for actua
|
|
|
51
51
|
gesture/motion/layout guarantees. Project settings belong in guarded configuration
|
|
52
52
|
changes; ADS does not silently raise budgets or override the worker count.
|
|
53
53
|
|
|
54
|
+
If a check cannot load its MCP preview, preserve the draft and inspect the exact
|
|
55
|
+
resource URI and failed browser requests before changing component code. The ADS
|
|
56
|
+
showcase retries a fetch transport failure on `resources/read` at most twice
|
|
57
|
+
(200/800 ms backoff); recovered startup reads remain visible in
|
|
58
|
+
`startupDiagnostics`. It never retries tool calls, assertions or complete checks,
|
|
59
|
+
and persistent failures still block application. HTTP/protocol/content errors,
|
|
60
|
+
integrity failures and cancellation do not retry. External hosts own their
|
|
61
|
+
transport behavior. Chrome's `ERR_NETWORK_CHANGED` does not prove an ADS restart
|
|
62
|
+
or identify Docker/VPN churn: correlate failure timestamps with live interface
|
|
63
|
+
events, Chrome network logs and server availability. Do not weaken checks or
|
|
64
|
+
rewrite a valid API to hide infrastructure failures.
|
|
65
|
+
|
|
54
66
|
Named barrel imports can narrow affected checks when the project accurately
|
|
55
67
|
declares package `sideEffects`; retain CSS/global effects in that policy. Missing
|
|
56
68
|
or unsupported policies and dynamic/wildcard dependencies stay conservative.
|
|
@@ -51,6 +51,18 @@ blanket sleeps. Fake clocks suit timer-only guarantees; keep real time for actua
|
|
|
51
51
|
gesture/motion/layout guarantees. Project settings belong in guarded configuration
|
|
52
52
|
changes; ADS does not silently raise budgets or override the worker count.
|
|
53
53
|
|
|
54
|
+
If a check cannot load its MCP preview, preserve the draft and inspect the exact
|
|
55
|
+
resource URI and failed browser requests before changing component code. The ADS
|
|
56
|
+
showcase retries a fetch transport failure on `resources/read` at most twice
|
|
57
|
+
(200/800 ms backoff); recovered startup reads remain visible in
|
|
58
|
+
`startupDiagnostics`. It never retries tool calls, assertions or complete checks,
|
|
59
|
+
and persistent failures still block application. HTTP/protocol/content errors,
|
|
60
|
+
integrity failures and cancellation do not retry. External hosts own their
|
|
61
|
+
transport behavior. Chrome's `ERR_NETWORK_CHANGED` does not prove an ADS restart
|
|
62
|
+
or identify Docker/VPN churn: correlate failure timestamps with live interface
|
|
63
|
+
events, Chrome network logs and server availability. Do not weaken checks or
|
|
64
|
+
rewrite a valid API to hide infrastructure failures.
|
|
65
|
+
|
|
54
66
|
Named barrel imports can narrow affected checks when the project accurately
|
|
55
67
|
declares package `sideEffects`; retain CSS/global effects in that policy. Missing
|
|
56
68
|
or unsupported policies and dynamic/wildcard dependencies stay conservative.
|
|
@@ -51,6 +51,18 @@ blanket sleeps. Fake clocks suit timer-only guarantees; keep real time for actua
|
|
|
51
51
|
gesture/motion/layout guarantees. Project settings belong in guarded configuration
|
|
52
52
|
changes; ADS does not silently raise budgets or override the worker count.
|
|
53
53
|
|
|
54
|
+
If a check cannot load its MCP preview, preserve the draft and inspect the exact
|
|
55
|
+
resource URI and failed browser requests before changing component code. The ADS
|
|
56
|
+
showcase retries a fetch transport failure on `resources/read` at most twice
|
|
57
|
+
(200/800 ms backoff); recovered startup reads remain visible in
|
|
58
|
+
`startupDiagnostics`. It never retries tool calls, assertions or complete checks,
|
|
59
|
+
and persistent failures still block application. HTTP/protocol/content errors,
|
|
60
|
+
integrity failures and cancellation do not retry. External hosts own their
|
|
61
|
+
transport behavior. Chrome's `ERR_NETWORK_CHANGED` does not prove an ADS restart
|
|
62
|
+
or identify Docker/VPN churn: correlate failure timestamps with live interface
|
|
63
|
+
events, Chrome network logs and server availability. Do not weaken checks or
|
|
64
|
+
rewrite a valid API to hide infrastructure failures.
|
|
65
|
+
|
|
54
66
|
Named barrel imports can narrow affected checks when the project accurately
|
|
55
67
|
declares package `sideEffects`; retain CSS/global effects in that policy. Missing
|
|
56
68
|
or unsupported policies and dynamic/wildcard dependencies stay conservative.
|
|
@@ -51,6 +51,18 @@ blanket sleeps. Fake clocks suit timer-only guarantees; keep real time for actua
|
|
|
51
51
|
gesture/motion/layout guarantees. Project settings belong in guarded configuration
|
|
52
52
|
changes; ADS does not silently raise budgets or override the worker count.
|
|
53
53
|
|
|
54
|
+
If a check cannot load its MCP preview, preserve the draft and inspect the exact
|
|
55
|
+
resource URI and failed browser requests before changing component code. The ADS
|
|
56
|
+
showcase retries a fetch transport failure on `resources/read` at most twice
|
|
57
|
+
(200/800 ms backoff); recovered startup reads remain visible in
|
|
58
|
+
`startupDiagnostics`. It never retries tool calls, assertions or complete checks,
|
|
59
|
+
and persistent failures still block application. HTTP/protocol/content errors,
|
|
60
|
+
integrity failures and cancellation do not retry. External hosts own their
|
|
61
|
+
transport behavior. Chrome's `ERR_NETWORK_CHANGED` does not prove an ADS restart
|
|
62
|
+
or identify Docker/VPN churn: correlate failure timestamps with live interface
|
|
63
|
+
events, Chrome network logs and server availability. Do not weaken checks or
|
|
64
|
+
rewrite a valid API to hide infrastructure failures.
|
|
65
|
+
|
|
54
66
|
Named barrel imports can narrow affected checks when the project accurately
|
|
55
67
|
declares package `sideEffects`; retain CSS/global effects in that policy. Missing
|
|
56
68
|
or unsupported policies and dynamic/wildcard dependencies stay conservative.
|
|
@@ -51,6 +51,18 @@ blanket sleeps. Fake clocks suit timer-only guarantees; keep real time for actua
|
|
|
51
51
|
gesture/motion/layout guarantees. Project settings belong in guarded configuration
|
|
52
52
|
changes; ADS does not silently raise budgets or override the worker count.
|
|
53
53
|
|
|
54
|
+
If a check cannot load its MCP preview, preserve the draft and inspect the exact
|
|
55
|
+
resource URI and failed browser requests before changing component code. The ADS
|
|
56
|
+
showcase retries a fetch transport failure on `resources/read` at most twice
|
|
57
|
+
(200/800 ms backoff); recovered startup reads remain visible in
|
|
58
|
+
`startupDiagnostics`. It never retries tool calls, assertions or complete checks,
|
|
59
|
+
and persistent failures still block application. HTTP/protocol/content errors,
|
|
60
|
+
integrity failures and cancellation do not retry. External hosts own their
|
|
61
|
+
transport behavior. Chrome's `ERR_NETWORK_CHANGED` does not prove an ADS restart
|
|
62
|
+
or identify Docker/VPN churn: correlate failure timestamps with live interface
|
|
63
|
+
events, Chrome network logs and server availability. Do not weaken checks or
|
|
64
|
+
rewrite a valid API to hide infrastructure failures.
|
|
65
|
+
|
|
54
66
|
Named barrel imports can narrow affected checks when the project accurately
|
|
55
67
|
declares package `sideEffects`; retain CSS/global effects in that policy. Missing
|
|
56
68
|
or unsupported policies and dynamic/wildcard dependencies stay conservative.
|
|
@@ -27,7 +27,11 @@ export async function openPreviewScenario(page, url, scenario, { timeout = 30000
|
|
|
27
27
|
while (Date.now() < end) {
|
|
28
28
|
for (const frame of page.frames().filter(frame => frame !== page.mainFrame())) {
|
|
29
29
|
const state = await frame.evaluate(() => ({ state: document.documentElement.dataset.adsPreviewState, id: document.documentElement.dataset.adsScenario, message: document.getElementById("ads-preview-status")?.textContent })).catch(() => ({}));
|
|
30
|
-
if (state.id === scenario && state.state === "ready")
|
|
30
|
+
if (state.id === scenario && state.state === "ready") {
|
|
31
|
+
const retries = await page.evaluate(() => Number(document.documentElement.dataset.adsResourceRetries ?? 0)).catch(() => 0);
|
|
32
|
+
if (retries > 0) console.warn(JSON.stringify({ adsPreviewDiagnostic: { kind: "resource-read-recovery", scenario, retries, failedRequests: failures } }));
|
|
33
|
+
return frame;
|
|
34
|
+
}
|
|
31
35
|
if (state.id === scenario && state.state === "error") throw new Error(state.message || "The MCP App failed before verification.");
|
|
32
36
|
}
|
|
33
37
|
const error = await page.evaluate(() => document.querySelector('#status[data-error="true"]')?.textContent).catch(() => null);
|
|
@@ -8,6 +8,8 @@ module.exports = class AdsBehaviorReporter {
|
|
|
8
8
|
this.cases = [];
|
|
9
9
|
this.errors = [];
|
|
10
10
|
this.active = new Map();
|
|
11
|
+
this.diagnostics = new Map();
|
|
12
|
+
this.diagnosticBuffers = new Map();
|
|
11
13
|
this.startedAt = Date.now();
|
|
12
14
|
this.totalTests = 0;
|
|
13
15
|
}
|
|
@@ -22,9 +24,27 @@ module.exports = class AdsBehaviorReporter {
|
|
|
22
24
|
}
|
|
23
25
|
onTestEnd(test, result) {
|
|
24
26
|
this.active.delete(test.id);
|
|
25
|
-
|
|
27
|
+
const diagnostics = this.diagnostics.get(test.id);
|
|
28
|
+
for (const entry of this.entries(test)) this.cases.push({ ...entry, status: result.status === "passed" && test.expectedStatus === "passed" ? "passed" : ["skipped", "interrupted"].includes(result.status) ? "skipped" : "failed", durationMs: result.duration, workerIndex: result.workerIndex, retry: result.retry, completedAt: new Date().toISOString(), ...(diagnostics?.length ? { diagnostics } : {}), message: result.errors?.map(error => error.message || error.stack || error.value || "The browser runner reported an error without details.").join("\n").slice(0, 1000) });
|
|
29
|
+
this.diagnostics.delete(test.id);
|
|
30
|
+
this.diagnosticBuffers.delete(test.id);
|
|
26
31
|
this.publish();
|
|
27
32
|
}
|
|
33
|
+
onStdErr(chunk, test) {
|
|
34
|
+
if (!test) return;
|
|
35
|
+
const lines = ((this.diagnosticBuffers.get(test.id) ?? "") + String(chunk)).split("\n");
|
|
36
|
+
this.diagnosticBuffers.set(test.id, lines.pop().slice(-4000));
|
|
37
|
+
for (const line of lines) {
|
|
38
|
+
if (line.length > 4000) continue;
|
|
39
|
+
try {
|
|
40
|
+
const diagnostic = JSON.parse(line).adsPreviewDiagnostic;
|
|
41
|
+
if (diagnostic?.kind !== "resource-read-recovery" || typeof diagnostic.scenario !== "string" || !Number.isSafeInteger(diagnostic.retries) || diagnostic.retries < 1) continue;
|
|
42
|
+
const collected = this.diagnostics.get(test.id) ?? [];
|
|
43
|
+
if (collected.length < 5) collected.push({ kind: diagnostic.kind, scenario: diagnostic.scenario.slice(0, 300), retries: diagnostic.retries, failedRequests: (Array.isArray(diagnostic.failedRequests) ? diagnostic.failedRequests : []).slice(0, 5).map(value => String(value).slice(0, 500)) });
|
|
44
|
+
this.diagnostics.set(test.id, collected);
|
|
45
|
+
} catch { /* Ordinary test output is not an ADS startup diagnostic. */ }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
28
48
|
onError(error) {
|
|
29
49
|
if (this.errors.length < 5) this.errors.push(String(error.message || error.stack || error.value || "The browser runner reported a suite error without details.").slice(0, 4000));
|
|
30
50
|
this.publish();
|
package/dist/verification.mjs
CHANGED
|
@@ -310,6 +310,7 @@ export function createVerificationController(root, { reportRoot = root, onProgre
|
|
|
310
310
|
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(),
|
|
311
311
|
previewRevision: profile.mode === "browser" ? host?.previewRevision() ?? readPreviewManifest(options)?.revision ?? null : null,
|
|
312
312
|
...(matches.length ? { reportedStatus, durationMs: matches.reduce((sum, item) => sum + (Number.isFinite(item.durationMs) ? Math.max(0, item.durationMs) : 0), 0) } : {}),
|
|
313
|
+
...(matches.some(item => item.diagnostics?.length) ? { startupDiagnostics: matches.flatMap(item => Array.isArray(item.diagnostics) ? item.diagnostics.slice(0, 5) : []).slice(0, 10) } : {}),
|
|
313
314
|
...(runnerFailure ? { runnerExitCode: run.code } : {}),
|
|
314
315
|
execution: progress.cases.find(item => item.unit === check.unit && item.check === check.id)?.state,
|
|
315
316
|
message: [matches.filter(item => item.status !== "passed").map(item => String(item.message || `Case reported ${item.status} without a diagnostic.`).slice(0, 2000)).join("\n"), runnerError ? `${runnerError.message} This check ${matches.length ? `reported ${reportedStatus}` : `was ${progress.cases.find(item => item.unit === check.unit && item.check === check.id)?.state ?? "not reported"}`}; the complete run did not pass.` : !matches.length ? "The selected case did not execute/report. Missing and skipped cases do not pass." : runnerFailure ? `This case reported ${reportedStatus}, but the complete run did not pass. ${runnerFailure}` : ""].filter(Boolean).join("\n"), report: slash(path.relative(reportRoot, report)) });
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -229,6 +229,15 @@ scenarios unmounts the previous view while keeping unchanged dependencies cached
|
|
|
229
229
|
Persistence is a host lifecycle choice; a new external widget loads the same
|
|
230
230
|
resources independently. Resource sharing is scoped to an App instance.
|
|
231
231
|
|
|
232
|
+
The showcase's resource bridge can recover a transient fetch failure with at most
|
|
233
|
+
three read attempts and bounded backoff. This applies only to `resources/read`;
|
|
234
|
+
tool calls, assertions and whole checks are never replayed. Cancellation,
|
|
235
|
+
HTTP/protocol/content errors and integrity failures remain failures. Browser
|
|
236
|
+
diagnostics record retries, and verification retains recovered startup reads in
|
|
237
|
+
its case results. Persistent transport failures still block a mutation. External
|
|
238
|
+
hosts own their transport recovery; the reusable App's integrity checks remain
|
|
239
|
+
the same.
|
|
240
|
+
|
|
232
241
|
Managed graph builders publish into a private session directory beside the
|
|
233
242
|
configured manifest. Logical scenario IDs and resource URIs stay unchanged;
|
|
234
243
|
standalone builds retain the configured output and cannot overwrite a live
|
package/docs/BEHAVIORS.md
CHANGED
|
@@ -169,8 +169,23 @@ pass, even if all reported cases claim success. Results retain `reportedStatus`
|
|
|
169
169
|
and `runnerExitCode` and explain the overall failure. Suite-level browser errors and
|
|
170
170
|
bounded runner output appear in diagnostics. `openBehaviorScenario` includes the
|
|
171
171
|
scenario ID and failed browser requests in startup failures; App resource errors
|
|
172
|
-
identify the resource URI.
|
|
173
|
-
|
|
172
|
+
identify the resource URI. The ADS showcase retries only `resources/read` fetch
|
|
173
|
+
transport failures, with at most three attempts and 200/800 ms backoff. Recovered
|
|
174
|
+
startup reads appear in `startupDiagnostics` with retry counts and failed browser
|
|
175
|
+
requests; each retry is also logged in the browser console. This does not retry a
|
|
176
|
+
tool call, assertion, check or complete startup. HTTP/protocol/content errors,
|
|
177
|
+
integrity failures and cancellations do not retry. Persistent loading failures
|
|
178
|
+
still fail the check and block mutations. External hosts control their own
|
|
179
|
+
transport recovery.
|
|
180
|
+
|
|
181
|
+
`net::ERR_NETWORK_CHANGED` reports Chrome's network-change error, not proof that
|
|
182
|
+
the MCP endpoint restarted or that a particular interface changed. To investigate
|
|
183
|
+
an intermittent failure, correlate the saved case timestamps with Chrome's
|
|
184
|
+
network log, server availability and live interface monitoring (for example,
|
|
185
|
+
`ip -ts monitor link address route` on Linux). Interfaces being present, or stable
|
|
186
|
+
after a failure, does not establish the cause. Preserve the draft and original
|
|
187
|
+
diagnostic; do not change a component API, reference example or verification
|
|
188
|
+
policy to compensate for a resource-loading failure.
|
|
174
189
|
|
|
175
190
|
The reporter atomically publishes partial snapshots at test start/end. While a
|
|
176
191
|
run is active, `ads_status.behaviors.progress` exposes the profile, runner budget,
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.16
|
|
4
|
+
|
|
5
|
+
- Recover transient showcase MCP resource fetch failures with bounded read-only
|
|
6
|
+
retries. Keep tool calls, assertions, checks and non-transport failures outside
|
|
7
|
+
recovery; expose recovered startup reads in verification diagnostics and keep
|
|
8
|
+
persistent loading failures blocking. Verify interrupted resource delivery and
|
|
9
|
+
failed delivery against a dummy App, without changing project verification policy.
|
|
10
|
+
|
|
3
11
|
## 0.3.15
|
|
4
12
|
|
|
5
13
|
- Keep fragment links inside inline preview documents by supplying a local
|