aboutsummaryrefslogtreecommitdiff
path: root/README.cli
blob: d61e868ee86c1371672cfb2f2c69234ff5ca8322 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
// cli --generate-txt --txt-suffix "" README.cli

// @@ add -n which prints the tree, asks for where to add (auto-completion)
//    and starts the editor.
//
// @@ drop script?
//
// @@ impl script? Don't even need to extract anything. Or maybe should to
//    make sure the commit message is the same. Could warn if doesn't match
//    subject. Not going to be easy if moved.

"
Version 1.0

This document describes the \i{change development} database and process. The
main premise of the approach described here is that planning changes in code
should be handled in the same way as changing the code itself; that is, using
\c{git(1)} and our favorite text editors, rather than some external database
accessible via a web interface (which what most bug trackers are these days).

To be usable, the database format and process must not be burdensome. As a
result, there is minimum notation as well as helper tools to automate common
operations, for example, adding a new item (called a note).

The database can either be stored in the \c{git} repository of the project
itself or, if the project consists of multiple \c{git} repositories, in a
repository of its own. In the former case it is recommended to place the
database in the top-level subdirectory of a project and call it \c{change}. In
the latter case it is recommended to call the repository \c{change},
potentially with a prefix denoting the overall project name, for example,
\c{hello-change}.

The change database is a collection of notes stored in plain text files that
use a certain notation. The files are organized in subdirectories which are
used to group notes that affect a certain subproject or an area of a project.
For a database that covers multiple \c{git} repositories it is common to have
top-level subdirectories named after those repositories. As an example, let's
say we have a \"Hello, World!\" project that consists of two git repositories:
the \c{libhello} library and the \c{hello} program. The resulting directory
structure then could be:

\
hello/

libhello/

change/
|
|--hello/
|
`--libhello/
\

Continuing with this example, inside \c{libhello/} we could have subdirectories
for major functionality areas:

\
change/
|
|--hello/
|
`--libhello/
   |
   |--format/
   |
   `--print/
\

It seldom makes sense to have more than two levels of subdirectories. At the
top level the subdirectory called \c{reference} is reserved for storing notes
that have been acted upon. Its usage is described in more detail below.

A note consists of a \i{header} and an optional \i{body} separated with a blank
line. All lines in a note should be no longer than 78 characters. The header
is always the first line and contains the note's \i{severity}, \i{summary},
and optional \i{labels}. The header has the following format (literal values
are quoted):

\
['-'|'!'|'?'|'+'] <summary>[ '['<label>[ <label>]...']']
\

For example:

\
! Detect empty name [bug]
- Add ability to customize greeting phrase [feature 2.0.0]
? Implement pluggable formatter [idea]
\

The '\c{-}' severity denotes a normal note, '\c{!}' \- critical, and '\c{?}'
\- unconfirmed or questionable, while '\c{+}' is used to denote implemented
notes in the \c{reference} directory (discussed below).

The summary should follow the \c{git} rules for a commit message summary, that
is, it should use no articles, past/future tenses, and should ideally be no
longer than 60 characters (though this rule can sometimes be broken for
clarity). Normally, you should be able to copy the summary into the commit
message when you have implemented a note.

Labels are separated with a space (note: not a comma and space). By convention
the first label should be the note type. Commonly used types are: \c{bug} (fix
something broken), \c{feature} (implement new functionality), \c{idea} (design
a new feature), \c{quality} (improve quality of implementation), \c{infra}
(work on project infrastructure).

Further, labels can be used to group notes based on certain criteria. For
example, \c{doc} (documentation issue), \c{windows} (Windows-specific),
\c{2.0.0} (scheduled for the 2.0.0 release), \c{john} (assigned to John). The
names of subdirectories in which the note is located are also considered its
labels. So, for example, if the above \"Detect empty name\" bug was filed in
\c{lihello/format/}, then its labels would be \c{bug}, \c{format}, and
\c{libhello}.

The body of a note is free-form. However, for clarity, it makes sense to avoid
using '\c{-}' for lists in the body ('\c{*}' for the first level and '\c{~}'
for the second level are good options).

Notes can be saved in three ways. Simple notes without a body or with a body
containing one or two paragraphs can be written in the \c{list} files. These
files can appear at the top level or in any subdirectory. More complex notes
can be placed in their own files. Finally, notes that have addition material
(what traditional bug trackers would call \"attachments\") should be placed
into their own subdirectories with both the directory and the note file
(inside that subdirectory) having the same name. Other than that, such a
subdirectory is free form; it can contain other files and subdirectories.

If a note is written in the \c{list} file, then its body must be indented two
spaces to align with the start of the summary. Notes are separated with blank
lines and their order in the \c{list} files is not significant. Normally you
would add a new note at the top, for convenience. Continuing with our example,
let's file our bug and idea in the \c{list} file under \c{libhello/format/}
(since they both only affect this functionality):

\
! Detect empty name [bug]

  It would make sense to detect empty names and throw invalid_argument.

? Implement pluggable formatter [idea]

  Some users asked for a way to provide their own formatting implementation
  via some sort of a plugin mechanism.

  Note that it's not clear at all this is a good idea.
\

If a note is written into its own file then its body need not be indented;
everything after the header and the blank like is just a normal plain text
file. When choosing a name for a file try to incorporate at least two and
preferably three keywords form the summary. This will minimize the chance of
a name conflict in the reference directory which will accumulate notes over
many years.

As an example, let's save our feature into \c{custom-greeting-phrase} under
\c{libhello/}:

\
- Add ability to customize greeting phrase [feature 2.0.0]

Some users asked for a way to customize the greeting phrase. For example, some
prefer less formal \"Hi\" to \"Hello\".

The way we can implement this is by adding greeting as the second argument to
say() that will default to \"Hello\".

Note that this change will be source but not binary compatible so we will have
to bump at least the minor version.
\

Note also that we can move notes freely between files. For example, we may add
a new subdirectory and move all the notes that affect this functionality from
the top-level \c{list} file. Or we can move a note from \c{list} to its own
file or from a file to a subdirectory if we need to keep some additional files
with the note. For example, if we start expanding on our \"Implement pluggable
formatter\" idea, then it probably makes sense to move it into its own file.

When committing (in the \c{git} sense) changes to the database, use a separate
commit for each note. When committing a newly added note, the commit message
should be in the form:

\
Add <type>: <summary>
\

For example:

\
Add bug: Detect empty name
\

If you only have a single note added in the database then you can use the
\c{add} script to automate this. This script will commit the new note with
the correct message and, unless the \c{-c} option is specified, push the
result to \c{origin}. This should make filing new notes a fairly burdenless
process: write a note using your favorite text editor and run the \c{add}
script. Note that the \c{add} script currently cannot handle notes with extra
files.

If you change an existing note (for example, add additional information), then
the commit message should have the following form:

\
Update <type>: <summary>
\

For example:

\
Update idea: Implement pluggable formatter
\

Similar to adding, if you only have a single note updated in the database then
you can use the \c{update} script to automate this. Note that the \c{update}
script currently cannot handle updates with extra files.

Once a note is acted upon (implemented or you have decided not to do anything
about it), you can either delete it or move it to the reference. Simply
deleting a note is appropriate for simple bugs and features where all the
design information, if any, is incorporated into the code itself. For a more
elaborate note, however, it may make sense to preserve it in case it needs to
be revisited in the future.

The top-level \c{reference} subdirectory should recreate the same directory
structure as top-level (except for \c{reference/} itself). For instance, this
will be the structure for our example:

\
change/
|
|--hello/
|
|--libhello/
|  |
|  |--format/
|  |
|  `--print/
|
`--reference/
   |
   |--hello/
   |
   `--libhello/
      |
      |--format/
      |
      `--print/
\


Only notes stored as separate files can be moved to the reference (in other
words, there should be no \c{list} files in \c{reference/}). When moved, a
note should be placed into the corresponding subdirectory and its severity
changed to either '\c{+}' if it has been implemented or to '\c{?}' if it has
been dropped (in which case it is a good idea to add an explanation as to
why).

Continuing with our example, let's say we have implemented the \"Customize
Greeting Phrase\" feature but would like to keep the note. This is the
relevant part of our directory structure before the move:

\
change/
|
|--libhello/
|  |
|  `--custom-greeting-phrase
|
`--reference/
   |
   `--libhello/
\

And this is after the move (we also change the severity to '\c{+}' inside
\c{custom-greeting-phrase}):

\
change/
|
|--libhello/
|
`--reference/
   |
   `--libhello/
      |
      `--custom-greeting-phrase
\

For an implemented note the commit message should be the same as the one for
the implementation in the code repository and which normally should be the
same as the note subject. If the change database is part of the project's
\c{git} repository, then everything should be in the same commit.

If you have decided not to implement a note, then the commit message should
have the following form:

\
Drop <type>: <summary>
\

For example:

\
Drop idea: Implement pluggable formatter
\
"