@geoly-ai/social-hub-cli 0.3.19 → 0.3.21

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.
Files changed (50) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/accounts-list-offset.test.d.ts +2 -0
  3. package/dist/accounts-list-offset.test.d.ts.map +1 -0
  4. package/dist/accounts-list-offset.test.js +53 -0
  5. package/dist/accounts-list-offset.test.js.map +1 -0
  6. package/dist/cmd-manifest.json +4 -2
  7. package/dist/compliance-risk-list-offset.test.d.ts +2 -0
  8. package/dist/compliance-risk-list-offset.test.d.ts.map +1 -0
  9. package/dist/compliance-risk-list-offset.test.js +63 -0
  10. package/dist/compliance-risk-list-offset.test.js.map +1 -0
  11. package/dist/content-review.test.js +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +40 -4
  14. package/dist/index.js.map +1 -1
  15. package/dist/index.test.js +16 -0
  16. package/dist/index.test.js.map +1 -1
  17. package/dist/register-calendar-directives.d.ts +64 -0
  18. package/dist/register-calendar-directives.d.ts.map +1 -0
  19. package/dist/register-calendar-directives.js +135 -0
  20. package/dist/register-calendar-directives.js.map +1 -0
  21. package/dist/register-calendar-directives.test.d.ts +2 -0
  22. package/dist/register-calendar-directives.test.d.ts.map +1 -0
  23. package/dist/register-calendar-directives.test.js +127 -0
  24. package/dist/register-calendar-directives.test.js.map +1 -0
  25. package/dist/register-shared.d.ts.map +1 -1
  26. package/dist/register-shared.js +13 -2
  27. package/dist/register-shared.js.map +1 -1
  28. package/dist/register-shared.test.js +78 -0
  29. package/dist/register-shared.test.js.map +1 -1
  30. package/package.json +2 -2
  31. package/skills/README.md +23 -22
  32. package/skills/manifest.json +6 -1
  33. package/skills/reddit-content-rewrite/SKILL.md +29 -0
  34. package/skills/reddit-content-writing/SKILL.md +53 -4
  35. package/skills/reddit-delivery-check/SKILL.md +38 -6
  36. package/skills/reddit-matrix.lock.json +6 -6
  37. package/skills/reddit-phase-brief/SKILL.md +39 -4
  38. package/skills/reddit-phase-brief/references/phase4-brief-workflow.md +43 -3
  39. package/skills/reddit-strategy-shared/references/content-diversity-contract.md +7 -2
  40. package/skills/reddit-strategy-shared/references/content-review-gate.md +48 -1
  41. package/skills/reddit-strategy-shared/references/handoff-schemas.md +72 -2
  42. package/skills/reddit-strategy-shared/references/native-copy-profile.md +207 -0
  43. package/skills/reddit-strategy-shared/references/persona-card-contract.md +210 -0
  44. package/skills/reddit-strategy-shared/references/version-manifest.md +60 -0
  45. package/skills/reddit-subreddit-compliance/SKILL.md +28 -1
  46. package/skills/social-hub-calendar-directives/SKILL.md +548 -0
  47. package/skills/social-hub-calendar-jobs/SKILL.md +10 -0
  48. package/skills/social-hub-cli/SKILL.md +2 -0
  49. package/skills/social-hub-notifications/SKILL.md +7 -0
  50. package/skills/social-hub-publishing/SKILL.md +5 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,29 @@ All notable changes to `@geoly-ai/social-hub-cli` are documented in this file.
4
4
 
5
5
  Release workflow: `pnpm release:cli` → `pnpm publish:cli`.
6
6
 
7
+ ## [0.3.21] - 2026-08-21
8
+
9
+ ### Fixed
10
+
11
+ - risk-list 分页补 ORDER BY 与 --offset
12
+ - doctor 不再明文打印 API token(R11)
13
+ - SDK 请求管线收敛 —— 两条 CSV 导出命令首次可用(R8/R9)
14
+
15
+ ## [0.3.20] - 2026-08-18
16
+
17
+ ### Added
18
+
19
+ - 发布日历指令端到端接线(Block 5) + 封死 D1 旁路
20
+ - 发布日历指令的 SDK/CLI/skills 交付面(Block 6)
21
+
22
+ ### Changed
23
+
24
+ - response mock 的 rubricVersion 跟到 content-review.v5
25
+
26
+ ### Documentation
27
+
28
+ - 写作侧 matrix skill 对齐冻结契约(块 2d)+ 删掉 WeaklyVerified
29
+
7
30
  ## [0.3.19] - 2026-08-14
8
31
 
9
32
  ### Added
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=accounts-list-offset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts-list-offset.test.d.ts","sourceRoot":"","sources":["../src/accounts-list-offset.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * R9 回归:`accounts list` 的分页游标。
3
+ *
4
+ * `limit` 上限 200(contracts `paginationQuerySchema`),此前 CLI 只有 `-n/--limit`,
5
+ * 账号数超过 200 的 team 无法穷举 —— SDK 与服务端一直支持 `offset`,缺的只有 CLI 这一层。
6
+ * 只断言选项已注册挡不住「注册了但忘了转发/转成 NaN」,所以这里跑真实 handler,
7
+ * 断言 SDK 收到的是**数值** offset,且不传时不发 offset(保持服务端默认 0)。
8
+ */
9
+ import { beforeAll, afterEach, describe, expect, it, vi } from "vitest";
10
+ const listAccounts = vi.fn().mockResolvedValue({ items: [], total: 0 });
11
+ vi.mock("@geoly-ai/social-hub-sdk", () => ({
12
+ SocialHubClient: vi.fn(),
13
+ getSocialHubHealth: vi.fn(),
14
+ }));
15
+ vi.mock("./client.js", () => ({
16
+ requireClient: () => ({ listAccounts }),
17
+ resolveTeamId: (t) => t ?? "team-1",
18
+ getBaseUrl: () => "http://localhost",
19
+ }));
20
+ let program;
21
+ beforeAll(async () => {
22
+ program = (await import("./index.js")).program;
23
+ vi.spyOn(console, "log").mockImplementation(() => { });
24
+ }, 30000);
25
+ afterEach(() => {
26
+ listAccounts.mockClear();
27
+ });
28
+ describe("accounts list 分页", () => {
29
+ // 两次 parse 放在同一个用例里且「不传」在前:commander 会把上一次 parse 的
30
+ // option 值留在同一个 command 实例上,拆成两个用例会互相污染。
31
+ it("--offset 以数值透传给 SDK,不传时则不发送(沿用服务端默认 0)", async () => {
32
+ await program.parseAsync(["node", "social-hub", "accounts", "list"]);
33
+ expect(listAccounts).toHaveBeenCalledTimes(1);
34
+ expect(listAccounts.mock.calls[0]?.[1]?.offset).toBeUndefined();
35
+ await program.parseAsync([
36
+ "node",
37
+ "social-hub",
38
+ "accounts",
39
+ "list",
40
+ "--limit",
41
+ "200",
42
+ "--offset",
43
+ "400",
44
+ ]);
45
+ expect(listAccounts).toHaveBeenCalledTimes(2);
46
+ expect(listAccounts.mock.calls[1]?.[0]).toBe("team-1");
47
+ expect(listAccounts.mock.calls[1]?.[1]).toMatchObject({
48
+ limit: 200,
49
+ offset: 400,
50
+ });
51
+ });
52
+ });
53
+ //# sourceMappingURL=accounts-list-offset.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts-list-offset.test.js","sourceRoot":"","sources":["../src/accounts-list-offset.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAExE,MAAM,YAAY,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;AAExE,EAAE,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC;IACzC,eAAe,EAAE,EAAE,CAAC,EAAE,EAAE;IACxB,kBAAkB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC5B,CAAC,CAAC,CAAC;AAEJ,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5B,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;IACvC,aAAa,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,IAAI,QAAQ;IAC5C,UAAU,EAAE,GAAG,EAAE,CAAC,kBAAkB;CACrC,CAAC,CAAC,CAAC;AAEJ,IAAI,OAAwD,CAAC;AAE7D,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,OAAO,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;IAC/C,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACxD,CAAC,EAAE,KAAK,CAAC,CAAC;AAEV,SAAS,CAAC,GAAG,EAAE;IACb,YAAY,CAAC,SAAS,EAAE,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,mDAAmD;IACnD,yCAAyC;IACzC,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;QAEhE,MAAM,OAAO,CAAC,UAAU,CAAC;YACvB,MAAM;YACN,YAAY;YACZ,UAAU;YACV,MAAM;YACN,SAAS;YACT,KAAK;YACL,UAAU;YACV,KAAK;SACN,CAAC,CAAC;QACH,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACpD,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,GAAG;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
- "generatedAt": "2026-08-14T09:17:16.590Z",
3
- "cliVersion": "0.3.19",
2
+ "generatedAt": "2026-08-21T06:10:56.141Z",
3
+ "cliVersion": "0.3.21",
4
4
  "commands": [
5
5
  "accounts",
6
6
  "accounts brand-bindings",
@@ -111,6 +111,8 @@
111
111
  "calendar list",
112
112
  "calendar list-full",
113
113
  "calendar patch",
114
+ "calendar preflight",
115
+ "calendar set-delivery-mode",
114
116
  "campaigns",
115
117
  "campaigns accounts",
116
118
  "campaigns accounts assign",
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compliance-risk-list-offset.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compliance-risk-list-offset.test.d.ts","sourceRoot":"","sources":["../src/compliance-risk-list-offset.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * 回归:`compliance risk-list` 的分页游标。
3
+ *
4
+ * `limit` 上限 200(contracts `listAccountRiskProfilesQuerySchema`),此前 CLI 只有
5
+ * `-n/--limit`,风险画像超过 200 个的 team 无法穷举 —— 调用方拿到 200 条会以为
6
+ * 那就是全部(生产上某团队已有 125 个)。与 `accounts list --offset`(R9)同形。
7
+ *
8
+ * 只断言选项已注册挡不住「注册了但忘了转发/转成 NaN」,所以这里跑真实 handler,
9
+ * 断言 SDK 收到的是**数值** offset,且不传时不发 offset(保持服务端默认 0)。
10
+ */
11
+ import { beforeAll, afterEach, describe, expect, it, vi } from "vitest";
12
+ const listAccountRiskProfiles = vi
13
+ .fn()
14
+ .mockResolvedValue({ items: [], total: 0 });
15
+ vi.mock("@geoly-ai/social-hub-sdk", () => ({
16
+ SocialHubClient: vi.fn(),
17
+ getSocialHubHealth: vi.fn(),
18
+ }));
19
+ vi.mock("./client.js", () => ({
20
+ requireClient: () => ({ listAccountRiskProfiles }),
21
+ resolveTeamId: (t) => t ?? "team-1",
22
+ getBaseUrl: () => "http://localhost",
23
+ }));
24
+ let program;
25
+ beforeAll(async () => {
26
+ program = (await import("./index.js")).program;
27
+ vi.spyOn(console, "log").mockImplementation(() => { });
28
+ }, 30000);
29
+ afterEach(() => {
30
+ listAccountRiskProfiles.mockClear();
31
+ });
32
+ describe("compliance risk-list 分页", () => {
33
+ // 两次 parse 放在同一个用例里且「不传」在前:commander 会把上一次 parse 的
34
+ // option 值留在同一个 command 实例上,拆成两个用例会互相污染。
35
+ it("--offset 以数值透传给 SDK,不传时则不发送(沿用服务端默认 0)", async () => {
36
+ await program.parseAsync(["node", "social-hub", "compliance", "risk-list"]);
37
+ expect(listAccountRiskProfiles).toHaveBeenCalledTimes(1);
38
+ expect(listAccountRiskProfiles.mock.calls[0]?.[0]).toBe("team-1");
39
+ expect(listAccountRiskProfiles.mock.calls[0]?.[1]?.offset).toBeUndefined();
40
+ expect(listAccountRiskProfiles.mock.calls[0]?.[1]?.limit).toBe(100);
41
+ await program.parseAsync([
42
+ "node",
43
+ "social-hub",
44
+ "compliance",
45
+ "risk-list",
46
+ "--limit",
47
+ "200",
48
+ "--offset",
49
+ "400",
50
+ "--search",
51
+ "espresso",
52
+ ]);
53
+ expect(listAccountRiskProfiles).toHaveBeenCalledTimes(2);
54
+ expect(listAccountRiskProfiles.mock.calls[1]?.[1]).toMatchObject({
55
+ limit: 200,
56
+ offset: 400,
57
+ search: "espresso",
58
+ });
59
+ // 老的 number 位置参数已经换成对象;传成数字会让 offset/search 静默丢失。
60
+ expect(typeof listAccountRiskProfiles.mock.calls[1]?.[1]).toBe("object");
61
+ });
62
+ });
63
+ //# sourceMappingURL=compliance-risk-list-offset.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compliance-risk-list-offset.test.js","sourceRoot":"","sources":["../src/compliance-risk-list-offset.test.ts"],"names":[],"mappings":"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"}
@@ -73,7 +73,7 @@ const okResult = {
73
73
  optimized: null,
74
74
  rationale: null,
75
75
  reviewModel: "m",
76
- rubricVersion: "content-review.v4",
76
+ rubricVersion: "content-review.v5",
77
77
  thresholdSnapshot: {},
78
78
  latencyMs: 12,
79
79
  degradedReason: null,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuDpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA8+E9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AAg+BD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AAQF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAkJnE;AAyqBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE,GAAG,MAAM,CAiBT;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAyCpD;AAgyDD,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAyhF9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AAg+BD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,CAAC;AAQF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,GACA,OAAO,CAAC;IAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,CAkJnE;AAyqBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,sBAAsB,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE,GAAG,MAAM,CAiBT;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAyCpD;AAgyDD,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { registerSubredditStyleCommands } from "./register-subreddit-style.js";
8
8
  import { registerContentClassificationCommands } from "./register-content-classification.js";
9
9
  import { registerNotifyCommands } from "./register-notify.js";
10
10
  import { registerFeishuIdentityCommands } from "./register-feishu-identities.js";
11
+ import { registerCalendarDirectiveCommands, calendarPatchNeedsGate, deliveryModeChangeRequiresApply, } from "./register-calendar-directives.js";
11
12
  import { assertApplyOrDryRun } from "./dry-run.js";
12
13
  import { withPermissionGate } from "./permission-runner.js";
13
14
  import { registerBatchAndExport } from "./register-batch.js";
@@ -284,6 +285,7 @@ dashboard
284
285
  });
285
286
  // --- calendar ---
286
287
  const calendar = program.command("calendar").description("发布日历条目");
288
+ registerCalendarDirectiveCommands(calendar);
287
289
  calendar
288
290
  .command("list")
289
291
  .description("GET /calendar-entries")
@@ -311,6 +313,8 @@ calendar
311
313
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
312
314
  .requiredOption("-e, --entry <entryId>", "Calendar entry UUID")
313
315
  .requiredOption("--body <json>", '例如 {"status":"succeeded","permalink":"https://www.reddit.com/..."}')
316
+ .option("--dry-run", "预览写入,不调用 API", false)
317
+ .option("--apply", "执行写入(仅 deliveryMode 变更必填)", false)
314
318
  .action(async (opts) => {
315
319
  let body;
316
320
  try {
@@ -320,7 +324,31 @@ calendar
320
324
  console.error("Invalid --body JSON");
321
325
  process.exit(1);
322
326
  }
323
- const res = await requireClient().updateCalendarEntry(resolveTeamId(opts.team), opts.entry, body);
327
+ const teamId = resolveTeamId(opts.team);
328
+ // 两道门,判据不同,不能合成一条:
329
+ //
330
+ // `--dry-run` **对任何 body 都必须生效** —— 全局 flag 契约是「预览写入,不调用
331
+ // API」(docs/command-governance.md)。只在 deliveryMode 分支上认它,就会出现
332
+ // 「我明明加了 --dry-run,它却真的把状态改了」这种最不该有的意外写入。
333
+ //
334
+ // `--apply` **只在 body 含 `deliveryMode` 时必填**。它是防重复发帖的唯一闸门
335
+ // (方案 D1):改它会让服务端在同一事务里撤销/创建内部 publish_post job 并
336
+ // append 指令。`calendar set-delivery-mode` 已经带这道门,raw patch 必须同样
337
+ // 挡住,否则那道门只是装饰。其余字段(status/permalink/…)不加必填门,既有
338
+ // 自动化行为完全不变。
339
+ if (calendarPatchNeedsGate(body, opts) &&
340
+ !assertApplyOrDryRun(opts, {
341
+ command: deliveryModeChangeRequiresApply(body)
342
+ ? "calendar patch (deliveryMode)"
343
+ : "calendar patch",
344
+ danger: deliveryModeChangeRequiresApply(body)
345
+ ? "切换发布主体:转 external_agent 会撤销内部 publish_post job 并发 upsert 指令;转 hub_managed 会发 cancel 指令并建内部 job。改错 = 双发或谁都不发。"
346
+ : "更新日历条目",
347
+ summary: { teamId, calendarEntryId: opts.entry, body },
348
+ })) {
349
+ return;
350
+ }
351
+ const res = await requireClient().updateCalendarEntry(teamId, opts.entry, body);
324
352
  console.log(JSON.stringify(res, null, 2));
325
353
  });
326
354
  // --- reddit ---
@@ -580,10 +608,12 @@ accounts
580
608
  .option("--campaign <uuid>", "campaignId 过滤(legacy)")
581
609
  .option("--persona <uuid>", "personaId")
582
610
  .option("--category <cat>", "人设分类")
583
- .option("-n, --limit <n>", "limit", "50")
611
+ .option("-n, --limit <n>", "limit(上限 200)", "50")
612
+ .option("--offset <n>", "offset(翻页:offset 每次 += limit;返回体的 total 是过滤后的总数,offset + items.length >= total 即翻完)")
584
613
  .action(async (opts) => {
585
614
  const res = await requireClient().listAccounts(resolveTeamId(opts.team), {
586
615
  limit: Number(opts.limit),
616
+ offset: opts.offset === undefined ? undefined : Number(opts.offset),
587
617
  status: opts.status,
588
618
  platform: opts.platform,
589
619
  brandId: opts.brand,
@@ -1629,9 +1659,15 @@ compliance
1629
1659
  .command("risk-list")
1630
1660
  .description("GET /account-risk-profiles")
1631
1661
  .option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
1632
- .option("-n, --limit <n>", "limit", "100")
1662
+ .option("-n, --limit <n>", "limit(上限 200)", "100")
1663
+ .option("--offset <n>", "offset(翻页:offset 每次 += limit;返回体的 total 是过滤后的总数,集合在翻页期间不变时 offset + items.length >= total 即翻完。offset 分页不是快照分页,并发写入下同一行可能重复出现或被跳过)")
1664
+ .option("--search <text>", "按 handle / platform 模糊过滤")
1633
1665
  .action(async (opts) => {
1634
- const res = await requireClient().listAccountRiskProfiles(resolveTeamId(opts.team), Number(opts.limit));
1666
+ const res = await requireClient().listAccountRiskProfiles(resolveTeamId(opts.team), {
1667
+ limit: Number(opts.limit),
1668
+ offset: opts.offset === undefined ? undefined : Number(opts.offset),
1669
+ search: opts.search,
1670
+ });
1635
1671
  console.log(JSON.stringify(res, null, 2));
1636
1672
  });
1637
1673
  compliance