KB-7657

RP DOT Pivot-Update — 02 Tool Design + Implementation

4 min read Revision 1
registries-pivotdot-pivot-updatetool-design2026-06-03

02 — dot-pivot-update: Design + Implementation

Full script: artifacts/dot-pivot-update (deployed to /opt/incomex/dot/bin/dot-pivot-update, 14392 bytes, +x).

Conventions followed (from reading the live framework)

Matched dot-matrix-update/dot-matrix-retire exactly: #!/usr/bin/env bashset -euo pipefailsource ../config/environment.sh (functions only; init_environment NOT called to avoid the interactive cloud read -p confirm) → VERSION/VPS_*/PG_* env defaults → log_info/ok/warn/errpg_sql() that auto-detects on-VPS (docker exec) vs remote (ssh) → --flag "$2"; shift 2 arg parsing → validate → UPDATE ... updated_at=NOW() → verify. Added -v ON_ERROR_STOP=1 so any server/trigger error yields non-zero exit. Header carries CHECKED-NO-DUPLICATE and a description (Đ3 metadata requirement).

Interface

dot-pivot-update --code <PIV-xxx> --field <f> --value <v> [--reason "..."] [--commit] [--allow-noop]
dot-pivot-update --code <PIV-xxx> --field composition_level --auto-from-species [--commit]
dot-pivot-update --show --code <PIV-xxx>
  • Default = DRY-RUN: applies the UPDATE inside BEGIN..ROLLBACK, prints OLD→NEW and the mapping-view composition_status, then ROLLBACK. Commits nothing. --commit persists.
  • --auto-from-species (composition_level only): sets value := the governed entity_species.composition_level for the row's species → the deterministic cleanup driver.
  • --show: prints current classification + governed species composition (read-only).

Allowlist + governed validation

Field Validation
(any) must be in {composition_level, species, registry_group, description} — else reject
species must exist in entity_species.species_code (governed)
composition_level if row has a governed species → value must equal that species' governed composition (deterministic guard); else value must be a known composition derived live from entity_species ∪ pivot_definitions (regex-filtered, never hardcoded)
registry_group must be a value already in use or a governed FAC-02 taxonomy code; else reject (→ council naming packet)
description non-empty

Other guards: --code must exist and be active (retired rows refused); no-op refused unless --allow-noop; exactly one of --value / --auto-from-species; single-quote SQL escaping via esc().

Trigger integration (intentional, Đ26 §II-QUINQUIES 1F)

A single-row, single-field UPDATE fires only trg_after_pivot_definitions_change (statement-level → refresh_meta_catalog_from_pivot() + refresh_pivot_results()), once per invocation. It does not fire trg_birth_pivot_definitions (INSERT-only) nor trg_matrix_config_changed (the 3 targets have matrix_spec IS NULL). Because the changed columns (composition/species/registry_group) do not affect pivot_query output, the refresh recomputes identical result values (only refreshed_at bumps) — the system's own designed consistency cascade, not a tool emit. Single-row scope = no row-by-row refresh explosion (the explicit requirement).

Why no manual rollback symmetry (by design)

The forward fix converges composition_level to the governed truth. The inverse value (the old drift) is rejected by the governed guard — you cannot use the tool to re-introduce known-wrong drift. Pre-fix values are recorded (molecule/atom/atom) for a DBA-level restore if ever required, but the lawful state is the governed one.

Deviations / honesty notes

  • description is allowlisted but unused this macro (kept for completeness/parity).
  • registry_group validation is conservative; it is not exercised in the executed cleanup (naming is council-gated, §06).
  • One bug was found and fixed during rehearsal (boolean inactive-guard) — see §04.
Back to Knowledge Hub knowledge/dev/reports/architecture/registries-pivot-dot-pivot-update-author-register-cleanup-2026-06-03/02-dot-update-tool-design-and-implementation.md