@geoly-ai/social-hub-cli 0.3.32 → 0.3.34
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 +20 -0
- package/dist/cmd-manifest.json +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/register-reddit-account-verification.d.ts +30 -0
- package/dist/register-reddit-account-verification.d.ts.map +1 -0
- package/dist/register-reddit-account-verification.js +207 -0
- package/dist/register-reddit-account-verification.js.map +1 -0
- package/package.json +3 -3
- package/skills/integrity.json +3 -3
- package/skills/manifest.json +1 -1
- package/skills/social-hub-intelligence/SKILL.md +30 -0
- package/skills/social-hub-openclaw-context/SKILL.md +31 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* Reddit 账号平台判定状态交付面(Block C)—— `social-hub reddit-verification ...`。
|
|
4
|
+
*
|
|
5
|
+
* team 维度端点(`/v1/teams/:teamId/...`):读 = 非 client 内部角色 + internal 只读;
|
|
6
|
+
* 写(record observation / patch evidence)= senior 及以上(client 恒拒,见 authz
|
|
7
|
+
* `redditAccountVerification` 资源梯度)。⛔ 一期不暴露 dispatch policy——本 CLI 只吐
|
|
8
|
+
* 原始 verification state,不做「能不能派活」的建议。
|
|
9
|
+
*/
|
|
10
|
+
declare const evidenceKinds: readonly ["dom_snapshot", "screenshot", "agent_narrative"];
|
|
11
|
+
declare const observedStates: readonly ["verification_required", "app_labeled", "verified"];
|
|
12
|
+
/** `observations record` 请求体的本地形状校验(非法输入 dry-run 前即拒)。 */
|
|
13
|
+
export declare function buildRecordObservationBody(raw: Record<string, unknown>): {
|
|
14
|
+
observedState: (typeof observedStates)[number];
|
|
15
|
+
observedAt: string;
|
|
16
|
+
requestId: string;
|
|
17
|
+
sourceEventType: string;
|
|
18
|
+
deadlineRaw?: string | null;
|
|
19
|
+
deadlineAt?: string | null;
|
|
20
|
+
evidence: Array<{
|
|
21
|
+
kind: (typeof evidenceKinds)[number];
|
|
22
|
+
ref?: string | null;
|
|
23
|
+
host?: string | null;
|
|
24
|
+
capturedAt?: string | null;
|
|
25
|
+
expiresAt?: string | null;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
export declare function registerRedditAccountVerificationCommands(program: Command): void;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=register-reddit-account-verification.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-reddit-account-verification.d.ts","sourceRoot":"","sources":["../src/register-reddit-account-verification.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUzC;;;;;;;GAOG;AAEH,QAAA,MAAM,aAAa,4DAIT,CAAC;AACX,QAAA,MAAM,cAAc,+DAIV,CAAC;AAQX,0DAA0D;AAC1D,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACxE,aAAa,EAAE,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;QACrC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC3B,CAAC,CAAC;CACJ,CA0DA;AAED,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,OAAO,GACf,IAAI,CA2LN"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { requireClient, resolveTeamId } from "./client.js";
|
|
2
|
+
import { assertApplyOrDryRun } from "./dry-run.js";
|
|
3
|
+
import { parseJsonOption, printResult, withCliErrorBoundary, } from "./output.js";
|
|
4
|
+
import { withPermissionGates } from "./permission-runner.js";
|
|
5
|
+
/**
|
|
6
|
+
* Reddit 账号平台判定状态交付面(Block C)—— `social-hub reddit-verification ...`。
|
|
7
|
+
*
|
|
8
|
+
* team 维度端点(`/v1/teams/:teamId/...`):读 = 非 client 内部角色 + internal 只读;
|
|
9
|
+
* 写(record observation / patch evidence)= senior 及以上(client 恒拒,见 authz
|
|
10
|
+
* `redditAccountVerification` 资源梯度)。⛔ 一期不暴露 dispatch policy——本 CLI 只吐
|
|
11
|
+
* 原始 verification state,不做「能不能派活」的建议。
|
|
12
|
+
*/
|
|
13
|
+
const evidenceKinds = [
|
|
14
|
+
"dom_snapshot",
|
|
15
|
+
"screenshot",
|
|
16
|
+
"agent_narrative",
|
|
17
|
+
];
|
|
18
|
+
const observedStates = [
|
|
19
|
+
"verification_required",
|
|
20
|
+
"app_labeled",
|
|
21
|
+
"verified",
|
|
22
|
+
];
|
|
23
|
+
const evidenceAvailabilities = [
|
|
24
|
+
"available",
|
|
25
|
+
"expired",
|
|
26
|
+
"missing",
|
|
27
|
+
"revoked",
|
|
28
|
+
];
|
|
29
|
+
/** `observations record` 请求体的本地形状校验(非法输入 dry-run 前即拒)。 */
|
|
30
|
+
export function buildRecordObservationBody(raw) {
|
|
31
|
+
const fail = (msg) => {
|
|
32
|
+
console.error(msg);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
};
|
|
35
|
+
const str = (k, required) => {
|
|
36
|
+
const v = raw[k];
|
|
37
|
+
if (v === undefined || v === null) {
|
|
38
|
+
if (required)
|
|
39
|
+
return fail(`--json 缺少必填字段 ${k}(string)`);
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (typeof v !== "string" || v.trim() === "") {
|
|
43
|
+
return fail(`--json 字段 ${k} 须为非空 string`);
|
|
44
|
+
}
|
|
45
|
+
return v;
|
|
46
|
+
};
|
|
47
|
+
const observedState = str("observedState", true);
|
|
48
|
+
if (!observedStates.includes(observedState)) {
|
|
49
|
+
return fail(`--json 字段 observedState 须为 ${observedStates.join("|")}`);
|
|
50
|
+
}
|
|
51
|
+
const observedAt = str("observedAt", true);
|
|
52
|
+
const requestId = str("requestId", true);
|
|
53
|
+
const sourceEventType = str("sourceEventType", true);
|
|
54
|
+
const deadlineRaw = str("deadlineRaw", false);
|
|
55
|
+
const deadlineAt = str("deadlineAt", false);
|
|
56
|
+
const evidenceRaw = raw.evidence;
|
|
57
|
+
if (!Array.isArray(evidenceRaw) || evidenceRaw.length === 0) {
|
|
58
|
+
return fail("--json 字段 evidence 须为非空数组");
|
|
59
|
+
}
|
|
60
|
+
const evidence = evidenceRaw.map((entry, i) => {
|
|
61
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
62
|
+
return fail(`--json evidence[${i}] 须为对象`);
|
|
63
|
+
}
|
|
64
|
+
const e = entry;
|
|
65
|
+
const kind = e.kind;
|
|
66
|
+
if (typeof kind !== "string" ||
|
|
67
|
+
!evidenceKinds.includes(kind)) {
|
|
68
|
+
return fail(`--json evidence[${i}].kind 须为 ${evidenceKinds.join("|")}`);
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
kind: kind,
|
|
72
|
+
ref: typeof e.ref === "string" ? e.ref : undefined,
|
|
73
|
+
host: typeof e.host === "string" ? e.host : undefined,
|
|
74
|
+
capturedAt: typeof e.capturedAt === "string" ? e.capturedAt : undefined,
|
|
75
|
+
expiresAt: typeof e.expiresAt === "string" ? e.expiresAt : undefined,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
observedState: observedState,
|
|
80
|
+
observedAt,
|
|
81
|
+
requestId,
|
|
82
|
+
sourceEventType,
|
|
83
|
+
...(deadlineRaw ? { deadlineRaw } : {}),
|
|
84
|
+
...(deadlineAt ? { deadlineAt } : {}),
|
|
85
|
+
evidence,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export function registerRedditAccountVerificationCommands(program) {
|
|
89
|
+
const rav = program
|
|
90
|
+
.command("reddit-verification")
|
|
91
|
+
.description("Reddit 账号平台判定状态(team 级;client 恒拒;⛔ 不含 dispatch policy)");
|
|
92
|
+
// ── 读:单账号详情(current + 最近 N 条 observation)─────────────────────
|
|
93
|
+
rav
|
|
94
|
+
.command("get")
|
|
95
|
+
.description("GET .../accounts/:accountId/reddit-verification — current + 最近 N 条 observation(含 evidence 摘要)")
|
|
96
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
97
|
+
.requiredOption("--account-id <uuid>", "social_accounts.id")
|
|
98
|
+
.option("--limit <n>", "最近观测条数上限(1-100,默认 20)")
|
|
99
|
+
.action(async (opts) => {
|
|
100
|
+
await withCliErrorBoundary(async () => {
|
|
101
|
+
await withPermissionGates({
|
|
102
|
+
command: "reddit-verification get",
|
|
103
|
+
gates: [{ resource: "redditAccountVerification", action: "read" }],
|
|
104
|
+
teamId: opts.team,
|
|
105
|
+
}, async () => {
|
|
106
|
+
const teamId = resolveTeamId(opts.team);
|
|
107
|
+
printResult(await requireClient().getRedditAccountVerification(teamId, opts.accountId, { limit: opts.limit ? Number(opts.limit) : undefined }));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// ── 读:列表 + coverage ──────────────────────────────────────────────────
|
|
112
|
+
rav
|
|
113
|
+
.command("list")
|
|
114
|
+
.description("GET .../reddit-verification/accounts — 列表 + coverage 计数(默认只看需处理:verification_required+app_labeled)")
|
|
115
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
116
|
+
.option("--all", "看全量(含 unknown/verified),默认只看需处理队列", false)
|
|
117
|
+
.option("--limit <n>", "最多返回条数(1-200,默认 50)")
|
|
118
|
+
.option("--offset <n>", "偏移")
|
|
119
|
+
.action(async (opts) => {
|
|
120
|
+
await withCliErrorBoundary(async () => {
|
|
121
|
+
await withPermissionGates({
|
|
122
|
+
command: "reddit-verification list",
|
|
123
|
+
gates: [{ resource: "redditAccountVerification", action: "list" }],
|
|
124
|
+
teamId: opts.team,
|
|
125
|
+
}, async () => {
|
|
126
|
+
const teamId = resolveTeamId(opts.team);
|
|
127
|
+
printResult(await requireClient().listRedditAccountVerificationAccounts(teamId, {
|
|
128
|
+
needsAttention: opts.all ? false : true,
|
|
129
|
+
limit: opts.limit ? Number(opts.limit) : undefined,
|
|
130
|
+
offset: opts.offset ? Number(opts.offset) : undefined,
|
|
131
|
+
}));
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
// ── 写:记一条观测(幂等键 requestId;响应固定三态)───────────────────────
|
|
136
|
+
rav
|
|
137
|
+
.command("record-observation")
|
|
138
|
+
.description("POST .../accounts/:accountId/reddit-verification/observations — 幂等键 requestId;201=recorded/200=duplicate_delivery/409=两种专用冲突码")
|
|
139
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
140
|
+
.requiredOption("--account-id <uuid>", "social_accounts.id")
|
|
141
|
+
.requiredOption("-j, --json <json>", '{ "observedState","observedAt","requestId","sourceEventType", 可选 "deadlineRaw"/"deadlineAt", "evidence":[{"kind",...}] }')
|
|
142
|
+
.option("--dry-run", "预览", false)
|
|
143
|
+
.option("--apply", "执行写入", false)
|
|
144
|
+
.action(async (opts) => {
|
|
145
|
+
await withCliErrorBoundary(async () => {
|
|
146
|
+
await withPermissionGates({
|
|
147
|
+
command: "reddit-verification record-observation",
|
|
148
|
+
gates: [
|
|
149
|
+
{ resource: "redditAccountVerification", action: "create" },
|
|
150
|
+
],
|
|
151
|
+
teamId: opts.team,
|
|
152
|
+
}, async () => {
|
|
153
|
+
const body = buildRecordObservationBody(parseJsonOption(opts.json));
|
|
154
|
+
if (!assertApplyOrDryRun(opts, {
|
|
155
|
+
command: "reddit-verification record-observation",
|
|
156
|
+
danger: "write",
|
|
157
|
+
summary: { accountId: opts.accountId, ...body },
|
|
158
|
+
})) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const teamId = resolveTeamId(opts.team);
|
|
162
|
+
printResult(await requireClient().recordRedditAccountVerificationObservation(teamId, opts.accountId, body));
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
// ── 写:标注证据可用性(只改 availability;拒绝较旧检查覆盖较新结果)────
|
|
167
|
+
rav
|
|
168
|
+
.command("mark-evidence")
|
|
169
|
+
.description("PATCH .../reddit-verification/evidence/:evidenceId — 只改 availability;checkedAt 必填,较旧检查覆盖较新结果会被拒(409)")
|
|
170
|
+
.option("-t, --team <teamId>", "Team UUID(缺省用当前 context)")
|
|
171
|
+
.requiredOption("--evidence-id <uuid>", "evidence 行 id")
|
|
172
|
+
.requiredOption("--availability <a>", `证据可用性(${evidenceAvailabilities.join("|")})`)
|
|
173
|
+
.requiredOption("--checked-at <iso>", "调用方实际检查该证据的时间(ISO 8601)")
|
|
174
|
+
.option("--dry-run", "预览", false)
|
|
175
|
+
.option("--apply", "执行写入", false)
|
|
176
|
+
.action(async (opts) => {
|
|
177
|
+
await withCliErrorBoundary(async () => {
|
|
178
|
+
await withPermissionGates({
|
|
179
|
+
command: "reddit-verification mark-evidence",
|
|
180
|
+
gates: [
|
|
181
|
+
{ resource: "redditAccountVerification", action: "update" },
|
|
182
|
+
],
|
|
183
|
+
teamId: opts.team,
|
|
184
|
+
}, async () => {
|
|
185
|
+
const availability = opts.availability;
|
|
186
|
+
if (!evidenceAvailabilities.includes(availability)) {
|
|
187
|
+
console.error(`--availability 须为 ${evidenceAvailabilities.join("|")}`);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
const body = {
|
|
191
|
+
availability: availability,
|
|
192
|
+
checkedAt: opts.checkedAt,
|
|
193
|
+
};
|
|
194
|
+
if (!assertApplyOrDryRun(opts, {
|
|
195
|
+
command: "reddit-verification mark-evidence",
|
|
196
|
+
danger: "write",
|
|
197
|
+
summary: { evidenceId: opts.evidenceId, ...body },
|
|
198
|
+
})) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const teamId = resolveTeamId(opts.team);
|
|
202
|
+
printResult(await requireClient().patchRedditAccountVerificationEvidence(teamId, opts.evidenceId, body));
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//# sourceMappingURL=register-reddit-account-verification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-reddit-account-verification.js","sourceRoot":"","sources":["../src/register-reddit-account-verification.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geoly-ai/social-hub-cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "social-hub CLI for Social Ops Hub",
|
|
6
6
|
"repository": {
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"commander": "^12.1.0",
|
|
25
|
-
"@geoly-ai/social-hub-authz": "0.0.
|
|
26
|
-
"@geoly-ai/social-hub-sdk": "0.1.
|
|
25
|
+
"@geoly-ai/social-hub-authz": "0.0.20",
|
|
26
|
+
"@geoly-ai/social-hub-sdk": "0.1.8"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^22.10.2",
|
package/skills/integrity.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"fileCount": 1656,
|
|
5
5
|
"files": {
|
|
6
6
|
"README.md": "5246d4ae2712e3e656b101041929183d7ae7f8ea487dacf5854187826ab7c335",
|
|
7
|
-
"manifest.json": "
|
|
7
|
+
"manifest.json": "958d12d518a307be8485b1b99402e2642cbbe2c52d73c0ec384ebeafa929cf8e",
|
|
8
8
|
"reddit-answers-research/SKILL.md": "ab6fd12eeb2fef4dc31a6f3c21a84810d6b5bdb309f130bcdc9eb902f075294a",
|
|
9
9
|
"reddit-answers-research/references/browser-playbook.md": "a8f61d3d43ca93d46dadc8a092a515ddcd32df12fb1d08d334cce2e02709d915",
|
|
10
10
|
"reddit-answers-research/references/report-template.md": "9aa9acf555ba8b2ca503bdbdf5750a5f53c66e19989bf6807fa6200c7317e306",
|
|
@@ -1643,10 +1643,10 @@
|
|
|
1643
1643
|
"social-hub-content-review/SKILL.md": "6d10a84ab56552fd953863b97978bddc0e925e3a2667d64a7a4c51e33a3ddb58",
|
|
1644
1644
|
"social-hub-events-observability/SKILL.md": "f4c17487c64bb1f48381d8d60e97cfa160a94a0f120153b1c0e798a0c7ee7ebe",
|
|
1645
1645
|
"social-hub-graph-compliance/SKILL.md": "2270aeb321733f0318f75da4838ca1ca03996c6cac59e5a12f7152bd1ecdfa26",
|
|
1646
|
-
"social-hub-intelligence/SKILL.md": "
|
|
1646
|
+
"social-hub-intelligence/SKILL.md": "beb25541425dda8639e799b6d8c027dee7e9d4ecd02433b8236ea06280bd82af",
|
|
1647
1647
|
"social-hub-migration/SKILL.md": "1c13f231bb81ae8d242c834eec93a499830481804c66f6dba95922972f56f9ce",
|
|
1648
1648
|
"social-hub-notifications/SKILL.md": "f80f4cf2f9ef0dbf60bd6e8bb4ad7e27dc0ff1fe59f4c7e79e49cc691ed4be6a",
|
|
1649
|
-
"social-hub-openclaw-context/SKILL.md": "
|
|
1649
|
+
"social-hub-openclaw-context/SKILL.md": "97c48f38f1f1a206c3af2af49fcd445a1cd5b78d4a9c805c2456de4ce98fec09",
|
|
1650
1650
|
"social-hub-ops-runtime/SKILL.md": "2fcf257f9c2a36236564fc9056605f2df1d706e0a6f290de68b05ac44890ae3e",
|
|
1651
1651
|
"social-hub-post-review/SKILL.md": "20a0d4886d1fc70397f9f3e5e25672e69608b1cce56971e1b2401e817fbf3cb6",
|
|
1652
1652
|
"social-hub-posts/SKILL.md": "bacb6e8f6880f4f60ad9068c6f7ba07e38fa68560dcd03052b0f82ad064391ab",
|
package/skills/manifest.json
CHANGED
|
@@ -79,6 +79,36 @@ social-hub intelligence posts-import --file posts.json
|
|
|
79
79
|
# 分类=material(标题/正文/flair/作者)变化;指标(score/comments)变不算 updated;陈旧回放不覆盖较新数据。
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
**🔴 强烈建议带上 `rawPayload`(可选字段,但不带就永久丢失 format)**:
|
|
83
|
+
|
|
84
|
+
```jsonc
|
|
85
|
+
// posts.json 的每一项,除上面那 6 个必填字段外,再带:
|
|
86
|
+
"rawPayload": {
|
|
87
|
+
"is_self": true, // 有正文帖 / link 帖
|
|
88
|
+
"is_video": false,
|
|
89
|
+
"is_gallery": false,
|
|
90
|
+
"url": "https://...", // ⛔ 键名必须是 url,不是 link_url(见下)
|
|
91
|
+
"selftext": "..." // 有就带,没有就省略
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**为什么重要**:服务端从 `rawPayload` 派生帖子的 `format`(poll/gallery/native_video/
|
|
96
|
+
image/external_link/self_text),**这个派生不问 LLM、只认原始字段**。不带 rawPayload 时
|
|
97
|
+
format 恒为 `unknown` —— 2026-08-31 实测生产 200 条连续 run **100% 是 unknown**,
|
|
98
|
+
根因就是回灌方没带这些字段(而本文档此前也没说要带)。
|
|
99
|
+
|
|
100
|
+
⚠️ **键名必须用 Reddit 原始名。** `reddit-voc-volume` 脚本输出的是 **`link_url`**,
|
|
101
|
+
而服务端读的是 **`url`** —— 直接把脚本输出整个塞进 rawPayload,external_link 那一档
|
|
102
|
+
**匹配不上、静默落 unknown**,比不带更难查(因为"明明传了")。映射一下再传。
|
|
103
|
+
|
|
104
|
+
⚠️ ⛔ **不要传脚本的加工字段**(`selftext_chars` / `selftext_excerpt` / `body_status` /
|
|
105
|
+
`sample_role` 等):对 format 派生无用,只会让 rawPayload 变大、且看起来像服务端应该认识它们。
|
|
106
|
+
|
|
107
|
+
⚠️ `image` 与 `poll` 两类**仍会是 unknown**(需要 `post_hint` / `poll_data`,
|
|
108
|
+
Arctic Shift 经脚本层后拿不到)。这是"确实没有证据",可接受;
|
|
109
|
+
⛔ **不要为了凑满六值去猜**(比如拿 thumbnail 猜 image)——format 进 revision hash,
|
|
110
|
+
猜错会静默产生一个错误的 revision 并据此重标。
|
|
111
|
+
|
|
82
112
|
**热帖归因**:`watchlistId` 是品牌归因主键(watchlist 挂 brandId);受限主体回灌时该条
|
|
83
113
|
必须能归因到授权板块、watchlist 属本牌、permalink 板块与声明一致,否则该条 rejected
|
|
84
114
|
(不整批拒)。permalink 全局去重(同帖多次回灌折叠为一行)。
|
|
@@ -144,6 +144,37 @@ social-hub query subreddit-candidates -t <team-id> --account A1 --action browse
|
|
|
144
144
|
| `personaPools.brandPools` | 账号品牌绑定及对应 `brand_pools.*` ref 展开结果 |
|
|
145
145
|
| `personaPools.unresolvedRefs` | alias 表无法解析的 ref;正常 seed 后 P01-P57 的 `starter/advanced/pet_pool` 不应出现 |
|
|
146
146
|
| `fallback.reason` | 如 `candidate_pool_exhausted` 须在 Agent 回执说明 |
|
|
147
|
+
| `exhaustion.reason` | **`items` 为空时是哪一类空** —— 用它判「要不要惊动人」,见下 |
|
|
148
|
+
|
|
149
|
+
### `items: []` 到底是哪一类空(`exhaustion`)
|
|
150
|
+
|
|
151
|
+
`items: []` 至少有三种**处置方式完全相反**的含义,**不要**靠再查一次 browse 反推——
|
|
152
|
+
直接读 `exhaustion.reason`:
|
|
153
|
+
|
|
154
|
+
| `reason` | 含义 | 要不要惊动人 |
|
|
155
|
+
| ------------------------------------------- | --------------------------------------------- | -------------------------------- |
|
|
156
|
+
| `all_comment_cooldown` | 近 24h 已在这些板评论过 | **不要**,回执写「已达当日覆盖」 |
|
|
157
|
+
| `all_action_not_permitted` | 结构性:系统共享池不作评论目标 | **不要**,换 `--action browse` |
|
|
158
|
+
| `all_sanctioned` / `all_blocklisted` | 被账号制裁 / 系统 blocklist 拦光 | **要**,人工换板 |
|
|
159
|
+
| `all_tier_filtered` / `all_quota_truncated` | tier 不匹配 / 被分档配额挤掉 | **要**,调参数 |
|
|
160
|
+
| `pool_empty` | 池子真的空 | **要**,修池子数据 |
|
|
161
|
+
| `persona_unavailable` | 没挂人设 / 人设停用 / `--persona-aware false` | **要**,去绑人设 |
|
|
162
|
+
| `resolution_incomplete` | **源集合没查全,说不清** | **要**,按说不清处置 |
|
|
163
|
+
| `mixed_exhausted` | 多个原因并存,不硬选一个 | **要**,看 `terminal` 明细 |
|
|
164
|
+
|
|
165
|
+
🔴 **`complete: false` 时任何 `all_*` 都不成立**,`reason` 会是 `resolution_incomplete`,
|
|
166
|
+
`incompleteReasons` 说明是哪一种(人设 industry key 超 50 的硬门 / 单 key 500 行打满 /
|
|
167
|
+
互动事件扫描打满 / 有未解析的池 ref)。这时**不要**去查制裁列表——
|
|
168
|
+
「没查到」和「查了但都被拦掉」是两回事。
|
|
169
|
+
|
|
170
|
+
- `terminal`:**互斥且守恒**的终局归属,`Σ terminal + returnedBoards === eligibleBeforeFilters`。
|
|
171
|
+
- `filtered`:各闸 raw 命中数,**允许重叠**(一个板可能既命中 blocklist 又命中制裁),
|
|
172
|
+
只用于排障,**不要**拿它选 reason。
|
|
173
|
+
- `returnedBoards` 按板块去重,`returned` 与 `items` 条数对齐(同板不同 scope 占两条)。
|
|
174
|
+
|
|
175
|
+
⛔ **`exhaustion` 不是准入依据。** 它是诊断快照,可能因并发变更或查询上限而滞后。
|
|
176
|
+
能不能去某个板**只由** `items` 与 `items[].allowedActions` 决定。
|
|
177
|
+
(`affinity` 就差点被当成「可去板块」的依据——同一个坑不要换个字段再踩一次。)
|
|
147
178
|
|
|
148
179
|
**Agent 门禁**:
|
|
149
180
|
|