Files
breakpilot-compliance/ai-compliance-sdk/migrations/153_iace_children_reconcile.sql
T
Benjamin Admin afb3f83f30 feat(iace): cross-domain precision overhaul + component review + schema reconcile
Engine precision (stop foreign-machine patterns leaking into a project):
- Wire project.MachineType into the engine machine-type gate (empty input no
  longer fires every machine class — press/cnc/excavator/crane/medical...).
- Capability-domain gating extended by 7 domains (outdoor, ventilation,
  machining, bulk, palletizer, playground, fitness) so domain-specific hazards
  only fire when the narrative names that domain; emitted via keyword_dictionary.
- Relevance backstop moved into iace (single gating contract, testable), and its
  dominant false-anchor class removed (a long pattern word no longer matches a
  short common token; prepositions/leitung added to the generic stoplist).
- New guard tests: TestCrossDomainPrecision (full pipeline, 0 foreign per GT) and
  TestPatternReachability now asserts 0 dead patterns. Both GTs keep coverage 1.0.

Reachability fix: the 51 dead patterns required electrical/pneumatic/hydraulic
tags nothing produced — renamed to the canonical electrical_energy/
pneumatic_pressure/hydraulic_pressure/hydraulic_part.

Component review (negation is best-effort + expert-correctable):
- Parser surfaces negated components (ComponentMatch.Negated) instead of dropping
  them; negated contribute no tags/energy → no phantom hazards.
- presence_status (vorhanden|nicht_vorhanden|geloescht) + ce_marked on components;
  only `vorhanden` feed matching. CE+safety-relevant flags the PL/SIL obligation.
- Force re-seed preserves the expert's component decisions instead of wiping them.
- Tag-based component→hazard assignment (was: all on the first component).
- Negation-aware narrative parsing ("keine Pneumatik" no longer extracts it).

Local-dev DB: ai-sdk sets search_path=compliance,core,public; reconcile migrations
152-156 bring the consolidated local iace tables to the current schema + add the
presence_status/ce_marked columns. Machine-type vocabulary endpoint for the form.

[migration-approved]

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 17:15:55 +02:00

71 lines
3.4 KiB
SQL

-- Migration 153: reconcile iace_components / iace_hazards / iace_mitigations
-- with the current Go schema.
-- ==========================================================================
-- Same drift as 152 (iace_projects): the consolidation copied an OLDER table
-- generation with different column names (title vs name, component_ids vs
-- component_id, safety_relevant vs is_safety_relevant). This adds every column
-- the current store layer reads/writes and relaxes legacy NOT NULL columns the
-- code no longer fills, so INSERTs succeed. Idempotent + guarded.
-- ==========================================================================
-- iace_components
ALTER TABLE iace_components
ADD COLUMN IF NOT EXISTS is_safety_relevant boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS is_networked boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS sort_order integer NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS parent_id uuid,
ADD COLUMN IF NOT EXISTS description text,
ADD COLUMN IF NOT EXISTS version text,
ADD COLUMN IF NOT EXISTS metadata jsonb;
-- iace_hazards
ALTER TABLE iace_hazards
ADD COLUMN IF NOT EXISTS component_id uuid,
ADD COLUMN IF NOT EXISTS library_hazard_id uuid,
ADD COLUMN IF NOT EXISTS name text,
ADD COLUMN IF NOT EXISTS scenario text,
ADD COLUMN IF NOT EXISTS sub_category text,
ADD COLUMN IF NOT EXISTS machine_module text,
ADD COLUMN IF NOT EXISTS function text,
ADD COLUMN IF NOT EXISTS lifecycle_phase text,
ADD COLUMN IF NOT EXISTS hazardous_zone text,
ADD COLUMN IF NOT EXISTS trigger_event text,
ADD COLUMN IF NOT EXISTS affected_person text,
ADD COLUMN IF NOT EXISTS possible_harm text,
ADD COLUMN IF NOT EXISTS review_status text;
-- iace_mitigations
ALTER TABLE iace_mitigations
ADD COLUMN IF NOT EXISTS name text,
ADD COLUMN IF NOT EXISTS verification_method text,
ADD COLUMN IF NOT EXISTS verification_result text,
ADD COLUMN IF NOT EXISTS verified_at timestamptz,
ADD COLUMN IF NOT EXISTS verified_by uuid,
ADD COLUMN IF NOT EXISTS is_relevant boolean NOT NULL DEFAULT false,
ADD COLUMN IF NOT EXISTS is_customer_standard boolean NOT NULL DEFAULT false;
-- Relax legacy NOT NULL columns the current code never writes.
DO $$
DECLARE
rec record;
BEGIN
FOR rec IN SELECT * FROM (VALUES
('iace_components','tenant_id'),('iace_components','safety_relevant'),('iace_components','tags'),
('iace_hazards','tenant_id'),('iace_hazards','title'),('iace_hazards','component_ids'),
('iace_hazards','library_id'),('iace_hazards','severity'),('iace_hazards','exposure'),
('iace_hazards','probability'),('iace_hazards','avoidance'),('iace_hazards','risk_score'),
('iace_hazards','risk_level'),
('iace_mitigations','tenant_id'),('iace_mitigations','project_id'),('iace_mitigations','title'),
('iace_mitigations','sub_type'),('iace_mitigations','control_ids'),
('iace_mitigations','verification_evidence')
) AS t(tbl, col)
LOOP
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = rec.tbl AND column_name = rec.col
) THEN
EXECUTE format('ALTER TABLE %I ALTER COLUMN %I DROP NOT NULL', rec.tbl, rec.col);
END IF;
END LOOP;
END $$;