Skip to content
This repository was archived by the owner on Oct 27, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions site/analytics.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// configured at build time; email_click is the primary intake path.
const allowedEvents = new Set([
"booking_click",
"demo_key_click",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bump the analytics cache key for the new event

The deployment caches analytics.js for seven days, but the homepage still loads it with the existing ?v=home-light-1 token. Returning visitors with the prior script cached will therefore keep the old allowlist and silently reject demo_key_click until expiry; bump the homepage analytics URL when adding this allowlist entry.

Useful? React with 👍 / 👎.

"email_click",
"proof_click",
]);
Expand Down
22 changes: 3 additions & 19 deletions site/home-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
const budget = byId("home-key-budget");
const retry = byId("home-key-retry");
const email = byId("home-key-email");
const quickstart = byId("home-quickstart-code");
const copyQuickstart = byId("home-copy-quickstart");
const copyStatus = byId("home-copy-status");
const quickstartTemplate = quickstart.textContent;
const heroQuickstart = byId("home-hero-python");
const heroQuickstartTemplate = heroQuickstart.textContent;
const copyHeroQuickstart = byId("home-hero-python-copy");
Expand Down Expand Up @@ -82,9 +78,7 @@
key.type = "password";
wallet.type = "password";
budget.textContent = String(data.budget_credits);
quickstart.textContent = fillQuickstart(quickstartTemplate, data);
heroQuickstart.textContent = fillQuickstart(heroQuickstartTemplate, data);
copyQuickstart.disabled = false;
copyHeroQuickstart.disabled = false;
title.textContent = "Your demo key is ready";
status.textContent = "Your demo key is ready";
Expand Down Expand Up @@ -188,17 +182,7 @@
copy(`export AMW_API_KEY=${shellQuote(key.value)}\nexport AMW_WALLET_ID=${shellQuote(wallet.value)}`,
"Key and wallet commands copied.", key, status,
"Copy was unavailable. Copy Key and Wallet separately."));
copyQuickstart.addEventListener("click", () =>
copy(quickstart.textContent, "Quickstart copied.", quickstart, copyStatus));
for (const [buttonId, codeId] of [
["home-hero-python-copy", "home-hero-python"],
["home-hero-curl-copy", "home-hero-curl"],
]) {
const button = byId(buttonId);
const code = byId(codeId);
if (button && code) {
button.addEventListener("click", () =>
copy(code.textContent, "Commands copied.", code, byId("home-hero-copy-status")));
}
}
copyHeroQuickstart.addEventListener("click", () =>
copy(heroQuickstart.textContent, "Commands copied.", heroQuickstart,
byId("home-hero-copy-status")));
})();
43 changes: 16 additions & 27 deletions site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
<script defer src="/arcade-boot.js?v=home-light-1"></script>
<script defer src="/analytics.js?v=home-light-1"></script>
<script defer src="/utm-capture.js?v=home-light-1"></script>
<script defer src="/home-key.js?v=home-light-2"></script>
<script defer src="/home-key.js?v=home-light-3"></script>
<script defer src="/a11y.js?v=home-light-1"></script>
</head>
<body class="home-light site-light">
Expand All @@ -196,9 +196,10 @@
<div class="hero-v2-inner">
<div class="hero-v2-intro">
<h1>Let agents retry safely.</h1>
<p>One accepted request key permits at most one gateway dispatch to the configured upstream tool and at most one debit. Each finalized or reconciled path has a receipt.</p>
<p>Each action runs once and leaves a receipt.</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Limit the hero promise to at-most-one dispatch

For denied, expired, or over-budget requests, the tool runs zero times, while a delivery_uncertain request may have completed but cannot be proven either way. This unconditional headline therefore contradicts the limits stated later on the page and overstates the actual guarantee; describe the at-most-one configured-upstream dispatch and debit instead.

AGENTS.md reference: AGENTS.md:L62-L71

Useful? React with 👍 / 👎.

<p class="hero-v2-boundary">One accepted request key permits at most one gateway dispatch to the configured upstream tool and at most one debit. Each finalized or reconciled path has a receipt.</p>
<div class="hero-v2-actions">
<button class="hero-v2-action hero-v2-action-primary" id="home-key-trigger" type="button" aria-controls="home-key-panel" hidden>Get a demo key</button>
<button class="hero-v2-action hero-v2-action-primary" id="home-key-trigger" type="button" aria-controls="home-key-panel" data-analytics-event="demo_key_click" hidden>Get a demo key</button>
<noscript><a class="hero-v2-action hero-v2-action-primary" href="/demo-key/">Get a demo key</a></noscript>
<a class="hero-v2-action hero-v2-action-secondary" href="https://github.com/agentmiddleware/amw-demo" rel="noopener noreferrer">Run the quickstart: amw-demo <span aria-hidden="true">→</span></a>
</div>
Expand All @@ -219,11 +220,12 @@ <h1>Let agents retry safely.</h1>
python examples/permit_echo_retry.py</code></pre>
<button id="home-hero-python-copy" type="button" aria-label="Copy Python commands" disabled>Copy</button>
</div>
<div class="hero-v2-command-row hero-v2-curl-row">
<pre id="home-hero-curl" tabindex="0"><code>curl -s -X POST https://api.thisisatest.tech/v1/demo/keys</code></pre>
<button id="home-hero-curl-copy" type="button" aria-label="Copy curl command">Copy</button>
<div class="hero-v2-command-row hero-v2-output" aria-label="Example output">
<p>Example output</p>
<pre tabindex="0"><code>receipt_id: rcpt_7Kq2mX9
Same receipt. The tool did not run again.</code></pre>
Comment on lines +225 to +226

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the example output at the gateway boundary

When an upstream tool performs internal retries or the original dispatch has an ambiguous outcome, replaying the same receipt establishes that the gateway did not dispatch again, not that the tool itself did not run again. The page's own receipt definition also says it does not prove the downstream effect, so this output should retain the gateway-scoped wording rather than presenting an unverifiable tool-side conclusion.

AGENTS.md reference: AGENTS.md:L62-L71

Useful? React with 👍 / 👎.

</div>
<p class="hero-v2-code-note">The button above fills these Python commands with a demo key. With curl, replace both export placeholders using <code>api_key</code> and <code>wallet_id</code> from the response.</p>
<p class="hero-v2-code-note">Get a demo key to fill the Python commands with your key and wallet ID.</p>
<p class="hero-v2-copy-status" id="home-hero-copy-status" role="status" aria-live="polite"></p>
</section>
<section class="hero-v2-flow" aria-label="Four step request flow">
Expand Down Expand Up @@ -292,26 +294,13 @@ <h2 id="home-key-title">Get your demo key</h2>

<section class="home-v2-section home-v2-how" id="how-it-works" aria-labelledby="how-title" data-wave="order">
<div class="home-v2-section-heading"><p>How it works</p><h2 id="how-title">From demo key to checked receipt</h2></div>
<div class="home-v2-steps">
<article class="home-v2-guide-step"><span class="home-v2-guide-number">1</span><div><h3>Get a demo key</h3><p>Use the button above. Save both <code>api_key</code> and <code>wallet_id</code> for the demo call.</p></div></article>
<article class="home-v2-guide-step" id="quickstart"><span class="home-v2-guide-number">2</span><div><h3>Set up</h3><p>Run the Python example with your demo key and wallet. It needs Python 3.10 or newer.</p>
<div class="home-code-panel">
<div class="home-code-toolbar"><span>Python</span><button id="home-copy-quickstart" type="button" disabled>Copy setup</button></div>
<pre class="home-code-scroll" tabindex="0"><code id="home-quickstart-code" tabindex="-1">git clone https://github.com/agentmiddleware/amw-demo.git
cd amw-demo
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
export AMW_API_KEY='YOUR_DEMO_KEY'
export AMW_WALLET_ID='YOUR_WALLET_ID'
python examples/permit_echo_retry.py</code></pre>
<p class="home-code-help" id="home-copy-status" role="status" aria-live="polite">Get a demo key to fill in the two export lines.</p>
</div>
</div></article>
<article class="home-v2-guide-step"><span class="home-v2-guide-number">3</span><div><h3>First call returns a receipt</h3><p>The example creates a permit and calls <code>partner.echo</code> through the gateway. It prints a receipt ID for the result.</p></div></article>
<article class="home-v2-guide-step"><span class="home-v2-guide-number">4</span><div><h3>Retry with the same request key</h3><p>For an accepted request key on the configured upstream tool, a retry with the same key returns the original receipt instead of dispatching again. The receipt does not prove what happened inside the tool.</p></div></article>
<article class="home-v2-guide-step"><span class="home-v2-guide-number">5</span><div><h3>Check the receipt offline</h3><p>The example fetches the receipt and public keys, then checks the signature on your machine. <a href="/proof/">See a published sample and verifier.</a></p></div></article>
</div>
<ul class="home-v2-steps">
<li>Get a demo key and save the API key and wallet ID.</li>
<li id="quickstart">Set the key and wallet ID in the Python commands above, then run the example.</li>
<li>The first call creates a permit and prints the receipt ID.</li>
<li>For an accepted request key on the configured upstream tool, a retry with the same key returns the original receipt instead of dispatching again.</li>
<li>Check the receipt signature offline. <a href="/proof/">See a published sample and verifier.</a></li>
</ul>
</section>

<section class="home-v2-section home-v2-limits" id="limits" aria-labelledby="limits-title" data-wave="quiet">
Expand Down
110 changes: 37 additions & 73 deletions site/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -2669,6 +2669,12 @@ body.home-light .hero-v2-intro > p {
font-size: 1.1875rem;
letter-spacing: -0.018em;
}
body.home-light .hero-v2-intro > .hero-v2-boundary {
margin-top: 5px;
font-size: 0.875rem;
line-height: 1.5;
letter-spacing: 0;
}
body.home-light .hero-v2-actions {
display: flex;
flex-wrap: wrap;
Expand Down Expand Up @@ -2744,7 +2750,7 @@ body.home-light .hero-v2-tab-disabled {
}
body.home-light .hero-v2-tab-disabled span {
padding: 3px 6px;
border: 1px solid var(--home-line);
border: 1px solid #6b7280;
border-radius: 4px;
font-size: 0.625rem;
}
Expand All @@ -2771,23 +2777,29 @@ body.home-light .hero-v2-command-row button {
cursor: pointer;
}
body.home-light .hero-v2-command-row button:disabled { cursor: not-allowed; opacity: 0.55; }
body.home-light .hero-v2-curl-row {
margin: 18px 23px 0;
body.home-light .hero-v2-output {
margin: 16px 23px 0;
border-top: 1px solid var(--home-line);
}
body.home-light .hero-v2-curl-row pre { padding: 14px 64px 0 0; line-height: 1.375rem; }
body.home-light .hero-v2-curl-row button { top: 6px; right: -8px; }
body.home-light .hero-v2-output p {
margin: 12px 0 0;
color: var(--home-muted);
font-size: 0.75rem;
}
body.home-light .hero-v2-command-row.hero-v2-output pre {
padding: 8px 0 0;
line-height: 1.5;
white-space: pre-wrap;
}
body.home-light .hero-v2-code-note {
margin: 16px 23px 0;
max-width: none;
color: var(--home-muted);
font-size: 0.75rem;
}
body.home-light .hero-v2-copy-status {
position: absolute;
right: 23px;
bottom: 7px;
margin: 0;
margin: 6px 23px 0;
min-height: 1rem;
color: var(--home-muted);
font-size: 0.6875rem;
}
Expand Down Expand Up @@ -3031,78 +3043,33 @@ body.home-light .home-v2-section-heading > p {
font-weight: 600;
}
body.home-light .home-v2-section-heading h2 { margin: 0 0 30px; font-size: 2.375rem; }
body.home-light .home-v2-guide-step {
display: grid;
grid-template-columns: 34px minmax(0, 1fr);
gap: 18px;
padding: 20px 0;
border-top: 1px solid var(--home-line);
body.home-light .home-v2-steps {
margin: 0;
padding: 0;
list-style: none;
}
body.home-light .home-v2-guide-number {
body.home-light .home-v2-steps li {
display: grid;
place-items: center;
width: 32px;
height: 32px;
border: 1px solid var(--home-line);
border-radius: 6px;
grid-template-columns: 24px minmax(0, 1fr);
gap: 12px;
padding: 16px 0;
border-top: 1px solid var(--home-line);
color: var(--home-muted);
font-size: 0.75rem;
font-weight: 600;
font-size: 0.9375rem;
line-height: 1.6;
}
body.home-light .home-v2-steps li::before {
content: "✓";
color: var(--home-blue);
font-weight: 700;
}
body.home-light .home-v2-guide-step h3 { margin: 2px 0 8px; font-size: 1.125rem; }
body.home-light .home-v2-guide-step p,
body.home-light .home-v2-limits > p,
body.home-light .home-v2-source > p {
max-width: 76ch;
color: var(--home-muted);
font-size: 0.9375rem;
line-height: 1.6;
}
body.home-light .home-code-panel {
max-width: 850px;
margin-top: 18px;
overflow: hidden;
border: 1px solid var(--home-line);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checklist link breaks grid layout

Medium Severity

The How it works checklist lays out each li as a two-column grid with a ::before checkmark, but the last step also has a direct child a. That link becomes its own grid item and drops onto the next row in the 24px marker column, so the proof-page CTA no longer sits in the step text.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit eb81a90. Configure here.

border-radius: 10px;
background: var(--home-soft);
box-shadow: none;
}
body.home-light .home-code-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
min-height: 46px;
padding: 0 18px;
border-bottom: 1px solid var(--home-line);
font-size: 0.75rem;
font-weight: 600;
}
body.home-light .home-code-toolbar button {
padding: 5px 9px;
border: 1px solid var(--home-line);
border-radius: 5px;
background: var(--home-bg);
color: var(--home-muted);
font: 600 0.6875rem "Public Sans", sans-serif;
cursor: pointer;
}
body.home-light .home-code-toolbar button:disabled { cursor: not-allowed; opacity: 0.55; }
body.home-light .home-code-scroll {
margin: 0;
overflow-x: auto;
padding: 18px 23px;
color: var(--home-text);
font-size: 0.8125rem;
line-height: 1.55;
}
body.home-light .home-code-help {
margin: 0;
padding: 0.55rem 1.4rem;
border-top: 1px solid var(--home-line);
color: var(--home-muted);
font-size: 0.75rem;
}
body.home-light .home-v2-section a { text-decoration: underline; }
body.home-light .home-v2-source { padding-bottom: 90px; }
body.home-light .home-v2-source a { overflow-wrap: anywhere; }
Expand Down Expand Up @@ -3130,15 +3097,12 @@ body.home-light .home-v2-source a { overflow-wrap: anywhere; }
align-self: flex-end;
margin: 8px 14px 0;
}
body.home-light .hero-v2-curl-row { margin-top: 12px; }
body.home-light .hero-v2-code-note { margin-top: 12px; }
body.home-light .hero-v2-copy-status { position: static; margin: 6px 23px 0; }
body.home-light .hero-v2-flow { grid-template-columns: minmax(0, 1fr); }
body.home-light .hero-v2-step { min-height: 0; }
body.home-light .home-v2-glossary { grid-template-columns: minmax(0, 1fr); min-height: 0; }
body.home-light .home-v2-glossary article { min-height: 0; }
body.home-light .home-v2-section { padding-top: 50px; padding-bottom: 50px; }
body.home-light .home-v2-guide-step { gap: 12px; }
body.home-light .home-key-drawer { padding: 84px 24px 24px; }
}

Expand Down
55 changes: 55 additions & 0 deletions site/test_analytics.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { createContext, runInContext } from "node:vm";

const script = readFileSync(new URL("./analytics.js", import.meta.url), "utf8");
const homeHtml = readFileSync(new URL("./index.html", import.meta.url), "utf8");

function analyticsPage(analyticsEnabled) {
const sent = [];
let click;
const context = createContext({
document: {
addEventListener(name, listener) {
assert.equal(name, "click");
click = listener;
},
},
window: analyticsEnabled ? {
va(...args) { sent.push(JSON.parse(JSON.stringify(args))); },
} : {},
});
runInContext(script, context, { filename: "analytics.js" });
return {
sent,
click(eventName) {
click({
target: {
closest(selector) {
assert.equal(selector, "[data-analytics-event]");
return eventName ? { dataset: { analyticsEvent: eventName } } : null;
},
},
});
},
};
}

test("homepage demo key button emits one existing analytics event per click", () => {
assert.match(homeHtml, /<button[^>]*id="home-key-trigger"[^>]*data-analytics-event="demo_key_click"[^>]*>/);
const page = analyticsPage(true);
page.click("demo_key_click");
assert.deepEqual(page.sent, [["event", { name: "demo_key_click" }]]);
});

test("analytics stays silent without opt in and rejects unknown event names", () => {
const disabled = analyticsPage(false);
disabled.click("demo_key_click");
assert.deepEqual(disabled.sent, []);

const enabled = analyticsPage(true);
enabled.click("receipt_verified");
enabled.click("");
assert.deepEqual(enabled.sent, []);
});
3 changes: 2 additions & 1 deletion site/test_home_contrast.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ test("homepage surfaces and controls use the contrast aware palette", () => {
["body.home-light .hero-v2-action-primary,\nbody.home-light #main .hero-v2-action-primary", "color", "var(--home-primary-text)"],
["body.home-light .hero-v2-code", "background", "var(--home-soft)"],
["body.home-light .hero-v2-command-row button", "border", "1px solid var(--home-line)"],
["body.home-light .hero-v2-tab-disabled span", "border", "1px solid #6b7280"],
["body.home-light .hero-v2-step", "background", "var(--home-bg)"],
["body.home-light .hero-v2-intro > p", "color", "var(--home-muted)"],
["body.home-light .hero-v2-intro > .hero-v2-boundary", "font-size", "0.875rem"],
["body.home-light .home-key-drawer", "background", "var(--home-bg)"],
["body.home-light .home-key-field-row", "border", "1px solid var(--home-line)"],
["body.home-light .home-key-field-row button", "color", "var(--home-muted)"],
["body.home-light .home-v2-glossary", "background", "var(--home-soft)"],
["body.home-light .home-code-toolbar button", "background", "var(--home-bg)"],
]) {
assert.equal(rule(selector)[property], value, `${selector} ${property}`);
}
Expand Down
Loading
Loading