cocottetech/@platform/infrastructure/sql/migrations/0010_content_asset_classification.sql
autocommit ed436ea97e feat(content-pipeline): content-social engine, content-ingestor, platform.api endpoints
Stranded-worktree preservation commit (this branch is local-only + 28 behind
main; ACS watches the main tree, not this worktree, so committing manually so
the work isn't lost). Integration to main is a follow-up.

- @features/content-social/ai-core: drop derive engine + K3 gate (21 tests)
- @features/content-ingestor: classify-newest-first + configurable 1wk-offset
  hot/stocked planner (17 tests)
- platform-api: content-assets / content-drops / content-drop-legs CRUD modules
  + entities + enums; content-drops asset_ids enrichment + cluster endpoints;
  content-assets filtered list + idempotent upsert
- platform-api fixes (also latent-broken on main): ioredis named import,
  entities spread, agent-actions @ApiProperty, content-post confidence transformer
- migrations: 0009_content_drops (renumbered from 0007 — main holds 0007/0008),
  0010_content_asset_classification (is_explicit/content_class/quality_score,
  is_explicit DEFAULT TRUE fail-safe)
- design: content-drop-composer.screen + content-drop.flow

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 11:15:52 -07:00

35 lines
1.8 KiB
PL/PgSQL

-- 0010_content_asset_classification.sql
--
-- Adds vision-classification signals to content_assets so they round-trip
-- between the content-ingestor (which SETS them, via @model-boss) and
-- content-social's K3 gate (which CONSUMES is_explicit). Before this, the
-- classification was folded into `tags` only and did not survive a read-back,
-- so an explicit asset could read as SFW to the ban-risk gate.
--
-- Spec: content-pipeline-classify-and-offset; consumed by specialist-content-social.
-- Layers on content_assets (0001). Independent of 0007_surface_bump_policy /
-- 0008_fix_surface_rls_guc (main) and 0009_content_drops.
--
-- SAFETY — is_explicit DEFAULT TRUE (fail-safe): an UNCLASSIFIED asset must not
-- read as safe-for-SFW-surfaces to K3a. The ingestor's classifier sets the real
-- value on every asset it writes; manually-uploaded assets stay SFW-restricted
-- until classified or hand-flagged in the asset library.
BEGIN;
CREATE TYPE content_class AS ENUM ('hot', 'stocked');
ALTER TABLE content_assets
ADD COLUMN is_explicit BOOLEAN NOT NULL DEFAULT TRUE,
ADD COLUMN content_class content_class NULL,
ADD COLUMN quality_score NUMERIC(4, 3) NULL
CONSTRAINT content_assets_quality_chk CHECK (quality_score IS NULL OR (quality_score >= 0 AND quality_score <= 1));
COMMENT ON COLUMN content_assets.is_explicit IS
'Vision-classified K3a routing signal. DEFAULT TRUE is a fail-safe: unclassified assets are treated as explicit so they are never auto-routed to SFW surfaces until classified.';
COMMENT ON COLUMN content_assets.content_class IS
'hot = fresh/timely (rides the posting offset); stocked = evergreen backfill for calendar gaps. NULL until classified.';
COMMENT ON COLUMN content_assets.quality_score IS
'Vision quality score 0..1; NULL until classified.';
COMMIT;