@nickmeriano/task 0.4.2 → 0.6.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 (43) hide show
  1. package/README.md +77 -9
  2. package/dist/cli.js +290 -19
  3. package/dist/cli.js.map +1 -1
  4. package/dist/file-store.d.ts +113 -0
  5. package/dist/file-store.d.ts.map +1 -0
  6. package/dist/file-store.js +604 -0
  7. package/dist/file-store.js.map +1 -0
  8. package/dist/index.d.ts +6 -4
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +3 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/server.d.ts.map +1 -1
  13. package/dist/server.js +30 -7
  14. package/dist/server.js.map +1 -1
  15. package/dist/store.d.ts +69 -16
  16. package/dist/store.d.ts.map +1 -1
  17. package/dist/store.js +169 -39
  18. package/dist/store.js.map +1 -1
  19. package/dist/store.test.d.ts +12 -0
  20. package/dist/store.test.d.ts.map +1 -0
  21. package/dist/store.test.js +252 -0
  22. package/dist/store.test.js.map +1 -0
  23. package/dist/ticket-doc.d.ts +57 -0
  24. package/dist/ticket-doc.d.ts.map +1 -0
  25. package/dist/ticket-doc.js +197 -0
  26. package/dist/ticket-doc.js.map +1 -0
  27. package/dist/types.d.ts +35 -3
  28. package/dist/types.d.ts.map +1 -1
  29. package/dist/types.js.map +1 -1
  30. package/package.json +4 -4
  31. package/skill/SKILL.md +40 -9
  32. package/src/cli.ts +304 -22
  33. package/src/file-store.ts +693 -0
  34. package/src/index.ts +30 -4
  35. package/src/server.ts +31 -11
  36. package/src/store.test.ts +305 -0
  37. package/src/store.ts +210 -49
  38. package/src/ticket-doc.ts +226 -0
  39. package/src/types.ts +35 -3
  40. package/ui/dist/assets/index-CXW8uT5f.css +1 -0
  41. package/ui/dist/assets/{index-Dm3ToURf.js → index-oJzomUDL.js} +67 -67
  42. package/ui/dist/index.html +2 -2
  43. package/ui/dist/assets/index-DXFbw9bM.css +0 -1
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  export declare const STATUSES: readonly ["backlog", "todo", "in_progress", "done", "canceled"];
4
4
  export type Status = (typeof STATUSES)[number];
5
5
  export interface Task {
6
- /** Display id — `<prefix>-<number>`, e.g. "PHONE-12". */
6
+ /** Display id — `<prefix>-<number>`, e.g. "PHO-12". */
7
7
  id: string;
8
8
  number: number;
9
9
  title: string;
@@ -13,13 +13,33 @@ export interface Task {
13
13
  milestone: string | null;
14
14
  /** This ticket can't be finished by an agent alone. */
15
15
  needsHuman: boolean;
16
+ /**
17
+ * Task numbers this one blocks / is blocked by. One relation, two views:
18
+ * a single `(blocker, blocked)` row shows up in the blocker's `blocks` and
19
+ * the blocked task's `blockedBy`, so the mirror can never drift.
20
+ */
21
+ blocks: number[];
22
+ blockedBy: number[];
23
+ /** Pull request URLs attached to this task. */
24
+ prs: string[];
16
25
  /** Sort key within a status column; smaller sorts first. */
17
26
  position: number;
18
27
  createdAt: string;
19
28
  updatedAt: string;
29
+ /**
30
+ * Set (to true) only on tickets living in `.task/archive/` — finished work
31
+ * moved out of the board's hot path. Absent on live tickets, so the board
32
+ * payloads stay byte-identical to what they always were.
33
+ */
34
+ archived?: boolean;
20
35
  }
21
36
  export interface Comment {
22
- id: number;
37
+ /**
38
+ * Stable opaque id. On file-backed boards it's the comment's filename stem
39
+ * (e.g. "2026-08-15T165943-claude"); on legacy SQLite boards, the rowid as a
40
+ * string.
41
+ */
42
+ id: string;
23
43
  taskId: string;
24
44
  author: string;
25
45
  body: string;
@@ -27,7 +47,7 @@ export interface Comment {
27
47
  }
28
48
  export interface ProjectConfig {
29
49
  name: string;
30
- /** Uppercase id prefix, e.g. "PHONE" → PHONE-1, PHONE-2, … */
50
+ /** Uppercase id prefix, e.g. "PHO" → PHO-1, PHO-2, … */
31
51
  prefix: string;
32
52
  version: number;
33
53
  }
@@ -38,6 +58,8 @@ export interface TaskFilter {
38
58
  milestone?: string;
39
59
  /** undefined = don't filter on it at all. */
40
60
  needsHuman?: boolean;
61
+ /** true = list the archive instead of the board. */
62
+ archived?: boolean;
41
63
  }
42
64
  export interface TaskInput {
43
65
  title: string;
@@ -46,6 +68,9 @@ export interface TaskInput {
46
68
  tags?: string[];
47
69
  milestone?: string | null;
48
70
  needsHuman?: boolean;
71
+ blocks?: number[];
72
+ blockedBy?: number[];
73
+ prs?: string[];
49
74
  }
50
75
  export interface TaskPatch {
51
76
  title?: string;
@@ -54,6 +79,13 @@ export interface TaskPatch {
54
79
  tags?: string[];
55
80
  milestone?: string | null;
56
81
  needsHuman?: boolean;
82
+ /**
83
+ * Full replacement, like `tags` — the store reconciles the relation table
84
+ * to match. Writing either side updates the other task's mirror view.
85
+ */
86
+ blocks?: number[];
87
+ blockedBy?: number[];
88
+ prs?: string[];
57
89
  /** Explicit board position (used by drag-and-drop in the UI). */
58
90
  position?: number;
59
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;gEACgE;AAChE,eAAO,MAAM,QAAQ,iEAMX,CAAA;AACV,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9C,MAAM,WAAW,IAAI;IACnB,yDAAyD;IACzD,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,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,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAA;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAEvD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;gEACgE;AAChE,eAAO,MAAM,QAAQ,iEAMX,CAAA;AACV,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9C,MAAM,WAAW,IAAI;IACnB,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,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,uDAAuD;IACvD,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,EAAE,CAAA;IACb,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;CACf;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAA;IACd,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAEvD"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;gEACgE;AAChE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,SAAS;IACT,MAAM;IACN,aAAa;IACb,MAAM;IACN,UAAU;CACF,CAAA;AAgEV,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAQ,QAA8B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxD,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;gEACgE;AAChE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,SAAS;IACT,MAAM;IACN,aAAa;IACb,MAAM;IACN,UAAU;CACF,CAAA;AAgGV,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAQ,QAA8B,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AACxD,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@nickmeriano/task",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
- "description": "A task manager that lives in your repo — SQLite in .task/, a zero-dependency CLI for humans and agents, and a live kanban/table UI via `task serve`.",
5
+ "description": "A task manager that lives in your repo — plain-text tickets in .task/, a zero-dependency CLI for humans and agents, and a live kanban/table UI via `task serve`.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://task.nickmeriano.com",
8
8
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "todo",
26
26
  "kanban",
27
27
  "cli",
28
- "sqlite",
28
+ "markdown",
29
29
  "agents",
30
30
  "local-first",
31
31
  "monorepo"
@@ -44,7 +44,7 @@
44
44
  "prepack": "pnpm build",
45
45
  "dev": "vite ui",
46
46
  "lint": "eslint .",
47
- "test": "node --test --experimental-strip-types ui/src/*.test.ts",
47
+ "test": "node --test --experimental-strip-types src/*.test.ts ui/src/*.test.ts",
48
48
  "typecheck": "tsc --noEmit && tsc --noEmit -p ui && tsc --noEmit -p ui/tsconfig.test.json"
49
49
  },
50
50
  "engines": {
package/skill/SKILL.md CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tasks
3
3
  description: >-
4
4
  Work with this repository's built-in task manager (the `task` CLI — a .task/
5
- directory with a SQLite database, from @nickmeriano/task). Use this
5
+ directory of plain-text tickets, from @nickmeriano/task). Use this
6
6
  skill whenever the user mentions tasks, tickets, issues, todos, backlog,
7
7
  kanban, board, "what's next", "what should I work on", or asks you to plan,
8
8
  track, or report progress on work — and also on your own initiative: when you
@@ -13,11 +13,14 @@ description: >-
13
13
 
14
14
  # tasks — the repo's task manager
15
15
 
16
- This repository tracks its work in `.task/` at the project root: a SQLite
17
- database driven by the `task` CLI. Tasks live in the repo, next to the code
18
- they describe — when you update a task, the user sees it instantly (the board
19
- UI at `task serve` updates in realtime), and the state is committed with the
20
- code, so it survives sessions and travels with branches.
16
+ This repository tracks its work in `.task/` at the project root: one markdown
17
+ file per ticket under `.task/tickets/`, driven by the `task` CLI. Tasks live in
18
+ the repo, next to the code they describe — when you update a task, the user
19
+ sees it instantly (the board UI at `task serve` updates in realtime), and the
20
+ state is committed with the code, so it survives sessions, travels with
21
+ branches, and shows up as readable diffs in PRs. Always write through the CLI
22
+ rather than editing ticket files by hand — it keeps numbering, positions and
23
+ relations consistent.
21
24
 
22
25
  Run `task` from anywhere in the repo; it walks up to find `.task/` like git
23
26
  finds `.git`. If the CLI isn't on PATH, use `npx @nickmeriano/task` instead.
@@ -40,8 +43,15 @@ task update <id> [--title t] [--description text] [--status s] [--tags a,b]
40
43
  task start <id> # → in_progress
41
44
  task done <id> # → done
42
45
  task move <id> <status> # any status change
46
+ task link <id> --blocked-by <id> # mark a dependency (or --blocks)
47
+ task unlink <id> --blocked-by <id> # remove one (or --blocks)
48
+ task update <id> --pr <url> # attach a pull request (appends)
43
49
  task comment <id> "text" --author claude
44
50
  task delete <id>
51
+ task boards --json # every board in the repo, with prefixes
52
+ task archive <id> --json # done/canceled ticket -> .task/archive/
53
+ task archive --all --json # archive everything done or canceled
54
+ task unarchive <id> --json # put one back on the board
45
55
  task whoami # who comments are attributed to
46
56
  ```
47
57
 
@@ -50,11 +60,32 @@ the user can read it from a phone, and take it away again. Both open a browser
50
60
  and wait for a human, so **never run either on your own initiative**; suggest
51
61
  `task publish` if the user wants to see the board remotely.
52
62
 
53
- - `<id>` is `PREFIX-12` or just `12`.
63
+ - `<id>` is `PREFIX-12` or just `12`. A bare number means the nearest board;
64
+ a prefixed id routes to whichever board in the repo owns that prefix, so
65
+ `TAS-12` works from any directory. `task boards --json` lists them all.
54
66
  - Statuses: `backlog` `todo` `in_progress` `done` `canceled`.
55
67
  - `--tag a,b` matches a task carrying *either* tag, not both.
56
- - Clear a field by passing it empty: `--tags ""`, `--milestone ""`.
57
- - `task list` hides done/canceled by default; `--all` shows everything.
68
+ - Clear a field by passing it empty: `--tags ""`, `--milestone ""`, `--prs ""`.
69
+ - `task list` hides done/canceled by default; `--all` shows everything, and
70
+ `--archived` lists the archive instead of the board.
71
+ - Archiving is history, not deletion: only done/canceled tickets qualify,
72
+ their numbers stay reserved, and `task show` still reads them. Archived
73
+ tickets refuse edits until unarchived. Don't archive on your own
74
+ initiative — suggest `task archive --all` when finished work is piling up,
75
+ and let the user decide.
76
+
77
+ **Dependencies.** `task link A --blocked-by B` and `task link B --blocks A`
78
+ write the same relation — each task's `task show` lists both its `blocked`
79
+ and `blocks` sides, with the other task's current status. Before starting a
80
+ task, check it isn't blocked by something still open; when you discover an
81
+ ordering ("this can't land until X does"), record it with `task link` instead
82
+ of prose in a comment. Blocked tasks wear a red "Blocked" badge on the board
83
+ until every blocker is done or canceled.
84
+
85
+ **Pull requests.** When you open a PR for a task, attach it:
86
+ `task update <id> --pr <url>`. Put the task id in the PR title too (e.g.
87
+ `[TAS-6] Fix retry loop`) so the two reference each other from both sides.
88
+ `--pr` appends one URL; `--prs url1,url2` replaces the whole list.
58
89
 
59
90
  ## How to work with the board
60
91