@geoly-ai/social-hub-sdk 0.1.15 → 0.1.17

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/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { ConfirmSubredditRestrictionInput, CreateSubredditRestrictionInput, ListSubredditRestrictionsParams, ListSubredditRestrictionsResponse, OpsBlockedJobAck, OpsBlockedReceipt, ReportSubredditRestrictionInput, ReportSubredditRestrictionResponse, RevokeSubredditRestrictionInput, SubredditRestriction, SubredditRestrictionCheckResult, SubredditRestrictionFanoutParams, SubredditRestrictionFanoutResponse } from "./subreddit-restrictions.js";
2
+ export * from "./subreddit-restrictions.js";
1
3
  /**
2
4
  * 「返回了不完整结果、但看起来像完整的」这一族缺陷的统一探针。
3
5
  *
@@ -267,6 +269,15 @@ export type AccountPoolsResponse = {
267
269
  personaPools?: unknown;
268
270
  systemPools?: unknown;
269
271
  fallback?: unknown;
272
+ /**
273
+ * 分页方案 B8b:本次生效的 limit / 返回条数 / 是否被截断(配额、limit 或单 key 行数上限)。
274
+ * 该端点没有 offset。配额 / limit 截断可调大 limit 或收窄 industry/tier;单 key 行数上限是
275
+ * 上游固定帽,调 limit 补不全,只能收窄 industry 或人工处理。
276
+ * 旧服务端不返回这三个字段。
277
+ */
278
+ selectionLimit?: number;
279
+ returned?: number;
280
+ truncated?: boolean;
270
281
  };
271
282
  export type DeviceCodeResponse = {
272
283
  device_code: string;
@@ -382,6 +393,113 @@ export type ContentReviewRequestInput = {
382
393
  /** 第几次送审;服务端强制上限 2(防重写循环)。 */
383
394
  attempt?: 1 | 2;
384
395
  traceId?: string;
396
+ } & ReviewScopeDeclaration;
397
+ /**
398
+ * ── Aporro Native Copy:四象限声明 / 逐稿 Card / acceptance 回执(手抄镜像)──
399
+ *
400
+ * 🔴 SDK **不能** re-export contracts(contracts 是 `private: true`,直接引用会生成
401
+ * 消费者装不上的 `.d.ts`),所以这组类型是手抄的,真源在
402
+ * `packages/contracts/src/review-scope.ts` 与 `knowledge-boundary.ts`。
403
+ * 手抄就会漂移 —— `index.test.ts` 里有对应的 `expectTypeOf` 编译期锁。
404
+ *
405
+ * 线上请求体一直是**原样透传**的(服务端 zod 校验);补这组类型之前,TS 调用方
406
+ * 传这几个字段会在编译期就被 SDK 自己的类型拦下 —— 能力在服务端,SDK 这层把门关上了。
407
+ */
408
+ export type ReviewAccountBinding = "account_bound" | "persona_less";
409
+ export type ReviewBrandTreatment = "managed_brand" | "organic";
410
+ export type ReviewScopeSource = "declared" | "legacy_derived";
411
+ export type ReviewBrandResolutionStatus = "resolved" | "none" | "unresolved";
412
+ export type ReviewAcceptanceProfile = "default" | "native_copy";
413
+ /** 调用方**声明**的象限(意图,不是事实)。 */
414
+ export type ReviewRequestedScope = {
415
+ accountBinding: ReviewAccountBinding;
416
+ brandTreatment: ReviewBrandTreatment;
417
+ };
418
+ /** 服务端解析后的权威象限 + 可用性事实。 */
419
+ export type ReviewResolvedScope = {
420
+ accountBinding: ReviewAccountBinding;
421
+ brandTreatment: ReviewBrandTreatment;
422
+ /** ⚠️ `legacy_derived` 不满足 Native Copy profile,也不满足发布 gate。 */
423
+ scopeSource: ReviewScopeSource;
424
+ /** `unresolved` 是覆盖态:声明 organic 却识别到已登记品牌 → 转人工,不豁免。 */
425
+ brandResolutionStatus: ReviewBrandResolutionStatus;
426
+ brandResolutionDetail: {
427
+ detectedBrandId: string | null;
428
+ detectedBrandKey: string | null;
429
+ reason: string;
430
+ resolverVersion: string;
431
+ } | null;
432
+ personaVoiceEvidenceAvailable: boolean;
433
+ knowledgeContextAvailable: boolean;
434
+ rulesEvidenceAvailable: boolean;
435
+ styleProfileAvailable: boolean;
436
+ };
437
+ /**
438
+ * 逐稿知识边界(Persona Card)。服务端内容寻址后固化,worker 发布前复审时完整恢复。
439
+ * ⚠️ 当前 **不影响 verdict**:`knowledge_boundary_consistency` 维度尚未激活
440
+ * (方案块 2a 口径下的 v5 原子提交),本字段现阶段只留痕、只决定 Gate 0 是否齐备。
441
+ */
442
+ export type KnowledgeBoundaryContextInput = {
443
+ schemaVersion: 1;
444
+ knowledgeAccess: "research" | "owned" | "used" | "observed" | "supplied_by_brand";
445
+ /** 最多 4 项。 */
446
+ permittedExperienceClaims: Array<"ownership" | "delivery" | "wear" | "service">;
447
+ postingWhy: string;
448
+ knows: string[];
449
+ doesNotKnow: string[];
450
+ attentionFocus?: string;
451
+ questionIntent?: string;
452
+ permittedFactVersionIds?: string[];
453
+ archetypeLabels?: string[];
454
+ };
455
+ export type KnowledgeContextRef = {
456
+ id: string;
457
+ hash: string;
458
+ schemaVersion: number;
459
+ };
460
+ /** 本次生效的 acceptance profile(可能被降级,原因在 downgradedReason)。 */
461
+ export type ResolvedAcceptanceProfile = {
462
+ profile: ReviewAcceptanceProfile;
463
+ policyVersion: string;
464
+ /** 非 null = 请求了 native_copy 但被降级(`legacy_derived_scope` / `incomplete_gate0`)。 */
465
+ downgradedReason: string | null;
466
+ };
467
+ export type ReviewProfileVerdictDetail = {
468
+ profile: ReviewAcceptanceProfile;
469
+ policyVersion: string;
470
+ verdict: "pass" | "revise" | "block" | "required_missing" | "not_applicable";
471
+ findings: Array<{
472
+ rule: string;
473
+ dimension: string | null;
474
+ threshold: number | null;
475
+ actual: number | null;
476
+ detail: string | null;
477
+ }>;
478
+ missingGateItems: string[];
479
+ };
480
+ /**
481
+ * 审核响应里的 Aporro 回执(帖/评共用)。全部可选:旧 pod / 旧 engine 下服务端会
482
+ * fail-closed **省略**它们,调用方应把「字段不在」读成「没有这项能力」,⛔ 不是「通过」。
483
+ */
484
+ export type ReviewScopeReceipt = {
485
+ resolvedScope?: ReviewResolvedScope;
486
+ capabilities?: string[];
487
+ knowledgeContextRef?: KnowledgeContextRef | null;
488
+ resolvedAcceptanceProfile?: ResolvedAcceptanceProfile;
489
+ profileVerdictDetail?: ReviewProfileVerdictDetail | null;
490
+ };
491
+ /** 审核请求里的 Aporro 声明字段(帖/评共用)。 */
492
+ export type ReviewScopeDeclaration = {
493
+ requestedScope?: ReviewRequestedScope;
494
+ /**
495
+ * ⚠️ 两类入口约束**不同**(Codex 块 5 P1 纠正了我原来写的「需同时声明」):
496
+ * - 同步 `postReview` / `contentReview`:三个字段各自可选,不要求成对;只传 Card
497
+ * 不传 requestedScope 时服务端照收,按 `legacy_derived` 象限审(不满足 native_copy)。
498
+ * - 异步 `createReviewTarget`:Card 与 requestedAcceptanceProfile **必须**伴随
499
+ * requestedScope,否则 400 —— 因为只有声明分支会被固化,不拦就是「接受后丢数据」。
500
+ */
501
+ knowledgeContext?: KnowledgeBoundaryContextInput;
502
+ requestedAcceptanceProfile?: ReviewAcceptanceProfile;
385
503
  };
386
504
  export type ContentReviewResponse = {
387
505
  reviewId: string;
@@ -406,7 +524,7 @@ export type ContentReviewResponse = {
406
524
  thresholdSnapshot: Record<string, unknown>;
407
525
  latencyMs: number;
408
526
  degradedReason: string | null;
409
- };
527
+ } & ReviewScopeReceipt;
410
528
  /** 审核目标状态(mirrors contracts REVIEW_TARGET_STATUSES;SDK 不 hard-dep contracts)。 */
411
529
  export type ReviewTargetStatusLike = "pending" | "running" | "passed" | "needs_revision" | "blocked" | "degraded" | "superseded";
412
530
  /**
@@ -459,10 +577,11 @@ export type CreateReviewTargetBody = {
459
577
  subject: {
460
578
  title?: string;
461
579
  body: string;
580
+ /** ⚠️ Gate 0 的版规证据读的是这里的 `subredditRules`(worker 重建请求也读这个位置)。 */
462
581
  threadContext?: Record<string, unknown>;
463
582
  subreddit?: string;
464
583
  };
465
- };
584
+ } & ReviewScopeDeclaration;
466
585
  export type CommentDraftStatusLike = "draft" | "scheduled" | "approved" | "archived" | "published";
467
586
  /**
468
587
  * 评论审核语境快照(mirrors contracts commentDraftThreadContextSchema;严格对象——
@@ -772,12 +891,30 @@ export type SubredditMonitorRuleScope = "title" | "body" | "both";
772
891
  * ⚠️ CJK 没有词边界概念,`word` 在 CJK 上退化为子串 —— 否则「咖啡」永远匹配不上「咖啡机」。
773
892
  */
774
893
  export type SubredditMonitorMatchMode = "word" | "substring" | "phrase";
894
+ /**
895
+ * 规则极性(0171)。
896
+ * - `include`:命中它就算相关;
897
+ * - `exclude`:命中它就**撤销**同等或更低来源优先级的 include 命中
898
+ * (优先级 manual > brand_keyword > expansion —— 模型扩出来的否定词不该把运营
899
+ * 亲手填的 include 词否掉)。
900
+ *
901
+ * ⚠️ exclude 规则**自己不产生命中**。一条 include 都没有的规则集会被服务端拒绝激活
902
+ *(409)—— 那等于把整个板块静音,而卡片上看起来只是「今天没有相关新帖」。
903
+ * ⚠️ 同一个 (term, scope, matchMode) 上**可以**同时存在 include 与 exclude 两条:
904
+ *「espresso 收进来、espresso martini 排出去」正是这个形状。
905
+ */
906
+ export type SubredditMonitorRulePolarity = "include" | "exclude";
775
907
  export type SubredditMonitorKeywordRuleInput = {
776
908
  /** 原样字面值;服务端归一化(NFKC / 去重音 / 小写)后才进唯一键。 */
777
909
  term: string;
778
910
  scope?: SubredditMonitorRuleScope;
779
911
  matchMode?: SubredditMonitorMatchMode;
780
- /** 只影响卡片里命中词的展示顺序,不影响是否命中(本期只做 include)。 */
912
+ /** 省略 = `include`。见 {@link SubredditMonitorRulePolarity}。 */
913
+ polarity?: SubredditMonitorRulePolarity;
914
+ /**
915
+ * 影响卡片里命中词的展示顺序;对 exclude 规则则决定「因为 X 被排除」里 X 的排序。
916
+ * ⚠️ 它**不是**打分阈值:命中与否是布尔判定,不存在「权重不够就不算命中」。
917
+ */
781
918
  weight?: number;
782
919
  /** 品牌词导入的**来源溯源**;⛔ 不建立同步语义。 */
783
920
  sourceBrandKeywordId?: string | null;
@@ -788,13 +925,89 @@ export type SubredditMonitorKeywordRule = Required<Pick<SubredditMonitorKeywordR
788
925
  ruleSetId: string;
789
926
  normalizedTerm: string;
790
927
  scope: SubredditMonitorRuleScope;
791
- /** 本期只有 `include`(排除词是 P2,契约与 DDL 层都表达不出来)。 */
792
- polarity: "include";
928
+ /** `include` / `exclude`(0171 起)。见 {@link SubredditMonitorRulePolarity}。 */
929
+ polarity: SubredditMonitorRulePolarity;
793
930
  matchMode: SubredditMonitorMatchMode;
794
931
  weight: number;
795
932
  sourceBrandKeywordId: string | null;
796
933
  sourceBrandKeywordValue: string | null;
797
934
  };
935
+ /**
936
+ * 回放的逐帖判定。
937
+ * 🔴 `excluded` 与 `no_match` 是**两个不同的值**,⛔ 不得合并:
938
+ * `excluded` = 命中了 include 但被排除词否掉(去看排除词是不是配宽了);
939
+ * `no_match` = 一个 include 都没命中(去看 include 词是不是配窄了)。
940
+ */
941
+ export type SubredditMonitorReplayDecision = "matched" | "indeterminate" | "excluded" | "no_match";
942
+ export type SubredditMonitorReplayRun = {
943
+ id: string;
944
+ monitorId: string;
945
+ ruleSetId: string;
946
+ ruleSetVersion: number | null;
947
+ ruleHash: string | null;
948
+ windowStart: string;
949
+ windowEnd: string;
950
+ evaluatedCount: number;
951
+ matchedCount: number;
952
+ indeterminateCount: number;
953
+ /** 命中了 include 但被排除词否掉。⛔ 不含在 screenedOutCount 里。 */
954
+ excludedCount: number;
955
+ screenedOutCount: number;
956
+ /** 撞上硬顶。⚠️ **是布尔不是计数** —— 查询给不出准确的剩余数。 */
957
+ truncated: boolean;
958
+ note: string | null;
959
+ requestedBy: string | null;
960
+ createdAt: string;
961
+ };
962
+ export type SubredditMonitorReplayHit = {
963
+ id: string;
964
+ canonicalPermalink: string;
965
+ title: string | null;
966
+ postedAt: string | null;
967
+ decision: SubredditMonitorReplayDecision;
968
+ matchedTerms: string[];
969
+ matchedScopes: string[];
970
+ totalWeight: number;
971
+ bodyAvailability: string;
972
+ /** 造成撤销的排除词。`decision='excluded'` 时非空。 */
973
+ excludedByTerms: string[];
974
+ /** 正文拿不到 + 有正文域 exclude 规则 ⇒「该不该排除」判不了。 */
975
+ exclusionIndeterminate: boolean;
976
+ /** 当时**真实**账本里的判定;null = 当时没有账本行(见 originalAbsentReason)。 */
977
+ originalDecision: "matched" | "indeterminate" | null;
978
+ originalReportedAt: string | null;
979
+ originalRuleSetId: string | null;
980
+ /**
981
+ * 🔴 `originalDecision === null` 是多义的,这一位把它拆开:
982
+ * `screened_out` = 当时确实见过、只是判了不命中(账本对不命中一条都不写);
983
+ * `never_observed` = 当时根本没见过(还没开监听 / VOC 回灌进来的)。
984
+ * ⛔ 合并成「原来没报」会让「监听那时还没开」被误读成「规则漏了」。
985
+ */
986
+ originalAbsentReason: "screened_out" | "never_observed" | null;
987
+ };
988
+ export type SubredditMonitorReplayRunDetail = SubredditMonitorReplayRun & {
989
+ subreddit: string;
990
+ ruleSetStatus: "draft" | "active" | "retired";
991
+ /** 与真实账本的差分 —— 回放的产品价值就在这里。 */
992
+ diff: {
993
+ /** 当初报过、按新规则不再报的条数。 */
994
+ wouldStopReporting: number;
995
+ /**
996
+ * 当初被筛掉、按新规则会报的条数。
997
+ * ⚠️ 分母**只算** `screened_out`,⛔ 不含 `never_observed`
998
+ *(那是「监听那时还没开」,不是规则的功劳)。
999
+ */
1000
+ wouldNewlyReport: number;
1001
+ /** 当时根本没被这个监听观察到的条数。⛔ 不是「规则漏了」。 */
1002
+ neverObserved: number;
1003
+ };
1004
+ /** 🔴 显式的副作用边界声明:回放没通知任何人、没改账本、没推进水位。 */
1005
+ sideEffects: {
1006
+ notificationsSent: 0;
1007
+ hitsLedgerWritten: false;
1008
+ reportedWatermarkAdvanced: false;
1009
+ };
1010
+ };
798
1011
  export type SubredditMonitorRuleSet = {
799
1012
  id: string;
800
1013
  monitorId: string;
@@ -977,6 +1190,24 @@ export type EnableSubredditMonitorBody = {
977
1190
  watchlistId: string;
978
1191
  fetchLimit?: number;
979
1192
  };
1193
+ /**
1194
+ * 监听配置更新 body。
1195
+ *
1196
+ * 🔴 **没有 `enabled`,也不许加**:改配置绝不隐式改启停 —— 启停走
1197
+ * `enableSubredditMonitor`(启用)与 `disableSubredditMonitor`(软停)两个显式入口。
1198
+ * 🔴 **没有 `sort`**:DDL 的 CHECK 只允许 `'new'` 一个值,加了就是「改了就 400」的面。
1199
+ */
1200
+ export type UpdateSubredditMonitorConfigBody = {
1201
+ /**
1202
+ * 单页抓取条数上限,1–100(与 `EnableSubredditMonitorBody` 同一套边界)。
1203
+ *
1204
+ * 🔴 **必填,⛔ 不要写成可选。** 服务端 schema 要求「至少给一个可更新字段」,
1205
+ * 而当前可更新字段只有它一个 —— 声明成可选会让 `updateSubredditMonitorConfig(id, {})`
1206
+ * 通过类型检查、运行时必然 400。将来真的加了第二个可更新字段,再把这里
1207
+ * 改成「二选一」的联合类型。
1208
+ */
1209
+ fetchLimit: number;
1210
+ };
980
1211
  export type ListHotPostsParams = {
981
1212
  limit?: number;
982
1213
  offset?: number;
@@ -2690,6 +2921,17 @@ export declare class SocialHubClient {
2690
2921
  * observation ledger 因此保留,重启后已报告过的帖子不会重复报告。
2691
2922
  */
2692
2923
  enableSubredditMonitor(body: EnableSubredditMonitorBody): Promise<SubredditMonitorConfig>;
2924
+ /**
2925
+ * **只改监听配置,⛔ 不碰启停。**
2926
+ *
2927
+ * 🔴 与 {@link SocialOpsHubClient.enableSubredditMonitor} 的区别就是全部要点:
2928
+ * 那个 `POST` 是 upsert,`DO UPDATE` 里写死 `enabled = true`,所以在一个**被软停**的
2929
+ * 监听上用它改 `fetchLimit` 会把监听静默重新启用。本方法背后的 SQL 里不出现
2930
+ * `enabled` 列,改完启停状态原样不动。
2931
+ *
2932
+ * ⚠️ **不 upsert**:该 watchlist 没配置过监听 -> 404(不会被悄悄创建成监听)。
2933
+ */
2934
+ updateSubredditMonitorConfig(watchlistId: string, body: UpdateSubredditMonitorConfigBody): Promise<SubredditMonitorConfig>;
2693
2935
  /**
2694
2936
  * 停止监听:DELETE 语义但服务端做**软停**(enabled=false),不删 observation ledger。
2695
2937
  * 幂等 —— 本来就没在监听时返回 `{ ok: true, updated: false }`,不是 404。
@@ -2747,6 +2989,27 @@ export declare class SocialHubClient {
2747
2989
  activated: SubredditMonitorRuleSetDetail;
2748
2990
  retiredRuleSetId: string | null;
2749
2991
  }>;
2992
+ runSubredditMonitorReplay(monitorId: string, body: {
2993
+ /** 省略 = 该监听当前 active 的那版。可显式传 draft(主要用法)。 */
2994
+ ruleSetId?: string;
2995
+ /** ISO 时间串或 Date;窗口按帖子的 postedAt 取,左闭右开,最长 30 天。 */
2996
+ windowStart: string | Date;
2997
+ windowEnd: string | Date;
2998
+ /** 硬顶(默认 500,最大 2000)。撞顶时结果 `truncated=true`。 */
2999
+ limit?: number;
3000
+ note?: string | null;
3001
+ }): Promise<SubredditMonitorReplayRunDetail>;
3002
+ listSubredditMonitorReplays(monitorId: string, params?: {
3003
+ limit?: number;
3004
+ }): Promise<{
3005
+ items: SubredditMonitorReplayRun[];
3006
+ }>;
3007
+ getSubredditMonitorReplay(monitorId: string, replayRunId: string, params?: {
3008
+ decision?: SubredditMonitorReplayDecision;
3009
+ limit?: number;
3010
+ }): Promise<SubredditMonitorReplayRun & {
3011
+ results: SubredditMonitorReplayHit[];
3012
+ }>;
2750
3013
  /** 停用当前版本 ⇒ 该监听回到「不设关键词门」,报告**恢复全量新帖**。 */
2751
3014
  retireSubredditMonitorRuleSet(monitorId: string, ruleSetId: string): Promise<{
2752
3015
  ok: boolean;
@@ -3161,6 +3424,9 @@ export declare class SocialHubClient {
3161
3424
  calendarEntryId?: string;
3162
3425
  redditPostSnapshotId?: string;
3163
3426
  payload?: Record<string, unknown>;
3427
+ /** execution fencing token pair(认领时拿到的;两者须同时给出或同时省略)。 */
3428
+ executionGeneration?: number;
3429
+ executionId?: string;
3164
3430
  }): Promise<{
3165
3431
  ok: boolean;
3166
3432
  jobId: string;
@@ -3169,33 +3435,39 @@ export declare class SocialHubClient {
3169
3435
  alreadyCompleted?: boolean;
3170
3436
  trace: Record<string, unknown>;
3171
3437
  updated: Record<string, unknown>;
3172
- }>;
3438
+ } | OpsBlockedReceipt>;
3173
3439
  opsFail(teamId: string, body: {
3174
3440
  agentId: string;
3175
3441
  jobId: string;
3176
3442
  reason: string;
3177
3443
  message?: string;
3178
3444
  payload?: Record<string, unknown>;
3445
+ /** execution fencing token pair(认领时拿到的;两者须同时给出或同时省略)。 */
3446
+ executionGeneration?: number;
3447
+ executionId?: string;
3179
3448
  }): Promise<{
3180
3449
  ok: boolean;
3181
3450
  jobId: string;
3182
3451
  status: string;
3183
3452
  /** True when the job was already in this terminal — idempotent retry. */
3184
3453
  alreadyTerminal?: boolean;
3185
- }>;
3454
+ } | OpsBlockedJobAck>;
3186
3455
  opsSkip(teamId: string, body: {
3187
3456
  agentId: string;
3188
3457
  jobId: string;
3189
3458
  reason: string;
3190
3459
  message?: string;
3191
3460
  payload?: Record<string, unknown>;
3461
+ /** execution fencing token pair(认领时拿到的;两者须同时给出或同时省略)。 */
3462
+ executionGeneration?: number;
3463
+ executionId?: string;
3192
3464
  }): Promise<{
3193
3465
  ok: boolean;
3194
3466
  jobId: string;
3195
3467
  status: string;
3196
3468
  /** True when the job was already in this terminal — idempotent retry. */
3197
3469
  alreadyTerminal?: boolean;
3198
- }>;
3470
+ } | OpsBlockedJobAck>;
3199
3471
  /**
3200
3472
  * 评论内容复审:独立 LLM 六维评审+服务端权威计分。
3201
3473
  * executionStatus=degraded 时 verdict 不可作为权威判定,调用方应降级本地自审。
@@ -3227,7 +3499,7 @@ export declare class SocialHubClient {
3227
3499
  thresholdSnapshot: Record<string, unknown>;
3228
3500
  latencyMs: number;
3229
3501
  degradedReason: string | null;
3230
- }>;
3502
+ } & ReviewScopeReceipt>;
3231
3503
  /** 互动时序 P2:批量调度上下文(team 级,best_effort 一致性,keyset 分页)。 */
3232
3504
  getInteractionScheduleContext(teamId: string, params?: {
3233
3505
  limit?: number;
@@ -3258,6 +3530,16 @@ export declare class SocialHubClient {
3258
3530
  systemPools?: unknown;
3259
3531
  fallback?: unknown;
3260
3532
  exhaustion?: SubredditCandidatesExhaustion;
3533
+ /**
3534
+ * 分页方案 B8b:本次生效的 limit / 返回条数 / 是否被截断(配额、limit 或单 key 行数上限)。
3535
+ * 该端点没有 offset。配额 / limit 截断可调大 limit 或收窄 industry/tier;单 key 行数上限是
3536
+ * 上游固定帽,调 limit 补不全,只能收窄 industry 或人工处理。评论动作下配额阶段尚未过冷却 /
3537
+ * affinity,`truncated: true` 可能偏多报;`false` 是精确的「没被截」。
3538
+ * 旧服务端不返回这三个字段。
3539
+ */
3540
+ selectionLimit?: number;
3541
+ returned?: number;
3542
+ truncated?: boolean;
3261
3543
  }>;
3262
3544
  listSubredditPostAnnotations(teamId: string, params?: {
3263
3545
  subreddit?: string;
@@ -3781,7 +4063,20 @@ export declare class SocialHubClient {
3781
4063
  }): Promise<{
3782
4064
  purpose: string;
3783
4065
  activeSpecId: string | null;
4066
+ /**
4067
+ * ⚠️ 本页条数,**不是总数**。保留仅为兼容,与 `returned` 恒相等;新代码读 `returned`。
4068
+ * @deprecated 用 `returned`。
4069
+ */
3784
4070
  count: number;
4071
+ /** 本页实际返回的条数。 */
4072
+ returned: number;
4073
+ /** 本次生效的条数上限(请求的 limit,缺省 20)。 */
4074
+ selectionLimit: number;
4075
+ /**
4076
+ * 是否还有更多未返回的 run(服务端多取一条哨兵判定,精确)。
4077
+ * 这是 recent 投影,**没有分页** —— 为 true 时请调大 limit 或改用精确查询,⛔ 不要自拼 offset。
4078
+ */
4079
+ truncated: boolean;
3785
4080
  runs: unknown[];
3786
4081
  }>;
3787
4082
  /**
@@ -4258,6 +4553,40 @@ export declare class SocialHubClient {
4258
4553
  availability: string;
4259
4554
  availabilityCheckedAt: string;
4260
4555
  }>;
4556
+ /** GET /v1/system/subreddit-restrictions — 列表(state 多值、updatedSince 增量拉取)。 */
4557
+ listSubredditRestrictions(params?: ListSubredditRestrictionsParams): Promise<ListSubredditRestrictionsResponse>;
4558
+ /** GET /v1/system/subreddit-restrictions/:id — 单条(含全量 evidence)。 */
4559
+ getSubredditRestriction(id: string): Promise<SubredditRestriction>;
4560
+ /** POST /v1/system/subreddit-restrictions — 新建(已有活跃限制 → 409 RESTRICTION_EXISTS)。 */
4561
+ createSubredditRestriction(body: CreateSubredditRestrictionInput): Promise<SubredditRestriction>;
4562
+ /** POST .../:id/confirm — provisional / verification_overdue → confirmed(409 VERSION_MISMATCH / INVALID_STATE)。 */
4563
+ confirmSubredditRestriction(id: string, body?: ConfirmSubredditRestrictionInput): Promise<SubredditRestriction>;
4564
+ /** POST .../:id/revoke — 解封(唯一的解封路径)。 */
4565
+ revokeSubredditRestriction(id: string, body: RevokeSubredditRestrictionInput): Promise<SubredditRestriction>;
4566
+ /** GET .../:id/fanout — 扇出汇总 + 回执明细(阶段 B 之前为空、complete=false)。 */
4567
+ getSubredditRestrictionFanout(id: string, params?: SubredditRestrictionFanoutParams): Promise<SubredditRestrictionFanoutResponse>;
4568
+ /**
4569
+ * GET /v1/teams/:teamId/subreddit-restrictions — team 级只读列表(`compliance:read`,manager 可用)。
4570
+ * 过滤参数与系统级 list 相同,只回证据摘要。运营侧 agent 拉取状态走这个,不走系统级 admin 面。
4571
+ */
4572
+ listTeamSubredditRestrictions(teamId: string, params?: ListSubredditRestrictionsParams): Promise<ListSubredditRestrictionsResponse>;
4573
+ /**
4574
+ * GET /v1/teams/:teamId/subreddit-restrictions/:id/fanout — 只统计、只返回**本 team** 的回执;
4575
+ * outbox 的 summary / lastError 为 null(跨 team 信息)。complete 仍按全局 outbox 判断。
4576
+ */
4577
+ getTeamSubredditRestrictionFanout(teamId: string, id: string, params?: Omit<SubredditRestrictionFanoutParams, "teamId">): Promise<SubredditRestrictionFanoutResponse>;
4578
+ /** POST /v1/teams/:teamId/subreddit-restrictions/report — runner 上报(只写 provisional 或 sanction)。 */
4579
+ reportSubredditRestriction(teamId: string, body: ReportSubredditRestrictionInput): Promise<ReportSubredditRestrictionResponse>;
4580
+ /**
4581
+ * GET /v1/teams/:teamId/subreddit-restrictions/check — runner 动手前自查。
4582
+ * 账号可以用 `socialAccountId`(与 contracts 同名)或 `account`(CLI flag 同名)给;两者都给且不同
4583
+ * → 直接抛错,绝不静默丢掉其中一个 —— 丢了账号就只判系统级,会得到假的 `allowed:true`。
4584
+ */
4585
+ checkSubredditRestriction(teamId: string, params: {
4586
+ subreddit: string;
4587
+ socialAccountId?: string;
4588
+ account?: string;
4589
+ }): Promise<SubredditRestrictionCheckResult>;
4261
4590
  }
4262
4591
  export type NotificationSubscriptionStatus = "active" | "paused"
4263
4592
  /** 游标落后于保留 floor,已无法保证不漏;需人工确认后 reset。 */
@@ -4863,5 +5192,4 @@ export type CalendarEntryStatus = "draft" | "scheduled" | "exported" | "running"
4863
5192
  export type ReviewTargetStatus = "pending" | "running" | "passed" | "needs_revision" | "blocked" | "degraded" | "superseded";
4864
5193
  /** 契约 `reviewGateStateSchema` 的镜像(日历条目上的审核门投影)。 */
4865
5194
  export type ReviewGateState = "passed" | "waiting" | "revision_required" | "blocked" | "stale" | "untracked";
4866
- export {};
4867
5195
  //# sourceMappingURL=index.d.ts.map