Skip to main content

CREATE_CONCEPTS_LOG_INSERT

Constant CREATE_CONCEPTS_LOG_INSERT 

Source
pub const CREATE_CONCEPTS_LOG_INSERT: &str = "\n    CREATE TRIGGER IF NOT EXISTS trg_concepts_log_insert\n    AFTER INSERT ON concepts\n    WHEN NOT EXISTS (\n        SELECT 1 FROM sqlite_master\n        WHERE type = \'table\' AND name = \'macrame_archive_session\'\n    )\n    BEGIN\n        INSERT INTO transaction_log (table_name, entity_id, operation, payload, recorded_at)\n        VALUES (\'concepts\', NEW.id, \'I\',\n                json_object(\'v\', 2, \'title\', NEW.title, \'content\', NEW.content,\n                            \'valid_from\', NEW.valid_from, \'valid_to\', NEW.valid_to,\n                            \'retired\', NEW.retired,\n                            \'embedding_model\', NEW.embedding_model),\n                NEW.recorded_at);\n    END;\n    ";
Expand description

The concepts insert log trigger, marker-gated since v10 (0.9.0, C3).

§Why an archive session must not log a concept insert

Rehydration is a physical move back and mints no transaction-time facts (§2.3): the concept returns to the hot table, the log entries describing it were never removed, and nothing about what was believed — or when — has changed. An unconditional AFTER INSERT makes that impossible to honour, because the move is an insert.

And the damage is worse than a spurious row, which is what forced the rung. The rehydrated row carries its original recorded_at, but the log row it would write gets a new seq_id at the end of the log. The fold partitions by (table_name, entity_id) and takes ROW_NUMBER() OVER (… ORDER BY seq_id DESC) = 1 — last writer wins by sequence, not by timestamp. So the rehydration 'I' would outrank the later 'U' that retired the concept, and every reconstruct after the original creation time would return it un-retired. Rehydration would resurrect a belief the ledger had superseded, silently and retroactively, which is precisely what [Doctrine III] forbids.

Only the insert trigger is gated. trg_concepts_log_update stays unconditional because nothing inside a session updates a concept — archival deletes and rehydration inserts — so gating it would suppress nothing and widen the hole for no reason.