@geoly-ai/social-hub-cli 0.2.23 → 0.2.25
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 +23 -0
- package/dist/client.d.ts +21 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +64 -1
- package/dist/client.js.map +1 -1
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +123 -0
- package/dist/client.test.js.map +1 -0
- package/dist/cmd-manifest.json +23 -2
- package/dist/cmd-manifest.test.js +4 -0
- package/dist/cmd-manifest.test.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -2
- package/dist/index.js.map +1 -1
- package/dist/permission-runner.d.ts +21 -4
- package/dist/permission-runner.d.ts.map +1 -1
- package/dist/permission-runner.js +36 -9
- package/dist/permission-runner.js.map +1 -1
- package/dist/permission-runner.test.js +76 -0
- package/dist/permission-runner.test.js.map +1 -1
- package/dist/permissions-gates-content-classification.d.ts +8 -0
- package/dist/permissions-gates-content-classification.d.ts.map +1 -0
- package/dist/permissions-gates-content-classification.js +40 -0
- package/dist/permissions-gates-content-classification.js.map +1 -0
- package/dist/permissions-gates-subreddit-style.d.ts +10 -0
- package/dist/permissions-gates-subreddit-style.d.ts.map +1 -0
- package/dist/permissions-gates-subreddit-style.js +66 -0
- package/dist/permissions-gates-subreddit-style.js.map +1 -0
- package/dist/permissions-gates-subreddit-style.test.d.ts +2 -0
- package/dist/permissions-gates-subreddit-style.test.d.ts.map +1 -0
- package/dist/permissions-gates-subreddit-style.test.js +44 -0
- package/dist/permissions-gates-subreddit-style.test.js.map +1 -0
- package/dist/permissions.d.ts +10 -0
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +11 -2
- package/dist/permissions.js.map +1 -1
- package/dist/register-content-classification.d.ts +14 -0
- package/dist/register-content-classification.d.ts.map +1 -0
- package/dist/register-content-classification.js +181 -0
- package/dist/register-content-classification.js.map +1 -0
- package/dist/register-content-classification.test.d.ts +2 -0
- package/dist/register-content-classification.test.d.ts.map +1 -0
- package/dist/register-content-classification.test.js +43 -0
- package/dist/register-content-classification.test.js.map +1 -0
- package/dist/register-extensions.d.ts.map +1 -1
- package/dist/register-extensions.js +1 -0
- package/dist/register-extensions.js.map +1 -1
- package/dist/register-subreddit-post-style.d.ts +8 -0
- package/dist/register-subreddit-post-style.d.ts.map +1 -0
- package/dist/register-subreddit-post-style.js +161 -0
- package/dist/register-subreddit-post-style.js.map +1 -0
- package/dist/register-subreddit-style-actions.test.d.ts +2 -0
- package/dist/register-subreddit-style-actions.test.d.ts.map +1 -0
- package/dist/register-subreddit-style-actions.test.js +295 -0
- package/dist/register-subreddit-style-actions.test.js.map +1 -0
- package/dist/register-subreddit-style.d.ts +57 -0
- package/dist/register-subreddit-style.d.ts.map +1 -0
- package/dist/register-subreddit-style.js +418 -0
- package/dist/register-subreddit-style.js.map +1 -0
- package/dist/register-subreddit-style.test.d.ts +2 -0
- package/dist/register-subreddit-style.test.d.ts.map +1 -0
- package/dist/register-subreddit-style.test.js +183 -0
- package/dist/register-subreddit-style.test.js.map +1 -0
- package/dist/update-check.d.ts +15 -0
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +106 -3
- package/dist/update-check.js.map +1 -1
- package/dist/update-check.test.js +71 -2
- package/dist/update-check.test.js.map +1 -1
- package/package.json +3 -3
- package/skills/README.md +1 -0
- package/skills/manifest.json +6 -1
- package/skills/social-hub-accounts/SKILL.md +32 -0
- package/skills/social-hub-calendar-jobs/SKILL.md +1 -1
- package/skills/social-hub-cli/SKILL.md +1 -0
- package/skills/social-hub-content-classification/SKILL.md +92 -0
- package/skills/social-hub-content-review/SKILL.md +31 -4
- package/skills/social-hub-ops-runtime/SKILL.md +19 -1
- package/skills/social-hub-post-review/SKILL.md +38 -12
- package/skills/social-hub-style-profiles/SKILL.md +126 -0
|
@@ -41,30 +41,56 @@ social-hub content post-review -t <team-id> -j '{
|
|
|
41
41
|
|
|
42
42
|
## 两种审核模式
|
|
43
43
|
|
|
44
|
-
| 模式
|
|
45
|
-
|
|
|
46
|
-
| `ContentOnly`
|
|
47
|
-
| `AccountBound` | 传真实 `accountId` | 在内容审核外验证账号 persona/style 与品牌适配;最终发布前使用
|
|
44
|
+
| 模式 | 请求 | 结论边界 |
|
|
45
|
+
| -------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| `ContentOnly` | 省略 `accountId` | 响应为 `reviewContext.accountMode=persona_less`;可审核标题正文、软广、AI 结构、规则证据和发帖动机,但不能声称账号人设适配已完成 |
|
|
47
|
+
| `AccountBound` | 传真实 `accountId` | 在内容审核外验证账号 persona/style 与品牌适配;最终发布前使用 |
|
|
48
48
|
|
|
49
49
|
ContentOnly 的 `completed/pass` 是内容结论,不是最终发布资格。应标记
|
|
50
50
|
`AccountBindingStatus: Pending`、`ReadyForDelivery: No`;
|
|
51
51
|
`accountCandidateFeedback` 只做账号候选建议,不阻断内容审核。
|
|
52
52
|
`stage` 仅在值来自有效账号上下文时传;不确定就省略。
|
|
53
53
|
|
|
54
|
+
### brandContext(可选品牌上下文)
|
|
55
|
+
|
|
56
|
+
请求可带 `brandContext`(可省略),三种入口任选其一:
|
|
57
|
+
|
|
58
|
+
| 键 | 语义 |
|
|
59
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `brandKey` | registry canonical key 或 alias |
|
|
61
|
+
| `campaignId` | legacy 归因入口:Hub 解 campaignId→campaign.brandId→registry brandKey |
|
|
62
|
+
| `brandId` | **系统级 brand `brands.id`(来自 `brands system-list`,不是 `brand_registry.id`)**,与 publishing 新流程对齐 |
|
|
63
|
+
|
|
64
|
+
`brandId` 是新流程入口(与 social-hub-publishing「新流程用系统级 brandId、campaignId 仅
|
|
65
|
+
legacy 归因」一致),**persona-less 与账号路径都支持**。生命周期语义按路径不同:persona-less
|
|
66
|
+
active 优先、否则回退最新 retired;**账号路径 active-only**(无 active 映射 → 422
|
|
67
|
+
`BRAND_REGISTRY_METADATA_MISSING`)。账号路径品牌上下文**仅账号已绑 persona 时才解析**,未绑
|
|
68
|
+
persona 则三入口一律静默忽略。多个入口解析到不同 canonical registry → 409 冲突。
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# persona-less(无 accountId)用系统级 brandId:
|
|
72
|
+
social-hub content post-review -t <team-id> -j '{
|
|
73
|
+
"title": "<帖子标题>",
|
|
74
|
+
"body": "<帖子正文>",
|
|
75
|
+
"subreddit": "buildapc",
|
|
76
|
+
"brandContext": { "brandId": "<brands.id from `brands system-list`>" }
|
|
77
|
+
}'
|
|
78
|
+
```
|
|
79
|
+
|
|
54
80
|
Reddit matrix 的发布闸门比本通用 skill 更严格:`degraded` 或 Hub
|
|
55
81
|
不可用只能诊断,不能替代 Hub pass。
|
|
56
82
|
|
|
57
83
|
## 七维口径(0-100,服务端计分,模型自报分仅对照)
|
|
58
84
|
|
|
59
|
-
| 维度 | 判什么
|
|
60
|
-
| --------------------------- |
|
|
61
|
-
| `title_body_fit` | 标题承诺 vs 正文兑现(bait-and-switch 低分)
|
|
62
|
-
| `clickbait_or_manipulation` | 标题党/情绪操纵/虚假紧迫(<35 单维红线 block)
|
|
63
|
-
| `promotion_risk` | 软广/导流/品牌推销痕迹(<40 单维红线 block)
|
|
64
|
-
| `subreddit_rule_fit` | 只按提供的版规快照判;**没传版规 → 该维标 insufficient_context 并被剔除权重,不伪造结论**
|
|
65
|
-
| `ai_structural_tone` | 小标题排比/总分总/清单腔等 AI 结构感
|
|
85
|
+
| 维度 | 判什么 |
|
|
86
|
+
| --------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
87
|
+
| `title_body_fit` | 标题承诺 vs 正文兑现(bait-and-switch 低分) |
|
|
88
|
+
| `clickbait_or_manipulation` | 标题党/情绪操纵/虚假紧迫(<35 单维红线 block) |
|
|
89
|
+
| `promotion_risk` | 软广/导流/品牌推销痕迹(<40 单维红线 block) |
|
|
90
|
+
| `subreddit_rule_fit` | 只按提供的版规快照判;**没传版规 → 该维标 insufficient_context 并被剔除权重,不伪造结论** |
|
|
91
|
+
| `ai_structural_tone` | 小标题排比/总分总/清单腔等 AI 结构感 |
|
|
66
92
|
| `persona_consistency` | AccountBound 时判断账号人设;ContentOnly/persona_less 时只能标 NotAssessed/弱验证,不得声称已验证 |
|
|
67
|
-
| `natural_post_intent` | 真人为何发这帖(无动机的"分享产品体验"低分)
|
|
93
|
+
| `natural_post_intent` | 真人为何发这帖(无动机的"分享产品体验"低分) |
|
|
68
94
|
|
|
69
95
|
## 判定规则
|
|
70
96
|
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: social-hub-style-profiles
|
|
3
|
+
description: >-
|
|
4
|
+
Social Hub 板块画像/帖子标注:style-profiles list/get/active/propose/approve/reject/cancel/retire
|
|
5
|
+
(系统级四眼治理)与 subreddit-annotations list/upsert(团队维度人工标注)。
|
|
6
|
+
用户要查/审板块风格画像、处理画像提案、给 Reddit 帖打 style_fit/brand_friendliness 标注时用本 skill。
|
|
7
|
+
不用于账号级 style-marks/curator(用 social-hub-style-curator)、运营板块池 CRUD(用 social-hub-subreddit-pools)。
|
|
8
|
+
metadata:
|
|
9
|
+
cliVersion: ">=0.2.24"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# social-hub-style-profiles
|
|
13
|
+
|
|
14
|
+
> **前置条件:** 先阅读 [`../social-hub-shared/SKILL.md`](../social-hub-shared/SKILL.md),
|
|
15
|
+
> 确认已 `auth login`(Device Code 的 CLI **user token**)并 `context use <team-id>`。
|
|
16
|
+
|
|
17
|
+
板块画像(`subreddit_style_profiles`)是系统级共享知识库:worker 定时从板块热帖用 LLM 起草,
|
|
18
|
+
**恒以 `proposed` 入库**,必须人工四眼审批后 `approved` 才生效(供发帖/评论审核 enrich 引用)。
|
|
19
|
+
帖子标注(`subreddit_post_annotations`)是 team 维度的人工研判(`style_fit` / `brand_friendliness`,1-5 分)。
|
|
20
|
+
|
|
21
|
+
## 职责边界
|
|
22
|
+
|
|
23
|
+
| 做 | 不做 |
|
|
24
|
+
| -------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
25
|
+
| 画像读面 list/get/active、提案 propose、四眼审批流转 | 账号级风格资产(style-marks / curator run → social-hub-style-curator) |
|
|
26
|
+
| 帖子 style_fit / brand_friendliness 人工标注 list/upsert | 运营板块池 catalog/aliases/tier rules(→ social-hub-subreddit-pools) |
|
|
27
|
+
|
|
28
|
+
## 关键约束(先读再操作)
|
|
29
|
+
|
|
30
|
+
- **写操作全部 user-only**:propose/approve/reject/cancel/retire/upsert 拒绝 API Key(CLI 本地先拒,API 侧同样 403)。
|
|
31
|
+
必须用 `social-hub auth login` 拿到的 CLI token 执行。
|
|
32
|
+
- **角色**:画像写只 manager/admin;标注 supervisor 及以上可写、senior/internal 只读、client 恒拒。
|
|
33
|
+
- **四眼审批**:提案人本人不能 approve(409 `SELF_APPROVE`)——propose 和 approve 要换人操作。
|
|
34
|
+
- **If-Match 乐观锁**:approve/reject/cancel/retire 必须带 `If-Match: <rowVersion>`。
|
|
35
|
+
CLI 缺省自动 `GET` 一次取当前 `profile.rowVersion` 带上;也可 `--row-version <token>` 显式传(接受裸 token 或带引号 ETag)。
|
|
36
|
+
自动 GET 只是便利,竞态保护在服务端锁内:409 `PROFILE_STALE` 表示已被他人变更,**重新 get 核对后再重试**(CLI 不会自动重试)。
|
|
37
|
+
- **cancel 仅提案人本人**(worker/LLM 起草的画像 `proposedByUserId` 为空,不可 cancel,由 manager/admin 用 `reject`)。
|
|
38
|
+
|
|
39
|
+
## 画像读面
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
social-hub style-profiles list [--subreddit <name>] [--scope global|brand] \
|
|
43
|
+
[--brand <uuid>] [--status proposed,approved] [-n 50] [--offset 0]
|
|
44
|
+
social-hub style-profiles get --id <profile-uuid> # 响应 profile.rowVersion = 写操作 If-Match 值
|
|
45
|
+
social-hub style-profiles active --subreddit <name> [--brand <uuid>]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`active` 语义:传 `--brand` 优先返回该品牌的 approved override,无 override 回退 global;不传只查 global。
|
|
49
|
+
**没有生效画像是正常状态**,输出 `{ "profile": null, "versionToken": null }`,退出码 0。
|
|
50
|
+
|
|
51
|
+
## 画像四眼工作流
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# 1) 提案人:起草新画像版本(恒 proposed 入库;profile 至少含 tone 或非空 stylePoints/taboos)
|
|
55
|
+
social-hub style-profiles propose -j '{
|
|
56
|
+
"scope": "global",
|
|
57
|
+
"subreddit": "bouldering",
|
|
58
|
+
"profile": {
|
|
59
|
+
"tone": "laid-back, supportive, anti-gatekeeping",
|
|
60
|
+
"stylePoints": ["share genuine progress stories", "beta questions welcome"],
|
|
61
|
+
"taboos": ["humble-bragging", "brand shilling"]
|
|
62
|
+
},
|
|
63
|
+
"summary": "r/bouldering 新手工友好社区画像"
|
|
64
|
+
}' --apply # scope=brand 时必须带 "brandId"
|
|
65
|
+
|
|
66
|
+
# 2) 另一位 manager/admin:审批(自动 GET 取 rowVersion;--dry-run 先看 status/版本/提案人)
|
|
67
|
+
social-hub style-profiles approve --id <profile-uuid> --dry-run
|
|
68
|
+
social-hub style-profiles approve --id <profile-uuid> --apply
|
|
69
|
+
|
|
70
|
+
# 审批人驳回(仅 proposed;落 retire_reason=rejected:<reason>)
|
|
71
|
+
social-hub style-profiles reject --id <profile-uuid> --reason "taboos 与实际版规不符" --apply
|
|
72
|
+
|
|
73
|
+
# 提案人本人撤回(仅 proposed 且本人;worker/LLM 提案请用 reject)
|
|
74
|
+
social-hub style-profiles cancel --id <profile-uuid> --reason "重新整理后再提" --apply
|
|
75
|
+
|
|
76
|
+
# 停用已生效画像(仅 approved)
|
|
77
|
+
social-hub style-profiles retire --id <profile-uuid> --reason "画像过时,等新版本" --apply
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
所有写命令都遵循 `--dry-run` 预览 / `--apply` 执行约定;dry-run 会展示将写入的摘要
|
|
81
|
+
(流转命令含自动取得的 `rowVersion` 与当前 `status/version/proposedByUserId`)。
|
|
82
|
+
|
|
83
|
+
## 帖子标注(team 维度)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
social-hub subreddit-annotations list [-t <team-id>] [--subreddit <name>] \
|
|
87
|
+
[--permalink <url>] [--type style_fit|brand_friendliness] [--brand <uuid>] \
|
|
88
|
+
[--source llm|human] [-n 50] [--offset 0]
|
|
89
|
+
|
|
90
|
+
social-hub subreddit-annotations upsert [-t <team-id>] \
|
|
91
|
+
--subreddit bouldering \
|
|
92
|
+
--permalink "https://www.reddit.com/r/bouldering/comments/abc123/some_title/" \
|
|
93
|
+
--type style_fit --score 4 \
|
|
94
|
+
--label "tone-match" --note "高赞评论语气与画像一致" --apply
|
|
95
|
+
|
|
96
|
+
# brand_friendliness 必须带 --brand;style_fit 禁带 --brand
|
|
97
|
+
social-hub subreddit-annotations upsert -t <team-id> \
|
|
98
|
+
--subreddit bouldering --permalink "https://old.reddit.com/r/bouldering/comments/xyz789/t/" \
|
|
99
|
+
--type brand_friendliness --brand <brand-uuid> --score 2 \
|
|
100
|
+
--note "对品牌提及敏感,慎用" --apply
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- **list 返回本团队行+全局行**:响应里 `teamId=null` 是系统全局行,当前 team UUID 是团队行。
|
|
104
|
+
- **upsert 是 last-write-wins**:同源(`human`)同 identity(team+subreddit+permalink+type+brand)重复提交会覆盖既有标注,
|
|
105
|
+
服务端同事务落 before/after 审计。`source` 由服务端固定 `human` 并绑定当前用户。
|
|
106
|
+
- **score 方向**:1=最差/敌意 … 5=最佳/友好。
|
|
107
|
+
- **permalink** 必须是 reddit.com 的 `/r/<sub>/comments/` 帖链接(https,www/old/np 等子域均可)。
|
|
108
|
+
- **`--scope global`**(默认 `team`)写系统共享知识库,另需 manager/admin 的画像治理权限,危险级升 admin。
|
|
109
|
+
|
|
110
|
+
## API
|
|
111
|
+
|
|
112
|
+
- `GET/POST /v1/system/subreddit-style-profiles`(list / propose)
|
|
113
|
+
- `GET /v1/system/subreddit-style-profiles/active`、`GET .../:id`
|
|
114
|
+
- `POST /v1/system/subreddit-style-profiles/:id/approve|reject|cancel|retire`(If-Match 必填)
|
|
115
|
+
- `GET/POST /v1/teams/:teamId/subreddit-post-annotations`(list / upsert 走 `.../upsert`)
|
|
116
|
+
|
|
117
|
+
权限资源:`subredditStyleProfile`(画像读写 + 全局标注的第二道 gate)、`subredditPostAnnotation`(标注读写)。
|
|
118
|
+
|
|
119
|
+
## 常见排障
|
|
120
|
+
|
|
121
|
+
- `PROFILE_IF_MATCH_REQUIRED` / `PROFILE_IF_MATCH_INVALID`(400):写操作没带 If-Match。CLI 会自动 GET 带上;显式 `--row-version` 时检查 token 是否完整(`ssp:<id>:<status>:<updatedAtISO>`)。
|
|
122
|
+
- `PROFILE_STALE`(409):画像已被他人变更。重新 `style-profiles get --id <id>` 核对最新 `rowVersion` 与内容后再重试。
|
|
123
|
+
- `SELF_APPROVE`(409):四眼约束,提案人本人不能 approve,换另一位 manager/admin。
|
|
124
|
+
- `ILLEGAL_TRANSITION`(409):状态机不允许(如 reject 一个已 approved 的画像;cancel/reject 只接受 proposed,retire 只接受 approved)。
|
|
125
|
+
- `403 subreddit style profile management requires an authenticated user`:用了 API Key。改 `social-hub auth login` 的 CLI token。
|
|
126
|
+
- 标注 upsert 403 但角色看似够:API 要求 create+update 双动作;`--scope global` 另需 `subredditStyleProfile:update`(manager/admin)。
|