agent-led-growth 0.0.0-stage → 0.6.0
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/.claude-plugin/marketplace.json +16 -0
- package/.claude-plugin/plugin.json +19 -0
- package/AGENTS.md +14 -0
- package/CHANGELOG.md +361 -0
- package/LICENSE +21 -0
- package/README.md +220 -2
- package/bin/cli.js +950 -0
- package/package.json +60 -4
- package/skills/alg/SKILL.md +65 -0
- package/skills/alg-test/SKILL.md +70 -0
- package/src/audit/config.js +83 -0
- package/src/audit/index.js +181 -0
- package/src/audit/prompts.js +311 -0
- package/src/audit/questions.js +89 -0
- package/src/audit/render.js +171 -0
- package/src/audit/standards.js +92 -0
- package/src/crash/smoke.js +210 -0
- package/src/dashboard/strip.js +39 -0
- package/src/harness/execute.js +201 -0
- package/src/harness/executors/claude-print.js +174 -0
- package/src/harness/executors/identity-guard.mjs +23 -0
- package/src/harness/index.js +96 -0
- package/src/harness/mail.js +72 -0
- package/src/harness/onboarding.js +234 -0
- package/src/harness/persona.js +25 -0
- package/src/harness/reconcile.js +109 -0
- package/src/harness/secrets.js +111 -0
- package/src/harness/tasks/agentmail-send.js +94 -0
- package/src/harness/tasks/pay-stripe-projects.js +210 -0
- package/src/harness/tasks/pay-x402.js +204 -0
- package/src/harness/tasks/signup.js +326 -0
- package/src/harness/tasks/stripe-subscription.js +111 -0
- package/src/harness/tasks/tanso-oss.js +150 -0
- package/src/history/index.js +42 -0
- package/src/index.js +8 -0
- package/src/interface/evaluate.js +355 -0
- package/src/interface/evidence.js +80 -0
- package/src/interface/extract.js +231 -0
- package/src/interface/funnel.js +237 -0
- package/src/interface/index.js +47 -0
- package/src/interface/journey.js +93 -0
- package/src/interface/onboarding.js +401 -0
- package/src/interface/purchase.js +270 -0
- package/src/interface/schema.js +101 -0
- package/src/interface/sources.js +281 -0
- package/src/probe/http.js +63 -0
- package/src/probe/index.js +263 -0
- package/src/probe/pricing.schema.json +377 -0
- package/src/report/captions.js +52 -0
- package/src/report/delta.js +83 -0
- package/src/report/demo.js +248 -0
- package/src/report/format.js +20 -0
- package/src/report/hero.js +262 -0
- package/src/report/html.js +242 -0
- package/src/report/index.js +62 -0
- package/src/report/md.js +93 -0
- package/src/report/merge.js +156 -0
- package/src/report/replay.js +156 -0
- package/src/report/video.js +151 -0
- package/src/report/web.js +182 -0
- package/src/scan/index.js +93 -0
- package/src/schema/ids.js +42 -0
- package/src/schema/map.js +134 -0
- package/src/schema/stages.js +85 -0
- package/src/schema/validate.js +114 -0
- package/src/verify/index.js +210 -0
- package/src/verify/infer.js +248 -0
- package/src/verify/journey.js +42 -0
- package/src/verify/render.js +76 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-led-growth",
|
|
3
|
+
"description": "agent-led-growth skills for Claude Code",
|
|
4
|
+
"owner": {
|
|
5
|
+
"name": "Kat Laszlo",
|
|
6
|
+
"url": "https://github.com/katrinalaszlo"
|
|
7
|
+
},
|
|
8
|
+
"plugins": [
|
|
9
|
+
{
|
|
10
|
+
"name": "agent-led-growth",
|
|
11
|
+
"description": "Check whether agents can sign up for and use your product, and test it with a real agent.",
|
|
12
|
+
"source": "./",
|
|
13
|
+
"category": "development"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-led-growth",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Check whether an AI agent can sign up for and use your product: check its public pages for free, or test it with a real agent that signs up and has its key checked.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Kat Laszlo",
|
|
7
|
+
"url": "https://github.com/katrinalaszlo"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/katrinalaszlo/agent-led-growth-cli",
|
|
10
|
+
"repository": "https://github.com/katrinalaszlo/agent-led-growth-cli",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"agents",
|
|
14
|
+
"onboarding",
|
|
15
|
+
"signup",
|
|
16
|
+
"audit",
|
|
17
|
+
"llms.txt"
|
|
18
|
+
]
|
|
19
|
+
}
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Using alg on a product
|
|
4
|
+
|
|
5
|
+
- To check a product, follow `skills/alg/SKILL.md`: `npx agent-led-growth check <url> --json --yes`. It reads public pages only and costs nothing.
|
|
6
|
+
- To test a product with a real agent, follow `skills/alg-test/SKILL.md`, and only when the developer asks. `test --check` is free; a real `test` creates an account on the product and spends the developer's Claude Code model use (capped by `--max-budget-usd`, default 5).
|
|
7
|
+
|
|
8
|
+
## Working on this code
|
|
9
|
+
|
|
10
|
+
- Node 20.9 or later, ES modules, no build step for the CLI. `npm test` runs every test with `node --test`.
|
|
11
|
+
- `bin/cli.js` defines the commands. `src/audit/` is `check`, `src/verify/` is `test`, `src/harness/` runs the agent (`claude -p`) and scrubs secrets, `src/interface/` reads a product's public pages.
|
|
12
|
+
- The `--json` documents (`agent-ready/audit-report@1`, `agent-ready/verify@1`, `agent-ready/verify-plan@1`, `agent-ready/error@1`), exit codes and `alg.yml` keys are contracts for agents and CI. Change one only with a CHANGELOG entry.
|
|
13
|
+
- The two skills and the README quote flags, defaults and limits from the code. When you change one in the code, change it there too.
|
|
14
|
+
- Keep `.claude-plugin/plugin.json`'s `version` equal to `package.json`'s; a test checks it.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0 (2026-10-22)
|
|
4
|
+
|
|
5
|
+
- One name. The command is `alg` (`npx agent-led-growth` still runs it); the config file is `alg.yml` and the run folder `.alg/`. The skills are `alg` and `alg-test`, the plugin `agent-led-growth`. `agent-ready`, `agent-ready.yml` and `.agent-ready/` are gone.
|
|
6
|
+
- Output first. `check` shows the seven steps in seconds by default; the five third-party benchmarks now run only with `--standards` (they were on by default and took 1-3 minutes). The README opens with a real result.
|
|
7
|
+
- Shorter help. One line per command and flag; `execute` is hidden from the top level (`alg execute --help` still works). The three onboarding flags say what they answer instead of "the first question".
|
|
8
|
+
- After a passing test the CLI says how to keep it passing in CI instead of pointing at a hosted waitlist.
|
|
9
|
+
- The user agent reads `agent-led-growth/<version>`.
|
|
10
|
+
|
|
11
|
+
## 0.5.0 (2026-10-22)
|
|
12
|
+
|
|
13
|
+
- Renamed. The package is `agent-led-growth` (`npx agent-led-growth check <url>`); `@tansohq/agent-ready` 0.4.20 is the last release under the old name. The `agent-ready` command name still works. Repositories moved to `katrinalaszlo/agent-led-growth` (this one) and `katrinalaszlo/agent-led-growth-cli` (the published build). `alg.yml`, `.alg/` and the skill names are unchanged.
|
|
14
|
+
|
|
15
|
+
## 0.4.20 (2026-10-20)
|
|
16
|
+
|
|
17
|
+
- `test <url>` uses `alg.yml` only when its `url` is that product. When the file is for another product, or there is none, it prints "Not using <path>: it is for <host>.", takes the task and answers from that product's latest check in `.alg/<host>/` (or the defaults), and uses a call from the product's OpenAPI document for that run only, never saving it to that file. Before, `test valueiq.ai` in a folder with `alg.yml` for tansohq.com used tansohq.com's `verify_call`, so the agent's valueiq.ai key would have been sent to tansohq.com. `config_missing` now means no product was named and there is no `alg.yml`.
|
|
18
|
+
- `check`'s Next names the product in the test commands (`npx agent-led-growth test valueiq.ai --check`), and the What next? menu passes it on, so a test runs on the product just checked whatever `alg.yml` the folder holds. The "alg.yml here is for <host>" message is gone.
|
|
19
|
+
|
|
20
|
+
## 0.4.19 (2026-10-20)
|
|
21
|
+
|
|
22
|
+
- `check` answers first: "Not yet. Your pages don't show how an agent signs up, gets a key or pays." (or "No gaps in your pages. Only a test shows an agent can do it."), above the headline, which is unchanged in the terminal, `--json` and `brief.md`.
|
|
23
|
+
- The fixes and Next are printed, and the run folder written, before the standards catalog runs. Next follows the README's steps: "Step 2 of 3: fix" with the first prompt's path and the check command, then "Step 3 of 3: test" with `test --check` and `test`. The separate Fix, Folder and Onboarding sections are one Onboarding line and one Files line under the fixes.
|
|
24
|
+
- The catalog's section is Benchmarks. In a terminal it shows elapsed time ("42 s · usually 1-3 min · Ctrl+C skips; your fixes are saved"); without one, one line. It ends with "Done in … Next: …" so the last line is the next action.
|
|
25
|
+
- Ctrl+C (or SIGTERM) during the catalog stops aeo-ready and the `npx` tools it started, prints "Benchmarks skipped. Fixes saved in …", and exits `130`; before, nothing was written until the catalog finished. `audit-report.json` is written through a temporary file and a rename, before the catalog and again after it with `standards`. The 15-minute timeout now stops aeo-ready's children too.
|
|
26
|
+
- Failed checks are one line per benchmark (the count, the first names that fit, `+N`) under the path of `aeo-ready.json`, which lists them all; before, one line per check, about 60 on a typical site. `--json` is unchanged.
|
|
27
|
+
- The What next? menu shows only when there is nothing to fix, since then the next step is a test.
|
|
28
|
+
|
|
29
|
+
## 0.4.18 (2026-10-20)
|
|
30
|
+
|
|
31
|
+
- `check` no longer asks the three onboarding questions. It uses `alg.yml`, what the product's docs describe, or the recommended model, and under Onboarding says how to change the model it used ("Not right? Change onboarding in alg.yml, or run check with --ask."). `--ask` asks them in the terminal; it now needs one, and exits `2` with `answers_required` without. Without a terminal and without `--yes` or answers, `check` used to exit `2` with `answers_required`; it now runs with the defaults. `--yes` only skips the offer to run a test next.
|
|
32
|
+
- README: the Quickstart is one path, check, fix, test, with what each step costs and sends; the coding-agent, CI and installed ways follow under Other ways to run it.
|
|
33
|
+
|
|
34
|
+
## 0.4.17 (2026-10-20)
|
|
35
|
+
|
|
36
|
+
- `check` in a terminal no longer asks who holds the account when the product's agent-facing pages document it; it shows the documented answer, which you can change in `alg.yml`. Answering "not sure", "?" or "idk" keeps a question's default instead of asking again.
|
|
37
|
+
|
|
38
|
+
## 0.4.16 (2026-10-15)
|
|
39
|
+
|
|
40
|
+
- `test` prints the seven steps after its verdict, the same strip the hosted product draws: the newest `check` of the product on this machine with every local `test` applied ("Your product, seven steps", a mark per step, which steps a test proved and where the agent stops). With no check on this machine yet, it says to run one. `check` marks a step a local test proved as Agent did, `from your test`.
|
|
41
|
+
- `verify.json` records `at` (when the run finished) and `step` (the step a failed run stopped at, `signup` or `access`).
|
|
42
|
+
- After a pass, `test` no longer says app.tansohq.com runs tests on a schedule: hosted runs are coming, and it points at the waitlist on tansohq.com.
|
|
43
|
+
- app.tansohq.com: every kind of run fills in the same seven steps. Test runs, payment runs, the product's own signals and stuck reports apply to a product's funnel, each step carrying `evidence`, newest first. `GET /v1/products/:host` (`agent-ready/product@1`) answers everything a workspace knows about one product. The dashboard's product page shows the strip with the stopped step marked, one column per step with its evidence, and the product's saved tests and stuck reports; the sidebar is Products, Docs, Account.
|
|
44
|
+
|
|
45
|
+
## 0.4.15 (2026-10-15)
|
|
46
|
+
|
|
47
|
+
- `test` shows a clock while the agent works ("Agent working · 7 actions · 1 min 42 s") and the verdict line says how long the run took ("ran 1 min 42 s · 12 turns · $0.41"), the same units as the dashboard. `check` prints "Read 1 public page" for one page. The help for `check` says it is free and sends GET requests only; the help for `test` says it is your Claude Code, creates a real account on your product, spends your model use capped at $5, and asks before it starts.
|
|
48
|
+
- app.tansohq.com: the Monetization paragraph in the docs links the tanso-oss documentation beside the repository.
|
|
49
|
+
- app.tansohq.com: signals. A product's own server tells Tanso when an account signed up, made its first authenticated call and paid, with its own account id and who made the request as the server saw it (`agent`, `human`, `unknown`): `POST /v1/signals`, one or up to 100 at once, write scope. `GET /v1/signals?host=&days=` gives the funnel by source over accounts that signed up in the window (signups, first calls, purchases, amount, median signup-to-first-call), counts not rates, with the latest run of each saved test for that host and its stuck reports by step beside it. `GET /v1/signals/snippet` is the code to paste: a source classifier (Signature-Agent, coding-agent and assistant user agents, Accept: text/markdown; anything else is unknown) and the three calls. The Products page shows the table for the selected product with an Install snippet button. No logs are shipped and nothing is fingerprinted; the last 2,000 accounts per host are kept.
|
|
50
|
+
- app.tansohq.com: compare two saved tests side by side. `GET /v1/flows/:id/compare?with=flow_...&runs=5` (`agent-ready/compare@1`) gives, for each test over its last few finished runs, how many passed, were blocked or inconclusive, the latest outcome, where the last blocked run stopped, and the first-call times. The Tests page gets a Compare button: pick the other test, see the table, start both runs at once, or duplicate a test for another URL (a staging host) with only the URL changed. Counts only; no rate is claimed from a handful of runs.
|
|
51
|
+
- app.tansohq.com: a finished test run carries `timing`: `startedAt` (when a worker started it, not when it was queued), `elapsedMs`, `firstCallMs` (from the start to the first 2xx request after the product handed over a credential; null when it never did), `requests` (after the automatic first GET) and `resumed`. It stays after the evidence is deleted. The run page shows "ran 1 min 42 s · first call after 58 s · 7 requests" and a test's row shows the latest first-call time and the median over its runs.
|
|
52
|
+
- app.tansohq.com: with `AGENT_READY_STUCK_PROJECT` set to this deployment's own stuck-report project, every 401, 403 and 404 body carries `stuck`, the line that tells an agent where to report being stuck, and auth.md and llms.txt say the same under "Stuck on this API itself". Unset, nothing changes.
|
|
53
|
+
- app.tansohq.com: stuck reports. An agent that cannot continue in a product says where it stopped, and the product's workspace hears it. `POST /v1/feedback/projects` with `{ "host": "yourproduct.com" }` (write scope; one project per host, 409 `project_exists`) returns the project (`fb_<hex>`), the page an agent reads (`GET /stuck/:id.md`), the collection URL (`POST /stuck/:id`), the one line to put in the product's 4xx bodies, llms.txt and auth.md (`placement`), and a signing secret, once. The public routes need no key or sign-in: an agent posts `message` (required, 2000 characters at most) and optionally `path`, `status`, `step` (one of the seven), `agent` and `task`, and gets 201 with the report id; an unknown id is 404 either way; more than 60 unverified reports on one project in an hour is 429 `report_rate_limited`. A report the product's own server forwards with `Tanso-Signature: t=<unix seconds>,v1=<HMAC-SHA256 hex of t.body>` is recorded as `signed`, within five minutes of `t` (else 400 `invalid_report_signature`); any other is `unverified`: what it says about the agent is taken as is. `GET /v1/feedback/projects` lists projects with counts and never the secret; `GET /v1/feedback/projects/:id/reports` lists reports newest first (`?limit`, `hasMore`); each project keeps its last 500. Hosts are reduced to a public hostname (no IP, single label, underscore, port or trailing dot). Lengths count code points; control characters are dropped and credential-looking strings replaced with `[redacted]` before a report is stored. The dashboard gets a Stuck reports view: add the selected product, copy the line and the secret from the dialog that shows them once, and read reports grouped by step. Agent sessions may list and create projects and read reports.
|
|
54
|
+
|
|
55
|
+
## 0.4.14 (2026-10-14)
|
|
56
|
+
|
|
57
|
+
- `execute` gains `pay-stripe-projects-cloudflare`: the agent buys Cloudflare's Workers Paid plan ($5/month) through Stripe Projects with one `stripe projects add cloudflare/workers:paid` command, from a project folder a person set up (`AGENT_READY_STRIPE_PROJECT_DIR`: Stripe sign-in, card, spending limit, Cloudflare linked). The evaluator reads `stripe projects spend cloudflare` before and after the run and `stripe projects status` from the operator's session, and Cloudflare's `GET /accounts/{id}/subscriptions` with `AGENT_READY_CLOUDFLARE_TOKEN` and `AGENT_READY_CLOUDFLARE_ACCOUNT`; it passes only when the charge grew by at most `AGENT_READY_PAY_CAP_USD` (default 5.00 here), the new resource is listed and Cloudflare shows the subscription paid. The command's own verdict is not consulted. Its `evaluation.json` carries `protocol: "stripe-projects"`, checks `plan_written`, `purchase_recorded`, `resource_listed`, `charge_recorded`, `amount_within_cap`, `provider_confirmed`, and `objects` with `paidUsd`, `provider`, `service`, `serviceName`, `resourceId`, `resourceStatus`, `subscriptionState`. A task may now set `sandbox: { enabled: false }` or `sandbox: { allowLocalBinding: true }` for the executor; this task turns the sandbox off, because Stripe's Projects plugin listens on 127.0.0.1 and keeps the session in the macOS Keychain, and the `execute` log and `execution.json` say so. Tasks may also export `prepare({ workDir, mode, env, log })`, run before the agent, whose result reaches `evaluate` as `prepared`.
|
|
58
|
+
- `execute --task pay-x402-telnyx --mode signup`: the funnel said "acquire_credential failed: no key obtained" for a run in which the agent signed up and wrote a working key, because the payment evaluator reported nothing about the key. It now records `credential_acquired` (the key in CREDENTIAL.env) and `credential_works` (the evaluator's own `GET /v2/balance` with it), and sets `authenticated` and `keySource` like the signup tasks, so Acquire and Access rest on the evaluator. A run the product stops after that at a step for a person (Telnyx's 403 "Feature not permitted" before the quote) reads `human_required` at Execute, not `failed`; Recover reads `not_reached`. AgentMail's payment task needs no key and is unchanged.
|
|
59
|
+
- app.tansohq.com: the leaderboard records a payment made through Stripe Projects as well as over x402. `POST /v1/leaderboard/:host/pay` reads the evaluation's `protocol` (`stripe-projects`; absent means x402) and validates the six checks of that evaluator (`plan_written`, `purchase_recorded`, `resource_listed`, `charge_recorded`, `amount_within_cap`, `provider_confirmed`); a paid Stripe Projects evaluation must carry `objects.paidUsd` and `objects.serviceName`, and the x402 rules (hash, payees) are unchanged. The `agent-ready/pay@1` extract gains `provider` and `service` (the provider's name and the service's human name, "Cloudflare" and "Workers Paid"; null for x402), `protocol` is `stripe-projects` and `txHash`, `network` and `payee` are null for such a run; the resource id and anything else from the operator's Stripe account are not stored. The product page's "Paid with a real agent" section reads "$5.00 through Stripe Projects for Cloudflare Workers Paid" with no transaction link, lists the six checks ("Purchase recorded", "Resource listed by Stripe Projects", "Charge recorded on the operator's Stripe account", "Provider confirms the plan"), and says "Only the verdict, the amount, the provider and the service are stored; the run's text and the account and resource ids are not."; the Pay card reads "A test proved this: the agent paid $5.00 through Stripe Projects for Cloudflare Workers Paid." A paid run sets Pay to "Agent did" and counts in `verified` as before; the run's summary says "through Stripe Projects". `scripts/leaderboard-post-pay.mjs` prints "posted, paid $5.00 through Stripe Projects for Cloudflare Workers Paid, paid <date>".
|
|
60
|
+
|
|
61
|
+
## 0.4.13 (2026-10-14)
|
|
62
|
+
|
|
63
|
+
- app.tansohq.com: the leaderboard shows when a real agent paid a product. `POST /v1/leaderboard/:host/pay` takes the `evaluation.json` and `journey.json` of an `execute --task pay-x402-*` run (same secret and refusals as `/test`) and keeps only an `agent-ready/pay@1` extract: outcome (`paid`, `stopped`, `not_paid`), the six payment checks as `{ id, ok }`, the amount, the transaction hash, the network, the payee, `x402`, turns and cost; the agent's wallet address, the endpoint and the run's text are not stored. A paid run sets the Pay step to "Agent did" and counts in `verified` (AgentMail: Sign up, Access and Pay, "3 verified"); a stopped or failed one leaves the check's reading. Rows and `GET /v1/leaderboard/:host` carry `pay` (or null). The product page gets a "Paid with a real agent" section (date, outcome, "$2.00 over x402, transaction <hash> on Base" linked to Basescan, the six checks, turns and cost; a stopped run names the check it stopped at), the Pay card reads "A test proved this: the agent paid $2.00 over x402 for one call.", and the limits say "A payment result is from one run on one day." `scripts/leaderboard-post-pay.mjs <host> <run folder>` posts one run by hand.
|
|
64
|
+
- `check` no longer reads a stored thing's expiry as an account awaiting an owner. supermemory.ai read as "Try first, claim later" from its OpenAPI example `"forgetReason": ... "example": "temporary project deadline"` next to `forgetAfter`, and from "temporary facts drop after they expire": a memory's TTL. The `expiry` signal now counts only in a sentence that names an account, project, workspace, deployment, bucket, inbox, sandbox, key, token or resource and none of memory, forget, data, record, item or message; the "temporary account/project" signup wording is skipped in a sentence that names a stored thing. Neon's "The unclaimed project dies at `expires_at` (72 hours today)" and Cosmic's "it is deleted after 14 days unless the human verifies" still read as the claim pattern. AgentLine's "GET /v1/events (auto-deletes after read)" no longer counts, so its primary pattern is now "Agent is the customer" (its OTP signup), not "Try first, claim later".
|
|
65
|
+
- `check` no longer infers "Person sets up access first" from an auth scheme alone. turso.tech's `openapi.json` declares `bearerAuth: http bearer`, and that was the whole evidence for Sign up "handoff" and Access "handoff". A scheme says how a request is signed, not who makes the key; `existing_account` now needs signup-side evidence (a key made in a dashboard or console, a token a person creates, a CLI token flag). With only a scheme, no onboarding pattern is recorded, Sign up reads "The pages read document no way for an agent to sign up. A person may have to create the account; only a real agent run can confirm." (`needs_person`) and Access reads "The docs describe bearer tokens and OAuth, but the pages read do not show how an agent gets one." "API requests require an API key from the console" (supermemory.ai) is now signup-side evidence and counts.
|
|
66
|
+
- `check` words absence as what the pages read document. Sign up read "No way for an agent to sign up was found in the pages read."; it reads "The pages read document no way for an agent to sign up." Pay read "Paid plans are published, but nothing documents a way for an agent to buy one, so a person has to check out."; it reads "Paid plans are published. The pages read document no way for an agent to buy one, so a person may have to check out." The Pay fix prompt says to document the purchase on the product's own domain and that a path documented only on a payments provider's site is not read; it no longer implies the product has no purchase API (Stripe Projects on stripe.com documents purchasing for several checked products).
|
|
67
|
+
- `limits` in `agent-ready/audit-report@1` and `interface.json`: the first sentence now reads "GET requests only to the product's own pages for the seven steps; the standards catalog sends the product's URL to isitagentready.com and AgentGrade's service (--no-standards avoids that)" where it read "GET requests only; nothing behind a login was read", and a new sentence follows the same-domain one: "purchase paths documented on another company's site (a payments provider's catalog) are not read". The skill's "What it cannot see" list says the same about purchase paths.
|
|
68
|
+
- `test`: a failed run in which the agent wrote `NEEDS_HUMAN.md` and got no key no longer reads "The agent reached a step only a person can do." The reason is "The agent did not get a key: rejected; cause unknown. Its notes (NEEDS_HUMAN.md) say it stopped at a step for a person; the run did not confirm that." The `handoff` outcome for a product whose onboarding model says a person sets access up is unchanged.
|
|
69
|
+
- app.tansohq.com: a leaderboard product's page no longer contradicts itself about a test. Stripe's Sign up and Access cards read "Agent did" above the check's reason that a person must supply the account and key, and Turso's "Tested with a real agent" section read like a completed signup with three key checks when the outcome was a handoff with no key. A step a test proved now says what the test did in place of the check's reading ("A test proved this: the agent created an account on its own.", "…the agent reached a point where a person must act (Sign up); no key was issued.", "…the agent got a key but the check failed.", "…the agent's signup was rejected; no key was issued (cause unknown)."), the test section says the same by outcome, and the three key checks are listed only when some ran; otherwise it says "No key was issued, so no check ran." The page's render functions are exported and tested in node.
|
|
70
|
+
- app.tansohq.com: an inconclusive test is recorded. `POST /v1/leaderboard/:host/test` refused it (400), so Whisper and monday showed no test although they were tested. It is stored with `outcome: "inconclusive"`, `steps: []` and no reason text; the row reads "N of 7 · tested, inconclusive", its headline "A test with a real agent was inconclusive; no step verified.", and the product page "Inconclusive on <date>: the run reached no verdict about the product". Ranking is unchanged (0 verified). `scripts/leaderboard-tests.mjs` posts an inconclusive verdict instead of skipping it.
|
|
71
|
+
- `check`'s Cloudflare benchmark no longer reads "1/5 next to 5/5 checks passed" (composio.dev). Its score is a readiness level, and aeo-ready up to 1.8.0 parsed only the PASS and OK lines of isitagentready.com's report, so `checks` held no failure. The counts now come from the report's own "n/m passing" category headings (4 of 21 for composio.dev), the terminal and the leaderboard page say "level 1/5" and "Level 1 of 5", and a card whose counts say some checks failed but names none says "Failed checks not named by the catalog." The aeo-ready fix that names them is in its branch `cloudflare-score`; stored leaderboard documents keep the old counts until the weekly check runs again.
|
|
72
|
+
- The README, the `agent-ready` skill and the terminal's Standards header say what leaves your machine: the seven steps come from GETs of the product's own pages; the standards catalog sends the product's URL to Cloudflare's isitagentready.com and AgentGrade's service, and `--no-standards` avoids that. The README said `check` sends GET requests only.
|
|
73
|
+
- The leaderboard test scripts, route description and comments named `final.json`; `test --json` writes `verify.json`. 0.4.12's entry below named the wrong file too.
|
|
74
|
+
- `execute` gains two tasks that have the agent pay over x402 from its own wallet, `pay-x402-agentmail` (one inbox, $2.00) and `pay-x402-telnyx` ($1 of account credit, needs `TELNYX_API_KEY`), with the private key in `AGENT_READY_WALLET_KEY` and a cap in `AGENT_READY_PAY_CAP_USD` (default 2.00). The evaluator confirms the settlement transaction on Base over keyless JSON-RPC: it succeeded, USDC left the agent's wallet, the amount is within the cap, and the paid request answered 2xx. Real money moves; the README says so.
|
|
75
|
+
- Repository: the leaderboard's tests can be rerun for every listed product with one command, by hand once a month. The workflow `.github/workflows/leaderboard-tests.yml` (the 2nd of each month at 05:17 UTC, or by hand with a list of hosts and a per-product cap, default $5) runs `scripts/leaderboard-tests.mjs`: `agent-ready test --yes --json --max-budget-usd <cap>` from inside each `src/hosting/tests/<host>/` folder, then posts the run's `verify.json` with the code of `scripts/leaderboard-post-test.mjs`. One line per host; a test that wrote no `verify.json` is printed and skipped, an inconclusive verdict is printed and not posted, and the script exits 1 only when a post was refused. It installs Claude Code from npm (`@anthropic-ai/claude-code`) and the sandbox's Linux dependencies (`bubblewrap`, `socat`, and the AppArmor profile Ubuntu 24.04 needs for `bwrap`), and needs the repository secrets `ANTHROPIC_API_KEY` and `AGENTMAIL_API_KEY` beside `LEADERBOARD_URL` and `LEADERBOARD_SECRET`; until they are set, every host prints a setup failure and nothing is posted.
|
|
76
|
+
- app.tansohq.com: the leaderboard's Product and Category cells no longer wrap letter by letter at phone width ("Railwa / y", "Cloud infrastru / cture"). They keep to one line and the table scrolls sideways, as it already did.
|
|
77
|
+
- The Sign up step's reason says what a self-serve signup needs in a sentence. It read "It needs: inbox." (the `needs` tokens joined with commas); it now reads "Needs an inbox the agent can read.", "Needs a shell where the agent can run the product's CLI.", "Needs a wallet the agent can pay from." or "Needs an identity provider the agent can sign in with.", one sentence per need. The `needs` field itself is unchanged.
|
|
78
|
+
- `check` says when parallel runs ran the machine dry. When aeo-ready fails and its stderr shows `EADDRNOTAVAIL` or `EAI_AGAIN`, `standards.error` ends with "local ports or DNS exhausted; run checks one at a time" after the raw error. The terminal's Standards header says the catalog runs one at a time and, for many products, to use `--no-standards` and run the catalog later.
|
|
79
|
+
- `npm run build:cli` leaves out iCloud Desktop sync duplicates, files named `<name> 2.<ext>` or `<name> 3.<ext>` next to the original. 0.4.11 and 0.4.12 shipped `src/report/format 2.js` this way. A test builds the package and checks no such name is in it.
|
|
80
|
+
- app.tansohq.com: a leaderboard product's page agrees with its row. The page rendered the check's funnel alone, so a tested product read "No step has been tested yet" above its "Tested with a real agent: Passed" section and showed Sign up and Access as "Agent can"; it now merges the test's steps and headline the way the row does.
|
|
81
|
+
- app.tansohq.com: the leaderboard shows what a real `test` verified. Every row said 0 verified because the board held only checks. `POST /v1/leaderboard/:host/test` (bearer `AGENT_READY_LEADERBOARD_SECRET`, as the check route) takes `{ verify, verifiedAt }`, `verify` the `agent-ready/verify@1` document `test` wrote as `verify.json`, and keeps only a verdict extract: `outcome`, the steps the test proved (`passed`: signup and access `agent_did`; `handoff`: signup `handoff`; `failed`: signup `agent_did` and access `blocked` when the checker ran, else signup `blocked`), the three key checks as `{ id, ok }`, `costUsd`, `turns` and `verifiedAt`. The task, reason, check details, folder, prompt, checker call and URL are not stored. A test of a product with no check yet is refused (`404 not_checked`); one test per product is kept. `GET /v1/leaderboard` rows gain `test` (the extract or `null`), `verified` counts the test's `agent_did` steps, so the ranking (documented, then verified, then name) now uses real tests, and a tested step's state is the one the test proved. `GET /v1/leaderboard/:host` answers `{ product, run, test }`. The page's "N of 7" cell adds "· N verified" when a test exists, and the product page gets "Tested with a real agent": date, outcome, the three checks, turns and cost, with "a test result is from one run on one day" among the limits. `scripts/leaderboard-post-test.mjs <host> <verify.json>` posts one document (`LEADERBOARD_URL`, `LEADERBOARD_SECRET`; `verifiedAt` from the file's modification time) and exits 1 when refused.
|
|
82
|
+
- app.tansohq.com: a check whose quoted page text holds a NUL character is stored. Postgres's JSONB column refuses the six-character `\u0000` escape ("unsupported Unicode escape sequence"), which made `POST /v1/leaderboard/digitalocean.com/check` and `langchain.com` answer 500 on the first leaderboard run and could do the same to any hosted check; the escape is dropped from the document's text before it is written.
|
|
83
|
+
|
|
84
|
+
## 0.4.12 (2026-10-14)
|
|
85
|
+
|
|
86
|
+
- `test` scrubs more of what an audit of real runs found left in the run folder. A key a product printed as a Python dict (`'user_api_key': 'uak_…'`), a token claim in a decoded JWT (`"pat"`), a second Firecrawl key (`fc-…`) shown in page text, and the sandbox proxy's credential (`HTTP_PROXY=http://srt.…`) in an environment dump are now redacted. Keys a CLI saved under `.tools/home` that the agent never printed (Composio's agent.json held a user key and an agent key next to the project key) are learned from the files before the scrub, so they are gone from every file.
|
|
87
|
+
- `test` no longer corrupts numbers or JSON while redacting. A learned value is replaced only where it stands as a whole token: a six-digit mail code had been replaced inside a token count (`1000000` became `1<redacted>`, and that trace line stopped parsing), and the word `databases`, learned from a pricing JSON's `"key"` fields, had turned Turso's "100 databases" into "100 <redacted>". Short plain words are no longer learned, and a value that is a whole JSON number is left alone.
|
|
88
|
+
- `test` reports every turn of a run. Claude Code prints one result event per segment when it resumes; `turns` in `verify.json` (this entry first said `final.json`) and on the terminal counted only the last segment (a 36-turn Stripe run said 4, a 46-turn monday run said 5). It now adds them up; the cost was already cumulative.
|
|
89
|
+
- `check` gives the aeo-ready catalog 15 minutes before killing it, not 5: airbyte.com, motherduck.com, clickhouse.com and duckdb.org take longer than 5 and lost all five benchmarks in the first leaderboard run. `AGENT_READY_STANDARDS_TIMEOUT_MS` sets another limit. When the catalog is killed, `standards.error` says `aeo-ready killed after 900 s without JSON`; it said `exited ... without JSON` whatever the cause. The in-process leaderboard sweep keeps its 180 seconds.
|
|
90
|
+
- `standards.benchmarks[]` in `agent-ready/audit-report@1` gains `durationMs`, the benchmark's own wall-clock time as aeo-ready 1.8.0 reports it; null from an older aeo-ready. Added at the end of each benchmark; nothing else in the document changes.
|
|
91
|
+
- The README says that many checks run in parallel can exhaust local ports, because the catalog fetches a site's whole sitemap at once, and to run them one at a time or with `--no-standards` and one catalog pass later.
|
|
92
|
+
|
|
93
|
+
## 0.4.11 (2026-10-14)
|
|
94
|
+
|
|
95
|
+
- `test` no longer stops with `ENOENT ... stat ... SingletonCookie` after the agent ran headless Chrome. The scrub that redacts secrets from files the agent wrote walked the work folder with `stat`, which fails on the dangling `SingletonCookie` and `SingletonLock` symlinks Chrome leaves in its profile under `.tools/`; it now reads entry types from the directory and scrubs regular files only, stepping over symlinks and sockets.
|
|
96
|
+
- `check` runs the aeo-ready standards catalog after the seven steps: five third-party benchmarks of the public surface (agentic-seo, Cloudflare, Fern, Vercel, AgentGrade; about 125 checks: llms.txt, markdown and content negotiation, MCP server cards, A2A agent cards, x402, UCP, ACP, AP2, Web Bot Auth, rate-limit headers, structured JSON errors). The terminal gets a "Standards" section between the run folder and Next: one line per benchmark (checks passed/total and the benchmark's own score), then the failed checks' names by benchmark. The scores are theirs, and nothing in the catalog changes the seven-step verdict or the fix prompts. It spawns `npx` and takes 1-3 minutes, so a check takes that much longer; `--no-standards` skips it and says "Standards skipped (--no-standards)". The verdict and the steps print before the catalog runs. When aeo-ready does not run, the section prints its error. `--json` (`agent-ready/audit-report@1`) gains `standards` (`{ generator: { name: "aeo-ready", version }, averageScore, benchmarks: [{ id, name, score, maxScore, grade, passed, total, failed, error }], warnings, error }`) and `files.standards`, the path of `aeo-ready.json` (the catalog's own output) in the run folder; both are absent with `--no-standards`, and the document is otherwise unchanged. `AGENT_READY_AEO_CLI` names another aeo-ready CLI script to run instead of the installed one.
|
|
97
|
+
- `check` reads an agent checkout over ACP (OpenAI and Stripe's Agentic Commerce Protocol), UCP (Google's Universal Commerce Protocol) and AP2 (Google's Agent Payments Protocol), next to x402 and MPP.
|
|
98
|
+
- New rule `checkout_protocol_own_api`: ACP or UCP named in a sentence (or a heading's section) with a checkout session call on the product's own API (ACP's `POST /checkout_sessions`, UCP's `POST /checkout-sessions`), read from text or OpenAPI JSON keys. A served `/.well-known/ucp` whose JSON has a top-level `ucp` member (the UCP business profile) counts on its own, with no call. A bare acronym counts only on a page that spells the protocol out or uses its tokens (`checkout_sessions`, `dev.ucp.`, a Payment Mandate), since ACP is also other protocols. Not counted: the billing-vocabulary guards from 0.4.3, a description of the protocol, a PSP's `delegate_payment` endpoint, payment providers, storefronts, "your checkout_sessions endpoint", merchant and seller pages by URL. AP2 defines no endpoint, so an agent buying with a mandate is read by `agent_buys_through_api` as before, now recording the protocol.
|
|
99
|
+
- `check` probes `/.well-known/ucp` (role `ucp_profile`); it is the one well-known path these three protocols define. ACP's docs say discovery mechanisms are still being worked on, and AP2 is carried in A2A messages.
|
|
100
|
+
- `pricing.agentPurchase` gains `protocol`: `x402`, `MPP`, `ACP`, `AP2`, `UCP` or null, the protocol the quoted sentence names. The Pay reason names it: "a paid call over x402 on the product's own API", "a checkout an agent completes over ACP on the product's own API (POST /checkout_sessions)", "publishes a UCP business profile at /.well-known/ucp", "the agent buys through the API over AP2". It said "x402 or MPP" before; a checkout is never worded as paying per request. The protocols' own sites (agenticcommerce.dev, ucp.dev, ap2-protocol.org) are not another site a purchase happens on.
|
|
101
|
+
- app.tansohq.com, same release:
|
|
102
|
+
- A public leaderboard, `/leaderboard`, with no sign-in, when the deployment sets `AGENT_READY_LEADERBOARD=on`. The products are a list in the repository (`src/hosting/leaderboard.json`: name, host, category), seeded with 30 products: Fly.io, Railway, Render, Cloudflare, DigitalOcean, Vercel, Edge, LangChain, Mem0, Exa, Supermemory, Composio, Airbyte, MotherDuck, ClickHouse, DuckDB, MongoDB, Neo4j, Neon, Supabase, Turso, Stripe, Telnyx, AgentMail, AISend, Inkbox, Cosmic, Whisper, Firecrawl and monday. Each row is the product's latest check: the seven step states the way the dashboard shows a check, "documented N of 7", the five aeo-ready benchmark scores, when it was scanned, and a link to the full check report at `/leaderboard/<host>`, also readable with no sign-in. Products are ranked by the steps their public pages document, then by steps a test verified, then by name; no score is invented and the benchmark scores are shown, not ranked on. The page says what a check cannot show and links to checking your own product.
|
|
103
|
+
- `GET /v1/leaderboard` (`agent-ready/leaderboard@1`) and `GET /v1/leaderboard/:host` return the same data, with `run` in the shape `GET /v1/runs/:id` gives a check. A host not on the list answers `404 not_found`; one not checked yet `404 not_checked`. Both are in `/v1/routes`, the OpenAPI document and the API reference when the leaderboard is on.
|
|
104
|
+
- The checks come from a weekly GitHub Actions workflow (`.github/workflows/leaderboard.yml`, `scripts/leaderboard-run.mjs`): it runs `agent-ready check` on every listed product, catalog included, and posts each result to the new `POST /v1/leaderboard/:host/check` with the bearer `AGENT_READY_LEADERBOARD_SECRET` (`401 leaderboard_unauthorized` without it, `503 hosting_not_configured` when the deployment has none, `400 invalid_leaderboard_check` for a document that is not that product's). The server builds the funnel from the posted document itself, so the ranking is its own reading. It runs in Actions rather than the Vercel cron because a check spawns `npx` for the catalog and takes minutes: Actions has node and npx and no 600-second cap, and a leaderboard check never shares a tick with a customer's run. Checks are saved under a system row (`agent-ready-leaderboard`) that is nobody's workspace: not billed, no credits reserved, no agent run; only each product's latest check is kept, with `source` `actions` or `sweep`. The cron's own one-product-a-tick sweep (never checked first, then any whose check is 7 days old, a failed check tried again after an hour, the catalog killed after 180 seconds, started only while the tick has used at most 240 of its 600 seconds) is off unless `AGENT_READY_LEADERBOARD_SWEEP=on`, which a local server sets to check on a one-minute timer.
|
|
105
|
+
|
|
106
|
+
## 0.4.10 (2026-10-10)
|
|
107
|
+
|
|
108
|
+
- `check` reads a pricing.json plan whose price is a bare number (`price: 5`) with the currency on the plan or the document, alongside `price: {amount, currency, period}`. It used to see no amounts in that shape and fall back to page prose.
|
|
109
|
+
- The README has a "Manage your workspace" section for hosted workspaces, and the `agent-ready` skill says an agent may check usage, cancel a waiting purchase, pause buying or lower the cap, and must leave unpausing, raising the cap, approving and paying to the person.
|
|
110
|
+
- app.tansohq.com, same release:
|
|
111
|
+
- An agent (an API key or an AgentID agent session) may move its workspace toward spending less; only the signed-in owner may move it toward spending more. New routes: `GET /v1/purchases` (newest first, at most 50), `POST /v1/purchases/:id/cancel`, `POST /v1/billing/cap`, and `POST /v1/keys/self/revoke` (API keys only). `POST /v1/billing/pause` accepts `{ "paused": true }` from an agent. Unpausing, raising the cap (or setting one when none was approved), approving and paying answer an agent `403 person_required`.
|
|
112
|
+
- Cancelling a purchase still waiting for approval, or at an unpaid checkout, sets its status to `cancelled` (spelled like the run status), closes the Stripe page, and makes the approval link answer `410 approval_expired`. Nothing is charged; a checkout already paid answers `409 checkout_completed` and stays paid. An agent can cancel up to 10 purchases a workspace a UTC day, then `429 cancel_limit` with `Retry-After`.
|
|
113
|
+
- `GET /v1/account` has `billing.usage` for the month: `runsUsed` (`freeRunsUsed` + `paidRunsUsed` + `runsReturned`), `spentCents`, `capCents`, `remainingCents`, `resetsAt`, and `recentRuns` (the last 20, each with `charged`: `free`, `paid` or `returned`). `GET /v1/runs` has every run.
|
|
114
|
+
- The scheduled sweep re-checks pause and the cap before it sends a charge Stripe never answered, and fails the purchase with nothing charged when they refuse, so an agent's pause or lower cap holds.
|
|
115
|
+
- The owner's pause and cap controls work on the person's own workspace too, not only on claimed ones, so the owner can undo anything an agent did there.
|
|
116
|
+
- The approval page never pre-fills a cap below the least an approval may set, even after an agent lowered the cap.
|
|
117
|
+
- The pre-filled signup test review names one onboarding pattern, the one the docs describe, where it showed the starting path and the documented pattern side by side.
|
|
118
|
+
|
|
119
|
+
## 0.4.9 (2026-10-09)
|
|
120
|
+
|
|
121
|
+
- The limits list in `check` output and `interface.json` says "public pages cannot show whether a step works; a test runs a real agent", where it said "live verification requires an agent usability run". Checks saved before this release keep the old sentence.
|
|
122
|
+
- `test` finds its check call with the same rules as before; the lookup was split so the hosted app can use it too. The plan, `verify_call` and `--json` output are unchanged.
|
|
123
|
+
- app.tansohq.com, same release:
|
|
124
|
+
- Products shows a "Get started" checklist until it is done: check your product, test it with a real agent, keep it passing. It can be hidden.
|
|
125
|
+
- "Test signup on <host>" builds a signup test from the latest check. The result URL comes from the product's OpenAPI document when one qualifies (`GET /v1/runs/:id/suggested-test`, looked up once per check and at most 20 new lookups per workspace an hour), so the person only confirms they may test the product. A test that checks the agent's key no longer needs text the answer contains: the call with the key must answer 200 and the same call with no key and with a wrong key must be refused. Tests that already have the text are unchanged.
|
|
126
|
+
- After a test passes, "Run daily, email me" turns on the daily schedule and email alerts.
|
|
127
|
+
- The blank setup form is now "Custom test". "Book a conversation" appears only when a test needs a test account the team arranges.
|
|
128
|
+
- A check report downloads as "Download report" (Markdown) or "Raw data (JSON)".
|
|
129
|
+
|
|
130
|
+
## 0.4.8 (2026-10-09)
|
|
131
|
+
|
|
132
|
+
- `check` for a new host in a folder whose `alg.yml` names another product drops that file's `verify_*` lines when it rewrites the answers ("Dropped verify_call for <old host>; test will pick a call for <new host>."), so the next `test` no longer sends the new product's agent key to the old product's API. `--yes` still never overwrites an existing `alg.yml`; when that file names another product, `check` says so under Next ("alg.yml here is for <host>, so test would run there.") instead of offering `test`.
|
|
133
|
+
- `check` in a terminal asks the three questions right after reading the pages, then prints the verdict and the seven steps once, from the answers given. It used to print them from the defaults first, so the verdict could change after you answered. With `--yes`, flags or no terminal the output is unchanged.
|
|
134
|
+
- `check` labels the fix prompt "Fix" and keeps "Next" for the trailing step, so there is one Next. The headline's second sentence reads "No step has been tested yet: a test runs a real agent." where it said "None is verified yet: a test runs a real agent.", and the brief says "checked" and "What this check cannot show" instead of "audited" and "What this audit cannot show".
|
|
135
|
+
- `--json` from `check` is unchanged except the `headline` sentence above and one `limits` sentence, which now reads "public pages cannot show whether a step works; a test runs a real agent".
|
|
136
|
+
- `test --check` warns, under READY and in a new `warnings` field of `agent-ready/verify-plan@1`, when the last check's `interface.json` says the chosen onboarding pattern needs an inbox and neither `AGENTMAIL_API_KEY` nor `--inbox` is set: "The product's docs mention an emailed code or link and no inbox is set. Set AGENTMAIL_API_KEY or pass --inbox, or the run may end inconclusive." `ready` and the exit code are unchanged.
|
|
137
|
+
- A failed `test` says to deploy the fix, run `check` again, and test again; a passing one mentions that app.tansohq.com can run it on a schedule.
|
|
138
|
+
- The `/agent-ready-verify` skill is now `/alg-test`, matching the command it runs. It still runs only when you invoke it.
|
|
139
|
+
- The CLI, README, skills and plugin use `check` and `test` throughout (`audit` and `verify` still work as aliases) and no longer call `test` free: Tanso charges nothing for the CLI, and `test` uses your own Claude Code model time (capped at $5 by default) and creates a real account on the product. The README says how a hosted test run differs from `test`, with a comparison table.
|
|
140
|
+
- app.tansohq.com, same release:
|
|
141
|
+
- The dashboard, `/docs`, `/auth.md`, `/llms.txt`, the OpenAPI document and the API reference use the same status words (Passed, "Failed: stopped at <step>", Waiting for approval, "Didn't finish (free)", Not run yet), the same hosted pricing and the same pattern and step names, and point CLI users at https://tansohq.com/quickstart instead of a local server.
|
|
142
|
+
- Pricing text says a run that doesn't finish (inconclusive), or fails on our side, is not charged: a free run goes back to the month, a paid run goes back to your balance.
|
|
143
|
+
- The `/v1/signup` example in `/auth.md` no longer shows `limits`; the response itself is unchanged. `/auth.md` no longer says "Authorization server: none": the API takes keys it issues directly, with no OAuth authorization server, and people and agents sign in to the dashboard (agents with AgentID). `/.well-known/oauth-protected-resource` is unchanged.
|
|
144
|
+
- Static pages, docs and the dashboard shell answer HEAD like GET without a body, where they answered 404, so link checkers and uptime monitors no longer report the app as down.
|
|
145
|
+
|
|
146
|
+
## 0.4.7 (2026-10-09)
|
|
147
|
+
|
|
148
|
+
- `test` in a terminal, with no `verify_call`, asks "To prove the agent's key works, we'll call your API with it after signup:" and shows the call and the document it came from, then "Use this call? [Y/n]", where it printed the "Will check with …" sentence and "Use it?". Without a terminal, and with `--yes`, the "Will check with …" line is unchanged. While it reads the docs it says "Finding a call that proves the agent's key works…".
|
|
149
|
+
- app.tansohq.com, same release: the dashboard says what a check and a test are ("A check reads your public pages (free). A test sends a real agent through them."), uses the CLI's pattern names, shows Passed, "Failed: stopped at <step>", "Didn't finish (free)" and "Not run yet", lists each test once, puts paused schedules in one notice with "Turn schedules back on", and orders Account as you, runs and billing, claimed workspaces, agents. The CLI 0.3 runs block is gone.
|
|
150
|
+
|
|
151
|
+
## 0.4.6 (2026-10-08)
|
|
152
|
+
|
|
153
|
+
- `check` ends with a next step instead of "A real agent run is the next check." In a terminal it asks "What next?": 1 runs a test now (test still shows its plan and asks before the agent starts), 2 shows the plan for free, 3 prints the commands and quits. The default is 1 when there is nothing to fix and 3 when there are fixes. With `--yes`, `--json`, or no terminal on stdin or stderr, it prints the two commands under "Next" and never waits for an answer. `brief.md` names the same commands. `--json` output is unchanged.
|
|
154
|
+
|
|
155
|
+
## 0.4.5 (2026-10-08)
|
|
156
|
+
|
|
157
|
+
- `check` reads an agent getting access through Stripe Projects ("use Stripe Projects to … provision", `stripe projects add`) as a person setting access up first, since the developer's Stripe account vouches for the agent. Across the 41 hosts checked on 2026-10-08, e2b.dev changes from Agent is the customer to Person sets up access first (Sign up and Access are handoffs); no other host changes.
|
|
158
|
+
- `check` fix prompts offer Sign in with AgentID, AgentMail's OpenID Connect provider for agents (issuer `https://auth.agentid.com`), as one way to let agents sign up:
|
|
159
|
+
- With `onboarding: agent_identity`, the Sign up prompt is now "Let agents sign up with AgentID": register the app with `npx @agentmail/agentid-cli init` (a person approves it once in a browser), add AgentID to the sign-in the repo already has (Clerk's `oauth_agentid` connection, a custom OpenID Connect provider in Supabase or Auth.js v4, Auth0's marketplace connection, `@agentmail/agentid-better-auth` for Better Auth 1.7.2 or later, or the app's own OpenID Connect client), show "Sign in with AgentID" next to the existing options, key accounts on issuer and `sub`, request `owner_email` and `owner_profile` to know the owner, and publish "Agents can sign in with AgentID to get an account." in `/auth.md` and `/llms.txt`, which `check` reads as an AgentID sign-in. The device flow prompt it replaced is named as the other option. The auth provider is not guessed from public pages; the prompt tells the coding agent to read it from the repo.
|
|
160
|
+
- With `try_then_claim`, `limited_until_claimed` or `agent_is_customer`, the Sign up prompt is unchanged and ends with an "Another option" paragraph: an existing OpenID Connect sign-in can accept AgentID instead of a new signup endpoint, and the agent then needs an AgentMail inbox and key, a person approves the app's registration once, and AgentID is new (launched 2026-10-06). `existing_account` and `pay_per_request` prompts do not mention AgentID.
|
|
161
|
+
- With `onboarding: agent_identity`, a Sign up that only describes a person handing the agent a key is now a finding, as it already was for the other agent-first models.
|
|
162
|
+
- The `agent_identity` option reads "The agent, with an identity a person delegated (for example Sign in with AgentID)", and `alg.yml` gets a comment line naming AgentID as one implementation.
|
|
163
|
+
- app.tansohq.com:
|
|
164
|
+
- `robots.txt` disallows only `/v1/`. The blanket `Disallow: /` also covered the sign-in pages, `/login/agentid` included, and `check` read it as blocking AI agents from the whole app.
|
|
165
|
+
- Sign in with AgentID. An agent with an AgentMail inbox signs in to the dashboard as itself, through Clerk's AgentID connection (`oauth_agentid`): a "Sign in with AgentID" button on the sign-in page, `/login/agentid` to start it as the page loads (AgentID's initiate login URI) and `/sso-callback` to finish. The session is an agent, never the person, decided by the Clerk user and failing closed: a user with an AgentID account linked is an agent in every session for as long as it stays linked, so a person who connects AgentID to their own account (or whose email Clerk links to an AgentID sign-in) is treated as an agent on their own workspace ("This account has AgentID connected, so it is treated as an agent. Remove AgentID from your account settings to approve purchases and change billing.") until they remove it and sign in again. Agent sessions are remembered by session id, and a user whose first AgentID session found no identity of its own and no Tanso workspace is recorded as AgentID-created and treated as an agent from its first API call on. An agent session can do what a workspace key can, except spend: it uses free and already-paid runs, and anything that would charge a card answers `402 payment_required` with reason `agent_session` and an approval link, even within a cap. Every other route answers `403 person_required` unless it is listed in `AGENT_SESSION_ROUTES`, so a new route is closed to agent sessions until it is added there. Refused: approvals, payment pages, key rotation, purchase pauses, claims, alert settings, agent links, and confirming that an agent may sign up to a product. An agent works in a workspace of its own (unclaimed, no free runs) unless its AgentID `owner_email` is verified, matches the verified Clerk email of a person who signed in here, and that person approved it under "Agents using your workspace" on the Account page (`GET /v1/agent-links`, `POST /v1/agent-links/:id/approve|decline|remove`, person only). The approval is checked on every request, so Remove takes effect at once. The owner claim is read at each AgentID sign-in and tried again hourly while linked; only an owner that changed or is no longer verified unlinks the agent, while an expired token or failed read leaves the link as it is. At most 20 requests wait on one person; past that a new one is not sent and the agent asks again at its next sign-in. A linked agent sees only that workspace: no claimed workspaces. Purchases and runs record `createdBy: { kind: "agent_session", agentId, ownerEmail }`, the approval page says "An agent signed in with AgentID", and the dashboard shows a banner and hides person-only controls. `/auth.md`, `/llms.txt` and `/docs` describe the sign-in. New error codes `session_check_unavailable` (503) and `agent_link_state` (409). No new environment variable: owner claims are read from AgentID's `/v0/userinfo` with the access token Clerk holds, using the existing `CLERK_SECRET_KEY`.
|
|
166
|
+
- Alert email no longer waits for `AGENT_READY_ALERTS_INBOX`. With only `AGENTMAIL_API_KEY` set, the server creates one "Tanso alerts" inbox in that AgentMail account on first use (`client_id` `tanso-alerts-v1`, so a repeat returns the same inbox) and saves its id in the accounts-table row `agent-ready-alerts-inbox`. `AGENT_READY_ALERTS_INBOX`, when set, still wins. While the inbox cannot be created, the failure is logged, emails stay queued and retry, and the Alerts dialog says "Email isn't available right now" instead of "not configured". Signup inboxes for agent runs are created separately, and a fixed or routed signup inbox that is the alerts inbox is refused.
|
|
167
|
+
- Alert emails have an HTML part beside the plain text, the test's host in the subject ("Test failing: First call (example.com)", "Test recovered: …", "Test alert: …"), and a last line on turning email off in the test's Alerts.
|
|
168
|
+
|
|
169
|
+
## 0.4.4 (2026-10-07)
|
|
170
|
+
|
|
171
|
+
- Pay reads a purchase the product's own pages document. Three rules, each over a sentence on a page of the product's registrable domain:
|
|
172
|
+
- `agent_buys_through_api`: an agent buying ("An agent can buy runs with POST /v1/purchases within a monthly cap") with a purchase call, a spending cap or a mandate, or a person approving in the same sentence.
|
|
173
|
+
- `payment_required_approval`: `402 payment_required` with an approval link or a person approving.
|
|
174
|
+
- `pay_per_request_own_api`: x402 or MPP next to a paid call on the product's own API. A call is paid when its path says so (`/v1/x402/numbers/buy`, `/v2/x402/credit_account`, `/x402/invoice/create`, `.../purchase-key`), when it is the x402 or MPP variant of an API path (`/v1/x402/search`, an `x402.` host), or when it sits under a heading that says the endpoints are paid ("## Paid endpoints (x402 or MPP)"). Calls are read from text, OpenAPI YAML ("post /v1/x") and OpenAPI JSON keys. Not paid: signing a payment for someone else (`/signature/x402/`), verify, settle, facilitator, registry and register calls, listings and catalogs (`/endpoints/md`, `openapi.json`), status, info and events, and docs links. Pages for sellers or with examples (by their URL), seller code (`paymentMiddleware`, `payTo`, "for sellers", "accept payments") and wallet or proxy pages ("Call any x402 URL", an x402 catalog, wrapped APIs) do not count.
|
|
175
|
+
- The billing-vocabulary guards from 0.4.3 apply to all three: sentences about the product's customers, about selling or monetizing, describing the protocol, buying from the reader's store, naming another site's URL, or saying it is not a purchase do not count. The interface document gains `pricing.agentPurchase` (`rule`, `rules`, `approval`, `call`, `evidence`, strongest call first), null when none is found.
|
|
176
|
+
- A person setting payment up once and the agent paying after that is a handoff, which passes: an approval link, a spending cap, a mandate, a saved card or a delegation within 300 characters of the hit ("charged to the card behind the delegation"). Otherwise an agent buying through the API, or a paid x402 or MPP call, is `agent_can`, and the reason names the call. A test still has to show the payment goes through. An x402 mention with no paid call on the product's API stays `not_checked`, as before.
|
|
177
|
+
- Across 44 products recorded by QA, Pay changes for 7: tansohq.com (needs_person to handoff), exa.ai (not_checked to handoff), and agentcash.dev, agentline.cloud, bitrefill.com, keenable.ai and telnyx.com (not_checked to agent_can). x402.org, neynar.com and paywithlocus.com do not change. No other step or onboarding pattern changed.
|
|
178
|
+
- `test` without a `verify_call` also looks at OpenAPI documents in JSON that the product's `llms.txt`, `llms-full.txt`, `auth.md`, agent and pricing files link to on the same registrable domain (`app.`, `api.`, `docs.` hosts included), when the product's own OpenAPI document has no GET that needs a key or there is none. Among those it prefers a call that reads the caller's account. tansohq.com now plans `GET https://app.tansohq.com/v1/account` from `https://app.tansohq.com/openapi.json`, linked from its llms.txt, instead of exiting 2. A product whose own document qualifies keeps the call it had. Links are taken in page order, absolute or relative. Linked YAML documents are named in the error but not read, because no YAML parser ships with the CLI. When nothing fits, the error says why each linked document was skipped: it answered 404, could not be read (for example over the size limit), is not JSON, redirects to another site, or has no GET that needs a key. A document that redirects to another site is not used. `agent-ready/verify-plan@1` and `agent-ready/verify@1` gain `checker.inferredVia` (the page that linked the document) when the document came from a link; the plan and the "Will check with" line name the document and the page.
|
|
179
|
+
- The plan and the "Will check with" line show the inferred call's API host and where it came from: "Will check with GET https://console.neon.tech/api/v2/users/me on console.neon.tech (Authorization) (from https://neon.com/openapi.json)." When the host is on a different site than the product (by the Public Suffix List), they add "This API host is on a different site than neon.com; the key the agent gets is sent there." The call is still used, with or without `--yes`: the key is the one the agent got from this product, and the host comes from a document the product serves. When calls on the product's site and on another site both qualify, the one on the product's site is chosen. `agent-ready/verify-plan@1` and `agent-ready/verify@1` gain `checker.apiHost` and `checker.apiHostOffSite` for an inferred call. A `verify_call` you write yourself still goes wherever it says.
|
|
180
|
+
- An inferred call whose API key goes in the `Authorization` header takes the prefix the OpenAPI document gives: from the scheme's description or `x-` fields, or from an Authorization header parameter's description or example ("Prefix your Mem0 API key with 'Token '", "Token <key>", "Bearer {API_KEY}"). Only Token, Bearer, Key, Api-Key and ApiKey count. mem0.ai now plans `Authorization: Token {key}`. Before, every such key was sent with nothing in front of it. With no documented prefix, or two different ones, that call is skipped and the next call or linked document is tried. When nothing is left, `test` exits 2 and says the document does not say what comes before the key. "Do not prefix the key", "send the raw key" and "without a prefix" mean the key goes in as it is, and a written-out header ("Authorization: Token abc123") counts as an example. Bearer schemes still give `Bearer {key}`.
|
|
181
|
+
- The headline keeps documented and verified apart. A check says "Your public pages document N of 7 steps. None is verified yet: a test runs a real agent.", where it said "Your public pages show N of 7 steps working." With test results (the hosted funnel), it says "N of 7 steps verified by a test.", how many more the public pages document, and which steps failed a test. `agent-ready/audit-report@1` and the funnel gain `documented` and `verified`; no field was removed or renamed. The terminal prints the headline one sentence a line.
|
|
182
|
+
- The hosted funnel's label above the headline reads "What your pages document and what a test proved", where it said "How far an agent gets".
|
|
183
|
+
- The terminal's handoff count reads "N work because a person steps in once", since a handoff can now be an approval, not only a key.
|
|
184
|
+
- `check` says "1 needs a test run." for steps public pages cannot show, matching each step's `needs a test run` tag.
|
|
185
|
+
- app.tansohq.com, same release:
|
|
186
|
+
- A second payment for a purchase already credited (a different PaymentIntent) is no longer dropped silently. It is logged with the intent to refund, and the purchase carries `secondPayments`, which the Account page shows to the owner.
|
|
187
|
+
- Coming back from Checkout lands on `#tests/paid-<purchase>`. Until Stripe's webhook confirms the payment, the review says "Confirming your payment…" and does not offer the paid page again.
|
|
188
|
+
- Prices read "$5.00 per run; an Inconclusive run or one that fails on our side goes back to your balance" in place of "per completed run", in the dashboard and the served docs.
|
|
189
|
+
- The docs say what a setup change does to alerts: a passing test's watch starts over; a failing test stays failing until it passes.
|
|
190
|
+
- `/auth.md` notes that a `202` with `charging: true` carries the workspace's purchase in flight, which may be for a different number of runs than asked.
|
|
191
|
+
- One step order everywhere: Discover, Understand, Sign up, Access, Use, Pay, Manage. `STAGES` in `src/schema/stages.js` now lists `use` before `pay`, the order the funnel, `check` and the README already used, and the older `agent-ready/report@1` is written in that order. A saved report.json with `pay` before `use` still validates: any order with each of the seven stages once is read. The delta against an earlier run counts that run's stages again in the new order, so an unchanged run no longer shows a drop in stages cleared. The `check` tag for a step public pages cannot show is `needs a test run`.
|
|
192
|
+
- The funnel counts every passing step, the same steps the strip shows, not only those before the first stop. It gains `stepsPassing`, that count: the documented steps plus the steps a test verified, the total the headline gives (see the headline entry above). `passed` still counts the steps before the first stop.
|
|
193
|
+
- app.tansohq.com, same release: the dashboard fixes from the October 7 audit. A step test starts with an empty result URL, and without a test profile it tries the product instead of needing a test account. With no runs left the review says what the run costs and pays first. The approval page words a person's own purchase as theirs and says when approving raises the cap. Inconclusive runs read "Inconclusive (free)" everywhere. `/auth.md` and `/llms.txt` show how to run a hosted test with the API, `/openapi.json` declares the success bodies and the 402 `PaymentRequired` body, and the served docs describe `/v1/local-runs` only as used by CLI 0.3. While a purchase is being charged, `POST /v1/purchases` with any key answers `202` with that purchase and `charging: true`, and a run start with no runs left answers `402` with `next_action: "wait"`; Stripe is not called again. The owner can return to an open payment page or close it (`GET /v1/purchases/:id/checkout`, `POST /v1/purchases/:id/checkout/cancel`), which only a signed-in person can call.
|
|
194
|
+
- app.tansohq.com only: a saved test can send alerts. Off until turned on in the test's Alerts or with `PATCH /v1/flows/:id/alerts`. An alert goes out when a passing test is blocked or ends inconclusive twice in a row (`test.failing`) and when it passes again (`test.recovered`), never on every run. Channels: email to the workspace owner's verified sign-in address, sent through AgentMail, and a webhook on a public HTTPS host, signed with HMAC-SHA256 in `Tanso-Signature`, with its secret shown once and rotatable (`POST /v1/flows/:id/alerts/secret`). After a rotation the old secret also signs for 24 hours, as a second `v1`. Webhooks get 5 seconds, follow no redirect, and are retried by the cron up to 5 attempts before they show as failed. `POST /v1/flows/:id/alerts/test` sends a test alert (5 an hour per test, 20 per workspace). Alerts need a workspace a person owns, and only that person changes them, from the Tests page or, for a claimed workspace, the Account page; a key can read them. New error codes: `invalid_webhook_url`, `alerts_email_unavailable`, `alerts_not_configured`, `alerts_test_limited`, `alerts_claim_required`. The npm package is unchanged.
|
|
195
|
+
|
|
196
|
+
## 0.4.3 (2026-10-07)
|
|
197
|
+
|
|
198
|
+
- `check` no longer reads a billing or agent-infrastructure product's own vocabulary as an agent signing up or paying. Recorded across 45 products, the patterns change for marginfront.com (Agent is the customer becomes Person sets up access first: Sign up and Access are handoffs), browser-use.com and exa.ai (no longer Agent is the customer; Pay per request stays), fly.io (Person sets up access first), and stripe.com and vercel.com (no longer Pay per request; Pay is needs_person). Use changes for marginfront.com, aisend.app and moltbook.com (below).
|
|
199
|
+
- A documented signup call has to end in a signup, register or onboard segment (`/agents/register`, `/v3/agents/sign-up`, `/v2/bot_signup`, `sign_up`), or in `agent/identity` (Neon) or `agent/auth` (Firecrawl). A path that only contains `agents` (`POST /v1/agents`, `POST /v1/pricing-plans/:planId/agents`), goes on under the signup path (`POST /agent-signup/{id}/approve`), or is OAuth dynamic client registration (`POST /oauth/register`, `/oauth2/register`, `/connect/register`) does not count.
|
|
200
|
+
- "Agent(s) can sign up" and "an agent creates its own account" count when the clause ends there or says only how ("in one API call", "and get an API key", ", get a key", "— no forms", "(beta)", "for an account", "instantly", "immediately", "automatically", "programmatically"). Not after "no", "not", "never" or "where", and not before a colon.
|
|
201
|
+
- Signup wording is skipped in a sentence about the product's own customers ("your customers", "end users", "guest checkout"), about signup being off ("Agent signup is off"), about a person without an account, about paying with x402 or MPP, or about OAuth dynamic client registration. Signup calls skip the customer sentences.
|
|
202
|
+
- x402 wording is skipped in a sentence about the product's customers, about selling ("Charge for API requests … via HTTP 402", "accept x402 payments", "monetize"), describing the protocol ("x402 is the internet's payment standard"), or paying at another site ("contribute … at climate.stripe.dev"). It is also skipped in sitemaps and on template or example pages. "Now accepts payment … over the x402 protocol" still counts.
|
|
203
|
+
- Sentences run across hard-wrapped lines. Each page gets up to 200 tries per guarded signal, and the sentence search stays within 200 characters of the match. A 2 MB one-line page no longer takes minutes.
|
|
204
|
+
- "Get a secret API key (`mf_sk_*`) from the dashboard" and similar wording ("a", "secret", "live" or "test" before API key, a short aside before "from", "under") reads as a person setting up access first.
|
|
205
|
+
- With no OpenAPI document and no API reference page, a page on the product's own domain that presents its API base URL ("REST API … Base URL: https://api.marginfront.com/v1") and lists at least two endpoints on that domain counts as an API documented in text. `interfaces.api.exists` is then `partial`, with rule `api_base_url_and_endpoints_in_text`, `baseUrl` and `endpointCount`, and Use is `agent_can` from page text, saying no OpenAPI spec was found. The URL has to read as an API: an `api.` host, an `/api` or `/v1` path, or "API" or "REST" just before it. "Your base URL", a `BASE_URL` variable, a tutorial's app URL and another company's base URL do not count. An endpoint written several ways (`/emails`, `/v1/emails`, the full URL) counts once.
|
|
206
|
+
- The Discover reason counts bare URLs in `/llms.txt` as links, once each, without trailing punctuation, and leaves out templated `{…}` URLs, URLs in code and URLs inside markdown links. A file of bare URLs no longer reads "with 0 links". Link text in llms.txt is read up to 500 characters on one line, so a file of unclosed "[" no longer takes seconds.
|
|
207
|
+
- When no way to start is found and docs, auth or similar links were skipped to other hosts that look like the product's own, the onboarding reason adds "Links to other hosts were not read." A host counts when its registrable name is the product's, or the product's plus docs, api, dev, app or hq: acme.io or acmedocs.com for acme.dev, and foo-docs.vercel.app for foo.vercel.app. Third-party docs such as nextjs.org, docker.com and raw.githubusercontent.com are not counted. The interface document gains `otherHostsSkipped`, the number of such hosts.
|
|
208
|
+
- Same-site and same-product checks use the Public Suffix List (`tldts`), so tenants on shared platforms like vercel.app or github.io, and names under suffixes like gov.au, are never read as one product.
|
|
209
|
+
- app.tansohq.com, same release: hosted runs may reach the product's own `api.`, `app.`, `docs.` and similar hosts (exact origin only on shared platforms); a test whose success check it cannot reach is refused when saved; the dashboard uses the tansohq.com look.
|
|
210
|
+
|
|
211
|
+
## 0.4.2 (2026-10-06)
|
|
212
|
+
|
|
213
|
+
- `check` recognizes a product that lets agents sign in with AgentID, AgentMail's OpenID Connect provider for agents, and sets the agent identity pattern with `provider: "AgentID"`, cited like other patterns. What counts, from the product's own pages: a sign-in phrase ("Sign in with AgentID", "signed in to Keenable with AgentID", "Sign-up with **AgentID**", "Archil accepts [AgentID](…)"); "via AgentID", "the AgentID path" or "chooses AgentID" next to sign-in words; "Identity provider: AgentID" or "Issuer: https://auth.agentid.com" on a page written for agents; or the product's own `/auth/agentid` route in its docs or OpenAPI document. Archil and Keenable read as agent identity with the AgentID reasons; Locus and AgentLine keep "Try first, claim later" as the followed path and also list agent identity.
|
|
214
|
+
- The Sign up reason names AgentID, what the agent needs (an AgentMail inbox, an AgentMail key with `app_connect` on, and usually a browser, or the owner finishes in the AgentMail console, or the agent's software registers its own signing key with AgentMail), and whether the docs mention the owner claims near the sign-in. Even then the owner's name and email reach the product only if the agent's key has App: Share Owner or the owner approves. When another agent-first path leads, Sign up and Access add a sentence about the AgentID path.
|
|
215
|
+
- The bare word "AgentID" no longer sets agent identity. Neither do sentences that place the sign-in at another product ("where apps accept it", "add Sign in with AgentID to your app"), integration guides ("Add AgentID to Clerk"), or AgentID's own site. Across the recorded products, agent identity is gone from agentmail.to's and www.agentid.com's detected patterns (both came from the bare name); no primary pattern or step verdict changed.
|
|
216
|
+
- `test` does not change: the harness keeps the AgentMail key away from the agent, so it cannot complete an AgentID sign-in, and the pattern still lists `needs: ["agent_identity"]`.
|
|
217
|
+
- app.tansohq.com, same release: dashboard reads no longer lock and rewrite the workspace, which had made checks fail with `workspace_busy` and stopped hosted runs mid-way while the dashboard polled; a storage error during a hosted run is retried, then reported as ours. The served `/auth.md`, `/llms.txt` and `/openapi.json` state the paid terms from the deployment's own settings. The local file store's lock can no longer be held by two writers at once after a crashed holder, and a restarted container's runs and locks are recovered.
|
|
218
|
+
|
|
219
|
+
## 0.4.1 (2026-10-06)
|
|
220
|
+
|
|
221
|
+
- `test` works without `verify_*` lines. With no `verify_call` in `alg.yml`, it takes one from the product's OpenAPI document: a GET that needs a key (a bearer scheme, or an API key in a header) and has no required parameters, preferring paths like `/me`, `/account`, `/user` and `/whoami`, on `servers[0]`. It reuses the latest `interface.json` from `check`, or reads the public pages the same way. In a terminal it asks before using the call; `--yes` accepts it. An accepted call is saved to `alg.yml` as `verify_call` and `verify_header`, and the file's other lines stay as they were. With nothing to infer from, `test` still exits `2` with `verify_call_invalid`.
|
|
222
|
+
- `agent-ready/verify-plan@1` and `agent-ready/verify@1` gain `checker.inferred` (true when the call was inferred) and `checker.inferredFrom` (the OpenAPI document's URL, or null). `agent-ready/verify@1` also gains `checker.call`. No field was removed or renamed.
|
|
223
|
+
- Report steps say "The agent did this step" and "The agent was stopped here", without "live".
|
|
224
|
+
- app.tansohq.com, same release: hosted test runs are paid. Each workspace gets 5 free a month, then $5.00 per completed run; inconclusive runs and our failures are free. An agent buys runs with `POST /v1/purchases` within a monthly cap ($50 by default, at most $200) that a person approves once through an approval link and Stripe Checkout; while a purchase waits for approval, new requests get that same purchase back, and `POST /v1/purchases/:id/approval-link` replaces a lost link. The dashboard is now Products, Tests, Docs and Account, and calls a saved task a test.
|
|
225
|
+
|
|
226
|
+
## 0.4.0 (2026-10-06)
|
|
227
|
+
|
|
228
|
+
- `audit` is now `check` and `verify` is now `test`. The old names still work, so scripts and the skills keep running. The JSON schema names (`agent-ready/audit-report@1`, `agent-ready/verify@1`) are unchanged.
|
|
229
|
+
- The CLI needs no Tanso account any more: `check` and `test` on your machine are free and send nothing to Tanso. 0.3's workspace (signup, counted runs, claim codes, `--create-account`, exit codes 4, 75 and 77) is gone from the CLI, and `account`, `login` and `logout` now only say that nothing is needed. Paying for runs is planned for the hosted dashboard, where Tanso pays for the model.
|
|
230
|
+
|
|
231
|
+
## 0.3.1 (2026-10-06)
|
|
232
|
+
|
|
233
|
+
- `audit` no longer prints "A person steps in none documented." for a product whose agent holds the account itself; it says no person step is documented.
|
|
234
|
+
- app.tansohq.com, same release: hosted live tests are back on, for workspaces a person owns (an agent's unclaimed workspace gets `403 claim_required` and runs its tests with the CLI). A hosted check proves the agent's key the way `verify` does, with no key and with a wrong key; the check report has the same three questions and fix prompts as `audit` (`GET /v1/runs/:id/audit`); the hosted agent may send only its run's inbox address; planner failures reach the operator log; long response bodies are shortened in reports.
|
|
235
|
+
|
|
236
|
+
## 0.3.0 (2026-10-06)
|
|
237
|
+
|
|
238
|
+
- `verify` counts each run on a free Tanso workspace, the allowance the hosted dashboard uses: 6 starting runs, then 10 a day once a person claims the workspace. Paid runs are planned and have no price yet. The first `verify` asks before creating the workspace, and with `--yes` it needs `--create-account` as well. The key is saved in `~/.config/agent-ready/credentials.json` (0600, per API host), and `AGENT_READY_API_KEY` overrides it.
|
|
239
|
+
- What Tanso receives: a signup label, the start of a run, and its outcome, with your IP address. Never the product, the task or the agent's work. `audit` still sends nothing.
|
|
240
|
+
- New exit codes, each with `next_action` in the JSON error: `4` means no workspace or a refused key, `75` means try later (Tanso unreachable, or today's runs used), and `77` means the starting runs are used and a person must claim. A run Tanso cannot count does not start.
|
|
241
|
+
- New commands: `account` (runs left and claim status; `--claim` prints the claim code), `login` (a key from standard input) and `logout`. `verify --check` and every finished run show the runs left.
|
|
242
|
+
- app.tansohq.com: the Account page takes a claim code and lists claimed workspaces with their runs left and recent CLI runs. New API routes: `POST /v1/local-runs`, `POST /v1/local-runs/:id/finish` and `GET /v1/claimed-workspaces`. Fixed the docs' broken route names, and `auth.md`'s claim and revocation text. The API reference now names agent keys.
|
|
243
|
+
|
|
244
|
+
## 0.2.0 (2026-10-05)
|
|
245
|
+
|
|
246
|
+
- `audit` recognizes a token a person creates that the product's CLI then takes from a flag or an environment variable ("Set the VERCEL_TOKEN environment variable", "use --with-token to pass in a personal access token"), and a CLI that signs in only through a browser. GitHub and Vercel had scored "needs a person" for Sign up and Access because their docs never say "API key in the dashboard"; both now read as a handoff, 5 of 7. Across the 25 products in the October sweep, no other verdict changed.
|
|
247
|
+
- `verify` can test products whose agents start with a CLI. `verify_cli: npm` (or `pypi`) lets the agent install from that registry. Installs, caches and saved CLI logins go under `.tools/` in the run folder, the only place the agent's sandbox can write, and saved logins are scrubbed. Node's `fetch` now goes through the sandbox's proxy (`NODE_USE_ENV_PROXY=1`): without it, any CLI built on `fetch` failed with `ENOTFOUND`.
|
|
248
|
+
- Real runs through each product's own CLI, all passing the three-call check: Mem0 with `mem0 init --agent` (18 turns, $0.16), Neon with `neon init -y --claimable` (18 turns, $0.17) and Cloudflare with `wrangler deploy --temporary` (24 turns, $0.22). Each CLI saved its credential under `.tools/home`, and the agent read it from there. The first Neon and Cloudflare runs used the CLI correctly but saved no key, because their tasks did not say which value was the key; the agent's instructions now say to save the credential even when a CLI keeps it in a file, and the docs say to name the key in `task` when a product returns several secrets.
|
|
249
|
+
- A claim link in the form `?claimToken=…` (Cloudflare's temporary accounts) was not scrubbed from the agent's notes. Any link parameter named like a token is now treated as a secret.
|
|
250
|
+
- Correction to 0.1.7: the Mem0 run did not pass through Mem0's CLI. The CLI installed, `mem0 init --agent` failed with "fetch failed" (the proxy problem above), and the agent then signed up over HTTP. The pass itself stands.
|
|
251
|
+
|
|
252
|
+
## 0.1.9 (2026-10-05)
|
|
253
|
+
|
|
254
|
+
- Two skills replace the old one, which taught agents the hidden `scan` and `crash` commands instead of `audit` and `verify`. `agent-ready` runs the audit; `agent-ready-verify` runs a real agent and, in Claude Code, starts only when you type `/agent-ready-verify`. In fresh Claude Code sessions, "audit neon.com with alg" ran the audit (5 turns, $0.03), "run agent-ready verify on neon.com" showed the plan and pointed to `/agent-ready-verify` without starting a run, and `/agent-ready-verify neon.com` stopped at the plan to ask for a yes.
|
|
255
|
+
- The package is a Claude Code plugin (`claude plugin marketplace add katrinalaszlo/agent-led-growth-cli`), and `npx skills add katrinalaszlo/agent-led-growth-cli` installs the skills for Codex, Cursor and other agents that read `.agents/skills`.
|
|
256
|
+
- `verify --max-budget-usd` caps the agent's model use, default $5. Claude Code checks it after each turn, so a run can end slightly above it, and a run stopped there is inconclusive. The confirmation said a run costs "about $1 to $4", taken from September runs; October runs cost $0.06 to $0.47, and it now says so.
|
|
257
|
+
- README: quickstarts for the terminal, a coding agent and CI, and new sections on cost, accounts and data, and on limits, with the numbers from the code.
|
|
258
|
+
- AGENTS.md ships in the package and the public repository, for agents that use or change the tool.
|
|
259
|
+
|
|
260
|
+
## 0.1.8 (2026-10-05)
|
|
261
|
+
|
|
262
|
+
- A Neon run printed and saved the project's database password: the check `verify_assert: database_url` showed the field's value, and the agent's trace kept the connection string. An assertion with no `=value` now reports only that the field is present, and the scrubber removes the password from any connection string (`postgres://user:password@…`) and Neon's `npg_` tokens, whatever the field is called.
|
|
263
|
+
- `verify --check` shows what a run would do without starting the agent or making a request: Claude Code installed and signed in, the hosts the agent may reach, the inbox, what the agent saves and the calls the checker makes. Exits `0` when ready, `2` when not; `--json` prints `agent-ready/verify-plan@1`. A real run now also stops at the start when Claude Code is signed out, instead of failing inside the agent.
|
|
264
|
+
- The `alg.yml` that `audit` writes lists every optional verify setting with a comment, and says the agent saves its key as `AGENT_READY_KEY` in `work/CREDENTIAL.env`, so the task need not.
|
|
265
|
+
- README: removed a line saying exchanges were unsupported (0.1.7 added them); documented `--check`, how the key is saved, and `execute`.
|
|
266
|
+
- The identity guard's message names the blocked address as the one that is not the test identity; it read as if the blocked address were the identity.
|
|
267
|
+
|
|
268
|
+
## 0.1.7 (2026-10-05)
|
|
269
|
+
|
|
270
|
+
- `verify` checks products that need more than one plain call: `verify_fields` (values the agent saves next to its key, used as `{NAME}` in the call), `POST` calls with `verify_body`, and an exchange step (`verify_exchange`, `verify_exchange_body`, `verify_exchange_token`) that turns the key into the token the check uses. `verify_hosts` lets the agent reach a CLI's package registry or a second domain. Real runs: Neon passed through its assertion-for-token exchange (12 turns, $0.13), Mem0 passed with a `Token` header and its CLI from npm (41 turns, $0.34).
|
|
271
|
+
- A 400 for a missing key counts as refused, alongside 401 and 403: Cloudflare answers that way, and a working Cloudflare key was reported as a failure. A second Cloudflare run used its 40 turns reading docs and got no key, so Cloudflare is not yet confirmed as a pass.
|
|
272
|
+
- Server errors are counted only from real 5xx responses (a status line or field, the reason phrase, or a short label and code on their own line). A bare number in prose had made that Cloudflare run read as an outage. Against every recorded run, only monday.com's real 503s match.
|
|
273
|
+
- When the trace shows no key and the agent's own notes report a 5xx, verify says the result is inconclusive and that it is the agent's report: Inkbox's 500s reached the agent through `curl -s`, which drops the status line.
|
|
274
|
+
|
|
275
|
+
## 0.1.6 (2026-10-05)
|
|
276
|
+
|
|
277
|
+
- The testing agent can no longer use a real person's email address. Claude Code tells the model the signed-in account's email, and two runs (Inkbox, Edge Network) gave it to the product as the account's human contact, one through a script the agent wrote and then ran. A PreToolUse hook now refuses any command, request or written file (other than the agent's own notes) that carries an address other than the test identity's; placeholder domains such as example.com are allowed. The persona instructions say the same. Checked with a real `claude -p` run.
|
|
278
|
+
- Mail is scrubbed of short codes after "code", "OTP", "passcode" or "PIN" and of long links, which in these emails are one-time: a Cosmic run had kept its claim code and a click-tracking claim link.
|
|
279
|
+
|
|
280
|
+
## 0.1.5 (2026-10-05)
|
|
281
|
+
|
|
282
|
+
- `verify` with `AGENTMAIL_API_KEY` set gives each run its own inbox and deletes it afterwards; documented in the README. Real runs: Cosmic (needs an email) and Telnyx (accepts the agent's own email) both passed, $0.15 each.
|
|
283
|
+
- Emails in the run's `inbox/` are scrubbed after the run, and one-time tokens in links (`?token=`, `?code=`, `?claim=`, `?portal_redirect_token=` and similar) are treated as secrets everywhere. The Telnyx run had left a one-time sign-in link in its saved mail: the scrub skipped subfolders and only knew JSON field names.
|
|
284
|
+
|
|
285
|
+
## 0.1.4 (2026-10-05)
|
|
286
|
+
|
|
287
|
+
- The npm package is built into `dist/cli` with its own `package.json` that depends only on `commander` and `aeo-ready`: about 15 MB installed instead of 65 MB, with no server dependencies (`pg`, Clerk, Vercel) and no Playwright. The hidden browser and video commands say how to install Playwright when they need it.
|
|
288
|
+
- Source is public at https://github.com/katrinalaszlo/agent-led-growth-cli, and the package links there.
|
|
289
|
+
- Tests that start the server or read run traces moved into their own files, so the CLI's tests ship with the public source and pass there.
|
|
290
|
+
|
|
291
|
+
## 0.1.3 (2026-10-05)
|
|
292
|
+
|
|
293
|
+
- `audit` writes `audit-report.json` (`agent-ready/audit-report@1`) instead of `audit.json` (`agent-ready/audit@1`). The Claude Code skill writes `audit.json`, in another format, into the same run folder, and `report` and `validate` read that file. Rename any script that reads the old name.
|
|
294
|
+
- `verify` checks that Claude Code is installed before starting and says how to install it, instead of reporting an inconclusive run.
|
|
295
|
+
- The Claude Code skill and `AGENTS.md` name the scoped package (`npx agent-led-growth`).
|
|
296
|
+
- Agents can drive the CLI without a terminal: each audit question has a flag (`--onboarding`, `--abuse-cost`, `--human-before`); with `--json`, every error from audit and verify, including usage errors, is a JSON document on stdout (`agent-ready/error@1`, with `code`, `message` and `hint`); and the audit JSON lists the files it wrote (`files.prompts`, `files.brief`, `files.config`). The README has a section for agents.
|
|
297
|
+
- Every fix prompt carries the owner's answer to "must a verified person exist before the agent acts?", not only the signup prompt, and says to fit the example endpoints to the product's existing API. Found by an agent doing a developer's task with the CLI.
|
|
298
|
+
- The verdict says how many working steps rely on a person handing the agent access, and wraps to 80 columns.
|
|
299
|
+
- Tested on Node 20.20 (the supported floor is 20.9): all tests pass and `audit` runs.
|
|
300
|
+
|
|
301
|
+
## 0.1.2 (2026-10-05)
|
|
302
|
+
|
|
303
|
+
Found by testing the published package as a new user and auditing 13 more companies.
|
|
304
|
+
|
|
305
|
+
- `audit --yes` writes `alg.yml` with the defaults when there is none, so `verify` has a file to read and the prompts' "chosen in alg.yml" is true. It never overwrites an existing file.
|
|
306
|
+
- One score everywhere: the terminal, `audit.json` and `brief.md` all say "Your public pages show N of 7 steps working". The brief had used the older count that stops at the first gap, so Buttondown read 3 of 7 in the terminal and 2 of 7 in the brief.
|
|
307
|
+
- Onboarding detection no longer reads "Agent Mode" (Postman, Copilot) or WhatsApp "Self Sign-up" (Twilio) as an agent signing itself up; Linear, GitHub and Twilio had been told agents can sign up. It now reads "manage your API keys at …" (Buttondown) as a person handing the agent a key.
|
|
308
|
+
- Use counts API operations, not OpenAPI tag groups: Resend went from "15 documented actions" to its real operation count.
|
|
309
|
+
- The product name drops the page title's tagline ("Resend", not "Resend · Email for developers").
|
|
310
|
+
- "Next" gives the prompt's full path from where you ran the command.
|
|
311
|
+
- The README covers only the npm commands, with a complete `alg.yml`; the dashboard and hidden commands moved to `docs/repository-guide.md`.
|
|
312
|
+
|
|
313
|
+
## 0.1.1 (2026-10-05)
|
|
314
|
+
|
|
315
|
+
- README leads with `npx agent-led-growth audit` and `verify`; the hosted dashboard has its own section.
|
|
316
|
+
- Package links point to tansohq.com instead of the private repository.
|
|
317
|
+
- `verify` output wraps long check details to 80 columns.
|
|
318
|
+
- `serve` names the repository by path instead of a GitHub URL the public cannot open.
|
|
319
|
+
|
|
320
|
+
## 0.1.0 (2026-10-05)
|
|
321
|
+
|
|
322
|
+
First release on npm as `agent-led-growth`.
|
|
323
|
+
|
|
324
|
+
- A product on your own machine works end to end: a bare `localhost` or IP address means `http://`, audit saves the full address to `alg.yml`, and the agent's sandbox opens localhost (`allowLocalBinding`, macOS) only when the target itself is local. A run where the agent cannot connect at all is inconclusive, not a failure.
|
|
325
|
+
- The onboarding model you choose drives the fixes: a product whose docs only describe a person handing over a key now gets a signup fix when you choose an agent-first model.
|
|
326
|
+
- Full loop checked on a local sample product: audit (3 of 7 working, 3 fixes), a coding agent applied two prompts (11 turns, $0.68, its 12 tests pass), re-audit (5 of 7, 1 fix left: Pay, not applied), verify PASS in 8 turns for $0.06 with an account the agent created itself.
|
|
327
|
+
- Known limit: a product whose key must be exchanged for a second token before it works (Neon's claimable projects) cannot be checked with one declared call yet.
|
|
328
|
+
|
|
329
|
+
- `verify [url]`: a real agent (local Claude Code) tries the task in `alg.yml` on your own product. The checker is the call you declare (`verify_call`, `verify_header`, `verify_expect`, `verify_assert`), made with the agent's key, with no key and with a wrong key; it passes only when the key works and both others are refused. A call that answers without a key is reported as inconclusive. Asks before creating an account (`--yes` skips). Exit 0 pass or correct handoff, 1 fail with a fix prompt, 2 usage, 3 inconclusive, 130 cancelled. First real run: app.tansohq.com passed in 11 turns for $0.37.
|
|
330
|
+
- The harness takes a task built at run time and can sign up with no inbox. Rewriting `alg.yml` from the audit questions keeps any `verify_*` lines.
|
|
331
|
+
- Secrets a product returns to the agent (fields named key, token, secret, claim code and similar) are learned from each full line of agent output before anything is written, so they are scrubbed from the trace even when the agent never writes `CREDENTIAL.env`. Real runs had left a claim code, and once a full key, in `trace.jsonl`: the event log keeps only the first 400 characters of each result, and `curl -i` headers filled them.
|
|
332
|
+
- The agent no longer inherits the operator's Claude Code setup: `--strict-mcp-config --setting-sources project,local`. Before this, a run loaded the operator's MCP servers (37, including Gmail, Slack and Drive), user hooks, plugins and CLAUDE.md. Runs before this change, including the examples in `examples/signup/`, had that setup loaded; their checker results came from independent API calls, but agent behavior may have been affected.
|
|
333
|
+
- An agent with no output for 5 minutes is stopped and reported as stalled. A run that does not finish (stalled, timed out, stopped) is inconclusive, never a failure of the product.
|
|
334
|
+
|
|
335
|
+
- `audit <url>`: one command for your own product. Reads public pages (GET only), shows the seven steps with how each was found (`from your files`, `from page text`, `needs agent run`), asks three onboarding questions with defaults from your docs, saves the answers to `alg.yml`, and writes `brief.md` plus one fix prompt per gap in `prompts/`. Prompts carry the evidence, the chosen onboarding model, security rules and acceptance tests, and tell the coding agent to check for an existing path before building a new one. `--json` prints `agent-ready/audit@1`; `--fail-on high|medium` exits 1; no answers without a terminal exits 2; a cancel at a question exits 130 and saves nothing.
|
|
336
|
+
- The funnel lists Use before Pay: in every passing live run the agent made real calls on a free key before any payment.
|
|
337
|
+
- Wording no longer claims more than public pages show: a missing signup reads "was not found in the pages read", not "a person has to create the account".
|
|
338
|
+
- Onboarding detection counts a signup call (`POST …/agents/register`, `…/signup`) documented on a page written for agents as agent signup. Moltbook is now recognised as limited until claimed; its recorded pages join the fixture set.
|
|
339
|
+
- `--help` shows `audit` and `execute`. Other commands still run and are hidden from help.
|
|
340
|
+
- `audit` stops instead of scoring a site that did not answer: no DNS record, a refused connection, a timeout or a 5xx exits 3 and writes nothing. A malformed address or a missing one exits 2 with an example. `--help` lists example commands. An answer that is not an option is asked again rather than read as the default.
|
|
341
|
+
- HTTP errors keep their cause code (`fetch failed (ENOTFOUND)`), so a failed fetch says why.
|
|
342
|
+
|
|
343
|
+
- Every check answers in seven steps. `POST /v1/interface` and saved checks carry `funnel` (`agent-ready/funnel@1`): Discover, Understand, Sign up, Access, Pay, Use, Manage, each `agent_can`, `handoff`, `needs_person`, `blocked` or `not_checked`, with the reason, what to build, and its evidence. A documented handoff to a person passes. `GET /v1/runs` includes each check's funnel summary.
|
|
344
|
+
- Dashboard: one URL box for a new workspace, a card per product with its latest steps, and reports that open on the steps with the evidence one click down. Two nouns, Check and Live test. Test it live on a step opens a live test with that step's task already written.
|
|
345
|
+
- Public live tests may follow the product's own subdomains (docs.example.com for example.com), GET only, never to an IP, another port or another site. A redirect that leaves the product now says where it went.
|
|
346
|
+
- Live tests remember the step they prove (`step` on a flow). The latest passed live test for a step shows it as `agent_did` on every check of that product; a blocked one sets `blocked` with the stop reason. Inconclusive tests change nothing.
|
|
347
|
+
- Docs, llms.txt and the README describe the check, the seven steps and live tests.
|
|
348
|
+
|
|
349
|
+
- `interface <url>` and `serve`: URL → structured agent interface (`agent-ready/interface@1`) with observations, evidence-backed facts, rule-based verdicts, unknowns; HTTP API + dashboard; `POST /v1/evaluate` runs a rule-based journey (`agent-ready/journey@1`): discover, understand, choose_interface, authenticate from evidence; execute and recover reported not_run.
|
|
350
|
+
- `execute --task stripe-subscription`: real task harness. Secret boundary (env-only, test-mode only, redacted everywhere), executor interface with a disposable `claude -p` implementation (scratch dir, tool allowlist, sandboxed network allowlist), structured trace, deterministic evaluator, reconciliation of extractor vs agent per stage. First real run in `examples/stripe-subscription/run-01/`.
|
|
351
|
+
|
|
352
|
+
- Seven-stage funnel contract (`discover → understand → signup → access → pay → use → manage`) with four ordered states plus not-tested / not-applicable.
|
|
353
|
+
- `scan`: aeo-ready benchmarks as a sandboxed child plus nine GET-only probes (robots AI rules, agent.json, llms.txt, OpenAPI, pricing.json, catalog pricing, CAPTCHA, signup endpoint, 402 handoff).
|
|
354
|
+
- `crash --smoke`: Playwright walk of pricing and signup pages with screenshots; never submits.
|
|
355
|
+
- Skill for Claude Code / Codex / Cursor / Gemini with the audit step (vendored agent-serve rubrics) and the full crash persona.
|
|
356
|
+
- `report`: merge, delta against history, self-contained HTML, markdown twin, JSON.
|
|
357
|
+
- `demo`: customer-task walkthrough in the tansohq.com demo layout (Before / After, step states, evidence), with `--video` recording to webm/mp4; `crash --smoke --video` records the real browser walk.
|
|
358
|
+
- `replay`: the agent's run played back request by request with its own commentary, recordable with `--video`.
|
|
359
|
+
- `reel`: one mp4 from walkthrough, UI clips, smoke walk and replay.
|
|
360
|
+
- `hero`: the 55-second launch cut, 16:9 and 1:1, captions burned in and as WebVTT; `export`: AV1/VP9 webm and posters; `--label` and page-zoom capture at the delivery frame for demo and replay.
|
|
361
|
+
- Skill: the crash step runs and records the product's crash dummy for the UI half of the funnel, watches the footage, and produces demo, replay and reel.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kat Laszlo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|