Skip to content

Commit c651d22

Browse files
committed
feat!: Allow patch to trigger bug/request update, new directives
A patch sent in reply to a bug/request set "Acked" and "Owned" on it. Marking the patch as applied will close the parent report. New directives: "Duplicate-of: <mid>" closes the source <mid> with reason :canceled and link to the target, use "Not duplicate" to undo. "Related-to: <mid>" cross-references; multiple "Related-to" lines in the same email are supported, use "Not related-to: <mid>" to undo. Bark-format bumped to 0.9.0, the legacy :related JSON field is gone. Breaking-Integrators: See the new BARK format.
1 parent b409788 commit c651d22

34 files changed

Lines changed: 2362 additions & 576 deletions

docs/bark-manual.org

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,54 @@ Three forms are accepted:
182182
- An archive URL where the message-id is the last path segment, e.g.
183183
=https://list.orgmode.org/orgmode/msg-id@host/=.
184184

185+
Source and target must both be bugs, patches, or requests, of the
186+
same type.
187+
185188
See the [[#superseding-a-report-1][maintainer section]] for the full details on what this does
186189
and how to undo it.
187190

191+
** Marking a report as a duplicate
192+
193+
To mark a report as a duplicate of another, reply with:
194+
195+
: Duplicate-of: <target-message-id@example.com>
196+
197+
Same three message-id forms and type constraints as =Superseded-by:=.
198+
Closes the duplicate with reason =:cancelled= and links it to the
199+
target. To undo: =Not duplicate.=
200+
201+
Use =Superseded-by:= for "replaced by a newer version" (=:superseded=,
202+
typical for patch v1=>v2); =Duplicate-of:= for "same issue as another
203+
report" (=:cancelled=, typical for duplicated bug reports).
204+
205+
** Cross-referencing reports
206+
207+
To cross-reference another report:
208+
209+
: Related-to: <other-message-id@example.com>
210+
211+
Accepts any pair of reports. Three message-id forms: bracketed
212+
(=<msg-id@host>=), bare (=msg-id@host=), or archive URL. Several
213+
=Related-to:= lines in one email post several links. Works on
214+
closed reports. To undo:
215+
=Not related-to: <other-message-id@example.com>=.
216+
217+
** Resolving a bug or request with a patch
218+
219+
A patch sent in reply to a bug or request links the two reports and
220+
credits you for what it resolves:
221+
222+
| What you do | Effect on the bug/request |
223+
|------------------------------+-------------------------------|
224+
| Send the patch | =Acked= + =Owned= by you |
225+
| =Closed.= the patch (applied) | =Closed=, reason =:resolved= |
226+
| =Cancelled.= the patch | Auto-acked/owned removed |
227+
| =Superseded-by:= a newer patch | =Owned= transfers to new author |
228+
229+
Only the *nearest* bug or request in the thread is affected. An
230+
existing explicit =Acked= or =Owned= setter is preserved (the link
231+
is still posted). To opt out: =Not acked.= / =Not owned.=
232+
188233
** Voting on requests
189234

190235
Requests (=[POLL]=, =[TODO]=, etc.) support voting:

resources/bark-index.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
// bark-index.js Client-side filtering, sorting, URL state, lazy-load closed.
1+
// bark-index.js -- Client-side filtering, sorting, URL state, lazy-load closed.
22
// Copyright (c) 2026 Bastien Guerry <bzg@gnu.org>
33
// SPDX-License-Identifier: MPL-2.0
44
//
55
// Expects global objects:
6-
// barkConfig .types, .total, .openCount, .closedCount, .closedJsonUrl, .pageSize, .sourceType
7-
// barkData array of report objects (open reports, embedded in page)
6+
// barkConfig -- .types, .total, .openCount, .closedCount, .closedJsonUrl, .pageSize, .sourceType
7+
// barkData -- array of report objects (open reports, embedded in page)
88

99
var allTypes = barkConfig.types;
1010
var activeTypes = {};
@@ -584,13 +584,28 @@ function buildRowElement(rpt) {
584584
}
585585

586586
var relatedHtml = '';
587-
if (r.related && r.related.length > 0) {
588-
var mids = r.related.map(function(x) { return x['message-id']; }).filter(Boolean).join(',');
589-
if (mids) {
590-
relatedHtml = '<a class="secondary" href="#" onclick="showRelated(\'m:' + escAttr(mids) +
591-
'\'); return false;" title="Filter related reports" style="font-size:0.75rem">\u21B3' +
592-
r.related.length + ' </a>';
587+
// Union of all qualified-relation kinds: a click on this link should
588+
// filter on every report linked to the current one regardless of how
589+
// (resolves, supersedes, duplicates, related-to, and their inverses).
590+
var allRelated = [];
591+
var seenMids = {};
592+
['resolves', 'resolved-by',
593+
'supersedes', 'superseded-by',
594+
'duplicates', 'duplicated-by',
595+
'related-to'].forEach(function(kind) {
596+
var entries = r[kind];
597+
if (entries && entries.length) {
598+
entries.forEach(function(e) {
599+
var mid = e && e['message-id'];
600+
if (mid && !seenMids[mid]) { seenMids[mid] = 1; allRelated.push(mid); }
601+
});
593602
}
603+
});
604+
if (allRelated.length > 0) {
605+
relatedHtml = '<a class="secondary" href="#" onclick="showRelated(\'m:' +
606+
escAttr(allRelated.join(',')) +
607+
'\'); return false;" title="Filter related reports" style="font-size:0.75rem">\u21B3' +
608+
allRelated.length + ' </a>';
594609
}
595610

596611
var eventsHtml = '';
@@ -635,9 +650,9 @@ function buildRowElement(rpt) {
635650
}
636651

637652
var priLabel = priority === 3 ? 'A' : priority === 2 ? 'B' : priority === 1 ? 'C' : ' ';
638-
var priTitle = priority === 3 ? 'Priority A urgent and important'
639-
: priority === 2 ? 'Priority B urgent'
640-
: priority === 1 ? 'Priority C important'
653+
var priTitle = priority === 3 ? 'Priority A -- urgent and important'
654+
: priority === 2 ? 'Priority B -- urgent'
655+
: priority === 1 ? 'Priority C -- important'
641656
: 'No priority';
642657
var isMaint = role === 'maintainer';
643658
var authorInner = isMaint ? '<strong>' + escHtml(author) + '</strong>' : escHtml(author);

resources/bark-schema.edn

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,18 @@
104104
:report/important-address {:db/valueType :db.type/string}
105105
;; Why the report was closed: :resolved, :cancelled, :expired, or :superseded
106106
:report/close-reason {:db/valueType :db.type/keyword}
107-
;; Topic, deadline, expiry and superseded-by: the ref points to the
108-
;; email that posed the value. The actual business value lives in
109-
;; the paired `-value` (scalar) or `-target` (structural ref) attr.
110-
;; These commands have no proxy form, so there is no `-address` attr.
107+
;; Topic, deadline, expiry: the ref points to the email that posed
108+
;; the value. The actual business value lives in the paired `-value`
109+
;; scalar attr. These commands have no proxy form, so there is no
110+
;; `-address` attr.
111+
;; (Superseded-by has moved to the qualified-relations layer below;
112+
;; see :rel/* attributes.)
111113
:report/topic {:db/valueType :db.type/ref}
112114
:report/topic-value {:db/valueType :db.type/string}
113115
:report/deadline {:db/valueType :db.type/ref}
114116
:report/deadline-value {:db/valueType :db.type/instant}
115117
:report/expiry {:db/valueType :db.type/ref}
116118
:report/expiry-value {:db/valueType :db.type/instant}
117-
:report/superseded-by {:db/valueType :db.type/ref}
118-
:report/superseded-by-target {:db/valueType :db.type/ref}
119119
:report/last-activity {:db/valueType :db.type/instant}
120120
:report/last-activity-address {:db/valueType :db.type/string}
121121
:report/has-ics {:db/valueType :db.type/boolean}
@@ -138,12 +138,32 @@
138138
:vote/voter {:db/valueType :db.type/string}
139139

140140
:report/series {:db/valueType :db.type/ref}
141-
:report/related {:db/valueType :db.type/ref
142-
:db/cardinality :db.cardinality/many}
143141
:report/patches {:db/valueType :db.type/ref
144142
:db/cardinality :db.cardinality/many
145143
:db/isComponent true}
146144

145+
;; --- Qualified relations between reports (defined by bark.relations) ---
146+
;;
147+
;; A relation is a standalone entity linking two reports. Asymmetric
148+
;; kinds (:resolves, :supersedes, :duplicates) are stored as TWO
149+
;; entities (one per direction); the symmetric kind :related-to is
150+
;; stored as ONE entity canonicalized by ascending eid order.
151+
;;
152+
;; :rel/id encodes <from-eid>:<kind>:<to-eid> for replay idempotence.
153+
;; :rel/active? is flipped to false on retract; the entity is kept
154+
;; for audit instead of being physically retracted.
155+
:rel/id {:db/valueType :db.type/string
156+
:db/unique :db.unique/identity}
157+
:rel/from {:db/valueType :db.type/ref}
158+
:rel/to {:db/valueType :db.type/ref}
159+
:rel/kind {:db/valueType :db.type/keyword}
160+
:rel/setter {:db/valueType :db.type/string}
161+
:rel/email {:db/valueType :db.type/ref}
162+
:rel/posed-at {:db/valueType :db.type/instant}
163+
:rel/value {:db/valueType :db.type/string}
164+
:rel/active? {:db/valueType :db.type/boolean}
165+
:rel/retracted-by {:db/valueType :db.type/ref}
166+
147167
;; --- Patch content entities ---
148168
:patch/filename {:db/valueType :db.type/string}
149169
:patch/source {:db/valueType :db.type/keyword}

resources/docs-tpl.org

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ report using predefined commands. Maintainers can update reports by
66
writing directly to the monitored inbox, manage roles, and receive
77
periodic digest emails.
88

9-
For maintainers, see the full [[https://codeberg.org/bzg/bark/src/branch/main/docs/bark-manual.org][BARK manual]].
10-
11-
To explore BARK reports from your terminal, use [[https://codeberg.org/bzg/bone][bone]].
9+
To explore BARK reports from your terminal, use [[https://codeberg.org/bzg/bone][bone]]. You can also
10+
highlight BARK with [[codeberg.org/bzg/gnus-bone][gnus-bone.el]] and [[https://codeberg.org/bzg/notmuch-bone][notmuch-bone.el]].
1211

13-
You can also highlight BARK with [[codeberg.org/bzg/gnus-bone][gnus-bone.el]] and [[https://codeberg.org/bzg/notmuch-bone][notmuch-bone.el]].
12+
For maintainers, see the full [[https://codeberg.org/bzg/bark/src/branch/main/docs/bark-manual.org][BARK manual]].
1413

1514
** Subject labels
1615

scripts/bark-docs.clj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bb
22

3-
;; bark-docs.clj Generate public/<source>/docs.html from resources/docs-tpl.org.
3+
;; bark-docs.clj -- Generate public/<source>/docs.html from resources/docs-tpl.org.
44
;;
55
;; Reads the org template and substitutes source-specific labels and
66
;; commands into the unified table, based on merged config
@@ -111,7 +111,7 @@
111111
(str/join "\n" (concat [header hline] (map row-str rows)))))
112112

113113
;; ---------------------------------------------------------------------------
114-
;; Template substitution detect and replace org table blocks
114+
;; Template substitution -- detect and replace org table blocks
115115
;; ---------------------------------------------------------------------------
116116

117117
(defn- table-line? [s] (str/starts-with? (str/trim s) "|"))
@@ -149,7 +149,7 @@
149149
[commands-block]
150150
(drop (inc t2-end) lines))))
151151

152-
;; Only one table replace with labels only
152+
;; Only one table -- replace with labels only
153153
(seq blocks)
154154
(let [[t1-start t1-end] (first blocks)]
155155
(str/join "\n"
@@ -264,7 +264,7 @@
264264
" footer-css))
265265

266266
(defn docs-page [body-html {:keys [ical]}]
267-
(let [title "BARK Docs"
267+
(let [title "BARK -- Docs"
268268
generated-at (str (java.util.Date.))]
269269
(str
270270
"<!DOCTYPE html>\n"
@@ -333,7 +333,7 @@
333333
(map (fn [line]
334334
(if (and (str/starts-with? (str/trim line) "|")
335335
(re-find #"\[\[.+\.(json|xml|org)\]" line))
336-
;; This is a table row with feed links process each cell
336+
;; This is a table row with feed links -- process each cell
337337
(let [cells (->> (str/split line #"\|" -1)
338338
(drop 1) butlast
339339
(mapv #(str/trim %)))

scripts/bark-email-test.clj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
#!/usr/bin/env bb
22

3-
;; test/bark-email-test.clj Test SMTP configuration by sending a test email.
3+
;; test/bark-email-test.clj -- Test SMTP configuration by sending a test email.
44
;;
55
;; Reads :notifications :smtp from config.edn, sends a short test message
66
;; to the lead maintainer of the first source (or to a custom address via --to).
77
;;
88
;; Usage:
9-
;; bb test-smtp validate config, no email sent (default)
10-
;; bb test-smtp --send actually send the test email
11-
;; bb test-smtp --to me@example.com --send send to a specific address
9+
;; bb test-smtp -- validate config, no email sent (default)
10+
;; bb test-smtp --send -- actually send the test email
11+
;; bb test-smtp --to me@example.com --send -- send to a specific address
1212

1313
(require '[babashka.pods :as pods]
1414
'[clojure.edn :as edn]

0 commit comments

Comments
 (0)