Claude Opus 5 评测:Anthropic的新款值得入手吗?

Claude Opus 5 评测:Anthropic的新款值得入手吗?

Claude Opus 5 评测:Anthropic的新款值得入手吗?

事实核查日期:2026年7月28日。.

简评: 这篇关于 Claude Opus 5 的评测发现,对于编码代理、复杂业务工作流以及希望获得接近前沿性能却无需始终为 Fable 5 付费的买家而言,这是一款极具吸引力的高端机型。 Anthropic 的计费标准为每百万输入令牌 $5,每百万输出令牌 $25;该模型支持 100 万令牌的上下文窗口,并在同步 Messages API 中支持最多 128,000 个输出令牌。 对于简单的聊天、简短摘要或高量低值的请求,它并非自动的最佳选择。.

最具说服力的论据在于其实用性而非夸张的宣传:Opus 5 既具备强大的推理余量,其经济性又比 Anthropic 的前沿级产品更易于掌控。 在我们进行的一次调试测试中,该模型准确发现了前缀匹配漏洞,提出了最小的补丁方案,添加了一个针对性的回归测试,并给出了一个在本地通过验证的命令。这对该任务而言是有力的证据——但并非证明该模型能在所有编程工作中胜出。.

最适合 编码代理、长上下文分析、企业自动化,以及那些因代价高昂的失败而需要采用溢价模式的团队。. 以下情况请跳过: 速度和单位成本比推理质量的最后阶段更为重要。Simplified Chinese (Mainland).

什么是 Claude Opus 5?

Claude Opus 5 是 Anthropic 专为复杂代理编码和企业级工作打造的高端日常机型。. Anthropic 于 2026 年 7 月 24 日发布了这一消息, ,称其设计周到、主动性强,且比其他模型更高效。它取代了 Claude Opus 4.8,成为 Claude Max 上的默认模型,并成为 Claude Pro 上性能最强的模型。.

Anthropic公告显示了Claude Opus的5个标题、2026年7月24日的发布日期以及“今日上线”的声明
Anthropic 于 2026 年 7 月 24 日发布了 Claude Opus 5,并表示该产品当天即可供货。.

这款产品的宣传方式对于Opus的发布而言颇为罕见:它并非仅被定位为一款智能程度最高的机型。Anthropic希望用户能将其作为日常工具使用,既能灵活调整运算强度,又具备适中的延迟表现。 这使得该模型更适合处理运行时间较长的代理和复杂的生产任务,而较简单的工作负载仍可分流至更快、更经济的模型上。.

访问方式取决于具体途径。普通用户可通过符合条件的 Claude 套餐使用 Opus 5;开发者则可通过 Claude API 及受支持的云平台调用该服务。GlobalGPT 还设有专门的产品页面。想要比较 Anthropic 订阅档位的读者可使用 Claude 免费版、专业版和高级版套餐对比 在选择计费方式之前。.

Claude Opus 5 价格、API 和主要规格

官方 Claude API价格每百万输入代币为 $5每百万个产出代币为 $25. 这些是基础 API 费率,并非 Claude 消费者订阅或第三方平台套餐的价格。提示缓存和批量处理有单独的费率,因此请比较完整的请求模式,而不是仅将标称输入价格进行乘法计算。.

字段Claude Opus 5是什么意思
Claude API ID克劳德-作品第5号在官方 Claude API 请求中,请使用此确切的模型值。.
基准输入价格$5 / MTok缓存或批量折扣前的标准输入令牌费率。.
基准出厂价$25 / MTok输出密集型代理的成本可能会迅速上升。.
上下文窗口100 万代币适用于大型存储库和文档集合,具体取决于检索请求的质量和检索策略。.
最大输出128K 代币适用于同步消息 API;消息批处理则有独立的测试版路径,上限为 30 万条。.
可靠的知识阈值2026年5月按模型标准来看算是最新的,但不能替代实时检索。.
延迟比较中度这不是 Anthropic 最快的模型;延迟仍会因操作方式、工具和工作负载的不同而有所变化。.
Claude 平台文档中的表格,显示了 Claude Opus 5 的 API ID 和别名
Claude 平台将 claude-opus-5 识别为当前的 Opus 5 API ID 和别名。.
Claude 平台文档中的表格,展示了 Claude Opus 5 的定价、适用场景、最大输出及截止规格
Claude 平台将 Opus 5 的定价定为每百万输入/输出令牌 $5/$25,其上下文窗口为 100 万令牌,最大输出为 12.8 万令牌,截止日期为 2026 年 5 月。.
Claude 平台文档:Claude Opus 5 的上下文、输出和截断行
Claude 平台列出的参数包括 1M 上下文窗口、128k 最大输出以及 2026 年 5 月的截止日期。.

关于消费者访问,, Anthropic 系列中的 Claude Pro 当 $200 按年计费时,按月费用为 $20;若按月计费,则为 $17;Claude Max 的起始月费为 $100。 Anthropic指出,Opus 5是Pro版本中最强大的型号,也是Max版本的默认配置,但套餐配额和产品功能与按量计费的API使用量是分开的。.

如果您需要更详细的费用明细,请参阅 Claude AI 套餐及 API 定价指南 将用户订阅、API 计费和使用限制区分开来。这种区分很重要:“包含在套餐中”并不意味着 API 调用次数无限制,而且 API 费率也无法说明您能获得多少用户聊天访问权限。.

Claude Opus 5 基准测试结果

重要边界: 下图所示的数据是 由 Anthropic 发布的基准测试结果, ,这些并非为本评测专门进行的独立测试。它们有助于理解 Anthropic 在性能与成本方面的定位,但并不能保证在您的提示词、工具、代码库或延迟预算下也能获得相同的结果。.

评估Anthropic 公开的声明如何阅读
Frontier-Bench v0.1Opus 5 的性能是 Opus 4.8 的两倍多,且每项任务的成本更低。.这是一个广泛的代理性能信号,而非普遍的两倍提升。.
CursorBench 3.2在全力运行时,Opus 5 的得分与 Fable 5 的峰值得分仅相差 0.5%,而每项任务的成本仅为后者的二分之一。.在 Anthropic 的经过验证的努力设置下,编码代理的经济性表现强劲。.
Zapier AutomationBench在每项任务成本相同的情况下,其通过率约为排名第二的通过率的1.5倍。.在端到端业务自动化方面前景可期;但工作流设计依然至关重要。.
OSWorld 2.0以仅略高于Fable 5最佳成绩三分之一的价格,超越了该成绩。.该基准测试结果表明,该计算机的使用效率颇具吸引力。.
Anthropic 公告文本,其中包含 Claude Opus 5 CursorBench 3.2 的性能与成本对比
Anthropic 表示,Opus 5 的 CursorBench 3.2 最高得分已逼近 Fable 5 的峰值,差距仅为 0.5%,且每任务成本仅为后者的二分之一。.
Anthropic 基准测试文本,对比 Zapier AutomationBench 和 OSWorld 2.0 上的 Claude Opus 5
Anthropic 报告称,在 Zapier AutomationBench 测试中,其通过率比其他产品高出 1.5 倍,并在 OSWorld 2.0 测试中展现出成本优势。.

投入是结果的一部分。Anthropic 指出,Opus 5 在 Claude API 和 Claude 代码中默认采用高投入模式,而其对比测试也使用了高、x高或最大设置。 更高的计算强度虽能提高高难度任务的成功率,但也会增加代币消耗、延迟,或两者兼而有之。因此,每项任务的基准成本比单纯的每代币价格更能反映实际情况——但无论哪种指标,都无法替代针对您自身工作负载进行的实际测试。.

我们如何测试 Claude Opus 5

我们针对一个由三个文件组成的 CommonJS 测试环境,执行了一项紧凑的根本原因排查任务。该任务要求模型在进行修改前先找出根本原因,提出尽可能小的修复方案,添加针对性的回归测试,避免进行无关的修改,并提供精确的验证命令。.

随后,我们独立核查了该补丁,而不是仅仅因为答案听起来很肯定就直接将其视为正确。该本地命令是 node --test test/account-summary.test.cjs. 在修复之前,该测试套件产生了一次通过和一次失败。应用精确相等性补丁后,该测试套件产生了两次通过和零次失败。.

该方法为我们提供了一些关于某种调试工作流的有用信息:诊断、补丁规范、回归测试质量以及可验证性。它并不衡量广泛的编码领导力、长期的代理可靠性、速度, nor 跨语言的性能。.

Claude Opus 5 实机评测

根本原因排查:准确、精简且可验证

在我们的测试中,Claude Opus 5 正确地将故障定位到了 normalizedQuery.startsWith(account.id.toLowerCase()). 使用以下查询 ACCT-10, ,前缀检查匹配成功 acct-1 首先,所以 Array.prototype.find 在找到确切的ID之前,返回了错误的账户。.

该修复方案将前缀匹配改为精确匹配,并为带填充符的、大小写混合的 ACCT-10 输入。它没有重写无关的代码。这种克制在实际的代码库中至关重要,因为范围过广的“清理”可能会产生比原始 bug 更多的代码审查工作量。.

最精彩的部分是完整的闭环流程:找出根本原因,解释现有测试为何未能发现该问题,进行最小的修改,添加正确的回归测试,并给出用于验证的命令。这一结果与Opus 5作为编码代理的定位相一致,但目前仍仅限于一个测试用例。如需了解更全面的工作流入门指南,请参阅 如何使用克劳德人工智能进行编码.

T1–T4 完整题目、答案及可复制的代码

T1:根本原因排查

通过——发现了前缀匹配缺陷,提出了最小的补丁,并添加了一个针对性的回归测试。.

Claude Opus 5 个动手实践的根本原因排查结果
确定了前缀匹配是缺陷所在;解释了旧测试为何未能发现该缺陷;提出了“精确相等加一”的回归测试方案。.
查看完整的T1题目和答案
完整的提示语
您正在调试一个特意设计得非常简单的 CommonJS 测试环境。请仅基于以下三个文件和所述的重现步骤进行调试。

要求:
1. 在提出任何修改建议之前,请先说明根本原因。
2. 提出能修复该 bug 的最小补丁。
3. 添加一个针对性强的回归测试,该测试在修复前应失败,修复后应通过。
4. 提供从测试环境根目录运行的精确验证命令。
5. 请勿重写无关代码。请勿重命名文件、添加依赖项或更改公共 API。
6. 请按以下顺序精确返回这些部分:`ROOT CAUSE`、`PATCH`、`VERIFICATION`、`LIMITATIONS`。
7. 在 `PATCH` 部分,请在带围栏的 `diff` 代码块中提供一个统一的差异(unified diff)。在 `VERIFICATION` 部分,请在带围栏的 `text` 代码块中提供一条命令。

重现步骤:`summarizeAccount(accounts, ' ACCT-10 ')` 应返回 `{ id: 'acct-10', name: 'Nimbus', seats: 24 }`,但实际返回了 `acct-1` 账户。

文件:`src/find-account.cjs`
```js
function findAccount(accounts, query) {
  const normalizedQuery = query.trim().toLowerCase();
  return accounts.find((account) =>
    normalizedQuery.startsWith(account.id.toLowerCase()),
  );
}

module.exports = { findAccount };
```

文件:`src/account-summary.cjs`
```js
const { findAccount } = require('./find-account.cjs');

function summarizeAccount(accounts, requestedId) {
  const account = findAccount(accounts, requestedId);
  if (!account) return null;
  return { id: account.id, name: account.name, seats: account.seats };
}

module.exports = { summarizeAccount };
```

文件:`test/account-summary.test.cjs`
```js
const test = require('node:test');
const assert = require('node:assert/strict');
const { summarizeAccount } = require('../src/account-summary.cjs');

const accounts = [
  { id: 'acct-1', name: 'Atlas', seats: 5 },
  { id: 'acct-10', name: 'Nimbus', seats: 24 },
];

test('汇总指定账户 ID'),() => {
  assert.deepEqual(summarizeAccount(accounts, 'acct-1'), {
    id: 'acct-1',
    name: 'Atlas',
    seats: 5,
  });
});
```
Claude Opus 5

根本原因

findAccount 根据前缀进行匹配,而非根据完全相等性:

js
normalizedQuery.startsWith(account.id.toLowerCase())
normalizedQuery.startsWith(account.id.toLowerCase())

Array.prototype.find 返回第一个满足谓词条件的元素。 对于‘ACCT-10‘,规范化后的查询为‘acct-10’,而第一个账户的 ID‘acct-1’是其前缀,因此 startsWith 返回 true,且 acct-1 会在 acct-10 被测试之前就终止搜索。.
trim().toLowerCase() 的规范化处理是正确的——空格和大小写并不是问题所在。summarizeAccount 只是一个传递函数,并不存在问题。.
现有的测试无法检测到这一点:‘acct-1’既是其自身的后缀,又是第一个元素,因此对于该输入,后缀匹配和精确匹配无法区分。.

PATCH

diff
--- a/src/find-account.cjs+++ b/src/find-account.cjs@@ -1,8 +1,8 @@ function findAccount(accounts, query) {   const normalizedQuery = query.trim().toLowerCase();-  return accounts.find((account) =>-    normalizedQuery.startsWith(account.id.toLowerCase()),-  );+  return accounts.find(+    (account) => account.id.toLowerCase() === normalizedQuery,+  ); }  module.exports = { findAccount };--- a/test/account-summary.test.cjs+++ b/test/account-summary.test.cjs@@ -14,3 +14,11 @@ test('summarizes an exact account ID', () => {     seats: 5,   }); });++test('matches the full ID rather than a prefix, with padding and mixed case', () => {+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {+    id: 'acct-10',+    name: 'Nimbus',+    seats: 24,+  });+});
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('汇总精确的账户 ID', () => {
 seats: 5,
   });
 });
+
+test('匹配完整的 ID 而非前缀,包含填充字符且大小写不分', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});

修复之前,新测试在 acct-1 / Atlas / 5 对象上会失败;修复后则通过了。.

验证

文本
node --test test/account-summary.test.cjs
node --test test/account-summary.test.cjs

限制条款

• 范围:更改了一个运算符。未进行重命名,未新增依赖项,且 findAccount / summarizeAccount 的签名和返回类型均保持不变。.
• 原有行为保持不变(不在此错误的范围之内):
• 若 requestedId 不是字符串(null 或数字),在调用 .trim() 时仍会抛出异常。.
• 账户 ID 本身不会被截断,因此存储的‘acct-10’仍无法匹配——只有查询条件会被规范化。.
• 区分大小写时使用简单的 toLowerCase() 方法;不进行 Unicode 规范化处理,也不进行基于区域设置的折叠处理。.
• 重复的 ID 仍会解析为第一个匹配项,且查找操作的时间复杂度仍为 O(n)。.
• 测试覆盖率:该单个回归测试仅针对报告的复现情况。未找到(空)路径和格式错误的输入仍未经过测试。.

ROOT CAUSE
findAccount matches by prefix, not by equality:

```js
normalizedQuery.startsWith(account.id.toLowerCase())
```

Array.prototype.find returns the first element satisfying the predicate. For ' ACCT-10 ' the normalized query is 'acct-10', and the first account's ID 'acct-1' is a prefix of it, so startsWith is true and acct-1 short-circuits the search before acct-10 is ever tested.
The trim().toLowerCase() normalization is correct — whitespace and casing are not the problem. summarizeAccount is a pass-through and is not at fault.
The existing test cannot catch this: 'acct-1' is a prefix of itself and is the first element, so prefix matching and exact matching are indistinguishable for that input.
PATCH

```diff
--- a/src/find-account.cjs
+++ b/src/find-account.cjs
@@ -1,8 +1,8 @@
 function findAccount(accounts, query) {
   const normalizedQuery = query.trim().toLowerCase();
-  return accounts.find((account) =>
-    normalizedQuery.startsWith(account.id.toLowerCase()),
-  );
+  return accounts.find(
+    (account) => account.id.toLowerCase() === normalizedQuery,
+  );
 }

 module.exports = { findAccount };
--- a/test/account-summary.test.cjs
+++ b/test/account-summary.test.cjs
@@ -14,3 +14,11 @@
 test('summarizes an exact account ID', () => {
     seats: 5,
   });
 });
+
+test('matches the full ID rather than a prefix, with padding and mixed case', () => {
+  assert.deepEqual(summarizeAccount(accounts, ' ACCT-10 '), {
+    id: 'acct-10',
+    name: 'Nimbus',
+    seats: 24,
+  });
+});
```

Before the fix the new test fails with the acct-1 / Atlas / 5 object; after the fix it passes.
VERIFICATION

```text
node --test test/account-summary.test.cjs
```

LIMITATIONS
• Scope: one operator changed. No renames, no new dependencies, and findAccount / summarizeAccount signatures and return shapes are unchanged.
• Pre-existing behavior left alone (out of scope for this bug):
• A non-string requestedId (null, a number) still throws on .trim().
• Account IDs themselves are not trimmed, so a stored ' acct-10' still will not match — only the query is normalized.
• Casing uses plain toLowerCase(); no Unicode normalization or locale-aware folding.
• Duplicate IDs still resolve to the first match, and lookup remains O(n).
• Test coverage: the single regression test targets exactly the reported reproduction. The not-found (null) path and malformed input remain untested.

T2:账户健康状况分析

不完整——计算了核心指标并确定了行动优先级,但捕获的答案末尾缺少要求的“重新检查”标记。.

Claude Opus 第5次实践性账户健康状况分析结果
计算得出 $34,800 个高风险 MRR(94.31%);已将 E-505 升级并排序后续行动;答复结束时未包含所要求的“重新检查”标记。.
查看完整的T2题目和答案
完整的提示语
将提供的 `account-health.csv` 作为封闭数据集进行分析。请勿使用外部事实,也不要自行填补缺失值。

风险规则(请分别评估每条规则):
- `inactivity`:`days_since_login >= 30`
- `payment`:`failed_payments >= 2`
- `low_utilization`:`seats_used / seats_purchased = 80`。
- `weak_health_without_risk`:账户虽未处于“at-risk”状态,但 `health_score = 9` 且 `open_tickets >= 3`。

要求:
1. 计算每个账户触发的风险标记和矛盾标记。
2. 报告以下数据集的总计:账户数、MRR、处于风险中的账户数、处于风险中的 MRR、需升级处理的账户数、矛盾行数、已购买席位数以及已使用席位数。
3. 生成一个精确包含五列的行动表:`账户 | 风险触发项 | 矛盾项 | 优先级 | 建议行动`。
4. 将直接计算的数值置于 `测量事实` 标题下,将判断性决策置于 `推断` 标题下。
5. 在 `复核` 部分,展示足够的计算过程,以便独立复核每个总计和每个阈值边界,包括 0.50 的等值情况。
6. 不要在未说明的情况下自行修正或重新解释规则。如果某个信号看似违反直觉,应将其记录为矛盾项,而非更改其分类。

`account-health.csv`:
```csv
account_id,account_name,plan,mrr_usd,days_since_login,failed_payments,seats_purchased,seats_used,health_score,nps,open_tickets
A-101,Aster,Enterprise,12000,45,0,100,82,92,9,1
B-202,Beacon,Pro,4200,4,2,20,18,70,7,0
C-303,Cinder,Pro,3600,12,0,20,8,65,10,4
D-404,Dahlia,Starter,900,5,0,5,4,42,6,0
E-505,Ember,Enterprise,15000,65,3,200,70,35,3,6
F-606,Fjord,Starter,1200,29,1,4,2,85,9,3
```
Claude Opus 5

经核实的事实

数据源:account-health.csv,6 行,被视为已关闭。未进行任何值插补。.

按账户评估规则

账户
天数≥30
失败≥2
util <0.50(简体中文(大陆))
风险计数
现状
A-101 紫菀
✅ 45
❌ 0
❌ 0.82
1
高风险
B-202 信标
❌ 4
✅ 2
❌ 0.90
1
高风险
C-303 灰烬
❌ 12
❌ 0
✅ 0.40
1
高风险
D-404 大丽花
❌ 5
❌ 0
❌ 0.80
0
不属于高风险人群
E-505 Ember
✅ 65
✅ 3
✅ 0.35(简体中文(大陆))
3
高风险 + 升级处理
F-606 峡湾
❌ 29
❌ 1
❌ 0.50
0
不属于高风险人群
每个账户的矛盾标记
账户
强健体魄与风险
健康状况不佳且无风险
手持门票的推广员
A-101 紫菀
✅ (92 ≥ 80,高风险)

❌(NPS 9 ✓,工单 1 ✗)
B-202 信标
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 灰烬
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10,票数 4)
D-404 大丽花

✅ (42 < 50,不属于高风险人群)
❌ (NPS 6)
E-505 Ember
❌ (35 < 80)
❌(35 < 50,但属于高风险人群)
❌ (NPS 3)
F-606 峡湾
❌ (85 ≥ 80,但不属于高风险人群)
❌ (85 ≥ 50)
✅ (NPS 9,票数 3)
数据集总计
公制
价值
账户
6
MRR总额
$36,900
高风险账户
4(A-101、B-202、C-303、E-505)
面临风险的MRR
$34,800(占总数的94.31%)
升级账户
1 (E-505)
矛盾行
4(A-101、C-303、D-404、F-606)
矛盾标记
4(1 个“健康良好且有风险”,1 个“健康欠佳且无风险”,2 个“持票推广者”)
已购买的座位
349
已使用的座位
184
推论
下文中的优先级排序和建议措施均基于主观判断,而非规则生成的结果。我的排序权重优先考虑状态升级,其次是面临风险的月经常性收入(MRR),然后是矛盾信号。.
账户
风险触发因素
矛盾
优先权
建议采取的行动
E-505 Ember
闲置、付款、低利用率

P0
这三条规则均在最大客户账户($15,000 MRR)上触发。将其视为活跃流失客户:恢复支付方式,然后对130个未使用的席位进行高管审查。.
A-101 紫菀
不活动
强健体魄与风险
P1
$12,000 MRR,尽管评分达92且82%利用率良好,但存在45天的停用期。在根据该评分采取行动之前,请核实登录间隔是真实的用户流失,还是追踪机制导致的偏差(如单点登录、仅API使用)。.
C-303 灰烬
低利用率
手持门票的推广员
P1
一名推广员(NPS 10)持有4张待处理工单,利用率为40%。工单积压可能是阻碍采用的主要因素;请先清理队列,然后推动座位激活。.
B-202 信标
付款

P2
典型单一原因案例:2笔支付失败,最近登录时间为4天,TP40T利用率为901。仅需进行账单跟进,无需客户服务介入。.
F-606 峡湾

手持门票的推广员
P3
各项指标均刚好处于临界值内(29天,1次付款失败,利用率恰好为0.50)。根据规则目前尚不处于风险状态,但若再多一天未活跃或再发生一次付款失败,情况就会发生逆转。请密切关注并处理好这3张工单。.
D-404 大丽花

健康状况不佳且无风险
P3
在 $900 MRR 上,得分 42,未触发任何规则,TP40T 利用率为 801。二者之一

实测数据
来源:account-health.csv,6行,视为已关闭。未进行任何值插补。
按账户规则评估
账户
天数≥30
失败次数≥2
利用率 <0.50
风险计数
状态
A-101 Aster
✅ 45
❌ 0
❌ 0.82
1
高风险
B-202 Beacon
❌ 4
✅ 2
❌ 0.90
1
高风险
C-303 Cinder
❌ 12
❌ 0
✅ 0.40
1
存在风险
D-404 Dahlia
❌ 5
❌ 0
❌ 0.80
0
不存在风险
E-505 Ember
✅ 65
✅ 3
✅ 0.35
3
存在风险 + 升级
F-606 峡湾
❌ 29
❌ 1
❌ 0.50
0
无风险
按账户划分的矛盾标记
账户
健康状况良好但存在风险
健康状况较弱但无风险
推广者且工单量较大
A-101 紫菀
✅ (92 ≥ 80,存在风险)
❌
❌ (NPS 9 ✓,工单 1 ✗)
B-202 Beacon
❌ (70 < 80)
❌ (70 ≥ 50)
❌ (NPS 7)
C-303 辛德
❌ (65 < 80)
❌ (65 ≥ 50)
✅ (NPS 10, 工单 4)
D-404 大丽花
❌
✅ (42 < 50,无风险)
❌ (NPS 6)
E-505 余烬
❌ (35 < 80)
❌ (35 < 50,但存在风险)
❌ (NPS 3)
F-606 Fjord
❌ (85 ≥ 80,但不属于高风险)
❌ (85 ≥ 50)
✅ (NPS 9,工单 3)
数据集总计
指标
数值
账户数
6
总 MRR
$36,900
面临风险的账户
4 (A-101, B-202, C-303, E-505)
面临风险的 MRR
$34,800(占总量的94.31%)
需上报的账户
1(E-505)
矛盾行
4(A-101、C-303、D-404、F-606)
矛盾标记
4 个(1 个“健康状况良好但存在风险”,1 个“健康状况较差但无风险”,2 个“推广者且票务负荷过重”)
已购座位
349
已使用座位
184
推断
下文的优先级排序和建议措施均为判断性决策,而非规则输出。 我的排序权重优先考虑状态升级,其次是存在风险的月经常性收入(MRR),最后是矛盾信号。
账户
风险触发因素
矛盾情况
优先级
建议措施
E-505 Ember
闲置、支付问题、低利用率
—
P0
最大账户($15,000 MRR)触发了全部三条规则。将其视为活跃流失:恢复支付方式,随后针对130个未使用席位进行高管审查。
A-101 Aster
无活动
健康状况良好但存在风险
P1
$12,000 MRR,尽管评分92且健康利用率达82%,但已停用45天。在根据评分采取行动前,需核实登录间隔是真实流失还是追踪异常(单点登录、仅API使用)。
C-303 Cinder
低利用率
票务负担较重的推广者
P1
推广者(NPS 10)持有 4 张未解决工单,利用率为 40%。工单负担可能是阻碍采用的合理因素;先清理工单队列,再推动席位激活。
B-202 Beacon
payment
—
P2
原因单一的典型案例:2次支付失败,最近登录时间为4天,利用率为90%。仅需进行账单跟进,无需客户服务干预。
F-606 Fjord
—
promoter_with_ticket_load
P3
各项指标均刚好处于阈值内(29天,1次支付失败,利用率恰好为0.50)。根据规则目前不属于高风险,但若再有1天闲置或1次支付失败,情况将发生逆转。 请监控并清除这3个工单。
D-404 Dahlia
—
weak_health_without_risk
P3
评分42,未触发任何规则,$900 MRR下80%利用率。要么

T3:响应式用户界面生成

部分完成——生成了一段完整的、自包含的实现代码及自检代码,同时明确指出该代码是对页面进行了检查,而非在运行时渲染页面。.

Claude Opus 5 个响应式 UI 生成实践成果
给出了一个包含21,907个字符的完整答案;涵盖了桌面端、移动端、溢出情况及无障碍访问;明确指出布局是经过检查的,而非运行时渲染的。.
查看完整的 T3 提示和答案
完整的提示语
仅使用下方的产品数据,构建一个精美的产品比较界面,并将其保存为单个可运行的 HTML 文件。

要求:
1. 输出一个被 `html` 标签包围的代码块,其后紧跟一个 `SELF-CHECK` 部分。请勿将 HTML、CSS 或 JavaScript 拆分为单独的文件。
2. 仅使用语义化 HTML、内嵌 CSS 和内嵌原生 JavaScript:不得使用任何外部框架、包、字体、图片、网络请求或构建步骤。
3. 提供三个可通过键盘操作的选项卡(`Overview`、`Pricing`、`Limits`),并确保其 `tablist`、`tab` 和 `tabpanel` 语义正确。 `ArrowLeft`/`ArrowRight` 键必须能够移动并激活选项卡;`Home`/`End` 键必须能够跳转至并激活第一个/最后一个选项卡。焦点必须始终可见。
4. 选中的选项卡必须通过 `aria-selected`、`tabindex` 以及可见面板来体现;未激活的面板必须隐藏。
5. 桌面端目标:宽度 1440px。移动端目标:宽度 390px,页面不得出现水平溢出,控件不得被裁剪,点击目标高度至少为 44px,比较卡片应单列堆叠。
6. 包含简洁的页眉、明确的推荐、三张产品卡片以及一张紧凑的比较表。 保持可读性对比,避免装饰性动画。
7. 请使用以下确切的产品信息,切勿添加额外宣传语:
   - Atlas:`$19/mo`,`20 个项目`,`10 GB`,`邮件支持`,最适合个人工作。
   - Beacon:`$49/mo`,`无限项目`,`100 GB`,`优先支持`,最适合正在发展的团队。
   - Cove:`$99/mo`,`无限项目`,`1 TB`,`专属支持`,最适合受监管的运营场景。
8. 为 Beacon 添加醒目的 `综合最佳` 标签,同时确保其他卡片不显得被禁用。
9. 在 `SELF-CHECK` 中,明确报告您对语义标签、键盘行为、1440px 布局、390px 布局、水平溢出以及外部依赖项的检查结果。除非确实渲染了视口,否则不要声称已渲染;请区分代码检查与运行时验证。

产品测试数据(也存储在 `fixtures/T3-responsive-ui/product-data.json` 中):
```json
{
  "products": [
    {"name":"Atlas","price":"$19/mo","projects":"20 projects","storage":"10 GB","support":"邮件支持","bestFor":"单人工作"},
    {"name":"Beacon","price":"$49/mo","projects":"无限项目","storage":"100 GB","support":"优先支持","bestFor":"正在成长的团队","badge":"综合最佳"},
    {"name":"Cove","price":"$99/mo","projects":"无限项目","storage":"1 TB","support":"专属支持","bestFor":"受监管业务"}
  ]
}
```
Claude Opus 5
html
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Compare plans — Atlas, Beacon, Cove</title><style>  :root {    --bg: #f6f7f9;    --surface: #ffffff;    --ink: #16191f;    --ink-soft: #4a515c;    --line: #d3d8df;    --line-strong: #b6bdc7;    --accent: #10457e;    --accent-soft: #e8f0f9;    --focus: #0b2f56;    --radius: 10px;  }   * {box-sizing: border-box; }   html { -webkit-text-size-adjust: 100%; }   body {    margin: 0;    padding: 0;    background: var(--bg);    color: var(--ink);    font-family: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;    font-size: 16px;    line-height: 1.5;    overflow-x: hidden;  }   .wrap {    width: 100%;    max-width: 1120px;    margin: 0 auto;    padding: 32px 24px 64px;  }   /* ---------- Header ---------- */   .page-header { margin-bottom: 24px; }   .page-header h1 {    margin: 0 0 8px;    font-size: 1.75rem;    line-height: 1.25;    letter-spacing: -0.01em;  }   .page-header p {    margin: 0;    max-width: 60ch;    color: var(--ink-soft);  }   /* ---------- Recommendation ---------- */   .recommendation {    display: flex;    flex-wrap: wrap;    gap: 4px 10px;    align-items: baseline;    margin: 0 0 28px;    padding: 14px 16px;    background: var(--accent-soft);    border: 1px solid #c2d5e8;    border-left: 4px solid var(--accent);    border-radius: var(--radius);  }   .recommendation strong { color: var(--accent); }   .recommendation span { color: #23405e; }   /* ---------- Tabs ---------- */   .tabs {    display: flex;    flex-wrap: wrap;    gap: 8px;    margin: 0 0 20px;    padding: 0;    border-bottom: 1px solid var(--line);  }   [role="tab"] {    appearance: none;    min-height: 44px;    padding: 10px 18px;    font: inherit;    font-weight: 600;    color: var(--ink-soft);    background: transparent;    border: 1px solid transparent;    border-bottom: 3px solid transparent;    border-radius: 8px 8px 0 0;    cursor: pointer;  }   [role="tab"]:hover { color: var(--ink); background: #eceff3; }   [role="tab"][aria-selected="true"] {    color: var(--accent);    background: var(--surface);    border-color: var(--line) var(--line) var(--accent);    border-bottom-width: 3px;  }   :focus-visible {    outline: 3px solid var(--focus);    outline-offset: 2px;  }   [role="tabpanel"] { outline: none; }   [role="tabpanel"]:focus-visible {    outline: 3px solid var(--focus);    outline-offset: 4px;    border-radius: var(--radius);  }   [hidden] { display: none !important; }   .panel-intro {    margin: 0 0 20px;    max-width: 62ch;    color: var(--ink-soft);  }   /* ---------- Cards ---------- */   .card-grid {    display: grid;    grid-template-columns: repeat(3, minmax(0, 1fr));    gap: 20px;    margin: 0;    padding: 0;    list-style: none;    align-items: start;  }   .card {    display: flex;    flex-direction: column;    height: 100%;    padding: 20px;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   .card.is-featured {    border-color: var(--accent);    border-width: 2px;    padding: 19px;  }   .card-head {    display: flex;    flex-wrap: wrap;    gap: 8px;    align-items: center;    justify-content: space-between;    margin-bottom: 4px;  }   .card h3 {    margin: 0;    font-size: 1.2rem;  }   .badge {    padding: 3px 10px;    font-size: 0.75rem;    font-weight: 700;    letter-spacing: 0.02em;    text-transform: uppercase;    color: #ffffff;    background: var(--accent);    border-radius: 999px;    white-space: nowrap;  }   .price {    margin: 8px 0 2px;    font-size: 1.6rem;    font-weight: 700;    letter-spacing: -0.02em;  }   .best-for {    margin: 0 0 14px;    font-size: 0.9375rem;    color: var(--ink-soft);  }   .spec-list {    margin: 0;    padding: 14px 0 0;    border-top: 1px solid var(--line);    font-size: 0.9375rem;  }   .spec-list div {    display: flex;    gap: 12px;    justify-content: space-between;    padding: 5px 0;  }   .spec-list dt { color: var(--ink-soft); }   .spec-list dd {    margin: 0;    font-weight: 600;    text-align: right;  }   /* ---------- Table ---------- */   .table-section { margin-top: 36px; }   .table-section h2 {    margin: 0 0 12px;    font-size: 1.125rem;  }   .table-scroll {    max-width: 100%;    overflow-x: auto;    background: var(--surface);    border: 1px solid var(--line);    border-radius: var(--radius);  }   table {    width: 100%;    border-collapse: collapse;    font-size: 0.9375rem;  }   caption {    padding: 12px 14px;    text-align: left;    color: var(--ink-soft);    font-size: 0.875rem;  }   th, td {    padding: 10px 14px;    text-align: left;    border-top: 1px solid var(--line);    white-space: nowrap;  }   thead th {    background: #eef1f5;    border-top: none;    font-weight: 700;  }   tbody th { font-weight: 600; color: var(--ink-soft); }   th[scope="col"].is-featured { color: var(--accent); }   /* ---------- Mobile ---------- */   @media (max-width: 720px) {    .wrap { padding: 20px 16px 48px; }     .page-header h1 { font-size: 1.4rem; }     .tabs {      gap: 4px;      overflow-x: auto;      -webkit-overflow-scrolling: touch;      flex-wrap: nowrap;    }     [role="tab"] {      flex: 1 0 auto;      padding: 10px 12px;      font-size: 0.9375rem;    }     .card-grid { grid-template-columns: minmax(0, 1fr); }     th, td { padding: 10px 12px; }  }   @media (prefers-reduced-motion: reduce) {    * {transition: none !important; animation: none !important; }  }</style></head><body><main class="wrap">   <header class="page-header">    <h1>Compare plans</h1>    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>  </header>   <p class="recommendation">    <strong>Recommended: Beacon</strong>    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>  </p>   <div class="tabs" role="tablist" aria-label="Plan comparison views">    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>  </div>   <!-- Overview -->  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>All plans at a glance</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">        <table>          <caption>Published facts for Atlas, Beacon, and Cove.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr>              <th scope="row">Atlas</th>              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>            </tr>            <tr>              <th scope="row">Beacon</th>              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>            </tr>            <tr>              <th scope="row">Cove</th>              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>            </tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Pricing -->  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Email support</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Priority support</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Support</dt><dd>Dedicated support</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Price and support</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">        <table>          <caption>Monthly price, support tier, and intended fit.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Price</th>              <th scope="col">Support</th>              <th scope="col">Best for</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>          </tbody>        </table>      </div>    </section>  </section>   <!-- Limits -->  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>    <p class="panel-intro">Project counts and storage allowances for each plan.</p>     <ul class="card-grid">      <li class="card">        <div class="card-head"><h3>Atlas</h3></div>        <p class="price">$19/mo</p>        <p class="best-for">Best for solo work</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>20 projects</dd></div>          <div><dt>Storage</dt><dd>10 GB</dd></div>        </dl>      </li>       <li class="card is-featured">        <div class="card-head">          <h3>Beacon</h3>          <span class="badge">Best overall</span>        </div>        <p class="price">$49/mo</p>        <p class="best-for">Best overall for growing teams</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>100 GB</dd></div>        </dl>      </li>       <li class="card">        <div class="card-head"><h3>Cove</h3></div>        <p class="price">$99/mo</p>        <p class="best-for">Best for regulated operations</p>        <dl class="spec-list">          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>          <div><dt>Storage</dt><dd>1 TB</dd></div>        </dl>      </li>    </ul>     <section class="table-section">      <h2>Projects and storage</h2>      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">        <table>          <caption>Project allowance and storage per plan.</caption>          <thead>            <tr>              <th scope="col">Plan</th>              <th scope="col">Projects</th>              <th scope="col">Storage</th>            </tr>          </thead>          <tbody>            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>          </tbody>        </table>      </div>    </section>  </section> </main> <script>(function () {  'use strict';   var tablist = document.querySelector('[role="tablist"]');  if (!tablist) return;   var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'));   function panelFor(tab) {    return document.getElementById(tab.getAttribute('aria-controls'));  }   function activate(index, moveFocus) {    if (index < 0 || index >= tabs.length) return;     tabs.forEach(function (tab, i) {      var selected = i === index;      var panel = panelFor(tab);       tab.setAttribute('aria-selected', selected ? 'true' : 'false');      tab.setAttribute('tabindex', selected ? '0' : '-1');       if (panel) {        if (selected) {          panel.removeAttribute('hidden');        }else {          panel.setAttribute('hidden', '');        }      }    });     if (moveFocus !== false) tabs[index].focus();  }   function currentIndex() {    var i = tabs.findIndex(function (tab) {      return tab.getAttribute('aria-selected') === 'true';    });    return i === -1 ? 0 : i;  }   tabs.forEach(function (tab, i) {    tab.addEventListener('click', function () {      activate(i);    });  });   tablist.addEventListener('keydown', function (event) {    var last = tabs.length - 1;    var i = currentIndex();    var next = null;     switch (event.key) {      case 'ArrowRight':        next = i === last ?0 : i + 1;        break;      case 'ArrowLeft':        next = i ===0 ? last : i - 1;        break;      case 'Home':        next =0;        break;      case 'End':        next = last;        break;      default:        return;    }     event.preventDefault();    activate(next);  });   // Normalize initial state from markup.  activate(currentIndex(), false);}());</script></body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>

自我检查

以下所有陈述均仅基于代码审查得出。我并未打开浏览器、渲染视口、运行屏幕阅读器,也未执行键盘处理程序,因此此处内容均未经运行时验证。若某项论断取决于布局引擎的行为,我会特别说明。.
语义标签页——经过检查,保持一致
一个 div[role="tablist"](其 aria-label 属性值为"计划比较视图")包含三个 button[type="button"][role="tab"]。 每个标签页都有一个唯一的 ID,并且其 `aria-controls` 属性指向一个 `section`[role="tabpanel"];每个面板都带有 `aria-labelledby` 属性,该属性反向指向其对应的标签页。我手动追踪了所有三对关联:tab-overview/panel-overview、tab-pricing/panel-pricing、tab-limits/panel-limits。 没有重复的 ID,也没有悬空引用。面板使用 tabindex="0",因此通过标签后可访问面板主体。.
键盘行为——已检查,但未执行
tablist 上设置了一个单一的 keydown 监听器,用于处理向右箭头、向左箭头、Home 和 End 键,仅针对这四个键调用 event.preventDefault(),否则提前返回。 方向键在两端会自动循环。由于 activate() 既会更新 aria-selected/tabindex/hidden 属性,又会移动焦点,因此方向键和 Home/End 键能在一步内同时移动焦点并激活,这正是需求中要求的"自动激活"模式。 Tab/Shift+Tab 导航依赖于动态调整的 tabindex:仅有一个选项的 tabindex="0",其余均为 -1,由 activate() 方法维护。焦点可见性来自全局 :focus-visible 规则,该规则设置了 3px 的轮廓和 2px 的偏移量;我未覆盖或移除任何默认轮廓。 我尚未在真实浏览器中验证过键位处理功能。.
选定状态反射 — 已检查
activate() 在同一个循环中设置这三个属性,因此 aria-selected="true"、tabindex="0" 以及未设置 hidden 属性这三者不会出现不一致的情况。 非活动面板会被赋予 hidden 属性,而 [hidden] { display: none !important; } 可防止显示规则破坏该效果——这一保护措施至关重要,因为面板中包含具有 display: grid 属性的子元素。activate(currentIndex(), false) 在页面加载时运行,用于根据标记规范化状态,同时不会抢占焦点。 如果 JavaScript 无法运行,标记将默认显示“概述”面板并隐藏其他两个面板,因此页面将降级为仅显示一个可读面板。.
1440px 布局——已检查,未渲染
.wrap 的 max-width 设置为 1120px,margin 设置为 0 auto,因此在 1440px 时,内容会居中显示,两侧各留出约 160px 的间距,而非拉伸。 卡片使用 `grid-template-columns: repeat(3, minmax(0, 1fr))` 并设置 20px 间距,形成三个等宽列;`align-items: start` 可防止卡片拉伸至共享高度,而 `.card { height: 100% }` 的效果则被该设置抵消。 使用 minmax(0, 1fr) 是经过深思熟虑的——仅使用 1fr 可能会导致网格拒绝缩小至内容宽度以下,从而使网格变宽。我并未测量实际的像素输出结果。.
390px 布局——已检查,未渲染
当块的 max-width 设置为 720px 时,卡片网格会切换为 minmax(0, 1fr) 的单列布局,因此卡片会垂直堆叠。各边距缩减至 16px,内容宽度约为 358px。 点击目标:每个 [role="tab"] 元素都设置了 min-height: 44px,且水平内边距缩小至 12px 而非高度缩减,因此即使在窄屏幕宽度下,44px 的高度下限也能保持不变。 标签列表设置为 `flex-wrap: nowrap`,并配合 `overflow-x: auto` 以及 `flex: 1 0 auto` 的子元素,因此三个标签要么完全显示在标签列表内,要么在列表内滚动,而不会在控件中间被裁剪或换行。 已包含 标签。尚未在实际 390px 视口下进行验证。.
水平溢出——已检查,一个有意限制的滚动条
body { overflow-x: hidden } 是最后的保障措施,但我尽量不依赖它。* { box-sizing: border-box } 可将内边距控制在声明的宽度之内。 比较表格的单元格使用了 `white-space: nowrap`,因此六列的"概述"表格在移动端会超过 358px;这通过 `.table-scroll { max-width: 100%; overflow-x: auto }` 进行控制,该样式会让表格区域滚动,而非整个页面。 该容器设置了 `tabindex="0"` 和 `role="region"`,并配有标签,以便键盘用户能够定位并滚动该区域。对于那些原本可能拒绝缩小的 Flex 和 Grid 子元素,通过在网格中使用 `minmax(0, 1fr)`,以及在 `.card-head` 和 `.recommendation` 上设置 `flex-wrap: wrap` 来处理。 唯一无法在未渲染的情况下排除的风险是表格单元格中出现过长的连续字符串,但所有测试数据值都很短。.
外部依赖项 — 已检查,无
没有 <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
对比度与运动——已检查
主文本 #16191f 在 #f6f7f9 背景上,以及次要文本 #4a515c 在白色背景上,其对比度均远超 4.5:1; 徽标在 #10457e 背景上为白色,而活动标签页则为 #10457e 配白色背景。 这些数据是我根据十六进制值估算比例得出的,并非使用对比度工具测得。页面中没有任何过渡效果、动画或变换;`prefers-reduced-motion` 规则块仅作为一种无操作的安全措施,而非针对现有动态效果的修复方案。.
夹具精度——已检查
这三种方案均出现在所有三个面板以及各面板的表格中。我已对照 JSON: Atlas 对每个价格、项目数量、存储容量和支持级别进行了交叉核对。
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/不限/100 GB/优先级,Cove $99/不限/1 TB/专用。 Beacon 带有"综合最佳"徽章和 2 像素的强调边框;Atlas 和 Cove 则保留全不透明度文本、普通边框以及相同的字体处理方式,因此看起来是可用的而非已禁用。最适合的场景以简短标签形式呈现(“最适合单人工作”)——在产品参数值周围添加文字说明,不添加新的产品宣传语。.
已知缺陷
不进行任何形式的运行时验证。三个面板的内容均以静态标记的形式复制,而非从 JSON 渲染而来,因此该测试用例通过转录而非绑定成为“权威数据源”——未来若数据发生变更,则需在多个位置进行编辑。.

```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compare plans — Atlas, Beacon, Cove</title>
<style>
  :root
 {
    --bg: #f6f7f9
;
    --surface: #ffffff
;
    --ink: #16191f
;
    --ink-soft: #4a515c
;
    --line: #d3d8df
;
    --line-strong: #b6bdc7
;
    --accent: #10457e
;
    --accent-soft: #e8f0f9
;
    --focus: #0b2f56
;
    --radius: 10px
;
  }

  * {
box-sizing
: border-box; }

  html { -webkit-text-size-adjust: 100%
; }

  body
 {
    margin: 0
;
    padding: 0
;
    background: var
(--bg);
    color: var
(--ink);
    font-family: system-ui, -apple-system, "Segoe UI"
, Roboto, Helvetica, Arial, sans-serif;
    font-size: 16px
;
    line-height: 1.5
;
    overflow-x
: hidden;
  }

  .wrap
 {
    width: 100%
;
    max-width: 1120px
;
    margin: 0
 auto;
    padding: 32px 24px 64px
;
  }

  /* ---------- Header ---------- */

  .page-header { margin-bottom: 24px
; }

  .page-header h1
 {
    margin: 0 0 8px
;
    font-size: 1.75rem
;
    line-height: 1.25
;
    letter-spacing: -0.01em
;
  }

  .page-header p
 {
    margin: 0
;
    max-width: 60ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Recommendation ---------- */

  .recommendation
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 4px 10px
;
    align-items
: baseline;
    margin: 0 0 28px
;
    padding: 14px 16px
;
    background: var
(--accent-soft);
    border: 1px solid #c2d5e8
;
    border-left: 4px solid var
(--accent);
    border-radius: var
(--radius);
  }

  .recommendation strong { color: var
(--accent); }

  .recommendation span { color: #23405e
; }

  /* ---------- Tabs ---------- */

  .tabs
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    margin: 0 0 20px
;
    padding: 0
;
    border-bottom: 1px solid var
(--line);
  }

  [role="tab"]
 {
    appearance
: none;
    min-height: 44px
;
    padding: 10px 18px
;
    font
: inherit;
    font-weight: 600
;
    color: var
(--ink-soft);
    background
: transparent;
    border: 1px
 solid transparent;
    border-bottom: 3px
 solid transparent;
    border-radius: 8px 8px 0 0
;
    cursor
: pointer;
  }

  [role="tab"]:hover { color: var(--ink); background: #eceff3
; }

  [role="tab"][aria-selected="true"]
 {
    color: var
(--accent);
    background: var
(--surface);
    border-color: var(--line) var(--line) var
(--accent);
    border-bottom-width: 3px
;
  }

  :focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 2px
;
  }

  [role="tabpanel"] { outline
: none; }

  [role="tabpanel"]:focus-visible
 {
    outline: 3px solid var
(--focus);
    outline-offset: 4px
;
    border-radius: var
(--radius);
  }

  [hidden] { display: none !important
; }

  .panel-intro
 {
    margin: 0 0 20px
;
    max-width: 62ch
;
    color: var
(--ink-soft);
  }

  /* ---------- Cards ---------- */

  .card-grid
 {
    display
: grid;
    grid-template-columns: repeat(3, minmax(0, 1
fr));
    gap: 20px
;
    margin: 0
;
    padding: 0
;
    list-style
: none;
    align-items
: start;
  }

  .card
 {
    display
: flex;
    flex-direction
: column;
    height: 100%
;
    padding: 20px
;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  .card.is-featured
 {
    border-color: var
(--accent);
    border-width: 2px
;
    padding: 19px
;
  }

  .card-head
 {
    display
: flex;
    flex-wrap
: wrap;
    gap: 8px
;
    align-items
: center;
    justify-content
: space-between;
    margin-bottom: 4px
;
  }

  .card h3
 {
    margin: 0
;
    font-size: 1.2rem
;
  }

  .badge
 {
    padding: 3px 10px
;
    font-size: 0.75rem
;
    font-weight: 700
;
    letter-spacing: 0.02em
;
    text-transform
: uppercase;
    color: #ffffff
;
    background: var
(--accent);
    border-radius: 999px
;
    white-space
: nowrap;
  }

  .price
 {
    margin: 8px 0 2px
;
    font-size: 1.6rem
;
    font-weight: 700
;
    letter-spacing: -0.02em
;
  }

  .best-for
 {
    margin: 0 0 14px
;
    font-size: 0.9375rem
;
    color: var
(--ink-soft);
  }

  .spec-list
 {
    margin: 0
;
    padding: 14px 0 0
;
    border-top: 1px solid var
(--line);
    font-size: 0.9375rem
;
  }

  .spec-list div
 {
    display
: flex;
    gap: 12px
;
    justify-content
: space-between;
    padding: 5px 0
;
  }

  .spec-list dt { color: var
(--ink-soft); }

  .spec-list dd
 {
    margin: 0
;
    font-weight: 600
;
    text-align
: right;
  }

  /* ---------- Table ---------- */

  .table-section { margin-top: 36px
; }

  .table-section h2
 {
    margin: 0 0 12px
;
    font-size: 1.125rem
;
  }

  .table-scroll
 {
    max-width: 100%
;
    overflow-x
: auto;
    background: var
(--surface);
    border: 1px solid var
(--line);
    border-radius: var
(--radius);
  }

  table
 {
    width: 100%
;
    border-collapse
: collapse;
    font-size: 0.9375rem
;
  }

  caption
 {
    padding: 12px 14px
;
    text-align
: left;
    color: var
(--ink-soft);
    font-size: 0.875rem
;
  }

  th, td
 {
    padding: 10px 14px
;
    text-align
: left;
    border-top: 1px solid var
(--line);
    white-space
: nowrap;
  }

  thead th
 {
    background: #eef1f5
;
    border-top
: none;
    font-weight: 700
;
  }

  tbody th { font-weight: 600; color: var
(--ink-soft); }

  th[scope="col"].is-featured { color: var
(--accent); }

  /* ---------- Mobile ---------- */

  @media (max-width: 720px
) {
    .wrap { padding: 20px 16px 48px
; }

    .page-header h1 { font-size: 1.4rem
; }

    .tabs
 {
      gap: 4px
;
      overflow-x
: auto;
      -webkit-
overflow
-scrolling: touch;
      flex-wrap
: nowrap;
    }

    [role="tab"]
 {
      flex: 1 0
 auto;
      padding: 10px 12px
;
      font-size: 0.9375rem
;
    }

    .card-grid { grid-template-columns: minmax(0, 1
fr); }

    th, td { padding: 10px 12px
; }
  }

  @media (prefers-reduced-motion
: reduce) {
    * {
transition: none !important; animation: none !important
; }
  }
</style>
</head>
<body>
<main class="wrap">

  <header class="page-header">
    <h1>Compare plans</h1>
    <p>Three plans across projects, storage, and support. Pick a tab to focus on the details that matter to you.</p>
  </header>

  <p class="recommendation">
    <strong>Recommended: Beacon</strong>
    <span>Best overall for growing teams — $49/mo, unlimited projects, 100&nbsp;GB, priority support.</span>
  </p>

  <div class="tabs" role="tablist" aria-label="Plan comparison views">
    <button type="button" role="tab" id="tab-overview" aria-controls="panel-overview" aria-selected="true" tabindex="0">Overview</button>
    <button type="button" role="tab" id="tab-pricing" aria-controls="panel-pricing" aria-selected="false" tabindex="-1">Pricing</button>
    <button type="button" role="tab" id="tab-limits" aria-controls="panel-limits" aria-selected="false" tabindex="-1">Limits</button>
  </div>

  <!-- Overview -->
  <section role="tabpanel" id="panel-overview" aria-labelledby="tab-overview" tabindex="0">
    <p class="panel-intro">Every plan side by side, with the full set of published facts for each one.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>All plans at a glance</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Full plan comparison table, scrollable">
        <table>
          <caption>Published facts for Atlas, Beacon, and Cove.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <th scope="row">Atlas</th>
              <td>$19/mo</td><td>20 projects</td><td>10 GB</td><td>Email support</td><td>Solo work</td>
            </tr>
            <tr>
              <th scope="row">Beacon</th>
              <td>$49/mo</td><td>Unlimited projects</td><td>100 GB</td><td>Priority support</td><td>Growing teams</td>
            </tr>
            <tr>
              <th scope="row">Cove</th>
              <td>$99/mo</td><td>Unlimited projects</td><td>1 TB</td><td>Dedicated support</td><td>Regulated operations</td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Pricing -->
  <section role="tabpanel" id="panel-pricing" aria-labelledby="tab-pricing" tabindex="0" hidden>
    <p class="panel-intro">Monthly price and the audience each plan is built for.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Email support</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Priority support</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Support</dt><dd>Dedicated support</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Price and support</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Pricing comparison table, scrollable">
        <table>
          <caption>Monthly price, support tier, and intended fit.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Price</th>
              <th scope="col">Support</th>
              <th scope="col">Best for</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>$19/mo</td><td>Email support</td><td>Solo work</td></tr>
            <tr><th scope="row">Beacon</th><td>$49/mo</td><td>Priority support</td><td>Growing teams</td></tr>
            <tr><th scope="row">Cove</th><td>$99/mo</td><td>Dedicated support</td><td>Regulated operations</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

  <!-- Limits -->
  <section role="tabpanel" id="panel-limits" aria-labelledby="tab-limits" tabindex="0" hidden>
    <p class="panel-intro">Project counts and storage allowances for each plan.</p>

    <ul class="card-grid">
      <li class="card">
        <div class="card-head"><h3>Atlas</h3></div>
        <p class="price">$19/mo</p>
        <p class="best-for">Best for solo work</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>20 projects</dd></div>
          <div><dt>Storage</dt><dd>10 GB</dd></div>
        </dl>
      </li>

      <li class="card is-featured">
        <div class="card-head">
          <h3>Beacon</h3>
          <span class="badge">Best overall</span>
        </div>
        <p class="price">$49/mo</p>
        <p class="best-for">Best overall for growing teams</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>100 GB</dd></div>
        </dl>
      </li>

      <li class="card">
        <div class="card-head"><h3>Cove</h3></div>
        <p class="price">$99/mo</p>
        <p class="best-for">Best for regulated operations</p>
        <dl class="spec-list">
          <div><dt>Projects</dt><dd>Unlimited projects</dd></div>
          <div><dt>Storage</dt><dd>1 TB</dd></div>
        </dl>
      </li>
    </ul>

    <section class="table-section">
      <h2>Projects and storage</h2>
      <div class="table-scroll" tabindex="0" role="region" aria-label="Limits comparison table, scrollable">
        <table>
          <caption>Project allowance and storage per plan.</caption>
          <thead>
            <tr>
              <th scope="col">Plan</th>
              <th scope="col">Projects</th>
              <th scope="col">Storage</th>
            </tr>
          </thead>
          <tbody>
            <tr><th scope="row">Atlas</th><td>20 projects</td><td>10 GB</td></tr>
            <tr><th scope="row">Beacon</th><td>Unlimited projects</td><td>100 GB</td></tr>
            <tr><th scope="row">Cove</th><td>Unlimited projects</td><td>1 TB</td></tr>
          </tbody>
        </table>
      </div>
    </section>
  </section>

</main>

<script>
(
function (
) {
  'use strict'
;

  var tablist = document.querySelector('[role="tablist"]'
);
  if (!tablist) return
;

  var tabs = Array.prototype.slice.call(tablist.querySelectorAll('[role="tab"]'
));

  function panelFor(tab
) {
    return document.getElementById(tab.getAttribute('aria-controls'
));
  }

  function activate(index, moveFocus
) {
    if (index < 0 || index >= tabs.length) return
;

    tabs.
forEach(function (tab, i
) {
      var
 selected = i === index;
      var panel = panelFor
(tab);

      tab.
setAttribute('aria-selected', selected ? 'true' : 'false'
);
      tab.
setAttribute('tabindex', selected ? '0' : '-1'
);

      if
 (panel) {
        if
 (selected) {
          panel.
removeAttribute('hidden'
);
        }
else
 {
          panel.
setAttribute('hidden', ''
);
        }
      }
    });

    if (moveFocus !== false) tabs[index].focus
();
  }

  function currentIndex(
) {
    var i = tabs.findIndex(function (tab
) {
      return tab.getAttribute('aria-selected') === 'true'
;
    });
    return i === -1 ? 0
 : i;
  }

  tabs.
forEach(function (tab, i
) {
    tab.
addEventListener('click', function (
) {
      activate
(i);
    });
  });

  tablist.
addEventListener('keydown', function (event
) {
    var last = tabs.length - 1
;
    var i = currentIndex
();
    var next = null
;

    switch (event.key
) {
      case 'ArrowRight'
:
        next = i === last ?
0 : i + 1
;
        break
;
      case 'ArrowLeft'
:
        next = i ===
0 ? last : i - 1
;
        break
;
      case 'Home'
:
        next =
0
;
        break
;
      case 'End'
:
        next = last;
        break
;
      default
:
        return
;
    }

    event.
preventDefault
();
    activate
(next);
  });

  // Normalize initial state from markup.
  activate(currentIndex(), false
);
}());
</script>
</body>
</html>
```

SELF-CHECK
All statements below come from code inspection only. I did not open a browser, render a viewport, run a screen reader, or execute the keyboard handlers, so nothing here is runtime-verified. Where a claim depends on layout engine behavior, I say so.
Semantic tabs — inspected, consistent
One div[role="tablist"] with aria-label="Plan comparison views" holds three button[type="button"][role="tab"]. Each tab has a unique id and an aria-controls pointing at a section[role="tabpanel"]; each panel carries aria-labelledby pointing back at its tab. I traced all three pairs by hand: tab-overview/panel-overview, tab-pricing/panel-pricing, tab-limits/panel-limits. No duplicate IDs, no dangling references. Panels use tabindex="0" so the panel body is reachable after the tab.
Keyboard behavior — inspected, not executed
A single keydown listener on the tablist handles ArrowRight, ArrowLeft, Home, and End, calls event.preventDefault() for those four keys only, and returns early otherwise. Arrow keys wrap at both ends. Because activate() both updates aria-selected/tabindex/hidden and moves focus, arrow and Home/End keys move andactivate in one step, which is the automatic-activation pattern the requirement asks for. Tab/Shift+Tab traversal relies on roving tabindex: exactly one tab is tabindex="0", the rest -1, maintained by activate(). Focus visibility comes from a global :focus-visible rule with a 3px outline and 2px offset; I did not override or remove any default outline. I have not confirmed key handling in a real browser.
Selected-state reflection — inspected
activate() sets all three signals in the same loop, so aria-selected="true", tabindex="0", and the absence of hidden cannot drift apart. Inactive panels get the hidden attribute, and [hidden] { display: none !important; } guards against the display rules that would otherwise defeat it — that guard matters because the panels contain display: grid children. activate(currentIndex(), false) runs on load to normalize state from markup without stealing focus. If JavaScript does not run, the markup ships with Overview selected and the other two panels hidden, so the page degrades to one readable panel.
1440px layout — inspected, not rendered
.wrap is max-width: 1120px with margin: 0 auto, so at 1440px the content centers with roughly 160px gutters rather than stretching. Cards use grid-template-columns: repeat(3, minmax(0, 1fr)) with a 20px gap, giving three equal columns; align-items: start keeps cards from stretching to a shared height while .card { height: 100% } is neutralized by that. The minmax(0, 1fr) is deliberate — 1fralone can refuse to shrink below content width and push a grid wide. I did not measure actual pixel output.
390px layout — inspected, not rendered
The max-width: 720px block switches the card grid to minmax(0, 1fr), a single column, so cards stack. Padding drops to 16px per side, leaving about 358px of content width. Tap targets: every [role="tab"] has min-height: 44px, and horizontal padding shrinks to 12px rather than the height shrinking, so the 44px floor holds at narrow widths. The tablist becomes flex-wrap: nowrap with overflow-x: auto and flex: 1 0 auto children, so three tabs either fit or scroll within the tablist itself instead of being clipped or wrapped mid-control. <meta name="viewport" content="width=device-width, initial-scale=1"> is present. Not verified at an actual 390px viewport.
Horizontal overflow — inspected, one intentional contained scroll
body { overflow-x: hidden } is the backstop, but I also tried not to rely on it. * { box-sizing: border-box } keeps padding inside declared widths. The comparison tables use white-space: nowrap on cells, so the six-column Overview table will exceed 358px on mobile; that is contained by .table-scroll { max-width: 100%; overflow-x: auto }, which scrolls the table region rather than the page. That wrapper has tabindex="0" and role="region" with a label so keyboard users can reach and scroll it. Flex and grid children that could otherwise refuse to shrink are handled with minmax(0, 1fr) on the grid and flex-wrap: wrap on .card-head and .recommendation. The one remaining risk I cannot rule out without rendering is a long unbroken string in a table cell, but all fixture values are short.
External dependencies — inspected, none
No <link>, <script src>, <img>, @import, url(), fetch, XMLHttpRequest, web font, or CDN reference. Fonts are a system-ui stack. The badge and featured border are CSS only, no icon assets. Everything is inline in one file, so it runs from file:// with no build step.
Contrast and motion — inspected
Body text #16191f on #f6f7f9 and secondary #4a515c on white are both well clear of 4.5:1; the badge is white on #10457e, and the active tab is #10457e on white. I computed these by ratio estimate from the hex values, not with a contrast tool. There are no transitions, animations, or transforms anywhere; the prefers-reduced-motion block is a no-op safety net rather than a fix for existing motion.
Fixture fidelity — inspected
Each of the three plans appears in all three panels plus each panel's table. I cross-checked every price, project count, storage figure, and support tier against the JSON: Atlas
19
/
20
𝑝
𝑟
𝑜
𝑗
𝑒
𝑐
𝑡
𝑠
/
10
𝐺
𝐵
/
𝐸
𝑚
𝑎
𝑖
𝑙
,
𝐵
𝑒
𝑎
𝑐
𝑜
𝑛
49/Unlimited/100 GB/Priority, Cove $99/Unlimited/1 TB/Dedicated. Beacon carries the Best overall badge and a 2px accent border; Atlas and Cove keep full-opacity text, normal borders, and identical type treatment, so they read as available rather than disabled. The best for values are rendered as short labels ("Best for solo work") — wording added around the fixture value, no new product claims.
Known gaps
No runtime verification of any kind. Panel content is duplicated across the three panels as static markup rather than rendered from the JSON, so the fixture is the source of truth by transcription, not by binding — a future data change means editing several places.

T4:自我验证

通过——在内部审核中发现了空数组的NaN错误,修改了一次,并确认了所有给定的测试用例。.

Claude Opus 5 实践性自我验证结果
在其自身的审核中发现了空数组导致 NaN 的结果;修改了一次,使其返回 N/A(0/0 通过);修改后确认了提供的所有四个案例均通过。.
查看完整的T4题目及答案
完整的提示语
完成这项带编号的约束任务,然后对其进行审核,如有必要,仅可修改一次。

任务约束:
1. 编写一个名为 `summarizeChecks(checks)` 的纯 JavaScript 函数;`checks` 是一个布尔值数组。
2. 对于非空输入,返回值应精确为 `% (/ 通过)`,其中 `rate` 保留一位小数,表示 `true` 值的百分比。 示例:对于 `[true, true, false, true]`,返回 `75.0% (3/4 通过)`。
3. 不得修改输入。
4. 不得使用 `for`、`while`、`forEach`、`eval`、外部库或第二个函数。
5. 函数体最多可包含三条语句。带有初始化的声明计为一条语句。
6. 在声明函数后将其赋值给 `globalThis.summarizeChecks`,以便独立的测试框架能够调用它。

必需的响应格式:
- `FIRST ANSWER`:在进行审核之前,将初始解法写在一个带围栏的 `js` 代码块中。
- `AUDIT`:根据约束条件 1–6 以及以下隐藏边界情况对第一个答案进行检查:空输入必须返回 `N/A (0/0 通过)`。针对每项约束说明通过或失败。
- 若有任何审核项未通过,请修改一次。修改次数不得超过一次。
- `最终答案`:在单个带边界标记的 `js` 代码块中给出最终解决方案。在满足空输入边界情况的同时,保留所有原始约束条件。

在审核中使用以下独立测试用例:
```text
[] -> N/A (0/0 通过)
[true] -> 100.0% (1/1 通过)
[false] -> 0.0% (0/1 通过)
[true, true, false, true] -> 75.0% (3/4 通过)
```
Claude Opus 5

第一个答案

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  return `${((通过数 / 总数) * 100).toFixed(1)}% (${通过数}/${总数} 通过)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((通过数 / 总数) * 100).toFixed(1)}% (${通过数}/${总数} 通过)`;
}

globalThis.summarizeChecks = summarizeChecks;

审计

#
制约因素
结果
1
名为 summarizeChecks(checks) 的普通函数
PASS — 普通声明,一个参数,没有类或箭头包装器。.
2
格式 % (/ 通过),通过率保留一位小数简体中文(大陆)
对于非空输入,通过验证——toFixed(1) 固定了小数位数,且字面量中的空格与规范完全一致。.
3
无输入突变
PASS — .length 和 .filter 均为只读;filter 会返回一个新数组。.
4
不允许使用 for、while、forEach、eval、library 或 second 函数
PASS — .filter 是唯一的迭代操作,Boolean 是一个内置类型,用作谓词引用,并非我定义的函数。.
5
正文中最多包含三条语句
PASS —— 正好三个:两个已初始化的声明加上返回语句。.
6
在声明后被赋值给 globalThis.summarizeChecks
PASS — 赋值操作紧跟在顶级声明之后。.
独立检查案例:
输入
预期
实际
结果
[]
不适用(0/0 通过)
NaN%(通过数:0/0)
失败
[true]
100.0%(1/1 通过)
100.0%(1/1 通过)
PASS
[false]
0.0%(通过0/1)
0.0%(通过0/1)
PASS
[true, true, false, true]
75.0%(通过率3/4)
75.0%(通过率3/4)
PASS
出现一次错误。当输入为空时,传入的参数为 / 总和为 0 / 0,这属于 NaN;由于 NaN.toFixed(1) 会返回字符串"NaN"而非抛出异常,因此该函数会无声地输出 NaN%(传入参数为 0/0)。.
修改一次。该修正作为条件表达式保留在现有的return语句中,因此语句数量保持不变。%符号移至非空分支内部,因为预期的空输出为N/A(0/0通过),且不包含百分号。.

最终答案

js
function summarizeChecks(checks) {  const total = checks.length;  const passed = checks.filter(Boolean).length;  返回 `${total === 0 ? 'N/A' : `${((通过数 / 总数) * 100).toFixed(1)}%`} (${通过数}/${总数} 通过)`;} globalThis.summarizeChecks = summarizeChecks;
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? 'N/A' : `${((通过数 / 总数) * 100).toFixed(1)}%`} (${通过数}/${总数} 通过)`;
}

globalThis.summarizeChecks = summarizeChecks;

四个案例的修订后确认结果:[] → 不适用(0/0 通过),[true] → 100.0%(1/1 通过),[false] → 0.0%(0/1 通过), [true, true, false, true] → 75.0%(3/4通过)。主体部分仍为三条语句,输入未作任何修改,且未引入任何被禁结构。.

第一个答案

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${((通过数 / 总数) * 100).toFixed(1)}% (${通过数}/${总数} 通过)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

审核
#
约束条件
结果
1
名为 summarizeChecks(checks) 的普通函数
通过 — 普通声明,一个参数,无类或箭头函数包装。
2
格式 % (/ 通过),rate 保留一位小数
对于非空输入通过 — toFixed(1) 固定了小数位数,且字面量间距完全符合规范。
3
无输入变异
通过 — .length 和 .filter 均为只读;filter 返回一个新数组。
4
无 for、while、forEach、eval、library 或第二个函数
通过 — .filter 是唯一的迭代操作,Boolean 是作为谓词引用使用的内置类型,并非我定义的函数。
5
主体中最多三个语句
通过 — 恰好三个:两个初始化声明加上返回语句。
6
在声明后将值赋给 globalThis.summarizeChecks
通过 — 赋值紧跟在顶级声明之后。
独立测试用例:
输入
预期
实际
结果
[]
不适用 (0/0 通过)
NaN% (0/0 通过)
失败
[true]
100.0% (1/1 通过)
100.0% (1/1 通过)
通过
[false]
0.0%(0/1 通过)
0.0%(0/1 通过)
通过
[true, true, false, true]
75.0% (3/4 通过)
75.0% (3/4 通过)
通过
出现一次失败。在空输入通过 / 总数为 0 / 0 的情况下,结果为 NaN;NaN.toFixed(1) 返回字符串"NaN"而非抛出异常,因此该函数会静默输出 NaN%(0/0 通过)。
修改一次。修复内容作为条件表达式保留在现有的返回语句中,因此语句数量保持不变。% 符号移至非空分支内部,因为预期空输出为 N/A(0/0 通过),且不包含百分号。
最终答案

```js
function summarizeChecks(checks) {
  const total = checks.length;
  const passed = checks.filter(Boolean).length;
  return `${total === 0 ? 'N/A' : `${((passed / total) * 100).toFixed(1)}%`} (${passed}/${total} 通过)`;
}

globalThis.summarizeChecks = summarizeChecks;
```

对所有四种情况进行修订后确认:[] → N/A(0/0 通过),[true] → 100.0%(1/1 通过), [false] → 0.0%(0/1 通过),[true, true, false, true] → 75.0%(3/4 通过)。主体仍为三条语句,输入未作任何改动,且未引入任何被禁止的构造。.

在跨供应商进行选择时,团队仍应测试其自身的代码库、工具栈以及代码审查工作量。更广泛地来说, Claude 与 ChatGPT 的编码对比 有助于从这一单一结果之外的角度来审视这些权衡。.

Claude Opus 5 与 Opus 4.8 与 Fable 5

要理解Opus 5,最直观的方式就是将其视为一款全新的高端主力机型。 Opus 4.8是其前代产品;Fable 5依然是业界标杆。Anthropic的发布资料指出,Opus 5在保持与Opus 4.8相同基础成本的同时,在部分评估指标上已接近Fable 5的水平,且每项任务的成本显著降低。.

模型职位性价比指标最合适
Claude Opus 5高端日常款;Opus 4.8的继任机型每个输入/输出 MTok 为 $5/$25;Anthropic 发布的每任务成本结果表现强劲复杂的编码、自动化以及对可靠性要求较高的企业级工作
克劳德作品 4.8上一代 Opus根据Anthropic的发布对比,其基础价格与Opus 5相同现有已固定但仍需进行迁移验证的工作流
克劳德·法布尔 5前沿情报层级基准参考点;Anthropic指出,Opus 5 在 CursorBench 测试中的表现与之相差无几,而每任务成本仅为其一半当最大能力比经济因素更重要时,最艰巨的任务

当您可以对迁移进行回归测试,且希望采用新模型而不提高基础 API 费率时,请选择 Opus 5 而非 Opus 4.8。当您自己的评估表明其额外功能对结果的影响足以证明额外费用合理时,请选择 Fable 5。 如需查看包含 Sonnet 5 的最新产品系列级细分信息,请使用 Claude Opus 5 与 Fable 5 与 Sonnet 5 的对比.

开发商和业界的反应

社交媒体帖子虽然能提供有关早期使用情况的有用线索,但并非中立的参考标准。Claude的官方账号将Opus 5描述为“设计周到且功能主动”,其性能接近Fable 5的前沿智能水平,但价格仅为后者的一半。这其实是Anthropic自身在发布时的定位,并非独立验证的结果。.

Claude于2026年7月24日发布的原X帖,宣布推出Claude Opus 5
Claude在X平台上发布了Opus 5,将其定位为一款设计周到、主动型的人工智能模型,其智能水平接近Fable 5,但价格仅为后者的一半。.

JetBrains 表示,其自身的评估显示, 45%的Python通过率高于Opus 4.8, ,以及对代码库更深入的理解。这是来自一家开发者工具公司的具体且切合实际的观察,但该结果属于 JetBrains 的评估结果,不应将其推广至每一个 Python 基准测试或代码库。.

JetBrains X 博文称,使用 Claude Opus 5 后,Python 通过率更高,对代码库的理解也更深入 5
JetBrains 表示,其评估显示,与 Opus 4.8 相比,Python 的通过率提高了 45%,且对代码库的理解更为深入。.

哈维公司报告称,在包括公司治理和仲裁在内的法律工作流程中,与Opus 4.8相比,质量和代币效率均有了显著提升。这对法律科技采购方而言意义重大,但这仍仅是哈维公司对其业务领域工作流程的评估,而非普遍法律准确性的证明。.

Harvey X 发布帖子,称在法律工作质量和代币效率方面取得了 Claude Opus 5 的提升
哈维指出,Opus 5 在法律工作质量和代币效率方面有所提升,涵盖公司治理和仲裁等领域。.

综合来看,这些帖子表明,早期采用者已经注意到在代码库理解和领域特定知识工作方面取得了进展。接下来负责任的做法,仍然是开展一项具有代表性的试点项目,其中应包含您自己的验收测试、代币预算以及人工审核流程。.

Claude Opus 5 API:模型 ID、示例和迁移说明

Claude 的官方 API 模型 ID 和别名均为 克劳德-作品第5号. 以下是一个最简的 人类应用程序接口 请求示例。该示例仅演示了官方的 Messages 端点;并未描述或承诺 GlobalGPT 的后端实现。.

curl https://api.anthropic.com/v1/messages \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data '{
    "model": "claude-opus-5",
    "max_tokens": 1024,
    "messages": [
 {
 "role": "user",
 "content": "找出根本原因,提出最小的修复方案,并给出验证指令。"
      }
    ]
  }'

迁移检查清单

  • 将模型值更改为 克劳德-作品第5号, ,然后重新运行您自己的回归分析和安全性评估。.
  • 针对每个 MTok,将预算设定为 $5 的输入和 $25 的输出;监控输出量较大的代理循环和工具重试。.
  • 不要延续旧习 thinking.type: "enabled" 配置。. Anthropic的思维指南 称目前已开始构思《Opus 5》,并记录了自适应设置。.
  • 请将 128K 视为同步消息 API 的最大输出量。独立的消息批次测试版在使用 Anthropic 文档中所述的测试版标头时,最多可支持 300K。.
  • 查看各供应商的型号名称及访问权限。Anthropic 文档 anthropic.claude-opus-5 适用于 Amazon Bedrock 和 克劳德-作品第5号 适用于 Google Cloud。.

对于希望在 Claude Code 之外使用命令行工作流的开发者,实用的配置指南如下: 如何在 Claude 代码中使用 GlobalGPT CLI. 请将该工作流与上文提到的官方 Anthropic API 示例分开,以确保凭据、计费和提供商的行为保持清晰。.

Claude Opus 5 值得购买吗?

是的——当失败的代价很高,而且工作量确实很大时。. 当更精准的诊断、工具应用或长上下文判断能够为工程师或分析师节省时间时,Opus 5 的优势便最为凸显。100 万令牌的上下文窗口、12.8 万令牌的同步输出上限,以及颇具吸引力的每任务成本承诺,这些因素的结合使其稳居值得信赖的高性能主力机型之列。.

哪些人适合使用 Claude Opus 5?

  • 工程团队正在针对大型代码仓库运行编码代理。.
  • 运维团队通过可量化的验收标准,将多步骤业务任务实现自动化。.
  • 能够将该模型与领域审查及实时数据源相结合的法律、财务或研究团队。.
  • 能够通过缓存、批处理、路由和回归测试来控制成本的开发人员。.

谁应该另作选择?

  • 以简单的提取、分类或短文重写为主的大规模应用。.
  • 对延迟敏感的产品,其中中等性能的模型运行速度过慢。.
  • 没有评估数据集、成本监控或针对重要产出的人工审核计划的团队。.
  • 仅需偶尔进行一般性聊天,且不会使用额外上下文或智能代理功能的买家。.

如果觉得Opus 5价格过高或过于专业化,不妨对比一下 2026年Claude的AI替代方案. 如需更全面的市场视角,请参阅《 适用于实际应用场景的最佳AI模型 有助于将工作负载与模型类进行匹配。.

编码采购人员在将团队工作流程标准化之前,还应对比当前的各种选项;该 2026年最适合编程的人工智能模型 将性能和价格置于更广阔的背景之下。.

最终结论: 对于硬编码、自动化以及知识型工作任务,Claude Opus 5 值得尝试,因为在这些场景中,更优异的性能表现足以抵消其较高的代币成本。其官方规格表现强劲,Anthropic 的基准测试结果在成本控制方面表现得尤为出色,而我们验证过的调试结果也精准且严谨。 若您需要处理具有可量化成果的复杂任务,不妨考虑购买该模型——但请注意,并非每项任务都需要 Opus 级别的模型。.

Claude Opus 5 常见问题解答

Claude Opus 5 多少钱?

Claude API 的官方基准价格为:每百万输入代币 $5,每百万输出代币 $25。 面向消费者的 Claude 套餐价格有所不同:Pro 套餐月费为 $20,按年付费时月费为 $17;而 Max 套餐月费起价为 $100。.

如何访问 Claude Opus 5?

Anthropic 表示,Opus 5 是 Claude Max 上的默认模型,也是 Claude Pro 上的最强模型。开发者可以使用 Claude API,而支持的云端路径包括 Amazon Bedrock 和 Google Cloud,但需满足各服务商特定的访问要求。.

Claude Opus 5 API 模型 ID 是多少?

Claude API 的官方模型 ID 和别名均为 claude-opus-5。请在 Anthropic Messages API 请求的 model 字段中使用完全相同的值,然后在迁移至生产环境之前,重新运行您自己的回归测试和安全性评估。.

Claude Opus 5 的应用场景和输出限制是什么?

Claude Opus 5 在同步 Messages API 中具有 100 万个令牌的上下文窗口,最大输出为 128,000 个令牌。Anthropic 另行说明,对于带有 beta 标头的消息批次,最大输出令牌数可达 300,000 个。.

Claude Opus 5 的基准测试结果是否经过独立验证?

此处引用的基准数据由 Anthropic 发布,并非为本评测而独立重现。这些数据反映了 Anthropic 测试所得的性能与成本表现,但购买者应根据自身工作负载,自行验证其质量、延迟、工具使用情况及总成本。.

Claude Opus 5 比 Opus 4.8 或 Fable 5 更好吗?

Opus 5 是 Opus 4.8 的最新继任版本,基础成本与后者相同,因此在回归测试后,它是理所当然的迁移候选方案。Fable 5 仍是前沿参考方案;仅当您的评估表明其额外功能足以证明更高成本的合理性时,才应选择它。.

Claude Opus 5 是否可在 GlobalGPT 上使用?

是的。GlobalGPT 设有专门的 Claude Opus 第 5 页。可用性仍可能取决于账户状态和平台条件,因此请在执行对时间敏感的工作流之前确认访问权限,并将平台访问权限与官方 Anthropic API 计费分开处理。.

Claude Opus 5 的费用应该由谁来承担?

Opus 5 最适合处理复杂编码、自动化或需要长期积累知识的任务的团队,在这些任务中,更优的答案能够为人类节省大量时间。而对于较为简单、处理量大或对延迟敏感的工作,通常应选择更经济、速度更快的模型。.

分享帖子:

相关帖子