@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.
Files changed (63) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/cmd-manifest.json +4 -2
  3. package/dist/content-review.test.js +1 -1
  4. package/dist/index.d.ts +24 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +98 -8
  7. package/dist/index.js.map +1 -1
  8. package/dist/register-calendar-directives.d.ts +64 -0
  9. package/dist/register-calendar-directives.d.ts.map +1 -0
  10. package/dist/register-calendar-directives.js +135 -0
  11. package/dist/register-calendar-directives.js.map +1 -0
  12. package/dist/register-calendar-directives.test.d.ts +2 -0
  13. package/dist/register-calendar-directives.test.d.ts.map +1 -0
  14. package/dist/register-calendar-directives.test.js +127 -0
  15. package/dist/register-calendar-directives.test.js.map +1 -0
  16. package/dist/scrape-output.test.d.ts +2 -0
  17. package/dist/scrape-output.test.d.ts.map +1 -0
  18. package/dist/scrape-output.test.js +58 -0
  19. package/dist/scrape-output.test.js.map +1 -0
  20. package/package.json +2 -2
  21. package/skills/README.md +23 -22
  22. package/skills/manifest.json +6 -1
  23. package/skills/reddit-content-rewrite/SKILL.md +29 -0
  24. package/skills/reddit-content-writing/SKILL.md +54 -5
  25. package/skills/reddit-content-writing/references/phase4-execution-table.md +24 -3
  26. package/skills/reddit-content-writing/references/phase4-writing.md +123 -3
  27. package/skills/reddit-content-writing/references/post-writing-templates.md +14 -6
  28. package/skills/reddit-delivery-check/SKILL.md +39 -6
  29. package/skills/reddit-delivery-check/references/phase5-delivery.md +7 -1
  30. package/skills/reddit-matrix.lock.json +10 -10
  31. package/skills/reddit-phase-brief/SKILL.md +62 -11
  32. package/skills/reddit-phase-brief/references/brand-SKU-PGC-rules.md +223 -36
  33. package/skills/reddit-phase-brief/references/phase4-brief-workflow.md +405 -19
  34. package/skills/reddit-phase-planning/SKILL.md +13 -0
  35. package/skills/reddit-phase-planning/references/phase4-execution-table.md +16 -2
  36. package/skills/reddit-phase-planning/references/phase4-planning.md +74 -15
  37. package/skills/reddit-phase-planning/references/scheduling-decision-procedure.md +386 -0
  38. package/skills/reddit-phase-research/SKILL.md +7 -1
  39. package/skills/reddit-phase-research/references/phase01-research.md +93 -29
  40. package/skills/reddit-strategy-orchestrator/SKILL.md +120 -18
  41. package/skills/reddit-strategy-shared/SKILL.md +4 -2
  42. package/skills/reddit-strategy-shared/references/content-diversity-contract.md +26 -5
  43. package/skills/reddit-strategy-shared/references/content-review-gate.md +48 -1
  44. package/skills/reddit-strategy-shared/references/context-contract.md +45 -11
  45. package/skills/reddit-strategy-shared/references/evidence-policy.md +139 -0
  46. package/skills/reddit-strategy-shared/references/handoff-schemas.md +88 -3
  47. package/skills/reddit-strategy-shared/references/native-copy-profile.md +207 -0
  48. package/skills/reddit-strategy-shared/references/path-conventions.md +26 -4
  49. package/skills/reddit-strategy-shared/references/persona-card-contract.md +210 -0
  50. package/skills/reddit-strategy-shared/references/prerequisites/README.md +57 -0
  51. package/skills/reddit-strategy-shared/references/prerequisites/{reddit-master-canvas-agent-prompt-template.md → archive/reddit-master-canvas-agent-prompt-template.md} +7 -0
  52. package/skills/reddit-strategy-shared/references/prerequisites/{reddit-sop-v2-universal.md → archive/reddit-sop-v2-universal.md} +7 -0
  53. package/skills/reddit-strategy-shared/references/prerequisites/{reddit-strategy-prerequisites-read.md → archive/reddit-strategy-prerequisites-read.md} +7 -0
  54. package/skills/reddit-strategy-shared/references/prerequisites/{reddit-strategy-reuse-playbook.md → archive/reddit-strategy-reuse-playbook.md} +7 -0
  55. package/skills/reddit-strategy-shared/references/subreddit-research-profile.md +514 -0
  56. package/skills/reddit-strategy-shared/references/version-manifest.md +89 -2
  57. package/skills/reddit-subreddit-compliance/SKILL.md +28 -1
  58. package/skills/reddit-voc-volume/matrix-contract.md +16 -1
  59. package/skills/social-hub-calendar-directives/SKILL.md +548 -0
  60. package/skills/social-hub-calendar-jobs/SKILL.md +10 -0
  61. package/skills/social-hub-cli/SKILL.md +2 -0
  62. package/skills/social-hub-notifications/SKILL.md +7 -0
  63. package/skills/social-hub-publishing/SKILL.md +5 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: reddit-phase-brief
3
3
  description: |
4
- Reddit Phase 4 Brief skill for the matrix SOP. Use after reddit-phase-planning completes Phase 4.0.6 and before reddit-content-writing starts. It assigns the target flair first, then establishes the flair-level subreddit baseline, then locks ContentFunction and StructureFamily, then the outline; it also creates board rationale, content schedule, per-Key title/direction/outlines, brand/SKU placement strategy, prewriting control fields (AssignedFlair / PostingTrigger), structure pre-assignment (OpeningMove / EvidenceShape / BrandEntryMode / EndingMode / LengthBand / SampleSetID / RecentCollisionCheck), and the approval gate. Trigger when the user says "确认进入 Phase 4 Brief", "开始 Brief", "产出 Brief 汇报稿", or when planning is complete but drafting has not started.
4
+ Reddit Phase 4 Brief skill for the matrix SOP. Use after reddit-phase-planning completes Phase 4.0.6 and before reddit-content-writing starts. It locks the target flair first by verifying planning's `ProposedFlair` from the scheduling ledger, then establishes the flair-level subreddit baseline, then locks ContentFunction and StructureFamily, then the outline; it also creates board rationale, content schedule, per-Key title/direction/outlines, brand/SKU placement strategy, prewriting control fields (AssignedFlair / PostingTrigger / PersonaCardRef), structure pre-assignment (OpeningMove / EvidenceShape / BrandEntryMode / EndingMode / LengthBand / SampleSetID / RecentCollisionCheck), and the approval gate. Trigger when the user says "确认进入 Phase 4 Brief", "开始 Brief", "产出 Brief 汇报稿", or when planning is complete but drafting has not started.
5
5
  ---
6
6
 
7
7
  # Reddit Phase Brief
@@ -17,6 +17,8 @@ Read the shared contracts first:
17
17
  - `~/.cursor/skills/reddit-strategy-shared/references/context-contract.md`
18
18
  - `~/.cursor/skills/reddit-strategy-shared/references/content-type-routing-contract.md` (mandatory)
19
19
  - `~/.cursor/skills/reddit-strategy-shared/references/content-diversity-contract.md` (mandatory)
20
+ - `~/.cursor/skills/reddit-strategy-shared/references/persona-card-contract.md` (mandatory — this skill **owns** the Persona Card)
21
+ - `~/.cursor/skills/reddit-strategy-shared/references/native-copy-profile.md` only when the batch runs `AcceptanceProfile: NativeCopy`
20
22
 
21
23
  Then verify these project memory files exist:
22
24
 
@@ -28,6 +30,7 @@ Then verify these project memory files exist:
28
30
  - `memory/phase4-执行表.md`
29
31
  - `memory/phase4-SKU品牌词映射.md`
30
32
  - `memory/phase4-撰写批次map.md`
33
+ - `memory/phase4-排期决策台账.md` with a `ProposedFlair` for every main-post Key in this batch (D2 output; source of `AssignedFlair`)
31
34
  - `memory/phase0.5-board-analysis.md`
32
35
  - `memory/phase1-VOC竞品缺口.md`
33
36
  - `memory/phase2-缺口分析.md`
@@ -59,7 +62,7 @@ guess the prototype from how the code reads.
59
62
  Read these local references before producing the brief:
60
63
 
61
64
  - `references/phase4-brief-workflow.md` for the full B-0 to B-3 workflow, templates, and gate checklist.
62
- - `references/brand-SKU-PGC-rules.md` before deciding brand/SKU placement for any P-B, C-B, or PGC row.
65
+ - `references/brand-SKU-PGC-rules.md` before deciding brand/SKU placement for any P-B, C-B, or PGC row. Read §2.0 (placement **source** = the brand-first-mention histogram; §2 A/B/C/D are risk **ceilings**) and §2.5 (comparable-sample semantics; `BrandMentionSampleCount = 0` means *no comparable evidence*, not *titles disallowed*) before A/B/C/D.
63
66
 
64
67
  ## Workflow
65
68
 
@@ -72,10 +75,18 @@ outline before the structure is decided from evidence.
72
75
  2. Confirm the number of Brief items in this batch.
73
76
  3. Load or initialize `memory/phase4-内容排期表.md`.
74
77
  4. Check historical `memory/phase4-撰写brief.md` for overlap before creating a new batch.
75
- 5. **Assign `AssignedFlair` (required, per main-post Key) before sampling.** flair 同时
76
- 决定合规资格、披露要求与触达,且决定 baseline 的采样口径。flair 必须取自该 subreddit
77
- 的现行 flair 列表(不得自造);板块无 flair 或允许不选时用哨兵值 `NoFlairAvailable` /
78
- `NoFlairRequired`(不得留空、不得用评论的 `N/A`);缺失 `BlockingGap`。评论 / 回复填 `N/A`。
78
+ 5. **Lock `AssignedFlair` (required, per main-post Key) before sampling by verifying the
79
+ planning-side `ProposedFlair`, not by choosing a new flair.** Read `ProposedFlair` for the
80
+ Key from `memory/phase4-排期决策台账.md` (produced by `reddit-phase-planning` D2, contract
81
+ `reddit-phase-planning/references/scheduling-decision-procedure.md`), then verify it against
82
+ the subreddit's **currently selectable** flair list and the account's eligibility. Verified →
83
+ `AssignedFlair = ProposedFlair`. Not verifiable → `FlairVerificationStatus: Rejected` +
84
+ `BlockingGap` back to planning for a new `ProposedFlair`; the Brief must **not** substitute a
85
+ flair of its own. The single exception is `ProposedFlair: Unknown(NoSRP)` (planning ran in
86
+ `SRPMode: Fallback`), where the Brief picks from the live flair list and writes the choice and
87
+ reason back to the ledger (`FlairVerificationStatus: FallbackAssigned`). Flairless boards use
88
+ the sentinels `NoFlairAvailable` / `NoFlairRequired` (never blank, never the comment `N/A`);
89
+ a missing ledger row is a `BlockingGap`. Comments / replies use `N/A`.
79
90
  6. **Establish or refresh the flair-level subreddit baseline** for every target subreddit
80
91
  and assign a `SampleSetID` (see `references/phase4-brief-workflow.md` step B-1.0).
81
92
  优先按 `AssignedFlair` 细分取 exact-flair 样本;记录 `BaselineScope` /
@@ -85,9 +96,29 @@ outline before the structure is decided from evidence.
85
96
  Reuse a valid, unexpired baseline of the same flair coverage; only re-acquire when it is missing or stale.
86
97
  7. **Lock the project diversity window** (`WindowCount` 8–12, `WindowDays` 30–60) if not already locked, and read the rolling window from `memory/phase4-叙事指纹索引.md`.
87
98
  8. Produce board-selection rationale with evidence URLs, then the board overview table.
88
- 9. For every post Key: resolve `客户内容原型` `MappingRuleID`, lock `ContentFunction`, confirm the `EvidenceShape` actually in hand, narrow `StructureFamily` candidates with the ordered filter in `content-type-routing-contract.md`, pre-assign `OpeningMove` / `BrandEntryMode` / `CaveatMode` / `EndingMode` / `LengthBand` / `AnchorSlot`, and the `PostingTrigger`(受控值 `ConcreteFailure` / `PurchaseDecision` / `MeasurementResult` / `CompatibilityGap` / `UnsolicitedTestimony`;`UnsolicitedTestimony` 仅当 `BrandEntryMode: 不出现` 且有真实非征集非品牌控制的 testimony 证据),and **only then** run `RecentCollisionCheck` on the complete triple. On collision, first swap `OpeningMove` / `EndingMode` within the same family; reselect a family only if that fails. **Only then** write the outline.
99
+ 8b. **Run the material-modality preflight (G4, step B-1.4) before locking any structure.** Every selling point / material carries `MaterialID` + `OriginalModality` (`Required` / `Preferred` / `Optional` / `Forbidden`) + `EffectiveModality` + `ModalitySource`. Upgrading modality is blocked unless an `AuthoritativeSource` (`ClientContract` / `SubredditRule` / `ComplianceRequirement` / an already-authorized `ApprovedBrief`) backs it via `ModalityUpgradeRef`, with `ApprovedBy` the generating agent. **A material the user explicitly marked `Optional` is never upgraded** — go back to the user instead. Missing or conflicting modality is fail-closed. Disclosure/compliance requirements are not selling-point modality.
100
+ 9. For every post Key: resolve `客户内容原型` → `MappingRuleID`, lock `ContentFunction`, confirm the `EvidenceShape` actually in hand, narrow `StructureFamily` candidates with the ordered filter in `content-type-routing-contract.md`, pre-assign `OpeningMove` / `CaveatMode` / `EndingMode` / `LengthBand` / `AnchorSlot` (**`BrandEntryMode` is deliberately excluded here — it is assigned in 9b, after its gate**), and **record (not yet validate)** the `PostingTrigger` candidate — its cross-constraint with `BrandEntryMode` can only be checked after 9b(受控值 `ConcreteFailure` / `PurchaseDecision` / `MeasurementResult` / `CompatibilityGap` / `UnsolicitedTestimony`;`UnsolicitedTestimony` 仅当 `BrandEntryMode: 不出现` 且有真实非征集非品牌控制的 testimony 证据),and **only then** — after 9b has supplied `BrandEntryMode` — run `RecentCollisionCheck` on the complete triple. On collision, first swap `OpeningMove` / `EndingMode` within the same family; reselect a family only if that fails. **Only then** write the outline. Under `AcceptanceProfile: NativeCopy` a client requirement about how posts end narrows **the set this step may assign from** — it is never a question appended to a finished draft, since `EndingMode` is a locked field and one of the three collision fields. If the narrowed set leaves no collision-free option, that is a `BlockingGap` back to planning (`../reddit-strategy-shared/references/native-copy-profile.md`).
101
+ 9b. **Only now assign `BrandEntryMode`, and only through `BrandPlacementGate` (G2):** for **P-B / PGC posts**, placement is decided by the brand-first-mention histogram plus the §2 risk ceiling (`SelectedPlacement` = the later of the two, histogram bucket 结论 mapping to 后段; the domain is 标题/首段/中段/后段, and a class-D board or `NoBrandMentionRate ≥ 0.8` that leaves no viable spot is a `BlockingGap` back to planning, never a silent drop to 不出现/评论) — **never derived from the P-B label**. **P-NB posts** go straight to `不出现` without running the formula; **C-B comments** use `CommentPlacementDecision` plus the §2 ceiling and complement rules. Fill the placement evidence first, **branching by row type**: P-B / PGC posts need a complete `BrandPlacementBasis`; P-NB posts take `N/A(P-NB · 主帖不露品牌)`; C-B comments take `InheritedBrandPlacementBasis` + `CommentPlacementDecision` instead and are never required to carry their own. Legitimate title exposure is preserved for `PGCApproved` (precedent check passed, board allows vendor/official, flair/disclosure/frequency met) and `BrandReviewPost` (genuinely a post about that brand, judged from `PrimaryPostType` / `WritingVariant` plus topic evidence — never by inventing a `ContentFunction: Review` value). This gate governs *what decides placement only* — brand quota semantics (P-B / P-NB / C-B / C-NB / PGC) are untouched.
102
+ 9c. **Narrative layering (G1, step B-1.6) before writing title directions or outlines:** every post and comment carries `InternalCoverageIntent` (FAQ ids, fanout queries, keywords, gap codes, `prompt_id` — internal only) and a non-empty `ReaderVisiblePremise`. The gate scans only reader-facing fields (核心角度 / 标题方向 / 大纲 / 撰写逻辑一句话 / 评论任务方向 / outbound Reddit payload); Routing Decision, TraceFields and 方向选取理由 keep their internal labels. Converting FAQ evidence into a real reader question is the intended outcome — only raw internal labels in the narrative are blocked.
103
+ 9d. **Assign the Persona Card for every main-post Key (contract:
104
+ `../reddit-strategy-shared/references/persona-card-contract.md`).** The Card is the
105
+ third `PrewritingControlField` and this skill owns it: record `PersonaCardRef` +
106
+ `PersonaCardVersion` + `PersonaCardHash`, the capability fields
107
+ (`knowledgeAccess` — exactly one of `research` / `owned` / `used` / `observed` /
108
+ `supplied_by_brand`; `permittedExperienceClaims` — a possibly-empty subset of
109
+ `{ownership, delivery, wear, service}`; `attentionFocus`; `questionIntent`), and the
110
+ per-draft fields (`postingWhy`, `knows[]`, `doesNotKnow[]`, `permittedFactRefs`,
111
+ `brandRelationshipDisclosed`). `postingWhy` must be able to coexist with the assigned
112
+ `PostingTrigger` — they are different fields and neither substitutes for the other.
113
+ **The writer never authors a Card**; letting it do so would let the draft grant itself
114
+ whatever boundary it already needs. Comments / self-comments / external comments take
115
+ `N/A` — this train does not put comments under a Card. `permittedExperienceClaims` is
116
+ authorised from submitted context, never inferred from the brand relationship: a
117
+ partner may genuinely own the product, and an empty set is a normal Card. The Card is a
118
+ **declared posting context, not a verified identity** — it is `LocalOnly`, is never
119
+ sent to Hub, and never implies the publishing account was resolved.
89
120
  10. Create one Brief block for every execution-table Key in the selected batch, including posts, self-comments, and external comments.
90
- 11. For all P-B/C-B/PGC rows, record brand/SKU placement rationale using `references/brand-SKU-PGC-rules.md`.
121
+ 11. For all P-B/C-B/PGC rows, record brand/SKU placement rationale using `references/brand-SKU-PGC-rules.md` (§3's five sample-learning classes are *rationale records only* — they never write `SelectedPlacement` directly nor bypass §2.0's mechanical rules).
91
122
  12. Write a `Planned` fingerprint row for every briefed post Key into `memory/phase4-叙事指纹索引.md` (`DraftHash: PENDING`), including the two `PrewritingControlFields` (`AssignedFlair`, `PostingTrigger`).
92
123
  13. Write or update the memory files listed below, then show the Brief gate checklist.
93
124
 
@@ -103,6 +134,14 @@ Baseline cards may live in `memory/phase4-撰写brief.md` or a dedicated baselin
103
134
  file; either way each is addressed by its `SampleSetID` and is reusable across
104
135
  Keys and batches within its validity period.
105
136
 
137
+ Persona Cards may likewise live inside `memory/phase4-撰写brief.md` or in a
138
+ dedicated `memory/phase4-persona-card.md`; either way each is addressed by its
139
+ `PersonaCardRef` and carries its own `PersonaCardVersion` / `PersonaCardHash`.
140
+ Unlike a baseline card a Persona Card is **per post Key, not shared** — its
141
+ per-draft fields belong to one submission. Do not record Cards in
142
+ `memory/phase4-叙事指纹索引.md`: the index has a fixed schema and a fixed hash
143
+ definition, and the Card is not a fingerprint field.
144
+
106
145
  Optional Feishu Brief documents require an explicit user-provided folder link.
107
146
 
108
147
  ## Gate
@@ -110,10 +149,15 @@ Optional Feishu Brief documents require an explicit user-provided folder link.
110
149
  Writing may start only after:
111
150
 
112
151
  - Every target subreddit has a valid, unexpired baseline card with a `SampleSetID`, with flair coverage recorded (`BaselineScope` / `FlairCoverageStatus`); `FlairCoverageStatus` is `Exact` or `ApprovedFallback` (never `Insufficient`).
113
- - Every **main-post** Key carries a non-empty `AssignedFlair` — drawn from the subreddit's live flair list, or the sentinel `NoFlairAvailable` / `NoFlairRequired` for flairless boards — and its `AssignedFlair` matches the baseline card's covered flair (or an approved fallback).
152
+ - Every **main-post** Key carries a non-empty `AssignedFlair` — verified against the ledger's `ProposedFlair` and the subreddit's live flair list (`FlairVerificationStatus: Verified` or `FallbackAssigned`; no `Rejected` left open), or the sentinel `NoFlairAvailable` / `NoFlairRequired` for flairless boards — and its `AssignedFlair` matches the baseline card's covered flair (or an approved fallback).
114
153
  - Every **main-post** Key's `客户内容原型` resolves to an `Approved` mapping row (`MappingRuleID` / `MappingVersion` recorded in the Routing Decision). Self-comments inherit the paired post's value; external comments use `—` and need no mapping of their own.
115
- - Every post Brief row carries the nine `LockedFingerprintFields` (`ContentFunction`, `StructureFamily`, `OpeningMove`, `EvidenceShape`, `BrandEntryMode`, `CaveatMode`, `EndingMode`, `LengthBand`, `AnchorSlot`), the two `PrewritingControlFields` (`AssignedFlair`, `PostingTrigger` — the latter satisfying the `PostingTrigger × BrandEntryMode` cross-constraint), and the four `TraceFields` (`SampleSetID`, `RecentCollisionCheck`, `MappingRuleID`, `MappingVersion`).
154
+ - Every post Brief row carries the nine `LockedFingerprintFields` (`ContentFunction`, `StructureFamily`, `OpeningMove`, `EvidenceShape`, `BrandEntryMode`, `CaveatMode`, `EndingMode`, `LengthBand`, `AnchorSlot`), the three `PrewritingControlFields` (`AssignedFlair`, `PostingTrigger` — satisfying the `PostingTrigger × BrandEntryMode` cross-constraint — and `PersonaCardRef`), and the four `TraceFields` (`SampleSetID`, `RecentCollisionCheck`, `MappingRuleID`, `MappingVersion`).
155
+ - Every **main-post** Key carries a non-empty `PersonaCardRef` with its `PersonaCardVersion` / `PersonaCardHash`, a single `knowledgeAccess`, a `permittedExperienceClaims` set drawn only from `{ownership, delivery, wear, service}` (empty is valid), non-empty `postingWhy`, and a `postingWhy` that can coexist with the assigned `PostingTrigger`. Comments take `N/A`. Role labels, if present, are non-authoritative and no gate reads them. Any Card with a non-empty `permittedExperienceClaims` also carries `DeclaredBy` (never the generating agent) and `ClaimAuthorizationRef`; without both, the claim set is reported as a Brief declaration rather than an authorised set.
116
156
  - `RecentCollisionCheck` is `Pass` for every row, or `Exception` with an approved `ExceptionRef`.
157
+ - Every **P-B / PGC post** row carries a complete `BrandPlacementBasis` and a `SelectedPlacement` consistent with it (an already-planned P-B/PGC row may only land on 标题/首段/中段/后段 — moving the brand to a comment or dropping it is a quota change, so it goes back to planning); **C-B comments** carry `InheritedBrandPlacementBasis` + `CommentPlacementDecision` instead and never build their own histogram. No row derives title-brand exposure from the P-B label; `NoComparableEvidence` rows went through re-sampling / StopAndAsk / a recorded `BrandTitleExposureException`, not a default; `Sparse` rows meet the three §2.5 conditions.
158
+ - Every post and comment Brief carries `InternalCoverageIntent` + a non-empty `ReaderVisiblePremise`, and no reader-facing field leaks internal labels.
159
+ - The material-modality ledger is complete, with no unauthorized upgrades or downgrades (and nothing the user marked `Optional` upgraded).
160
+ - Baseline cards cover all **10** dimensions (the 10th is the em-dash / parenthesis usage distribution).
117
161
  - `memory/phase4-叙事指纹索引.md` has exactly one active `Planned` row for every briefed **post** Key (comments are out of scope while `WindowScope: PostOnly`).
118
162
  - `memory/phase4-撰写brief.md` exists and covers every planned Key for the batch.
119
163
  - `brief_approval_mode` is recorded.
@@ -138,8 +182,15 @@ Writing may start only after:
138
182
  - FlairCoverageStatus: Exact / ApprovedFallback / Insufficient # batch-level = worst status across cards (Insufficient > ApprovedFallback > Exact)
139
183
  - ClientPrototypeMappingStatus: AllApproved / BlockingGap
140
184
  - StructureFieldsAssigned: Yes / No
141
- - PrewritingControlFieldsAssigned: Yes / No # AssignedFlair + PostingTrigger per main-post Key
185
+ - PrewritingControlFieldsAssigned: Yes / No # AssignedFlair + PostingTrigger + PersonaCardRef per main-post Key
142
186
  - PostingTriggerCrossConstraintOK: Yes / No # UnsolicitedTestimony ⇒ BrandEntryMode 不出现
187
+ - PersonaCardCoverage: <n>/<N> # main-post Keys with a non-empty PersonaCardRef
188
+ - PersonaCardTransportStatus: LocalOnly(ServerContractMissing) # the Card is never sent to Hub
189
+ - PersonaCardAuthorizationStatus: Authorized / DeclaredOnly / NotApplicable # worst status across Keys; propagate to writing and delivery
190
+ - AcceptanceProfile: Default / NativeCopy
191
+ - NativeCopyProfileStatus: NotSelected / Unavailable(ServerContractMissing)
192
+ - LocalReviewIntent: accountBinding=<account_bound|persona_less>, brandTreatment=<managed_brand|organic> # local planner declaration; propagate to writing and delivery, never sent to Hub
193
+ - HubReviewScopeStatus: Unavailable(ServerContractMissing) # no server-side scope exists to report
143
194
  - FingerprintPlannedRows: <n>/<N>
144
195
  - DiversityWindow: WindowCount=<n>, WindowDays=<n>
145
196
  - RecentCollisionCheck: Pass / BlockingCollision / Exception(<ExceptionRef>)
@@ -17,11 +17,90 @@ P-B / C-B 只表示该内容需要承载品牌词,不代表品牌名、SKU、
17
17
 
18
18
  禁止把所有 P-B 主帖批量设置为“标题或第一段露出品牌 / SKU”。
19
19
 
20
+ > **上列因素的分工见 §2.0:** 「板块规则 / 推广容忍度 / 帖型 / 合规风险」是**风险边界**,
21
+ > 「样本(GEOly 引用帖、VOC 帖、同板块高存活帖)」是**位置来源**。二者不可互换,
22
+ > 且 **P-B 标签本身不是任何一方**。
23
+
20
24
  ---
21
25
 
22
- ## 2. 默认露出位置规则
26
+ ## 2. 露出位置规则
27
+
28
+ ### 2.0 位置来源 vs 风险边界(G2 · 读 A/B/C/D 之前必须先读本节)
29
+
30
+ > **出处(真实返工):** 需求方质问「**为什么你把 P-B 的标题都统一加上了 aporro 这个
31
+ > 品牌了?**」——P-B 的含义是「帖子中包含品牌词」,**并不代表品牌名必须在标题里出现**,
32
+ > 那样显得很广告。修正后的口径:品牌词出现在 P-B 帖的**正文 body 中**,标题中通常不写
33
+ > 品牌名,**除非是 Brand Review / 专门讨论该品牌的帖子**。
34
+
35
+ 本节确立两条不同性质的输入,**不得互相替代**:
36
+
37
+ | | 是什么 | 谁给出 |
38
+ |---|---|---|
39
+ | **位置来源(source)** | 该板块真实帖子的**品牌首次出现位置直方图**(baseline 卡第 5 维;或板块级 SRP 的 `brandFirstMentionHistogram`) | 证据 |
40
+ | **风险边界(ceiling)** | 下面 A/B/C/D 四类给出的**允许位置集合 / 最早允许位置** | 版规、合规、板块风险 |
41
+
42
+ **取值规则(机械化,不留解释空间):**
43
+
44
+ ```
45
+ SelectedPlacement = 更晚的(§2 A/B/C/D 允许的最早位置, 直方图给出的经验位置)
46
+
47
+ 例外分支:持有有效 BrandTitleExposureException(§2.5)时
48
+ → 该例外可覆盖直方图与「标题档 < 20%」限制,SelectedPlacement 允许取「标题」
49
+ → 但仍不得越过 §2 D 类、版规与披露要求
50
+ → 此时 BrandPlacementBasis.SourceKind = Exception(**Exception 是合法的 SourceKind**)
51
+
52
+ D 类是终止条件:主帖不露品牌,不参与「取更晚」比较
53
+
54
+ 档位映射(直方图档 → SelectedPlacement 受控值,必须按此换算):
55
+ 标题 → 标题 首段 → 首段 中段 → 中段 结论 → 后段
56
+ (直方图只有四档,SelectedPlacement 的「评论」/「不出现」不来自直方图)
57
+ ```
58
+
59
+ **⚠️ 既有 P-B / PGC 行的取值域限制(防止位置改动变成配额改动):**
60
+ 对**规划时已定为 P-B / PGC** 的行,`SelectedPlacement` 只能取
61
+ `标题 / 首段 / 中段 / 后段` —— **不得取「评论」或「不出现」**。因为帖—评互补规则是
62
+ 「P-B 主帖含品牌 → 配对自评 C-NB;P-NB 主帖不含品牌 → 配对自评 C-B」,把 P-B 的品牌
63
+ 挪到评论或取消,实际上就把这行变成了 P-NB + C-B,**那是配额与行类型变更**。
64
+ 正确动作:`BlockingGap: BrandPlacementUnsupported` → 回规划决定。
65
+ 「评论」与「不出现」只对**规划时已是 P-NB** 的行合法。
66
+
67
+ - 直方图允许标题、但 §2 判为 C / D(敏感 / 高风险)→ 按 C / D。
68
+ - §2 判为 A(可标题或首段)、但直方图显示该板块几乎不在标题出现品牌 → **按直方图**。
69
+ - **`SelectedPlacement` 永远不得从「这行标记 P-B」推导出来。** 出现该推导即
70
+ `BlockingGap: BrandPlacementUnsupported`。
71
+
72
+ **直方图的经验位置怎么取(不得自由解释「占比低」):**
73
+
74
+ - `BrandFirstMentionHistogram` **只有四档:标题 / 首段 / 中段 / 结论**,分母是
75
+ `BrandMentionSampleCount`(**确实出现品牌的样本**)。「不出现」**不是本直方图的一档**,
76
+ 它由另一个量 `NoBrandMentionRate`(= 1 − `BrandMentionSampleCount` /
77
+ `ComparableSampleCount`)表示;两者不得混为一谈(详见 §2.5)。
78
+ - 取**众数档**(四档中占比最高的那一档)作为经验位置;
79
+ - **并列时取更晚的那一档**(标题 < 首段 < 中段 < 结论),不得挑更靠前的;
80
+ - 「标题」档占比 **< 20%** 时不得选标题位置,除非持有 §2.5 的合法例外;
81
+ - `NoBrandMentionRate` **≥ 0.8**(该板块普遍不提品牌)**不直接决定位置**,它是把位置往后推
82
+ 一档、或触发 §3.5 StopAndAsk 的信号;**它本身不构成 §2 D 类终止条件**。
83
+ 后推到「后段」仍不可行时:**规划时已是 P-NB 的行**可落到「不出现」;
84
+ **规划时是 P-B / PGC 的行** → `BlockingGap` 回规划,**不得**静默落到「不出现」。
85
+ 持有有效 `BrandTitleExposureException` 时,该后推信号**可被例外覆盖**
86
+ (例外仍受 D 类、版规与披露要求约束)。
87
+ `ComparableSampleCount = 0` 时该比率**未定义**,填 `N/A`,并直接按
88
+ `DecisionStatus: NoComparableEvidence` 处理。
89
+ - **众数档已是「结论」时没有更晚的一档**:保持「结论」,不再后移(后移的下一步是
90
+ 「评论 / 不出现」,那属于配额语义,见上方取值域限制)。
91
+
92
+ **A/B/C/D 四类的读法(重要):** 下面 A/B/C/D 是**风险边界**,即「最早允许到哪」和
93
+ 「哪些位置被版规/合规禁掉」,**不是位置来源**。看到某个帖型落在 A 类**不等于**应该把
94
+ 品牌放进标题 —— 还要直方图支持。
95
+
96
+ ⚠️ **本节不改动品牌配额语义。** P-B / P-NB / C-B / C-NB / PGC 的配额是否为合同硬约束,
97
+ 属另一批工作。本节只回答**位置由什么决定**,不回答**要不要有品牌**:位置不成立时正确
98
+ 动作是 `BlockingGap` 或回规划确认,**不得**静默把 P-B 改成 P-NB、不得自动改配对或配额,
99
+ PGC 行也不因标题例外变成 P-B 行。
100
+
101
+ ---
23
102
 
24
- ### A. 可标题或首段露出
103
+ ### A. 风险边界:可标题或首段露出
25
104
 
26
105
  适用于:
27
106
 
@@ -49,7 +128,7 @@ P-B / C-B 只表示该内容需要承载品牌词,不代表品牌名、SKU、
49
128
 
50
129
  ---
51
130
 
52
- ### B. 默认中段露出
131
+ ### B. 风险边界:最早中段露出
53
132
 
54
133
  适用于:
55
134
 
@@ -73,7 +152,7 @@ P-B / C-B 只表示该内容需要承载品牌词,不代表品牌名、SKU、
73
152
 
74
153
  ---
75
154
 
76
- ### C. 默认后段或评论露出
155
+ ### C. 风险边界:最早后段或评论露出
77
156
 
78
157
  适用于:
79
158
 
@@ -92,20 +171,89 @@ P-B / C-B 只表示该内容需要承载品牌词,不代表品牌名、SKU、
92
171
 
93
172
  ---
94
173
 
95
- ### D. 高风险或禁止推广板块
174
+ ### D. 终止条件:高风险或禁止推广板块
96
175
 
97
- 适用于:
176
+ 适用于(**只由明确规则触发,不由样本分布触发**):
98
177
 
99
- - 明确禁止 self-promotion、advertising、commercial post 的板块
178
+ - 明确禁止 self-promotion、advertising、commercial post 的板块(版规原文可引用)
100
179
  - 医疗、法律、隐私等高敏感板块
101
- - 样本显示高存活内容通常不直接提品牌的板块
180
+ - 合规 / 法务明确列为高风险的板块
181
+
182
+ > **v3 变更(G2):删除「样本显示高存活内容通常不直接提品牌的板块」这一条 D 类触发项。**
183
+ > 那是**样本分布**,属于位置来源,会把 source 直接升级成终止条件,与 §2.0 的分层冲突。
184
+ > 该信号现在记为 `NoBrandMentionRate` 高,作用是**把位置往后推**(最多到「不出现」这一
185
+ > `SelectedPlacement`)或触发 §3.5 StopAndAsk,**不自动把板块判成 D 类**。
186
+
187
+ 处理方式(**按该行规划时的既有类型分叉**):
188
+
189
+ - **规划时已是 P-NB 的行**:主帖不露品牌;如规则允许,再用 C-B 评论谨慎补位;
190
+ 如果评论也有推广风险,则该板块不做品牌露出。
191
+ - **规划时是 P-B / PGC 的行**:**不得**在本阶段把它降成「不露品牌」或挪到评论 ——
192
+ 那是配额与行类型变更。正确动作是 `BlockingGap: BrandPlacementUnsupported`,
193
+ **回规划决定**(换板块 / 改配额 / 撤这行)。
194
+ - 有效 `BrandTitleExposureException` **不能**越过 D 类:D 类的禁止推广规则优先。
195
+
196
+ ---
197
+
198
+ ### 2.5 品牌位置直方图的可比样本口径(G2 · 防止把「没样本」误读成「不允许」)
199
+
200
+ **最容易犯的错:** baseline 的 5–10 条样本大多是普通 UGC,里面本来就没几条提品牌,
201
+ 于是「标题」档占比 = 0 —— 这只说明**没有可比较的品牌样本**,**不等于**「品牌标题被证明
202
+ 不允许」。把 0 当成一个保守位置,会把 PGC 与 Brand Review 的合法标题露出一并挡掉。
203
+
204
+ 因此直方图必须分三个量记录,缺一不可:
205
+
206
+ | 字段 | 含义 |
207
+ |---|---|
208
+ | `ComparableSampleCount` | 该 Scope(subreddit + flair + `PrimaryPostType`/`ContentFunction` + 账号类型 UGC/PGC)下的合格样本总数 |
209
+ | `ComparableScopeStatus` | `Exact`(四维全分层)/ `ApprovedFallback`(放宽了某一维,须记放宽了哪一维 + `ComparableScopeApprovedBy`)/ `Insufficient`(→ 按 `NoComparableEvidence` 处理)。⚠️ **baseline 采样默认只按 subreddit + flair 分层**(见 brief B-1.0),因此帖型 / 账号类型这两维通常需要显式声明:要么在建卡时补分层,要么记 `ApprovedFallback`。**混了不同帖型或 UGC/PGC 的样本,直方图就不是本行的有效位置来源** |
210
+ | `BrandMentionSampleCount` | 其中**确实出现品牌 / 产品**的样本数 —— **直方图的真实分母** |
211
+ | `NoBrandMentionRate` | `1 − BrandMentionSampleCount / ComparableSampleCount`,即该板块**根本不提品牌**的比例。**它不是直方图的一档**,也不构成 D 类终止条件 |
212
+ | `BrandFirstMentionHistogram` | 在 `BrandMentionSampleCount` 这个分母内,首次出现位置落在 **标题 / 首段 / 中段 / 结论** 四档的占比(**没有「不出现」这一档**) |
102
213
 
103
- 处理方式:
214
+ **`DecisionStatus` 四值(producer 与 consumer 必须同口径):**
104
215
 
105
- - 主帖不露品牌
106
- - 使用 P-NB 主帖
107
- - 如规则允许,再用 C-B 评论谨慎补位
108
- - 如果评论也有推广风险,则该板块不做品牌露出
216
+ | 值 | 判据 | 处置 |
217
+ |---|---|---|
218
+ | `Supported` | `BrandMentionSampleCount ≥ 5` | 按 §2.0 取值规则直接使用 |
219
+ | `Sparse` | `1 ≤ BrandMentionSampleCount ≤ 4` | **可用**,但须同时满足三条:①Brief 写明**三个计数字段**(`ComparableSampleCount` / `BrandMentionSampleCount` / `NoBrandMentionRate`)**与四档直方图**;②在众数档与其下一档之间取**更保守(更晚)**的一档(众数已是「结论」则保持「结论」);③记 `SparseApprovedBy`(显式批准人,≠ 生成本 Brief 的 agent)。三条缺一 → 按 `NoComparableEvidence` 处理 |
220
+ | `NoComparableEvidence` | `BrandMentionSampleCount = 0` | **不得**当成「不允许标题」;走 §3.5 的补样本 / 换来源 / StopAndAsk / 合法例外 |
221
+ | `Exception` | 持有下方**有效**合法例外 | **该状态优先于 `NoComparableEvidence`**:例外成立时 `DecisionStatus` 直接记 `Exception`(不再同时报 `NoComparableEvidence`),须记 `BrandTitleExposureException` 四字段;此时 `SourceKind: Exception`,`SourceRef` 填 `ExceptionRef`(或 `ExceptionBasis` 的引用),**不要求 SampleSetID** |
222
+
223
+ **零分母时的字段填法(避免必填字段互相打架):** `BrandMentionSampleCount = 0` 时,
224
+ `BrandFirstMentionHistogram` 与 `NoBrandMentionRate` 均填 `N/A`(`ComparableSampleCount = 0`
225
+ 时两者同样 `N/A`),**不得编造占比**;`ComparableSampleCount` 与 `BrandMentionSampleCount`
226
+ 本身仍必填(写 0)。
227
+
228
+ **`NoComparableEvidence` 的正确动作(按序):** ①扩大时间窗 / 放宽到 `FlairCluster` 重采;
229
+ ②改用板块级 SRP 的 `brandFirstMentionHistogram`(契约见
230
+ `../../reddit-strategy-shared/references/subreddit-research-profile.md`;**该板块暂无可用 SRP 实例时
231
+ 以 baseline 卡为主来源,不得因其缺失而无条件阻断**);③仍无可比样本 → **停下来问人**
232
+ (策略师 / 用户),或走下方例外;④都不成立 → `BlockingGap`。
233
+
234
+ #### ⚠️ 合法例外(必须保留,不得一刀切)
235
+
236
+ 以下两类**标题出现品牌名是合法的**,即使直方图不支持:
237
+
238
+ | 例外值 | 成立条件(全部满足) |
239
+ |---|---|
240
+ | `PGCApproved` | ①账号类型为官方 / PGC;②已过 §4 PGC account precedent check(**有真实先例**,须给出先例 URL);③版规允许 brand / vendor / official account 内容;④flair / disclosure / frequency 要求均满足 |
241
+ | `BrandReviewPost` | 该帖**确实**围绕该品牌 / 该产品本身展开。判据用**现有受控字段组合**,两个条件**必须同时成立**:<br>`( PrimaryPostType ∈ {ROUNDUP, OWNER, OPINION} OR WritingVariant ∈ {COMPARE, WORTHIT, DATA} )`<br>**AND** 选题证据表明**内容主体就是评这个品牌 / 产品**(须给出证据)。<br>**只命中枚举、没有选题证据 → 不成立。** 另:**不得**为此新造 `ContentFunction: Review` —— `ContentFunction` 是受控枚举,没有 Review 值,自造即非法;§2 A 里的自然语言「Review」是帖子意图描述,**不是受控字段值** |
242
+
243
+ **例外不是绕过口:**
244
+
245
+ - 只有「这是 PGC」「这是 Review」的**自我描述**、拿不出先例或内容并非专门讨论该品牌
246
+ → 仍是 `BlockingGap`,不得放行;
247
+ - 例外**不得越过 D 类**(禁止 self-promotion / 高风险板块)与任何披露要求;
248
+ - 例外须**拆字段**记录,不得只塞进一段括号文本:
249
+
250
+ ```markdown
251
+ BrandTitleExposureException: None / PGCApproved / BrandReviewPost
252
+ ExceptionBasis: (PGC:先例 URL + 版规条款;BrandReview:PrimaryPostType/WritingVariant + 选题证据)
253
+ ExceptionScope: (适用到哪些 Key / 哪个 subreddit / 有效期)
254
+ ExceptionApprovedBy: (批准人,≠ 生成本 Brief 的 agent)
255
+ ExceptionApprovedAt: (ISO-8601)
256
+ ```
109
257
 
110
258
  ---
111
259
 
@@ -121,6 +269,11 @@ P-B / C-B 只表示该内容需要承载品牌词,不代表品牌名、SKU、
121
269
  - 同帖型或相近帖型的 Reddit 内容
122
270
  - 已移除 / 被删帖样本中的风险信号
123
271
 
272
+ > **⚠️ §3 是「样本学习理由的记录格式」,不是第二套位置来源(G2)。**
273
+ > 下面五类**不得直接写入 `SelectedPlacement`**,也**不得绕过** §2.0 的机械取值规则
274
+ > (众数档、并列取更晚、标题档 < 20% 不得选标题、既有 P-B/PGC 的取值域限制)。
275
+ > 归类结论与 `SelectedPlacement` 冲突时,**以 §2.0 的取值为准**,并在 Brief 写明差异原因。
276
+
124
277
  每条 P-B 必须归入以下五类之一:
125
278
 
126
279
  ### 1. 样本支持前置露出
@@ -155,7 +308,9 @@ Brief 必须写明:
155
308
 
156
309
  - 中段露出
157
310
  - 后段露出
158
- - 配对评论露出
311
+ - 配对评论露出 —— ⚠️ **仅当该行规划时已是 P-NB**(其配对自评为 C-B)。
312
+ **规划时是 P-B / PGC 的行不得选此项**(见 §2.0 取值域限制),只能后移到中段 / 后段,
313
+ 否则 `BlockingGap` 回规划
159
314
 
160
315
  Brief 必须写明:
161
316
 
@@ -173,17 +328,19 @@ Brief 必须写明:
173
328
  - 板块规则或社区氛围反感推广
174
329
  - 样本显示问题讨论比产品推荐更容易存活
175
330
 
176
- 允许结果:
331
+ 允许结果(⚠️ **区分当前行的既有类型,不得自动重分类**):
177
332
 
178
- - P-NB 主帖
179
- - C-B 评论补位
180
- - 完全不露品牌
333
+ - **本行规划时已是 P-NB** → 可采用 P-NB 主帖 + C-B 评论补位,或完全不露品牌;
334
+ - **本行规划时是 P-B / PGC** → 样本只说明**该主帖的前置位置不被支持**,正确动作是把
335
+ `SelectedPlacement` 后移到**中段 / 后段**(**不含「评论」,也不含「不出现」**),
336
+ 或 `BlockingGap` **回规划决定**;
337
+ **不得**在 Brief 阶段把 P-B 静默改成 P-NB,也不得自行改动配对与配额。
181
338
 
182
339
  Brief 必须写明:
183
340
 
184
- - 为什么主帖不露品牌
341
+ - 为什么主帖不前置品牌
185
342
  - 是否由评论补位
186
- - 如果不补位,品牌配额如何在其他位置补偿
343
+ - 若建议改变行类型或配额:写成**建议 + 回规划确认**,不是已执行的变更
187
344
 
188
345
  ---
189
346
 
@@ -207,27 +364,46 @@ Brief 必须写明:
207
364
 
208
365
  ---
209
366
 
210
- ### 5. 样本不足或不可比
367
+ ### 5. 样本不足或不可比 → **StopAndAsk(不再套默认位置)**
211
368
 
212
369
  使用条件:
213
370
 
214
- - 样本太少
371
+ - 样本太少(`ComparableSampleCount` 不足,或 `BrandMentionSampleCount = 0`)
215
372
  - 帖子被删除,看不到正文
216
373
  - 样本板块不同、帖型不同或语境不可比
217
374
 
218
- 默认处理:
375
+ > **v3 变更(G2):旧版「样本不足时仍按内容类型给默认品牌位置」已删除。**
376
+ > 那四条默认(Review/owner/price/comparison → 标题或首段;Guide/workflow → 中段;
377
+ > Discussion/sensitive → 后段或评论;高风险 → 不露)正是「**位置由帖型标签推导**」,
378
+ > 与 §2.0 的位置来源规则直接冲突。样本不足时套默认,会产出一个**看起来有依据、
379
+ > 实际没有证据**的位置,而这正是「P-B 标题统一加品牌」那类返工的入口。
380
+ > §2 A/B/C/D 仍然有效,但它们是**风险边界**,只能把位置往后推,**不能在没有证据时
381
+ > 把位置往前提到标题或首段**。
219
382
 
220
- - Review / owner / price / product comparison:允许标题或首段露出
221
- - Guide / workflow / checklist:默认中段露出
222
- - Discussion / caution / sensitive scenario:默认后段或评论露出
223
- - 高风险板块:主帖不露品牌
383
+ **样本不足时的正确动作(按序,不得跳到最后一步):**
384
+
385
+ 1. **补样本**:扩大时间窗重采 / 放宽到 `FlairCluster` / 取相邻可比板块;
386
+ 2. **换来源**:改用板块级 SRP 的 `brandFirstMentionHistogram`
387
+ (`../../reddit-strategy-shared/references/subreddit-research-profile.md`;
388
+ 该板块暂无可用 SRP 实例时以 baseline 卡为主来源,不得因其缺失而无条件阻断);
389
+ 3. **停下来问人**:向策略师 / 用户说明「本行缺品牌位置证据,请裁决」,
390
+ 给出可选项与各自风险;
391
+ 4. 仍不成立 → `BlockingGap: BrandPlacementUnsupported`,
392
+ `DecisionStatus: NoComparableEvidence`,本行不得进入写作。
393
+
394
+ **唯二可以在缺证据时仍取标题位置的情况**:§2.5 的 `PGCApproved` 与 `BrandReviewPost`
395
+ 两类合法例外(须满足其全部成立条件并记 `BrandTitleExposureException`)。
224
396
 
225
397
  Brief 必须写明:
226
398
 
227
- - 样本不足原因
228
- - 使用了哪条默认规则
399
+ - 样本不足原因与三个计数字段(`ComparableSampleCount` / `BrandMentionSampleCount` /
400
+ `NoBrandMentionRate`)**加**四档直方图(零分母时后两项填 `N/A`)
401
+ - 走了上述哪一步(补样本 / 换来源 / 问人 / 例外 / BlockingGap)及其结论与批准人
229
402
  - 后续写作时需要特别注意什么
230
403
 
404
+ ⚠️ **不得因为「位置定不下来」就改动配额**:不得把 P-B 静默改成 P-NB,
405
+ 也不得删行或把品牌配额挪到别处凑数 —— 那是规划侧决策,须回规划确认。
406
+
231
407
  ---
232
408
 
233
409
  ## 4. PGC 账号前置验证规则
@@ -257,7 +433,9 @@ Brief 必须写明:
257
433
  - 有竞品 PGC 成功样本:该板块可进入 PGC 候选,但仍需符合 flair、披露、频率、账号历史等条件。
258
434
  - 有竞品 PGC 但集中在 weekly thread / AMA / vendor flair:只能按该路径发,不能普通发帖。
259
435
  - 有品牌名但都是普通用户 UGC:不能直接推导 PGC 可发,只能说明品牌话题可讨论。
260
- - 没有竞品 PGC 样本:默认按 UGC / P-NB / C-B 保守处理。
436
+ - 没有竞品 PGC 样本:**该板块的 PGC 候选**默认按 UGC / P-NB / C-B 保守处理。
437
+ ⚠️ 这条只适用于**尚未定为 PGC 的候选**;**已进入执行表的 PGC 行不得据此自动改成
438
+ P-NB / C-B** —— 那是配额与行类型变更,须回规划确认。
261
439
  - 明确禁止 self-promotion / commercial post / company account:即使竞品出现过,也不能直接判定可用,必须标高风险或排除。
262
440
 
263
441
  ### PGC 可用时的品牌 / SKU 露出
@@ -279,13 +457,15 @@ Brief 必须写明:
279
457
 
280
458
  每条 P-B 主帖 Brief 必须包含:
281
459
 
282
- - 品牌 / SKU 露出位置:标题 / 第一段 / 中段 / 后段 / 评论
460
+ - 品牌 / SKU 露出位置(`SelectedPlacement`):标题 / 第一段 / 中段 / 后段
461
+ —— ⚠️ **P-B / PGC 主帖不含「评论」与「不出现」**(见 §2.0 取值域限制);
462
+ 确需改到评论 = 行类型/配额变更,须回规划并重跑门禁
283
463
  - 露出位置理由
284
464
  - subreddit 规则依据
285
465
  - 帖型与内容意图依据
286
466
  - 样本学习对齐结果
287
467
  - 是否存在 GEO 与 Reddit 原生感冲突
288
- - 如果不前置,具体在什么结构位置或哪条评论露出
468
+ - 如果不前置,具体在正文的什么结构位置露出(P-B / PGC 主帖不得答「放到配对评论里」)
289
469
 
290
470
  每条 PGC 主帖 Brief 还必须包含:
291
471
 
@@ -305,13 +485,20 @@ Brief 必须写明:
305
485
 
306
486
  - [ ] 没有把所有 P-B 批量设置为标题或第一段露出
307
487
  - [ ] 每条 P-B 都单独判断了品牌 / SKU 露出位置
308
- - [ ] Review / owner / price / comparison 才默认允许标题或首段露出
309
- - [ ] Guide / workflow / checklist 默认中段露出
488
+ - [ ] **不存在「因为这行标记 P-B,所以标题写品牌」的推导**(G2 硬拦截)
489
+ - [ ] 每条 **P-B / PGC 主帖**均已填满 `BrandPlacementBasis`,`SelectedPlacement` = 更晚的(§2 风险边界允许的最早位置, 直方图经验位置),且对既有 P-B/PGC 行未取「评论」/「不出现」
490
+ - [ ] 每条 **C-B 评论**填 `InheritedBrandPlacementBasis`(继承配对 P Key;配对为 P-NB 时填 `N/A(PairedPostIsP-NB)`;外部评论填 `N/A(ExternalComment)`)+ `CommentPlacementDecision`;**评论不要求自有 Basis、不单独建直方图**
491
+ - [ ] **P-B / PGC 主帖**的三个计数字段齐全(`ComparableSampleCount` / `BrandMentionSampleCount` / `NoBrandMentionRate`)**且**四档 `BrandFirstMentionHistogram`(标题/首段/中段/结论)已给出(零分母填 `N/A`),`ComparableScopeStatus` 与 `DecisionStatus` 已判定 —— **C-B 评论不适用本项**(无自有直方图)
492
+ - [ ] 直方图档位已按「结论 → 后段」映射换算成 `SelectedPlacement` 受控值
493
+ - [ ] 既有 P-B / PGC 行未被 D 类或高 `NoBrandMentionRate` 静默推成「不出现」/「评论」(该情况须 BlockingGap 回规划)
494
+ - [ ] `BrandMentionSampleCount = 0` 的行未被当作「不允许标题」,而是走了 §3.5 的补样本 / 换来源 / 问人 / 例外 / BlockingGap
495
+ - [ ] 选标题位置的行:直方图「标题」档 ≥ 20%,或持有 `BrandTitleExposureException`(`PGCApproved` 须有真实先例,`BrandReviewPost` 须确为专门讨论该品牌的帖)
496
+ - [ ] §2 A/B/C/D 仅用作风险边界(只能把位置往后推),未被当作位置来源
310
497
  - [ ] 中段露出没有被机械理解为固定第 2-4 段
311
- - [ ] Discussion / caution / sensitive scenario 默认后段或评论露出
312
- - [ ] 高风险板块没有主帖前置品牌
498
+ - [ ] 高风险(D 类)板块没有主帖前置品牌,例外未越过 D 类与披露要求
313
499
  - [ ] 样本学习结果已经写入每条 P-B 的 Brief
314
500
  - [ ] 若样本与 GEO 需求冲突,已说明最终选择理由
501
+ - [ ] 本文件的判定未改动 P-B / P-NB / C-B / C-NB / PGC 配额语义(位置不成立时走 BlockingGap 或回规划,不静默改配额或改行类型)
315
502
  - [ ] 如果使用 PGC,已经完成 PGC account precedent check
316
503
  - [ ] PGC 帖已在执行表标注为 PGC,且帖子品牌词为有
317
504
  - [ ] PGC 发帖板块已确认允许品牌 / vendor / official account 路径