INV-3: changereportcategory Vocabulary Archaeology
INV-3: change_report_category Vocabulary Archaeology
Section titled “INV-3: change_report_category Vocabulary Archaeology”Date: 14/05/2026 · Wave: S236 WP6 INV-3 · Author: INV-3 sub-agent
Branch: content-items-investigation · Source under question: docs/plans/phase-0-investigation/phase-b-prerequisite-1-onthology-pipeline.md §2.1, row change_report_category (NEEDED).
1. Executive Summary
Section titled “1. Executive Summary”No expanded vocabulary located. The 4 starter values in the source row (content_added, content_edited, content_promoted, content_archived) appear ONLY in the source phase-b-prerequisite-1-onthology-pipeline.md itself and the derived docs/ontology/28-change-report-category.md. There is no other authoritative document enumerating a fuller set, no migration, and no Liam ratification beyond ONT.15 (RESOLVED-S234 — closed list ships with digest → change_reports rename).
Critical archaeology finding: the live, shipped MCP tool get_change_report (P1-35, in lib/mcp/tools/change-report.ts) operates on a 3-bucket scheme — additions / updates / removals — not the 4-value scheme in the ontology MD. These are the two parallel realities of “change report category” today. INV-3 cannot reconcile without Liam’s ruling: are the four ontology values the ratified target vocabulary (event-level taxonomy for the future change_reports table), and is the existing 3-bucket tool simply a different surface (a runtime aggregation grouped by event type)? Or should the ontology vocabulary collapse to match the implemented 3-bucket scheme?
Recommended C1 action (preferred): ratify the existing 4 values + close the list, because the change_reports table does not yet exist and these four match the dominant verbs in the digest/change-report code surface (created → added; updated → edited; archived → archived; the new promoted category captures publication-state transitions per the §5.2 publication lifecycle). Status planned, awaiting combined-PR Q-OQR1-16 schema. Notes section flags the 3-bucket tool divergence for ratifier wave.
2. Search Log
Section titled “2. Search Log”| # | Tool / location | Query | Result |
|---|---|---|---|
| 1 | grep | change_report_category across docs/ scripts/ lib/ types/ supabase/ app/ | 7 hits — all in 4 ontology/plan documents (no specs, no code). |
| 2 | grep | digest_category across same paths | 0 hits. The concept is not surfaced as a column or constant under that name. |
| 3 | grep | content_added|content_edited|content_promoted|content_archived | 6 hits — all in 28-change-report-category.md and the source plan §2.1 row. Zero hits in code. |
| 4 | grep | ”change report” / “change_report” across docs/ | 30+ hits across plans, specs, audits, ontology — none enumerating a vocabulary beyond the source row. |
| 5 | grep | ”change report” / “change_report” across lib/ types/ app/ components/ supabase/ | Concentrated in lib/mcp/tools/change-report.ts (P1-35), lib/mcp/formatters/change-report.ts, lib/digest/digest-export.ts, app/digest/, lib/validation/schemas.ts (email_weekly_change_report, auto_generate_change_reports notification prefs), app/api/notifications/preferences/route.ts. No vocabulary enum. |
| 6 | grep | change_type enum live values (CHECK constraint) | content_history.change_type has 11 values: create, edit, ai_update, import, merge, rollback, archive, delete, metadata_change, owner_change, publication_state (per migration 20260427164439_extend_content_history_change_type_for_publication_state.sql). This is a different but adjacent vocabulary (history events on a single content_item, not aggregated change-report categories). |
| 7 | mcp__supabase__execute_sql | digests table schema | 15 columns; no category column. Only digest_type (weekly, daily, custom — cadence, not category). 2 prod rows, both weekly. |
| 8 | mcp__supabase__execute_sql | tables matching %change% or %digest% | Only digests exists. No change_reports table yet — confirms ONT.15 “ships with digest → change_reports rename” hasn’t landed. |
| 9 | Read | lib/mcp/tools/change-report.ts (full file) | Authoritative live code: P1-35 get_change_report MCP tool uses 3-bucket scheme: additions (newly created in window), updates (modified in window but pre-existing), removals (archived in window). Each bucket queried independently from content_items by created_at / updated_at / archived_at timestamps. No category column read or written anywhere. |
| 10 | Read | lib/mcp/formatters/change-report.ts | Confirms ChangeReportData TypeScript interface uses additions: { count, items }, updates: { count, items }, removals: { count, items }. No category enum. |
| 11 | Read | docs/specs/p1-35-get-change-report-spec.md (full spec) | Confirms 3-bucket design ratified at P1-35 implementation time. “Open questions: None” — this was a settled design. No mention of a change_report_category ontology CV. |
| 12 | grep | docs/specs/ for change_report_category / change-report-category | Only INV-3 sibling files (verifier reports). No spec enumerates the vocabulary. |
| 13 | Read | docs/plans/phase-0-investigation/0.9-decision-graph.md ONT.15 row | ”RESOLVED-S234 — closed list ships with digest → change_reports rename”. Closed-CORE ratification, but no list expansion. |
| 14 | grep | phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.md for change_report_category | Confirms `CORE (closed) |
| 15 | mempalace_search | ”change_report_category vocabulary content_promoted Liam ratification” | 0 relevant hits — no Liam ratification of expanded vocabulary in mempalace. |
| 16 | mempalace_search | ”digest category additions updates removals enum” | 0 relevant hits. |
| 17 | find | .planning/.archive/.specs/ for digest/change-report | One archived spec found: digest-detail-route-spec.md (UI/route spec, not vocabulary). |
Bottom line: every documented mention of change_report_category traces back to the source row in §2.1, which itself ends in “etc.” The 4 values are the only candidates that exist anywhere in the corpus. The actual implemented get_change_report tool uses a separate 3-bucket scheme that has no vocabulary enum (the buckets are computed from timestamp filters, not stored as a column).
3. Authoritative Source(s) Located
Section titled “3. Authoritative Source(s) Located”3.1 Primary source — phase-b-prerequisite-1-onthology-pipeline.md §2.1
Section titled “3.1 Primary source — phase-b-prerequisite-1-onthology-pipeline.md §2.1”docs/plans/phase-0-investigation/phase-b-prerequisite-1-onthology-pipeline.md:71 (verbatim):
| `change_report_category` (NEEDED — not built) | new vocabulary | content_added, content_edited, content_promoted, content_archived, etc. | Change reports (digest rename) needs typed vocabulary |The etc. is unresolved. This is the only enumeration in the corpus.
3.2 Decision-graph status — 0.9-decision-graph.md ONT.15
Section titled “3.2 Decision-graph status — 0.9-decision-graph.md ONT.15”docs/plans/phase-0-investigation/0.9-decision-graph.md:455 (verbatim):
| ONT.15 | `change_report_category` Layer-1 CV | **RESOLVED-S234** — closed list ships with digest → change_reports rename | Onto-doc §2.1 |This locks classification (CLOSED-CORE) but doesn’t expand the list.
3.3 Feedback investigation — phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.md
Section titled “3.3 Feedback investigation — phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.md”docs/plans/phase-0-investigation/phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.md:663 (verbatim):
| `change_report_category` (NEEDED) | **CORE (closed)** | Platform vocab. | CORE. |Confirms CORE-closed classification, no list.
3.4 Existing ontology MD — docs/ontology/28-change-report-category.md
Section titled “3.4 Existing ontology MD — docs/ontology/28-change-report-category.md”Already contains the 4 starter values verbatim (drafter A1 transcribed from §2.1, which is correct). Status: needed. Notes line 46 explicitly flags: “Source §2.1 lists ‘etc.’ after these — verifier sub-agent should enumerate the full set or flag as needs-Liam-input.”
3.5 Combined-PR scope — 0.9-decision-graph.md §11.3 item 7
Section titled “3.5 Combined-PR scope — 0.9-decision-graph.md §11.3 item 7”docs/plans/phase-0-investigation/0.9-decision-graph.md:486:
7. Digests rename: `digests` → `change_reports` (Q5.x); cron + UI text updatesConfirms the rename lands in the combined PR (Q-OQR1-16) but does NOT prescribe a category column or vocabulary.
4. Full Vocabulary List (with Definitions and Provenance)
Section titled “4. Full Vocabulary List (with Definitions and Provenance)”Based on the only authoritative enumeration (§2.1) and code-side reality:
| # | Key | Label | Provenance | Definition (proposed by INV-3) | Source |
|---|---|---|---|---|---|
| 1 | content_added | Content Added | core | A new content_items row was created within the change-report window (matches get_change_report “additions” bucket: created_at >= cutoff AND archived_at IS NULL). | phase-b-prerequisite-1-onthology-pipeline.md:71 + maps to lib/mcp/tools/change-report.ts:96-110 |
| 2 | content_edited | Content Edited | core | An existing content_items row was modified within the window (matches “updates” bucket: updated_at >= cutoff AND created_at < cutoff AND archived_at IS NULL). Maps to content_history.change_type IN ('edit', 'ai_update', 'metadata_change') events. | phase-b-prerequisite-1-onthology-pipeline.md:71 + maps to lib/mcp/tools/change-report.ts:113-127 |
| 3 | content_promoted | Content Promoted | core | A content_items row transitioned publication_status from draft or in_review to published within the window. Maps to content_history.change_type='publication_state' (added in migration 20260427164439). No equivalent bucket in the live get_change_report tool today — the existing tool predates the publication-lifecycle work and conflates this into “updates”. | phase-b-prerequisite-1-onthology-pipeline.md:71 + inferred from §5.2 publication-lifecycle spec (docs/specs/publication-lifecycle-state-machine-spec.md) |
| 4 | content_archived | Content Archived | core | A content_items row had archived_at set within the window (matches “removals” bucket: archived_at >= cutoff). Maps to content_history.change_type IN ('archive', 'delete'). | phase-b-prerequisite-1-onthology-pipeline.md:71 + maps to lib/mcp/tools/change-report.ts:130-142 |
Additions found via archaeology
Section titled “Additions found via archaeology”NONE. No additional values located in any authoritative source. The “etc.” in §2.1 was speculative shorthand; no follow-up document expanded it.
Adjacency note — content_history.change_type (CV 11) is NOT this vocabulary
Section titled “Adjacency note — content_history.change_type (CV 11) is NOT this vocabulary”content_history.change_type is the per-event audit-row type (one row per state change on one content_item). Live values: create, edit, ai_update, import, merge, rollback, archive, delete, metadata_change, owner_change, publication_state. The ontology’s CV 11 covers this column.
change_report_category (CV 28) is one cardinality up — it categorises Change Report rows themselves (a Change Report aggregates many content_history events for a domain/window). Mapping above shows how the 4 categories collapse the 11 history-event types into a user-facing 4-bucket taxonomy.
5. Code-Side Reality
Section titled “5. Code-Side Reality”5.1 No TypeScript enum exists
Section titled “5.1 No TypeScript enum exists”There is no TS const tuple, Zod enum, or interface field that names the 4 categories. The closest analogues are:
-
ChangeReportDatainterface (lib/mcp/formatters/change-report.ts:23-32):export interface ChangeReportData {period_days: number;start_date: string;end_date: string;domain: string | null;keywords: string[] | null;additions: { count: number; items: ChangeReportItem[] };updates: { count: number; items: ChangeReportItem[] };removals: { count: number; items: ChangeReportItem[] };}This is a 3-bucket scheme with bucket names hardcoded as object keys, not enum values.
-
digestTypeLabel(lib/digest/digest-helpers.ts:1-13): switches onweekly/daily/custom— that’sdigest_type(cadence), notchange_report_category. -
types/digest.tshasDigest/DigestDomainSummary/DigestGovernanceSummaryinterfaces — none carry a category enum.
5.2 Live database state
Section titled “5.2 Live database state”mcp__supabase__execute_sql on prod project rovrymhhffssilaftdwd:
digeststable exists with 15 columns (id, digest_type, period_start, period_end, item_count, domain_summaries, theme_clusters, narrative_summary, generated_at, generated_by, tokens_used, metadata, created_at, item_ids, created_by). Nocategorycolumn.- 2 prod rows; both
digest_type='weekly'. - No
change_reportstable — confirms the rename hasn’t landed.
5.3 get_change_report MCP tool reality
Section titled “5.3 get_change_report MCP tool reality”The live, shipped tool (P1-35, lib/mcp/tools/change-report.ts) categorises by timestamp filters, not by a stored category column:
- Additions =
created_at >= cutoff AND archived_at IS NULL(would map tocontent_added). - Updates =
updated_at >= cutoff AND created_at < cutoff AND archived_at IS NULL(would map tocontent_edited; conflatescontent_promotedsince publication_state transitions also bumpupdated_at). - Removals =
archived_at >= cutoff(would map tocontent_archived).
No content_promoted bucket exists in the tool today. Promotions show up as updates.
6. Recommended C1 Action for 28-change-report-category.md
Section titled “6. Recommended C1 Action for 28-change-report-category.md”Recommended action: PROCEED with the 4 starter values; replace “etc.” narrative with explicit closed-list framing.
Section titled “Recommended action: PROCEED with the 4 starter values; replace “etc.” narrative with explicit closed-list framing.”Reasoning
Section titled “Reasoning”- The 4 values map cleanly onto the existing
content_history.change_typeenum and theget_change_reporttool’s 3-bucket scheme + the publication-state event added in20260427164439. They cover the full change-event surface area today. - ONT.15 ratification (RESOLVED-S234) explicitly says “closed list ships with digest → change_reports rename”. A closed list with 4 values is a sufficient first cut; the combined PR Q-OQR1-16 lands the schema where
change_reports.categorywill be added. - No alternative or additional values exist anywhere in the corpus. Asking Liam to confirm the 4 (rather than asking him to draft net-new vocabulary) is the lower-friction path.
- The 3-bucket vs 4-value divergence with the live tool is reconcilable: the tool’s 3 buckets are a runtime aggregation of
change_reportsrows by theircategory. A future refactor ofget_change_reportto read fromchange_reports.categorywould naturally split “updates” into “edited” + “promoted” — a quality-of-life improvement, not a breaking change.
Concrete edits for C1
Section titled “Concrete edits for C1”-
Frontmatter
status:— change fromneeded→planned(consistent with other CVs whose target column doesn’t exist yet, e.g. CV 20chunk-kind, CV 22origin-kind). -
§Definition — keep current prose; add one sentence at the end:
Closed enumeration of 4 values, ratified S234 (ONT.15) as CORE-closed. No further values planned for v1; future event types may be added in a CHECK-extending migration.
-
§Baseline values — keep the 4 rows as they are; remove line 46 (“Source §2.1 lists ‘etc.’ after these — verifier sub-agent should enumerate the full set or flag as needs-Liam-input.”) since INV-3 has resolved this.
-
§Notes — add the following bullets:
- Provenance: Source §2.1 (the only enumeration in the corpus) lists 4 values + “etc.” Archaeology (S236 INV-3) found no additional values across
docs/,lib/,types/,supabase/migrations/,.planning/.archive/, mempalace, or the live DB. Recommendation: ratify the 4 + close the list. No further Liam input required unless he wishes to add a 5th category at this stage. - Code-side divergence: The live
get_change_reportMCP tool (lib/mcp/tools/change-report.ts, P1-35) categorises by 3 timestamp buckets (additions/updates/removals) computed at query time, NOT by reading acategorycolumn. Whenchange_reports.categorylands in the combined PR Q-OQR1-16, the tool can be refactored to split “updates” intocontent_edited+content_promoted(publication-state transitions). This is a quality-of-life improvement, not a breaking change. - Mapping to
content_history.change_type(CV 11): the 4 categories aggregate the 11 per-event types as follows:content_added←create/import;content_edited←edit/ai_update/metadata_change/owner_change;content_promoted←publication_state(only when transitioning topublished);content_archived←archive/delete.mergeandrollbackmay map tocontent_editedor be excluded from change reports entirely (open question for ratifier wave).
- Provenance: Source §2.1 (the only enumeration in the corpus) lists 4 values + “etc.” Archaeology (S236 INV-3) found no additional values across
-
§Relationships — keep current prose; tighten the line about
change_type(CV 11) to reflect the explicit aggregation mapping in the §Notes bullet above.
Open items (low priority, not blocking ratification)
Section titled “Open items (low priority, not blocking ratification)”- (a) Should
mergeandrollbackchange_typeevents surface in change reports at all? They’re administrative/recovery operations; arguably not user-relevant. Recommendation: exclude from v1; revisit if user feedback requests. - (b) Should
content_promotedalso fire onpublished → archived(deprecation event), or only on transitions INTOpublished? Recommendation: only INTOpublished. Deprecation should map tocontent_archivedsincearchived_atis set at the same time.
7. Provenance Summary
Section titled “7. Provenance Summary”| Claim | Evidence |
|---|---|
| 4 values are the only enumeration in the corpus | grep across docs/ scripts/ lib/ types/ supabase/ app/ returned 6 hits, all in 28-change-report-category.md + source §2.1 row. |
| ONT.15 ratifies “closed list” classification | docs/plans/phase-0-investigation/0.9-decision-graph.md:455 verbatim. |
| Feedback investigation confirms CORE-closed | phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.md:663 verbatim. |
change_reports table doesn’t exist yet | mcp__supabase__execute_sql confirms only digests table exists. |
digests has no category column | mcp__supabase__execute_sql on information_schema.columns confirms 15 columns, no category. |
| Live tool uses 3 timestamp buckets, not 4 categories | lib/mcp/tools/change-report.ts:96-142 and lib/mcp/formatters/change-report.ts:23-32. |
| No TS enum exists for the 4 categories | grep across lib/ types/ returned zero matches for any of the 4 values. |
content_history.change_type is the per-event vocabulary (CV 11), not this CV | Migration 20260427164439_extend_content_history_change_type_for_publication_state.sql enumerates 11 values; docs/ontology/28-change-report-category.md notes the one-to-many adjacency. |
| Mempalace has no Liam ratification of expanded vocabulary | mempalace_search queries returned 0 relevant hits across 15 candidates each. |
8. Verification SQL (reproducible)
Section titled “8. Verification SQL (reproducible)”-- digests table schema (no category column)SELECT column_name, data_type, is_nullable, column_defaultFROM information_schema.columnsWHERE table_name = 'digests' AND table_schema = 'public'ORDER BY ordinal_position;
-- digest_type live values (cadence, not category)SELECT digest_type, COUNT(*) FROM digests GROUP BY digest_type ORDER BY count DESC;
-- Confirm change_reports table doesn't exist yetSELECT table_name FROM information_schema.tablesWHERE table_schema = 'public' AND (table_name LIKE '%change%' OR table_name LIKE '%digest%')ORDER BY table_name;
-- Adjacent CV 11 — content_history.change_type live CHECK enum (11 values post-migration 20260427164439)SELECT pg_get_constraintdef(oid)FROM pg_constraintWHERE conname = 'content_history_change_type_check';Appendix A — Files Verified, Not Modified
Section titled “Appendix A — Files Verified, Not Modified”This investigation reads the following but does not edit any of them:
docs/ontology/28-change-report-category.mddocs/ontology/README.mddocs/plans/phase-0-investigation/phase-b-prerequisite-1-onthology-pipeline.mddocs/plans/phase-0-investigation/0.9-decision-graph.mddocs/plans/phase-0-investigation/phase-b-prerequisite-1-onthology-pipeline-feedback-investigation.mddocs/specs/p1-35-get-change-report-spec.mdlib/mcp/tools/change-report.tslib/mcp/formatters/change-report.tslib/digest/digest-helpers.tslib/digest/digest-export.tstypes/digest.tssupabase/migrations/20260427164439_extend_content_history_change_type_for_publication_state.sql
Per agent prompt §Constraints: “Do NOT touch any path outside docs/specs/wp6-ontology-harness/investigations/.”