@adhd/backlog 0.1.9 → 1.0.1
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 +128 -47
- package/README.md +369 -81
- package/api.d.ts +196 -0
- package/api.ir.json +1 -0
- package/cli.d.ts +45 -18
- package/env.d.ts +23 -3
- package/envelope.d.ts +163 -0
- package/extract-live.d.ts +56 -0
- package/index.d.ts +11 -10
- package/index.js +255 -197
- package/index.mjs +11348 -19043
- package/install-skill.d.ts +23 -0
- package/ir-artifact.d.ts +86 -0
- package/package.json +51 -15
- package/query/card.d.ts +31 -0
- package/query/get.d.ts +11 -0
- package/query/index.d.ts +67 -0
- package/query/markdown.d.ts +11 -0
- package/query/query.d.ts +131 -0
- package/query/resolve.d.ts +123 -0
- package/query/types.d.ts +450 -0
- package/query/views/registry.d.ts +43 -0
- package/query/views/semantic.d.ts +101 -0
- package/query/views/stats.d.ts +109 -0
- package/search-shortcut.d.ts +79 -0
- package/serve.d.ts +18 -0
- package/server.d.ts +139 -4
- package/skill/SKILL.md +632 -138
- package/store/graph-backlog-store.d.ts +80 -17
- package/store/immediate-retry.d.ts +24 -13
- package/store/type-policy.d.ts +4 -0
- package/store/vocabulary-guard.d.ts +52 -0
- package/write/audit.d.ts +36 -0
- package/write/bootstrap.d.ts +161 -0
- package/write/catalog.d.ts +369 -0
- package/write/citation-path.d.ts +133 -0
- package/write/claim-lease.d.ts +21 -0
- package/write/claim.d.ts +80 -0
- package/write/create-issue.d.ts +253 -0
- package/write/delete.d.ts +39 -0
- package/write/embed-drain.d.ts +68 -0
- package/write/embedding-config.d.ts +81 -0
- package/write/embedding-observer.d.ts +80 -0
- package/write/errors.d.ts +365 -0
- package/write/issue-status.d.ts +10 -0
- package/write/move.d.ts +70 -0
- package/write/relate.d.ts +52 -0
- package/write/transition.d.ts +64 -0
- package/write/tx.d.ts +344 -0
- package/write/update.d.ts +81 -0
- package/client.d.ts +0 -174
- package/markdown.d.ts +0 -75
- package/migration-admin.d.ts +0 -26
- package/model.d.ts +0 -437
- package/store/audit-log.d.ts +0 -16
- package/store/claim.d.ts +0 -24
- package/store/crud.d.ts +0 -62
- package/store/ids.d.ts +0 -24
- package/store/lifecycle.d.ts +0 -36
- package/store/mapping.d.ts +0 -101
- package/store/mutate-metadata.d.ts +0 -8
- package/store/query.d.ts +0 -68
- package/store/repo-migration.d.ts +0 -51
- package/store/serve-lock.d.ts +0 -42
- package/store/structure.d.ts +0 -66
package/README.md
CHANGED
|
@@ -1,103 +1,391 @@
|
|
|
1
1
|
# @adhd/backlog
|
|
2
2
|
|
|
3
|
-
A structured, queryable,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
already uses.
|
|
3
|
+
A structured, queryable, concurrent-safe backlog for bugs, debt, features, and
|
|
4
|
+
investigations — served from one graph store over a CLI, an MCP server, an HTTP
|
|
5
|
+
API, and an in-process client.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
live via `@adhd/apigen-core-client` (no code generation — `extract()` →
|
|
10
|
-
`composeSchemas()` → `plugin.run()`).
|
|
7
|
+
## Why
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
The problem this solves: a plain `BACKLOG.md` file has no way to represent
|
|
10
|
+
"someone is already working on this," no way to enforce that a closed item
|
|
11
|
+
cites the fix that closed it, no structured way to ask "what's open in this
|
|
12
|
+
component," and no safe way for two agents to edit it at once. `@adhd/backlog`
|
|
13
|
+
replaces that file with a real store: issues are addressed by a stable `uid`,
|
|
14
|
+
every mutation is audited, claims are leases with staleness detection, and
|
|
15
|
+
queries are structured filters instead of `grep`.
|
|
16
|
+
|
|
17
|
+
## Install
|
|
15
18
|
|
|
16
19
|
```bash
|
|
17
|
-
pnpm add @adhd/backlog
|
|
20
|
+
pnpm add -g @adhd/backlog
|
|
21
|
+
adhd-backlog --help
|
|
18
22
|
```
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
This installs the `adhd-backlog` CLI binary. The same package also runs as an
|
|
25
|
+
MCP server, an HTTP API, and an importable client library — see
|
|
26
|
+
[Transports](#transports).
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
Issues live under a **project** (and, optionally, a **component**), both
|
|
31
|
+
resolved by name or `uid`. File the project first — `create` never mints one.
|
|
32
|
+
File every issue with the correct project **and component**: a component-less
|
|
33
|
+
item lands on the project's reserved `(root)` component and is invisible to
|
|
34
|
+
component-scoped queries. The agent-facing filing rules and the real misfiling
|
|
35
|
+
hazards live in [`skill/SKILL.md` §4](skill/SKILL.md).
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
adhd-backlog upsert-project --input '{
|
|
39
|
+
"name": "demo-project",
|
|
40
|
+
"path": "/tmp/demo",
|
|
41
|
+
"by": "agent:worker-1"
|
|
42
|
+
}'
|
|
43
|
+
```
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const ctx = { store, env };
|
|
45
|
+
```json
|
|
46
|
+
{ "ok": true, "data": { "uid": "49ec673b-…", "created": true, "project": { "uid": "49ec673b-…", "name": "demo-project", "path": "/tmp/demo" } } }
|
|
47
|
+
```
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
family: 'BUG-EXAMPLE',
|
|
34
|
-
title: 'Example bug',
|
|
35
|
-
body: 'Something is broken.',
|
|
36
|
-
repo: 'PseudoSky/adhd',
|
|
37
|
-
});
|
|
49
|
+
File an issue against it:
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
```bash
|
|
52
|
+
adhd-backlog create --input '{
|
|
53
|
+
"title": "Query pagination drops the last page under offset paging",
|
|
54
|
+
"body": "offset+limit near the end of a result set silently returns fewer rows than `total` implies.",
|
|
55
|
+
"project": "demo-project",
|
|
56
|
+
"priority": "HIGH",
|
|
57
|
+
"gitContext": "feat/backlog-hard-replacement @ 4bf902fc",
|
|
58
|
+
"by": "agent:worker-1"
|
|
59
|
+
}'
|
|
60
|
+
```
|
|
44
61
|
|
|
45
|
-
|
|
62
|
+
```json
|
|
63
|
+
{ "ok": true, "data": { "created": true, "uid": "b3b2da0e-…", "item": { "uid": "b3b2da0e-…", "title": "Query pagination drops the last page under offset paging", "kind": "issue", "status": "open", "priority": "HIGH", "project": "49ec673b-…", "component": "65c4e373-…", "createdAt": "2026-09-24T00:14:38.802Z", "author": "agent:worker-1", "gitContext": "feat/backlog-hard-replacement @ 4bf902fc" } } }
|
|
46
64
|
```
|
|
47
65
|
|
|
48
|
-
|
|
66
|
+
> `project` and `component` in the result are `uid`s, not names. `gitContext`
|
|
67
|
+
> is described under [Citations & git context](#citations--git-context).
|
|
49
68
|
|
|
50
|
-
|
|
51
|
-
|
|
69
|
+
Query for it:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
adhd-backlog query --input '{"filter":{"project":"demo-project","status":"open"}}'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{ "ok": true, "data": { "view": "list", "items": [{ "uid": "b3b2da0e-…", "title": "Query pagination drops the last page under offset paging", "kind": "issue", "status": "open", "priority": "HIGH" }], "hasMore": false }, "meta": { "total": 1, "returned": 1, "limit": 50 } }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Move it forward — a `transition` records the status change in the issue's audit
|
|
80
|
+
trail. A non-empty `note` is required by default
|
|
81
|
+
(`project_policy.transition_requires_note`); a terminal status additionally
|
|
82
|
+
requires verifiable `citations` **only if** the project's policy turns citation
|
|
83
|
+
enforcement on (`citationRequired`, default `false`):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
adhd-backlog transition --input '{
|
|
87
|
+
"uid": "b3b2da0e-…",
|
|
88
|
+
"toStatus": "in-progress",
|
|
89
|
+
"note": "reproduced with limit:10, offset:95 against a 100-row set",
|
|
90
|
+
"by": "agent:worker-1"
|
|
91
|
+
}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{ "ok": true, "data": { "uid": "b3b2da0e-…", "fromStatus": "open", "toStatus": "in-progress", "transitionUid": "9bcb9844-…" } }
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
A failed call returns the same envelope with `ok:false` instead of throwing:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{ "ok": false, "error": { "code": "item_not_found", "message": "No live issue found for uid \"does-not-exist\"", "details": { "retryable": false } } }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Every output above was captured from the built binary
|
|
105
|
+
(`entrypoint/backlog/dist/index.js`); `uid`s are truncated with `…`. See
|
|
106
|
+
[Which build these docs describe](#which-build-these-docs-describe).
|
|
107
|
+
|
|
108
|
+
## Key features
|
|
109
|
+
|
|
110
|
+
### 1. One shared graph store, concurrent-safe by design
|
|
111
|
+
|
|
112
|
+
The store is not a file you edit — it is a graph database that many processes
|
|
113
|
+
read and write at once. There is no single-writer lock; concurrency is bounded
|
|
114
|
+
by real transactions and leases. File the same item from two agents and one
|
|
115
|
+
wins cleanly, with correct audit rows. (SPEC.md §3/§4; `src/write/tx.ts`.)
|
|
116
|
+
|
|
117
|
+
### 2. Leased claims for multi-agent work
|
|
52
118
|
|
|
53
|
-
|
|
54
|
-
|
|
119
|
+
`claim` is a lease, not a flag: it is idempotent for the same claimant
|
|
120
|
+
(`renew`), self-healing when stale, and it protects the item — a competing
|
|
121
|
+
`transition` by another agent is refused with `conflict` until the lease is
|
|
122
|
+
released or goes stale.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
adhd-backlog claim --input '{"uid":"b3b2da0e-…","by":"agent:worker-1","action":"claim"}'
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
{ "ok": true, "data": { "uid": "b3b2da0e-…", "status": "claimed", "claimedBy": "agent:worker-1", "claimedAt": "2026-09-24T00:14:39.978Z" } }
|
|
55
130
|
```
|
|
56
131
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
132
|
+
### 3. Structured, verifiable citations
|
|
133
|
+
|
|
134
|
+
A citation is `{ file, lines?, context?, symbol? }`, not hand-typed markdown.
|
|
135
|
+
When a project enforces citations, a terminal transition is rejected with
|
|
136
|
+
`precondition_failed` unless every cited file resolves inside the project's own
|
|
137
|
+
registered path. Name a `symbol` and the store shells out to
|
|
138
|
+
`gitnexus impact <symbol>` at write time to stamp a best-effort `blastRadius`
|
|
139
|
+
on the citation.
|
|
140
|
+
|
|
141
|
+
### 4. A registry that answers "where does this live?"
|
|
63
142
|
|
|
64
|
-
|
|
143
|
+
`lookup` resolves a tool name, file path, or URL to its owning
|
|
144
|
+
project/component — before you reach for `find`. `query` also lists the
|
|
145
|
+
registry directly:
|
|
65
146
|
|
|
66
147
|
```bash
|
|
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
|
-
|
|
148
|
+
adhd-backlog get --input '{"registry":"project","name":"demo-project"}'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{ "ok": true, "data": { "uid": "49ec673b-…", "name": "demo-project", "path": "/tmp/demo", "components": [{ "name": "(root)" }], "locations": [] } }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 5. Optional semantic search, optional Markdown rendering
|
|
156
|
+
|
|
157
|
+
With embeddings off (the default), keyword filtering (`filter.grep`),
|
|
158
|
+
exact/registry lookup, and every write verb work fully. Turn them on and
|
|
159
|
+
`query`'s natural-language `text` routes to semantic ranking; ask for a semantic
|
|
160
|
+
read with no backend and you get a precise `rag_not_configured` error rather
|
|
161
|
+
than a silent empty result. `query --input '{"format":"markdown", …}'` renders
|
|
162
|
+
every item-list view as Markdown.
|
|
163
|
+
|
|
164
|
+
### 6. N-way fan-out with `batch action`
|
|
165
|
+
|
|
166
|
+
Run one operation over many items instead of N one-at-a-time calls. `operation`
|
|
167
|
+
is the mounted id (`backlog/create`, …); each item wraps its payload under
|
|
168
|
+
`input`; `mode` (`parallel`/`serial`/`chained`), `onItemError`, `concurrency`,
|
|
169
|
+
and `itemTimeoutMs` govern the run.
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
adhd-backlog batch action --input '{
|
|
173
|
+
"operation": "backlog/get",
|
|
174
|
+
"items": [{"input": {"uid": "does-not-exist"}}]
|
|
175
|
+
}'
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 7. Supersede-safe history
|
|
179
|
+
|
|
180
|
+
A `body` edit does not mutate in place — it mints a successor issue and carries
|
|
181
|
+
the previous node's edges (claims, citations, notes, transitions, relations)
|
|
182
|
+
forward to it. The old `uid` remains queryable history: addressing it returns
|
|
183
|
+
`conflict` and names the live successor, so a stale uid can never silently
|
|
184
|
+
resolve to the wrong record.
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{ "ok": false, "error": { "code": "conflict", "message": "Issue \"63c2f57e-…\" was superseded by a body edit and is no longer the live issue; it now lives under \"e3b32183-…\"", "details": { "retryable": false } } }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Command surface
|
|
191
|
+
|
|
192
|
+
Every verb but `embedding-status` takes a single `--input` flag carrying one JSON
|
|
193
|
+
object; there are no per-field flags. Nineteen operations (the 18 verbs plus
|
|
194
|
+
`batch`):
|
|
195
|
+
|
|
196
|
+
| Verb | CLI | MCP tool |
|
|
197
|
+
| ----------------- | ------------------------------- | -------------------------- |
|
|
198
|
+
| `get` | `adhd-backlog get` | `backlog_get` |
|
|
199
|
+
| `query` | `adhd-backlog query` | `backlog_query` |
|
|
200
|
+
| `priorityMatrix` | `adhd-backlog priority-matrix` | `backlog_priority_matrix` |
|
|
201
|
+
| `partOfRollup` | `adhd-backlog part-of-rollup` | `backlog_part_of_rollup` |
|
|
202
|
+
| `openCurve` | `adhd-backlog open-curve` | `backlog_open_curve` |
|
|
203
|
+
| `embeddingStatus` | `adhd-backlog embedding-status` | `backlog_embedding_status` |
|
|
204
|
+
| `lookup` | `adhd-backlog lookup` | `backlog_lookup` |
|
|
205
|
+
| `create` | `adhd-backlog create` | `backlog_create` |
|
|
206
|
+
| `update` | `adhd-backlog update` | `backlog_update` |
|
|
207
|
+
| `transition` | `adhd-backlog transition` | `backlog_transition` |
|
|
208
|
+
| `claim` | `adhd-backlog claim` | `backlog_claim` |
|
|
209
|
+
| `relate` | `adhd-backlog relate` | `backlog_relate` |
|
|
210
|
+
| `move` | `adhd-backlog move` | `backlog_move` |
|
|
211
|
+
| `delete` | `adhd-backlog delete` | `backlog_delete` |
|
|
212
|
+
| `upsertProject` | `adhd-backlog upsert-project` | `backlog_upsert_project` |
|
|
213
|
+
| `upsertComponent` | `adhd-backlog upsert-component` | `backlog_upsert_component` |
|
|
214
|
+
| `upsertLocation` | `adhd-backlog upsert-location` | `backlog_upsert_location` |
|
|
215
|
+
| `rmLocation` | `adhd-backlog rm-location` | `backlog_rm_location` |
|
|
216
|
+
| `batch` | `adhd-backlog batch action` | `batch_action` |
|
|
217
|
+
|
|
218
|
+
`--help` prints these as `backlog <verb>`; the CLI also accepts the bare
|
|
219
|
+
`adhd-backlog <verb>` form shown above, and accepts the explicit namespace
|
|
220
|
+
prefix at any position. `get`/`query`/`lookup`/`embedding-status` are reads.
|
|
221
|
+
`create`/`update`/`transition`/`claim`/`relate`/`move`/`delete` mutate one
|
|
222
|
+
issue. The four `upsert*`/`rmLocation` verbs manage the **registry** —
|
|
223
|
+
projects, components, and locations. `batch action` fans any one of them out
|
|
224
|
+
over many items.
|
|
225
|
+
|
|
226
|
+
## Transports
|
|
227
|
+
|
|
228
|
+
`adhd-backlog` mounts one set of operation descriptors onto every host — there
|
|
229
|
+
is no per-transport reimplementation, so a change to a verb's behavior is
|
|
230
|
+
simultaneously true everywhere:
|
|
231
|
+
|
|
232
|
+
- **CLI** — `adhd-backlog <verb> --input '<json>'`
|
|
233
|
+
- **MCP** — tools named `backlog_<verb>` (e.g. `backlog_create`, `backlog_query`)
|
|
234
|
+
- **HTTP** — a REST API generated from the same descriptors, with an OpenAPI document
|
|
235
|
+
- **In-process** — the package's exported client library, for embedding the store in a Node process
|
|
236
|
+
|
|
237
|
+
## Envelope
|
|
238
|
+
|
|
239
|
+
Every verb call returns one of two shapes, on every transport:
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
{ ok: true, data: T, warnings?: string[], meta?: { total, returned, limit?, offset?, truncated? } }
|
|
243
|
+
{ ok: false, error: { code, message, details? }, warnings?: string[] }
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`meta` is present on list-shaped reads (`query`) and its `total` is the true
|
|
247
|
+
match count _before_ `limit`/`offset` are applied; a truncated page sets
|
|
248
|
+
`data.hasMore: true` and `data.nextCursor`, so a short result never silently
|
|
249
|
+
looks complete.
|
|
250
|
+
|
|
251
|
+
### Error codes
|
|
252
|
+
|
|
253
|
+
| Code | Meaning | CLI exit code |
|
|
254
|
+
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
255
|
+
| `not_found` | A referenced catalog entry (project/component/kind/status/priority) doesn't exist | 4 |
|
|
256
|
+
| `item_not_found` | The addressed issue doesn't exist | 1 |
|
|
257
|
+
| `invalid_argument` | Malformed flag or parameter shape | 2 |
|
|
258
|
+
| `validation` | Schema rejection — unknown filter key, unknown projection field, over-limit | 2 |
|
|
259
|
+
| `store_busy` | Store contention (a lease or a write conflict); `details.retryable` and `details.retryAfterMs` indicate whether/how to retry | 1 |
|
|
260
|
+
| `rag_not_configured` | A semantic/similarity read was requested but no embedding backend is configured, or the vector space is empty | 1 |
|
|
261
|
+
| `conflict` | Someone else holds the claim, a single-valued relation is already taken, or a supersede raced | 1 |
|
|
262
|
+
| `precondition_failed` | A gate refused the write — a terminal transition missing its required citation/note, or a citation that couldn't be verified against a known project path | 1 |
|
|
263
|
+
| `internal` | Unclassified server-side failure | 1 |
|
|
264
|
+
|
|
265
|
+
Success always exits 0. `item_not_found` and `internal` are deliberately
|
|
266
|
+
distinct codes even though they share exit code 1 — a caller distinguishes
|
|
267
|
+
"this uid doesn't exist" from "something broke" by `error.code`, not by exit
|
|
268
|
+
code alone.
|
|
269
|
+
|
|
270
|
+
### Citations & git context
|
|
271
|
+
|
|
272
|
+
A citation is `{ file, lines?, context?, symbol? }`. Pass `citations` on
|
|
273
|
+
`create`, or on the `transition` that moves an issue into a terminal status
|
|
274
|
+
when the project's policy requires it. `file` must name a file, not a
|
|
275
|
+
directory: a directory target is rejected as a non-retryable `validation`
|
|
276
|
+
error.
|
|
277
|
+
|
|
278
|
+
The item-level **`gitContext`** is separate from a citation's own `context`:
|
|
279
|
+
it records the repo disclosure contract's `<active git context>` — the first
|
|
280
|
+
element of a `Citations:` block (`Citations: [<active git context>, …]`).
|
|
281
|
+
Pass it on `create`, or on a `transition` to update it. It is stored on the
|
|
282
|
+
issue itself, and a `format:'markdown'` query renders it once at the head of
|
|
283
|
+
the item's `Citations:` block. Omit it and nothing is stored.
|
|
284
|
+
|
|
285
|
+
### Which build these docs describe
|
|
286
|
+
|
|
287
|
+
These docs describe `entrypoint/backlog/dist/index.js` built from revision
|
|
288
|
+
`9df2a5c7`, whose `create`/`transition` inputs include `gitContext`. A
|
|
289
|
+
**globally installed** `adhd-backlog` may be an older build (it is whatever was
|
|
290
|
+
last published/installed); on such a build `gitContext` is not in the schema
|
|
291
|
+
and is rejected with `invalid_argument`, and the stats/rollup ops
|
|
292
|
+
(`priority-matrix` / `part-of-rollup` / `open-curve`) are absent. Run
|
|
293
|
+
`adhd-backlog --help` and compare the `backlog create` / `backlog
|
|
294
|
+
priority-matrix` lines against this page if a documented field or verb is
|
|
295
|
+
refused.
|
|
296
|
+
|
|
297
|
+
## Build & startup
|
|
298
|
+
|
|
299
|
+
`nx build backlog` emits TWO things into `dist/`: the compiled
|
|
300
|
+
`index.js` + `api.d.ts`, and `api.ir.json` — the extracted operation
|
|
301
|
+
descriptors for `api.d.ts`, produced by the build's own hidden `ir-artifact`
|
|
302
|
+
subcommand:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
node dist/index.js ir-artifact --out dist/api.ir.json
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Startup (the CLI, an MCP `initialize`, `--help`) reads `api.ir.json` and
|
|
309
|
+
derives the mounted surface from it **without loading the type extractor**, so
|
|
310
|
+
a cold start is fast without any warm cache — the fix for a startup path that
|
|
311
|
+
previously paid a multi-second synchronous extraction on every invocation.
|
|
312
|
+
|
|
313
|
+
`api.ir.json` is trusted only while it still matches the built declarations
|
|
314
|
+
beside it: the artifact records content hashes of the WHOLE `dist/**.d.ts`
|
|
315
|
+
surface it was extracted from (not just `api.d.ts` — extraction resolves types
|
|
316
|
+
through `api.d.ts`'s sibling imports), and startup re-hashes that surface
|
|
317
|
+
before using it. A missing, corrupt, or stale artifact (any `.d.ts` changed
|
|
318
|
+
since the bake) is refused, and startup falls back to a live extraction through
|
|
319
|
+
the extract-stage IR cache, which persists the result for the next run.
|
|
320
|
+
|
|
321
|
+
`ir-artifact` is a build step, not a user command — it is absent from `--help`
|
|
322
|
+
and store-free (it never opens the graph store and never writes under
|
|
323
|
+
`~/.adhd`).
|
|
324
|
+
|
|
325
|
+
| Setting | Env var | Default | Notes |
|
|
326
|
+
| ---------------- | -------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
327
|
+
| IR cache enabled | `APIGEN_IR_CACHE_ENABLED` | `1` | Governs ONLY the **runtime fallback** cache. It does **not** bypass the baked `api.ir.json` artifact — that artifact is the startup path, not a cache |
|
|
328
|
+
| IR cache file | `APIGEN_IR_CACHE_FILE` | a machine-global path under `~/.adhd` | Where a fallback extraction's result is cached |
|
|
329
|
+
|
|
330
|
+
## Library API
|
|
331
|
+
|
|
332
|
+
Beyond the CLI/MCP/HTTP surface, the package exports its query layer
|
|
333
|
+
(`src/query/index.ts`), including three rollup/stats read views that are **not**
|
|
334
|
+
members of `query.view`:
|
|
335
|
+
|
|
336
|
+
- `priorityMatrix(handle, { filter? })` — a status-aware per-priority count
|
|
337
|
+
breakdown (defaults to open work; `filter.status` may be `'open'`, `'closed'`,
|
|
338
|
+
`'all'`, or a status name).
|
|
339
|
+
- `partOfRollup(handle, { uid })` — transitive `part_of` descendants of an
|
|
340
|
+
issue, counted once each regardless of chain depth.
|
|
341
|
+
- `openCurve(handle, { filter?, at })` — per-sampled-instant counts of issues
|
|
342
|
+
that existed and how many were open, reconstructed from the audit trail.
|
|
343
|
+
|
|
344
|
+
Reach them by importing `@adhd/backlog` in-process. The same three are also
|
|
345
|
+
mounted as operations — `priority-matrix` / `part-of-rollup` / `open-curve` on
|
|
346
|
+
the CLI (`backlog_priority_matrix` / `backlog_part_of_rollup` /
|
|
347
|
+
`backlog_open_curve` on MCP); see the command surface above.
|
|
348
|
+
|
|
349
|
+
## Configuration
|
|
350
|
+
|
|
351
|
+
Configuration cascades over `@adhd/environment`, prefixed `ADHD_BACKLOG_`
|
|
352
|
+
(later layers override earlier: built-in default → config file → environment
|
|
353
|
+
variable). The store defaults to a single shared **global** scope — one backlog
|
|
354
|
+
spanning every project on the machine, not one per repository — so an agent
|
|
355
|
+
working across repos sees the same graph everywhere unless it explicitly opts
|
|
356
|
+
into a narrower scope.
|
|
357
|
+
|
|
358
|
+
| Setting | Env var | Default | Notes |
|
|
359
|
+
| ------------------ | ----------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
360
|
+
| Database path | `ADHD_BACKLOG_DATABASE_PATH` | resolved under the scope root | Where the graph store's data file lives |
|
|
361
|
+
| Write busy timeout | `ADHD_BACKLOG_DATABASE_BUSY_TIMEOUT_MS` | `5000` | How long a write waits on a contended lock before giving up |
|
|
362
|
+
| Log level | `ADHD_BACKLOG_LOG_LEVEL` | `info` | `trace`\|`debug`\|`info`\|`warn`\|`error`\|`fatal`\|`silent` |
|
|
363
|
+
| Scope | `ADHD_BACKLOG_SCOPE` (falls back to `ADHD_ENV_SCOPE`) | `global` | Which store root to resolve against |
|
|
364
|
+
| Namespace | `--namespace <value>` CLI flag (no env var) | `production` | Which path segment under the scope root to resolve against (`<root>/backlog/<namespace>/…`) — one of `production`\|`test`\|`sandbox`. `--namespace sandbox` ALSO mints a fresh throwaway root and writes a real `config.yaml` there with `embedding.enabled: false`, so a sandboxed invocation is isolated along two independent axes plus a deliberate config, never an accident of an empty directory |
|
|
365
|
+
| Semantic search | `ADHD_BACKLOG_EMBEDDING_ENABLED` | `false` | See below |
|
|
366
|
+
| Embedding provider | `ADHD_BACKLOG_EMBEDDING_PROVIDER` | `fastembed` | Only consulted when embedding is enabled |
|
|
367
|
+
| Embedding model | `ADHD_BACKLOG_EMBEDDING_MODEL` | `bge-base-en-v1.5` (768-dim) | Only consulted when embedding is enabled |
|
|
368
|
+
|
|
369
|
+
**Embedding (semantic search) is entirely optional.** With it left at its
|
|
370
|
+
default (`false`), `@adhd/backlog` works fully — every verb, keyword filtering
|
|
371
|
+
(`filter.grep`), and exact/registry lookup all function with no embedding
|
|
372
|
+
backend at all. Turning `filter.semantic`, `filter.anchor`, `view:"similar"`,
|
|
373
|
+
`sort:"relevance"`, or `fields:["_vector"]` on without an embedding backend
|
|
374
|
+
configured doesn't crash anything — it returns a `rag_not_configured` error
|
|
375
|
+
that says exactly that, so a caller can tell "not available" apart from "no
|
|
376
|
+
matches." Enabling embedding requires two optional dependencies to be
|
|
377
|
+
installed alongside the package and a store backend that supports native
|
|
378
|
+
vector storage; if either is missing, backlog logs the reason and leaves
|
|
379
|
+
semantic search unconfigured rather than failing to start.
|
|
380
|
+
|
|
381
|
+
## Further docs
|
|
382
|
+
|
|
383
|
+
- [`skill/SKILL.md`](skill/SKILL.md) — the full agent-facing command surface, worked examples, and filing rules.
|
|
384
|
+
- [`SPEC.md`](SPEC.md) — the functional specification: operation surface, status vocabulary, acceptance criteria.
|
|
385
|
+
- [`DATA_MODEL.md`](DATA_MODEL.md) — the node/edge model this package reads and writes.
|
|
386
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — version history.
|
|
387
|
+
|
|
388
|
+
## Contributing
|
|
389
|
+
|
|
390
|
+
See [`CONTRIBUTING.md`](CONTRIBUTING.md). This package is MIT-licensed under
|
|
391
|
+
[`LICENSE`](LICENSE); security policy: [`SECURITY.md`](../../SECURITY.md).
|