@navbook/cli 0.1.2 → 0.2.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.
Files changed (167) hide show
  1. package/dist/commands/complete.js +124 -0
  2. package/dist/commands/complete.js.map +1 -0
  3. package/dist/{cli/commands → commands}/compose.js +5 -3
  4. package/dist/commands/compose.js.map +1 -0
  5. package/dist/commands/doctor.js +56 -0
  6. package/dist/commands/doctor.js.map +1 -0
  7. package/dist/commands/entity.js +235 -0
  8. package/dist/commands/entity.js.map +1 -0
  9. package/dist/commands/feature.js +202 -0
  10. package/dist/commands/feature.js.map +1 -0
  11. package/dist/commands/init.js +23 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/{cli/commands → commands}/install.js +1 -2
  14. package/dist/commands/install.js.map +1 -0
  15. package/dist/commands/issue.js +89 -0
  16. package/dist/commands/issue.js.map +1 -0
  17. package/dist/commands/policy.js +49 -0
  18. package/dist/commands/policy.js.map +1 -0
  19. package/dist/commands/pr.js +262 -0
  20. package/dist/commands/pr.js.map +1 -0
  21. package/dist/context.js +21 -0
  22. package/dist/context.js.map +1 -0
  23. package/dist/{cli/editor.js → editor.js} +1 -1
  24. package/dist/editor.js.map +1 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/install/completions.js.map +1 -0
  27. package/dist/{cli/install → install}/hook.js +1 -1
  28. package/dist/install/hook.js.map +1 -0
  29. package/dist/{cli/main.js → main.js} +10 -0
  30. package/dist/main.js.map +1 -0
  31. package/dist/{cli/program.js → program.js} +161 -23
  32. package/dist/program.js.map +1 -0
  33. package/dist/{cli/prompt.js → prompt.js} +11 -0
  34. package/dist/prompt.js.map +1 -0
  35. package/dist/render/colors.js.map +1 -0
  36. package/dist/render/detail.js +197 -0
  37. package/dist/render/detail.js.map +1 -0
  38. package/dist/render/table.js.map +1 -0
  39. package/dist/sort.js +77 -0
  40. package/dist/sort.js.map +1 -0
  41. package/package.json +15 -21
  42. package/README.md +0 -165
  43. package/dist/cli/commands/complete.d.ts +0 -9
  44. package/dist/cli/commands/complete.js +0 -72
  45. package/dist/cli/commands/complete.js.map +0 -1
  46. package/dist/cli/commands/compose.d.ts +0 -27
  47. package/dist/cli/commands/compose.js.map +0 -1
  48. package/dist/cli/commands/doctor.d.ts +0 -14
  49. package/dist/cli/commands/doctor.js +0 -127
  50. package/dist/cli/commands/doctor.js.map +0 -1
  51. package/dist/cli/commands/entity.d.ts +0 -55
  52. package/dist/cli/commands/entity.js +0 -209
  53. package/dist/cli/commands/entity.js.map +0 -1
  54. package/dist/cli/commands/init.d.ts +0 -11
  55. package/dist/cli/commands/init.js +0 -39
  56. package/dist/cli/commands/init.js.map +0 -1
  57. package/dist/cli/commands/install.d.ts +0 -17
  58. package/dist/cli/commands/install.js.map +0 -1
  59. package/dist/cli/commands/issue.d.ts +0 -12
  60. package/dist/cli/commands/issue.js +0 -42
  61. package/dist/cli/commands/issue.js.map +0 -1
  62. package/dist/cli/commands/pr.d.ts +0 -64
  63. package/dist/cli/commands/pr.js +0 -466
  64. package/dist/cli/commands/pr.js.map +0 -1
  65. package/dist/cli/commit-flow.d.ts +0 -27
  66. package/dist/cli/commit-flow.js +0 -47
  67. package/dist/cli/commit-flow.js.map +0 -1
  68. package/dist/cli/context.d.ts +0 -39
  69. package/dist/cli/context.js +0 -93
  70. package/dist/cli/context.js.map +0 -1
  71. package/dist/cli/editor.d.ts +0 -23
  72. package/dist/cli/editor.js.map +0 -1
  73. package/dist/cli/errors.d.ts +0 -17
  74. package/dist/cli/errors.js.map +0 -1
  75. package/dist/cli/history-checks.d.ts +0 -21
  76. package/dist/cli/history-checks.js +0 -134
  77. package/dist/cli/history-checks.js.map +0 -1
  78. package/dist/cli/install/completions.d.ts +0 -19
  79. package/dist/cli/install/completions.js.map +0 -1
  80. package/dist/cli/install/hook.d.ts +0 -20
  81. package/dist/cli/install/hook.js.map +0 -1
  82. package/dist/cli/main.d.ts +0 -14
  83. package/dist/cli/main.js.map +0 -1
  84. package/dist/cli/program.d.ts +0 -23
  85. package/dist/cli/program.js.map +0 -1
  86. package/dist/cli/prompt.d.ts +0 -22
  87. package/dist/cli/prompt.js.map +0 -1
  88. package/dist/cli/render/colors.d.ts +0 -13
  89. package/dist/cli/render/colors.js.map +0 -1
  90. package/dist/cli/render/detail.d.ts +0 -10
  91. package/dist/cli/render/detail.js +0 -105
  92. package/dist/cli/render/detail.js.map +0 -1
  93. package/dist/cli/render/table.d.ts +0 -19
  94. package/dist/cli/render/table.js.map +0 -1
  95. package/dist/cli/resolve.d.ts +0 -17
  96. package/dist/cli/resolve.js +0 -68
  97. package/dist/cli/resolve.js.map +0 -1
  98. package/dist/cli/workspace.d.ts +0 -52
  99. package/dist/cli/workspace.js +0 -178
  100. package/dist/cli/workspace.js.map +0 -1
  101. package/dist/core/comments.d.ts +0 -31
  102. package/dist/core/comments.js +0 -80
  103. package/dist/core/comments.js.map +0 -1
  104. package/dist/core/files.d.ts +0 -88
  105. package/dist/core/files.js +0 -441
  106. package/dist/core/files.js.map +0 -1
  107. package/dist/core/frontmatter.d.ts +0 -63
  108. package/dist/core/frontmatter.js +0 -149
  109. package/dist/core/frontmatter.js.map +0 -1
  110. package/dist/core/id.d.ts +0 -46
  111. package/dist/core/id.js +0 -66
  112. package/dist/core/id.js.map +0 -1
  113. package/dist/core/index.d.ts +0 -19
  114. package/dist/core/index.js +0 -20
  115. package/dist/core/index.js.map +0 -1
  116. package/dist/core/json.d.ts +0 -18
  117. package/dist/core/json.js +0 -51
  118. package/dist/core/json.js.map +0 -1
  119. package/dist/core/ops.d.ts +0 -92
  120. package/dist/core/ops.js +0 -173
  121. package/dist/core/ops.js.map +0 -1
  122. package/dist/core/person.d.ts +0 -20
  123. package/dist/core/person.js +0 -50
  124. package/dist/core/person.js.map +0 -1
  125. package/dist/core/query.d.ts +0 -30
  126. package/dist/core/query.js +0 -106
  127. package/dist/core/query.js.map +0 -1
  128. package/dist/core/refs.d.ts +0 -12
  129. package/dist/core/refs.js +0 -36
  130. package/dist/core/refs.js.map +0 -1
  131. package/dist/core/slug.d.ts +0 -22
  132. package/dist/core/slug.js +0 -40
  133. package/dist/core/slug.js.map +0 -1
  134. package/dist/core/time.d.ts +0 -14
  135. package/dist/core/time.js +0 -37
  136. package/dist/core/time.js.map +0 -1
  137. package/dist/core/tree.d.ts +0 -94
  138. package/dist/core/tree.js +0 -237
  139. package/dist/core/tree.js.map +0 -1
  140. package/dist/core/validate.d.ts +0 -55
  141. package/dist/core/validate.js +0 -312
  142. package/dist/core/validate.js.map +0 -1
  143. package/dist/git/config.d.ts +0 -12
  144. package/dist/git/config.js +0 -27
  145. package/dist/git/config.js.map +0 -1
  146. package/dist/git/exec.d.ts +0 -35
  147. package/dist/git/exec.js +0 -58
  148. package/dist/git/exec.js.map +0 -1
  149. package/dist/git/history.d.ts +0 -35
  150. package/dist/git/history.js +0 -82
  151. package/dist/git/history.js.map +0 -1
  152. package/dist/git/index-ops.d.ts +0 -20
  153. package/dist/git/index-ops.js +0 -45
  154. package/dist/git/index-ops.js.map +0 -1
  155. package/dist/git/merge.d.ts +0 -27
  156. package/dist/git/merge.js +0 -57
  157. package/dist/git/merge.js.map +0 -1
  158. package/dist/git/refscan.d.ts +0 -32
  159. package/dist/git/refscan.js +0 -82
  160. package/dist/git/refscan.js.map +0 -1
  161. package/dist/git/repo.d.ts +0 -45
  162. package/dist/git/repo.js +0 -95
  163. package/dist/git/repo.js.map +0 -1
  164. /package/dist/{cli/errors.js → errors.js} +0 -0
  165. /package/dist/{cli/install → install}/completions.js +0 -0
  166. /package/dist/{cli/render → render}/colors.js +0 -0
  167. /package/dist/{cli/render → render}/table.js +0 -0
package/dist/sort.js ADDED
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The orders `nav issue list --sort` offers — spec 02 §2.5.
3
+ *
4
+ * Sorting is a front end's reading of what it was handed, never an order the
5
+ * files or the API hold: core lists newest first and the server takes no sort
6
+ * argument, because an order either of them owned would be the index spec 06
7
+ * §6.6 refuses. So this is here rather than in `core`, and the web client has
8
+ * its own copy of the same rules for the same reason.
9
+ *
10
+ * Each order is a chain of comparisons ending in the one that can never tie,
11
+ * so an ordering is total and two tools sorting one listing agree about it.
12
+ */
13
+ import { compareNewest, readDeadline, readRank } from "@navbook/core";
14
+ import { fail } from "./errors.js";
15
+ export const SORT_ORDERS = ["priority", "deadline", "newest"];
16
+ /** The order a `list` command uses when nobody asks for one: spec 04 §4.2's. */
17
+ export const DEFAULT_SORT = "newest";
18
+ /**
19
+ * What `--sort` was given, or the default when it was not given at all.
20
+ *
21
+ * A value that is not an order is refused rather than defaulted: somebody who
22
+ * typed `--sort priorty` asked a question, and answering a different one by
23
+ * handing back a listing in the usual order would hide the typo.
24
+ */
25
+ export function parseSortOrder(value) {
26
+ if (value === undefined)
27
+ return DEFAULT_SORT;
28
+ if (typeof value === "string" && SORT_ORDERS.includes(value)) {
29
+ return value;
30
+ }
31
+ fail(`--sort must be one of ${SORT_ORDERS.join(", ")}`);
32
+ }
33
+ /**
34
+ * Unranked last and undated last, whichever way the values themselves run.
35
+ *
36
+ * An issue nobody has placed is not at the front of the queue, and one nobody
37
+ * has dated is not the most urgent; both belong after everything that was
38
+ * said about explicitly.
39
+ */
40
+ function nullsLast(a, b, compare) {
41
+ if (a === null)
42
+ return b === null ? 0 : 1;
43
+ if (b === null)
44
+ return -1;
45
+ return compare(a, b);
46
+ }
47
+ const byRank = (a, b) => nullsLast(readRank(a.fm), readRank(b.fm), (x, y) => x - y);
48
+ const byDeadline = (a, b) =>
49
+ // Dates in this spelling sort as text, which is most of why the spelling was
50
+ // chosen: no parse, and no way for a parse to disagree with a comparison.
51
+ nullsLast(readDeadline(a.fm), readDeadline(b.fm), (x, y) => (x < y ? -1 : x > y ? 1 : 0));
52
+ /** Try each comparison in turn; the first that has an opinion decides. */
53
+ function chain(...comparators) {
54
+ return (a, b) => {
55
+ for (const compare of comparators) {
56
+ const verdict = compare(a, b);
57
+ if (verdict !== 0)
58
+ return verdict;
59
+ }
60
+ return 0;
61
+ };
62
+ }
63
+ /**
64
+ * Each order ends on `compareNewest`, which is core's own and cannot tie: the
65
+ * ordering is therefore total, and "newest first" has one spelling rather than
66
+ * two that could drift.
67
+ */
68
+ const COMPARATORS = {
69
+ priority: chain(byRank, byDeadline, compareNewest),
70
+ deadline: chain(byDeadline, byRank, compareNewest),
71
+ newest: compareNewest,
72
+ };
73
+ /** A listing in one of the orders of spec 02 §2.5. */
74
+ export function sortListing(entities, order) {
75
+ return [...entities].sort(COMPARATORS[order]);
76
+ }
77
+ //# sourceMappingURL=sort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort.js","sourceRoot":"","sources":["../src/sort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAqB,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAU,CAAC;AAGvE,gFAAgF;AAChF,MAAM,CAAC,MAAM,YAAY,GAAc,QAAQ,CAAC;AAIhD;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,YAAY,CAAC;IAC7C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,WAAiC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpF,OAAO,KAAkB,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC,yBAAyB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAI,CAAW,EAAE,CAAW,EAAE,OAA+B;IAC7E,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,MAAM,GAAe,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAEhG,MAAM,UAAU,GAAe,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;AACtC,6EAA6E;AAC7E,0EAA0E;AAC1E,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE5F,0EAA0E;AAC1E,SAAS,KAAK,CAAC,GAAG,WAAyB;IACzC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACd,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9B,IAAI,OAAO,KAAK,CAAC;gBAAE,OAAO,OAAO,CAAC;QACpC,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAkC;IACjD,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,CAAC;IAClD,QAAQ,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC;IAClD,MAAM,EAAE,aAAa;CACtB,CAAC;AAEF,sDAAsD;AACtD,MAAM,UAAU,WAAW,CAAC,QAAiC,EAAE,KAAgB;IAC7E,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;AAChD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@navbook/cli",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Git-native issue and pull-request tracking as plaintext files in your repository",
5
5
  "keywords": [
6
6
  "issues",
@@ -11,12 +11,19 @@
11
11
  "markdown"
12
12
  ],
13
13
  "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/peyremorgan/navbook.git",
17
+ "directory": "packages/cli"
18
+ },
19
+ "homepage": "https://github.com/peyremorgan/navbook#readme",
20
+ "bugs": "https://github.com/peyremorgan/navbook/issues",
14
21
  "type": "module",
15
22
  "publishConfig": {
16
23
  "access": "public"
17
24
  },
18
25
  "bin": {
19
- "nav": "dist/cli/main.js"
26
+ "nav": "dist/main.js"
20
27
  },
21
28
  "engines": {
22
29
  "node": ">=24"
@@ -24,28 +31,15 @@
24
31
  "files": [
25
32
  "dist"
26
33
  ],
27
- "exports": {
28
- ".": "./dist/core/index.js",
29
- "./core": "./dist/core/index.js"
34
+ "dependencies": {
35
+ "commander": "^14.0.2",
36
+ "picocolors": "^1.1.1",
37
+ "@navbook/core": "0.2.0"
30
38
  },
31
39
  "scripts": {
32
40
  "build": "tsc -p tsconfig.build.json",
33
41
  "typecheck": "tsc --noEmit",
34
- "lint": "biome check .",
35
- "format": "biome check --write .",
36
- "check": "biome check . && tsc --noEmit",
37
- "test": "node --test \"test/{unit,cli,conformance}/**/*.test.ts\"",
38
- "prepack": "npm run build",
42
+ "test": "node --test \"test/cli/**/*.test.ts\"",
39
43
  "bench": "node --test \"test/perf/**/*.test.ts\""
40
- },
41
- "dependencies": {
42
- "commander": "^14.0.2",
43
- "picocolors": "^1.1.1",
44
- "yaml": "^2.8.4"
45
- },
46
- "devDependencies": {
47
- "@biomejs/biome": "^2.3.6",
48
- "@types/node": "^24.10.1",
49
- "typescript": "^5.9.3"
50
44
  }
51
- }
45
+ }
package/README.md DELETED
@@ -1,165 +0,0 @@
1
- # Navbook
2
-
3
- _A lightweight software project manager that lives inside your git repo._
4
-
5
- Navbook stores every issue and pull request as plaintext files inside the
6
- repository, on the same branch and history as the code they describe. There is
7
- no server, no database, and no hidden ref namespace. If you can clone the
8
- repository, you have the whole tracker.
9
-
10
- This is meant to replace your code forge's issues with a portable,
11
- decentralised, offline-first solution. Is GitHub down? No big deal — you'll push
12
- your comment to `origin` whenever it's available again.
13
-
14
- ```console
15
- $ nav issue open "Login times out on slow connections" --label bug -m "Aborts after 5 s on 3G."
16
- Created .navbook/issues/open/bqlybac0-login-timeout/ (#bqlybac0)
17
-
18
- $ nav issue list
19
- ID STATUS TITLE LABELS
20
- #bqlybac0 open Login times out on slow connections bug
21
-
22
- $ nav issue close bqly --resolution fixed --commit
23
- Closed #bqlybac0 .navbook/issues/closed/bqlybac0-login-timeout/
24
- Committed docs(issue): close #bqlybac0
25
- ```
26
-
27
- That last command moved a directory and made a commit. On the branch that fixes
28
- the bug, the fix and the close travel together — merging the branch merges both.
29
-
30
- ## Install
31
-
32
- Requires Node 24 or newer and a working `git`.
33
-
34
- ```sh
35
- npm install -g @navbook/cli # or: npx @navbook/cli <command>
36
- cd your-repo
37
- nav init
38
- nav install # git alias, merge config, pre-commit hook, completions
39
- ```
40
-
41
- `nav install` prints every change it is about to make and asks before making
42
- it, `apt`-style. `-y` skips the question; `nav uninstall` removes exactly what
43
- it added.
44
-
45
- The one setting worth knowing about is `merge.directoryRenames=true`, which
46
- `nav install` offers. Without it, the most common concurrent pair in Navbook — a
47
- comment racing a close — is placed correctly by git but still reported as a
48
- conflict to confirm. With it, that merge is clean.
49
-
50
- ## What it looks like on disk
51
-
52
- ```
53
- .navbook/
54
- ├── issues/
55
- │ ├── open/
56
- │ │ └── bqlybac0-login-timeout/
57
- │ │ ├── issue.md
58
- │ │ └── comments/
59
- │ │ └── 2026-08-03T141207Z-t5kr1gq6.md
60
- │ └── closed/
61
- └── prs/
62
- ├── open/
63
- ├── merged/
64
- └── closed/
65
- ```
66
-
67
- An issue is a Markdown file with YAML frontmatter. Its status is which directory
68
- it sits in. A comment is one file, which is why two people commenting at once
69
- can never conflict. Every forge file browser, every editor, `ls` and `cat` are
70
- complete Navbook clients for reading.
71
-
72
- **The files are the product.** The `nav` CLI mints IDs, renders listings and
73
- validates the tree, but nothing requires it: creating, commenting on, closing
74
- and reviewing with a text editor and `git` is a first-class, supported workflow.
75
- No operation exists that only the tool can perform correctly.
76
-
77
- ## Commands
78
-
79
- Everything is noun-verb, with one verb vocabulary shared by both entity kinds.
80
-
81
- ```
82
- nav {issue|pr} {open|list|show|edit|comment|close|reopen}
83
- nav pr {update|review|merge}
84
- nav {init|id|doctor|install|uninstall}
85
- ```
86
-
87
- IDs accept any unambiguous prefix of four characters or more, so `bqly` is
88
- usually enough. A full directory name works too.
89
-
90
- | Command | What it does |
91
- |---|---|
92
- | `nav issue open <title>` | File an issue. `-m TEXT`, or `$EDITOR` opens on the new file. |
93
- | `nav issue list [query]` | Filtered table; `--json` for one JSON object per line. |
94
- | `nav issue close <id> [--resolution R]` | Move it to `closed/`. |
95
- | `nav pr open [--target BRANCH]` | Open a PR from the current branch, pinning the exact head and merge base under review. |
96
- | `nav pr review <id> --approve` | Record a verdict bound to a specific revision. |
97
- | `nav pr list --all-refs` | Find PRs on branches you have fetched but not checked out. |
98
- | `nav pr merge <id>` | Merge into the checked-out target, archiving the discussion into its history. |
99
- | `nav doctor [--fix]` | Check the tree against the specification. |
100
-
101
- `--commit` on any mutating command wraps the change in a well-formed
102
- Conventional Commits `docs` commit (`docs(issue): close #bqlybac0`,
103
- `docs(pr): merge #dk3mp2x9`). Without it, changes are left staged for your own
104
- commit.
105
-
106
- ### Query syntax
107
-
108
- ```sh
109
- nav issue list status:closed label:bug assignee:example.com "timeout"
110
- ```
111
-
112
- `status:`, `label:`, `assignee:`, `author:`, `milestone:`, and bare words that
113
- match the title, description or any comment body. Terms AND together; the
114
- default query is `status:open`.
115
-
116
- ## Why the design is what it is
117
-
118
- Three properties drive everything else:
119
-
120
- - **Browsable.** The tracker renders on any forge with no plugin, because it is
121
- just Markdown in human-named directories.
122
- - **Same history as the code.** `git log`, `git blame` and `git bisect` work on
123
- tracker state exactly as they do on code. A release tag captures what the
124
- tracker said at that moment.
125
- - **No coordination.** IDs are 8 random characters, not sequential numbers —
126
- the single most repeated mistake in this problem space. Two people can file
127
- issues offline, on different branches, and never collide.
128
-
129
- Pull requests live on the branch they propose to merge, so opening one needs no
130
- server and works offline. Merging carries the whole discussion into the target
131
- branch's permanent history. Approvals are bound to the exact revision they
132
- judged, so a force-push can never inherit a stale approval.
133
-
134
- ## Platforms
135
-
136
- Developed and tested on Linux and macOS. Windows is not guaranteed; use
137
- [Git Bash](https://gitforwindows.org/) or WSL, where Navbook works because both
138
- provide the POSIX shell the hooks and completions expect.
139
-
140
- ## Documentation
141
-
142
- The [specification](doc/spec/README.md) is the normative definition of the file
143
- format and the reference for anyone writing another implementation. Start with
144
- [01-functionality.md](doc/spec/01-functionality.md) for what Navbook does, or
145
- [02-data-model.md](doc/spec/02-data-model.md) for the exact file format.
146
-
147
- ## Contributing
148
-
149
- Navbook tracks its own development in `.navbook/` — run `nav issue list` in a
150
- clone to see what is open.
151
-
152
- ```sh
153
- npm install
154
- npm test # unit, CLI and conformance suites
155
- npm run check # lint and type-check
156
- npm run bench # the performance budget, on its own machine
157
- ```
158
-
159
- The [conformance fixtures](doc/spec/fixtures/README.md) are golden repositories
160
- that any implementation must pass; they run against `$NAV_BIN`, so the same
161
- suite validates the planned Rust rewrite.
162
-
163
- ## License
164
-
165
- MIT.
@@ -1,9 +0,0 @@
1
- /**
2
- * `nav __complete` — the completion backend the shell scripts call.
3
- *
4
- * Given the words typed so far (without the leading `nav`), it prints one
5
- * candidate per line. Keeping the logic here rather than in three shell
6
- * dialects is what makes ID and slug completion possible at all.
7
- */
8
- import type { Ctx } from "../context.ts";
9
- export declare function cmdComplete(ctx: Ctx, words: string[]): void;
@@ -1,72 +0,0 @@
1
- /**
2
- * `nav __complete` — the completion backend the shell scripts call.
3
- *
4
- * Given the words typed so far (without the leading `nav`), it prints one
5
- * candidate per line. Keeping the logic here rather than in three shell
6
- * dialects is what makes ID and slug completion possible at all.
7
- */
8
- import { allEntities } from "../../core/tree.js";
9
- import { loadRepo } from "../workspace.js";
10
- const ROOT_COMMANDS = ["issue", "pr", "init", "id", "doctor", "install", "uninstall", "help"];
11
- const SHARED_VERBS = ["open", "list", "show", "edit", "comment", "close", "reopen"];
12
- const PR_VERBS = [...SHARED_VERBS, "update", "review", "merge"];
13
- const QUERY_KEYS = ["status:", "label:", "assignee:", "author:", "milestone:"];
14
- export function cmdComplete(ctx, words) {
15
- for (const candidate of completionsFor(ctx, words))
16
- ctx.stdout.write(`${candidate}\n`);
17
- }
18
- function completionsFor(ctx, words) {
19
- const [noun, verb] = words;
20
- if (noun === undefined)
21
- return ROOT_COMMANDS;
22
- if (noun !== "issue" && noun !== "pr") {
23
- return words.length === 1 ? ROOT_COMMANDS : [];
24
- }
25
- const kind = noun === "issue" ? "issue" : "pr";
26
- const verbs = kind === "issue" ? SHARED_VERBS : PR_VERBS;
27
- if (verb === undefined)
28
- return verbs;
29
- if (!verbs.includes(verb))
30
- return [];
31
- if (verb === "list")
32
- return [...QUERY_KEYS, ...labels(ctx)];
33
- if (verb === "open")
34
- return [];
35
- // Every other verb takes an ID as its first argument.
36
- return words.length === 2 ? entityCandidates(ctx, kind) : [];
37
- }
38
- /**
39
- * Bare IDs and full directory names, so a user can complete either the short
40
- * form they would type or the readable name they would recognize.
41
- */
42
- function entityCandidates(ctx, kind) {
43
- try {
44
- const repo = loadRepo(ctx, { includeComments: false });
45
- return allEntities(repo)
46
- .filter((entity) => entity.kind === kind)
47
- .flatMap((entity) => [entity.id, entity.dirName])
48
- .sort();
49
- }
50
- catch {
51
- return [];
52
- }
53
- }
54
- function labels(ctx) {
55
- try {
56
- const repo = loadRepo(ctx, { includeComments: false });
57
- const found = new Set();
58
- for (const entity of allEntities(repo)) {
59
- const values = entity.fm.labels;
60
- if (!Array.isArray(values))
61
- continue;
62
- for (const value of values)
63
- if (typeof value === "string")
64
- found.add(`label:${value}`);
65
- }
66
- return [...found].sort();
67
- }
68
- catch {
69
- return [];
70
- }
71
- }
72
- //# sourceMappingURL=complete.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"complete.js","sourceRoot":"","sources":["../../../src/cli/commands/complete.ts"],"names":[],"mappings":"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"}
@@ -1,27 +0,0 @@
1
- /**
2
- * Producing the text of a new Navbook file, from `-m` or from `$EDITOR`.
3
- *
4
- * Both paths end in the same place: a complete file that has been parsed and
5
- * validated before anything is written into `.navbook/`. The editor buffer is
6
- * the whole file — frontmatter included — so an author can set the title,
7
- * labels and body in one pass, and an abort leaves nothing behind.
8
- */
9
- import { type ParsedFile, type Problem } from "../../core/files.ts";
10
- import type { Ctx } from "../context.ts";
11
- export interface ComposeOptions {
12
- /** Text supplied with `-m`; when absent the editor is opened. */
13
- message?: string;
14
- /** Name of the scratch buffer inside the git directory. */
15
- bufferName: string;
16
- /** Render the complete file from a body. */
17
- render: (body: string) => string;
18
- /** Schema check applied to the finished file. */
19
- validate: (parsed: ParsedFile) => Problem[];
20
- /** Noun used in error messages, e.g. "issue" or "comment". */
21
- noun: string;
22
- }
23
- export interface Composed {
24
- content: string;
25
- parsed: ParsedFile;
26
- }
27
- export declare function composeFile(ctx: Ctx, opts: ComposeOptions): Composed;
@@ -1 +0,0 @@
1
- {"version":3,"file":"compose.js","sourceRoot":"","sources":["../../../src/cli/commands/compose.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAiC,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE/E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAoBpC,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,IAAoB;IACxD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,iBAAiB,CAAC,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,IAAI,MAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,aAAa,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,oBAAoB,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,KAAK,CAAC,IAAoB,EAAE,OAAe;IAClD,IAAI,MAAkB,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,aAAa,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,CACF,OAAO,IAAI,CAAC,IAAI,mCAAmC,EACnD,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAClD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AAC7B,CAAC"}
@@ -1,14 +0,0 @@
1
- /**
2
- * `nav doctor` — spec 04 §4.3.
3
- *
4
- * Doctor enforces the specification, not a house style: hand edits that are
5
- * unusual but valid must pass. Errors (exit 2) are format violations; warnings
6
- * (exit 0) are things worth a look that may be perfectly deliberate.
7
- */
8
- import type { Ctx } from "../context.ts";
9
- export interface DoctorOptions {
10
- staged?: boolean;
11
- fix?: boolean;
12
- json?: boolean;
13
- }
14
- export declare function cmdDoctor(ctx: Ctx, opts: DoctorOptions): void;
@@ -1,127 +0,0 @@
1
- /**
2
- * `nav doctor` — spec 04 §4.3.
3
- *
4
- * Doctor enforces the specification, not a house style: hand edits that are
5
- * unusual but valid must pass. Errors (exit 2) are format violations; warnings
6
- * (exit 0) are things worth a look that may be perfectly deliberate.
7
- */
8
- import { NAVBOOK_ROOT } from "../../core/json.js";
9
- import { parseTree } from "../../core/tree.js";
10
- import { hasErrors, sortDiagnostics, validateRepo } from "../../core/validate.js";
11
- import { git, gitMaybe, splitNul } from "../../git/exec.js";
12
- import { stagedContent, stagedPaths } from "../../git/index-ops.js";
13
- import { NavError } from "../errors.js";
14
- import { runHistoryChecks } from "../history-checks.js";
15
- import { applyOps, loadRepo, repoPath, requireNavbook } from "../workspace.js";
16
- export function cmdDoctor(ctx, opts) {
17
- requireNavbook(ctx);
18
- const repo = opts.staged ? stagedRepo(ctx) : loadRepo(ctx);
19
- const diagnostics = sortDiagnostics([
20
- ...validateRepo(repo, { commitMessages: recentCommitMessages(ctx, opts) }),
21
- // History-dependent checks are skipped for --staged: the commit being made
22
- // does not exist yet, so there is nothing for them to read.
23
- ...(opts.staged ? [] : runHistoryChecks(ctx, repo)),
24
- ]);
25
- const applied = opts.fix ? applyFixes(ctx, diagnostics) : [];
26
- const remaining = opts.fix ? diagnostics.filter((d) => !d.fix) : diagnostics;
27
- if (opts.json) {
28
- for (const diagnostic of remaining) {
29
- ctx.stdout.write(`${JSON.stringify(toJson(diagnostic))}\n`);
30
- }
31
- }
32
- else {
33
- report(ctx, remaining, applied);
34
- }
35
- if (hasErrors(remaining)) {
36
- throw new NavError(`${countErrors(remaining)} format violation(s) found`, { exitCode: 2 });
37
- }
38
- }
39
- function toJson(diagnostic) {
40
- return {
41
- check: diagnostic.check,
42
- level: diagnostic.level,
43
- path: diagnostic.path === "" ? "" : `${NAVBOOK_ROOT}/${diagnostic.path}`,
44
- message: diagnostic.message,
45
- };
46
- }
47
- function report(ctx, diagnostics, applied) {
48
- const c = ctx.colors;
49
- for (const line of applied)
50
- ctx.stdout.write(`${c.green("fixed")} ${line}\n`);
51
- for (const diagnostic of diagnostics) {
52
- const level = diagnostic.level === "error" ? c.red("error") : c.yellow("warning");
53
- const where = diagnostic.path === "" ? "" : `${NAVBOOK_ROOT}/${diagnostic.path}: `;
54
- ctx.stdout.write(`${level} ${c.dim(diagnostic.check)} ${where}${diagnostic.message}\n`);
55
- }
56
- const errors = countErrors(diagnostics);
57
- const warnings = diagnostics.length - errors;
58
- if (errors === 0 && warnings === 0) {
59
- ctx.stdout.write(applied.length > 0 ? "No problems remain.\n" : "No problems found.\n");
60
- return;
61
- }
62
- ctx.stdout.write(`${plural(errors, "error")}, ${plural(warnings, "warning")}\n`);
63
- }
64
- function plural(count, noun) {
65
- return `${count} ${noun}${count === 1 ? "" : "s"}`;
66
- }
67
- function countErrors(diagnostics) {
68
- return diagnostics.filter((d) => d.level === "error").length;
69
- }
70
- /** Apply every mechanical repair a diagnostic offers, reporting each one. */
71
- function applyFixes(ctx, diagnostics) {
72
- const applied = [];
73
- for (const diagnostic of diagnostics) {
74
- if (!diagnostic.fix || diagnostic.fix.length === 0)
75
- continue;
76
- applyOps(ctx, diagnostic.fix);
77
- for (const op of diagnostic.fix)
78
- applied.push(describeFix(op));
79
- }
80
- return applied;
81
- }
82
- function describeFix(op) {
83
- return op.op === "move"
84
- ? `moved ${repoPath(op.from)} to ${repoPath(op.to)}`
85
- : `wrote ${repoPath(op.path)}`;
86
- }
87
- /** Build the repository model from what is staged rather than the working tree. */
88
- function stagedRepo(ctx) {
89
- const prefix = `${NAVBOOK_ROOT}/`;
90
- const paths = allIndexedNavPaths(ctx).filter((path) => path.startsWith(prefix));
91
- const files = new Map();
92
- for (const path of paths) {
93
- const content = stagedContent(ctx.repoRoot, path);
94
- if (content !== null)
95
- files.set(path.slice(prefix.length), content);
96
- }
97
- return parseTree(files);
98
- }
99
- /**
100
- * Every `.navbook/` path in the index. The pre-commit hook needs the whole
101
- * indexed tree, not only the changed paths: checks like ID uniqueness and
102
- * reply-to resolution are properties of the tree the commit will create.
103
- */
104
- function allIndexedNavPaths(ctx) {
105
- const listed = splitNul(git(["ls-files", "--cached", "-z", "--", NAVBOOK_ROOT], { cwd: ctx.repoRoot }));
106
- return listed.length > 0 ? listed : stagedPaths(ctx.repoRoot);
107
- }
108
- /**
109
- * Commit messages scanned for dangling trailers (check D8).
110
- *
111
- * Bounded to recent history: a trailer naming an entity that is not in this
112
- * tree is worth knowing about while the work is current, but the whole history
113
- * of a long-lived repository would produce standing noise for entities that
114
- * were legitimately archived or that live on a branch nobody has fetched.
115
- */
116
- const TRAILER_SCAN_DEPTH = 100;
117
- function recentCommitMessages(ctx, opts) {
118
- if (opts.staged)
119
- return [];
120
- const output = gitMaybe(["log", "--format=%B%x00", "-n", String(TRAILER_SCAN_DEPTH)], {
121
- cwd: ctx.repoRoot,
122
- });
123
- if (output === null)
124
- return [];
125
- return output.split("\0").filter((message) => message.trim() !== "");
126
- }
127
- //# sourceMappingURL=doctor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -1,55 +0,0 @@
1
- /**
2
- * The verbs issues and pull requests share — spec 04 §4.3.
3
- *
4
- * One implementation serves both nouns; the entity kind only selects which
5
- * collection is searched, which file name is edited, and which words appear in
6
- * the report.
7
- */
8
- import { type NewCommentInput } from "../../core/files.ts";
9
- import { type CloseInput, type Plan } from "../../core/ops.ts";
10
- import { type Query } from "../../core/query.ts";
11
- import type { EntityKind, EntityRecord, Repo } from "../../core/tree.ts";
12
- import type { Ctx } from "../context.ts";
13
- export interface GlobalFlags {
14
- json?: boolean;
15
- commit?: boolean;
16
- }
17
- /** Author string for the current git identity. */
18
- export declare function currentAuthor(ctx: Ctx): string;
19
- /** Entities of one kind from a parsed repository. */
20
- export declare function selectEntities(repo: Repo, kind: EntityKind): EntityRecord[];
21
- /** Newest first, with a stable tie-break on ID. */
22
- export declare function sortEntities(entities: readonly EntityRecord[]): EntityRecord[];
23
- export interface ExtraColumn {
24
- header: string;
25
- value: (entity: EntityRecord) => string;
26
- }
27
- export interface ListOptions extends GlobalFlags {
28
- /** Columns appended by PR-specific listings. */
29
- extraColumns?: ExtraColumn[];
30
- /** Pre-collected entities, used by `nav pr list --all-refs`. */
31
- entities?: EntityRecord[];
32
- /** Extra JSON keys per entity, keyed by entity identity. */
33
- jsonExtra?: (entity: EntityRecord) => Record<string, unknown>;
34
- }
35
- export declare function cmdList(ctx: Ctx, kind: EntityKind, terms: string[], opts: ListOptions): void;
36
- /** The query a listing will run, for callers that need it before loading. */
37
- export declare function parseListQuery(terms: string[], kind: EntityKind): Query;
38
- export declare function cmdShow(ctx: Ctx, kind: EntityKind, prefix: string, opts: GlobalFlags): void;
39
- export declare function cmdEdit(ctx: Ctx, kind: EntityKind, prefix: string, opts: GlobalFlags): void;
40
- export interface CommentOptions extends GlobalFlags {
41
- message?: string;
42
- replyTo?: string;
43
- /** Review fields, supplied by `nav pr review`. */
44
- review?: Pick<NewCommentInput, "verdict" | "revision" | "file" | "line">;
45
- }
46
- export declare function cmdComment(ctx: Ctx, kind: EntityKind, prefix: string, opts: CommentOptions): void;
47
- export interface CloseOptions extends GlobalFlags, CloseInput {
48
- }
49
- export declare function cmdClose(ctx: Ctx, kind: EntityKind, prefix: string, opts: CloseOptions): void;
50
- export declare function cmdReopen(ctx: Ctx, kind: EntityKind, prefix: string, opts: GlobalFlags): void;
51
- /**
52
- * Build a plan that rewrites an entity file, turning a malformed-frontmatter
53
- * failure into an operational error that names the file and the way out.
54
- */
55
- export declare function rewritePlan(entity: EntityRecord, build: () => Plan): Plan;