gitroll 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -1
- package/README.md +135 -18
- package/SECURITY.md +10 -5
- package/SPEC.md +143 -97
- package/dist/THIRD_PARTY_NOTICES.txt +406 -406
- package/dist/gitroll.mjs +4564 -1945
- package/dist/web/THIRD_PARTY_NOTICES.txt +406 -406
- package/dist/web/app.js +238 -124
- package/dist/web/style.css +1 -1
- package/package.json +1 -1
- package/template/{.gitattributes → .gitroll/.gitattributes} +1 -1
- package/template/.gitroll/README.md +90 -0
- package/template/.gitroll/config.yaml +3 -2
- package/template/README.md +7 -8
- package/template/attachments/.gitkeep +0 -0
- package/template/entries/.gitkeep +0 -0
- package/template/projects/.gitkeep +0 -0
- /package/template/.gitroll/{types → events}/.gitkeep +0 -0
package/SPEC.md
CHANGED
|
@@ -1,146 +1,192 @@
|
|
|
1
|
-
# GitRoll
|
|
1
|
+
# GitRoll format, template version 1
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A log lives in an ordinary Git repository, in a folder called `.gitroll/`. It must stay readable and useful without GitRoll: every file is Markdown, YAML, or an unmodified original attachment, and the format is small enough to hold in your head.
|
|
4
|
+
|
|
5
|
+
The only thing you must do to log an event is create a Markdown file in `.gitroll/events/`.
|
|
4
6
|
|
|
5
7
|
## Layout
|
|
6
8
|
|
|
7
9
|
```
|
|
8
|
-
.gitroll/config.yaml
|
|
9
|
-
.gitroll/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
attachments/<sha256><.ext> attachment bytes, named by content hash
|
|
10
|
+
.gitroll/config.yaml required: template_version
|
|
11
|
+
.gitroll/README.md optional: how to log, for whoever opens the folder
|
|
12
|
+
.gitroll/events/2026-09-15-ac-serviced.md one event per file
|
|
13
|
+
.gitroll/files/ac-receipt.pdf files kept with events, created when first needed
|
|
13
14
|
```
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
`.gitroll/` sits at the root of the repository, whether the repository exists only for the log or already holds a project. It is committed like any other source file.
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
**`.gitroll/` is a namespace, not a privacy boundary.** A log is exactly as visible as the repository it lives in: in a public repository, every event and every attachment in it is public.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
Anything else in the repository belongs to whoever put it there. GitRoll reads and writes only `.gitroll/`, and commits only the files it wrote.
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
- `2026-09-15T14:30:00-07:00` or `2026-09-15T21:30:00Z`: an exact instant.
|
|
23
|
-
- `2026-09-15T14:30` or `2026-09-15T14:30:00`: no offset, so the reader's local time.
|
|
24
|
-
- `2026-09-15`: a date typed by hand, meaning noon local time, so it falls on that day in every time zone. Writers expand it to `2026-09-15T12:00:00` when they next save the event.
|
|
25
|
-
- Anything else (such as `Sept 15`) is invalid, and `gitroll check` reports it.
|
|
26
|
-
- **Ordering** uses the instant, so events logged in different time zones sort correctly.
|
|
27
|
-
- **Display and filters** use the viewer's time zone. An event logged at 9:00 in New York shows as 6:00 to someone in Los Angeles, and "this month", `after:` and `before:` use the viewer's local days.
|
|
28
|
-
- **Folders** (`entries/YYYY/MM`) use the year and month as written in `created`, the author's local date, and never move.
|
|
29
|
-
- **Fields** of kind `date` in custom types hold a date (`2026-09-15`) and are shown as that calendar day, without time zone conversion.
|
|
22
|
+
### Events
|
|
30
23
|
|
|
31
|
-
|
|
24
|
+
Any `.md` file anywhere under `.gitroll/events/` is an event. Subfolders are allowed and mean nothing to GitRoll: they are for people who like to organize.
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
An event's **identity is its path**. There is no id field, and nothing is required inside the file. Renaming an event is an ordinary `git mv`; Git history follows the rename.
|
|
27
|
+
|
|
28
|
+
### Files
|
|
29
|
+
|
|
30
|
+
Files kept with an event are ordinary files with readable names, linked from the event's Markdown with ordinary relative links:
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
[Receipt](../files/ac-receipt.pdf)
|
|
34
|
+
|
|
35
|
+

|
|
40
36
|
```
|
|
41
37
|
|
|
42
|
-
|
|
38
|
+
There are no content hashes, no manifest, and no list of attachments in the front matter: what an event links to is what it has. A link is resolved relative to the event's own file, and only inside the repository — a link that climbs out of the root (`../../../etc/passwd`) or starts at `/` is not an attachment, and `gitroll check` reports it.
|
|
43
39
|
|
|
44
|
-
|
|
40
|
+
Writers must not overwrite a file that is already there: an app storing a second `ac-receipt.pdf` writes `ac-receipt-2.pdf`.
|
|
45
41
|
|
|
46
|
-
##
|
|
42
|
+
## The minimum event
|
|
47
43
|
|
|
48
|
-
|
|
44
|
+
`.gitroll/events/2026-09-15-ac-serviced.md`:
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| `version` | yes | Format version, currently `1` |
|
|
53
|
-
| `id` | yes | Globally unique id. Writers use UUIDv7 (time-sortable). Must match the file name. |
|
|
54
|
-
| `type` | no | Event type id, default `log`. Lowercase letters, digits and `-`. |
|
|
55
|
-
| `created` | yes | ISO 8601 timestamp with offset: when the event was recorded |
|
|
56
|
-
| `occurred` | no | When it happened. Defaults to `created`. Same format as `created`; see [Dates and time zones](#dates-and-time-zones). |
|
|
57
|
-
| `author` | no | Who logged it |
|
|
58
|
-
| `projects` | no | List of project slugs |
|
|
59
|
-
| `tags` | no | List of lowercase tags |
|
|
60
|
-
| `attachments` | no | List of `{ hash, name, type, size }`, where `hash` is `sha256:<hex>` |
|
|
61
|
-
| `amount` | no | `{ value, currency }`, where currency is an ISO 4217 code |
|
|
62
|
-
| `data` | no | Type-specific structured fields (a mapping) |
|
|
63
|
-
| `source` | no | `{ adapter, id, url? }` for events created by an import. `adapter` + `id` is unique within a Roll. |
|
|
46
|
+
```markdown
|
|
47
|
+
# AC serviced
|
|
64
48
|
|
|
65
|
-
|
|
49
|
+
Replaced the capacitor. Paid $325.
|
|
50
|
+
One-year warranty on the repair.
|
|
66
51
|
|
|
67
|
-
|
|
52
|
+
[Receipt](../files/ac-receipt.pdf)
|
|
53
|
+
```
|
|
68
54
|
|
|
69
|
-
|
|
55
|
+
That is a complete, valid event. No front matter, no id, no author, no timestamps.
|
|
70
56
|
|
|
71
|
-
|
|
57
|
+
- **Title**: the first heading; failing that, the first line of text; failing that, the file name.
|
|
58
|
+
- **Date**: the `YYYY-MM-DD` at the start of the file name.
|
|
59
|
+
- **Tags**: any `#hashtag` in the text (not in code spans or fences).
|
|
60
|
+
- **Attachments**: the files it links to.
|
|
72
61
|
|
|
73
|
-
|
|
62
|
+
## Optional metadata
|
|
74
63
|
|
|
75
|
-
|
|
64
|
+
Front matter is optional. When it is there, it is YAML, and it may hold anything; these keys have meaning:
|
|
76
65
|
|
|
77
|
-
|
|
66
|
+
| Key | Meaning |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| `date` | When it happened. Overrides the date in the file name. |
|
|
69
|
+
| `projects` | List of project slugs (`projects: [house]`). Nothing declares a project: naming it is all there is to it. |
|
|
70
|
+
| `tags` | List of tags. Merged with any `#hashtags` in the text. |
|
|
71
|
+
| `amount` | A number. What totals add up. |
|
|
72
|
+
| `currency` | ISO 4217 code for `amount`, default `USD`. |
|
|
73
|
+
| `title` | Overrides the heading as the event's title. Rarely needed. |
|
|
74
|
+
| `source` | Where the event came from. An importer writes `{ adapter, id, url? }`, and `adapter` + `id` is unique within a log, so importing the same thing twice creates one event. An event about code writes `{ repo, branch, commit }`; see below. |
|
|
78
75
|
|
|
79
|
-
|
|
76
|
+
```markdown
|
|
77
|
+
---
|
|
78
|
+
date: 2026-09-15
|
|
79
|
+
projects: [house]
|
|
80
|
+
tags: [maintenance, warranty]
|
|
81
|
+
amount: 325
|
|
82
|
+
currency: USD
|
|
83
|
+
---
|
|
80
84
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
fields:
|
|
87
|
-
- key: odometer # lowercase letters, digits, underscore
|
|
88
|
-
label: Odometer
|
|
89
|
-
kind: number # text | longtext | number | date | select | boolean | url
|
|
90
|
-
- key: shop
|
|
91
|
-
label: Shop
|
|
92
|
-
kind: text
|
|
85
|
+
# AC serviced
|
|
86
|
+
|
|
87
|
+
Replaced the capacitor.
|
|
88
|
+
|
|
89
|
+
[Receipt](../files/ac-receipt.pdf)
|
|
93
90
|
```
|
|
94
91
|
|
|
95
|
-
|
|
92
|
+
Every other key is yours. **Writers must preserve keys they don't know**, along with the comments and formatting of the YAML they didn't change.
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
An amount written only in prose ("Paid $325") stays prose: GitRoll never extracts it, and no total counts it. If you want it counted, put it in `amount`.
|
|
95
|
+
|
|
96
|
+
## Code references
|
|
97
|
+
|
|
98
|
+
An event may say which repository, branch and commit it is about:
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
---
|
|
102
|
+
source:
|
|
103
|
+
repo: acme/app
|
|
104
|
+
branch: fix/checkout
|
|
105
|
+
commit: 9f1c2d3e4a5b6c7d8e9f0a1b2c3d4e5f60718293
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
# Checkout times out
|
|
109
|
+
|
|
110
|
+
Caused by the index dropped in 9f1c2d3, fixed in #412. Related: other/lib#88.
|
|
104
111
|
```
|
|
105
112
|
|
|
106
|
-
|
|
113
|
+
`repo` is `owner/repo` or any address Git understands (`git@github.com:acme/app.git`, `https://github.com/acme/app`). **This is the source repository — where the work happened.** It is not the repository the log lives in, and it is not the branch the log is on, even when they happen to be the same.
|
|
114
|
+
|
|
115
|
+
References in the text are ordinary text, and readers recognize them:
|
|
116
|
+
|
|
117
|
+
| Written | Means |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| `#412` | Pull request or issue 412 **in the event's own `source.repo`**. With no `source.repo`, it is shown as text and never linked to a guess. |
|
|
120
|
+
| `owner/repo#412` | 412 in that repository |
|
|
121
|
+
| `9f1c2d3` … `9f1c2d3e4a5b…` | A commit, 7 to 40 hex characters |
|
|
122
|
+
| `https://github.com/owner/repo/pull/412` | Whatever the URL says |
|
|
107
123
|
|
|
108
|
-
|
|
124
|
+
Code spans, fenced code and HTML comments are not prose, so a `#412` inside one is an example, not a reference.
|
|
109
125
|
|
|
110
|
-
|
|
126
|
+
## Links between events
|
|
111
127
|
|
|
112
|
-
|
|
128
|
+
An event links to another with an ordinary relative Markdown link:
|
|
113
129
|
|
|
114
|
-
|
|
130
|
+
```markdown
|
|
131
|
+
Follows [the incident on the 14th](2026-09-14-checkout-timeouts.md).
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
That link is the relationship, and the backlink is the same link read the other way round — worked out when it is needed, never stored. Nothing declares a relationship, and the link still resolves on GitHub and in a text editor.
|
|
115
135
|
|
|
116
|
-
|
|
136
|
+
## Dates
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
- A date is `2026-09-15`, or a full ISO 8601 timestamp when the time of day matters (`2026-09-15T14:30:00-07:00`).
|
|
139
|
+
- The date comes from the front matter if it has one, else from the `YYYY-MM-DD` prefix of the file name.
|
|
140
|
+
- **If neither supplies one, the event is undated.** That is a normal state, not an error: it shows as undated and is left out of date searches.
|
|
141
|
+
- Filters and grouping compare **calendar days as written**, so an event stays on the day its author put it on wherever the log is opened.
|
|
142
|
+
- Anything a reader can't parse as a date (`Sept 15`, `15/09/2026`) is reported by `gitroll check` rather than guessed at.
|
|
119
143
|
|
|
120
|
-
##
|
|
144
|
+
## `.gitroll/config.yaml`
|
|
121
145
|
|
|
122
146
|
```yaml
|
|
123
|
-
#
|
|
124
|
-
name:
|
|
125
|
-
|
|
126
|
-
|
|
147
|
+
template_version: 1 # required: which template revision this repository follows
|
|
148
|
+
name: My Roll # optional: the name shown in GitRoll
|
|
149
|
+
attachments:
|
|
150
|
+
max_mb: 25 # optional per-file limit for new attachments
|
|
151
|
+
remove_location: true # optional; remove GPS data from photos (default true)
|
|
152
|
+
ai: true # optional; false turns off "Ask your Roll" for everyone
|
|
127
153
|
```
|
|
128
154
|
|
|
129
|
-
|
|
155
|
+
`.gitroll/theme.css` (optional) overrides the app's style variables. See docs/TEMPLATES.md.
|
|
156
|
+
|
|
157
|
+
### Template versions
|
|
158
|
+
|
|
159
|
+
`template_version` says which revision of the template a repository follows. It describes the repository, not the app, so a new GitRoll release never changes it.
|
|
160
|
+
|
|
161
|
+
- **Version 1** is this document.
|
|
162
|
+
- It is **incremented only for published changes to the template's structure or conventions.** New *optional* keys (`source`, and anything else a writer preserves rather than requires) don't change it: a reader of version 1 still reads every file correctly, and bumping the version would stop older versions of GitRoll writing to a repository they understand perfectly well.
|
|
163
|
+
- Readers read it when they open a repository, and **preserve it** during ordinary logging and editing.
|
|
164
|
+
- **A missing marker means the version is unknown, not current.** Tools say so, explain how to record one (`gitroll template --set 1`), and must not write one on their own: a version an app only guessed at is not a fact about the repository.
|
|
165
|
+
- **A version newer than the reader understands blocks writes.** Nothing is changed, and the reader says the app needs updating.
|
|
166
|
+
- **Future upgrades are explicit and reviewable**, and the marker is updated only after the upgrade succeeds.
|
|
167
|
+
|
|
168
|
+
There is no per-event version field. An event is Markdown; it does not need one.
|
|
169
|
+
|
|
170
|
+
## Identity, history and simultaneous edits
|
|
171
|
+
|
|
172
|
+
- **Identity** is the file's path. It is readable, typeable, and needs nothing generated.
|
|
173
|
+
- **Renames and moves** are ordinary Git renames. A writer that moves an event rewrites the relative links in its body so they still resolve, and Git history follows the file.
|
|
174
|
+
- **Filename collisions**: a writer appends `-2`, `-3`, … before the extension. Two events logged the same day about the same thing become `2026-09-15-ac-serviced.md` and `2026-09-15-ac-serviced-2.md`. Nothing is overwritten, ever.
|
|
175
|
+
- **Edits** rewrite the file in place, each in its own commit. Git history is the audit trail: previous versions are never rewritten or force-pushed away by GitRoll.
|
|
176
|
+
- **Simultaneous edits** are merged as Markdown, line by line, the way Git merges any text file. That succeeds whenever two people touched different parts of the file. When the same lines changed on both sides, this device's version is kept as it is and the other version is appended in a note tagged `#conflict`, so nothing is lost and the conflict is easy to find.
|
|
177
|
+
- **Authors** come from Git: `git log` and `git blame` know who wrote what. Events carry no author field, so nobody can sign as someone else by editing a file.
|
|
130
178
|
|
|
131
|
-
##
|
|
179
|
+
## Reading a log
|
|
132
180
|
|
|
133
|
-
|
|
181
|
+
A reader:
|
|
134
182
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- invalid project or type definition files
|
|
140
|
-
- `data` values that don't match a known type's field kinds
|
|
183
|
+
1. Looks for `.gitroll/config.yaml` at the root of the Git repository (searching upwards from the current folder, so it works from a subfolder).
|
|
184
|
+
2. Checks `template_version` before writing anything.
|
|
185
|
+
3. Reads every `*.md` under `.gitroll/events/`, recursively.
|
|
186
|
+
4. Resolves each event's links relative to the event's own path.
|
|
141
187
|
|
|
142
|
-
|
|
188
|
+
Files it cannot parse are reported, not skipped silently, and never stop the rest of the log from loading.
|
|
143
189
|
|
|
144
|
-
##
|
|
190
|
+
## What is deliberately absent
|
|
145
191
|
|
|
146
|
-
|
|
192
|
+
No ids, no per-event version, no required timestamps, no author fields, no attachment manifests, no content-hash file names, no project definition files, no event type definitions, no mandatory folder structure. Every one of those was something a person would have had to produce before they could write down what happened.
|