Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions docs/audits/claim-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,24 @@ Owner: TASK-013. Source: `docs-site/deployment/index.mdx`, `docker.mdx`, `kubern
Owner: TASK-015. The docs site has no pricing page. `commonly.me/pricing` redirects to the landing
page's pricing section (`frontend/nginx.conf:36`), which renders at
`frontend/src/v2/landing/V2LandingPage.tsx:827` with its copy under `landing.pricing` in
`frontend/src/i18n/locales/en.json:981`.
`frontend/src/i18n/locales/en.json:978`.

Evidence below is `main` at `75d80918e`. Rows marked "Removed here" or "Now" are fixed in the PR that
adds them. Rows that name another PR were already fixed on main.

| Page | Claim | Verdict | Evidence | Date |
|---|---|---|---|---|
| Landing pricing | "10 hosted agent seats" | FALSE | `backend/services/hostedRuntimeService.ts:36` `DEFAULT_AGENTS_PER_USER = 1`, the same on every plan (`:58`). Removed here. | 2026-10-26 |
| Landing pricing | "coming soon, included when it lands" (hosted) | FALSE | Hosted agents run now; per-plan caps are wired in `backend/services/hostedRuntimeService.ts:58-61`. Removed here. | 2026-10-26 |
| Landing pricing | "SSO/SAML" | FALSE | No code: `git grep -i saml origin/main -- backend frontend/src` matches only the copy (`en.json:1021`, `zh-CN.json:1020`). Main already reads "SSO/SAML is planned" (#2856, `bafad4060`). This PR keeps that wording, and the guard allows that phrase and no other SSO/SAML copy. | 2026-10-26 |
| Landing pricing | "federation across instances" | FALSE | Federation is cross-pod inside one instance: `backend/server.ts:271`, `backend/services/federationService.ts:1-5`. `federationProtocol` is only declared in the schema (`backend/models/Installable.ts:242`, `:482`). Removed on main by #2856 (`bafad4060`). | 2026-10-26 |
| Landing pricing | "30 days of message history" (as a flat promise) | FALSE | `backend/services/pgRetentionService.ts:47` (30-day default), `:51` (1-day floor), `:267-296` (steps down under disk pressure). Now "Up to 30 days". | 2026-10-26 |
| Landing pricing | "Pro adds hosted agents" | FALSE | Cloud free gets hosted agents too: the agent cap ignores plan (`backend/services/hostedRuntimeService.ts:58`); the plan only changes turns (`:60-61`). Now "a higher hosted-agent turn cap". | 2026-10-26 |
| Landing pricing | "Pro adds unlimited history" (unscoped) | FALSE | Only pods the buyer created: `backend/services/pgRetentionService.ts:125-150` (the pod's creator governs), `:166` (Pro flag read on the creator). Now "in pods you create". | 2026-10-26 |
| Landing pricing | "Up to 30 days of message history" (Cloud free) | TRUE | `backend/services/pgRetentionService.ts:47,51,267-296`. A ceiling: disk pressure can shorten it. | 2026-10-26 |
| Landing pricing | "Unlimited history in pods you create" (Pro) | TRUE | `backend/services/pgRetentionService.ts:125-150,166`. | 2026-10-26 |
| Landing pricing | "Hosted agents: 200 turns a day per agent, against 30 on Cloud free" | TRUE | Code defaults `backend/services/hostedRuntimeService.ts:38-39`, plan switch `:60-61`, per agent per UTC day `:11-13`. Live env not read: no `HOSTED_TURNS*` override in repo k8s or docs. | 2026-10-26 |
| Landing pricing | "Community listing" (Pro) | TRUE | `backend/routes/pods.ts:768-770`: a non-admin pod creator without `entitlements.pro` gets 402 `pro_required`. | 2026-10-26 |

## Other customer surfaces

Expand All @@ -125,7 +139,7 @@ the FAQ, and `CONTRIBUTING.md`. The section is complete when every surface in th
| Page | Claim | Verdict | Evidence | Date |
|---|---|---|---|---|
| In-app Plan (`billing.proNote`) | "…and hosted agent seats when they land." | FALSE | Hosted agents have shipped. `backend/services/hostedRuntimeService.ts:36` gives a free account one agent (`DEFAULT_AGENTS_PER_USER = 1`). The key has no call site, so the sentence is removed with it. | 2026-10-26 |
| In-app Plan (`billing.freeNote`) | "Unlimited agents you bring, and 30 days of message history. …" | CUT | No call site in `frontend/src` or `backend`. The only other match is a fixture label at `frontend/src/i18n/__tests__/zhNumberUnitSpacing.test.ts:254`, which reads no catalog value. The key is removed. | 2026-10-26 |
| In-app Plan (`billing.freeNote`) | "Unlimited agents you bring, and 30 days of message history. …" | CUT | No call site in `frontend/src` or `backend`. The only other match is a fixture label at `frontend/src/i18n/__tests__/zhNumberUnitSpacing.test.ts:256`, which reads no catalog value. The key is removed. | 2026-10-26 |
| Landing, open-source list (`landing.openSource.items.federation`) | "Federation on the roadmap. Agents on different instances will interact — ActivityPub for agents." | CUT | `git grep -i activitypub` finds nothing under `backend`, `frontend/src` or `docs-site`. The federation code that exists is cross-pod queries (`backend/services/federationService.ts:1-5`). The bullet is removed; it can return with a shipped track or a walk. | 2026-10-26 |
| CONTRIBUTING.md | "pick up an open issue labeled `good first issue` on GitHub" (the label-query link on main before this PR) | FALSE | `gh issue list -R Team-Commonly/commonly --label "good first issue" --state open` returned 0 on 2026-10-26, so the link opened an empty list. The earlier task-board link, `app-dev.commonly.me/pods/team`, was already dead (`CLAUDE.md`, Quick Start). This PR replaces the link with the open-issues list, which had 138 open issues on 2026-10-27. | 2026-10-27 |
| CONTRIBUTING.md | "you can install it into the public Commonly instance" (OpenClaw) | TRUE | The provider route exists: `backend/routes/providers/moltbot.ts:4`. This row checks the code path only, not a contributor install on commonly.me. | 2026-10-26 |
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -978,7 +978,7 @@
"pricing": {
"kicker": "Pricing",
"title": "Humans are seats. Agents never are.",
"sub": "Self-host free forever under Apache-2.0. On the hosted plans, agents you bring connect free and unlimited — on every tier, forever. Pro adds unlimited history, Community listing and hosted agents. Never per agent.",
"sub": "Self-host free forever under Apache-2.0. On the hosted plans, agents you bring connect free and unlimited — on every tier, forever. Pro adds unlimited history in pods you create, Community listing and a higher hosted-agent turn cap. Never per agent.",
"zero": "$0",
"selfHost": {
"name": "Self-host",
Expand All @@ -998,7 +998,7 @@
"items": {
"unlimited": "Unlimited BYO agents — they run on your machines, connect free",
"private": "Private and invited pods",
"history": "30 days of message history",
"history": "Up to 30 days of message history",
"connect": "Connect via webhook, CLI wrapper, or MCP",
"card": "No credit card"
}
Expand All @@ -1012,7 +1012,7 @@
"everything": "Everything in Cloud free",
"history": "Unlimited history in pods you create — nothing expires at 30 days",
"community": "List your pods in Community so your team can find them",
"hosted": "10 hosted agent seats — our compute, zero setup (coming soon, included when it lands)",
"hosted": "Hosted agents: 200 turns a day per agent, against 30 on Cloud free — our compute, zero setup",
"support": "Priority support"
}
},
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@
"pricing": {
"kicker": "定价",
"title": "人类占席位,智能体永远不占。",
"sub": "基于 Apache-2.0,自托管永久免费。托管版中,你自带的智能体在所有档位都免费且不限数量——永远如此。Pro 增加无限历史记录、社区收录与托管智能体。绝不按智能体收费。",
"sub": "基于 Apache-2.0,自托管永久免费。托管版中,你自带的智能体在所有档位都免费且不限数量——永远如此。Pro 增加你创建的 Pod 内无限历史记录、社区收录,以及更高的托管智能体每日轮数上限。绝不按智能体收费。",
"zero": "$0",
"selfHost": {
"name": "自托管",
Expand All @@ -997,7 +997,7 @@
"items": {
"unlimited": "不限数量的自带智能体 —— 跑在你自己的机器上,免费接入",
"private": "私密 Pod 与邀请制 Pod",
"history": "30天消息历史",
"history": "最长30天消息历史",
"connect": "通过 webhook、CLI wrapper 或 MCP 接入",
"card": "无需信用卡"
}
Expand All @@ -1011,7 +1011,7 @@
"everything": "包含 Cloud free 的全部功能",
"history": "你创建的 Pod 内消息历史无限 —— 不再有30天过期",
"community": "把你的 Pod 收录进「社区」,方便团队找到",
"hosted": "10个托管智能体席位 —— 我们的算力,零配置(即将推出,上线即包含)",
"hosted": "托管智能体:每个智能体每天200轮,云端免费版为30轮 —— 我们的算力,零配置",
"support": "优先支持"
}
},
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/v2/__tests__/pricing-copy-invariants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,41 @@ describe('landing pricing copy', () => {
expect(zhCN.landing.pricing.pro.price).toBe(en.landing.pricing.pro.price);
});
});

/**
* Claims the TASK-015 walk checked against code and found false. Each is a
* promise a buyer would hold us to: SSO/SAML and cross-instance federation have
* no code behind them, the hosted caps are 1 agent per user on every plan, and
* hosted agents shipped, so "coming soon" is wrong. The history line keeps its
* "up to": disk pressure can shorten retention below 30 days. Unlimited history
* is a Pro promise only for pods the buyer created: the pod's creator governs
* retention, not any member.
*/
describe('landing pricing claims that code does not back', () => {
Object.entries(LOCALES).forEach(([locale, bundle]) => {
test(`${locale}: no SSO/SAML, federation, hosted-seat, or coming-soon promise`, () => {
// "SSO/SAML is planned" is the one allowed mention (main, #2856). Strip it
// first, so any other SSO/SAML copy still fails.
const pricing = JSON.stringify(bundle.landing.pricing).replace(/SSO\/SAML (is planned|已在计划中)/g, '');
expect(pricing).not.toMatch(/SSO|SAML|federation across|跨实例联邦/);
expect(pricing).not.toMatch(/10 hosted agent seats|10个托管智能体席位|coming soon|即将推出/);
});
});

test('message history is stated as a ceiling, not a guarantee', () => {
expect(en.landing.pricing.cloud.items.history).toMatch(/^Up to 30 days/);
expect(zhCN.landing.pricing.cloud.items.history).toMatch(/^最长30天/);
});

test('Pro unlimited history is scoped to pods the buyer creates', () => {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
expect(en.landing.pricing.sub).toMatch(/unlimited history in pods you create/);
expect(zhCN.landing.pricing.sub).toMatch(/你创建的 Pod 内无限历史记录/);
});

test('hosted-agent turn caps are stated per agent per day, at the plan defaults', () => {
// 200 and 30 are the plan defaults in hostedRuntimeService.ts. Pinning both
// numbers and the per-agent scope fails if either limit or the scope changes.
expect(en.landing.pricing.pro.items.hosted).toMatch(/200 turns a day per agent, against 30 on Cloud free/);
expect(zhCN.landing.pricing.pro.items.hosted).toMatch(/每个智能体每天200轮,云端免费版为30轮/);
});
});
Loading