@geoly-ai/social-hub-cli 0.3.2 → 0.3.4
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/CHANGELOG.md +13 -0
- package/dist/client-delivery.test.d.ts +2 -0
- package/dist/client-delivery.test.d.ts.map +1 -0
- package/dist/client-delivery.test.js +201 -0
- package/dist/client-delivery.test.js.map +1 -0
- package/dist/cmd-manifest.json +25 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +279 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/skills/manifest.json +1 -1
- package/skills/reddit-content-rewrite/SKILL.md +58 -3
- package/skills/reddit-content-writing/SKILL.md +43 -5
- package/skills/reddit-content-writing/references/phase4-writing.md +3 -1
- package/skills/reddit-matrix.lock.json +4 -4
- package/skills/reddit-phase-brief/SKILL.md +30 -13
- package/skills/reddit-phase-brief/references/phase4-brief-workflow.md +39 -4
- package/skills/reddit-strategy-shared/references/content-diversity-contract.md +60 -5
- package/skills/reddit-strategy-shared/references/evidence-policy.md +30 -0
- package/skills/reddit-strategy-shared/references/handoff-schemas.md +7 -3
- package/skills/social-hub-cli/SKILL.md +2 -0
- package/skills/social-hub-intelligence/SKILL.md +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ 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.4] - 2026-07-31
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- 写作矩阵 P0-C —— 五项写作前置门与返工机制(vendored)
|
|
12
|
+
- 客户交付 Phase1 Wave2-A —— SDK/CLI 接 Block3 client-delivery API
|
|
13
|
+
|
|
14
|
+
## [0.3.3] - 2026-07-31
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- 补 hot-posts↔Arctic history 跨 skill 划界 —— 历史帖别误用 Hub 缓存
|
|
19
|
+
|
|
7
20
|
## [0.3.2] - 2026-07-31
|
|
8
21
|
|
|
9
22
|
### Added
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-delivery.test.d.ts","sourceRoot":"","sources":["../src/client-delivery.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for the `client-delivery` CLI command group:
|
|
3
|
+
* - staff + client subcommands register on the program;
|
|
4
|
+
* - request-changes reads its body via --json-file (Windows-friendly) and
|
|
5
|
+
* forwards it to the SDK;
|
|
6
|
+
* - approve forwards the CAS expectedRevisionHash and a 409 (hash conflict)
|
|
7
|
+
* propagates faithfully instead of being swallowed;
|
|
8
|
+
* - list-bundles forwards the required brandId filter.
|
|
9
|
+
*/
|
|
10
|
+
import { beforeAll, afterEach, describe, expect, it, vi } from "vitest";
|
|
11
|
+
import { writeFileSync, mkdtempSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
const clientDeliveryRequestChanges = vi
|
|
15
|
+
.fn()
|
|
16
|
+
.mockResolvedValue({ revision: {} });
|
|
17
|
+
const clientDeliveryApproveRevision = vi
|
|
18
|
+
.fn()
|
|
19
|
+
.mockResolvedValue({ revision: {} });
|
|
20
|
+
const clientDeliveryListBundles = vi.fn().mockResolvedValue({ items: [] });
|
|
21
|
+
vi.mock("@geoly-ai/social-hub-sdk", () => ({
|
|
22
|
+
SocialHubClient: vi.fn(),
|
|
23
|
+
getSocialHubHealth: vi.fn(),
|
|
24
|
+
}));
|
|
25
|
+
vi.mock("./client.js", () => ({
|
|
26
|
+
requireClient: () => ({
|
|
27
|
+
clientDeliveryRequestChanges,
|
|
28
|
+
clientDeliveryApproveRevision,
|
|
29
|
+
clientDeliveryListBundles,
|
|
30
|
+
}),
|
|
31
|
+
resolveTeamId: (t) => t ?? "team-1",
|
|
32
|
+
getBaseUrl: () => "http://localhost",
|
|
33
|
+
}));
|
|
34
|
+
let program;
|
|
35
|
+
beforeAll(async () => {
|
|
36
|
+
program = (await import("./index.js")).program;
|
|
37
|
+
vi.spyOn(console, "log").mockImplementation(() => { });
|
|
38
|
+
}, 30000);
|
|
39
|
+
function group() {
|
|
40
|
+
return program.commands.find((c) => c.name() === "client-delivery");
|
|
41
|
+
}
|
|
42
|
+
function subNames() {
|
|
43
|
+
return group()?.commands.map((c) => c.name()) ?? [];
|
|
44
|
+
}
|
|
45
|
+
function subCmd(name) {
|
|
46
|
+
return group()?.commands.find((c) => c.name() === name);
|
|
47
|
+
}
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
clientDeliveryRequestChanges.mockClear();
|
|
50
|
+
clientDeliveryApproveRevision.mockClear();
|
|
51
|
+
clientDeliveryListBundles.mockClear();
|
|
52
|
+
// Commander stores parsed option values on the singleton command; clear them
|
|
53
|
+
// so a value from one parseAsync run does not leak into the next.
|
|
54
|
+
for (const name of ["request-changes", "approve", "list-bundles"]) {
|
|
55
|
+
const cmd = subCmd(name);
|
|
56
|
+
for (const key of ["json", "jsonFile", "expectedHash", "note", "brand"]) {
|
|
57
|
+
cmd?.setOptionValue(key, undefined);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
describe("client-delivery command registration", () => {
|
|
62
|
+
it("registers the group", () => {
|
|
63
|
+
expect(program.commands.map((c) => c.name())).toContain("client-delivery");
|
|
64
|
+
});
|
|
65
|
+
it("registers staff + client subcommands", () => {
|
|
66
|
+
const names = subNames();
|
|
67
|
+
for (const expected of [
|
|
68
|
+
// staff
|
|
69
|
+
"create-bundle",
|
|
70
|
+
"upsert-item",
|
|
71
|
+
"create-revision",
|
|
72
|
+
"submit-revision",
|
|
73
|
+
"create-product",
|
|
74
|
+
"create-fact-version",
|
|
75
|
+
"activate-fact-version",
|
|
76
|
+
"create-policy-version",
|
|
77
|
+
"activate-policy-version",
|
|
78
|
+
// client
|
|
79
|
+
"list-bundles",
|
|
80
|
+
"get-bundle",
|
|
81
|
+
"list-items",
|
|
82
|
+
"get-item",
|
|
83
|
+
"list-revisions",
|
|
84
|
+
"get-revision",
|
|
85
|
+
"list-comments",
|
|
86
|
+
"list-events",
|
|
87
|
+
"approve",
|
|
88
|
+
"request-changes",
|
|
89
|
+
"add-comment",
|
|
90
|
+
"resolve-comment",
|
|
91
|
+
"create-client-fact-version",
|
|
92
|
+
]) {
|
|
93
|
+
expect(names).toContain(expected);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("client-delivery request-changes JSON input", () => {
|
|
98
|
+
const body = {
|
|
99
|
+
expectedRevisionHash: "hash-abc",
|
|
100
|
+
comments: [{ fieldKey: "title", body: "shorten" }],
|
|
101
|
+
};
|
|
102
|
+
function tmpFile() {
|
|
103
|
+
const dir = mkdtempSync(join(tmpdir(), "cd-json-"));
|
|
104
|
+
const file = join(dir, "body.json");
|
|
105
|
+
writeFileSync(file, JSON.stringify(body), "utf8");
|
|
106
|
+
return file;
|
|
107
|
+
}
|
|
108
|
+
it("reads body from --json-file and forwards to the SDK", async () => {
|
|
109
|
+
const file = tmpFile();
|
|
110
|
+
await program.parseAsync([
|
|
111
|
+
"node",
|
|
112
|
+
"social-hub",
|
|
113
|
+
"client-delivery",
|
|
114
|
+
"request-changes",
|
|
115
|
+
"--revision",
|
|
116
|
+
"r-1",
|
|
117
|
+
"--json-file",
|
|
118
|
+
file,
|
|
119
|
+
]);
|
|
120
|
+
expect(clientDeliveryRequestChanges).toHaveBeenCalledWith("team-1", "r-1", body);
|
|
121
|
+
});
|
|
122
|
+
it("reads body from -j @file", async () => {
|
|
123
|
+
const file = tmpFile();
|
|
124
|
+
await program.parseAsync([
|
|
125
|
+
"node",
|
|
126
|
+
"social-hub",
|
|
127
|
+
"client-delivery",
|
|
128
|
+
"request-changes",
|
|
129
|
+
"--revision",
|
|
130
|
+
"r-1",
|
|
131
|
+
"-j",
|
|
132
|
+
`@${file}`,
|
|
133
|
+
]);
|
|
134
|
+
expect(clientDeliveryRequestChanges).toHaveBeenCalledWith("team-1", "r-1", body);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
describe("client-delivery approve (CAS)", () => {
|
|
138
|
+
it("forwards --expected-hash as expectedRevisionHash", async () => {
|
|
139
|
+
await program.parseAsync([
|
|
140
|
+
"node",
|
|
141
|
+
"social-hub",
|
|
142
|
+
"client-delivery",
|
|
143
|
+
"approve",
|
|
144
|
+
"--revision",
|
|
145
|
+
"r-1",
|
|
146
|
+
"--expected-hash",
|
|
147
|
+
"hash-abc",
|
|
148
|
+
"--note",
|
|
149
|
+
"lgtm",
|
|
150
|
+
]);
|
|
151
|
+
expect(clientDeliveryApproveRevision).toHaveBeenCalledWith("team-1", "r-1", {
|
|
152
|
+
expectedRevisionHash: "hash-abc",
|
|
153
|
+
note: "lgtm",
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
it("propagates a 409 hash conflict instead of swallowing it", async () => {
|
|
157
|
+
clientDeliveryApproveRevision.mockRejectedValueOnce(new Error("HTTP 409: revision changed; reload before deciding"));
|
|
158
|
+
await expect(program.parseAsync([
|
|
159
|
+
"node",
|
|
160
|
+
"social-hub",
|
|
161
|
+
"client-delivery",
|
|
162
|
+
"approve",
|
|
163
|
+
"--revision",
|
|
164
|
+
"r-1",
|
|
165
|
+
"--expected-hash",
|
|
166
|
+
"stale",
|
|
167
|
+
])).rejects.toThrow(/HTTP 409/);
|
|
168
|
+
});
|
|
169
|
+
it("propagates a 403 (api_key rejected; decision needs a user credential)", async () => {
|
|
170
|
+
// Client decisions require an auth-login user; a static api_key is refused
|
|
171
|
+
// server-side and the SDK surfaces it as HTTP 403. The CLI must not swallow
|
|
172
|
+
// it — credentials are decided by `auth login`, the CLI only relays.
|
|
173
|
+
clientDeliveryApproveRevision.mockRejectedValueOnce(new Error("HTTP 403: this action requires an authenticated user"));
|
|
174
|
+
await expect(program.parseAsync([
|
|
175
|
+
"node",
|
|
176
|
+
"social-hub",
|
|
177
|
+
"client-delivery",
|
|
178
|
+
"approve",
|
|
179
|
+
"--revision",
|
|
180
|
+
"r-1",
|
|
181
|
+
"--expected-hash",
|
|
182
|
+
"hash-abc",
|
|
183
|
+
])).rejects.toThrow(/HTTP 403/);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe("client-delivery list-bundles", () => {
|
|
187
|
+
it("forwards the required brandId filter", async () => {
|
|
188
|
+
await program.parseAsync([
|
|
189
|
+
"node",
|
|
190
|
+
"social-hub",
|
|
191
|
+
"client-delivery",
|
|
192
|
+
"list-bundles",
|
|
193
|
+
"--brand",
|
|
194
|
+
"brand-9",
|
|
195
|
+
]);
|
|
196
|
+
expect(clientDeliveryListBundles).toHaveBeenCalledWith("team-1", {
|
|
197
|
+
brandId: "brand-9",
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
//# sourceMappingURL=client-delivery.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-delivery.test.js","sourceRoot":"","sources":["../src/client-delivery.test.ts"],"names":[],"mappings":"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"}
|
package/dist/cmd-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-07-
|
|
3
|
-
"cliVersion": "0.3.
|
|
2
|
+
"generatedAt": "2026-07-31T10:50:16.756Z",
|
|
3
|
+
"cliVersion": "0.3.4",
|
|
4
4
|
"commands": [
|
|
5
5
|
"accounts",
|
|
6
6
|
"accounts brand-bindings",
|
|
@@ -121,6 +121,29 @@
|
|
|
121
121
|
"campaigns get",
|
|
122
122
|
"campaigns list",
|
|
123
123
|
"campaigns update",
|
|
124
|
+
"client-delivery",
|
|
125
|
+
"client-delivery activate-fact-version",
|
|
126
|
+
"client-delivery activate-policy-version",
|
|
127
|
+
"client-delivery add-comment",
|
|
128
|
+
"client-delivery approve",
|
|
129
|
+
"client-delivery create-bundle",
|
|
130
|
+
"client-delivery create-client-fact-version",
|
|
131
|
+
"client-delivery create-fact-version",
|
|
132
|
+
"client-delivery create-policy-version",
|
|
133
|
+
"client-delivery create-product",
|
|
134
|
+
"client-delivery create-revision",
|
|
135
|
+
"client-delivery get-bundle",
|
|
136
|
+
"client-delivery get-item",
|
|
137
|
+
"client-delivery get-revision",
|
|
138
|
+
"client-delivery list-bundles",
|
|
139
|
+
"client-delivery list-comments",
|
|
140
|
+
"client-delivery list-events",
|
|
141
|
+
"client-delivery list-items",
|
|
142
|
+
"client-delivery list-revisions",
|
|
143
|
+
"client-delivery request-changes",
|
|
144
|
+
"client-delivery resolve-comment",
|
|
145
|
+
"client-delivery submit-revision",
|
|
146
|
+
"client-delivery upsert-item",
|
|
124
147
|
"comment-drafts",
|
|
125
148
|
"comment-drafts create",
|
|
126
149
|
"comment-drafts delete",
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+CpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA43E9B,8DAA8D;AAC9D,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,MAAM,GAAG,IAAI,CAOf;AA2/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;AA+1ED,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1208,6 +1208,285 @@ commentDrafts
|
|
|
1208
1208
|
const res = await requireClient().scheduleCommentDraft(resolveTeamId(opts.team), opts.draft, body);
|
|
1209
1209
|
console.log(JSON.stringify(res, null, 2));
|
|
1210
1210
|
});
|
|
1211
|
+
// --- 客户面内容审核(Client Content Delivery)---
|
|
1212
|
+
//
|
|
1213
|
+
// staff 管理面(clientDeliveryAdmin):建 bundle/item/revision + 产品/事实/政策。
|
|
1214
|
+
// 客户 portal 面(clientDelivery):读、决策(approve/request-changes,走 CAS
|
|
1215
|
+
// expectedRevisionHash;不符 → 409)、字段级评论。**客户决策/评论/事实提交须用 user 凭证
|
|
1216
|
+
// (`social-hub auth login`),api_key 会被服务端拒**——CLI 如实透传服务端错误。
|
|
1217
|
+
const clientDelivery = program
|
|
1218
|
+
.command("client-delivery")
|
|
1219
|
+
.description("客户面内容审核交付(bundle/item/revision + 客户 approve/request-changes;决策须 user 凭证)");
|
|
1220
|
+
// ── staff 管理面 ──────────────────────────────────────────────────────────────
|
|
1221
|
+
clientDelivery
|
|
1222
|
+
.command("create-bundle")
|
|
1223
|
+
.description("POST client-delivery/bundles — staff 建 bundle")
|
|
1224
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1225
|
+
.option("-j, --json <json>", "{ brandId, bundleCode, name, clientDueAt? }。也可 -j @<path> / -j -(stdin)")
|
|
1226
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 - 表示 stdin);与 -j 二选一(Windows 友好)")
|
|
1227
|
+
.action(async (opts) => {
|
|
1228
|
+
const body = readJsonArgOrExit({
|
|
1229
|
+
inline: opts.json,
|
|
1230
|
+
file: opts.jsonFile,
|
|
1231
|
+
});
|
|
1232
|
+
const res = await requireClient().clientDeliveryCreateBundle(resolveTeamId(opts.team), body);
|
|
1233
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1234
|
+
});
|
|
1235
|
+
clientDelivery
|
|
1236
|
+
.command("upsert-item")
|
|
1237
|
+
.description("POST client-delivery/bundles/:id/items — staff upsert 条目(帖/评 + 矩阵字段)")
|
|
1238
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1239
|
+
.requiredOption("--bundle <uuid>", "Bundle UUID")
|
|
1240
|
+
.option("-j, --json <json>", "{ kind(post|comment), itemCode, contentDraftId?, commentDraftId?, ordinal?, boundProductId?, ...矩阵字段 }")
|
|
1241
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1242
|
+
.action(async (opts) => {
|
|
1243
|
+
const body = readJsonArgOrExit({
|
|
1244
|
+
inline: opts.json,
|
|
1245
|
+
file: opts.jsonFile,
|
|
1246
|
+
});
|
|
1247
|
+
const res = await requireClient().clientDeliveryUpsertItem(resolveTeamId(opts.team), opts.bundle, body);
|
|
1248
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1249
|
+
});
|
|
1250
|
+
clientDelivery
|
|
1251
|
+
.command("create-revision")
|
|
1252
|
+
.description("POST client-delivery/items/:id/revisions — staff 建不可变送审快照")
|
|
1253
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1254
|
+
.requiredOption("--item <uuid>", "Item UUID")
|
|
1255
|
+
.action(async (opts) => {
|
|
1256
|
+
const res = await requireClient().clientDeliveryCreateRevision(resolveTeamId(opts.team), opts.item);
|
|
1257
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1258
|
+
});
|
|
1259
|
+
clientDelivery
|
|
1260
|
+
.command("submit-revision")
|
|
1261
|
+
.description("POST client-delivery/revisions/:id/submit — staff 送审(not_submitted|withdrawn → pending)")
|
|
1262
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1263
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1264
|
+
.option("--note <text>", "送审备注(可选)")
|
|
1265
|
+
.action(async (opts) => {
|
|
1266
|
+
const body = {};
|
|
1267
|
+
if (opts.note !== undefined)
|
|
1268
|
+
body.note = opts.note;
|
|
1269
|
+
const res = await requireClient().clientDeliverySubmitRevision(resolveTeamId(opts.team), opts.revision, body);
|
|
1270
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1271
|
+
});
|
|
1272
|
+
clientDelivery
|
|
1273
|
+
.command("create-product")
|
|
1274
|
+
.description("POST client-delivery/products — staff 建产品身份")
|
|
1275
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1276
|
+
.option("-j, --json <json>", "{ brandId, sku, brandRegistryId?, modelName?, market?, status? }")
|
|
1277
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1278
|
+
.action(async (opts) => {
|
|
1279
|
+
const body = readJsonArgOrExit({
|
|
1280
|
+
inline: opts.json,
|
|
1281
|
+
file: opts.jsonFile,
|
|
1282
|
+
});
|
|
1283
|
+
const res = await requireClient().clientDeliveryCreateProduct(resolveTeamId(opts.team), body);
|
|
1284
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1285
|
+
});
|
|
1286
|
+
clientDelivery
|
|
1287
|
+
.command("create-fact-version")
|
|
1288
|
+
.description("POST client-delivery/products/:productId/fact-versions(staff 面)— provenance 默认 staff")
|
|
1289
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1290
|
+
.requiredOption("--product <uuid>", "Product UUID")
|
|
1291
|
+
.option("-j, --json <json>", "{ provenance?, positioning?, materials?, priceAmount?, priceCurrency?, inventoryStatus?, factsJson?, effectiveAt?, expiresAt?, sourceRef?, ... }")
|
|
1292
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1293
|
+
.action(async (opts) => {
|
|
1294
|
+
const body = readJsonArgOrExit({
|
|
1295
|
+
inline: opts.json,
|
|
1296
|
+
file: opts.jsonFile,
|
|
1297
|
+
});
|
|
1298
|
+
const res = await requireClient().clientDeliveryCreateFactVersion(resolveTeamId(opts.team), opts.product, body);
|
|
1299
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1300
|
+
});
|
|
1301
|
+
clientDelivery
|
|
1302
|
+
.command("activate-fact-version")
|
|
1303
|
+
.description("POST client-delivery/products/:productId/fact-versions/:fvId/activate — staff 激活 + stale 传播")
|
|
1304
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1305
|
+
.requiredOption("--product <uuid>", "Product UUID")
|
|
1306
|
+
.requiredOption("--fact-version <uuid>", "Fact version UUID")
|
|
1307
|
+
.action(async (opts) => {
|
|
1308
|
+
const res = await requireClient().clientDeliveryActivateFactVersion(resolveTeamId(opts.team), opts.product, opts.factVersion);
|
|
1309
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1310
|
+
});
|
|
1311
|
+
clientDelivery
|
|
1312
|
+
.command("create-policy-version")
|
|
1313
|
+
.description("POST client-delivery/policy-versions — staff 建品牌内容政策版本")
|
|
1314
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1315
|
+
.option("-j, --json <json>", "{ brandId, market?, provenance?, policyJson?, effectiveAt? }")
|
|
1316
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1317
|
+
.action(async (opts) => {
|
|
1318
|
+
const body = readJsonArgOrExit({
|
|
1319
|
+
inline: opts.json,
|
|
1320
|
+
file: opts.jsonFile,
|
|
1321
|
+
});
|
|
1322
|
+
const res = await requireClient().clientDeliveryCreatePolicyVersion(resolveTeamId(opts.team), body);
|
|
1323
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1324
|
+
});
|
|
1325
|
+
clientDelivery
|
|
1326
|
+
.command("activate-policy-version")
|
|
1327
|
+
.description("POST client-delivery/policy-versions/:id/activate — staff 激活政策版本")
|
|
1328
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1329
|
+
.requiredOption("--policy-version <uuid>", "Policy version UUID")
|
|
1330
|
+
.action(async (opts) => {
|
|
1331
|
+
const res = await requireClient().clientDeliveryActivatePolicyVersion(resolveTeamId(opts.team), opts.policyVersion);
|
|
1332
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1333
|
+
});
|
|
1334
|
+
// ── 客户 portal 面(读/决策/评论)──────────────────────────────────────────────
|
|
1335
|
+
clientDelivery
|
|
1336
|
+
.command("list-bundles")
|
|
1337
|
+
.description("GET client-delivery/bundles — 客户面 bundle 列表(brandId 必填)")
|
|
1338
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1339
|
+
.requiredOption("--brand <uuid>", "brandId(服务端必填)")
|
|
1340
|
+
.option("--status <st>", "状态过滤:open | closed | cancelled")
|
|
1341
|
+
.option("-n, --limit <n>", "limit")
|
|
1342
|
+
.option("--offset <n>", "offset")
|
|
1343
|
+
.action(async (opts) => {
|
|
1344
|
+
const params = { brandId: opts.brand };
|
|
1345
|
+
if (opts.status)
|
|
1346
|
+
params.status = opts.status;
|
|
1347
|
+
if (opts.limit !== undefined)
|
|
1348
|
+
params.limit = Number(opts.limit);
|
|
1349
|
+
if (opts.offset !== undefined)
|
|
1350
|
+
params.offset = Number(opts.offset);
|
|
1351
|
+
const res = await requireClient().clientDeliveryListBundles(resolveTeamId(opts.team), params);
|
|
1352
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1353
|
+
});
|
|
1354
|
+
clientDelivery
|
|
1355
|
+
.command("get-bundle")
|
|
1356
|
+
.description("GET client-delivery/bundles/:id")
|
|
1357
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1358
|
+
.requiredOption("--bundle <uuid>", "Bundle UUID")
|
|
1359
|
+
.action(async (opts) => {
|
|
1360
|
+
const res = await requireClient().clientDeliveryGetBundle(resolveTeamId(opts.team), opts.bundle);
|
|
1361
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1362
|
+
});
|
|
1363
|
+
clientDelivery
|
|
1364
|
+
.command("list-items")
|
|
1365
|
+
.description("GET client-delivery/bundles/:id/items")
|
|
1366
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1367
|
+
.requiredOption("--bundle <uuid>", "Bundle UUID")
|
|
1368
|
+
.action(async (opts) => {
|
|
1369
|
+
const res = await requireClient().clientDeliveryListItems(resolveTeamId(opts.team), opts.bundle);
|
|
1370
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1371
|
+
});
|
|
1372
|
+
clientDelivery
|
|
1373
|
+
.command("get-item")
|
|
1374
|
+
.description("GET client-delivery/items/:id")
|
|
1375
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1376
|
+
.requiredOption("--item <uuid>", "Item UUID")
|
|
1377
|
+
.action(async (opts) => {
|
|
1378
|
+
const res = await requireClient().clientDeliveryGetItem(resolveTeamId(opts.team), opts.item);
|
|
1379
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1380
|
+
});
|
|
1381
|
+
clientDelivery
|
|
1382
|
+
.command("list-revisions")
|
|
1383
|
+
.description("GET client-delivery/items/:id/revisions")
|
|
1384
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1385
|
+
.requiredOption("--item <uuid>", "Item UUID")
|
|
1386
|
+
.action(async (opts) => {
|
|
1387
|
+
const res = await requireClient().clientDeliveryListRevisions(resolveTeamId(opts.team), opts.item);
|
|
1388
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1389
|
+
});
|
|
1390
|
+
clientDelivery
|
|
1391
|
+
.command("get-revision")
|
|
1392
|
+
.description("GET client-delivery/revisions/:id(含 sourceContentHash 作 approve/request-changes 的 CAS 凭证)")
|
|
1393
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1394
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1395
|
+
.action(async (opts) => {
|
|
1396
|
+
const res = await requireClient().clientDeliveryGetRevision(resolveTeamId(opts.team), opts.revision);
|
|
1397
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1398
|
+
});
|
|
1399
|
+
clientDelivery
|
|
1400
|
+
.command("list-comments")
|
|
1401
|
+
.description("GET client-delivery/revisions/:id/comments")
|
|
1402
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1403
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1404
|
+
.action(async (opts) => {
|
|
1405
|
+
const res = await requireClient().clientDeliveryListComments(resolveTeamId(opts.team), opts.revision);
|
|
1406
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1407
|
+
});
|
|
1408
|
+
clientDelivery
|
|
1409
|
+
.command("list-events")
|
|
1410
|
+
.description("GET client-delivery/revisions/:id/events — 决策事件链")
|
|
1411
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1412
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1413
|
+
.action(async (opts) => {
|
|
1414
|
+
const res = await requireClient().clientDeliveryListEvents(resolveTeamId(opts.team), opts.revision);
|
|
1415
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1416
|
+
});
|
|
1417
|
+
clientDelivery
|
|
1418
|
+
.command("approve")
|
|
1419
|
+
.description("POST client-delivery/revisions/:id/approve — 客户批准(CAS;须 user 凭证,api_key 被拒;hash 不符 → 409)")
|
|
1420
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1421
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1422
|
+
.requiredOption("--expected-hash <hash>", "expectedRevisionHash(取自 get-revision 的 sourceContentHash;不符 → 409)")
|
|
1423
|
+
.option("--note <text>", "批准备注(可选)")
|
|
1424
|
+
.action(async (opts) => {
|
|
1425
|
+
const body = {
|
|
1426
|
+
expectedRevisionHash: opts.expectedHash,
|
|
1427
|
+
};
|
|
1428
|
+
if (opts.note !== undefined)
|
|
1429
|
+
body.note = opts.note;
|
|
1430
|
+
const res = await requireClient().clientDeliveryApproveRevision(resolveTeamId(opts.team), opts.revision, body);
|
|
1431
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1432
|
+
});
|
|
1433
|
+
clientDelivery
|
|
1434
|
+
.command("request-changes")
|
|
1435
|
+
.description("POST client-delivery/revisions/:id/request-changes — 客户请求修改 + 字段级评论(CAS;须 user 凭证;hash 不符 → 409)")
|
|
1436
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1437
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1438
|
+
.option("-j, --json <json>", "{ expectedRevisionHash, comments:[{ fieldKey, quotedText?, body }], note? }。也可 -j @<path> / -j -")
|
|
1439
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1440
|
+
.action(async (opts) => {
|
|
1441
|
+
const body = readJsonArgOrExit({
|
|
1442
|
+
inline: opts.json,
|
|
1443
|
+
file: opts.jsonFile,
|
|
1444
|
+
});
|
|
1445
|
+
const res = await requireClient().clientDeliveryRequestChanges(resolveTeamId(opts.team), opts.revision, body);
|
|
1446
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1447
|
+
});
|
|
1448
|
+
clientDelivery
|
|
1449
|
+
.command("add-comment")
|
|
1450
|
+
.description("POST client-delivery/revisions/:id/comments — 客户字段级讨论(须 user 凭证)")
|
|
1451
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1452
|
+
.requiredOption("--revision <uuid>", "Revision UUID")
|
|
1453
|
+
.requiredOption("--field-key <key>", "字段定位(如 title/body/price)")
|
|
1454
|
+
.requiredOption("--body <text>", "评论正文")
|
|
1455
|
+
.option("--quoted-text <text>", "引用的原文片段(可选)")
|
|
1456
|
+
.action(async (opts) => {
|
|
1457
|
+
const body = {
|
|
1458
|
+
fieldKey: opts.fieldKey,
|
|
1459
|
+
body: opts.body,
|
|
1460
|
+
};
|
|
1461
|
+
if (opts.quotedText !== undefined)
|
|
1462
|
+
body.quotedText = opts.quotedText;
|
|
1463
|
+
const res = await requireClient().clientDeliveryAddComment(resolveTeamId(opts.team), opts.revision, body);
|
|
1464
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1465
|
+
});
|
|
1466
|
+
clientDelivery
|
|
1467
|
+
.command("resolve-comment")
|
|
1468
|
+
.description("POST client-delivery/comments/:id/resolve — 客户关闭讨论(幂等;须 user 凭证)")
|
|
1469
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1470
|
+
.requiredOption("--comment <uuid>", "Comment UUID")
|
|
1471
|
+
.action(async (opts) => {
|
|
1472
|
+
const res = await requireClient().clientDeliveryResolveComment(resolveTeamId(opts.team), opts.comment);
|
|
1473
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1474
|
+
});
|
|
1475
|
+
clientDelivery
|
|
1476
|
+
.command("create-client-fact-version")
|
|
1477
|
+
.description("POST client-delivery/products/:productId/fact-versions(客户面)— provenance 强制 client(须 user 凭证)")
|
|
1478
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
1479
|
+
.requiredOption("--product <uuid>", "Product UUID")
|
|
1480
|
+
.option("-j, --json <json>", "{ positioning?, materials?, priceAmount?, priceCurrency?, inventoryStatus?, factsJson?, effectiveAt?, expiresAt?, sourceRef?, ... }")
|
|
1481
|
+
.option("--json-file <path>", "从文件读 body JSON(路径,或 -);与 -j 二选一")
|
|
1482
|
+
.action(async (opts) => {
|
|
1483
|
+
const body = readJsonArgOrExit({
|
|
1484
|
+
inline: opts.json,
|
|
1485
|
+
file: opts.jsonFile,
|
|
1486
|
+
});
|
|
1487
|
+
const res = await requireClient().clientDeliveryCreateClientFactVersion(resolveTeamId(opts.team), opts.product, body);
|
|
1488
|
+
console.log(JSON.stringify(res, null, 2));
|
|
1489
|
+
});
|
|
1211
1490
|
// --- compliance ---
|
|
1212
1491
|
const compliance = program.command("compliance").description("合规 / 风控");
|
|
1213
1492
|
compliance
|