@nickmeriano/task 0.7.0 → 0.8.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 (86) hide show
  1. package/README.md +12 -7
  2. package/dist/check.d.ts +42 -0
  3. package/dist/check.d.ts.map +1 -0
  4. package/dist/check.js +364 -0
  5. package/dist/check.js.map +1 -0
  6. package/dist/check.test.d.ts +9 -0
  7. package/dist/check.test.d.ts.map +1 -0
  8. package/dist/check.test.js +209 -0
  9. package/dist/check.test.js.map +1 -0
  10. package/dist/claim.d.ts +56 -3
  11. package/dist/claim.d.ts.map +1 -1
  12. package/dist/claim.js +164 -9
  13. package/dist/claim.js.map +1 -1
  14. package/dist/claim.test.js +168 -14
  15. package/dist/claim.test.js.map +1 -1
  16. package/dist/cli.js +504 -93
  17. package/dist/cli.js.map +1 -1
  18. package/dist/file-store.d.ts +41 -15
  19. package/dist/file-store.d.ts.map +1 -1
  20. package/dist/file-store.js +197 -99
  21. package/dist/file-store.js.map +1 -1
  22. package/dist/index.d.ts +5 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +5 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/overview.d.ts +43 -0
  27. package/dist/overview.d.ts.map +1 -0
  28. package/dist/overview.js +53 -0
  29. package/dist/overview.js.map +1 -0
  30. package/dist/overview.test.d.ts +8 -0
  31. package/dist/overview.test.d.ts.map +1 -0
  32. package/dist/overview.test.js +47 -0
  33. package/dist/overview.test.js.map +1 -0
  34. package/dist/promote.test.d.ts +14 -0
  35. package/dist/promote.test.d.ts.map +1 -0
  36. package/dist/promote.test.js +106 -0
  37. package/dist/promote.test.js.map +1 -0
  38. package/dist/search.d.ts +32 -0
  39. package/dist/search.d.ts.map +1 -0
  40. package/dist/search.js +66 -0
  41. package/dist/search.js.map +1 -0
  42. package/dist/search.test.d.ts +2 -0
  43. package/dist/search.test.d.ts.map +1 -0
  44. package/dist/search.test.js +53 -0
  45. package/dist/search.test.js.map +1 -0
  46. package/dist/server.d.ts.map +1 -1
  47. package/dist/server.js +10 -2
  48. package/dist/server.js.map +1 -1
  49. package/dist/store.d.ts +16 -50
  50. package/dist/store.d.ts.map +1 -1
  51. package/dist/store.js +0 -368
  52. package/dist/store.js.map +1 -1
  53. package/dist/store.test.d.ts +1 -2
  54. package/dist/store.test.d.ts.map +1 -1
  55. package/dist/store.test.js +77 -48
  56. package/dist/store.test.js.map +1 -1
  57. package/dist/ticket-doc.d.ts +55 -2
  58. package/dist/ticket-doc.d.ts.map +1 -1
  59. package/dist/ticket-doc.js +177 -7
  60. package/dist/ticket-doc.js.map +1 -1
  61. package/dist/types.d.ts +67 -14
  62. package/dist/types.d.ts.map +1 -1
  63. package/dist/types.js.map +1 -1
  64. package/package.json +1 -1
  65. package/skill/SKILL.md +97 -31
  66. package/src/check.test.ts +271 -0
  67. package/src/check.ts +454 -0
  68. package/src/claim.test.ts +202 -14
  69. package/src/claim.ts +194 -10
  70. package/src/cli.ts +510 -89
  71. package/src/file-store.ts +217 -111
  72. package/src/index.ts +4 -2
  73. package/src/overview.test.ts +51 -0
  74. package/src/overview.ts +90 -0
  75. package/src/promote.test.ts +131 -0
  76. package/src/search.test.ts +64 -0
  77. package/src/search.ts +91 -0
  78. package/src/server.ts +11 -2
  79. package/src/store.test.ts +89 -57
  80. package/src/store.ts +18 -431
  81. package/src/ticket-doc.ts +210 -10
  82. package/src/types.ts +71 -14
  83. package/ui/dist/assets/{index-oJzomUDL.js → index-BJmOsOdR.js} +76 -76
  84. package/ui/dist/assets/index-BoqQlqSU.css +1 -0
  85. package/ui/dist/index.html +2 -2
  86. package/ui/dist/assets/index-CXW8uT5f.css +0 -1
@@ -4,8 +4,7 @@
4
4
  * 1. The text format round-trips — parse(serialize(x)) loses nothing.
5
5
  * 2. `FileStore` behaves like the store always has (positions, links,
6
6
  * comments, cascade on delete).
7
- * 3. `task migrate` reproduces a legacy SQLite board in files, exactly.
8
- * 4. Concurrent-writer shapes merge by construction: a comment is a new file,
7
+ * 3. Concurrent-writer shapes merge by construction: a comment is a new file,
9
8
  * a claim is a one-line status diff.
10
9
  */
11
10
  import assert from "node:assert/strict";
@@ -13,9 +12,9 @@ import { test } from "node:test";
13
12
  import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
14
13
  import { tmpdir } from "node:os";
15
14
  import { join } from "node:path";
16
- import { FileStore, initProject, migrateBoard, openBoard } from "./file-store.js";
15
+ import { FileStore, initProject, openBoard } from "./file-store.js";
17
16
  import { parseTicket, serializeTicket } from "./ticket-doc.js";
18
- import { TaskStore, findBoardsByPrefix, findScopeRoot } from "./store.js";
17
+ import { findBoardsByPrefix, findScopeRoot } from "./store.js";
19
18
  function tempRoot() {
20
19
  const dir = mkdtempSync(join(tmpdir(), "task-test-"));
21
20
  process.on("exit", () => rmSync(dir, { recursive: true, force: true }));
@@ -28,7 +27,7 @@ test("ticket documents round-trip, including the awkward bodies", () => {
28
27
  description: "One line.",
29
28
  status: "todo",
30
29
  tags: [],
31
- milestone: null,
30
+ goal: null,
32
31
  needsHuman: false,
33
32
  blockedBy: [],
34
33
  prs: [],
@@ -43,7 +42,7 @@ test("ticket documents round-trip, including the awkward bodies", () => {
43
42
  description: "# Not the title\n\n---\n\nstatus: not-a-field\n\n```md\n---\n```",
44
43
  status: "in_progress",
45
44
  tags: ["storage", "architecture"],
46
- milestone: "v2 storage",
45
+ goal: "v2-storage",
47
46
  needsHuman: true,
48
47
  blockedBy: [3, 7],
49
48
  prs: ["https://github.com/x/y/pull/1"],
@@ -56,7 +55,7 @@ test("ticket documents round-trip, including the awkward bodies", () => {
56
55
  description: "",
57
56
  status: "backlog",
58
57
  tags: [],
59
- milestone: null,
58
+ goal: null,
60
59
  needsHuman: false,
61
60
  blockedBy: [],
62
61
  prs: [],
@@ -73,7 +72,7 @@ test("hand-edits are forgiven where they're unambiguous", () => {
73
72
  const text = [
74
73
  "---",
75
74
  "status: todo",
76
- "milestone: launch", // unquoted string — the YAML instinct
75
+ "goal: launch", // unquoted string — the YAML instinct
77
76
  "position: 8",
78
77
  "created: 2026-08-15T16:00:33.758Z",
79
78
  "updated: 2026-08-15T16:00:33.758Z",
@@ -84,8 +83,14 @@ test("hand-edits are forgiven where they're unambiguous", () => {
84
83
  "Body.",
85
84
  ].join("\n");
86
85
  const doc = parseTicket(text, "test");
87
- assert.equal(doc.milestone, "launch");
86
+ assert.equal(doc.goal, "launch");
88
87
  assert.equal(doc.position, 8);
88
+ // The pre-0.8 spelling still reads as the goal — old boards keep rendering,
89
+ // and `task check --fix`'s canonical rewrite is the migration.
90
+ const legacy = parseTicket(text.replace("goal: launch", "milestone: launch"), "test");
91
+ assert.equal(legacy.goal, "launch");
92
+ assert.match(serializeTicket(legacy), /goal: "launch"/);
93
+ assert.doesNotMatch(serializeTicket(legacy), /milestone/);
89
94
  assert.throws(() => parseTicket(text.replace("status: todo", "status: todoo"), "here"), /here.*invalid status/);
90
95
  assert.throws(() => parseTicket("no frontmatter", "here"), /here.*frontmatter/);
91
96
  });
@@ -94,7 +99,7 @@ test("FileStore keeps the store's contract", () => {
94
99
  const store = initProject(root, { name: "sample project" });
95
100
  assert.equal(store.config.prefix, "SAM");
96
101
  assert.ok(store instanceof FileStore);
97
- const a = store.create({ title: "First", description: "alpha", tags: ["api"] });
102
+ const a = store.create({ title: "First", description: "alpha", tags: ["api"], status: "todo" });
98
103
  const b = store.create({ title: "Second", status: "todo" });
99
104
  const c = store.create({ title: "Third", status: "backlog" });
100
105
  assert.deepEqual([a.number, b.number, c.number], [1, 2, 3]);
@@ -133,53 +138,30 @@ test("FileStore keeps the store's contract", () => {
133
138
  const d = store.create({ title: "Fourth" });
134
139
  assert.equal(d.number, 4);
135
140
  });
136
- test("openBoard picks the backend by what's on disk", () => {
141
+ test("openBoard reads text boards, and refuses a pre-0.6 SQLite board loudly", () => {
137
142
  const fileRoot = tempRoot();
138
143
  initProject(fileRoot, { name: "files" });
139
144
  assert.ok(openBoard(fileRoot) instanceof FileStore);
145
+ // A pre-0.6 board: version-1 config, committed database, no tickets/ tree.
146
+ // Reading it as an empty text board would silently strand every ticket in
147
+ // the database, so it must refuse instead — pointing at the last release
148
+ // that still carries `task migrate`.
140
149
  const legacyRoot = tempRoot();
141
150
  mkdirSync(join(legacyRoot, ".task"));
142
151
  writeFileSync(join(legacyRoot, ".task", "config.json"), `${JSON.stringify({ name: "legacy", prefix: "LEG", version: 1 }, null, 2)}\n`);
143
- const legacy = openBoard(legacyRoot);
144
- assert.ok(legacy instanceof TaskStore);
145
- legacy.close();
146
- });
147
- test("migrate reproduces a legacy board, byte-visible and loss-free", () => {
148
- const root = tempRoot();
149
- mkdirSync(join(root, ".task"));
150
- writeFileSync(join(root, ".task", "config.json"), `${JSON.stringify({ name: "legacy board", prefix: "LEG", version: 1 }, null, 2)}\n`);
151
- const legacy = new TaskStore(root);
152
- const one = legacy.create({ title: "Keep me", description: "with *body*", tags: ["a", "b"] });
153
- const two = legacy.create({
154
- title: "Blocked one",
155
- status: "in_progress",
156
- milestone: "launch",
157
- needsHuman: true,
158
- blockedBy: [one.number],
159
- prs: ["https://github.com/x/y/pull/9"],
160
- });
161
- legacy.addComment(one.number, "hello", "nick");
162
- legacy.addComment(one.number, "and back", "claude");
163
- const expectedTasks = legacy.list({});
164
- const expectedComments = legacy.comments(one.number);
165
- legacy.close();
166
- const result = migrateBoard(root);
167
- assert.deepEqual(result, { tasks: 2, comments: 2 });
168
- assert.throws(() => migrateBoard(root), /already migrated/);
169
- const store = openBoard(root);
170
- assert.ok(store instanceof FileStore);
171
- assert.deepEqual(store.list({}), expectedTasks);
172
- assert.deepEqual(store.comments(one.number).map(({ author, body, createdAt }) => ({ author, body, createdAt })), expectedComments.map(({ author, body, createdAt }) => ({ author, body, createdAt })));
173
- assert.deepEqual(store.get(two.number).blockedBy, [one.number]);
174
- assert.match(readFileSync(join(root, ".task", ".gitignore"), "utf8"), /tasks\.db/);
175
- assert.equal(JSON.parse(readFileSync(join(root, ".task", "config.json"), "utf8"))
176
- .version, 2);
152
+ writeFileSync(join(legacyRoot, ".task", "tasks.db"), "not really a database");
153
+ assert.throws(() => openBoard(legacyRoot), /pre-0\.6 SQLite database.*migrate/);
154
+ // A version-2 board with no tickets yet is just an empty board, not legacy.
155
+ const emptyRoot = tempRoot();
156
+ mkdirSync(join(emptyRoot, ".task"));
157
+ writeFileSync(join(emptyRoot, ".task", "config.json"), `${JSON.stringify({ name: "empty", prefix: "EMP", version: 2 }, null, 2)}\n`);
158
+ assert.deepEqual(openBoard(emptyRoot).list({}), []);
177
159
  });
178
160
  test("archive moves finished tickets off the hot path, losing nothing", () => {
179
161
  const root = tempRoot();
180
162
  const store = initProject(root, { name: "archive test", prefix: "ARC" });
181
- const keep = store.create({ title: "Still open" });
182
- const old = store.create({ title: "Finished work" });
163
+ const keep = store.create({ title: "Still open", status: "todo" });
164
+ const old = store.create({ title: "Finished work", status: "todo" });
183
165
  store.link(keep.number, "blocked_by", old.number);
184
166
  store.addComment(old.number, "how it went", "nick");
185
167
  // Only finished work qualifies — archive is history, not a hiding place.
@@ -215,6 +197,53 @@ test("archive moves finished tickets off the hot path, losing nothing", () => {
215
197
  assert.equal(store.comments(old.number).length, 1);
216
198
  assert.throws(() => store.unarchive(old.number), /isn't archived/);
217
199
  });
200
+ test("goals: titled and described, one per task, progress always derived", () => {
201
+ const root = tempRoot();
202
+ const store = initProject(root, { name: "goals test", prefix: "GOA" });
203
+ // Created deliberately, slug derived from the title.
204
+ const goal = store.createGoal({
205
+ title: "Trust & guardrail layer",
206
+ description: "Why: DialMCP context lives here once, not in every ticket.",
207
+ });
208
+ assert.equal(goal.slug, "trust-guardrail-layer");
209
+ assert.throws(() => store.createGoal({ title: "Trust & guardrail layer" }), /already exists/);
210
+ assert.throws(() => store.createGoal({ title: "x", slug: "archive" }), /invalid goal slug/);
211
+ assert.throws(() => store.createGoal({ title: "x", slug: "Not A Slug" }), /invalid goal slug/);
212
+ // Assignment is validated: a goal must exist before a task can belong to it.
213
+ assert.throws(() => store.create({ title: "T", goal: "nope" }), /no such goal/);
214
+ const a = store.create({ title: "First", goal: goal.slug });
215
+ const b = store.create({ title: "Second" });
216
+ store.update(b.number, { goal: goal.slug });
217
+ assert.equal(store.get(b.number).goal, goal.slug);
218
+ assert.deepEqual(store.list({ goal: goal.slug }).map((t) => t.number), [a.number, b.number]);
219
+ // The file is the state: goal ref serialized on the ticket, goal file on disk.
220
+ assert.match(readFileSync(join(root, ".task", "tickets", "1", "ticket.md"), "utf8"), /goal: "trust-guardrail-layer"/);
221
+ const goalFile = readFileSync(join(root, ".task", "goals", "trust-guardrail-layer.md"), "utf8");
222
+ assert.match(goalFile, /# Trust & guardrail layer/);
223
+ // Update touches the file; clearing a task's goal is `goal: null`.
224
+ store.updateGoal(goal.slug, { description: "Sharper why." });
225
+ assert.equal(store.getGoal(goal.slug).description, "Sharper why.");
226
+ store.update(b.number, { goal: null });
227
+ assert.equal(store.get(b.number).goal, null);
228
+ // Archive refuses while open work references the goal, allows after.
229
+ assert.throws(() => store.archiveGoal(goal.slug), /still has open tasks \(GOA-1\)/);
230
+ store.update(a.number, { status: "done" });
231
+ const shelved = store.archiveGoal(goal.slug);
232
+ assert.equal(shelved.archived, true);
233
+ assert.deepEqual(store.goals().map((g) => g.slug), []);
234
+ assert.deepEqual(store.goals(true).map((g) => g.slug), [goal.slug]);
235
+ // Still resolvable (done tickets keep their ref readable), not assignable.
236
+ assert.equal(store.getGoal(goal.slug).title, "Trust & guardrail layer");
237
+ assert.throws(() => store.update(b.number, { goal: goal.slug }), /is archived — run/);
238
+ assert.throws(() => store.updateGoal(goal.slug, { title: "x" }), /is archived — run/);
239
+ // Delete needs every live ref cleared first — pruning organization is a
240
+ // human call, so the human makes it.
241
+ store.unarchiveGoal(goal.slug);
242
+ assert.throws(() => store.deleteGoal(goal.slug), /referenced by GOA-1/);
243
+ store.update(a.number, { goal: null });
244
+ store.deleteGoal(goal.slug);
245
+ assert.equal(store.getGoal(goal.slug), null);
246
+ });
218
247
  test("prefix routing helpers find the right board from anywhere", () => {
219
248
  const repo = tempRoot();
220
249
  initProject(repo, { name: "root board", prefix: "NIC" });
@@ -230,7 +259,7 @@ test("prefix routing helpers find the right board from anywhere", () => {
230
259
  test("concurrent-writer shapes merge by construction", () => {
231
260
  const root = tempRoot();
232
261
  const store = initProject(root, { name: "merge" });
233
- const task = store.create({ title: "Contended" });
262
+ const task = store.create({ title: "Contended", status: "todo" });
234
263
  // Two agents commenting at once = two files; simulate the second writer by
235
264
  // dropping its file in directly, the way a git merge would.
236
265
  store.addComment(task.number, "from session one", "claude");
@@ -1 +1 @@
1
- {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../src/store.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../src/store.test.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,8 @@ export interface TicketDoc {
21
21
  description: string;
22
22
  status: Status;
23
23
  tags: string[];
24
- milestone: string | null;
24
+ /** Slug of the goal this ticket belongs to — at most one, by design. */
25
+ goal: string | null;
25
26
  needsHuman: boolean;
26
27
  /** Task numbers blocking this one — the single stored side of the relation. */
27
28
  blockedBy: number[];
@@ -29,7 +30,23 @@ export interface TicketDoc {
29
30
  position: number;
30
31
  createdAt: string;
31
32
  updatedAt: string;
33
+ /**
34
+ * Frontmatter keys this version doesn't know, as raw `[key, value]` pairs in
35
+ * file order. Carried so a rewrite can't silently drop them — a hand-added
36
+ * field (or one written by a newer CLI) survives every update, re-emitted
37
+ * after the known fields. Present only when the file actually has any.
38
+ */
39
+ extras?: [string, string][];
32
40
  }
41
+ /**
42
+ * The frontmatter keys a ticket file may carry; anything else is an extra.
43
+ * `milestone` is the pre-0.8 spelling of `goal`: still *read* (as the goal, so
44
+ * old boards keep rendering) but never written — `task check` flags it and
45
+ * `--fix` rewrites the file, which is the whole migration.
46
+ */
47
+ export declare const TICKET_FIELDS: readonly ["status", "tags", "goal", "milestone", "needs_human", "blocked_by", "prs", "position", "created", "updated"];
48
+ /** The frontmatter keys a comment file may carry. */
49
+ export declare const COMMENT_FIELDS: readonly ["author", "created"];
33
50
  export interface CommentDoc {
34
51
  author: string;
35
52
  createdAt: string;
@@ -42,11 +59,47 @@ export declare function parseTicket(text: string, where: string): TicketDoc;
42
59
  /**
43
60
  * The canonical bytes for a ticket. Field order is fixed and empty fields are
44
61
  * omitted, so an unchanged ticket always serializes identically — diffs show
45
- * edits, never churn.
62
+ * edits, never churn. Unknown fields the parse carried through are re-emitted
63
+ * after the known ones, in their original order.
46
64
  */
47
65
  export declare function serializeTicket(doc: TicketDoc): string;
66
+ /** Everything `goals/<slug>.md` stores. The slug is the filename, not a field. */
67
+ export interface GoalDoc {
68
+ title: string;
69
+ description: string;
70
+ createdAt: string;
71
+ updatedAt: string;
72
+ /** Unknown frontmatter, carried through rewrites — same deal as tickets. */
73
+ extras?: [string, string][];
74
+ }
75
+ /** The frontmatter keys a goal file may carry. */
76
+ export declare const GOAL_FIELDS: readonly ["created", "updated"];
77
+ /**
78
+ * What a goal slug may look like — same alphabet as the claim-branch-safe
79
+ * ticket ids, because the slug ends up in frontmatter, URLs and prompts.
80
+ * "archive" is reserved: `goals/archive/` is where archived goals live.
81
+ */
82
+ export declare const GOAL_SLUG_PATTERN: RegExp;
83
+ export declare function isGoalSlug(value: string): boolean;
84
+ /** Derive a slug from a title: "Trust & guardrail layer" → "trust-guardrail-layer". */
85
+ export declare function slugifyGoal(title: string): string;
86
+ export declare function parseGoal(text: string, where: string): GoalDoc;
87
+ /** Canonical bytes for a goal — fixed field order, like tickets. */
88
+ export declare function serializeGoal(doc: GoalDoc): string;
89
+ /** A goal, forgivingly — null when there's no frontmatter at all. */
90
+ export declare function parseGoalLenient(text: string): GoalDoc | null;
48
91
  export declare function parseComment(text: string, where: string): CommentDoc;
49
92
  export declare function serializeComment(doc: CommentDoc): string;
93
+ /** A ticket, forgivingly — or null when there's no frontmatter to read at all. */
94
+ export declare function parseTicketLenient(text: string): TicketDoc | null;
95
+ /**
96
+ * The frontmatter keys a file carries, leniently — null when there's no
97
+ * frontmatter at all. `task check` uses this to spot unknown keys in files
98
+ * whose parsed shape (comments) doesn't carry them through.
99
+ */
100
+ export declare function frontmatterKeys(text: string): string[] | null;
101
+ /** A comment, forgivingly — or null when there's no frontmatter at all. */
102
+ export declare function parseCommentLenient(text: string): CommentDoc | null;
50
103
  /**
51
104
  * A comment's filename stem — readable, sortable, and unique enough that two
52
105
  * branches almost never mint the same one: `2026-08-15T165943-claude`. The
@@ -1 +1 @@
1
- {"version":3,"file":"ticket-doc.d.ts","sourceRoot":"","sources":["../src/ticket-doc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAA;AAE5D,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,OAAO,CAAA;IACnB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AA0F9C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAkClE;AAOD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAatD;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAOpE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAKxD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQrE"}
1
+ {"version":3,"file":"ticket-doc.d.ts","sourceRoot":"","sources":["../src/ticket-doc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,YAAY,CAAA;AAE5D,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,wEAAwE;IACxE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,UAAU,EAAE,OAAO,CAAA;IACnB,+EAA+E;IAC/E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,wHAWhB,CAAA;AAEV,qDAAqD;AACrD,eAAO,MAAM,cAAc,gCAAiC,CAAA;AAE5D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,kFAAkF;AAClF,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAmG9C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAwClE;AAOD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CActD;AASD,kFAAkF;AAClF,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;CAC5B;AAED,kDAAkD;AAClD,eAAO,MAAM,WAAW,iCAAkC,CAAA;AAE1D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,QAA8B,CAAA;AAE5D,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAkB9D;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAMlD;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAU7D;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAOpE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAKxD;AAyBD,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAuBjE;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAG7D;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQnE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQrE"}
@@ -15,6 +15,26 @@
15
15
  * diff of a new ticket *is* the ticket.
16
16
  */
17
17
  import { STATUSES, isStatus } from "./types.js";
18
+ /**
19
+ * The frontmatter keys a ticket file may carry; anything else is an extra.
20
+ * `milestone` is the pre-0.8 spelling of `goal`: still *read* (as the goal, so
21
+ * old boards keep rendering) but never written — `task check` flags it and
22
+ * `--fix` rewrites the file, which is the whole migration.
23
+ */
24
+ export const TICKET_FIELDS = [
25
+ "status",
26
+ "tags",
27
+ "goal",
28
+ "milestone",
29
+ "needs_human",
30
+ "blocked_by",
31
+ "prs",
32
+ "position",
33
+ "created",
34
+ "updated",
35
+ ];
36
+ /** The frontmatter keys a comment file may carry. */
37
+ export const COMMENT_FIELDS = ["author", "created"];
18
38
  /** A parse that names the file it failed in — these files invite hand-editing. */
19
39
  export class TicketParseError extends Error {
20
40
  }
@@ -34,13 +54,23 @@ function parseScalar(raw) {
34
54
  return trimmed;
35
55
  }
36
56
  }
57
+ /**
58
+ * Split a file into frontmatter fields and body. Two callers, two stances:
59
+ * with a `where` the CLI is parsing and every malformation throws, naming the
60
+ * file; with `where: null` the hosted board is rendering and a file with no
61
+ * frontmatter returns null while a merely-odd line is skipped.
62
+ */
37
63
  function splitRaw(text, where) {
38
64
  const lines = text.replace(/\r\n/g, "\n").split("\n");
39
65
  if (lines[0] !== "---") {
66
+ if (where === null)
67
+ return null;
40
68
  throw new TicketParseError(`${where}: expected the file to start with a --- frontmatter block`);
41
69
  }
42
70
  const end = lines.indexOf("---", 1);
43
71
  if (end < 0) {
72
+ if (where === null)
73
+ return null;
44
74
  throw new TicketParseError(`${where}: unterminated frontmatter — no closing ---`);
45
75
  }
46
76
  const fields = new Map();
@@ -49,6 +79,8 @@ function splitRaw(text, where) {
49
79
  continue;
50
80
  const colon = line.indexOf(":");
51
81
  if (colon < 0) {
82
+ if (where === null)
83
+ continue;
52
84
  throw new TicketParseError(`${where}: not a "key: value" frontmatter line: ${line}`);
53
85
  }
54
86
  fields.set(line.slice(0, colon).trim(), line.slice(colon + 1));
@@ -107,9 +139,9 @@ export function parseTicket(text, where) {
107
139
  if (!isStatus(status)) {
108
140
  throw new TicketParseError(`${where}: invalid status "${status}" — one of: ${STATUSES.join(", ")}`);
109
141
  }
110
- const milestone = field(raw, "milestone");
111
- if (milestone !== undefined && milestone !== null && typeof milestone !== "string") {
112
- throw new TicketParseError(`${where}: milestone should be a string`);
142
+ const goal = field(raw, "goal") ?? field(raw, "milestone");
143
+ if (goal !== undefined && goal !== null && typeof goal !== "string") {
144
+ throw new TicketParseError(`${where}: goal should be a string`);
113
145
  }
114
146
  const needsHuman = field(raw, "needs_human");
115
147
  const position = field(raw, "position");
@@ -120,18 +152,25 @@ export function parseTicket(text, where) {
120
152
  if (title === null) {
121
153
  throw new TicketParseError(`${where}: expected the body to start with "# <title>"`);
122
154
  }
155
+ const known = new Set(TICKET_FIELDS);
156
+ const extras = [];
157
+ for (const [key, value] of raw.fields) {
158
+ if (!known.has(key))
159
+ extras.push([key, value.trim()]);
160
+ }
123
161
  return {
124
162
  title,
125
163
  description,
126
164
  status,
127
165
  tags: stringList(raw, "tags", where),
128
- milestone: typeof milestone === "string" && milestone !== "" ? milestone : null,
166
+ goal: typeof goal === "string" && goal !== "" ? goal : null,
129
167
  needsHuman: needsHuman === true,
130
168
  blockedBy: numberList(raw, "blocked_by", where),
131
169
  prs: stringList(raw, "prs", where),
132
170
  position: typeof position === "number" ? position : 0,
133
171
  createdAt: stringField(raw, "created", where, ""),
134
172
  updatedAt: stringField(raw, "updated", where, ""),
173
+ ...(extras.length ? { extras } : {}),
135
174
  };
136
175
  }
137
176
  /** JSON array on one line — `["a", "b"]` — which is also valid YAML flow style. */
@@ -141,14 +180,15 @@ function list(values) {
141
180
  /**
142
181
  * The canonical bytes for a ticket. Field order is fixed and empty fields are
143
182
  * omitted, so an unchanged ticket always serializes identically — diffs show
144
- * edits, never churn.
183
+ * edits, never churn. Unknown fields the parse carried through are re-emitted
184
+ * after the known ones, in their original order.
145
185
  */
146
186
  export function serializeTicket(doc) {
147
187
  const lines = ["---", `status: ${doc.status}`];
148
188
  if (doc.tags.length)
149
189
  lines.push(`tags: ${list(doc.tags)}`);
150
- if (doc.milestone)
151
- lines.push(`milestone: ${JSON.stringify(doc.milestone)}`);
190
+ if (doc.goal)
191
+ lines.push(`goal: ${JSON.stringify(doc.goal)}`);
152
192
  if (doc.needsHuman)
153
193
  lines.push(`needs_human: true`);
154
194
  if (doc.blockedBy.length)
@@ -158,11 +198,76 @@ export function serializeTicket(doc) {
158
198
  lines.push(`position: ${doc.position}`);
159
199
  lines.push(`created: ${doc.createdAt}`);
160
200
  lines.push(`updated: ${doc.updatedAt}`);
201
+ for (const [key, value] of doc.extras ?? [])
202
+ lines.push(`${key}: ${value}`);
161
203
  lines.push("---", "", `# ${doc.title}`);
162
204
  if (doc.description)
163
205
  lines.push("", doc.description);
164
206
  return `${lines.join("\n")}\n`;
165
207
  }
208
+ /** The frontmatter keys a goal file may carry. */
209
+ export const GOAL_FIELDS = ["created", "updated"];
210
+ /**
211
+ * What a goal slug may look like — same alphabet as the claim-branch-safe
212
+ * ticket ids, because the slug ends up in frontmatter, URLs and prompts.
213
+ * "archive" is reserved: `goals/archive/` is where archived goals live.
214
+ */
215
+ export const GOAL_SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
216
+ export function isGoalSlug(value) {
217
+ return GOAL_SLUG_PATTERN.test(value) && value !== "archive";
218
+ }
219
+ /** Derive a slug from a title: "Trust & guardrail layer" → "trust-guardrail-layer". */
220
+ export function slugifyGoal(title) {
221
+ return title
222
+ .toLowerCase()
223
+ .replace(/[^a-z0-9]+/g, "-")
224
+ .replace(/^-+|-+$/g, "")
225
+ .slice(0, 64)
226
+ .replace(/-+$/g, "");
227
+ }
228
+ export function parseGoal(text, where) {
229
+ const raw = splitRaw(text, where);
230
+ const { title, description } = splitTitle(raw.body);
231
+ if (title === null) {
232
+ throw new TicketParseError(`${where}: expected the body to start with "# <title>"`);
233
+ }
234
+ const known = new Set(GOAL_FIELDS);
235
+ const extras = [];
236
+ for (const [key, value] of raw.fields) {
237
+ if (!known.has(key))
238
+ extras.push([key, value.trim()]);
239
+ }
240
+ return {
241
+ title,
242
+ description,
243
+ createdAt: stringField(raw, "created", where, ""),
244
+ updatedAt: stringField(raw, "updated", where, ""),
245
+ ...(extras.length ? { extras } : {}),
246
+ };
247
+ }
248
+ /** Canonical bytes for a goal — fixed field order, like tickets. */
249
+ export function serializeGoal(doc) {
250
+ const lines = ["---", `created: ${doc.createdAt}`, `updated: ${doc.updatedAt}`];
251
+ for (const [key, value] of doc.extras ?? [])
252
+ lines.push(`${key}: ${value}`);
253
+ lines.push("---", "", `# ${doc.title}`);
254
+ if (doc.description)
255
+ lines.push("", doc.description);
256
+ return `${lines.join("\n")}\n`;
257
+ }
258
+ /** A goal, forgivingly — null when there's no frontmatter at all. */
259
+ export function parseGoalLenient(text) {
260
+ const raw = splitRaw(text, null);
261
+ if (!raw)
262
+ return null;
263
+ const { title, description } = splitTitle(raw.body);
264
+ return {
265
+ title: title ?? "",
266
+ description,
267
+ createdAt: lenientString(field(raw, "created")),
268
+ updatedAt: lenientString(field(raw, "updated")),
269
+ };
270
+ }
166
271
  // ── Comments ─────────────────────────────────────────────────────────────────
167
272
  export function parseComment(text, where) {
168
273
  const raw = splitRaw(text, where);
@@ -179,6 +284,71 @@ export function serializeComment(doc) {
179
284
  lines.push(`created: ${doc.createdAt}`, "---", "", doc.body);
180
285
  return `${lines.join("\n")}\n`;
181
286
  }
287
+ // ── Lenient parsing ──────────────────────────────────────────────────────────
288
+ //
289
+ // The hosted board's read of the same format. The CLI is strict — it wrote the
290
+ // file, so a malformation is a bug worth halting on — but a renderer is looking
291
+ // at whatever a hand-edit or a bad merge left behind, and it must degrade
292
+ // rather than throw: a broken ticket becomes a degraded ticket (unknown status
293
+ // → backlog, missing heading → empty title), never a broken board. Living here
294
+ // rather than restated in the worker keeps one definition of the format.
295
+ function lenientStrings(value) {
296
+ return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
297
+ }
298
+ function lenientNumbers(value) {
299
+ return Array.isArray(value)
300
+ ? value.filter((v) => typeof v === "number" && Number.isInteger(v))
301
+ : [];
302
+ }
303
+ function lenientString(value) {
304
+ return typeof value === "string" ? value : "";
305
+ }
306
+ /** A ticket, forgivingly — or null when there's no frontmatter to read at all. */
307
+ export function parseTicketLenient(text) {
308
+ const raw = splitRaw(text, null);
309
+ if (!raw)
310
+ return null;
311
+ const status = field(raw, "status");
312
+ // The pre-0.8 `milestone` key still reads as the goal — the lenient parser
313
+ // exists precisely for old bytes (hand-edits, and here: old branches the
314
+ // hosted board previews).
315
+ const goal = field(raw, "goal") ?? field(raw, "milestone");
316
+ const position = field(raw, "position");
317
+ const { title, description } = splitTitle(raw.body);
318
+ return {
319
+ title: title ?? "",
320
+ description,
321
+ status: typeof status === "string" && isStatus(status) ? status : "backlog",
322
+ tags: lenientStrings(field(raw, "tags")),
323
+ goal: typeof goal === "string" && goal !== "" ? goal : null,
324
+ needsHuman: field(raw, "needs_human") === true,
325
+ blockedBy: [...new Set(lenientNumbers(field(raw, "blocked_by")))].sort((a, b) => a - b),
326
+ prs: lenientStrings(field(raw, "prs")),
327
+ position: typeof position === "number" && Number.isFinite(position) ? position : 0,
328
+ createdAt: lenientString(field(raw, "created")),
329
+ updatedAt: lenientString(field(raw, "updated")),
330
+ };
331
+ }
332
+ /**
333
+ * The frontmatter keys a file carries, leniently — null when there's no
334
+ * frontmatter at all. `task check` uses this to spot unknown keys in files
335
+ * whose parsed shape (comments) doesn't carry them through.
336
+ */
337
+ export function frontmatterKeys(text) {
338
+ const raw = splitRaw(text, null);
339
+ return raw ? [...raw.fields.keys()] : null;
340
+ }
341
+ /** A comment, forgivingly — or null when there's no frontmatter at all. */
342
+ export function parseCommentLenient(text) {
343
+ const raw = splitRaw(text, null);
344
+ if (!raw)
345
+ return null;
346
+ return {
347
+ author: lenientString(field(raw, "author")),
348
+ createdAt: lenientString(field(raw, "created")),
349
+ body: raw.body,
350
+ };
351
+ }
182
352
  /**
183
353
  * A comment's filename stem — readable, sortable, and unique enough that two
184
354
  * branches almost never mint the same one: `2026-08-15T165943-claude`. The