@nickmeriano/task 0.8.0 → 0.9.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 (114) hide show
  1. package/README.md +65 -22
  2. package/dist/asks.test.d.ts +17 -0
  3. package/dist/asks.test.d.ts.map +1 -0
  4. package/dist/asks.test.js +278 -0
  5. package/dist/asks.test.js.map +1 -0
  6. package/dist/check.d.ts +3 -2
  7. package/dist/check.d.ts.map +1 -1
  8. package/dist/check.js +99 -60
  9. package/dist/check.js.map +1 -1
  10. package/dist/check.test.js +99 -60
  11. package/dist/check.test.js.map +1 -1
  12. package/dist/claim-io.d.ts +73 -0
  13. package/dist/claim-io.d.ts.map +1 -0
  14. package/dist/claim-io.js +344 -0
  15. package/dist/claim-io.js.map +1 -0
  16. package/dist/claim.d.ts +21 -22
  17. package/dist/claim.d.ts.map +1 -1
  18. package/dist/claim.js +58 -83
  19. package/dist/claim.js.map +1 -1
  20. package/dist/claim.test.d.ts +2 -2
  21. package/dist/claim.test.js +111 -94
  22. package/dist/claim.test.js.map +1 -1
  23. package/dist/cli.js +241 -64
  24. package/dist/cli.js.map +1 -1
  25. package/dist/file-store.d.ts +70 -24
  26. package/dist/file-store.d.ts.map +1 -1
  27. package/dist/file-store.js +319 -141
  28. package/dist/file-store.js.map +1 -1
  29. package/dist/git-serve.d.ts +183 -0
  30. package/dist/git-serve.d.ts.map +1 -0
  31. package/dist/git-serve.js +503 -0
  32. package/dist/git-serve.js.map +1 -0
  33. package/dist/git-serve.test.d.ts +16 -0
  34. package/dist/git-serve.test.d.ts.map +1 -0
  35. package/dist/git-serve.test.js +183 -0
  36. package/dist/git-serve.test.js.map +1 -0
  37. package/dist/git.d.ts +65 -0
  38. package/dist/git.d.ts.map +1 -0
  39. package/dist/git.js +114 -0
  40. package/dist/git.js.map +1 -0
  41. package/dist/id.d.ts +39 -0
  42. package/dist/id.d.ts.map +1 -0
  43. package/dist/id.js +67 -0
  44. package/dist/id.js.map +1 -0
  45. package/dist/inbox.d.ts +41 -0
  46. package/dist/inbox.d.ts.map +1 -0
  47. package/dist/inbox.js +56 -0
  48. package/dist/inbox.js.map +1 -0
  49. package/dist/overview.d.ts +9 -0
  50. package/dist/overview.d.ts.map +1 -1
  51. package/dist/overview.js +19 -11
  52. package/dist/overview.js.map +1 -1
  53. package/dist/overview.test.js +6 -5
  54. package/dist/overview.test.js.map +1 -1
  55. package/dist/promote.test.d.ts +3 -2
  56. package/dist/promote.test.d.ts.map +1 -1
  57. package/dist/promote.test.js +29 -31
  58. package/dist/promote.test.js.map +1 -1
  59. package/dist/publish.d.ts +2 -17
  60. package/dist/publish.d.ts.map +1 -1
  61. package/dist/publish.js +4 -49
  62. package/dist/publish.js.map +1 -1
  63. package/dist/search.d.ts +3 -1
  64. package/dist/search.d.ts.map +1 -1
  65. package/dist/search.js +15 -2
  66. package/dist/search.js.map +1 -1
  67. package/dist/search.test.js +9 -9
  68. package/dist/search.test.js.map +1 -1
  69. package/dist/server.d.ts.map +1 -1
  70. package/dist/server.js +218 -21
  71. package/dist/server.js.map +1 -1
  72. package/dist/store.d.ts +28 -14
  73. package/dist/store.d.ts.map +1 -1
  74. package/dist/store.js.map +1 -1
  75. package/dist/store.test.js +88 -75
  76. package/dist/store.test.js.map +1 -1
  77. package/dist/ticket-doc.d.ts +26 -10
  78. package/dist/ticket-doc.d.ts.map +1 -1
  79. package/dist/ticket-doc.js +71 -27
  80. package/dist/ticket-doc.js.map +1 -1
  81. package/dist/types.d.ts +51 -17
  82. package/dist/types.d.ts.map +1 -1
  83. package/dist/types.js.map +1 -1
  84. package/package.json +1 -1
  85. package/skill/SKILL.md +70 -23
  86. package/src/asks.test.ts +355 -0
  87. package/src/check.test.ts +129 -72
  88. package/src/check.ts +101 -58
  89. package/src/claim-io.ts +401 -0
  90. package/src/claim.test.ts +141 -99
  91. package/src/claim.ts +69 -96
  92. package/src/cli.ts +251 -63
  93. package/src/file-store.ts +357 -145
  94. package/src/git-serve.test.ts +240 -0
  95. package/src/git-serve.ts +595 -0
  96. package/src/git.ts +141 -0
  97. package/src/id.ts +68 -0
  98. package/src/inbox.ts +77 -0
  99. package/src/overview.test.ts +6 -5
  100. package/src/overview.ts +25 -10
  101. package/src/promote.test.ts +40 -28
  102. package/src/publish.ts +6 -53
  103. package/src/search.test.ts +11 -11
  104. package/src/search.ts +17 -3
  105. package/src/server.ts +221 -19
  106. package/src/store.test.ts +95 -77
  107. package/src/store.ts +28 -13
  108. package/src/ticket-doc.ts +93 -30
  109. package/src/types.ts +52 -17
  110. package/ui/dist/assets/index-BjsorZOU.js +229 -0
  111. package/ui/dist/assets/index-CoKCUYic.css +1 -0
  112. package/ui/dist/index.html +2 -2
  113. package/ui/dist/assets/index-BJmOsOdR.js +0 -229
  114. package/ui/dist/assets/index-BoqQlqSU.css +0 -1
package/dist/check.js CHANGED
@@ -10,8 +10,9 @@
10
10
  * references (one branch deleted a ticket another branch linked to), `goal:`
11
11
  * refs naming a goal that doesn't exist, tickets duplicated between the board
12
12
  * and the archive, unknown frontmatter keys, and formatting drift from the
13
- * canonical serialization (including the pre-0.8 `milestone:` key, whose
14
- * rewrite to `goal:` is the migration).
13
+ * canonical serialization. Retired pre-0.8 spellings (`milestone:`,
14
+ * `claimPrefix`) are refused by the parsers with the rename in the error —
15
+ * this lint just surfaces those messages; there is no migration machinery.
15
16
  *
16
17
  * The mechanical repairs — pruning dangling or self references, deduping and
17
18
  * sorting `blocked_by`, rewriting a file into canonical form — are applied by
@@ -21,10 +22,11 @@
21
22
  */
22
23
  import { existsSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
23
24
  import { join } from "node:path";
24
- import { ARCHIVE_DIR, COMMENTS_DIR, GOALS_ARCHIVE_DIR, GOALS_DIR, TICKETS_DIR, TICKET_FILE, } from "./file-store.js";
25
- import { COMMENT_FIELDS, TicketParseError, frontmatterKeys, isGoalSlug, parseComment, parseGoal, parseTicket, serializeComment, serializeGoal, serializeTicket, } from "./ticket-doc.js";
25
+ import { ARCHIVE_DIR, ASKS_DIR, COMMENTS_DIR, GOALS_ARCHIVE_DIR, GOALS_DIR, TICKETS_DIR, TICKET_FILE, } from "./file-store.js";
26
+ import { ASK_FIELDS, COMMENT_FIELDS, TicketParseError, frontmatterKeys, isGoalSlug, parseAsk, parseComment, parseGoal, parseTicket, serializeAsk, serializeComment, serializeGoal, serializeTicket, } from "./ticket-doc.js";
26
27
  import { CONFIG_FILE, TASK_DIR, boardConfig, findBoards, findRoot, findScopeRoot, } from "./store.js";
27
28
  import { claimNamespace } from "./claim.js";
29
+ import { isTicketKey } from "./id.js";
28
30
  /** The boards `task check` covers from `cwd` — the same set `task serve` has. */
29
31
  export function checkRoot(cwd) {
30
32
  return findRoot(cwd) ?? cwd;
@@ -66,14 +68,16 @@ export function checkBoards(root, fix) {
66
68
  return { boards: boards.length, files, issues, fixed };
67
69
  }
68
70
  /**
69
- * Config lints (TAS-27): the pre-0.8 `claimPrefix` spelling (fixable — the
70
- * migration to `claims.branchPrefix` is mechanical), a `boards` list on a
71
- * non-root board (root-only by design, so vendored boards can't opt into a
72
- * repo's automation), a malformed one, an unusable branch prefix, and a
73
- * branch prefix that disagrees with the root board's (workflows match claim
74
- * branches by patternone repo, one namespace).
71
+ * Config lints (TAS-27): a `boards` list on a non-root board (root-only by
72
+ * design, so vendored boards can't opt into a repo's automation), a malformed
73
+ * one, an unusable branch prefix, a branch prefix that disagrees with the
74
+ * root board's (workflows match claim branches by pattern one repo, one
75
+ * namespace), and a leftover pre-0.8 `claimPrefix` key. The retired spelling
76
+ * is not migrated anymore (TAS-41: no compat) with no `claims.branchPrefix`
77
+ * beside it, `claimNamespace` refuses by name and that error surfaces here;
78
+ * with one, the stray key is inert and gets its own line.
75
79
  */
76
- function checkConfig(board, scopeRoot, rootBranchPrefix, fix, push, fixed) {
80
+ function checkConfig(board, scopeRoot, rootBranchPrefix, push) {
77
81
  const absolute = join(board.root, TASK_DIR, CONFIG_FILE);
78
82
  const file = posixJoin(board.id, TASK_DIR, CONFIG_FILE);
79
83
  let raw;
@@ -85,29 +89,8 @@ function checkConfig(board, scopeRoot, rootBranchPrefix, fix, push, fixed) {
85
89
  return null;
86
90
  }
87
91
  const config = raw;
88
- if (raw.claimPrefix !== undefined) {
89
- push(file, "`claimPrefix` is now `claims.branchPrefix` `task check --fix` rewrites it", true);
90
- if (fix) {
91
- // In-place key replacement so the migration diff is one line where
92
- // possible; an existing claims.branchPrefix wins over the legacy key.
93
- const claims = {
94
- ...(typeof raw.claims === "object" && raw.claims !== null
95
- ? raw.claims
96
- : {}),
97
- };
98
- claims.branchPrefix ??= raw.claimPrefix;
99
- const migrated = {};
100
- for (const [key, value] of Object.entries(raw)) {
101
- if (key === "claimPrefix") {
102
- if (raw.claims === undefined)
103
- migrated.claims = claims;
104
- continue;
105
- }
106
- migrated[key] = key === "claims" ? claims : value;
107
- }
108
- writeFileSync(absolute, `${JSON.stringify(migrated, null, 2)}\n`);
109
- fixed.push(file);
110
- }
92
+ if (raw.claimPrefix !== undefined && config.claims?.branchPrefix !== undefined) {
93
+ push(file, "`claimPrefix` is the pre-0.8 spelling and is no longer read — `claims.branchPrefix` wins; delete the leftover key");
111
94
  }
112
95
  if (raw.boards !== undefined) {
113
96
  if (board.root !== scopeRoot) {
@@ -138,9 +121,9 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
138
121
  const taskDir = join(board.root, TASK_DIR);
139
122
  const relTaskDir = posixJoin(board.id, TASK_DIR);
140
123
  const push = (file, message, fixable = false) => issues.push({ board: board.id, file, message, fixable });
141
- const config = checkConfig(board, scopeRoot, rootBranchPrefix, fix, push, fixed);
124
+ const config = checkConfig(board, scopeRoot, rootBranchPrefix, push);
142
125
  const prefix = config?.prefix ?? "TASK";
143
- const displayId = (n) => `${prefix}-${n}`;
126
+ const displayId = (k) => `${prefix}-${k}`;
144
127
  // ── Collect every ticket, live and archived ────────────────────────────────
145
128
  const tickets = [];
146
129
  let files = 0;
@@ -155,8 +138,18 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
155
138
  if (entry.name.startsWith("."))
156
139
  continue;
157
140
  const relEntry = posixJoin(relTaskDir, dir, entry.name);
158
- if (!entry.isDirectory() || !/^\d+$/.test(entry.name)) {
159
- push(relEntry, "unexpected entry the board only reads numeric ticket directories");
141
+ // A purely numeric directory is a pre-TAS-42 ticket — the old
142
+ // sequential-id format, which nothing reads anymore. The likely way one
143
+ // appears post-migration is merging a branch cut before the cutover;
144
+ // the fix is mechanical and named here.
145
+ if (entry.isDirectory() && /^\d+$/.test(entry.name)) {
146
+ push(relEntry, "numeric ticket directory — the pre-TAS-42 sequential-id format, which is no longer read; migrate it with `node tools/migrate-ids/migrate.mjs --ticket <board-dir> " +
147
+ entry.name +
148
+ "`");
149
+ continue;
150
+ }
151
+ if (!entry.isDirectory() || !isTicketKey(entry.name)) {
152
+ push(relEntry, "unexpected entry — ticket directories are named by their key (e.g. x7k4m)");
160
153
  continue;
161
154
  }
162
155
  const absolute = join(home, entry.name, TICKET_FILE);
@@ -176,17 +169,19 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
176
169
  throw error;
177
170
  push(file, reason(error, file));
178
171
  }
179
- tickets.push({ number: Number(entry.name), file, absolute, archived, text, doc });
172
+ tickets.push({ key: entry.name, file, absolute, archived, text, doc });
180
173
  }
181
174
  }
182
175
  // A ticket present in both tickets/ and archive/ is a merge artifact: one
183
176
  // branch archived it while another kept editing it. Which copy wins is a
184
- // human call, so it's reported, never auto-fixed.
185
- const live = new Set(tickets.filter((t) => !t.archived).map((t) => t.number));
186
- const valid = new Set(tickets.map((t) => t.number));
177
+ // human call, so it's reported, never auto-fixed. (This doubles as the
178
+ // duplicate-key lint: within either directory git itself makes duplicates
179
+ // impossible, so board-and-archive is the only place one can exist.)
180
+ const live = new Set(tickets.filter((t) => !t.archived).map((t) => t.key));
181
+ const valid = new Set(tickets.map((t) => t.key));
187
182
  for (const ticket of tickets) {
188
- if (ticket.archived && live.has(ticket.number)) {
189
- push(ticket.file, `${displayId(ticket.number)} also exists in ${TICKETS_DIR}/ — a merge kept both copies; delete one`);
183
+ if (ticket.archived && live.has(ticket.key)) {
184
+ push(ticket.file, `${displayId(ticket.key)} also exists in ${TICKETS_DIR}/ — a merge kept both copies; delete one`);
190
185
  }
191
186
  }
192
187
  // ── Goals ──────────────────────────────────────────────────────────────────
@@ -256,7 +251,7 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
256
251
  }
257
252
  // ── Per-ticket content checks ──────────────────────────────────────────────
258
253
  for (const ticket of tickets) {
259
- const { doc, file, number } = ticket;
254
+ const { doc, file, key } = ticket;
260
255
  if (!doc)
261
256
  continue;
262
257
  for (const [key, at] of [
@@ -282,32 +277,27 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
282
277
  // The repaired relation list: no self references, no dangling targets, no
283
278
  // duplicates, sorted. Each divergence is its own issue; all are mechanical.
284
279
  const pruned = [...new Set(doc.blockedBy)]
285
- .filter((n) => n !== number && valid.has(n))
286
- .sort((a, b) => a - b);
287
- if (doc.blockedBy.includes(number)) {
288
- push(file, `${displayId(number)} is blocked by itself`, true);
280
+ .filter((k) => k !== key && valid.has(k))
281
+ .sort((a, b) => a.localeCompare(b));
282
+ if (doc.blockedBy.includes(key)) {
283
+ push(file, `${displayId(key)} is blocked by itself`, true);
289
284
  }
290
285
  for (const target of new Set(doc.blockedBy)) {
291
- if (target !== number && !valid.has(target)) {
286
+ if (target !== key && !valid.has(target)) {
292
287
  push(file, `blocked_by references ${displayId(target)}, which doesn't exist`, true);
293
288
  }
294
289
  }
295
290
  // Everything else — duplicate or unsorted blocked_by, hand-edited field
296
291
  // order or quoting, stray whitespace — is formatting drift: the parse is
297
292
  // fine, the bytes just aren't what the CLI would write. `normalized` keeps
298
- // the dangling refs so drift isn't double-reported on top of them.
299
- //
300
- // One drift gets its own words: a pre-0.8 `milestone:` key. It already
301
- // parses as the goal, and the canonical rewrite is the whole migration —
302
- // but "not in canonical form" would undersell what the fix is about to do.
293
+ // the dangling refs so drift isn't double-reported on top of them. (The
294
+ // pre-0.8 `milestone:` key never reaches here — the strict parse refuses
295
+ // it by name, and that error is the whole report.)
303
296
  const normalized = serializeTicket({
304
297
  ...doc,
305
- blockedBy: [...new Set(doc.blockedBy)].sort((a, b) => a - b),
298
+ blockedBy: [...new Set(doc.blockedBy)].sort((a, b) => a.localeCompare(b)),
306
299
  });
307
- if (frontmatterKeys(ticket.text)?.includes("milestone")) {
308
- push(file, "`milestone:` is now `goal:` — `task check --fix` rewrites it", true);
309
- }
310
- else if (normalized !== ticket.text) {
300
+ if (normalized !== ticket.text) {
311
301
  push(file, "not in canonical form — `task check --fix` rewrites it", true);
312
302
  }
313
303
  const canonical = serializeTicket({ ...doc, blockedBy: pruned });
@@ -316,6 +306,55 @@ function checkBoard(board, scopeRoot, rootBranchPrefix, fix, issues, fixed) {
316
306
  fixed.push(file);
317
307
  }
318
308
  }
309
+ // ── Asks ───────────────────────────────────────────────────────────────────
310
+ // Same pass as comments: strict parse, timestamps, unknown keys, canonical
311
+ // drift. An empty ask body gets its own line — an ask that doesn't say what's
312
+ // owed is the old boolean wearing a new file.
313
+ const knownAskKeys = new Set(ASK_FIELDS);
314
+ for (const ticket of tickets) {
315
+ const dir = join(ticket.absolute, "..", ASKS_DIR);
316
+ if (!existsSync(dir))
317
+ continue;
318
+ for (const entry of readdirSync(dir)) {
319
+ if (!entry.endsWith(".md") || entry.startsWith("."))
320
+ continue;
321
+ files++;
322
+ const file = posixJoin(ticket.file.slice(0, -TICKET_FILE.length - 1), ASKS_DIR, entry);
323
+ const text = readFileSync(join(dir, entry), "utf8");
324
+ let parsed;
325
+ try {
326
+ parsed = parseAsk(text, file);
327
+ }
328
+ catch (error) {
329
+ if (!(error instanceof TicketParseError))
330
+ throw error;
331
+ push(file, reason(error, file));
332
+ continue;
333
+ }
334
+ if (!isValidTimestamp(parsed.createdAt))
335
+ push(file, "created is not a valid timestamp");
336
+ if (parsed.resolvedAt !== null && !isValidTimestamp(parsed.resolvedAt)) {
337
+ push(file, "resolved is not a valid timestamp");
338
+ }
339
+ if (!parsed.body.trim())
340
+ push(file, "empty ask — say what a person owes, or delete it");
341
+ let unknownKeys = false;
342
+ for (const key of frontmatterKeys(text) ?? []) {
343
+ if (knownAskKeys.has(key))
344
+ continue;
345
+ unknownKeys = true;
346
+ push(file, `unknown frontmatter key "${key}"`);
347
+ }
348
+ const canonical = serializeAsk(parsed);
349
+ if (canonical !== text && !unknownKeys) {
350
+ push(file, "not in canonical form — `task check --fix` rewrites it", true);
351
+ if (fix) {
352
+ writeFileSync(join(dir, entry), canonical);
353
+ fixed.push(file);
354
+ }
355
+ }
356
+ }
357
+ }
319
358
  // ── Comments ───────────────────────────────────────────────────────────────
320
359
  const knownCommentKeys = new Set(COMMENT_FIELDS);
321
360
  for (const ticket of tickets) {
package/dist/check.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
@@ -24,45 +24,71 @@ test("a board the CLI wrote is clean", () => {
24
24
  store.createGoal({ title: "Ship it", description: "the why" });
25
25
  const a = store.create({ title: "First", description: "with a body", goal: "ship-it" });
26
26
  const b = store.create({ title: "Second", status: "backlog", tags: ["x"] });
27
- store.link(b.number, "blocked_by", a.number);
28
- store.addComment(a.number, "hello", "claude");
29
- store.update(a.number, { status: "done" });
30
- store.archive(a.number);
27
+ store.link(b.key, "blocked_by", a.key);
28
+ store.addComment(a.key, "hello", "claude");
29
+ store.update(a.key, { status: "done" });
30
+ store.archive(a.key);
31
31
  const result = checkBoards(root, false);
32
32
  assert.deepEqual(result.issues, []);
33
33
  assert.equal(result.boards, 1);
34
34
  assert.equal(result.files, 4); // two tickets + one comment + one goal
35
35
  });
36
+ test("ask files are linted like comments; the retired flag reads as an unknown key", () => {
37
+ const root = tempRoot();
38
+ const store = initProject(root, { name: "owed", prefix: "OWE" });
39
+ const t = store.create({ title: "Owes things", status: "in_progress" });
40
+ store.addAsk(t.key, "Mint the token", "claude");
41
+ assert.deepEqual(checkBoards(root, false).issues, [], "a CLI-written ask is clean");
42
+ const asksDir = join(root, ".task", "tickets", t.key, "asks");
43
+ // Hand-edit shapes: an ask that says nothing, a resolution that isn't a
44
+ // timestamp, a key nothing reads, and mere drift (unquoted author).
45
+ writeFileSync(join(asksDir, "z-empty.md"), '---\nauthor: "x"\ncreated: 2026-08-27T00:00:00.000Z\n---\n\n\n');
46
+ writeFileSync(join(asksDir, "z-bad.md"), '---\nauthor: "x"\ncreated: 2026-08-27T00:00:00.000Z\nresolved: yesterday-ish\nurgency: high\n---\n\nDo the thing\n');
47
+ const found = checkBoards(root, false);
48
+ const messages = found.issues.map((issue) => issue.message);
49
+ assert.ok(messages.some((m) => /empty ask/.test(m)), "empty ask reported");
50
+ assert.ok(messages.some((m) => /resolved is not a valid timestamp/.test(m)), "bad resolution reported");
51
+ assert.ok(messages.some((m) => /unknown frontmatter key "urgency"/.test(m)), "unknown key reported");
52
+ // The retired pre-0.8 boolean isn't a field anymore — a file still carrying
53
+ // it (deep history, an ancient branch) reads as an unknown key: flagged,
54
+ // preserved through rewrites, never interpreted.
55
+ const ticketPath = join(root, ".task", "tickets", t.key, "ticket.md");
56
+ writeFileSync(ticketPath, readFileSync(ticketPath, "utf8").replace("status: in_progress", "status: in_progress\nneeds_human: true"));
57
+ const flagged = checkBoards(root, true);
58
+ const unknown = flagged.issues.find((issue) => /unknown frontmatter key "needs_human"/.test(issue.message));
59
+ assert.ok(unknown, "retired key flagged as unknown");
60
+ assert.match(readFileSync(ticketPath, "utf8"), /needs_human: true/);
61
+ });
36
62
  test("finds what merges and hand-edits leave behind, and --fix repairs the mechanical part", () => {
37
63
  const root = tempRoot();
38
64
  const store = initProject(root, { name: "rough", prefix: "RGH" });
39
65
  const a = store.create({ title: "Kept", status: "todo" });
40
66
  const b = store.create({ title: "Points at a ghost", status: "todo" });
41
- store.create({ title: "Broken later", status: "todo" });
67
+ const c = store.create({ title: "Broken later", status: "todo" });
42
68
  // A dangling reference: link b to a ticket, then lose the ticket the way a
43
69
  // merge would — the directory vanishes without the store's delete cascade.
44
- store.link(b.number, "blocked_by", a.number);
45
- const ticketPath = (n) => join(root, ".task", "tickets", String(n), "ticket.md");
46
- const bText = readFileSync(ticketPath(b.number), "utf8");
47
- writeFileSync(ticketPath(b.number), bText.replace("blocked_by: [1]", "blocked_by: [1, 99, 99]"));
70
+ store.link(b.key, "blocked_by", a.key);
71
+ const ticketPath = (key) => join(root, ".task", "tickets", key, "ticket.md");
72
+ const bText = readFileSync(ticketPath(b.key), "utf8");
73
+ writeFileSync(ticketPath(b.key), bText.replace(`blocked_by: ["${a.key}"]`, `blocked_by: ["${a.key}", "zz9zz", "zz9zz"]`));
48
74
  // A hand-edit that still parses but isn't canonical (bare goal string).
49
75
  store.createGoal({ title: "Launch" });
50
- const cText = readFileSync(ticketPath(3), "utf8");
51
- writeFileSync(ticketPath(3), cText.replace("status: todo", "status: todo\ngoal: launch"));
52
- // A file that doesn't parse at all.
53
- mkdirSync(join(root, ".task", "tickets", "4"));
54
- writeFileSync(ticketPath(4), "---\nstatus: todoo\nposition: 0\ncreated: x\nupdated: x\n---\n\n# Bad status\n");
76
+ const cText = readFileSync(ticketPath(c.key), "utf8");
77
+ writeFileSync(ticketPath(c.key), cText.replace("status: todo", "status: todo\ngoal: launch"));
78
+ // A file that doesn't parse at all, in a well-formed key directory.
79
+ mkdirSync(join(root, ".task", "tickets", "zzz9x"));
80
+ writeFileSync(ticketPath("zzz9x"), "---\nstatus: todoo\nposition: 0\ncreated: x\nupdated: x\n---\n\n# Bad status\n");
55
81
  const found = checkBoards(root, false);
56
82
  const messages = found.issues.map((issue) => issue.message);
57
- assert.ok(messages.some((m) => /RGH-99, which doesn't exist/.test(m)), "dangling ref reported");
83
+ assert.ok(messages.some((m) => /RGH-zz9zz, which doesn't exist/.test(m)), "dangling ref reported");
58
84
  assert.ok(messages.some((m) => /not in canonical form/.test(m)), "drift reported");
59
85
  assert.ok(messages.some((m) => /invalid status "todoo"/.test(m)), "parse error reported");
60
86
  assert.ok(messages.some((m) => /not a valid timestamp/.test(m)) === false, "unparseable file isn't double-reported");
61
87
  const fixed = checkBoards(root, true);
62
88
  assert.ok(fixed.fixed.length >= 2, "fix rewrote the repairable files");
63
89
  // The dangling ref is pruned, the real one kept; the drift is normalized.
64
- assert.match(readFileSync(ticketPath(b.number), "utf8"), /blocked_by: \[1\]\n/);
65
- assert.match(readFileSync(ticketPath(3), "utf8"), /goal: "launch"/);
90
+ assert.ok(readFileSync(ticketPath(b.key), "utf8").includes(`blocked_by: ["${a.key}"]\n`));
91
+ assert.match(readFileSync(ticketPath(c.key), "utf8"), /goal: "launch"/);
66
92
  // What remains is exactly what needs a human: the unparseable file.
67
93
  const after = checkBoards(root, false);
68
94
  assert.deepEqual(after.issues.filter((issue) => issue.fixable), []);
@@ -73,11 +99,11 @@ test("merge artifacts across the archive are reported, never auto-fixed", () =>
73
99
  const root = tempRoot();
74
100
  const store = initProject(root, { name: "dup", prefix: "DUP" });
75
101
  const t = store.create({ title: "Archived on one branch" });
76
- store.update(t.number, { status: "done" });
77
- store.archive(t.number);
102
+ store.update(t.key, { status: "done" });
103
+ store.archive(t.key);
78
104
  // The other branch kept editing it — the merge keeps both directories.
79
- mkdirSync(join(root, ".task", "tickets", String(t.number)), { recursive: true });
80
- writeFileSync(join(root, ".task", "tickets", String(t.number), "ticket.md"), readFileSync(join(root, ".task", "archive", String(t.number), "ticket.md")));
105
+ mkdirSync(join(root, ".task", "tickets", t.key), { recursive: true });
106
+ writeFileSync(join(root, ".task", "tickets", t.key, "ticket.md"), readFileSync(join(root, ".task", "archive", t.key, "ticket.md")));
81
107
  const result = checkBoards(root, true);
82
108
  assert.ok(result.issues.some((issue) => /also exists in tickets\//.test(issue.message)));
83
109
  assert.deepEqual(result.fixed, []);
@@ -86,8 +112,8 @@ test("a ticket parked in the archive while still open is flagged", () => {
86
112
  const root = tempRoot();
87
113
  const store = initProject(root, { name: "arc", prefix: "ARC" });
88
114
  const t = store.create({ title: "Half archived", status: "todo" });
89
- renameSync(join(root, ".task", "tickets", String(t.number)), (mkdirSync(join(root, ".task", "archive"), { recursive: true }),
90
- join(root, ".task", "archive", String(t.number))));
115
+ renameSync(join(root, ".task", "tickets", t.key), (mkdirSync(join(root, ".task", "archive"), { recursive: true }),
116
+ join(root, ".task", "archive", t.key)));
91
117
  const result = checkBoards(root, false);
92
118
  assert.ok(result.issues.some((issue) => /archived but still todo/.test(issue.message)));
93
119
  });
@@ -95,12 +121,12 @@ test("unknown frontmatter keys are reported — and survive a rewrite round-trip
95
121
  const root = tempRoot();
96
122
  const store = initProject(root, { name: "extra", prefix: "EXT" });
97
123
  const t = store.create({ title: "Carries a custom field", status: "todo" });
98
- const path = join(root, ".task", "tickets", String(t.number), "ticket.md");
124
+ const path = join(root, ".task", "tickets", t.key, "ticket.md");
99
125
  writeFileSync(path, readFileSync(path, "utf8").replace("status: todo", 'status: todo\nowner: "nick"'));
100
126
  const result = checkBoards(root, false);
101
127
  assert.ok(result.issues.some((issue) => /unknown frontmatter key "owner"/.test(issue.message)));
102
128
  // The sharp edge this fixed: an ordinary update used to drop the key.
103
- store.update(t.number, { title: "Renamed" });
129
+ store.update(t.key, { title: "Renamed" });
104
130
  const text = readFileSync(path, "utf8");
105
131
  assert.match(text, /owner: "nick"/);
106
132
  assert.match(text, /# Renamed/);
@@ -112,23 +138,23 @@ test("unknown frontmatter keys are reported — and survive a rewrite round-trip
112
138
  'unknown frontmatter key "owner" — preserved on rewrite, but nothing reads it',
113
139
  ]);
114
140
  });
115
- test("the pre-0.8 milestone key is flagged by name, and --fix is the migration", () => {
141
+ test("the pre-0.8 milestone key is refused by name no migration machinery", () => {
116
142
  const root = tempRoot();
117
143
  const store = initProject(root, { name: "old", prefix: "OLD" });
118
144
  const t = store.create({ title: "From an old board", status: "todo" });
119
- const path = join(root, ".task", "tickets", String(t.number), "ticket.md");
145
+ const path = join(root, ".task", "tickets", t.key, "ticket.md");
120
146
  writeFileSync(path, readFileSync(path, "utf8").replace("status: todo", 'status: todo\nmilestone: "launch"'));
121
- const found = checkBoards(root, false);
122
- const migration = found.issues.find((issue) => /`milestone:` is now `goal:`/.test(issue.message));
123
- assert.ok(migration?.fixable, "migration flagged as fixable");
124
- // The old key parses as the goal, so the ref lint also fires until the goal
125
- // file exists stated with both ways out, never auto-pruned.
126
- assert.ok(found.issues.some((issue) => /goal "launch" doesn't exist/.test(issue.message) && !issue.fixable));
147
+ // The strict parse refuses the retired spelling with the rename in the
148
+ // error; check surfaces exactly that, unfixable, and --fix leaves the file
149
+ // alone renaming the key is the human's one edit.
150
+ const found = checkBoards(root, true);
151
+ const refusal = found.issues.find((issue) => /`milestone:` is the pre-0\.8 spelling.*rename the key to `goal:`/.test(issue.message));
152
+ assert.ok(refusal, "retired spelling refused by name");
153
+ assert.equal(refusal.fixable, false);
154
+ assert.match(readFileSync(path, "utf8"), /milestone: "launch"/);
155
+ writeFileSync(path, readFileSync(path, "utf8").replace('milestone: "launch"', 'goal: "launch"'));
127
156
  store.createGoal({ title: "Launch" });
128
157
  checkBoards(root, true);
129
- const text = readFileSync(path, "utf8");
130
- assert.match(text, /goal: "launch"/);
131
- assert.doesNotMatch(text, /milestone/);
132
158
  assert.deepEqual(checkBoards(root, false).issues, []);
133
159
  });
134
160
  test("goal files are linted, and drift in them is fixable", () => {
@@ -150,14 +176,14 @@ test("comment files are linted too", () => {
150
176
  const root = tempRoot();
151
177
  const store = initProject(root, { name: "com", prefix: "COM" });
152
178
  const t = store.create({ title: "Talked about" });
153
- store.addComment(t.number, "fine", "claude");
154
- const dir = join(root, ".task", "tickets", String(t.number), "comments");
179
+ store.addComment(t.key, "fine", "claude");
180
+ const dir = join(root, ".task", "tickets", t.key, "comments");
155
181
  // A hand-dropped comment: parseable, wrong created, non-canonical spacing.
156
182
  writeFileSync(join(dir, "2026-08-15T170000-other.md"), '---\nauthor: "other"\ncreated: not-a-date\n---\nbody\n');
157
183
  const result = checkBoards(root, false);
158
184
  assert.ok(result.issues.some((issue) => /created is not a valid timestamp/.test(issue.message)));
159
185
  });
160
- test("config lints: legacy claimPrefix migrates, boards is root-only, prefixes must agree", () => {
186
+ test("config lints: retired claimPrefix refuses, boards is root-only, prefixes must agree", () => {
161
187
  const root = tempRoot();
162
188
  initProject(root, { name: "cfg", prefix: "CFG" });
163
189
  const rootConfig = join(root, ".task", "config.json");
@@ -174,25 +200,20 @@ test("config lints: legacy claimPrefix migrates, boards is root-only, prefixes m
174
200
  subRaw.boards = ["SUB"];
175
201
  subRaw.claims = { branchPrefix: "task/claim/" };
176
202
  writeFileSync(subConfig, `${JSON.stringify(subRaw, null, 2)}\n`);
177
- const found = checkBoards(root, false);
203
+ // The retired key with no claims.branchPrefix beside it: claimNamespace
204
+ // refuses by name, check surfaces that refusal, and --fix touches nothing —
205
+ // renaming the key is the human's one edit. The root's namespace being
206
+ // unreadable also means the sub-board mismatch lint has no reference to
207
+ // compare against; the root-only boards lint still fires.
208
+ const found = checkBoards(root, true);
178
209
  const messages = found.issues.map((issue) => issue.message);
179
- assert.ok(messages.some((m) => /`claimPrefix` is now `claims\.branchPrefix`/.test(m)));
210
+ assert.ok(messages.some((m) => /`claimPrefix` in \.task\/config\.json is the pre-0\.8 spelling/.test(m)));
180
211
  assert.ok(messages.some((m) => /"boards" is root-only/.test(m)));
181
- assert.ok(messages.some((m) => /disagrees with the root board's "claude\/task\/"/.test(m)));
182
- // --fix migrates the legacy key in place; the human decisions remain.
183
- const fixed = checkBoards(root, true);
184
- assert.ok(fixed.fixed.includes(".task/config.json"));
185
- const migrated = JSON.parse(readFileSync(rootConfig, "utf8"));
186
- assert.equal(migrated.claimPrefix, undefined);
187
- assert.equal(migrated.claims?.branchPrefix, "claude/task/");
188
- assert.deepEqual(migrated.boards, ["CFG", "SUB"]);
189
- assert.equal(migrated.prefix, "CFG");
190
- const remaining = checkBoards(root, false).issues.map((issue) => issue.message);
191
- assert.ok(!remaining.some((m) => /`claimPrefix` is now/.test(m)), "nag gone after migration");
192
- assert.ok(remaining.some((m) => /"boards" is root-only/.test(m)), "root-only lint stays");
193
- assert.ok(remaining.some((m) => /disagrees with the root board's/.test(m)), "mismatch stays");
212
+ assert.ok(found.issues.every((issue) => !issue.fixable || !/claimPrefix/.test(issue.message)));
213
+ const untouched = JSON.parse(readFileSync(rootConfig, "utf8"));
214
+ assert.equal(untouched.claimPrefix, "claude/task/");
194
215
  });
195
- test("an existing claims.branchPrefix wins over the legacy key on migration", () => {
216
+ test("a stray claimPrefix beside claims.branchPrefix is inert and flagged", () => {
196
217
  const root = tempRoot();
197
218
  initProject(root, { name: "dup", prefix: "DUP" });
198
219
  const configPath = join(root, ".task", "config.json");
@@ -200,10 +221,28 @@ test("an existing claims.branchPrefix wins over the legacy key on migration", ()
200
221
  raw.claimPrefix = "old/ns/";
201
222
  raw.claims = { branchPrefix: "new/ns/", maxOpenCount: 2 };
202
223
  writeFileSync(configPath, `${JSON.stringify(raw, null, 2)}\n`);
203
- checkBoards(root, true);
204
- const migrated = JSON.parse(readFileSync(configPath, "utf8"));
205
- assert.equal(migrated.claimPrefix, undefined);
206
- assert.equal(migrated.claims?.branchPrefix, "new/ns/");
207
- assert.equal(migrated.claims?.maxOpenCount, 2);
224
+ const messages = checkBoards(root, false).issues.map((issue) => issue.message);
225
+ assert.ok(messages.some((m) => /`claims\.branchPrefix` wins; delete the leftover key/.test(m)));
226
+ });
227
+ test("numeric ticket dirs are called out as pre-TAS-42 — junk entries separately", () => {
228
+ const root = tempRoot();
229
+ const store = initProject(root, { name: "mig", prefix: "MIG" });
230
+ store.create({ title: "A modern ticket", status: "todo" });
231
+ // A pre-migration ticket, imported by merging a branch cut before the id
232
+ // cutover: numeric directory, numeric blocked_by.
233
+ mkdirSync(join(root, ".task", "tickets", "42"), { recursive: true });
234
+ writeFileSync(join(root, ".task", "tickets", "42", "ticket.md"), "---\nstatus: todo\nposition: 0\ncreated: 2026-08-15T16:00:33.758Z\nupdated: 2026-08-15T16:00:33.758Z\n---\n\n# Old-format ticket\n");
235
+ // And something that was never a ticket directory at all.
236
+ mkdirSync(join(root, ".task", "tickets", "Not A Key"), { recursive: true });
237
+ const messages = checkBoards(root, false).issues.map((issue) => issue.message);
238
+ assert.ok(messages.some((m) => /numeric ticket directory — the pre-TAS-42 sequential-id format/.test(m)), "pre-migration dir named with the migration fix");
239
+ assert.ok(messages.some((m) => /ticket directories are named by their key/.test(m)), "junk entry reported as unexpected");
240
+ // A modern file whose blocked_by still carries numbers is refused by the
241
+ // strict parser with the migration named — surfaced through check.
242
+ const modern = store.create({ title: "Bad link format", status: "todo" });
243
+ const path = join(root, ".task", "tickets", modern.key, "ticket.md");
244
+ writeFileSync(path, readFileSync(path, "utf8").replace("status: todo", "status: todo\nblocked_by: [7]"));
245
+ const after = checkBoards(root, false).issues.map((issue) => issue.message);
246
+ assert.ok(after.some((m) => /pre-TAS-42 id format, which is no longer read/.test(m)));
208
247
  });
209
248
  //# sourceMappingURL=check.test.js.map