|
260 | 260 | :unset-expiry (-> acc (dissoc :expiry) (assoc :unexpiry? true)) |
261 | 261 | :set-topic (assoc acc :topic topic) |
262 | 262 | :unset-topic (-> acc (dissoc :topic) (assoc :untopic? true)) |
263 | | - :set-superseded (cond-> acc |
264 | | - :always (assoc :superseded-by target-message-id) |
265 | | - :always (dissoc :unsuperseded-by? :unsuperseded-by-mid)) |
266 | | - :unset-superseded (cond-> acc |
267 | | - :always (dissoc :superseded-by) |
268 | | - :always (assoc :unsuperseded-by? true) |
269 | | - target-message-id (assoc :unsuperseded-by-mid target-message-id)) |
270 | | - :set-supersedes (cond-> acc |
271 | | - :always (assoc :supersedes target-message-id) |
272 | | - :always (dissoc :unsupersedes? :unsupersedes-mid)) |
273 | | - :unset-supersedes (cond-> acc |
274 | | - :always (dissoc :supersedes) |
275 | | - :always (assoc :unsupersedes? true) |
276 | | - target-message-id (assoc :unsupersedes-mid target-message-id)) |
277 | | - :set-duplicate (cond-> acc |
278 | | - :always (assoc :duplicate-of target-message-id) |
279 | | - :always (dissoc :unduplicate-of? :unduplicate-of-mid)) |
280 | | - :unset-duplicate (cond-> acc |
281 | | - :always (dissoc :duplicate-of) |
282 | | - :always (assoc :unduplicate-of? true) |
283 | | - target-message-id (assoc :unduplicate-of-mid target-message-id)) |
| 263 | + ;; All relation actions carry a mid (the `:param :message-id` |
| 264 | + ;; in the registry guarantees the parser captured one). |
| 265 | + :set-superseded (-> acc (assoc :superseded-by target-message-id) |
| 266 | + (dissoc :unsuperseded-by? :unsuperseded-by-mid)) |
| 267 | + :unset-superseded (-> acc (dissoc :superseded-by) |
| 268 | + (assoc :unsuperseded-by? true |
| 269 | + :unsuperseded-by-mid target-message-id)) |
| 270 | + :set-supersedes (-> acc (assoc :supersedes target-message-id) |
| 271 | + (dissoc :unsupersedes? :unsupersedes-mid)) |
| 272 | + :unset-supersedes (-> acc (dissoc :supersedes) |
| 273 | + (assoc :unsupersedes? true |
| 274 | + :unsupersedes-mid target-message-id)) |
| 275 | + :set-duplicate (-> acc (assoc :duplicate-of target-message-id) |
| 276 | + (dissoc :unduplicate-of? :unduplicate-of-mid)) |
| 277 | + :unset-duplicate (-> acc (dissoc :duplicate-of) |
| 278 | + (assoc :unduplicate-of? true |
| 279 | + :unduplicate-of-mid target-message-id)) |
284 | 280 | :set-related (-> acc |
285 | 281 | (update :related-to-set (fnil conj #{}) target-message-id) |
286 | 282 | (update :related-to-unset (fnil disj #{}) target-message-id)) |
|
524 | 520 | supersedes unsupersedes? unsupersedes-mid |
525 | 521 | duplicate-of unduplicate-of? unduplicate-of-mid |
526 | 522 | related-to-set related-to-unset]} resolved] |
527 | | - (str/join ", " (concat (map (fn [[attr addr]] (str (name attr) " -> " addr)) set) |
528 | | - (map #(str "un-" (name %)) unset) |
529 | | - (when deadline [(str "deadline " deadline)]) |
530 | | - (when undeadline? ["no deadline"]) |
531 | | - (when expiry [(str "expiry " expiry)]) |
532 | | - (when unexpiry? ["no expiry"]) |
533 | | - (when topic [(str "topic:" topic)]) |
534 | | - (when untopic? ["no topic"]) |
535 | | - (when superseded-by [(str "superseded-by:" superseded-by)]) |
536 | | - (when unsuperseded-by? [(str "not superseded-by:" unsuperseded-by-mid)]) |
537 | | - (when supersedes [(str "supersedes:" supersedes)]) |
538 | | - (when unsupersedes? [(str "not supersedes:" unsupersedes-mid)]) |
539 | | - (when duplicate-of [(str "duplicate-of:" duplicate-of)]) |
540 | | - (when unduplicate-of? [(str "not duplicate-of:" unduplicate-of-mid)]) |
541 | | - (map #(str "related-to:" %) related-to-set) |
542 | | - (map #(str "not-related-to:" %) related-to-unset))))) |
| 523 | + (str/join |
| 524 | + ", " |
| 525 | + (concat (map (fn [[attr addr]] (str (name attr) " -> " addr)) set) |
| 526 | + (map #(str "un-" (name %)) unset) |
| 527 | + (keep identity |
| 528 | + [(when deadline (str "deadline " deadline)) |
| 529 | + (when undeadline? "no deadline") |
| 530 | + (when expiry (str "expiry " expiry)) |
| 531 | + (when unexpiry? "no expiry") |
| 532 | + (when topic (str "topic:" topic)) |
| 533 | + (when untopic? "no topic") |
| 534 | + (when superseded-by (str "superseded-by:" superseded-by)) |
| 535 | + (when unsuperseded-by? (str "not superseded-by:" unsuperseded-by-mid)) |
| 536 | + (when supersedes (str "supersedes:" supersedes)) |
| 537 | + (when unsupersedes? (str "not supersedes:" unsupersedes-mid)) |
| 538 | + (when duplicate-of (str "duplicate-of:" duplicate-of)) |
| 539 | + (when unduplicate-of? (str "not duplicate-of:" unduplicate-of-mid))]) |
| 540 | + (map #(str "related-to:" %) related-to-set) |
| 541 | + (map #(str "not-related-to:" %) related-to-unset))))) |
543 | 542 |
|
544 | 543 | (defn- setter-address |
545 | 544 | "Return the address credited as the setter of `attr` on `current`. |
|
847 | 846 | surfaced in the pull map so `scope-permits?` can |
848 | 847 | resolve :setter-or-maintainer on the unset |
849 | 848 | command in the open-report path." |
| 849 | + ;; :setter-attr must be UNIQUE per row. Both :supersedes rows share |
| 850 | + ;; the `:rel/supersedes` schema kind; if we reused `:rel/supersedes` |
| 851 | + ;; as the pull-map key, `relation-setters-as-pull` would overwrite |
| 852 | + ;; the from-setter with the to-setter on a chained report (one that |
| 853 | + ;; supersedes X AND is superseded by Y), so the scope check on the |
| 854 | + ;; `Not superseded-by:` unset would see the wrong setter. The |
| 855 | + ;; suffix `-from` / `-to` records the row's role. These keys are |
| 856 | + ;; internal to the pull map; nothing else reads them as schema attrs. |
850 | 857 | [{:id :superseded-by :kind :supersedes :role :current-as-from |
851 | 858 | :propagate :superseded :propagate-tgt true |
852 | 859 | :syntax "Superseded-by" |
853 | 860 | :mid-key :superseded-by :unset-key :unsuperseded-by? :unset-mid-key :unsuperseded-by-mid |
854 | | - :unset-syntax "Not superseded-by" |
855 | | - :setter-attr :rel/supersedes} |
| 861 | + :setter-attr :rel/supersedes-from} |
856 | 862 | {:id :supersedes :kind :supersedes :role :current-as-to |
857 | 863 | :propagate :superseded :propagate-tgt true |
858 | 864 | :syntax "Supersedes" |
859 | 865 | :mid-key :supersedes :unset-key :unsupersedes? :unset-mid-key :unsupersedes-mid |
860 | | - :unset-syntax "Not supersedes" |
861 | | - :setter-attr :rel/supersedes} |
| 866 | + :setter-attr :rel/supersedes-to} |
862 | 867 | {:id :duplicate-of :kind :duplicates :role :current-as-from |
863 | 868 | :propagate :canceled :propagate-tgt false |
864 | 869 | :syntax "Duplicate-of" |
865 | 870 | :mid-key :duplicate-of :unset-key :unduplicate-of? :unset-mid-key :unduplicate-of-mid |
866 | | - :unset-syntax "Not duplicate-of" |
867 | | - :setter-attr :rel/duplicates}]) |
| 871 | + :setter-attr :rel/duplicates-from}]) |
868 | 872 |
|
869 | 873 | (defn- compute-closure-rows |
870 | 874 | "Enrich `closure-relation-rows` with per-row decisions derived from |
|
1020 | 1024 | (into [] |
1021 | 1025 | (comp (filter #(= :current-as-from (:role %))) |
1022 | 1026 | (map #(select-keys % [:id :kind :role :unset-key :unset-mid-key |
1023 | | - :unset-syntax :setter-attr]))) |
| 1027 | + :setter-attr]))) |
1024 | 1028 | closure-relation-rows)) |
1025 | 1029 |
|
1026 | 1030 | (defn- try-unclosed! |
|
1231 | 1235 | word-result (cond-> (merge implicit body-words) |
1232 | 1236 | self-ack? (dissoc :report/acked) |
1233 | 1237 | :always (filter-words-by-scope overrides is-maint? fail-ctx)) |
1234 | | - line-id-ok? (cond |
1235 | | - carrier-only? carrier-eligible-ids |
1236 | | - no-carrier? (complement carrier-eligible-ids) |
1237 | | - :else (constantly true)) |
| 1238 | + keep-line? (case line-filter |
| 1239 | + :carrier-only #(contains? carrier-eligible-ids (:id %)) |
| 1240 | + :no-carrier #(not (contains? carrier-eligible-ids (:id %))) |
| 1241 | + (constantly true)) |
1238 | 1242 | lines (when body-text |
1239 | 1243 | (->> (detect-lines report-type body-text overrides |
1240 | 1244 | (:email/date-sent email) |
1241 | 1245 | (:line-patterns src-cmds)) |
1242 | | - (filter #(line-id-ok? (:id %))) |
| 1246 | + (filter keep-line?) |
1243 | 1247 | (remove (fn [d] |
1244 | 1248 | (and (= :set (:action d)) |
1245 | 1249 | (= :report/acked (:attr d)) |
|
0 commit comments