:relationsThe proposal is a one-line change to futon1b_graph.clj:
(def ^:private retractable-tables #{:entities :hyperedges})
;; becomes
(def ^:private retractable-tables #{:entities :hyperedges :relations})
This page shows what that line actually buys, using a real pattern that is in the store right now.
Since this morning the watcher writes each .flexiarg file as
three kinds of document. Taking
baldwin/two-claims-not-one, a real pattern the new ingest path
wrote today:
| kind | table | count | example id |
|---|---|---|---|
| pattern entity | :entities | 1 | baldwin/two-claims-not-one |
| clause entities | :entities | 7 | baldwin/two-claims-not-one/because |
| relations | :relations | 7 | :pattern/has-because |
15 documents for one pattern. The seven clause entities are the five required components plus conclusion and next-steps. The relations are what tie them to the parent — without them the clauses are seven loose paragraphs with no pattern to belong to.
One real relation, fetched from the store just now:
{:relation/from "baldwin/two-claims-not-one",
:relation/to "baldwin/two-claims-not-one/because",
:relation/type :pattern/has-because,
:relation/provenance {:note ":pattern/has-because",
:source "multi-watcher-flexiarg"}}
retractable-tables is the allow-list for
POST /api/alpha/documents/retract. It contains
:entities and :hyperedges. It does not contain
:relations.
| documents | can retract? |
|---|---|
| 1 pattern entity | yes |
| 7 clause entities | yes |
| 7 relations | no — no endpoint accepts them |
So a delete removes 8 of the 15 and leaves seven relations
pointing at documents that no longer exist. POST /api/alpha/relation
is upsert-only; there is no delete path at all.
Two patterns were re-filed today. Both left orphans, and both still answer
200:
math-informal-CT/verify-universal-property 200 correct, new location
math-informal/verify-universal-property 200 ORPHAN — file moved away
math-strategy/clarification-meta 200 ORPHAN — file deleted
The first orphan is the one that bites. It still reports its family as
math-informal for a pattern we deliberately re-classified as
category theory. Retrieval can therefore still serve the
mis-classification we just corrected.
Two moves produced two orphans. The re-filing manifest waiting behind this is roughly forty moves.
The deletion itself is already table-generic — this is the existing body of
retract-documents!:
(xt/execute-tx node
(mapv (fn [{:keys [table id]}] [:delete-docs table id]) documents))
;; and the post-commit read-back check, also generic:
(filterv (fn [{:keys [table id]}] (fxt/present? node table id)) documents)
[:delete-docs table id] takes the table as a parameter. The
:hyperedges-specific follow-up work — cache invalidation, memory
projection refresh — is already guarded by
(= :hyperedges (:table %)), so relations skip it harmlessly.
Adding :relations to the allow-list means the watcher can send
one atomic request naming all fifteen documents, and get the existing
read-back verification for free:
{:documents [{:table "entities" :id "baldwin/two-claims-not-one"}
{:table "entities" :id "baldwin/two-claims-not-one/because"}
...
{:table "relations" :id "rel|baldwin/two-claims-not-one|..."}]}
Cascading would mean futon1b knowing that :pattern/has-*
relations belong to a pattern entity — i.e. embedding pattern semantics in the
store. Letting the caller name what it wants removed keeps that knowledge in
the watcher, where the pattern shape is already understood. It also keeps the
operation atomic and verifiable, which cascade would complicate.
Were relations excluded on purpose?
The API contract says the counter-ratchet protects the classes
:entity :relation :descriptor :docbook, and explicitly notes that
“hyperedges/evidence are not protected — deletes
pass.”
So relations sit in a protected class while hyperedges do not, and the
retraction allow-list happens to match that split exactly. That may be
coincidence, or it may be the reason. If it is the reason, this is not a
one-liner and the ratchet needs an :allow-drop-classes entry
rather than a wider allow-list.
This is the only part I would not change without a ruling.
The re-filing stays blocked, or it proceeds and leaves ~40 orphans that
answer 200 with stale classifications. Codex-3 refused to
implement the partial version — retract the entities, strand the relations —
citing the no-workarounds invariant, and that was the right call.