Skip to content

Commit 753a93f

Browse files
committed
refactor: Condense manual structure and phrasing
1 parent 4a77428 commit 753a93f

1 file changed

Lines changed: 104 additions & 203 deletions

File tree

docs/bark-manual.org

Lines changed: 104 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -67,41 +67,28 @@ BARK is for: storing reports sent to a mailbox in a database.
6767

6868
* Principles
6969

70-
- *Email-native* :: No account to create, no platform to maintain, no
71-
vendor lock-in. Users report bugs and review patches with whatever
72-
mail client they already use. The mailing list archive *is* the
73-
tracker history — BARK simply indexes it.
74-
75-
- *One place* :: [[https://orgmode.org][Org mode]] was born out of the idea that to-do items and
76-
free-form notes should be edited in the same space. Similarly, bug
77-
reports, patches and feature requests should be handled where users
78-
and developers discuss them. It is the tracker's job to filter out
79-
the noise and help everyone focus on how they can contribute.
80-
81-
- *KISS* :: BARK provides a simple framework for acting on reports, with
82-
a fixed vocabulary: =acked=, =owned=, or =closed= for status; =urgency= and
83-
=importance= for priority. You cannot invent a custom =WONTFIX-MAYBE=
84-
status or manually set a report to P0. This is deliberate: a fixed
85-
vocabulary prevents the label proliferation that eventually makes
86-
trackers unusable.
87-
88-
- *Immutable* :: No web form, no API endpoint, no account. Users report
89-
bugs and request features by emailing a list. Maintainers respond by
90-
replying to the same thread. As every state change is encoded in an
91-
email, the entire tracker state can be reconstructed at any time by
92-
re-monitoring the mailbox from scratch. This means no tracker backup
93-
to manage and no database migration between BARK versions — the
94-
mailbox is the source of truth.
95-
96-
- *Low ops* :: BARK exports static HTML, JSON, RSS and Org files. There
97-
is no application server to keep running, no database to back up
98-
(beyond the mailbox itself), and no user accounts to administer. A
99-
cron job and a web server serving static files are all you need.
100-
101-
- *Local-first* :: BARK exports to JSON, RSS, Org. Companion tools like
102-
=bone= (TUI browser), =gnus-bone.el= (Emacs/Gnus) and =notmuch-bone.el=
103-
(Emacs/notmuch) let users consume the data in whatever environment
104-
they already live in, rather than forcing a new interface on them.
70+
- *One place* :: Reports and their discussions belong in one source
71+
-- the mailing list, which BARK indexes. The tracker's job is to
72+
filter noise, not to host a separate conversation.
73+
74+
- *Email-native* :: No account, no platform, no vendor lock-in.
75+
Users work in whatever mail client they already use, and the
76+
mailing list archive *is* the tracker history -- BARK simply
77+
indexes it.
78+
79+
- *Immutable* :: Every state change is encoded in an email, so the
80+
whole tracker state can be rebuilt from the mailbox at any time.
81+
No tracker backups to manage, no DB migrations between versions
82+
-- the mailbox is the source of truth.
83+
84+
- *Local-first* :: Companion tools (=bone= TUI, =gnus-bone.el=,
85+
=notmuch-bone.el=) let users consume BARK data from their existing
86+
environment instead of imposing a new interface.
87+
88+
- *KISS* :: Fixed vocabulary, deliberately: =acked=, =owned=, =closed=
89+
for status; =urgency= and =importance= for priority. No custom
90+
=WONTFIX-MAYBE= status, no manual P0 -- this prevents the label
91+
proliferation that eventually breaks trackers.
10592

10693
* As a user
10794
** Bug, Patch, Request
@@ -169,38 +156,30 @@ maintainers, who can undo anyone's action (see [[#undoing-updates][Undoing updat
169156

170157
** Superseding a report
171158

172-
If your report turns out to duplicate another one, or if you send a
173-
new version of a patch that replaces the previous one, you can mark
174-
the old report as superseded by replying to its thread with:
159+
When one report replaces another (a newer patch version, a fresh bug
160+
report capturing the real issue), mark the supersession with either
161+
of two equivalent directives -- they produce the same effect and
162+
differ only by point of view:
175163

176-
: Superseded-by: <target-message-id@example.com>
164+
- From the *old* report's thread:
177165

178-
Three forms are accepted:
166+
: Superseded-by: <new-message-id@example.com>
179167

180-
- =<msg-id@host>= --- the canonical RFC form.
181-
- =msg-id@host= --- a bare message-id.
182-
- An archive URL where the message-id is the last path segment, e.g.
183-
=https://list.orgmode.org/orgmode/msg-id@host/=.
168+
- From the *new* report's thread (works in a reply *and* in the
169+
opening mail of a brand-new bug/patch/request):
184170

185-
Source and target must both be bugs, patches, or requests, of the
186-
same type.
171+
: Supersedes: <old-message-id@example.com>
187172

188-
Symmetric form -- when investigation matures and you file a fresh
189-
report that captures the real problem, mark the old one as superseded
190-
from the new report's side:
173+
Message-ids accept three forms: =<id@host>=, bare =id@host=, or the
174+
last path segment of an archive URL (e.g.
175+
=https://list.orgmode.org/orgmode/id@host/=). Source and target must
176+
be of the same type (both bugs, both patches, or both requests).
191177

192-
: Supersedes: <old-message-id@example.com>
178+
To undo: =Not superseded= (from the closed report's thread) or =Not
179+
superseding= (from the replacement's thread).
193180

194-
Both =Superseded-by:= and =Supersedes:= produce the exact same effect
195-
(same close, same relation) -- they differ only by point of view.
196-
=Supersedes:= works in the opening mail of a new bug/patch/request,
197-
not only in replies.
198-
199-
To undo: =Not superseded= (from the closed report's thread) or
200-
=Not superseding= (from the replacement's thread).
201-
202-
See the [[#superseding-a-report-1][maintainer section]] for the full details on what this does
203-
and how to undo it.
181+
See the [[#superseding-a-report-1][maintainer section]] for the automatic actions BARK performs
182+
on supersession.
204183

205184
** Marking a report as a duplicate
206185

@@ -222,10 +201,9 @@ To cross-reference another report:
222201

223202
: Related-to: <other-message-id@example.com>
224203

225-
Accepts any pair of reports. Three message-id forms: bracketed
226-
(=<msg-id@host>=), bare (=msg-id@host=), or archive URL. Several
227-
=Related-to:= lines in one email post several links. Works on
228-
closed reports. To undo:
204+
Accepts any pair of reports. Same message-id forms as
205+
=Superseded-by:= (see above). Several =Related-to:= lines in one
206+
email post several links. Works on closed reports. To undo:
229207
=Not related-to: <other-message-id@example.com>=.
230208

231209
** Resolving a bug or request with a patch
@@ -335,17 +313,8 @@ To remove a per-report expiry:
335313

336314
** Superseding a report
337315

338-
When a report is made obsolete by another (e.g. a patch resubmitted
339-
without version numbers, or a bug report that duplicates a broader
340-
one), anyone can mark the old report as superseded by replying to its
341-
thread with:
342-
343-
: Superseded-by: <target-message-id@example.com>
344-
345-
The message-id can be given as =<msg-id@host>=, bare =msg-id@host=, or
346-
extracted from an archive URL where it is the last path segment (e.g.
347-
=https://list.orgmode.org/orgmode/msg-id@host/=). This does three
348-
things automatically:
316+
A =Supersedes:= or =Superseded-by:= directive (see [[#superseding-a-report][the user section]]
317+
for syntax and message-id forms) triggers three automatic actions:
349318

350319
1. Poses a =:supersedes= qualified relation (=:rel/from= = the closed
351320
report, =:rel/to= = the replacement) and a symmetric =:related-to=
@@ -354,47 +323,18 @@ things automatically:
354323
3. Links the two reports as related (bidirectional, kept on undo).
355324

356325
In the index, superseded reports appear struck through (like canceled
357-
reports) and display an "S" status flag. The subject tooltip shows the
358-
title of the superseding report.
359-
360-
To undo:
361-
362-
: Not superseded.
363-
364-
This retracts the supersede reference, reopens the report, and clears
365-
the close-reason. The related link is kept.
366-
367-
*** Supersedes (symmetric form, replacement's point of view)
326+
reports) with an "S" status flag; the subject tooltip shows the
327+
replacement's title.
368328

369-
After several rounds of investigation, the original mail of a bug or
370-
patch often no longer captures the real understanding. Filing a
371-
fresh report that supersedes the old one is a natural editorial move,
372-
and BARK supports it from the replacement's side:
329+
Last-write-wins on direction: if a later directive flips the direction
330+
(e.g. =Supersedes: <X>= posed at t1, then =Superseded-by: <X>= posed
331+
at t2 on the same report), the second pose retracts the first,
332+
reopens the previously-closed report, and applies the new direction.
373333

374-
: Supersedes: <old-message-id@example.com>
375-
376-
This works both in a reply (the current report becomes the replacement)
377-
and in the *opening mail* of a brand-new bug/patch/request -- making
378-
the new report the canonical face of the issue.
379-
380-
=Supersedes:= and =Superseded-by:= produce the *same* relation and
381-
the *same* close on the same pair of reports: the canonical
382-
=:supersedes= relation always points from the closed (superseded)
383-
report to the replacement. They only differ in point of view.
384-
385-
Last-write-wins on direction: if a later directive flips the
386-
direction (e.g. =Supersedes: <X>= posed at t1, then
387-
=Superseded-by: <X>= posed at t2 on the same report), the second
388-
pose retracts the first and reopens the previously-closed report
389-
before applying the new direction.
390-
391-
To undo from the replacement's side:
392-
393-
: Not superseding.
394-
395-
This retracts the =:supersedes= relation and reopens the
396-
previously-closed target. Same scope as =Not superseded.= (the
397-
original setter or a maintainer).
334+
Undo scope: =Not superseded= and =Not superseding= can be issued by
335+
the original setter or by any maintainer. Either retracts the
336+
relation, reopens the closed report, and clears the close-reason; the
337+
=:related-to= link is kept.
398338

399339
*** Automatic supersession of patches and diffs
400340

@@ -638,16 +578,10 @@ in turn take precedence over the built-in defaults.
638578

639579
*** Syntax mode: =:loose= vs =:strict=
640580

641-
The =:command-syntax= key controls whether Bark instructions must be
642-
prefixed with =!=. Accepts =:loose= (default) or =:strict=.
643-
644-
- =:loose= — every Bark instruction can be written with or without a
645-
=!= prefix. Matches prose-style usage on mailing lists.
646-
- =:strict= — every Bark instruction MUST start with =!=. Eliminates
647-
false positives on common English words like "Done.", "Closed.",
648-
"Applied." that appear naturally in conversation.
649-
650-
The rule applies uniformly to all Bark instructions:
581+
The =:command-syntax= key (=:loose= default, =:strict= opt-in) controls
582+
whether Bark instructions must be prefixed with =!=. =:strict= eliminates
583+
false positives on common English words like "Done.", "Closed." or
584+
"Applied." that appear naturally in conversation.
651585

652586
| Form | Loose | Strict |
653587
|------------------+------------------------+------------------------|
@@ -743,63 +677,38 @@ The BARK instance can expose reports as HTML, JSON, Org and RSS.
743677

744678
Running =bb export all= generates, for each source:
745679

746-
- =index.html= --- the main reports table (filterable, sortable).
747-
- =stats.html= --- report statistics and charts.
748-
- =docs.html= --- a user-facing documentation page (from =docs-tpl.org=).
749-
- =all.json=, =all.org=, =all.xml= --- full exports in JSON, Org and RSS.
680+
- HTML pages: =index.html= (reports table), =stats.html= (charts),
681+
=docs.html= (user docs).
682+
- Full exports: =all.json=, =all.org=, =all.xml=.
683+
- Per-type feeds: =bugs.json=, =patches.xml=, =requests.org=, etc.
750684
- =votes.json= --- per-report vote details (see below).
751-
- Per-type feeds: =bugs.json=, =patches.xml=, etc.
752-
- =patches/= --- a directory with attached and inline patch files.
753-
- =text/= --- a directory with =text/plain= and =text/x-log= attachments
754-
(e.g. backtraces, log files). Saved under =text/<mid-hash>/=.
755-
- =events/= --- a directory with =.ics= calendar files extracted from
756-
announcements. Each report's =.ics= attachments are saved under
757-
=events/<mid-hash>/=. Combined =events/announcements.ics=,
758-
=events/announcements-open.ics= and =events/announcements-closed.ics=
759-
aggregate =VEVENT= blocks into subscribable calendar feeds.
760-
- =events.json=, =events.org=, =events.xml= --- open announcements that
761-
carry an =.ics= attachment or inline =VCALENDAR= content.
762-
- =events-closed.json=, =events-closed.org=, =events-closed.xml= ---
763-
closed announcements with =.ics= content.
764-
765-
RSS feeds contain up to 50 items, most recent first.
766-
767-
Export is incremental: only sources modified since the last export are
768-
re-generated. Use =bb export all --force= to force a full re-export.
769-
770-
You can also export a single format:
771-
772-
: bb export json
773-
: bb export rss
774-
: bb export org
775-
: bb export html
776-
: bb export stats
777-
: bb export text
778-
: bb export events
779-
780-
Use =-n <source>= to restrict to one source, =-p <N>= to filter by minimum
781-
priority, and =-s <N>= to filter by minimum status.
782-
783-
Use =--page-size <N>= to paginate the HTML report table (e.g.
784-
=bb export --page-size 100=). Pagination is client-side: all data is
785-
still exported, but only one page of rows is rendered at a time,
786-
improving browser responsiveness on large trackers.
787-
788-
Use =--closed-retention <date-or-duration>= to exclude old closed reports
789-
from all exports. Accepts an ISO date (=2024-01-01=) or a duration
790-
(=1y=, =6m=, =90d=). For instance, =bb export --closed-retention 1y=
791-
keeps only reports closed within the last 12 months.
792-
793-
Use =--topics-filter <topics>= to export only reports matching given
794-
topics (comma-separated, case-insensitive). For instance,
795-
=bb export --topics-filter event= exports only reports with topic
796-
"event". Use =bb export --topics-filter "event,security"= for
797-
multiple topics. The filter can also be set per source in =config.edn=
798-
(see below); the CLI flag overrides all config values.
799-
800-
=:page-size= and =:closed-retention= are CLI-only flags.
801-
=:topics-filter= can also be set per source in =config.edn=; the CLI
802-
flag overrides any per-source value.
685+
- =patches/= --- attached and inline patch files.
686+
- =text/<mid-hash>/= --- =text/plain= and =text/x-log= attachments
687+
(backtraces, log files).
688+
- =events/<mid-hash>/= --- =.ics= attachments from announcements;
689+
combined feeds at =events/announcements{,-open,-closed}.ics=
690+
aggregate VEVENT blocks for subscription.
691+
- =events.{json,org,xml}= and =events-closed.{json,org,xml}= ---
692+
open/closed announcements carrying =.ics= or inline VCALENDAR content.
693+
694+
RSS feeds contain up to 50 items, most recent first. Export is
695+
incremental (only sources modified since the last export are
696+
re-generated); use =--force= to bypass.
697+
698+
Single-format export: =bb export {json|rss|org|html|stats|text|events}=.
699+
700+
| Flag | Purpose | Configurable |
701+
|-----------------------+----------------------------------------------------------+--------------|
702+
| =-n <source>= | restrict to one source | -- |
703+
| =-p <N>= | filter by minimum priority | -- |
704+
| =-s <N>= | filter by minimum status | -- |
705+
| =--page-size <N>= | paginate HTML report table (client-side rendering) | CLI only |
706+
| =--closed-retention= | exclude reports closed before given ISO date or duration | CLI only |
707+
| =--topics-filter= | restrict to topics (comma-separated, case-insensitive) | per source |
708+
| =--force= | force a full re-export | CLI only |
709+
710+
Durations accept =Nd=, =Nw=, =Nm=, =Ny= (e.g. =--closed-retention 1y=
711+
keeps reports closed within the last 12 months).
803712

804713
** Vote transparency
805714

@@ -1045,17 +954,11 @@ All rules are conjunctive: a report is only expired when *all*
1045954
conditions are met. Only =:inactive-after= is required; the others are
1046955
optional filters.
1047956

1048-
When =:inactive-after= is a duration, it is measured from the date of the
1049-
*last email in the thread* (the most recent descendant, or the founding
1050-
email if there are no replies). This means any reply — from any
1051-
participant — resets the expiry clock.
1052-
1053-
When =:inactive-after= is an ISO date, the report expires after that
1054-
fixed date regardless of activity.
1055-
1056-
When =:inactive-after= is =:deadline=, the report expires when its
1057-
deadline date is in the past (reports without a deadline are never
1058-
expired by this rule).
957+
| =:inactive-after= value | Trigger |
958+
|-----------------------+----------------------------------------------------------------------|
959+
| Duration (e.g. =30d=) | Last email in the thread is older than the duration (any reply resets) |
960+
| ISO date | The fixed date has passed, regardless of activity |
961+
| =:deadline= | The report's deadline is in the past (no deadline => never expires) |
1059962

1060963
The =:max-status= value uses an activity score that only counts acked
1061964
and owned (since expiry candidates are always open reports):
@@ -1092,18 +995,16 @@ report has an explicit expiry date, only that date is checked.
1092995
:max-size 1048576} ;; skip emails > 1 MB (optional)
1093996
#+end_src
1094997

1095-
- =:fetch= — first-run fetch window (no watermark yet). Exactly one of
1096-
three disjoint map shapes (strict; no key mixing, empty map rejected):
1097-
- ={:limit N}= — fetch the latest N messages (positive integer).
1098-
- ={:since "30d"}= — relative duration from now. Accepts =Nd=, =Nw=, =Nm=, =Ny=.
1099-
- ={:start "yyyy-MM-dd" :end "yyyy-MM-dd"}= — absolute half-open window
1100-
=[start, end)=. Both =:start= and =:end= are optional (at least one
1101-
must be present); ISO dates only.
1102-
Default when =:fetch= is omitted: ={:limit 50}=. CLI shortcut
1103-
(=--fetch=), the scalar is lifted to one of the three map shapes:
1104-
- =--fetch 50= → ={:limit 50}=
1105-
- =--fetch 30d= → ={:since "30d"}=
1106-
- =--fetch 2020-01-01= → ={:start "2020-01-01"}=
998+
- =:fetch= — first-run fetch window (no watermark yet). Exactly one
999+
of three disjoint map shapes (no key mixing, empty map rejected);
1000+
default is ={:limit 50}=:
1001+
1002+
| Config form | CLI shortcut | Meaning |
1003+
|-----------------------------------+-------------------------+-----------------------------------------------------------|
1004+
| ={:limit N}= | =--fetch 50= | Latest N messages (positive integer) |
1005+
| ={:since "Nd"}= | =--fetch 30d= | Relative duration from now (=Nd=, =Nw=, =Nm=, =Ny=) |
1006+
| ={:start "yyyy-MM-dd" :end "..."}= | =--fetch 2020-01-01= | Absolute half-open window =[start, end)=; both keys optional, at least one required |
1007+
11071008
- =:max-size= — skip emails larger than N bytes. No limit by default.
11081009

11091010
Text content of =.patch=, =.diff=, =.ics=, =text/plain= and =text/x-log=

0 commit comments

Comments
 (0)