siluzan-tso-cli 1.1.28-beta.1 → 1.1.28-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
51
51
  siluzan-tso init --force # 强制覆盖已存在文件
52
52
  ```
53
53
 
54
- > **注意**:当前为测试版(1.1.28-beta.1),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.28-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
55
55
 
56
56
  | 助手 | 建议 `--ai` |
57
57
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -102729,7 +102729,7 @@ init_dist();
102729
102729
  import * as fs18 from "fs";
102730
102730
  import * as path26 from "path";
102731
102731
  import { fileURLToPath as fileURLToPath6 } from "url";
102732
- import { Command } from "commander";
102732
+ import { Command as Command2 } from "commander";
102733
102733
 
102734
102734
  // src/commands/login/urls.ts
102735
102735
  init_defaults();
@@ -121435,6 +121435,8 @@ function register25(program2) {
121435
121435
  console.log(" CLI \u62C9\u6570\uFF1A");
121436
121436
  console.log(" siluzan-tso website-diagnosis collect --url <url> --json-out ./snap-web");
121437
121437
  console.log(" siluzan-tso website-diagnosis performance --url <url> --json-out ./snap-web");
121438
+ console.log(" \u9ED8\u8BA4\u4EA4\u4ED8 HTML\uFF1A");
121439
+ console.log(" siluzan-tso website-diagnosis render --data ./diagnosis.json --collect ./snap-web/<collect>.json");
121438
121440
  console.log(" Skill\uFF1Areferences/analytics/website-diagnosis-guide.md\n");
121439
121441
  console.log(" \u3010\u8D26\u6237\u5217\u8868 ARIT \u5206\u3011");
121440
121442
  console.log(" list-accounts \u4F1A\u8865\u5145 ma.diagnoseReports \u4E2D reportSource=ARIT \u7684\u5F97\u5206\uFF1B");
@@ -121633,7 +121635,7 @@ async function runWebsiteDiagnosisCollect(opts) {
121633
121635
  htmlPreview,
121634
121636
  ...htmlFull ? { htmlContent: htmlFull } : {},
121635
121637
  ...htmlError ? { htmlError } : {},
121636
- agentHint: "1) \u6309 website-diagnosis-rules.md \u751F\u6210\u8BCA\u65AD JSON\uFF1B2) siluzan-tso website-diagnosis render --data <diagnosis.json> --collect <\u672C\u6587\u4EF6> \u8F93\u51FA\u5E26\u56FE\u8868\u7684 website-diagnosis-report.html\u3002"
121638
+ agentHint: "1) \u6309 website-diagnosis-rules.md \u751F\u6210\u8BCA\u65AD JSON\uFF1B2) siluzan-tso website-diagnosis render --data <diagnosis.json> --collect <\u672C\u6587\u4EF6> \u9ED8\u8BA4\u4EA7\u51FA HTML \u7EC8\u7A3F website-diagnosis-report.html\uFF08\u7981\u6B62\u4EC5 Markdown/JSON \u4EA4\u4ED8\uFF09\u3002"
121637
121639
  };
121638
121640
  if (await emitCliJsonOrSnapshot(
121639
121641
  { jsonOut: opts.jsonOut },
@@ -121756,7 +121758,7 @@ async function runWebsiteDiagnosisRender(opts) {
121756
121758
  // src/commands/website-diagnosis/register.ts
121757
121759
  function registerWebsiteDiagnosisCommands(program2) {
121758
121760
  const root = program2.command("website-diagnosis").description(
121759
- "\u7F51\u7AD9\u8BCA\u65AD\uFF1ALighthouse \u6027\u80FD\u3001HTML \u91C7\u96C6\uFF08Agent download-assets\uFF09\u3001ARIT \u5386\u53F2\u5F97\u5206\u67E5\u8BE2"
121761
+ "\u7F51\u7AD9\u8BCA\u65AD\uFF1ALighthouse \u6027\u80FD\u3001HTML \u91C7\u96C6\u3001ARIT \u5386\u53F2\u5F97\u5206\uFF1B\u9ED8\u8BA4\u4EA4\u4ED8 HTML \u62A5\u544A\uFF08render \u5B50\u547D\u4EE4\uFF09"
121760
121762
  );
121761
121763
  root.command("performance").description("\u62C9\u53D6 Lighthouse \u6027\u80FD\u6570\u636E\uFF08GET WebsiteDiagnosisReports/performance\uFF09").requiredOption("--url <url>", "\u7F51\u7AD9 URL\uFF08\u53EF\u7701\u7565 https://\uFF0C\u81EA\u52A8\u8865\u5168\uFF09").option("--token <token>", "JWT\uFF08\u9ED8\u8BA4\u8BFB config / \u73AF\u5883\u53D8\u91CF\uFF09").option("--verbose", "\u6253\u5370\u8BF7\u6C42\u8BE6\u60C5").option("--json-out <dir>", "\u843D\u76D8 cli-manifest + JSON").action(async (opts) => {
121762
121764
  await runWebsiteDiagnosisPerformance({
@@ -121789,7 +121791,7 @@ function registerWebsiteDiagnosisCommands(program2) {
121789
121791
  }
121790
121792
  );
121791
121793
  root.command("render").description(
121792
- "\u6839\u636E\u8BCA\u65AD JSON \u751F\u6210\u5E26\u56FE\u8868\u7684\u5355\u6587\u4EF6 HTML \u62A5\u544A\uFF08website-diagnosis-report.html\uFF09"
121794
+ "\u6839\u636E\u8BCA\u65AD JSON \u751F\u6210 HTML \u7EC8\u7A3F\uFF08\u9ED8\u8BA4\u4EA4\u4ED8\u683C\u5F0F\uFF0Cwebsite-diagnosis-report.html\uFF09"
121793
121795
  ).requiredOption("--data <file>", "\u8BCA\u65AD\u7ED3\u679C JSON\uFF08getWebsiteDiagnosisData \u540C\u7ED3\u6784\uFF09").option("--collect <file>", "\u53EF\u9009\uFF1Acollect \u843D\u76D8 JSON\uFF0C\u7528\u4E8E\u5408\u5E76 lighthouse").option("--out <file>", "\u8F93\u51FA HTML \u8DEF\u5F84\uFF08\u9ED8\u8BA4\u540C --data \u76EE\u5F55\uFF09").action(async (opts) => {
121794
121796
  await runWebsiteDiagnosisRender({
121795
121797
  dataFile: opts.data,
@@ -122476,6 +122478,9 @@ function endpointHintForFacebookSection(def, apiId) {
122476
122478
  return `GET \u2026/FacebookAds/${apiId}/${def.segment}`;
122477
122479
  }
122478
122480
 
122481
+ // src/commands/facebook-analysis/register-cli.ts
122482
+ import { Command } from "commander";
122483
+
122479
122484
  // src/commands/facebook-analysis/render-report.ts
122480
122485
  import fs17 from "fs";
122481
122486
  import fsPromises2 from "fs/promises";
@@ -122746,20 +122751,19 @@ async function runFacebookAnalysisRender(opts) {
122746
122751
  await fsPromises2.writeFile(outPath, injectReportData2(html, data), "utf8");
122747
122752
  const runtimeSrc = metaPeriodReportRuntimePath();
122748
122753
  const runtimeOut = path24.join(outDir, TEMPLATE_BASENAMES2.runtime);
122754
+ let runtimeCopied = false;
122749
122755
  try {
122750
122756
  await fsPromises2.copyFile(runtimeSrc, runtimeOut);
122757
+ runtimeCopied = true;
122751
122758
  } catch {
122752
- console.error(`
122753
- \u274C \u672A\u627E\u5230\u62A5\u544A\u8FD0\u884C\u65F6\uFF1A${runtimeSrc}
122754
- \u8BF7\u5148\u6267\u884C npm run build
122755
- `);
122756
- process.exit(1);
122757
122759
  }
122758
122760
  console.log(`
122759
122761
  \u2705 Meta/Facebook \u5468\u671F\u5206\u6790 HTML \u62A5\u544A\u5DF2\u751F\u6210\uFF1A${outPath}
122760
122762
  `);
122761
- console.log(` \u8FD0\u884C\u65F6\u811A\u672C\uFF1A${runtimeOut}
122763
+ if (runtimeCopied) {
122764
+ console.log(` \u8FD0\u884C\u65F6\u811A\u672C\uFF1A${runtimeOut}
122762
122765
  `);
122766
+ }
122763
122767
  console.log("\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00 HTML \u6587\u4EF6\u5373\u53EF\u67E5\u770B\u56FE\u8868\u4E0E\u5B8C\u6574\u7AE0\u8282\uFF08\u9700\u8054\u7F51\u52A0\u8F7D Chart.js CDN\uFF09\u3002\n");
122764
122768
  }
122765
122769
 
@@ -122887,10 +122891,9 @@ async function runAllFacebookSections(opts) {
122887
122891
  }
122888
122892
 
122889
122893
  // src/commands/facebook-analysis/register-cli.ts
122890
- function registerFacebookAnalysisCommands(program2) {
122891
- const sectionHelp = FACEBOOK_SECTION_NAMES.join(", ");
122892
- const root = program2.command("facebook-analysis").description(
122893
- "Facebook Ads \u8D26\u6237\u5206\u6790\u6279\u91CF\u62C9\u53D6\uFF08TSO reporting/media-account/FacebookAds/\u2026\uFF0C7 \u4E2A Section\uFF09"
122894
+ function registerBatchCommand(sectionHelp) {
122895
+ return new Command("run").description(
122896
+ "\u6279\u91CF\u62C9\u53D6 TSO reporting/media-account/FacebookAds Section \u6570\u636E\uFF08\u7701\u7565\u5B50\u547D\u4EE4\u540D\u65F6\u9ED8\u8BA4\u6267\u884C\u672C\u547D\u4EE4\uFF09"
122894
122897
  ).requiredOption(
122895
122898
  "-a, --account <id>",
122896
122899
  "Facebook \u5E7F\u544A\u8D26\u6237 mediaCustomerId\uFF08\u6570\u5B57\u6216 act_<\u6570\u5B57>\uFF09"
@@ -122910,6 +122913,13 @@ function registerFacebookAnalysisCommands(program2) {
122910
122913
  ).option("--concurrency <n>", "\u5E76\u53D1\u6570\uFF0C\u9ED8\u8BA4 5\uFF0C\u4E0A\u9650 16", (v) => parseInt(v, 10)).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
122911
122914
  await runAllFacebookSections(opts);
122912
122915
  });
122916
+ }
122917
+ function registerFacebookAnalysisCommands(program2) {
122918
+ const sectionHelp = FACEBOOK_SECTION_NAMES.join(", ");
122919
+ const root = program2.command("facebook-analysis").description(
122920
+ "Facebook Ads \u8D26\u6237\u5206\u6790\uFF1A\u6279\u91CF\u62C9\u53D6 Section \u6570\u636E\uFF08\u9ED8\u8BA4\uFF09\uFF0C\u6216\u7531 render \u751F\u6210 HTML \u5468\u671F\u62A5\u544A"
122921
+ );
122922
+ root.addCommand(registerBatchCommand(sectionHelp), { isDefault: true });
122913
122923
  root.command("render").description(
122914
122924
  "\u6839\u636E Agent \u64B0\u5199\u7684\u62A5\u544A JSON \u751F\u6210 Meta/Facebook \u5468\u671F\u5206\u6790 HTML \u7EC8\u7A3F\uFF08meta-period-report.html\uFF09"
122915
122925
  ).requiredOption("--data <file>", "Agent \u4EA7\u51FA\u7684 meta-period-report.json").option(
@@ -122938,7 +122948,7 @@ function getVersion() {
122938
122948
  return "0.0.0";
122939
122949
  }
122940
122950
  }
122941
- var program = new Command();
122951
+ var program = new Command2();
122942
122952
  program.name("siluzan-tso").description(
122943
122953
  "Siluzan \u5E7F\u544A\u8D26\u6237\u7BA1\u7406\uFF1A\u8D26\u6237\u67E5\u8BE2\u3001\u4F59\u989D\u3001\u6295\u653E\u6570\u636E\u3001\u5F00\u6237\u7533\u8BF7\uFF08Google/TikTok/Yandex/Bing/Kwai\uFF09\u3001\n\u8D26\u53F7\u5206\u4EAB/\u89E3\u7ED1\u3001\u4F18\u5316\u62A5\u544A\u3001Google \u8D26\u6237\u5206\u6790\u7F51\u5173\uFF08google-analysis\uFF09\u3001\u7F51\u7AD9\u8BCA\u65AD\uFF08website-diagnosis\uFF09\u3001\u6218\u7565\u5E02\u573A\u5206\u6790\uFF08market-analysis\uFF0CAgent \u751F\u6210\u62A5\u544A\uFF09\u3001\u5145\u503C\u8F6C\u8D26\u3001\u5F00\u7968\u3001\u667A\u80FD\u9884\u8B66\u3001Google \u5E7F\u544A\u7BA1\u7406\uFF08\u542B\u5F02\u6B65\u6279\u91CF\uFF09\u3002"
122944
122954
  ).version(getVersion());
@@ -19,6 +19,8 @@ allowed-tools: Bash(siluzan-tso:*) Read Write
19
19
  >
20
20
  > **报告/Excel 交付前**:Read `references/core/deliverable-preflight.md`,**Read 最终产物**并按自检表确认币种与章节完整;币种只认当次 `list-accounts` 的 `currencyCode`。
21
21
  >
22
+ > **HTML 终稿类报告(用户未指定格式时默认 HTML)**:网站诊断 P8(`website-diagnosis render`)、Meta 周期 P4-FB(`facebook-analysis render`)、战略市场 P9(`market-analysis render`)。Agent 只写 JSON,**禁止**仅交付 Markdown 摘要或纯 JSON 充当终稿。
23
+ >
22
24
  > **开户**:首次进入开户话题须先向用户罗列该媒体(或未指明媒体时六平台)**全部必填项**,见 `references/accounts/open-account-by-media.md` §「首次响应硬规范」。
23
25
  >
24
26
  > **Subagent(可选)**:若宿主支持 Task / 子会话,复杂报告(P5/P6/P7)或长 CLI 输出前 Read `references/core/subagent-orchestration.md`,**自行决定**是否委派;写操作确认与对用户的最终交付留在主 Agent。
@@ -84,10 +86,10 @@ Windows:部分 Agent 通过 PowerShell 代执行时可能失败,改在 [Git
84
86
  | 用户意图(关键词) | 必读(Read 后再 `-h` / 执行) |
85
87
  | ------------------ | ----------------------------- |
86
88
  | 任意任务(首次) | `core/agent-conventions.md` |
87
- | 账户列表 / 余额 / 消耗 / 分享 / MCC / 多账户汇总 | `accounts/accounts.md`;金额加 `accounts/currency.md` |
89
+ | 账户列表 / 有多少 / 列出全部 / 余额 / 消耗 / 分享 / MCC | `accounts/accounts.md`(§ list-accounts **Agent 意图速查**:`-m <媒体> --page-size 999 --json-out` 一步拉全);金额加 `accounts/currency.md` |
88
90
  | google ads 拉数 / 报告 / 周报 / `google-analysis` | `analytics/account-analytics.md` + `core/tips.md` + **`core/deliverable-preflight.md`**;多账户加 `analytics/google-analysis-batch.md` |
89
- | Meta/Facebook 周期或诊断报告 / `facebook-analysis` | `report-templates/meta-period-report-excel.md`(Excel Sheet 基准)+ `meta-period-report.md` + `analytics/facebook-analysis-guide.md`;Agent `meta-period-report.json`,`facebook-analysis render` 出 HTML |
90
- | 网站诊断 / 落地页评分 / `website-diagnosis` | `analytics/website-diagnosis-guide.md` + `assets/website-diagnosis-rules.md` + `core/playbooks.md` P8Agent 只写 JSON,`website-diagnosis render` HTML |
91
+ | Meta/Facebook 周期或诊断报告 / `facebook-analysis` | **默认 HTML**:`meta-period-report.md` + **`assets/meta-period-report-rules.md`**(内容丰富度必读)+ `facebook-analysis-guide.md` + `deliverable-preflight.md` → 拉数 → 分析 → JSON(4 条建议≥150字+7维补充+HTML扩展)→ `render`;**仅用户要 Excel** 时加读 `meta-period-report-excel.md` |
92
+ | 网站诊断 / 落地页评分 / `website-diagnosis` | `analytics/website-diagnosis-guide.md` + `assets/website-diagnosis-rules.md` + `core/playbooks.md` P8 + `core/deliverable-preflight.md`;Agent 只写 JSON,**默认交付** `website-diagnosis render` 产出的 **HTML**(禁止仅 Markdown/JSON) |
91
93
  | 市场分析 / 行业分析 / 战略市场报告 / `market-analysis` | `analytics/market-analysis-guide.md` + `assets/market-analysis-rules.md`(原始业务维度清单)+ `report-templates/market-analysis-report.md` + `core/playbooks.md` P9;`collect` → Agent 按维度调研写 `market-report.json` → `render`(缺项校验) |
92
94
  | Google 新建搜索系列 | `google-ads/google-ads-campaign-plan.md` |
93
95
  | Google 广告 CRUD / 拒审 | `google-ads/google-ads.md` |
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.28-beta.1",
4
- "publishedAt": 1780888059129
3
+ "version": "1.1.28-beta.2",
4
+ "publishedAt": 1780907501825
5
5
  }
@@ -0,0 +1,169 @@
1
+ # Meta 周期报告撰写规则(Agent 用)
2
+
3
+ > 对齐 **P8 网站诊断** 的「结构化 + 全量覆盖 + 每条必有建议」思路。
4
+ > 源:业务 Excel 模板(`无锡顺晟Facebook4月报告.xlsx`)+ `meta-period-report.html` 深度分析章节。
5
+ > **禁止**只写 KPI 表、4 条一句话建议或空白占位后交付。
6
+
7
+ ---
8
+
9
+ ## 与网站诊断的对照(为何 FB 报告会显得「建议太少」)
10
+
11
+ | 网站诊断(P8) | Meta 周期报告(P4-FB) |
12
+ | -------------- | ---------------------- |
13
+ | `website-diagnosis-rules.md` 规定 29 子项全覆盖 | 本文件规定 **5 维数据 + 叙事 + 建议** 全覆盖 |
14
+ | 每项 `issue` + `suggestion`(较差项以「强烈建议:」开头) | 每条建议 `content` 须 **引用当次数字** + **可执行动作** |
15
+ | `coreIssuesIds` + `PriorityPlan` 高/中/低 | `priorityPlan` + `narrative.recommendations` 4 条 + `supplementaryRecommendations` |
16
+ | HTML 由 `render` 渲染全部章节 | HTML **必须**填 `executiveSummary`、`healthDiagnosis`、`sections.*.insight` 等(见下) |
17
+ | 交付前 Read HTML 对照章节清单 | 交付前 Read HTML/xlsx 对照 `deliverable-preflight.md` § P4-FB |
18
+
19
+ **常见失误(导致建议偏少)**:
20
+
21
+ 1. 只写 Excel 叙事 4 条标题、每条 1~2 句泛化话术,未引用 CPL/花费/国家名。
22
+ 2. HTML 默认路径只填 `narrative`,**未填** `executiveSummary` / `healthDiagnosis` / `sections.insight`(模板原先不展示 `narrative.recommendations`,现已修复)。
23
+ 3. 未按 **7 维数据驱动清单** 逐条给建议,只写「优化素材」「调整预算」等空话。
24
+
25
+ ---
26
+
27
+ ## JSON 结构(摘要)
28
+
29
+ 完整 Schema:`assets/meta-period-report.schema.json`。
30
+ **Excel 与 HTML 共用** `narrative`;**HTML 默认交付**还须填「深度分析扩展」字段。
31
+
32
+ ---
33
+
34
+ ## 一、Excel / 总数据叙事(`narrative` · 必填)
35
+
36
+ ### 1. `narrative.overall`(整体表现)
37
+
38
+ | 要求 | 细则 |
39
+ | ---- | ---- |
40
+ | 字数 | **≥ 120 字**(中文) |
41
+ | 必含数字 | 花费、`results`、CPL(`costPerResult`)、`reach`、`impressions`、`frequency` **至少 5 项** |
42
+ | 必含口径 | `resultType`、`attributionSetting`(写入 `meta` 并在段中提及) |
43
+ | 可选 | 若有 `previousPeriod`,写 1~2 句环比(花费 ±%、CPL ±%) |
44
+
45
+ ### 2. `narrative.regional[]`(区域 / 广告组)
46
+
47
+ | 要求 | 细则 |
48
+ | ---- | ---- |
49
+ | 条数 | **每个** `ad-sets` 中花费 >0 的广告组 **各 1 段**(不得合并成 1 句带过) |
50
+ | 字数 | 每段 **≥ 80 字** |
51
+ | 必含 | 组名、花费占比或绝对值、线索数、`costPerResult`、频次;判断「曝光不足 / 频次过高 / 效率领先」 |
52
+ | 数据依据 | `ad-sets-<id>.json` → `adGroups[]` |
53
+
54
+ ### 3. `narrative.country`(国家报告)
55
+
56
+ | 要求 | 细则 |
57
+ | ---- | ---- |
58
+ | 字数 | **≥ 80 字** |
59
+ | 必含 | CPL **最低** 与 **最高** 国家名及具体 CPL;中间梯队 1~2 国;花费集中度 |
60
+ | 数据依据 | `country-<id>.json` → `countries[]` |
61
+
62
+ ### 4. `narrative.recommendations[]`(固定 4 条标题)
63
+
64
+ **必须恰好 4 条**,`title` 仅限下表枚举;`content` 须**数据驱动**,不得模板空话。
65
+
66
+ | title | content 最低要求(每条 **≥ 150 字**) |
67
+ | ----- | ------------------------------------- |
68
+ | **简化表单问题** | 结合 **高频次 + 高 CPL** 的国家/组(写出名称与数字);建议字段从 N 减到 3;说明预期对 CPL 的影响 |
69
+ | **区域调整** | 按 **具体广告组** 写语言/市场策略(如土/葡/德);引用各组 CPL 对比;写清「加谁、减谁、暂停谁」 |
70
+ | **预算重构** | 给出 **具体比例**(如 4:3:3 或按 spend 占比调整);测试周期(7/14 天);优胜劣汰阈值(CPL > 账户均值 ×1.2 则减 30%) |
71
+ | **素材建议** | 按 **平台**(IG/FB)与 **国家** 分述;素材套数、视频时长、形态;至少点名 1 个高花费低结果创意/版位 |
72
+
73
+ **建议前缀(对齐网站诊断)**:
74
+
75
+ - 问题严重(CPL > 均值 1.3 倍、频次 >2.5、零成效花费 >$50)→ `content` 以 **「强烈建议:」** 开头
76
+ - 其余优化项 → **「推荐优化:」** 开头
77
+
78
+ ---
79
+
80
+ ## 二、数据驱动补充建议(`supplementaryRecommendations` · 必填)
81
+
82
+ 在 4 条固定标题之外,**必须**再写 **7 维清单**,每条 `{ "dimension", "issue", "suggestion" }`:
83
+
84
+ | dimension | issue(发现了什么) | suggestion(怎么办) |
85
+ | --------- | ------------------- | -------------------- |
86
+ | 预算与广告组 | 点名高 `spendPercentage`、差 `costPerResult` 的组 | 降预算 %、暂停、或合并受众 |
87
+ | 平台与版位 | `publisherPlatform` + `platformPosition` 组合 | 减投差版位、加码 winner 平台 |
88
+ | 地域 | 高消耗低结果国家 | geo 排除 / 收窄 / 单独组 |
89
+ | 受众 | 低效 age×gender | 排除或降 bid;扩量高效段 |
90
+ | 创意 | 高花费低 `results` 的 ad | 关停、复制 winner 结构 |
91
+ | 频次与疲劳 | `frequency` >2.5 且转化差 | 扩受众、换创意、降预算 |
92
+ | 接口限制 | 无按日/关键词等 | 一句说明「Meta 接口未提供」,**禁止编造** |
93
+
94
+ 每条 `suggestion` **≥ 60 字**,须含 **至少 1 个当次数字或名称**。
95
+
96
+ ---
97
+
98
+ ## 三、优先级改进计划(`priorityPlan` · HTML 必填 · Excel 推荐)
99
+
100
+ 对齐网站诊断 `PriorityPlan`:
101
+
102
+ ```jsonc
103
+ {
104
+ "priorityPlan": {
105
+ "high": ["…", "…"], // ≥2 条,本周必须做
106
+ "medium": ["…", "…"], // ≥2 条
107
+ "low": ["…", "…"] // ≥2 条,持续优化
108
+ }
109
+ }
110
+ ```
111
+
112
+ 每条 **≥ 40 字**,带责任维度(预算/素材/地域等)。
113
+
114
+ ---
115
+
116
+ ## 四、HTML 默认交付 · 深度分析扩展(必填)
117
+
118
+ 用户未指定 Excel 时,除 §一~§三外 **还必须** 填写:
119
+
120
+ | 字段 | 最低要求 |
121
+ | ---- | -------- |
122
+ | `executiveSummary` | **3~5 段**,每段 **≥ 80 字**;解释「为什么」而不只报数;可拆自 `narrative.overall` 但须加深因果 |
123
+ | `healthDiagnosis.lifecyclePhase` | `test-market` / `find-winner` / `scale` 三选一 |
124
+ | `healthDiagnosis.lifecycleVerdict` | **≥ 60 字**,结合总花费与维度分散度 |
125
+ | `healthDiagnosis.fourQuestions` | **恰好 4 张卡片**(钱花得值不值 / 赢在哪 / 输在哪 / 下月重点) |
126
+ | 每张 `fourQuestions[]` | `verdict` + `evidence` **≥2 条**(含数字)+ `action` **≥ 40 字** |
127
+ | `healthDiagnosis.scorecard` | **≥ 6 行**(平台、国家、广告组、受众等分项红绿灯) |
128
+ | `sections.platform.insight` | **≥ 200 字** |
129
+ | `sections.country.insight` | **≥ 200 字** |
130
+ | `sections.adSets.insight` | **≥ 200 字** |
131
+ | `sections.audience` | `goldenProfile` **≥3 条** + `antiProfile` **≥2 条** + `insight` **≥ 150 字** |
132
+ | `sections.landingPage.rows` | **≥ 3 行**(心理阻碍 / 数据信号 / 推演 / 优先级) |
133
+ | `abTests` | **≥ 3 个**实验(变量、假设、成功标准) |
134
+ | `actionChecklist` | `today` **≥2**、`thisWeek` **≥3**、`thisMonth` **≥3** 条可执行项 |
135
+
136
+ **禁止**:HTML 中大量「(待 Agent 撰写)」占位;交付前 Read HTML 确认无空节。
137
+
138
+ ---
139
+
140
+ ## 五、撰写流程(对齐 P8)
141
+
142
+ 1. **拉数**:`facebook-analysis` + `--json-out`(默认 5 维)。
143
+ 2. **脚本读盘**:聚合 KPI、Top/Bottom 国家、平台、受众、广告组(禁止 Read 业务 JSON 进对话)。
144
+ 3. **先 outline 后 JSON**:列出将引用的数字与 7 维建议要点,再写 `meta-period-report.json`。
145
+ 4. **渲染**:`facebook-analysis render`(HTML)或脚本写 xlsx(Excel)。
146
+ 5. **Read 终稿**:对照 `deliverable-preflight.md` § P4-FB。
147
+
148
+ ---
149
+
150
+ ## 六、自检清单(Agent 交付前勾选)
151
+
152
+ - [ ] `narrative.recommendations` 4 条,每条 content ≥150 字且含真实数字
153
+ - [ ] `supplementaryRecommendations` 7 维齐全
154
+ - [ ] `priorityPlan` high/medium/low 各 ≥2 条
155
+ - [ ] HTML:`executiveSummary` ≥3 段、`fourQuestions` =4、`scorecard` ≥6 行
156
+ - [ ] HTML:`sections.platform/country/adSets.insight` 各 ≥200 字
157
+ - [ ] HTML:`actionChecklist` 三列非空;`abTests` ≥3
158
+ - [ ] Excel:总数据 Sheet 叙事块 4 节齐全,无 1 句话敷衍
159
+ - [ ] 未编造 Meta 无接口维度(按日、关键词等)
160
+
161
+ ---
162
+
163
+ ## 相关文档
164
+
165
+ - `report-templates/meta-period-report.md` — 流程与章节
166
+ - `report-templates/meta-period-report-excel.md` — Excel 五 Sheet
167
+ - `references/analytics/facebook-analysis-guide.md` — API 字段
168
+ - `references/core/deliverable-preflight.md` — 交付审阅
169
+ - `assets/website-diagnosis-rules.md` — 网站诊断(对照参考)
@@ -60,8 +60,9 @@
60
60
  },
61
61
  "recommendations": {
62
62
  "type": "array",
63
- "description": "优化建议固定 4 ",
64
- "minItems": 1,
63
+ "description": "优化建议固定 4 条;每条 content ≥150 字且引用当次数据(见 meta-period-report-rules.md)",
64
+ "minItems": 4,
65
+ "maxItems": 4,
65
66
  "items": {
66
67
  "type": "object",
67
68
  "required": ["title", "content"],
@@ -70,12 +71,39 @@
70
71
  "type": "string",
71
72
  "enum": ["简化表单问题", "区域调整", "预算重构", "素材建议"]
72
73
  },
73
- "content": { "type": "string" }
74
+ "content": {
75
+ "type": "string",
76
+ "description": "≥150 字;严重问题以「强烈建议:」开头,其余以「推荐优化:」开头"
77
+ }
74
78
  }
75
79
  }
76
80
  }
77
81
  }
78
82
  },
83
+ "supplementaryRecommendations": {
84
+ "type": "array",
85
+ "description": "7 维数据驱动补充建议(预算/平台/地域/受众/创意/频次/接口限制);每条 suggestion ≥60 字",
86
+ "minItems": 7,
87
+ "maxItems": 7,
88
+ "items": {
89
+ "type": "object",
90
+ "required": ["dimension", "issue", "suggestion"],
91
+ "properties": {
92
+ "dimension": { "type": "string" },
93
+ "issue": { "type": "string" },
94
+ "suggestion": { "type": "string" }
95
+ }
96
+ }
97
+ },
98
+ "priorityPlan": {
99
+ "type": "object",
100
+ "description": "高/中/低优先级改进计划(对齐网站诊断 PriorityPlan)",
101
+ "properties": {
102
+ "high": { "type": "array", "items": { "type": "string" }, "minItems": 2 },
103
+ "medium": { "type": "array", "items": { "type": "string" }, "minItems": 2 },
104
+ "low": { "type": "array", "items": { "type": "string" }, "minItems": 2 }
105
+ }
106
+ },
79
107
  "tables": {
80
108
  "type": "object",
81
109
  "description": "Sheet2~5 表格数据;可省略,由 --snapshot-dir 合并",
@@ -106,11 +134,12 @@
106
134
  "executiveSummary": {
107
135
  "type": "array",
108
136
  "items": { "type": "string" },
109
- "description": "HTML 深度分析扩展:多段执行摘要(可选,优先用 narrative.overall)"
137
+ "minItems": 3,
138
+ "description": "HTML 默认交付必填:3~5 段执行摘要,每段 ≥80 字;可深化 narrative.overall"
110
139
  },
111
140
  "healthDiagnosis": {
112
141
  "type": "object",
113
- "description": "HTML 深度分析扩展:账户健康诊断(Excel 不含)",
142
+ "description": "HTML 默认交付必填:四问卡片 + 红绿灯表(Excel 不含)",
114
143
  "properties": {
115
144
  "lifecyclePhase": { "enum": ["test-market", "find-winner", "scale"] },
116
145
  "lifecycleVerdict": { "type": "string" },
@@ -69,6 +69,8 @@
69
69
  | ---- | ---- |
70
70
  | `campaign-create-template.md` / `.json` | 搜索系列 batch 契约 |
71
71
  | `website-diagnosis-rules.md` | 网站诊断评分项与 JSON Schema |
72
+ | `meta-period-report-rules.md` | Meta 周期报告内容丰富度与建议撰写规则 |
73
+ | `meta-period-report.schema.json` | Meta 周期报告 Agent JSON Schema |
72
74
  | `pmax-create-template.md` / `.json` | PMax 新建契约 |
73
75
  | `pmax-asset-group-template.json` | PMax 素材组 |
74
76
  | `pmax-signals-template.json` | PMax 信号 |
@@ -30,23 +30,52 @@ siluzan-tso list-accounts [选项]
30
30
 
31
31
  需要真实余额或消耗时:单户优先 `balance` / `stats`;列表顺带看余额/消耗时加 `--detail`。**禁止**在 JSON 无余额/消耗字段时臆造数值。
32
32
 
33
- **示例:**
33
+ ### Agent 意图速查(**必读 · 避免多次试探**)
34
+
35
+ 用户问「有哪些 / 列出全部 / 有多少」某媒体广告账户时,**第一次 CLI 就应带大 `--page-size`**,**禁止**先用默认 20 条再翻页重试。
36
+
37
+ | 用户意图 | 推荐命令(一步) | 脚本读落盘 JSON |
38
+ | -------- | ---------------- | --------------- |
39
+ | 列出全部 Google 账户 | `list-accounts -m Google --page-size 999 --json-out <dir>` | `items[]`(`ma.mediaCustomerId`、`ma.mediaCustomerName`、`ma.currencyCode`、`ma.mediaAccountState` 等) |
40
+ | 有多少个 Google 账户 | 同上 | **`total`**(无需翻页;`itemCount < total` 时说明 page-size 不够大) |
41
+ | 列出全部某媒体(TikTok / MetaAd 等) | `list-accounts -m <媒体> --page-size 999 --json-out <dir>` | 同上 |
42
+ | 只查某一个户 | `list-accounts -m <媒体> -k <id或名称> --json-out <dir>` | 无需大 page-size |
43
+ | 列表顺带看余额/消耗 | 在上述命令加 `--detail`(**明显变慢**;仅用户要余额/消耗时) | 含 `ma.balance` 等 enrichment 字段 |
44
+
45
+ **执行纪律**:
46
+
47
+ 1. **一次 CLI**:`--page-size 999` + `--json-out <dir>`;**不要**默认 20 条后再循环 `--page`。
48
+ 2. **stdout 只是摘要**(`kind=siluzan-tso-cli-json-snapshot`),**没有** `total` / `items`;业务数据在 `writtenFiles[0]`(如 `list-accounts-google.json`),**必须用脚本读盘**。
49
+ 3. 仅当读盘后 `total > itemCount` 且已用 `--page-size 999` 时,再 `--page 2` 等同参数补拉;**禁止**对 stdout 写翻页循环。
50
+ 4. 列账户 / 数个数 **不需要** `accounts-digest`、`balance-scan`(那些是消耗汇总或余额预警)。
34
51
 
35
52
  ```bash
36
- # 查询所有 Google 账户(默认:JSON 不含余额/消耗字段)
37
- siluzan-tso list-accounts -m Google
53
+ # 推荐:列出或统计全部 Google 账户(Agent 默认路径)
54
+ siluzan-tso list-accounts -m Google --page-size 999 --json-out ./snap-accounts
38
55
 
39
- # 列表同时带出真实余额与近期消耗(较慢)
40
- siluzan-tso list-accounts -m Google --detail
56
+ # 脚本读盘(示例)
57
+ node -e "
58
+ const fs=require('fs');
59
+ const p='./snap-accounts/list-accounts-google.json';
60
+ const d=JSON.parse(fs.readFileSync(p,'utf8'));
61
+ console.log('total:', d.total, '本页:', d.itemCount);
62
+ "
63
+ ```
64
+
65
+ **示例:**
66
+
67
+ ```bash
68
+ # 关键字搜索(单户/少量,无需大 page-size)
69
+ siluzan-tso list-accounts -m Google -k "品牌A" --json-out ./snap
41
70
 
42
- # 关键字搜索
43
- siluzan-tso list-accounts -k "品牌A"
71
+ # 只看正常状态
72
+ siluzan-tso list-accounts -m TikTok -s normal --page-size 999 --json-out ./snap
44
73
 
45
- # 只看正常状态,输出 JSON 供后续处理
46
- siluzan-tso list-accounts -m TikTok -s normal --json-out ./snap
74
+ # 列表同时带出真实余额与近期消耗(较慢,仅用户要余额/消耗时)
75
+ siluzan-tso list-accounts -m Google --page-size 999 --detail --json-out ./snap
47
76
 
48
- # 分页获取(第 2 页,每页 50 条)
49
- siluzan-tso list-accounts --page 2 --page-size 50
77
+ # 极少数账户超过 999 条时才翻页(先确认读盘 total > itemCount)
78
+ siluzan-tso list-accounts -m Google --page 2 --page-size 999 --json-out ./snap-p2
50
79
  ```
51
80
 
52
81
  **输出字段说明:**
@@ -293,12 +293,13 @@ siluzan-tso facebook-analysis -a <id> --json-out ./snap-fb
293
293
  siluzan-tso facebook-analysis -a <id> --sections country --limit 10 --json-out ./snap-fb
294
294
  ```
295
295
 
296
- ### 报告模板
296
+ ### 报告模板与交付流程
297
297
 
298
- | 场景 | 模板 |
299
- | --- | --- |
300
- | 周期 / 月报 / 周报 | `report-templates/meta-period-report.md`(终稿 HTML:`facebook-analysis render`) |
301
- | 深度诊断 | `report-templates/meta-account-diagnosis-report.md` |
298
+ | 场景 | 模板 | 默认终稿 |
299
+ | --- | --- | --- |
300
+ | 周期 / 月报 / 周报 | `report-templates/meta-period-report.md` | **HTML**(四步:拉数 → 分析 → `meta-period-report.json` → `facebook-analysis render`) |
301
+ | 用户指定 Excel | `report-templates/meta-period-report-excel.md` | Agent 脚本写 `.xlsx`(步骤 1~3 同上;**不**默认 `render`) |
302
+ | 深度诊断 | `report-templates/meta-account-diagnosis-report.md` | 按该模板(通常 HTML) |
302
303
 
303
304
  遗留总览:`siluzan-tso report meta-overview -a <id> [--start … --end …] --json-out <dir>`。
304
305
 
@@ -374,7 +375,7 @@ siluzan-tso report bing-audience-merged -a <mediaCustomerId> --json-out ./snap-b
374
375
  | `meta-period-report.md` | Meta(Facebook)周期报告 |
375
376
  | `tiktok-period-report.md` | TikTok 周期报告 |
376
377
  | `bing-period-report.md` | Bing 周期报告 |
377
- | `website-diagnosis-report.md` | 网站/落地页诊断(`website-diagnosis`,见 `website-diagnosis-guide.md` P8) |
378
+ | `website-diagnosis-report.md` | 网站/落地页诊断(`website-diagnosis`,见 P8);**默认交付 HTML**(`website-diagnosis render`,禁止仅 Markdown) |
378
379
  | `README.md` | 索引与规则 |
379
380
 
380
381
  `.html` 文件(`report-template.html`、`report-template-academic.html` 等)为 HTML 路线的样式参考。选其他格式时仍以各 `*.md` 纲要为章节清单。
@@ -4,6 +4,25 @@
4
4
 
5
5
  ---
6
6
 
7
+ ## 周期报告标准流程(默认 HTML)
8
+
9
+ 用户要 **Facebook / Meta 分析报告**且**未指定交付格式**时,按以下四步执行:
10
+
11
+ | 步骤 | 说明 |
12
+ | ---- | ---- |
13
+ | **1. 拉数** | `facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb`(默认 `--sections overview,ad-sets,platform,country,audience`) |
14
+ | **2. 分析** | Agent 用脚本读 `report-manifest-<id>.json` 与各 `<section>-<id>.json`,完成聚合与洞察(禁止 Read 业务 JSON、禁止对话里手填数) |
15
+ | **3. 写 JSON** | 产出 `meta-period-report.json`(`narrative` 必填;HTML 扩展字段按需) |
16
+ | **4. 渲染** | `facebook-analysis render --data ./meta-period-report.json --snapshot-dir ./snap-fb --out ./meta-period-report.html` |
17
+
18
+ **禁止**:跳过步骤 3/4 直接交付 Markdown;禁止 Agent 手写 HTML。
19
+
20
+ ### Excel 分支(仅用户指定时)
21
+
22
+ 用户明确要求 **Excel / xlsx** 时:步骤 1~3 相同;步骤 4 改为 Agent 脚本按 `meta-period-report-excel.md` 写 `.xlsx`,**不**调用 `render`(除非同时要 HTML)。
23
+
24
+ ---
25
+
7
26
  ## 与 Google 周期报告的能力对照
8
27
 
9
28
  | Google 默认/常见维度 | Facebook 对应 | CLI | 说明 |
@@ -93,16 +112,16 @@
93
112
 
94
113
  ---
95
114
 
96
- ## 周期报告默认拉数(对齐 Excel 五 Sheet
115
+ ## 周期报告默认拉数(步骤 1
97
116
 
98
117
  ```bash
99
118
  mkdir -p ./snap-fb
100
- siluzan-tso facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb
101
- # 等价显式(Excel 模板默认,不含 creative):
102
- # --sections overview,ad-sets,platform,country,audience
119
+ siluzan-tso facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb \
120
+ --sections overview,ad-sets,platform,country,audience
103
121
  ```
104
122
 
105
- Excel 模板章节与叙事结构:**`report-templates/meta-period-report-excel.md`**。Agent JSON Schema:**`assets/meta-period-report.schema.json`**。
123
+ 叙事结构与 Agent JSON:**`meta-period-report.md`** + **`assets/meta-period-report.schema.json`**。
124
+ 仅 Excel 交付时再读 **`report-templates/meta-period-report-excel.md`**(5 Sheet 版式)。
106
125
 
107
126
  可选追加:`--sections material`(DC 账户)。
108
127
 
@@ -110,9 +129,10 @@ Excel 模板章节与叙事结构:**`report-templates/meta-period-report-excel
110
129
 
111
130
  ---
112
131
 
113
- ## HTML 终稿渲染(对齐网站诊断 `render`)
132
+ ## HTML 终稿渲染(步骤 4 · 默认交付)
114
133
 
115
- Agent 读完各 section JSON 后撰写 `meta-period-report.json`(叙事 + 健康诊断结构),**禁止手写 HTML**:
134
+ 完成步骤 2(分析)与步骤 3(`meta-period-report.json`)后执行,**禁止手写 HTML**。
135
+ `render` 为独立子命令,**不需要** `-a` / `--json-out`(与批拉命令分离):
116
136
 
117
137
  ```bash
118
138
  siluzan-tso facebook-analysis render \
@@ -129,15 +149,29 @@ siluzan-tso facebook-analysis render \
129
149
 
130
150
  ## 优化建议撰写清单(不额外拉数)
131
151
 
132
- 结合已拉维度,至少覆盖:
152
+ **必读** `assets/meta-period-report-rules.md`(对齐 P8 网站诊断:每条建议须**引用当次数字** + **可执行动作**,禁止空话)。
153
+
154
+ ### 三层建议结构
155
+
156
+ | 层级 | JSON 字段 | 要求 |
157
+ | ---- | --------- | ---- |
158
+ | 固定 4 条 | `narrative.recommendations[]` | 标题枚举 4 个;每条 content **≥150 字** |
159
+ | 7 维补充 | `supplementaryRecommendations` | 预算/平台/地域/受众/创意/频次/接口限制 **各 1 条** |
160
+ | 优先级 | `priorityPlan` | high/medium/low 各 **≥2 条** |
161
+
162
+ ### 7 维数据驱动要点
163
+
164
+ 1. **预算**:高 `spendPercentage` 但 `costPerResult` 差的 Ad Set → 降预算 % / 暂停(写组名与数字)。
165
+ 2. **平台/版位**:`publisherPlatform` + `platformPosition` 组合(勿只读 `network`)。
166
+ 3. **地域**:高消耗国家转化差 → geo 排除 / 收窄(写国家名与 CPL)。
167
+ 4. **受众**:低效 age×gender → 排除或降 bid(写年龄段)。
168
+ 5. **创意**:关停高花费低 `results` 的 ad;复制 winner 结构。
169
+ 6. **频次**:`frequency` >2.5 + 转化差 → 扩受众或换创意。
170
+ 7. **接口限制**:按日/关键词等 — 一句「Meta 接口未提供」,不编造。
171
+
172
+ ### HTML 默认交付(还须填)
133
173
 
134
- 1. **预算**:高 `spendPercentage` `costPerResult` 差的 Ad Set 降预算/暂停。
135
- 2. **平台/版位**:按 `publisherPlatform` + `platformPosition` 定位高消耗低 `costPerResult` 组合(勿只读 `network`);可分别按平台或版位汇总后给减投建议。
136
- 3. **地域**:高消耗国家转化差 → 收窄/geo 排除。
137
- 4. **受众**:低效 age×gender → 收窄定向。
138
- 5. **创意**:关停高消耗低 `results` 的 ad;复制 winner 的 `creativeType`/文案结构。
139
- 6. **频次**:`frequency` 过高 + 转化下滑 → 扩受众或换创意。
140
- 7. **无法做的 Google 项**:按日趋势、关键词、质量分等 — 一句说明「接口未提供」,不编造。
174
+ `executiveSummary`(3~5 段)、`healthDiagnosis`(四问+红绿灯)、`sections.*.insight`(各 ≥200 字)、`abTests`(≥3)、`actionChecklist` rules 文档 §四。
141
175
 
142
176
  ---
143
177
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 对齐 Aiagent-Server `agent/tso_agent`:`getWebsiteDiagnosisData`(`website_diagnosis_tools.py` + `data/website_guide.py`)。
4
4
  > **CLI 负责拉数**;**6 模块 × 29 子项评分**由 Agent 按规则 + 采集数据生成 JSON。
5
- > **最终交付**:与线上一致,为**一份可浏览器打开、含 ECharts 图表的单文件 HTML 报告**(雷达图、模块得分条形图、Lighthouse 对比图等)。TSO 网页由 Vue `WebsiteAnalysisReport/v3` 渲染;Skill/CLI 场景 **Agent 只写诊断 JSON,HTML 一律由 `website-diagnosis render` 生成**(禁止 Agent 手写 HTML)。
5
+ > **最终交付**:与线上一致,为**一份可浏览器打开、含 ECharts 图表的单文件 HTML 报告**(雷达图、模块得分条形图、Lighthouse 对比图等)。**用户未指定格式时默认交付 HTML**;TSO 网页由 Vue `WebsiteAnalysisReport/v3` 渲染;Skill/CLI 场景 **Agent 只写诊断 JSON,HTML 一律由 `website-diagnosis render` 生成**(禁止 Agent 手写 HTML,禁止仅 Markdown/JSON 充当终稿)。
6
6
 
7
7
  ---
8
8
 
@@ -111,7 +111,7 @@
111
111
 
112
112
  **例外**(不反问):
113
113
 
114
- - `list-accounts` 全量:用 `--json-out`,注意翻页;**默认无 `--detail` 时 JSON 不含余额/消耗字段**;要看列表内真实值须加 `--detail` 或另跑 `balance`/`stats`
114
+ - `list-accounts` 列全部 / 数个数:一次 `list-accounts -m <媒体> --page-size 999 --json-out <dir>`,脚本读落盘 `list-accounts-*.json` 的 `total` / `items[]`;**禁止**默认 page-size 20 再翻页;**禁止**对 stdout 摘要解析 `total`/`items`(见 `accounts/accounts.md` § Agent 意图速查);**默认无 `--detail` 时 JSON 不含余额/消耗**;要看余额/消耗加 `--detail` 或另跑 `balance`/`stats`
115
115
  - 「昨天」单日 stats:默认 `Asia/Shanghai` 日历日;先 `list-accounts` 再 `stats`
116
116
  - 仅持有 `entityId`:先 `list-accounts` 解出 `mediaCustomerId`,**禁止**把 `entityId` 传给 `stats -a` / `balance -a`
117
117
  - `forewarning records`、`invoice list`「本月」、TikTok `clue`「最近一周」:见对应 references
@@ -51,7 +51,7 @@
51
51
  - [ ] **无**整章空白(除非该章标注 `[ 数据不可用:… ]`)
52
52
  - [ ] 执行摘要 / 概览:有消耗、展示、点击等**至少一项非空数字**(或明确写无数据)
53
53
  - [ ] 周期报告默认维(P4):概览、日趋势、系列、设备、地域、关键词等**均有对应段落**(Meta 无接口的维度按模板写「未提供」)
54
- - [ ] 优化建议:独立一节,**不是**只有表格没有文字
54
+ - [ ] 优化建议:独立一节,**不是**只有表格没有文字(Meta:**4 条 + 7 维补充**,每条引用当次数字,见 `meta-period-report-rules.md`)
55
55
  - [ ] Google 诊断:每模块除表格外有「分析」+「建议」(见 `google-ads-diagnosis.md`)
56
56
 
57
57
  **不通过** → 补拉 CLI 维度、重跑生成逻辑、**重写产物**后再 Read 审阅。
@@ -93,8 +93,9 @@
93
93
  | -------- | ---------- |
94
94
  | P1 | 画像是否含 stats + 系列要点;币种 |
95
95
  | P4 | `google-period-report.md` 8 块是否齐 |
96
- | P4-FB | 无接口维度是否写「未提供」 |
96
+ | P4-FB | 对照 `meta-period-report-rules.md`:**4 条建议各 ≥150 字** + **7 维补充建议**;HTML 须无「待 Agent 撰写」占位,含执行摘要/四问/红绿灯/优化建议节;Excel:总数据叙事 4 块非空话 |
97
97
  | P6 / P7 | 按各自 `report-templates/*.md` Sheet/章节表逐项 |
98
+ | P8 | **HTML 终稿**(非 Markdown):`website-diagnosis-report.md` 六模块章节齐全;雷达图/得分环/条形图/Lighthouse 由 `render` 注入;Lighthouse 缺失时 callout 已说明 |
98
99
 
99
100
  ---
100
101
 
@@ -8,11 +8,11 @@
8
8
  | P2 | 多账户余额扫描 | `accounts/accounts.md`(`balance-scan`)、`accounts/currency.md` |
9
9
  | P3 | 多账户投放画像汇总 | `accounts/accounts.md` § accounts-digest、`accounts/currency.md`、`core/tips.md` |
10
10
  | P4 | Google 账户周期报告 | `report-templates/google-period-report.md`、`analytics/account-analytics.md`、`core/tips.md`、`core/deliverable-preflight.md` |
11
- | P4-FB | Meta/Facebook 周期报告 | `report-templates/meta-period-report.md`、`analytics/facebook-analysis-guide.md`、`analytics/account-analytics.md`、`core/tips.md` |
11
+ | P4-FB | Meta/Facebook 周期报告 | `report-templates/meta-period-report.md`、`assets/meta-period-report-rules.md`、`analytics/facebook-analysis-guide.md`、`core/deliverable-preflight.md` |
12
12
  | P5 | 多账户多维度报告 | `analytics/google-analysis-batch.md`、`analytics/account-analytics.md`、`core/tips.md`;可选 `core/subagent-orchestration.md` |
13
13
  | P6 | OKKI 周报 | `report-templates/okki-weekly-google-client.md`(全文)、`analytics/account-analytics.md`、`core/tips.md`;可选 `core/subagent-orchestration.md` |
14
14
  | P7 | Google 询盘分析 | `report-templates/google-inquiry-analysis.md`(全文)、`analytics/account-analytics.md`、`core/tips.md`、`analytics/geo-continents.json`;可选 `core/subagent-orchestration.md` |
15
- | P8 | 网站诊断 | `analytics/website-diagnosis-guide.md`、`assets/website-diagnosis-rules.md`、`report-templates/website-diagnosis-report.md`、`core/tips.md` |
15
+ | P8 | 网站诊断 | `analytics/website-diagnosis-guide.md`、`assets/website-diagnosis-rules.md`、`report-templates/website-diagnosis-report.md`、`core/tips.md`、`core/deliverable-preflight.md` |
16
16
  | P9 | 战略市场分析 | `analytics/market-analysis-guide.md`、`assets/market-analysis-rules.md`、`report-templates/market-analysis-report.md`、`core/tips.md` |
17
17
 
18
18
  ---
@@ -74,18 +74,23 @@ siluzan-tso accounts-digest -m Google -a id1,id2,... --start <S> --end <D> --jso
74
74
 
75
75
  ## P4-FB · Meta/Facebook 账户周期报告
76
76
 
77
- 1. `list-accounts -m MetaAd -k <mediaCustomerId> --json-out ./snap-fb` 确认账户。
77
+ > **默认交付 HTML**(`facebook-analysis render`)。用户**明确要求 Excel** 时改走 `meta-period-report-excel.md`(Agent 脚本写 xlsx,无 CLI excel 子命令)。
78
+
79
+ 1. `list-accounts -m MetaAd -k <mediaCustomerId> --json-out ./snap-fb` 确认账户与 `currencyCode`。
78
80
  2. 确认 `--start` / `--end`(>3 个月可分段,与 P4 相同)。
79
- 3. **一次批拉**(默认 6 维,对齐 Google 周期主章节):
81
+ 3. **步骤 1 · 拉数**(默认 5 维;用户要创意时加 `creative`):
80
82
 
81
83
  ```bash
82
84
  siluzan-tso facebook-analysis -a <id> --start <S> --end <D> --json-out ./snap-fb \
83
- --sections overview,ad-sets,platform,country,audience,creative
85
+ --sections overview,ad-sets,platform,country,audience
84
86
  ```
85
87
 
86
- 4. `report-templates/meta-period-report.md` 撰写;字段与 Google 对照见 `analytics/facebook-analysis-guide.md`。
87
- 5. 无按日趋势/关键词/质量分等:对应章节写「接口未提供」,**禁止编造**。
88
- 6. 用户要素材 Tab 时追加 `--sections material`(或全量省略 `--sections`)。
88
+ 4. **步骤 2 · 分析**:脚本读落盘 JSON,聚合指标与洞察(见 `analytics/facebook-analysis-guide.md`)。
89
+ 5. **步骤 3 · 写 JSON**:Read **`assets/meta-period-report-rules.md`**;先 outline 后落盘 `meta-period-report.json`(`narrative` 4 条建议各 ≥150 字 + `supplementaryRecommendations` 7 维 + HTML 必填扩展字段);无按日/关键词等写「接口未提供」,**禁止编造**。
90
+ 6. **步骤 4 · 交付**:
91
+ - **默认(HTML)**:`facebook-analysis render --data ./meta-period-report.json --snapshot-dir ./snap-fb --out ./meta-period-report.html`
92
+ - **用户要 Excel**:Agent 脚本按 `meta-period-report-excel.md` 写 `.xlsx`(步骤 1~3 不变;**不**默认调用 `render`)
93
+ 7. 交付前:**Read 最终 HTML 或 xlsx**,对照 `deliverable-preflight.md` 自检。
89
94
 
90
95
  诊断场景改用 `report-templates/meta-account-diagnosis-report.md`,拉数可省略 `--sections` 拉全 7 维。
91
96
 
@@ -175,7 +180,8 @@ siluzan-tso accounts-digest -m Google -a id1,id2,... --start <S> --end <D> --jso
175
180
 
176
181
  ## P8 · 网站诊断
177
182
 
178
- > **触发**:用户要对某 URL 做网站/落地页诊断、投放前网站评分,或话术含「网站诊断」「落地页质量」(**非** Google 账户 `AdvertisingDiagnosis`)。
183
+ > **触发**:用户要对某 URL 做网站/落地页诊断、投放前网站评分,或话术含「网站诊断」「落地页质量」(**非** Google 账户 `AdvertisingDiagnosis`)。
184
+ > **默认交付格式**:**HTML**(`website-diagnosis render` → `website-diagnosis-report.html`)。用户未指定格式时一律交付 HTML;**禁止**仅 Markdown 摘要或纯 JSON 充当终稿。
179
185
 
180
186
  1. 确认完整 URL(`https://` 可省略,CLI 自动补全)。
181
187
  2. 采集原料(**必须** `--json-out`):
@@ -26,6 +26,7 @@
26
26
  每条 `--json-out` 命令成功后,**必须**按以下顺序处理,不要跳步、不要把 outline 当数据:
27
27
 
28
28
  1. **解析 stdout 一行摘要 JSON**(禁止 Read 打开 `writtenFiles[0]` 的 `.json`):拿到 `outlineFile`、`writtenFiles[0]`、`manifestFile`、`agentHint`。**不要硬编码 `<section>.json` 文件名**。
29
+ - **反例(常见踩坑)**:摘要里**没有** `total`、`items`、`page` 等业务字段;`JSON.parse(stdout)` 后取 `result.total` 会得到 `undefined`。**禁止**用 stdout 写翻页循环;`total` / `items` 只存在于 `writtenFiles[0]` 落盘文件(如 `list-accounts-google.json`)。
29
30
  2. **了解字段结构**(二选一,推荐 A):
30
31
  - **A**:宿主 **Read** 仅 `outlineFile`(`*.outline.txt`,体积小);或
31
32
  - **B**:`node -e "const fs=require('fs'); const o=fs.readFileSync(process.argv[1],'utf8').trimEnd().split('\\n').filter(l=>!l.startsWith('//')); console.log(o.pop())" <outlineFile>`
@@ -320,8 +321,9 @@ console.log('可用字段:', first && Object.keys(first));
320
321
 
321
322
  ## 通用分页与查询建议
322
323
 
323
- - 绝大多数列表类命令默认每页 20 条记录,数据量较大时建议显式指定分页参数。
324
- - 建议在拉取大批量数据时使用命令自带的 `--page-size`(如设置为 `100`)与 `--page` 组合翻页,确认无更多数据后再停止,避免遗漏。
324
+ - 绝大多数列表类命令默认每页 20 条记录,数据量较大时须显式指定 `--page-size`。
325
+ - **`list-accounts` 列全部 / 数个数**:优先 **`--page-size 999` 一次拉取** + `--json-out` + 脚本读盘(见 `accounts/accounts.md` § Agent 意图速查);**不要**先试默认 20 再翻页。
326
+ - 其他列表命令(报告列表、发票列表等)在单页拉不满时,再用 `--page-size`(如 `100`)与 `--page` 组合翻页;读盘确认 `total > itemCount` 后再补下一页。
325
327
 
326
328
  ---
327
329
 
@@ -550,8 +550,11 @@ siluzan-tso report delete --ids <id1>,<id2>
550
550
  1. 确认账户 ID(`list-accounts`)与日期区间。
551
551
  2. 选定对应媒体的 `report-templates/*.md`(Google 周期分析默认 `google-period-report.md`;用户说 **「使用 okki 周报模板」「OKKI 周报」** 等 → **`okki-weekly-google-client.md`**,见 SKILL **P6**)。
552
552
  3. 按该 `*.md` 的**默认维度**直接拉数;**若为 OKKI 周报模板则固定维度、不追问追加**;否则向用户发消息,展示**可选追加维度**列表(见该 `*.md`),询问是否追加。
553
- 4. 用默认维度数据撰写报告;用户追加的维度数据到位后,补充在末尾。
554
- 5. 可选:按 `report-template*.html` 选择 HTML 样式输出(未指定时默认 `report-template.html`)。
553
+ 4. 用脚本分析落盘 JSON,撰写报告中间产物(Google:直接写 HTML/Markdown;**Meta/Facebook**:写 `meta-period-report.json`)。
554
+ 5. **交付格式**:
555
+ - **Meta/Facebook 周期报告(默认)**:`facebook-analysis render` → HTML(见 `meta-period-report.md` 四步流程);用户指定 Excel 时 Agent 脚本写 xlsx,见 `meta-period-report-excel.md`。
556
+ - **Google 等**:按 `report-template*.html` 选择样式(未指定时默认 `report-template.html`)。
557
+ 6. 用户追加的维度数据到位后,更新 JSON/报告并重新渲染(Meta)或补充章节(Google)。
555
558
 
556
559
  ---
557
560
 
@@ -781,17 +784,31 @@ siluzan-tso balance -m Google -a <mediaCustomerId>
781
784
 
782
785
  广告投放前需评估落地页质量:页面访问速度、产品描述完整性、转化代码部署、移动端适配等。系统通过 Lighthouse + AI 分析给出评分和优化建议,判断该页面是否适合直接投放广告。
783
786
 
784
- ### Agent 操作流程
787
+ ### Agent 操作流程(P8 · 默认交付 HTML)
785
788
 
786
- **网站诊断**(需在网页完成):
789
+ **网站诊断**(CLI + Skill,**默认产出 HTML 终稿**):
787
790
 
788
791
  ```bash
789
- # 引导用户打开网站诊断页面(在 AICreation 流程中内嵌,或直接访问)
790
- siluzan-tso config show # webUrl
792
+ # 1. 采集 Lighthouse + 首页 HTML
793
+ siluzan-tso website-diagnosis collect --url <url> --json-out ./snap-web
794
+
795
+ # 2. Agent 按 website-diagnosis-rules.md 生成 diagnosis.json(脚本落盘)
796
+
797
+ # 3. 生成带图表的 HTML 报告(用户未指定格式时必做)
798
+ siluzan-tso website-diagnosis render \
799
+ --data ./diagnosis.json \
800
+ --collect ./snap-web/<collect>.json \
801
+ --out ./snap-web/website-diagnosis-report.html
802
+ ```
791
803
 
792
- # 诊断入口(网页 AICreation 向导内嵌):
804
+ 向用户交付 `website-diagnosis-report.html` 路径;**禁止**仅交付 Markdown 或 JSON。详见 `references/core/playbooks.md` P8、`references/analytics/website-diagnosis-guide.md`。
805
+
806
+ **TSO 网页内嵌诊断**(Copilot / AICreation 向导,可选):
807
+
808
+ ```bash
809
+ siluzan-tso config show # 取 webUrl
793
810
  # https://www-ci.siluzan.com/v3/foreign_trade/tso/advertising/AICreation
794
- # → 输入推广链接时,系统会自动触发网站诊断
811
+ # → 输入推广链接时,系统会自动触发网站诊断并渲染 Vue 全页 HTML
795
812
  ```
796
813
 
797
814
  **CLI 辅助**(诊断前后核对账户授权):
@@ -18,8 +18,8 @@
18
18
  | `google-period-report.md` | Google 账户分析报告(周期/月度/诊断均用此模板) |
19
19
  | `google-account-diagnosis-report.md` | Google 账户深度诊断(健康度/转化/结构等) |
20
20
  | `google-ads-diagnosis.md` | Google **广告诊断**完整纲要(HTML 区块、**每日趋势 2 位小数**、**每模块必填分析/建议**) |
21
- | `meta-period-report.md` / `.html` | **Meta(Facebook)周期报告**:终稿 HTML;配合 `facebook-analysis render`,见 P4-FB |
22
- | `meta-period-report-excel.md` | **Excel Sheet 业务模板规格**(总数据叙事 + 4 维表;内容基准) |
21
+ | `meta-period-report.md` / `.html` | **Meta(Facebook)周期报告(默认)**:四步流程 `facebook-analysis render` 出 HTML,见 P4-FB |
22
+ | `meta-period-report-excel.md` | **仅用户要 Excel 时**:5 Sheet xlsx 版式;Agent 脚本写表,无 CLI excel 子命令 |
23
23
  | `meta-account-diagnosis-report.md` | Meta(Facebook)诊断报告(在 7 Section 内对齐 Google 诊断结构) |
24
24
  | `tiktok-period-report.md` | TikTok 广告主周期报告 |
25
25
  | `bing-period-report.md` | Bing(BingV2)分析报告 |
@@ -59,12 +59,22 @@
59
59
 
60
60
  ---
61
61
 
62
- ### 步骤 5:撰写报告
62
+ ### 步骤 5:分析并撰写中间产物
63
63
 
64
- - `*.md` 章节结构组织内容。
65
- - 所有数字可追溯到具体命令的 JSON 输出字段。
66
- - 最后写**优化建议**(基于已有数据,不额外拉数)。
67
- - 可选:按 `report-template*.html` 选择 HTML 样式输出(未指定时默认 `report-template.html`)。
64
+ - **node/python 脚本**读落盘 JSON,完成聚合与洞察(禁止 Read 业务 JSON、禁止对话手填数)。
65
+ - `*.md` 章节结构组织叙事与建议;所有数字可追溯到 JSON 字段。
66
+ - **Meta/Facebook**:产出 `meta-period-report.json`(见 `meta-period-report.md`)。
67
+ - **Google 等**:可直接组织 Markdown/HTML 正文。
68
+
69
+ ### 步骤 5b:生成终稿(按媒体与格式)
70
+
71
+ | 媒体 | 用户未指定格式 | 用户指定 Excel |
72
+ | ---- | -------------- | -------------- |
73
+ | **Meta/Facebook** | `facebook-analysis render` → **HTML**(必做) | Agent 脚本按 `meta-period-report-excel.md` 写 xlsx;**不**默认 `render` |
74
+ | **Google** | 按 `report-template*.html` 写 HTML(默认 `report-template.html`) | OKKI / 询盘等见各自 `*.md` |
75
+ | **网站诊断** | `website-diagnosis render` → HTML | — |
76
+
77
+ **禁止**:Meta 周期报告默认只交 Markdown/JSON;禁止 Agent 手写 Meta HTML。
68
78
 
69
79
  **Google 广告诊断报告**(`google-ads-diagnosis.md` / `google-account-diagnosis-report.md`)额外必遵:
70
80
 
@@ -1,7 +1,10 @@
1
1
  # Meta(Facebook)周期报告 — Excel 模板规格
2
2
 
3
+ > **适用场景**:用户**明确要求 Excel / xlsx** 交付时读本文件。
4
+ > 用户未指定格式时,**默认交付 HTML**,走 `meta-period-report.md` 标准四步(拉数 → 分析 → 写 JSON → `facebook-analysis render`),**不要**默认走 Excel。
5
+
3
6
  > 对照业务交付物:`无锡顺晟Facebook4月报告.xlsx`(5 个 Sheet)。
4
- > CLI 拉数 → Agent 按本规格写 `meta-period-report.json` → `facebook-analysis render` HTML。
7
+ > Excel 流程:CLI 拉数 → Agent 分析并写 `meta-period-report.json` → **Agent 脚本**按本规格写 `.xlsx`(**无** CLI 内置 excel 子命令)。
5
8
 
6
9
  ---
7
10
 
@@ -84,14 +87,21 @@ Excel 导出列与 API 字段对照(撰写/渲染时统一用 API camelCase,
84
87
  - **1 段话**对比 Top 国家:最低 CPL 国家、最高 CPL 国家、中间梯队。
85
88
  - 数据依据:`country-<id>.json` → `countries[]`(按 `costPerResult` 或 `spend` 排序)。
86
89
 
87
- ### 4. 优化建议(固定 4 条)
90
+ ### 4. 优化建议(固定 4 条 + 7 维补充)
91
+
92
+ **每条 `content` ≥150 字**,须引用当次国家名/CPL/广告组名;严重项以「强烈建议:」开头。完整规则见 **`assets/meta-period-report-rules.md`**。
88
93
 
89
94
  | # | 标题 | 撰写要点 |
90
95
  | - | ---- | -------- |
91
- | 1 | **简化表单问题** | 结合高频次低转化市场,建议表单字段缩减(姓名+联系方式+需求类型) |
92
- | 2 | **区域调整** | 按广告组写语言/市场策略(如土耳其语、葡萄牙语、德语三套) |
93
- | 3 | **预算重构** | 组间预算比例(如 4:3:3)、测试周期(7 天)、优胜劣汰规则 |
94
- | 4 | **素材建议** | 素材轮播数量、IG 短视频时长、FB 是否换形态、分市场卖点差异 |
96
+ | 1 | **简化表单问题** | 点名高频次高 CPL 国家/组;字段缩减至 3 项;写预期 CPL 改善 |
97
+ | 2 | **区域调整** | 按广告组写语言/市场策略;写清加谁、减谁、暂停谁 |
98
+ | 3 | **预算重构** | 具体比例(如 4:3:3)、测试 7/14 天、CPL 阈值优胜劣汰 |
99
+ | 4 | **素材建议** | IG/FB、分市场;素材套数、视频时长、高花费低结果创意处理 |
100
+
101
+ **Excel 总数据 Sheet 另须**(可写在 4 条之后或单独小节):
102
+
103
+ - `supplementaryRecommendations` 7 维表(预算/平台/地域/受众/创意/频次/接口限制)
104
+ - `priorityPlan` 高/中/低各 ≥2 条(推荐)
95
105
 
96
106
  ---
97
107
 
@@ -140,12 +150,16 @@ siluzan-tso facebook-analysis -a <mediaCustomerId> \
140
150
  ],
141
151
  "country": "土耳其单条9.45美元,远低于其他国家…",
142
152
  "recommendations": [
143
- { "title": "简化表单问题", "content": "" },
144
- { "title": "区域调整", "content": "" },
153
+ { "title": "简化表单问题", "content": "强烈建议:…(≥150字,含国家/CPL数字)" },
154
+ { "title": "区域调整", "content": "推荐优化:…" },
145
155
  { "title": "预算重构", "content": "…" },
146
156
  { "title": "素材建议", "content": "…" }
147
157
  ]
148
158
  },
159
+ "supplementaryRecommendations": [
160
+ { "dimension": "预算与广告组", "issue": "…", "suggestion": "…" }
161
+ ],
162
+ "priorityPlan": { "high": ["…"], "medium": ["…"], "low": ["…"] },
149
163
  // 对应 Sheet2~5 表格 + 图表:可省略,由 --snapshot-dir 自动合并
150
164
  "tables": {
151
165
  "adSets": [/* 见 merge-snapshot */],
@@ -184,7 +198,9 @@ siluzan-tso facebook-analysis -a <mediaCustomerId> \
184
198
 
185
199
  ---
186
200
 
187
- ## 渲染命令
201
+ ## HTML 渲染(可选 · 非 Excel 默认路径)
202
+
203
+ 用户**同时要 HTML** 或**未要 Excel、走默认流程**时,在写完 `meta-period-report.json` 后执行:
188
204
 
189
205
  ```bash
190
206
  siluzan-tso facebook-analysis render \
@@ -193,6 +209,8 @@ siluzan-tso facebook-analysis render \
193
209
  --out ./meta-period-report.html
194
210
  ```
195
211
 
212
+ **仅交付 Excel** 时可跳过本节。
213
+
196
214
  ---
197
215
 
198
216
  ## 相关文档
@@ -128,6 +128,104 @@ tr:hover td{background:rgba(255,255,255,.03)}
128
128
  return items.map((p) => `<p>${escapeHtml(p)}</p>`).join("");
129
129
  }
130
130
 
131
+ function summaryParagraphs(data) {
132
+ const exec = data.executiveSummary;
133
+ if (Array.isArray(exec) && exec.length > 0) return exec;
134
+ const overall = data.narrative?.overall;
135
+ if (typeof overall === "string" && overall.trim()) {
136
+ const parts = overall.split(/(?<=[。!?])\s*/).filter((s) => s.trim());
137
+ return parts.length > 1 ? parts : [overall];
138
+ }
139
+ return [];
140
+ }
141
+
142
+ function renderNarrativePerformance(narrative) {
143
+ if (!narrative) return "";
144
+ const overall = narrative.overall
145
+ ? `<div class="card"><h3 style="margin-top:0">整体表现</h3><p>${escapeHtml(narrative.overall)}</p></div>`
146
+ : "";
147
+ const regional = (narrative.regional || [])
148
+ .map(
149
+ (r) => `
150
+ <div class="card">
151
+ <h3 style="margin-top:0">${escapeHtml(r.adGroupName || r.campaignName || "广告组")}</h3>
152
+ <p>${escapeHtml(r.text || "")}</p>
153
+ </div>`,
154
+ )
155
+ .join("");
156
+ const country = narrative.country
157
+ ? `<div class="card"><h3 style="margin-top:0">国家 / 市场对比</h3><p>${escapeHtml(narrative.country)}</p></div>`
158
+ : "";
159
+ if (!overall && !regional && !country) return "";
160
+ return `
161
+ <section>
162
+ <h2>账户表现解读(数据叙事)</h2>
163
+ ${overall}${regional}${country}
164
+ </section>`;
165
+ }
166
+
167
+ function renderRecommendationsBlock(data) {
168
+ const recs = data.narrative?.recommendations || [];
169
+ const extra = data.supplementaryRecommendations || [];
170
+ const plan = data.priorityPlan;
171
+ const recCards = recs
172
+ .map(
173
+ (r) => `
174
+ <div class="card" style="margin-bottom:12px">
175
+ <h3 style="margin-top:0;color:#93c5fd">${escapeHtml(r.title || "优化建议")}</h3>
176
+ <p>${escapeHtml(r.content || "")}</p>
177
+ </div>`,
178
+ )
179
+ .join("");
180
+ const extraRows = extra
181
+ .map(
182
+ (r) => `
183
+ <tr>
184
+ <td>${escapeHtml(r.dimension || "")}</td>
185
+ <td>${escapeHtml(r.issue || "")}</td>
186
+ <td>${escapeHtml(r.suggestion || "")}</td>
187
+ </tr>`,
188
+ )
189
+ .join("");
190
+ const planCol = (title, items, color) => `
191
+ <div class="card check-card" style="border-color:var(--${color})">
192
+ <h4>${escapeHtml(title)}</h4>
193
+ <ul>${(items || []).map((li) => `<li>${escapeHtml(li)}</li>`).join("") || '<li class="empty-note">(待补充)</li>'}</ul>
194
+ </div>`;
195
+ const planHtml = plan
196
+ ? `
197
+ <div class="checklist" style="margin-top:16px">
198
+ ${planCol("高优先级(本周必做)", plan.high, "red")}
199
+ ${planCol("中优先级(两周内)", plan.medium, "yellow")}
200
+ ${planCol("低优先级(持续优化)", plan.low, "green")}
201
+ </div>`
202
+ : "";
203
+ if (!recCards && !extraRows && !planHtml) {
204
+ return `
205
+ <section>
206
+ <h2>优化建议与行动计划</h2>
207
+ <div class="card"><p class="empty-note">(待 Agent 按 meta-period-report-rules.md 撰写 narrative.recommendations 与 supplementaryRecommendations)</p></div>
208
+ </section>`;
209
+ }
210
+ return `
211
+ <section>
212
+ <h2>优化建议与行动计划</h2>
213
+ ${recCards || '<div class="card"><p class="empty-note">(待撰写固定 4 条建议:简化表单 / 区域调整 / 预算重构 / 素材建议)</p></div>'}
214
+ ${
215
+ extraRows
216
+ ? `<div class="card" style="margin-top:16px">
217
+ <h3 style="margin-top:0">数据驱动补充建议(7 维清单)</h3>
218
+ <table>
219
+ <thead><tr><th>维度</th><th>发现</th><th>建议</th></tr></thead>
220
+ <tbody>${extraRows}</tbody>
221
+ </table>
222
+ </div>`
223
+ : ""
224
+ }
225
+ ${planHtml ? `<h3 style="margin-top:24px">优先级改进计划</h3>${planHtml}` : ""}
226
+ </section>`;
227
+ }
228
+
131
229
  function renderHero(meta, kpis) {
132
230
  const title = meta.accountName || meta.accountId || "Meta 广告账户";
133
231
  const period = meta.periodLabel || `${meta.startDate || ""} ~ ${meta.endDate || ""}`;
@@ -493,8 +591,10 @@ ${col("本月持续优化", checklist.thisMonth, "green")}
493
591
  ${renderHero(meta, kpis)}
494
592
  <section>
495
593
  <h2>执行摘要:数据背后的「为什么」</h2>
496
- <div class="card">${paragraphsHtml(data.executiveSummary)}</div>
594
+ <div class="card">${paragraphsHtml(summaryParagraphs(data))}</div>
497
595
  </section>
596
+ ${renderNarrativePerformance(data.narrative)}
597
+ ${renderRecommendationsBlock(data)}
498
598
  ${renderHealthDiagnosis(data.healthDiagnosis)}
499
599
  ${renderInsightBlock("平台策略:Facebook vs Instagram", sections.platform?.insight, "chartPlatform")}
500
600
  ${renderInsightBlock("国家 / 市场矩阵", sections.country?.insight, "chartCountry")}
@@ -3,13 +3,51 @@
3
3
  > 统计区间:`{startDate}` ~ `{endDate}`
4
4
  > 账户:`{mediaCustomerId}`(`{mediaCustomerName}`)
5
5
 
6
- > **最终交付物:一份可打开的、带 Chart.js 图表的 HTML 文件**(如 `meta-period-report.html`),不是仅 Markdown 摘要。
7
- > **内容基准**:业务 Excel 模板(5 Sheet,见 `meta-period-report-excel.md`);HTML 可追加深度分析章节(健康诊断、A/B 实验等)。
8
- > 数据:`facebook-analysis --json-out` 落盘 JSON + Agent 按本纲要生成的 `meta-period-report.json`。
6
+ > **默认交付物**:一份可打开的、带 Chart.js 图表的 **HTML 文件**(如 `meta-period-report.html`)。
7
+ > 用户**未指定格式**时一律走下方 **标准四步流程**;**禁止**仅 Markdown 摘要或纯 JSON 充当终稿。
8
+ > 用户**明确要求 Excel / xlsx** 时,改走 `report-templates/meta-period-report-excel.md` 分支(见文末「Excel 分支」)。
9
9
 
10
- `google-period-report.md` 同级流程:先拉数、再按章节撰写。字段口径见 `references/analytics/facebook-analysis-guide.md`。
10
+ 字段口径见 `references/analytics/facebook-analysis-guide.md`。
11
+ **内容丰富度(必读)**:`assets/meta-period-report-rules.md`(对齐 P8 网站诊断:全量建议 + 字数下限 + 7 维清单)。
12
+ Agent JSON Schema:`assets/meta-period-report.schema.json`。
11
13
 
12
- **Excel 模板对照(必读)**:`report-templates/meta-period-report-excel.md` — 定义 5 个 Sheet、统一数据列、总数据叙事 4 块 + 优化建议 4 条。JSON Schema:`assets/meta-period-report.schema.json`。
14
+ ---
15
+
16
+ ## 标准四步流程(默认 · 交付 HTML)
17
+
18
+ | 步骤 | 执行者 | 动作 |
19
+ | ---- | ------ | ---- |
20
+ | **1. 拉数** | Agent 调 CLI | `facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb` |
21
+ | **2. 分析** | Agent | 用 **node/python 脚本**读落盘 JSON(勿用 Read 打开业务 `*.json`),完成筛选、聚合、排序与洞察 |
22
+ | **3. 写 JSON** | Agent | 按本纲要撰写 `meta-period-report.json`(`meta` / `narrative` / 可选 HTML 扩展字段) |
23
+ | **4. 渲染 HTML** | CLI | `facebook-analysis render` — **禁止** Agent 手写/拼接 HTML |
24
+
25
+ ```bash
26
+ # 步骤 1
27
+ siluzan-tso facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb \
28
+ --sections overview,ad-sets,platform,country,audience
29
+
30
+ # 步骤 4(步骤 2~3 完成后)
31
+ siluzan-tso facebook-analysis render \
32
+ --data ./meta-period-report.json \
33
+ --snapshot-dir ./snap-fb \
34
+ --out ./meta-period-report.html
35
+ ```
36
+
37
+ `--snapshot-dir` 与步骤 1 的 `--json-out` 同目录;CLI 自动合并 KPI、平台/国家/受众图表与表格(Agent JSON 已有字段不覆盖)。
38
+
39
+ ---
40
+
41
+ ## Excel 分支(仅当用户指定 Excel / xlsx)
42
+
43
+ 用户说「要 Excel」「导出 xlsx」「按业务 Excel 模板」等时:
44
+
45
+ 1. 步骤 1~3 **与 HTML 流程相同**(拉数 → 分析 → 写 `meta-period-report.json`)。
46
+ 2. **步骤 4 改为**:Agent 执行 **node/python 脚本**(如 `openpyxl` / `exceljs`)读取快照 JSON + `meta-period-report.json`,按 `meta-period-report-excel.md` 写出 `.xlsx`。
47
+ 3. **不要**调用 `facebook-analysis render`(除非用户同时要 HTML + Excel)。
48
+ 4. **禁止**假设存在 `siluzan-tso … excel` 子命令。
49
+
50
+ 版式与 5 Sheet 结构见 **`report-templates/meta-period-report-excel.md`**。
13
51
 
14
52
  ---
15
53
 
@@ -17,13 +55,10 @@
17
55
 
18
56
  | 环节 | 实现 |
19
57
  | ---- | ---- |
20
- | CLI 拉数 | `facebook-analysis -a <id> --start <s> --end <e> --json-out ./snap-fb` |
21
- | Agent 撰写 | 读各 section JSON,产出 `meta-period-report.json`(叙事 + 可选结构化字段) |
22
- | **完整报告** | **Agent 只写 JSON**;终稿 HTML **必须**由 CLI 生成,**禁止** Agent 现场手写/拼接 HTML |
23
-
24
- ```bash
25
- siluzan-tso facebook-analysis render --data ./meta-period-report.json --snapshot-dir ./snap-fb --out ./meta-period-report.html
26
- ```
58
+ | CLI 拉数 | 步骤 1 |
59
+ | Agent 分析 + 撰写 | 步骤 2~3 `meta-period-report.json` |
60
+ | **HTML 终稿** | 步骤 4 `facebook-analysis render` |
61
+ | **Excel 终稿** | 仅用户指定时 → Agent 脚本写 xlsx |
27
62
 
28
63
  模板源码:
29
64
  - `report-templates/meta-period-report.html` — 结构与样式(对齐深度分析月报)
@@ -98,14 +133,18 @@ siluzan-tso facebook-analysis -a <mediaCustomerId> --start <s> --end <e> --json-
98
133
  - 数据源:`country-<id>.json` → `countries[]`。
99
134
  - **1 段话**:最低/最高 CPL 国家、中间梯队;表格按花费或 CPL 排序展示。
100
135
 
101
- ### 4. 优化建议(`narrative.recommendations[]`,固定 4 条)
136
+ ### 4. 优化建议(`narrative.recommendations[]` + `supplementaryRecommendations` + `priorityPlan`)
137
+
138
+ **固定 4 条标题**(`narrative.recommendations[]`,每条 content **≥150 字**,须引用当次 CPL/国家/组名):
102
139
 
103
140
  | 标题 | 内容要点 |
104
141
  | ---- | -------- |
105
- | 简化表单问题 | 字段过多导致放弃提交;建议 3 字段 |
106
- | 区域调整 | 各广告组语言/市场策略(土/葡/德等) |
107
- | 预算重构 | 组间比例(如 4:3:3)、测试 7 天、按 CPL 优胜劣汰 |
108
- | 素材建议 | 素材套数、IG 短视频、FB 形态、分市场卖点 |
142
+ | 简化表单问题 | 结合高频次高 CPL 市场;字段缩减至 3 项;写预期影响 |
143
+ | 区域调整 | 各广告组语言/市场策略(土/葡/德等);加减仓名单 |
144
+ | 预算重构 | 具体比例(如 4:3:3)、测试周期、CPL 阈值优胜劣汰 |
145
+ | 素材建议 | 分平台/分市场;素材套数、IG 短视频、FB 形态 |
146
+
147
+ **另须** `supplementaryRecommendations` **7 维**(预算、平台、地域、受众、创意、频次、接口限制)与 `priorityPlan`(高/中/低各 ≥2 条)。细则见 **`assets/meta-period-report-rules.md`**。
109
148
 
110
149
  ### 5. 平台数据(Sheet3 表 + 可选 `sections.platform.insight`)
111
150
 
@@ -122,12 +161,16 @@ siluzan-tso facebook-analysis -a <mediaCustomerId> --start <s> --end <e> --json-
122
161
  - 仅当用户追加拉取 `creative` / `material`。
123
162
  - **勿**加总各行 `results` 与 overview 对比。
124
163
 
125
- ### HTML 深度分析扩展(Excel 不含,按需撰写)
164
+ ### HTML 深度分析扩展(**默认交付必填**,Excel 不含)
165
+
166
+ 用户未指定 Excel 时,除 `narrative` 外 **必须** 填写(字数见 `meta-period-report-rules.md` §四):
126
167
 
127
- - `executiveSummary[]`:多段「为什么」解读
128
- - `healthDiagnosis`:三阶段 / 四问 / 红绿灯表
129
- - `sections.*.insight`:各维度 200+ 字深度解读
130
- - `abTests`、`actionChecklist`、`sections.landingPage`
168
+ - `executiveSummary[]`:**3~5 段**「为什么」解读(每段 ≥80 字)
169
+ - `healthDiagnosis`:三阶段 + **4 张四问卡片** + **≥6 行**红绿灯表
170
+ - `sections.platform/country/adSets.insight`:各 **≥200 字**
171
+ - `sections.audience`:`goldenProfile` ≥3 条 + `antiProfile` ≥2 条
172
+ - `sections.landingPage.rows`:≥3 行
173
+ - `abTests`:≥3 个实验;`actionChecklist`:today/thisWeek/thisMonth 非空
131
174
 
132
175
  ---
133
176
 
@@ -153,12 +196,14 @@ siluzan-tso facebook-analysis -a <mediaCustomerId> --start <s> --end <e> --json-
153
196
  | **`narrative.overall`** | **Excel 必含** | 整体表现 1 段 |
154
197
  | **`narrative.regional[]`** | **Excel 必含** | `{ adGroupName, text }` 区域报告 |
155
198
  | **`narrative.country`** | **Excel 必含** | 国家对比 1 段 |
156
- | **`narrative.recommendations[]`** | **Excel 必含** | 固定 4 条:简化表单 / 区域调整 / 预算重构 / 素材建议 |
199
+ | **`narrative.recommendations[]`** | **必含** | 固定 4 条,每条 ≥150 |
200
+ | **`supplementaryRecommendations`** | **必含** | 7 维数据驱动建议 |
201
+ | **`priorityPlan`** | **推荐** | 高/中/低各 ≥2 条;HTML 强烈建议填写 |
157
202
  | `tables` / `charts` | 可省略 | Sheet2~5;由快照自动汇总 |
158
- | `executiveSummary` | HTML 扩展 | 多段深度摘要(可替代或补充 `narrative.overall`) |
159
- | `healthDiagnosis` | HTML 扩展 | 三阶段 / 四问 / 红绿灯表 |
160
- | `sections.*.insight` | HTML 扩展 | 各维度深度解读 |
161
- | `abTests` / `actionChecklist` | HTML 扩展 | 实验设计与行动清单 |
203
+ | `executiveSummary` | **HTML 必填** | 3~5 段深度摘要 |
204
+ | `healthDiagnosis` | **HTML 必填** | 四问 + 红绿灯表 |
205
+ | `sections.*.insight` | **HTML 必填** | 各维度 ≥200 字 |
206
+ | `abTests` / `actionChecklist` | **HTML 必填** | ≥3 实验 + 三列行动清单 |
162
207
 
163
208
  ---
164
209
 
@@ -9,7 +9,7 @@ $ErrorActionPreference = 'Stop'
9
9
  # -- Package info (injected at build time) ------------------------------------
10
10
  $PKG_NAME = 'siluzan-tso-cli'
11
11
  # PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
12
- $PKG_VERSION = '1.1.28-beta.1'
12
+ $PKG_VERSION = '1.1.28-beta.2'
13
13
  $CLI_BIN = 'siluzan-tso'
14
14
  $SKILL_LABEL = 'Siluzan TSO'
15
15
  $INSTALL_CMD = 'npm install -g siluzan-tso-cli@beta'
@@ -9,7 +9,7 @@ set -euo pipefail
9
9
  # -- Package info (injected at build time) ------------------------------------
10
10
  readonly PKG_NAME="siluzan-tso-cli"
11
11
  # PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
12
- readonly PKG_VERSION="1.1.28-beta.1"
12
+ readonly PKG_VERSION="1.1.28-beta.2"
13
13
  readonly CLI_BIN="siluzan-tso"
14
14
  readonly SKILL_LABEL="Siluzan TSO"
15
15
  readonly INSTALL_CMD="npm install -g siluzan-tso-cli@beta"
@@ -4,7 +4,7 @@
4
4
  "turns": [
5
5
  "帮我查一下我所有的 Google 广告账户,看看哪些是正常状态的。用 siluzan-tso,需要 JSON。"
6
6
  ],
7
- "judgeExpectation": "路径:应使用 `list-accounts -m Google`(建议 --json-out)获取账户列表,并结合返回中的状态字段解释「正常」含义;不得编造未在 CLI 输出中的账户。\n输出:可按状态分组或列表说明;stub 数据即可。",
7
+ "judgeExpectation": "路径:应使用 `list-accounts -m Google --page-size 999 --json-out` 一次拉全(禁止默认 page-size 20 后再多次翻页);脚本读落盘 JSON 的 total/items,并结合状态字段解释「正常」含义;不得编造未在 CLI 输出中的账户。\n输出:可按状态分组或列表说明;stub 数据即可。",
8
8
  "skillMapping": "references/accounts/accounts.md · list-accounts",
9
9
  "judgeReferencePaths": [
10
10
  "references/accounts/accounts.md"
@@ -18,6 +18,9 @@
18
18
  ],
19
19
  [
20
20
  "--json-out"
21
+ ],
22
+ [
23
+ "page-size"
21
24
  ]
22
25
  ]
23
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.1.28-beta.1",
3
+ "version": "1.1.28-beta.2",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",