backlog.md 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/bin/backlog-darwin-arm64/backlog +0 -0
  2. package/bin/backlog-darwin-x64/backlog +0 -0
  3. package/bin/backlog-linux-arm64/backlog +0 -0
  4. package/{cli → bin/backlog-linux-x64}/backlog +0 -0
  5. package/bin/backlog-win32-x64/backlog.exe +0 -0
  6. package/cli.js +62 -0
  7. package/package.json +57 -46
  8. package/.backlog/archive/drafts/readme.md +0 -3
  9. package/.backlog/archive/drafts/task-41 - temporary-test-task.md +0 -13
  10. package/.backlog/archive/readme.md +0 -6
  11. package/.backlog/archive/tasks/readme.md +0 -3
  12. package/.backlog/archive/tasks/task-41 - cli-migrate-terminal-ui-to-bblessed.md +0 -14
  13. package/.backlog/config.yml +0 -7
  14. package/.backlog/decisions/readme.md +0 -7
  15. package/.backlog/docs/readme.md +0 -20
  16. package/.backlog/drafts/readme.md +0 -3
  17. package/.backlog/drafts/task-26 - docs-add-board-export-step-to-agent-dod.md +0 -21
  18. package/.backlog/drafts/task-28 - add-code-of-conduct.md +0 -20
  19. package/.backlog/drafts/task-30 - create-changelog.md +0 -19
  20. package/.backlog/milestones/m-0 - project-setup.md +0 -8
  21. package/.backlog/milestones/m-1 - cli.md +0 -8
  22. package/.backlog/milestones/m-2 - cli-kanban.md +0 -8
  23. package/.backlog/milestones/m-3 - gui.md +0 -8
  24. package/.backlog/milestones/m-4 - gui-kanban.md +0 -8
  25. package/.backlog/milestones/m-5 - gui-advanced.md +0 -12
  26. package/.backlog/milestones/readme.md +0 -3
  27. package/.backlog/readme.md +0 -5
  28. package/.backlog/tasks/readme.md +0 -37
  29. package/.backlog/tasks/task-1 - cli-setup-core-project.md +0 -23
  30. package/.backlog/tasks/task-10 - gui-init-packaging.md +0 -23
  31. package/.backlog/tasks/task-11 - gui-kanban-board.md +0 -26
  32. package/.backlog/tasks/task-12 - gui-advanced.md +0 -25
  33. package/.backlog/tasks/task-13 - cli-add-agent-instruction-prompt.md +0 -53
  34. package/.backlog/tasks/task-13.1 - cli-agent-instruction-file-selection.md +0 -40
  35. package/.backlog/tasks/task-14 - gui-introduction-screens.md +0 -21
  36. package/.backlog/tasks/task-15 - improve-tasks-readme-with-generic-example-and-cli-reference.md +0 -20
  37. package/.backlog/tasks/task-16 - improve-docs-readme-with-generic-example-and-cli-reference.md +0 -20
  38. package/.backlog/tasks/task-17 - improve-drafts-readme-with-generic-example-and-cli-reference.md +0 -20
  39. package/.backlog/tasks/task-18 - improve-decisions-readme-with-generic-example-and-cli-reference.md +0 -20
  40. package/.backlog/tasks/task-19 - cli-fix-default-task-status-and-remove-draft-from-statuses.md +0 -55
  41. package/.backlog/tasks/task-2 - cli-core-logic-library.md +0 -28
  42. package/.backlog/tasks/task-20 - add-agent-guideline-to-mark-tasks-in-progress-on-start.md +0 -32
  43. package/.backlog/tasks/task-21 - kanban-board-vertical-layout.md +0 -31
  44. package/.backlog/tasks/task-22 - cli-prevent-double-dash-in-task-filenames.md +0 -24
  45. package/.backlog/tasks/task-23 - cli-kanban-board-order-tasks-by-id-asc.md +0 -30
  46. package/.backlog/tasks/task-24 - handle-subtasks-in-the-kanban-view.md +0 -38
  47. package/.backlog/tasks/task-24.1 - cli-kanban-board-milestone-view.md +0 -19
  48. package/.backlog/tasks/task-25 - cli-export-kanban-board-to-readme.md +0 -28
  49. package/.backlog/tasks/task-27 - add-contributing-guidelines.md +0 -27
  50. package/.backlog/tasks/task-29 - add-github-templates.md +0 -28
  51. package/.backlog/tasks/task-3 - cli-implement-backlog-init.md +0 -63
  52. package/.backlog/tasks/task-31 - update-readme-for-open-source.md +0 -26
  53. package/.backlog/tasks/task-32 - cli-hide-empty-'no-status'-column.md +0 -31
  54. package/.backlog/tasks/task-33 - cli-export-milestones-board-as-roadmap.md +0 -20
  55. package/.backlog/tasks/task-34 - split-readme.md-for-users-and-contributors.md +0 -26
  56. package/.backlog/tasks/task-35 - finalize-package.json-metadata-for-publishing.md +0 -24
  57. package/.backlog/tasks/task-36 - cli-prompt-for-project-name-in-init.md +0 -24
  58. package/.backlog/tasks/task-37 - cli-board-view-open-tasks-in-ide.md +0 -19
  59. package/.backlog/tasks/task-38 - cli-improved-agent-selection-for-init.md +0 -25
  60. package/.backlog/tasks/task-39 - cli-fix-empty-agent-instruction-files-on-init.md +0 -31
  61. package/.backlog/tasks/task-4 - cli-task-management-commands.md +0 -28
  62. package/.backlog/tasks/task-4.1 - cli-task-create.md +0 -27
  63. package/.backlog/tasks/task-4.10 - use-cli-to-mark-tasks-done.md +0 -51
  64. package/.backlog/tasks/task-4.11 - docs-add-definition-of-done-to-agent-guidelines.md +0 -23
  65. package/.backlog/tasks/task-4.12 - cli-handle-task-id-conflicts-across-branches.md +0 -53
  66. package/.backlog/tasks/task-4.13 - cli-fix-config-command-local-global-logic.md +0 -58
  67. package/.backlog/tasks/task-4.2 - cli-task-list-view.md +0 -25
  68. package/.backlog/tasks/task-4.3 - cli-task-edit.md +0 -24
  69. package/.backlog/tasks/task-4.4 - cli-task-archive-transition.md +0 -27
  70. package/.backlog/tasks/task-4.5 - cli-init-prompts-for-reporter-name-and-global-local-config.md +0 -28
  71. package/.backlog/tasks/task-4.6 - cli-add-empty-assignee-array-field-for-new-tasks.md +0 -35
  72. package/.backlog/tasks/task-4.7 - cli-parse-unquoted-created_date.md +0 -40
  73. package/.backlog/tasks/task-4.8 - cli-enforce-description-header.md +0 -48
  74. package/.backlog/tasks/task-4.9 - cli-normalize-task-id-inputs.md +0 -66
  75. package/.backlog/tasks/task-40 - cli-board-command-defaults-to-view.md +0 -38
  76. package/.backlog/tasks/task-41 - cli-migrate-terminal-ui-to-bblessed.md +0 -93
  77. package/.backlog/tasks/task-41.1 - cli-bblessed-init-wizard.md +0 -42
  78. package/.backlog/tasks/task-41.2 - cli-bblessed-task-view.md +0 -44
  79. package/.backlog/tasks/task-41.3 - cli-bblessed-doc-view.md +0 -45
  80. package/.backlog/tasks/task-41.4 - cli-bblessed-board-view.md +0 -49
  81. package/.backlog/tasks/task-41.5 - cli-audit-remaining-ui-for-bblessed.md +0 -55
  82. package/.backlog/tasks/task-42 - visual-hierarchy.md +0 -54
  83. package/.backlog/tasks/task-43 - remove-duplicate-acceptance-criteria-and-style-metadata.md +0 -56
  84. package/.backlog/tasks/task-44 - checklist-alignment.md +0 -24
  85. package/.backlog/tasks/task-45 - safe-line-wrapping.md +0 -23
  86. package/.backlog/tasks/task-46 - split-pane-layout.md +0 -24
  87. package/.backlog/tasks/task-47 - sticky-header-in-detail-view.md +0 -43
  88. package/.backlog/tasks/task-48 - footer-hint-line.md +0 -21
  89. package/.backlog/tasks/task-49 - status-styling.md +0 -53
  90. package/.backlog/tasks/task-5 - cli-docs-decisions.md +0 -57
  91. package/.backlog/tasks/task-50 - borders-&-padding.md +0 -22
  92. package/.backlog/tasks/task-51 - code-path-styling.md +0 -23
  93. package/.backlog/tasks/task-52 - cli-filter-tasks-list-by-status-or-assignee.md +0 -29
  94. package/.backlog/tasks/task-6 - cli-packaging.md +0 -65
  95. package/.backlog/tasks/task-6.1 - cli-local-installation-support-for-bunx-npx.md +0 -49
  96. package/.backlog/tasks/task-6.2 - cli-github-actions-for-build-&-publish.md +0 -64
  97. package/.backlog/tasks/task-7 - cli-kanban-view.md +0 -60
  98. package/.backlog/tasks/task-7.1 - cli-kanban-board-detect-remote-task-status.md +0 -62
  99. package/.backlog/tasks/task-8 - gui-project-setup.md +0 -21
  100. package/.backlog/tasks/task-9 - gui-task-crud.md +0 -24
  101. package/.cursorrules +0 -223
  102. package/.gitattributes +0 -2
  103. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -25
  104. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -15
  105. package/.github/PULL_REQUEST_TEMPLATE.md +0 -8
  106. package/.github/workflows/ci.yml +0 -36
  107. package/.husky/pre-commit +0 -1
  108. package/AGENTS.md +0 -65
  109. package/CLAUDE.md +0 -87
  110. package/CONTRIBUTING.md +0 -19
  111. package/DEVELOPMENT.md +0 -37
  112. package/biome.json +0 -31
  113. package/bun.lock +0 -152
  114. package/cli/.cursorrules-xh86jabm.md +0 -82
  115. package/cli/AGENTS-xh86jabm.md +0 -82
  116. package/cli/CLAUDE-xh86jabm.md +0 -82
  117. package/cli/cli.js +0 -19622
  118. package/cli/index.js +0 -2
  119. package/docs/npm-publishing.md +0 -69
  120. package/scripts/build.js +0 -73
  121. package/src/agent-instructions.ts +0 -54
  122. package/src/board.ts +0 -263
  123. package/src/cli.ts +0 -806
  124. package/src/constants/index.ts +0 -48
  125. package/src/core/backlog.ts +0 -183
  126. package/src/core/remote-tasks.ts +0 -168
  127. package/src/file-system/operations.ts +0 -515
  128. package/src/git/operations.ts +0 -189
  129. package/src/guidelines/.cursorrules.md +0 -82
  130. package/src/guidelines/AGENTS.md +0 -82
  131. package/src/guidelines/CLAUDE.md +0 -82
  132. package/src/guidelines/index.ts +0 -7
  133. package/src/index.ts +0 -30
  134. package/src/markdown/parser.ts +0 -145
  135. package/src/markdown/serializer.ts +0 -71
  136. package/src/test/agent-instructions.test.ts +0 -62
  137. package/src/test/board.test.ts +0 -291
  138. package/src/test/build.test.ts +0 -28
  139. package/src/test/checklist.test.ts +0 -273
  140. package/src/test/cli.test.ts +0 -1300
  141. package/src/test/code-path.test.ts +0 -204
  142. package/src/test/core.test.ts +0 -330
  143. package/src/test/filesystem.test.ts +0 -435
  144. package/src/test/git.test.ts +0 -26
  145. package/src/test/heading.test.ts +0 -102
  146. package/src/test/line-wrapping.test.ts +0 -252
  147. package/src/test/local-install.test.ts +0 -34
  148. package/src/test/markdown.test.ts +0 -526
  149. package/src/test/parallel-loading.test.ts +0 -160
  150. package/src/test/parent-id-normalization.test.ts +0 -48
  151. package/src/test/remote-id-conflict.test.ts +0 -60
  152. package/src/test/status-icon.test.ts +0 -93
  153. package/src/types/blessed.d.ts +0 -14
  154. package/src/types/index.ts +0 -55
  155. package/src/types/raw.d.ts +0 -4
  156. package/src/ui/board.ts +0 -322
  157. package/src/ui/checklist.ts +0 -103
  158. package/src/ui/code-path.ts +0 -113
  159. package/src/ui/heading.ts +0 -121
  160. package/src/ui/loading.ts +0 -216
  161. package/src/ui/status-icon.ts +0 -53
  162. package/src/ui/task-list.ts +0 -168
  163. package/src/ui/task-viewer.ts +0 -640
  164. package/src/ui/tui.ts +0 -301
  165. package/tsconfig.json +0 -26
@@ -1,82 +0,0 @@
1
- # AI Agent Guidelines
2
-
3
- *How to collaborate on Backlog.md–driven projects*
4
-
5
- ---
6
-
7
- ## 1. Source of Truth
8
- - Tasks live under **`.backlog/tasks/`** (drafts under **`.backlog/drafts/`**).
9
- - Every implementation decision starts with reading the corresponding Markdown task file.
10
-
11
- ## 2. Typical Workflow
12
-
13
- ```bash
14
- # 1 Identify work
15
- backlog task list --status "To Do"
16
-
17
- # 2 Read details
18
- backlog task view 42
19
-
20
- # 3 Start work: assign yourself & move column
21
- backlog task edit 42 -a @ai-bot -s "In Progress"
22
-
23
- # 4 Break work down if needed
24
- backlog task create "Refactor DB layer" --parent 42 -a @ai-bot
25
-
26
- # 5 Complete and mark Done
27
- backlog task edit 42 -s Done
28
- ```
29
-
30
- ## 3. Definition of Done (DOD)
31
-
32
- A task is **Done** only when **all** of the following hold:
33
-
34
- 1. **Acceptance criteria** checklist in the task file is fully checked.
35
- 2. **Automated tests** (unit + integration) cover new logic and CI passes.
36
- 3. **Static analysis**: linter & formatter succeed (when available).
37
- 4. **Documentation**:
38
- - Docs updated.
39
- - Task file appended with a `## Implementation Notes` section summarising approach, trade‑offs and follow‑ups.
40
- 5. **Review**: code reviewed.
41
- 6. **Task hygiene**: status set to **Done** via CLI.
42
- 7. **No regressions**: performance, security and licence checks green.
43
-
44
- ## 4. Recommended Task Anatomy
45
-
46
- ```markdown
47
- # task‑42 - Add GraphQL resolver
48
-
49
- ## Description
50
- Short, imperative explanation of the work.
51
-
52
- ## Acceptance Criteria
53
- - [ ] Resolver returns correct data for happy path
54
- - [ ] Error response matches REST
55
- - [ ] P95 latency ≤ 50 ms under 100 RPS
56
-
57
- ## Implementation Notes (only added after working on the task)
58
- *Created by @ai-bot on 2025‑06‑13*
59
-
60
- - Added `src/graphql/resolvers/user.ts`
61
- - Considered DataLoader but deferred
62
- - Follow‑up: integrate cache layer
63
- ```
64
-
65
- ## 5. Handy CLI Commands
66
-
67
- | Purpose | Command |
68
- |---------|---------|
69
- | Create task | `backlog task create "Add OAuth"` |
70
- | Create sub task | `backlog task create --parent 14 "Add Google auth"` |
71
- | List tasks | `backlog task list` |
72
- | View detail | `backlog task 7` |
73
- | Edit | `backlog task edit 7 -a @sara -l auth,backend` |
74
- | Archive | `backlog task archive 7` |
75
- | Draft flow | `backlog draft create "Spike GraphQL"` → `backlog draft promote 3.1` |
76
- | Demote to draft| `backlog task demote <id>` |
77
-
78
- ## 6. Tips for AI Agents
79
- - Keep tasks **small, atomic, and testable**; create subtasks liberally.
80
- - Prefer **idempotent** changes so reruns remain safe.
81
- - Leave **breadcrumbs** in `## Implementation Notes`; humans may continue your thread.
82
- - If uncertain, **draft a new task** describing the ambiguity rather than guessing.
@@ -1,82 +0,0 @@
1
- # AI Agent Guidelines
2
-
3
- *How to collaborate on Backlog.md–driven projects*
4
-
5
- ---
6
-
7
- ## 1. Source of Truth
8
- - Tasks live under **`.backlog/tasks/`** (drafts under **`.backlog/drafts/`**).
9
- - Every implementation decision starts with reading the corresponding Markdown task file.
10
-
11
- ## 2. Typical Workflow
12
-
13
- ```bash
14
- # 1 Identify work
15
- backlog task list --status "To Do"
16
-
17
- # 2 Read details
18
- backlog task view 42
19
-
20
- # 3 Start work: assign yourself & move column
21
- backlog task edit 42 -a @ai-bot -s "In Progress"
22
-
23
- # 4 Break work down if needed
24
- backlog task create "Refactor DB layer" --parent 42 -a @ai-bot
25
-
26
- # 5 Complete and mark Done
27
- backlog task edit 42 -s Done
28
- ```
29
-
30
- ## 3. Definition of Done (DOD)
31
-
32
- A task is **Done** only when **all** of the following hold:
33
-
34
- 1. **Acceptance criteria** checklist in the task file is fully checked.
35
- 2. **Automated tests** (unit + integration) cover new logic and CI passes.
36
- 3. **Static analysis**: linter & formatter succeed (when available).
37
- 4. **Documentation**:
38
- - Docs updated.
39
- - Task file appended with a `## Implementation Notes` section summarising approach, trade‑offs and follow‑ups.
40
- 5. **Review**: code reviewed.
41
- 6. **Task hygiene**: status set to **Done** via CLI.
42
- 7. **No regressions**: performance, security and licence checks green.
43
-
44
- ## 4. Recommended Task Anatomy
45
-
46
- ```markdown
47
- # task‑42 - Add GraphQL resolver
48
-
49
- ## Description
50
- Short, imperative explanation of the work.
51
-
52
- ## Acceptance Criteria
53
- - [ ] Resolver returns correct data for happy path
54
- - [ ] Error response matches REST
55
- - [ ] P95 latency ≤ 50 ms under 100 RPS
56
-
57
- ## Implementation Notes (only added after working on the task)
58
- *Created by @ai-bot on 2025‑06‑13*
59
-
60
- - Added `src/graphql/resolvers/user.ts`
61
- - Considered DataLoader but deferred
62
- - Follow‑up: integrate cache layer
63
- ```
64
-
65
- ## 5. Handy CLI Commands
66
-
67
- | Purpose | Command |
68
- |---------|---------|
69
- | Create task | `backlog task create "Add OAuth"` |
70
- | Create sub task | `backlog task create --parent 14 "Add Google auth"` |
71
- | List tasks | `backlog task list` |
72
- | View detail | `backlog task 7` |
73
- | Edit | `backlog task edit 7 -a @sara -l auth,backend` |
74
- | Archive | `backlog task archive 7` |
75
- | Draft flow | `backlog draft create "Spike GraphQL"` → `backlog draft promote 3.1` |
76
- | Demote to draft| `backlog task demote <id>` |
77
-
78
- ## 6. Tips for AI Agents
79
- - Keep tasks **small, atomic, and testable**; create subtasks liberally.
80
- - Prefer **idempotent** changes so reruns remain safe.
81
- - Leave **breadcrumbs** in `## Implementation Notes`; humans may continue your thread.
82
- - If uncertain, **draft a new task** describing the ambiguity rather than guessing.
@@ -1,82 +0,0 @@
1
- # AI Agent Guidelines
2
-
3
- *How to collaborate on Backlog.md–driven projects*
4
-
5
- ---
6
-
7
- ## 1. Source of Truth
8
- - Tasks live under **`.backlog/tasks/`** (drafts under **`.backlog/drafts/`**).
9
- - Every implementation decision starts with reading the corresponding Markdown task file.
10
-
11
- ## 2. Typical Workflow
12
-
13
- ```bash
14
- # 1 Identify work
15
- backlog task list --status "To Do"
16
-
17
- # 2 Read details
18
- backlog task view 42
19
-
20
- # 3 Start work: assign yourself & move column
21
- backlog task edit 42 -a @ai-bot -s "In Progress"
22
-
23
- # 4 Break work down if needed
24
- backlog task create "Refactor DB layer" --parent 42 -a @ai-bot
25
-
26
- # 5 Complete and mark Done
27
- backlog task edit 42 -s Done
28
- ```
29
-
30
- ## 3. Definition of Done (DOD)
31
-
32
- A task is **Done** only when **all** of the following hold:
33
-
34
- 1. **Acceptance criteria** checklist in the task file is fully checked.
35
- 2. **Automated tests** (unit + integration) cover new logic and CI passes.
36
- 3. **Static analysis**: linter & formatter succeed (when available).
37
- 4. **Documentation**:
38
- - Docs updated.
39
- - Task file appended with a `## Implementation Notes` section summarising approach, trade‑offs and follow‑ups.
40
- 5. **Review**: code reviewed.
41
- 6. **Task hygiene**: status set to **Done** via CLI.
42
- 7. **No regressions**: performance, security and licence checks green.
43
-
44
- ## 4. Recommended Task Anatomy
45
-
46
- ```markdown
47
- # task‑42 - Add GraphQL resolver
48
-
49
- ## Description
50
- Short, imperative explanation of the work.
51
-
52
- ## Acceptance Criteria
53
- - [ ] Resolver returns correct data for happy path
54
- - [ ] Error response matches REST
55
- - [ ] P95 latency ≤ 50 ms under 100 RPS
56
-
57
- ## Implementation Notes (only added after working on the task)
58
- *Created by @ai-bot on 2025‑06‑13*
59
-
60
- - Added `src/graphql/resolvers/user.ts`
61
- - Considered DataLoader but deferred
62
- - Follow‑up: integrate cache layer
63
- ```
64
-
65
- ## 5. Handy CLI Commands
66
-
67
- | Purpose | Command |
68
- |---------|---------|
69
- | Create task | `backlog task create "Add OAuth"` |
70
- | Create sub task | `backlog task create --parent 14 "Add Google auth"` |
71
- | List tasks | `backlog task list` |
72
- | View detail | `backlog task 7` |
73
- | Edit | `backlog task edit 7 -a @sara -l auth,backend` |
74
- | Archive | `backlog task archive 7` |
75
- | Draft flow | `backlog draft create "Spike GraphQL"` → `backlog draft promote 3.1` |
76
- | Demote to draft| `backlog task demote <id>` |
77
-
78
- ## 6. Tips for AI Agents
79
- - Keep tasks **small, atomic, and testable**; create subtasks liberally.
80
- - Prefer **idempotent** changes so reruns remain safe.
81
- - Leave **breadcrumbs** in `## Implementation Notes`; humans may continue your thread.
82
- - If uncertain, **draft a new task** describing the ambiguity rather than guessing.
@@ -1,7 +0,0 @@
1
- import CURSOR_GUIDELINES from "./.cursorrules.md";
2
- import AGENT_GUIDELINES from "./AGENTS.md";
3
- import CLAUDE_GUIDELINES from "./CLAUDE.md";
4
-
5
- const README_GUIDELINES = `## AI Agent Guidelines\n\n${AGENT_GUIDELINES.replace(/^#.*\n/, "")}`;
6
-
7
- export { AGENT_GUIDELINES, CLAUDE_GUIDELINES, CURSOR_GUIDELINES, README_GUIDELINES };
package/src/index.ts DELETED
@@ -1,30 +0,0 @@
1
- // Types
2
- export * from "./types/index.ts";
3
-
4
- // Constants
5
- export * from "./constants/index.ts";
6
-
7
- // Markdown operations
8
- export * from "./markdown/parser.ts";
9
- export * from "./markdown/serializer.ts";
10
-
11
- // File system operations
12
- export { FileSystem } from "./file-system/operations.ts";
13
-
14
- // Git operations
15
- export {
16
- GitOperations,
17
- isGitRepository,
18
- initializeGitRepository,
19
- } from "./git/operations.ts";
20
-
21
- // Core entry point
22
- export { Core } from "./core/backlog.ts";
23
-
24
- // Kanban board utilities
25
- export { generateKanbanBoard, exportKanbanBoardToFile } from "./board.ts";
26
- export {
27
- addAgentInstructions,
28
- type AgentInstructionFile,
29
- _loadAgentGuideline,
30
- } from "./agent-instructions.ts";
@@ -1,145 +0,0 @@
1
- import matter from "gray-matter";
2
- import type { DecisionLog, Document, ParsedMarkdown, Task } from "../types/index.ts";
3
-
4
- function preprocessFrontmatter(frontmatter: string): string {
5
- return frontmatter
6
- .split("\n")
7
- .map((line) => {
8
- // Handle both assignee and reporter fields that start with @
9
- const match = line.match(/^(\s*(?:assignee|reporter):\s*)(.*)$/);
10
- if (!match) return line;
11
-
12
- const [, prefix, raw] = match;
13
- const value = raw.trim();
14
-
15
- if (
16
- value &&
17
- !value.startsWith("[") &&
18
- !value.startsWith("'") &&
19
- !value.startsWith('"') &&
20
- !value.startsWith("-")
21
- ) {
22
- return `${prefix}"${value.replace(/"/g, '\\"')}"`;
23
- }
24
- return line;
25
- })
26
- .join("\n");
27
- }
28
-
29
- function normalizeDate(value: unknown): string {
30
- if (!value) return "";
31
- if (value instanceof Date) {
32
- return value.toISOString().slice(0, 10);
33
- }
34
- const str = String(value)
35
- .trim()
36
- .replace(/^['"]|['"]$/g, "");
37
- if (!str) return "";
38
- let match: RegExpMatchArray | null = str.match(/^(\d{4})-(\d{2})-(\d{2})$/);
39
- if (match) {
40
- return `${match[1]}-${match[2]}-${match[3]}`;
41
- }
42
- match = str.match(/^(\d{2})-(\d{2})-(\d{2})$/);
43
- if (match) {
44
- const [day, month, year] = match.slice(1);
45
- return `20${year}-${month}-${day}`;
46
- }
47
- match = str.match(/^(\d{2})\/(\d{2})\/(\d{2})$/);
48
- if (match) {
49
- const [day, month, year] = match.slice(1);
50
- return `20${year}-${month}-${day}`;
51
- }
52
- match = str.match(/^(\d{2})\.(\d{2})\.(\d{2})$/);
53
- if (match) {
54
- const [day, month, year] = match.slice(1);
55
- return `20${year}-${month}-${day}`;
56
- }
57
- return str;
58
- }
59
-
60
- export function parseMarkdown(content: string): ParsedMarkdown {
61
- const fmRegex = /^---\n([\s\S]*?)\n---/;
62
- const match = content.match(fmRegex);
63
- let toParse = content;
64
-
65
- if (match) {
66
- const processed = preprocessFrontmatter(match[1]);
67
- toParse = content.replace(fmRegex, `---\n${processed}\n---`);
68
- }
69
-
70
- const parsed = matter(toParse);
71
- return {
72
- frontmatter: parsed.data,
73
- content: parsed.content.trim(),
74
- };
75
- }
76
-
77
- export function parseTask(content: string): Task {
78
- const { frontmatter, content: description } = parseMarkdown(content);
79
-
80
- return {
81
- id: String(frontmatter.id || ""),
82
- title: String(frontmatter.title || ""),
83
- status: String(frontmatter.status || ""),
84
- assignee: Array.isArray(frontmatter.assignee)
85
- ? frontmatter.assignee.map(String)
86
- : frontmatter.assignee
87
- ? [String(frontmatter.assignee)]
88
- : [],
89
- reporter: frontmatter.reporter ? String(frontmatter.reporter) : undefined,
90
- createdDate: normalizeDate(frontmatter.created_date),
91
- updatedDate: frontmatter.updated_date ? normalizeDate(frontmatter.updated_date) : undefined,
92
- labels: Array.isArray(frontmatter.labels) ? frontmatter.labels.map(String) : [],
93
- milestone: frontmatter.milestone ? String(frontmatter.milestone) : undefined,
94
- dependencies: Array.isArray(frontmatter.dependencies) ? frontmatter.dependencies.map(String) : [],
95
- description: description,
96
- acceptanceCriteria: extractAcceptanceCriteria(description),
97
- parentTaskId: frontmatter.parent_task_id ? String(frontmatter.parent_task_id) : undefined,
98
- subtasks: Array.isArray(frontmatter.subtasks) ? frontmatter.subtasks.map(String) : undefined,
99
- };
100
- }
101
-
102
- export function parseDecisionLog(content: string): DecisionLog {
103
- const { frontmatter, content: body } = parseMarkdown(content);
104
-
105
- return {
106
- id: String(frontmatter.id || ""),
107
- title: String(frontmatter.title || ""),
108
- date: normalizeDate(frontmatter.date),
109
- status: String(frontmatter.status || "proposed") as DecisionLog["status"],
110
- context: extractSection(body, "Context") || "",
111
- decision: extractSection(body, "Decision") || "",
112
- consequences: extractSection(body, "Consequences") || "",
113
- alternatives: extractSection(body, "Alternatives"),
114
- };
115
- }
116
-
117
- export function parseDocument(content: string): Document {
118
- const { frontmatter, content: body } = parseMarkdown(content);
119
-
120
- return {
121
- id: String(frontmatter.id || ""),
122
- title: String(frontmatter.title || ""),
123
- type: String(frontmatter.type || "other") as Document["type"],
124
- createdDate: normalizeDate(frontmatter.created_date),
125
- updatedDate: frontmatter.updated_date ? normalizeDate(frontmatter.updated_date) : undefined,
126
- content: body,
127
- tags: Array.isArray(frontmatter.tags) ? frontmatter.tags.map(String) : undefined,
128
- };
129
- }
130
-
131
- function extractAcceptanceCriteria(content: string): string[] {
132
- const criteriaSection = extractSection(content, "Acceptance Criteria");
133
- if (!criteriaSection) return [];
134
-
135
- return criteriaSection
136
- .split("\n")
137
- .filter((line) => line.trim().startsWith("- [ ]") || line.trim().startsWith("- [x]"))
138
- .map((line) => line.trim().replace(/^- \[[ x]\] /, ""));
139
- }
140
-
141
- function extractSection(content: string, sectionTitle: string): string | undefined {
142
- const regex = new RegExp(`## ${sectionTitle}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`, "i");
143
- const match = content.match(regex);
144
- return match?.[1]?.trim();
145
- }
@@ -1,71 +0,0 @@
1
- import matter from "gray-matter";
2
- import type { DecisionLog, Document, Task } from "../types/index.ts";
3
-
4
- export function serializeTask(task: Task): string {
5
- const frontmatter = {
6
- id: task.id,
7
- title: task.title,
8
- status: task.status,
9
- assignee: task.assignee,
10
- ...(task.reporter && { reporter: task.reporter }),
11
- created_date: task.createdDate,
12
- ...(task.updatedDate && { updated_date: task.updatedDate }),
13
- labels: task.labels,
14
- ...(task.milestone && { milestone: task.milestone }),
15
- dependencies: task.dependencies,
16
- ...(task.parentTaskId && { parent_task_id: task.parentTaskId }),
17
- ...(task.subtasks && task.subtasks.length > 0 && { subtasks: task.subtasks }),
18
- };
19
-
20
- const serialized = matter.stringify(task.description, frontmatter);
21
- // Ensure there's a blank line between frontmatter and content
22
- return serialized.replace(/^(---\n(?:.*\n)*?---)\n(?!$)/, "$1\n\n");
23
- }
24
-
25
- export function serializeDecisionLog(decision: DecisionLog): string {
26
- const frontmatter = {
27
- id: decision.id,
28
- title: decision.title,
29
- date: decision.date,
30
- status: decision.status,
31
- };
32
-
33
- let content = `## Context\n\n${decision.context}\n\n`;
34
- content += `## Decision\n\n${decision.decision}\n\n`;
35
- content += `## Consequences\n\n${decision.consequences}`;
36
-
37
- if (decision.alternatives) {
38
- content += `\n\n## Alternatives\n\n${decision.alternatives}`;
39
- }
40
-
41
- return matter.stringify(content, frontmatter);
42
- }
43
-
44
- export function serializeDocument(document: Document): string {
45
- const frontmatter = {
46
- id: document.id,
47
- title: document.title,
48
- type: document.type,
49
- created_date: document.createdDate,
50
- ...(document.updatedDate && { updated_date: document.updatedDate }),
51
- ...(document.tags && document.tags.length > 0 && { tags: document.tags }),
52
- };
53
-
54
- return matter.stringify(document.content, frontmatter);
55
- }
56
-
57
- export function updateTaskAcceptanceCriteria(content: string, criteria: string[]): string {
58
- // Find if there's already an Acceptance Criteria section
59
- const criteriaRegex = /## Acceptance Criteria\s*\n([\s\S]*?)(?=\n## |$)/i;
60
- const match = content.match(criteriaRegex);
61
-
62
- const newCriteria = criteria.map((criterion) => `- [ ] ${criterion}`).join("\n");
63
- const newSection = `## Acceptance Criteria\n\n${newCriteria}`;
64
-
65
- if (match) {
66
- // Replace existing section
67
- return content.replace(criteriaRegex, newSection);
68
- }
69
- // Add new section at the end
70
- return `${content}\n\n${newSection}`;
71
- }
@@ -1,62 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
- import { mkdir, rm } from "node:fs/promises";
3
- import { join } from "node:path";
4
- import {
5
- AGENT_GUIDELINES,
6
- CLAUDE_GUIDELINES,
7
- CURSOR_GUIDELINES,
8
- README_GUIDELINES,
9
- addAgentInstructions,
10
- } from "../index.ts";
11
- import { _loadAgentGuideline } from "../index.ts";
12
-
13
- const TEST_DIR = join(process.cwd(), "test-agents");
14
-
15
- describe("addAgentInstructions", () => {
16
- beforeEach(async () => {
17
- await rm(TEST_DIR, { recursive: true, force: true });
18
- await mkdir(TEST_DIR, { recursive: true });
19
- });
20
-
21
- afterEach(async () => {
22
- await rm(TEST_DIR, { recursive: true, force: true });
23
- });
24
-
25
- it("creates guideline files when none exist", async () => {
26
- await addAgentInstructions(TEST_DIR);
27
- const agents = await Bun.file(join(TEST_DIR, "AGENTS.md")).text();
28
- const claude = await Bun.file(join(TEST_DIR, "CLAUDE.md")).text();
29
- const cursor = await Bun.file(join(TEST_DIR, ".cursorrules")).text();
30
- expect(agents).toBe(await _loadAgentGuideline(AGENT_GUIDELINES));
31
- expect(claude).toBe(await _loadAgentGuideline(CLAUDE_GUIDELINES));
32
- expect(cursor).toBe(await _loadAgentGuideline(CURSOR_GUIDELINES));
33
- });
34
-
35
- it("appends guideline files when they already exist", async () => {
36
- await Bun.write(join(TEST_DIR, "AGENTS.md"), "Existing\n");
37
- await addAgentInstructions(TEST_DIR);
38
- const agents = await Bun.file(join(TEST_DIR, "AGENTS.md")).text();
39
- expect(agents.startsWith("Existing\n")).toBe(true);
40
- expect(agents.trimEnd()).toBe(`Existing\n${await _loadAgentGuideline(AGENT_GUIDELINES)}`.trimEnd());
41
- });
42
-
43
- it("creates only selected files", async () => {
44
- await addAgentInstructions(TEST_DIR, undefined, ["AGENTS.md", "readme.md"]);
45
-
46
- const agentsExists = await Bun.file(join(TEST_DIR, "AGENTS.md")).exists();
47
- const claudeExists = await Bun.file(join(TEST_DIR, "CLAUDE.md")).exists();
48
- const cursorExists = await Bun.file(join(TEST_DIR, ".cursorrules")).exists();
49
- const readme = await Bun.file(join(TEST_DIR, "readme.md")).text();
50
-
51
- expect(agentsExists).toBe(true);
52
- expect(claudeExists).toBe(false);
53
- expect(cursorExists).toBe(false);
54
- expect(readme.trim()).toBe((await _loadAgentGuideline(README_GUIDELINES)).trim());
55
- });
56
-
57
- it("loads guideline content from file paths", async () => {
58
- const pathGuideline = join(__dirname, "../guidelines/AGENTS.md");
59
- const content = await _loadAgentGuideline(pathGuideline);
60
- expect(content).toContain("AI Agent Guidelines");
61
- });
62
- });