@geoly-ai/social-hub-cli 0.3.18 → 0.3.20
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 +29 -0
- package/dist/cmd-manifest.json +4 -2
- package/dist/content-review.test.js +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -8
- package/dist/index.js.map +1 -1
- package/dist/register-calendar-directives.d.ts +64 -0
- package/dist/register-calendar-directives.d.ts.map +1 -0
- package/dist/register-calendar-directives.js +135 -0
- package/dist/register-calendar-directives.js.map +1 -0
- package/dist/register-calendar-directives.test.d.ts +2 -0
- package/dist/register-calendar-directives.test.d.ts.map +1 -0
- package/dist/register-calendar-directives.test.js +127 -0
- package/dist/register-calendar-directives.test.js.map +1 -0
- package/dist/scrape-output.test.d.ts +2 -0
- package/dist/scrape-output.test.d.ts.map +1 -0
- package/dist/scrape-output.test.js +58 -0
- package/dist/scrape-output.test.js.map +1 -0
- package/package.json +2 -2
- package/skills/README.md +23 -22
- package/skills/manifest.json +6 -1
- package/skills/reddit-content-rewrite/SKILL.md +29 -0
- package/skills/reddit-content-writing/SKILL.md +54 -5
- package/skills/reddit-content-writing/references/phase4-execution-table.md +24 -3
- package/skills/reddit-content-writing/references/phase4-writing.md +123 -3
- package/skills/reddit-content-writing/references/post-writing-templates.md +14 -6
- package/skills/reddit-delivery-check/SKILL.md +39 -6
- package/skills/reddit-delivery-check/references/phase5-delivery.md +7 -1
- package/skills/reddit-matrix.lock.json +10 -10
- package/skills/reddit-phase-brief/SKILL.md +62 -11
- package/skills/reddit-phase-brief/references/brand-SKU-PGC-rules.md +223 -36
- package/skills/reddit-phase-brief/references/phase4-brief-workflow.md +405 -19
- package/skills/reddit-phase-planning/SKILL.md +13 -0
- package/skills/reddit-phase-planning/references/phase4-execution-table.md +16 -2
- package/skills/reddit-phase-planning/references/phase4-planning.md +74 -15
- package/skills/reddit-phase-planning/references/scheduling-decision-procedure.md +386 -0
- package/skills/reddit-phase-research/SKILL.md +7 -1
- package/skills/reddit-phase-research/references/phase01-research.md +93 -29
- package/skills/reddit-strategy-orchestrator/SKILL.md +120 -18
- package/skills/reddit-strategy-shared/SKILL.md +4 -2
- package/skills/reddit-strategy-shared/references/content-diversity-contract.md +26 -5
- package/skills/reddit-strategy-shared/references/content-review-gate.md +48 -1
- package/skills/reddit-strategy-shared/references/context-contract.md +45 -11
- package/skills/reddit-strategy-shared/references/evidence-policy.md +139 -0
- package/skills/reddit-strategy-shared/references/handoff-schemas.md +88 -3
- package/skills/reddit-strategy-shared/references/native-copy-profile.md +207 -0
- package/skills/reddit-strategy-shared/references/path-conventions.md +26 -4
- package/skills/reddit-strategy-shared/references/persona-card-contract.md +210 -0
- package/skills/reddit-strategy-shared/references/prerequisites/README.md +57 -0
- package/skills/reddit-strategy-shared/references/prerequisites/{reddit-master-canvas-agent-prompt-template.md → archive/reddit-master-canvas-agent-prompt-template.md} +7 -0
- package/skills/reddit-strategy-shared/references/prerequisites/{reddit-sop-v2-universal.md → archive/reddit-sop-v2-universal.md} +7 -0
- package/skills/reddit-strategy-shared/references/prerequisites/{reddit-strategy-prerequisites-read.md → archive/reddit-strategy-prerequisites-read.md} +7 -0
- package/skills/reddit-strategy-shared/references/prerequisites/{reddit-strategy-reuse-playbook.md → archive/reddit-strategy-reuse-playbook.md} +7 -0
- package/skills/reddit-strategy-shared/references/subreddit-research-profile.md +514 -0
- package/skills/reddit-strategy-shared/references/version-manifest.md +89 -2
- package/skills/reddit-subreddit-compliance/SKILL.md +28 -1
- package/skills/reddit-voc-volume/matrix-contract.md +16 -1
- package/skills/social-hub-calendar-directives/SKILL.md +548 -0
- package/skills/social-hub-calendar-jobs/SKILL.md +10 -0
- package/skills/social-hub-cli/SKILL.md +2 -0
- package/skills/social-hub-notifications/SKILL.md +7 -0
- package/skills/social-hub-publishing/SKILL.md +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,35 @@ 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.20] - 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- 发布日历指令端到端接线(Block 5) + 封死 D1 旁路
|
|
12
|
+
- 发布日历指令的 SDK/CLI/skills 交付面(Block 6)
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- response mock 的 rubricVersion 跟到 content-review.v5
|
|
17
|
+
|
|
18
|
+
### Documentation
|
|
19
|
+
|
|
20
|
+
- 写作侧 matrix skill 对齐冻结契约(块 2d)+ 删掉 WeaklyVerified
|
|
21
|
+
|
|
22
|
+
## [0.3.19] - 2026-08-14
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- classify outcomes instead of reporting 2xx login pages as success
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- align AUTHZ_POLICY_VERSION with package version
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- rebuild reddit matrix SOP around evidence and decision gates
|
|
35
|
+
|
|
7
36
|
## [0.3.18] - 2026-08-13
|
|
8
37
|
|
|
9
38
|
### Added
|
package/dist/cmd-manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-08-
|
|
3
|
-
"cliVersion": "0.3.
|
|
2
|
+
"generatedAt": "2026-08-18T09:08:50.530Z",
|
|
3
|
+
"cliVersion": "0.3.20",
|
|
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",
|
package/dist/index.d.ts
CHANGED
|
@@ -22,5 +22,29 @@ export declare function orchestrateVocAcquire(client: VocAcquireClient, params:
|
|
|
22
22
|
exitCode: 0 | 1 | 2;
|
|
23
23
|
output: Record<string, unknown>;
|
|
24
24
|
}>;
|
|
25
|
+
/**
|
|
26
|
+
* 业务失败(HTTP 200 + ok:false)的人类可读摘要:抓到了页面,但**不是正文**。
|
|
27
|
+
* 结论(outcome) + 阶段 + provider request id 全部打出来,别再让人对着通用错误猜。
|
|
28
|
+
*/
|
|
29
|
+
export declare function formatScrapeFailure(res: {
|
|
30
|
+
outcome: string;
|
|
31
|
+
finalUrl?: string;
|
|
32
|
+
targetStatusCode?: number | null;
|
|
33
|
+
failureStage?: string | null;
|
|
34
|
+
providerRequestId?: string | null;
|
|
35
|
+
requestId?: string | null;
|
|
36
|
+
attempts?: number;
|
|
37
|
+
retryAfterMs?: number | null;
|
|
38
|
+
classifierVersion?: string;
|
|
39
|
+
classificationEvidence?: Array<{
|
|
40
|
+
ruleId: string;
|
|
41
|
+
signal: string;
|
|
42
|
+
}>;
|
|
43
|
+
}): string;
|
|
44
|
+
/**
|
|
45
|
+
* 技术层失败(429/502/504 等)的摘要:把 provider typed code / 失败阶段 /
|
|
46
|
+
* request id 从 `details` 里挖出来,取代以前的「Scrape service returned HTTP 500」。
|
|
47
|
+
*/
|
|
48
|
+
export declare function formatScrapeError(e: unknown): string;
|
|
25
49
|
export { program };
|
|
26
50
|
//# sourceMappingURL=index.d.ts.map
|
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;AA4DpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA2gF9B,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
|
|
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 ---
|
|
@@ -3272,6 +3300,56 @@ intel
|
|
|
3272
3300
|
const scrapeCmd = program
|
|
3273
3301
|
.command("scrape")
|
|
3274
3302
|
.description("通用网页抓取(Reddit .json 直连 / HTML 经 Firecrawl)");
|
|
3303
|
+
/**
|
|
3304
|
+
* 业务失败(HTTP 200 + ok:false)的人类可读摘要:抓到了页面,但**不是正文**。
|
|
3305
|
+
* 结论(outcome) + 阶段 + provider request id 全部打出来,别再让人对着通用错误猜。
|
|
3306
|
+
*/
|
|
3307
|
+
export function formatScrapeFailure(res) {
|
|
3308
|
+
const evidence = (res.classificationEvidence ?? [])
|
|
3309
|
+
.map((e) => `${e.ruleId}(${e.signal})`)
|
|
3310
|
+
.join(", ");
|
|
3311
|
+
const parts = [
|
|
3312
|
+
`scrape 未取得正文:outcome=${res.outcome}`,
|
|
3313
|
+
`targetStatus=${res.targetStatusCode ?? "null"}`,
|
|
3314
|
+
`finalUrl=${res.finalUrl ?? "null"}`,
|
|
3315
|
+
`stage=${res.failureStage ?? "null"}`,
|
|
3316
|
+
`attempts=${res.attempts ?? 1}`,
|
|
3317
|
+
];
|
|
3318
|
+
if (res.retryAfterMs != null)
|
|
3319
|
+
parts.push(`retryAfterMs=${res.retryAfterMs}`);
|
|
3320
|
+
parts.push(`requestId=${res.requestId ?? "null"}`);
|
|
3321
|
+
parts.push(`providerRequestId=${res.providerRequestId ?? "null"}`);
|
|
3322
|
+
if (res.classifierVersion)
|
|
3323
|
+
parts.push(`classifier=${res.classifierVersion}`);
|
|
3324
|
+
if (evidence)
|
|
3325
|
+
parts.push(`evidence=[${evidence}]`);
|
|
3326
|
+
return parts.join(" ");
|
|
3327
|
+
}
|
|
3328
|
+
/**
|
|
3329
|
+
* 技术层失败(429/502/504 等)的摘要:把 provider typed code / 失败阶段 /
|
|
3330
|
+
* request id 从 `details` 里挖出来,取代以前的「Scrape service returned HTTP 500」。
|
|
3331
|
+
*/
|
|
3332
|
+
export function formatScrapeError(e) {
|
|
3333
|
+
const err = e;
|
|
3334
|
+
const base = err?.message ?? String(e);
|
|
3335
|
+
const d = err?.details;
|
|
3336
|
+
if (!d?.outcome)
|
|
3337
|
+
return base;
|
|
3338
|
+
const p = d.diagnostics?.provider ?? {};
|
|
3339
|
+
const x = d.diagnostics?.execution ?? {};
|
|
3340
|
+
return [
|
|
3341
|
+
base,
|
|
3342
|
+
`code=${err.code ?? "null"}`,
|
|
3343
|
+
`outcome=${d.outcome}`,
|
|
3344
|
+
`stage=${x.failureStage ?? "null"}`,
|
|
3345
|
+
`providerStatus=${p.providerStatusCode ?? "null"}`,
|
|
3346
|
+
`providerErrorCode=${p.providerErrorCode ?? "null"}`,
|
|
3347
|
+
`providerRequestId=${p.providerRequestId ?? "null"}`,
|
|
3348
|
+
`providerScrapeId=${p.providerScrapeId ?? "null"}`,
|
|
3349
|
+
`attempts=${x.attemptCount ?? 1}`,
|
|
3350
|
+
...(x.retryAfterMs != null ? [`retryAfterMs=${x.retryAfterMs}`] : []),
|
|
3351
|
+
].join(" ");
|
|
3352
|
+
}
|
|
3275
3353
|
scrapeCmd
|
|
3276
3354
|
.command("url <url>")
|
|
3277
3355
|
.description("POST /v1/system/scrape —— 抓取任意网页(Reddit .json 或 HTML)")
|
|
@@ -3285,13 +3363,25 @@ scrapeCmd
|
|
|
3285
3363
|
.map((s) => s.trim())
|
|
3286
3364
|
.filter(Boolean)
|
|
3287
3365
|
: undefined;
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3366
|
+
try {
|
|
3367
|
+
const res = await requireClient().scrapeUrl({
|
|
3368
|
+
url,
|
|
3369
|
+
formats,
|
|
3370
|
+
mode: opts.redditJson ? "reddit-json" : undefined,
|
|
3371
|
+
timeoutMs: opts.timeout ? Number(opts.timeout) : undefined,
|
|
3372
|
+
});
|
|
3373
|
+
console.log(JSON.stringify(res, null, 2));
|
|
3374
|
+
if (!res.ok) {
|
|
3375
|
+
// 业务失败(2xx 登录墙/验证码/空正文/目标站限流…):HTTP 是 200,但**不是正文**。
|
|
3376
|
+
// 退出码必须非零,否则 shell/agent 会把「抓到登录页」当成抓取成功。
|
|
3377
|
+
console.error(formatScrapeFailure(res));
|
|
3378
|
+
process.exit(2);
|
|
3379
|
+
}
|
|
3380
|
+
}
|
|
3381
|
+
catch (e) {
|
|
3382
|
+
console.error(formatScrapeError(e));
|
|
3383
|
+
process.exit(1);
|
|
3384
|
+
}
|
|
3295
3385
|
});
|
|
3296
3386
|
scrapeCmd
|
|
3297
3387
|
.command("status")
|