@coralai/sps-cli 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 (145) hide show
  1. package/dist/commands/cardAdd.d.ts +2 -0
  2. package/dist/commands/cardAdd.d.ts.map +1 -0
  3. package/dist/commands/cardAdd.js +65 -0
  4. package/dist/commands/cardAdd.js.map +1 -0
  5. package/dist/commands/doctor.d.ts +9 -0
  6. package/dist/commands/doctor.d.ts.map +1 -0
  7. package/dist/commands/doctor.js +264 -0
  8. package/dist/commands/doctor.js.map +1 -0
  9. package/dist/commands/monitorTick.d.ts +2 -0
  10. package/dist/commands/monitorTick.d.ts.map +1 -0
  11. package/dist/commands/monitorTick.js +47 -0
  12. package/dist/commands/monitorTick.js.map +1 -0
  13. package/dist/commands/pipelineTick.d.ts +2 -0
  14. package/dist/commands/pipelineTick.d.ts.map +1 -0
  15. package/dist/commands/pipelineTick.js +44 -0
  16. package/dist/commands/pipelineTick.js.map +1 -0
  17. package/dist/commands/pmCommand.d.ts +2 -0
  18. package/dist/commands/pmCommand.d.ts.map +1 -0
  19. package/dist/commands/pmCommand.js +159 -0
  20. package/dist/commands/pmCommand.js.map +1 -0
  21. package/dist/commands/projectInit.d.ts +2 -0
  22. package/dist/commands/projectInit.d.ts.map +1 -0
  23. package/dist/commands/projectInit.js +75 -0
  24. package/dist/commands/projectInit.js.map +1 -0
  25. package/dist/commands/qaTick.d.ts +2 -0
  26. package/dist/commands/qaTick.d.ts.map +1 -0
  27. package/dist/commands/qaTick.js +43 -0
  28. package/dist/commands/qaTick.js.map +1 -0
  29. package/dist/commands/schedulerTick.d.ts +2 -0
  30. package/dist/commands/schedulerTick.d.ts.map +1 -0
  31. package/dist/commands/schedulerTick.js +45 -0
  32. package/dist/commands/schedulerTick.js.map +1 -0
  33. package/dist/commands/tick.d.ts +14 -0
  34. package/dist/commands/tick.d.ts.map +1 -0
  35. package/dist/commands/tick.js +251 -0
  36. package/dist/commands/tick.js.map +1 -0
  37. package/dist/commands/workerLaunch.d.ts +2 -0
  38. package/dist/commands/workerLaunch.d.ts.map +1 -0
  39. package/dist/commands/workerLaunch.js +56 -0
  40. package/dist/commands/workerLaunch.js.map +1 -0
  41. package/dist/core/config.d.ts +38 -0
  42. package/dist/core/config.d.ts.map +1 -0
  43. package/dist/core/config.js +131 -0
  44. package/dist/core/config.js.map +1 -0
  45. package/dist/core/context.d.ts +23 -0
  46. package/dist/core/context.d.ts.map +1 -0
  47. package/dist/core/context.js +28 -0
  48. package/dist/core/context.js.map +1 -0
  49. package/dist/core/lock.d.ts +14 -0
  50. package/dist/core/lock.d.ts.map +1 -0
  51. package/dist/core/lock.js +65 -0
  52. package/dist/core/lock.js.map +1 -0
  53. package/dist/core/logger.d.ts +24 -0
  54. package/dist/core/logger.d.ts.map +1 -0
  55. package/dist/core/logger.js +62 -0
  56. package/dist/core/logger.js.map +1 -0
  57. package/dist/core/paths.d.ts +27 -0
  58. package/dist/core/paths.d.ts.map +1 -0
  59. package/dist/core/paths.js +29 -0
  60. package/dist/core/paths.js.map +1 -0
  61. package/dist/core/queue.d.ts +14 -0
  62. package/dist/core/queue.d.ts.map +1 -0
  63. package/dist/core/queue.js +38 -0
  64. package/dist/core/queue.js.map +1 -0
  65. package/dist/core/state.d.ts +32 -0
  66. package/dist/core/state.d.ts.map +1 -0
  67. package/dist/core/state.js +52 -0
  68. package/dist/core/state.js.map +1 -0
  69. package/dist/engines/CloseoutEngine.d.ts +60 -0
  70. package/dist/engines/CloseoutEngine.d.ts.map +1 -0
  71. package/dist/engines/CloseoutEngine.js +596 -0
  72. package/dist/engines/CloseoutEngine.js.map +1 -0
  73. package/dist/engines/ExecutionEngine.d.ts +65 -0
  74. package/dist/engines/ExecutionEngine.d.ts.map +1 -0
  75. package/dist/engines/ExecutionEngine.js +603 -0
  76. package/dist/engines/ExecutionEngine.js.map +1 -0
  77. package/dist/engines/MonitorEngine.d.ts +39 -0
  78. package/dist/engines/MonitorEngine.d.ts.map +1 -0
  79. package/dist/engines/MonitorEngine.js +473 -0
  80. package/dist/engines/MonitorEngine.js.map +1 -0
  81. package/dist/engines/SchedulerEngine.d.ts +24 -0
  82. package/dist/engines/SchedulerEngine.d.ts.map +1 -0
  83. package/dist/engines/SchedulerEngine.js +195 -0
  84. package/dist/engines/SchedulerEngine.js.map +1 -0
  85. package/dist/interfaces/HookProvider.d.ts +9 -0
  86. package/dist/interfaces/HookProvider.d.ts.map +1 -0
  87. package/dist/interfaces/HookProvider.js +2 -0
  88. package/dist/interfaces/HookProvider.js.map +1 -0
  89. package/dist/interfaces/Notifier.d.ts +11 -0
  90. package/dist/interfaces/Notifier.d.ts.map +1 -0
  91. package/dist/interfaces/Notifier.js +2 -0
  92. package/dist/interfaces/Notifier.js.map +1 -0
  93. package/dist/interfaces/RepoBackend.d.ts +23 -0
  94. package/dist/interfaces/RepoBackend.d.ts.map +1 -0
  95. package/dist/interfaces/RepoBackend.js +2 -0
  96. package/dist/interfaces/RepoBackend.js.map +1 -0
  97. package/dist/interfaces/TaskBackend.d.ts +24 -0
  98. package/dist/interfaces/TaskBackend.d.ts.map +1 -0
  99. package/dist/interfaces/TaskBackend.js +2 -0
  100. package/dist/interfaces/TaskBackend.js.map +1 -0
  101. package/dist/interfaces/WorkerProvider.d.ts +23 -0
  102. package/dist/interfaces/WorkerProvider.d.ts.map +1 -0
  103. package/dist/interfaces/WorkerProvider.js +2 -0
  104. package/dist/interfaces/WorkerProvider.js.map +1 -0
  105. package/dist/main.d.ts +3 -0
  106. package/dist/main.d.ts.map +1 -0
  107. package/dist/main.js +226 -0
  108. package/dist/main.js.map +1 -0
  109. package/dist/models/types.d.ts +68 -0
  110. package/dist/models/types.d.ts.map +1 -0
  111. package/dist/models/types.js +2 -0
  112. package/dist/models/types.js.map +1 -0
  113. package/dist/providers/ClaudeWorkerProvider.d.ts +84 -0
  114. package/dist/providers/ClaudeWorkerProvider.d.ts.map +1 -0
  115. package/dist/providers/ClaudeWorkerProvider.js +293 -0
  116. package/dist/providers/ClaudeWorkerProvider.js.map +1 -0
  117. package/dist/providers/CodexWorkerProvider.d.ts +50 -0
  118. package/dist/providers/CodexWorkerProvider.d.ts.map +1 -0
  119. package/dist/providers/CodexWorkerProvider.js +275 -0
  120. package/dist/providers/CodexWorkerProvider.js.map +1 -0
  121. package/dist/providers/GitLabRepoBackend.d.ts +42 -0
  122. package/dist/providers/GitLabRepoBackend.d.ts.map +1 -0
  123. package/dist/providers/GitLabRepoBackend.js +280 -0
  124. package/dist/providers/GitLabRepoBackend.js.map +1 -0
  125. package/dist/providers/MarkdownTaskBackend.d.ts +88 -0
  126. package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -0
  127. package/dist/providers/MarkdownTaskBackend.js +414 -0
  128. package/dist/providers/MarkdownTaskBackend.js.map +1 -0
  129. package/dist/providers/MatrixNotifier.d.ts +30 -0
  130. package/dist/providers/MatrixNotifier.d.ts.map +1 -0
  131. package/dist/providers/MatrixNotifier.js +82 -0
  132. package/dist/providers/MatrixNotifier.js.map +1 -0
  133. package/dist/providers/PlaneTaskBackend.d.ts +86 -0
  134. package/dist/providers/PlaneTaskBackend.d.ts.map +1 -0
  135. package/dist/providers/PlaneTaskBackend.js +409 -0
  136. package/dist/providers/PlaneTaskBackend.js.map +1 -0
  137. package/dist/providers/TrelloTaskBackend.d.ts +53 -0
  138. package/dist/providers/TrelloTaskBackend.d.ts.map +1 -0
  139. package/dist/providers/TrelloTaskBackend.js +300 -0
  140. package/dist/providers/TrelloTaskBackend.js.map +1 -0
  141. package/dist/providers/registry.d.ts +10 -0
  142. package/dist/providers/registry.d.ts.map +1 -0
  143. package/dist/providers/registry.js +29 -0
  144. package/dist/providers/registry.js.map +1 -0
  145. package/package.json +36 -0
@@ -0,0 +1,88 @@
1
+ import type { ProjectConfig } from '../core/config.js';
2
+ import type { TaskBackend } from '../interfaces/TaskBackend.js';
3
+ import type { Card, CardState } from '../models/types.js';
4
+ /**
5
+ * Markdown-based TaskBackend.
6
+ *
7
+ * Directory layout:
8
+ * cards/
9
+ * ├── planning/
10
+ * │ └── 3-build-dashboard.md
11
+ * ├── todo/
12
+ * │ └── 2-add-payment.md
13
+ * ├── inprogress/
14
+ * │ └── 1-implement-login.md
15
+ * ├── done/
16
+ * │ └── 0-setup.md
17
+ * └── seq.txt ← current max sequence number
18
+ *
19
+ * Each card file uses YAML frontmatter for metadata + markdown body.
20
+ */
21
+ export declare class MarkdownTaskBackend implements TaskBackend {
22
+ private readonly cardsDir;
23
+ private readonly seqFile;
24
+ constructor(config: ProjectConfig);
25
+ bootstrap(): Promise<void>;
26
+ listByState(state: CardState): Promise<Card[]>;
27
+ getBySeq(seq: string): Promise<Card | null>;
28
+ move(seq: string, targetState: CardState): Promise<void>;
29
+ addLabel(seq: string, label: string): Promise<void>;
30
+ removeLabel(seq: string, label: string): Promise<void>;
31
+ claim(seq: string, workerSlot: string): Promise<void>;
32
+ releaseClaim(seq: string): Promise<void>;
33
+ comment(seq: string, text: string): Promise<void>;
34
+ create(name: string, desc: string, state: CardState): Promise<Card>;
35
+ checklistCreate(seq: string, items: string[]): Promise<void>;
36
+ checklistList(seq: string): Promise<{
37
+ id: string;
38
+ text: string;
39
+ checked: boolean;
40
+ }[]>;
41
+ checklistCheck(seq: string, itemId: string): Promise<void>;
42
+ checklistUncheck(seq: string, itemId: string): Promise<void>;
43
+ private toggleChecklistItem;
44
+ metaRead(seq: string): Promise<Record<string, unknown>>;
45
+ metaWrite(seq: string, data: Record<string, unknown>): Promise<void>;
46
+ /**
47
+ * Find the card file by seq across all state directories.
48
+ */
49
+ private findCardFile;
50
+ /**
51
+ * Read a card file and return Card object.
52
+ */
53
+ private readCard;
54
+ /**
55
+ * Parse a markdown file into frontmatter + body.
56
+ */
57
+ private parseFile;
58
+ /**
59
+ * Write frontmatter + body back to file.
60
+ */
61
+ private writeFile;
62
+ /**
63
+ * Simple YAML parser (handles: strings, numbers, null, arrays of strings).
64
+ * Not a full YAML parser — covers our frontmatter needs.
65
+ */
66
+ private parseYamlSimple;
67
+ /**
68
+ * Simple YAML serializer.
69
+ */
70
+ private serializeYamlSimple;
71
+ /**
72
+ * Extract content from a ## section (until next ## or end).
73
+ */
74
+ private extractSection;
75
+ /**
76
+ * Replace content of a ## section.
77
+ */
78
+ private replaceSection;
79
+ /**
80
+ * Parse checklist items from markdown body.
81
+ */
82
+ private parseChecklist;
83
+ /**
84
+ * Get next sequence number (atomic increment).
85
+ */
86
+ private nextSeq;
87
+ }
88
+ //# sourceMappingURL=MarkdownTaskBackend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownTaskBackend.d.ts","sourceRoot":"","sources":["../../src/providers/MarkdownTaskBackend.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAoB1D;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,mBAAoB,YAAW,WAAW;IACrD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAM3B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAY1B,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAO9C,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAY3C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWnD,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASrD,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBjD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCnE,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;IAMrF,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1D,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAIpD,mBAAmB;IAgB3B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAMvD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1E;;OAEG;IACH,OAAO,CAAC,YAAY;IAUpB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAchB;;OAEG;IACH,OAAO,CAAC,SAAS;IAYjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAMjB;;;OAGG;IACH,OAAO,CAAC,eAAe;IA6DvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0B3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAMtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,OAAO;CAWhB"}
@@ -0,0 +1,414 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync, readdirSync, } from 'node:fs';
2
+ import { resolve, basename } from 'node:path';
3
+ const ALL_STATES = ['Planning', 'Backlog', 'Todo', 'Inprogress', 'QA', 'Done'];
4
+ /** Map CardState to directory name (lowercase for filesystem friendliness). */
5
+ const STATE_DIR = {
6
+ Planning: 'planning',
7
+ Backlog: 'backlog',
8
+ Todo: 'todo',
9
+ Inprogress: 'inprogress',
10
+ QA: 'qa',
11
+ Done: 'done',
12
+ };
13
+ /** Reverse map: directory name → CardState. */
14
+ const DIR_STATE = {};
15
+ for (const [state, dir] of Object.entries(STATE_DIR)) {
16
+ DIR_STATE[dir] = state;
17
+ }
18
+ /**
19
+ * Markdown-based TaskBackend.
20
+ *
21
+ * Directory layout:
22
+ * cards/
23
+ * ├── planning/
24
+ * │ └── 3-build-dashboard.md
25
+ * ├── todo/
26
+ * │ └── 2-add-payment.md
27
+ * ├── inprogress/
28
+ * │ └── 1-implement-login.md
29
+ * ├── done/
30
+ * │ └── 0-setup.md
31
+ * └── seq.txt ← current max sequence number
32
+ *
33
+ * Each card file uses YAML frontmatter for metadata + markdown body.
34
+ */
35
+ export class MarkdownTaskBackend {
36
+ cardsDir;
37
+ seqFile;
38
+ constructor(config) {
39
+ const home = process.env.HOME || '/home/coral';
40
+ this.cardsDir = resolve(home, '.projects', config.PROJECT_NAME, 'cards');
41
+ this.seqFile = resolve(this.cardsDir, 'seq.txt');
42
+ }
43
+ async bootstrap() {
44
+ for (const dir of Object.values(STATE_DIR)) {
45
+ const path = resolve(this.cardsDir, dir);
46
+ if (!existsSync(path))
47
+ mkdirSync(path, { recursive: true });
48
+ }
49
+ if (!existsSync(this.seqFile)) {
50
+ writeFileSync(this.seqFile, '0\n');
51
+ }
52
+ }
53
+ // ─── Query ─────────────────────────────────────────────────────
54
+ async listByState(state) {
55
+ const dir = resolve(this.cardsDir, STATE_DIR[state]);
56
+ if (!existsSync(dir))
57
+ return [];
58
+ const files = readdirSync(dir).filter((f) => f.endsWith('.md')).sort();
59
+ return files.map((f) => this.readCard(resolve(dir, f), state));
60
+ }
61
+ async getBySeq(seq) {
62
+ for (const state of ALL_STATES) {
63
+ const dir = resolve(this.cardsDir, STATE_DIR[state]);
64
+ if (!existsSync(dir))
65
+ continue;
66
+ const file = readdirSync(dir).find((f) => f.startsWith(`${seq}-`));
67
+ if (file)
68
+ return this.readCard(resolve(dir, file), state);
69
+ }
70
+ return null;
71
+ }
72
+ // ─── State transitions ────────────────────────────────────────
73
+ async move(seq, targetState) {
74
+ const { filePath, currentState } = this.findCardFile(seq);
75
+ if (currentState === targetState)
76
+ return;
77
+ const targetDir = resolve(this.cardsDir, STATE_DIR[targetState]);
78
+ if (!existsSync(targetDir))
79
+ mkdirSync(targetDir, { recursive: true });
80
+ const targetPath = resolve(targetDir, basename(filePath));
81
+ renameSync(filePath, targetPath);
82
+ }
83
+ // ─── Labels ───────────────────────────────────────────────────
84
+ async addLabel(seq, label) {
85
+ const { filePath } = this.findCardFile(seq);
86
+ const { frontmatter, body } = this.parseFile(filePath);
87
+ const labels = frontmatter.labels || [];
88
+ if (!labels.includes(label)) {
89
+ labels.push(label);
90
+ frontmatter.labels = labels;
91
+ this.writeFile(filePath, frontmatter, body);
92
+ }
93
+ }
94
+ async removeLabel(seq, label) {
95
+ const { filePath } = this.findCardFile(seq);
96
+ const { frontmatter, body } = this.parseFile(filePath);
97
+ const labels = frontmatter.labels || [];
98
+ const filtered = labels.filter((l) => l !== label);
99
+ if (filtered.length !== labels.length) {
100
+ frontmatter.labels = filtered;
101
+ this.writeFile(filePath, frontmatter, body);
102
+ }
103
+ }
104
+ // ─── Claim ────────────────────────────────────────────────────
105
+ async claim(seq, workerSlot) {
106
+ const { filePath } = this.findCardFile(seq);
107
+ const { frontmatter, body } = this.parseFile(filePath);
108
+ frontmatter.claimed_by = workerSlot;
109
+ frontmatter.claimed_at = new Date().toISOString();
110
+ this.writeFile(filePath, frontmatter, body);
111
+ await this.addLabel(seq, 'CLAIMED');
112
+ }
113
+ async releaseClaim(seq) {
114
+ const { filePath } = this.findCardFile(seq);
115
+ const { frontmatter, body } = this.parseFile(filePath);
116
+ frontmatter.claimed_by = null;
117
+ frontmatter.claimed_at = null;
118
+ this.writeFile(filePath, frontmatter, body);
119
+ await this.removeLabel(seq, 'CLAIMED');
120
+ }
121
+ // ─── Comments (append to ## 日志 section) ─────────────────────
122
+ async comment(seq, text) {
123
+ const { filePath } = this.findCardFile(seq);
124
+ const { frontmatter, body } = this.parseFile(filePath);
125
+ const ts = new Date().toISOString().slice(0, 19).replace('T', ' ');
126
+ const entry = `\n### ${ts} [pipeline]\n${text}\n`;
127
+ // Find or create ## 日志 section
128
+ const logHeader = '## 日志';
129
+ let newBody;
130
+ if (body.includes(logHeader)) {
131
+ newBody = body + entry;
132
+ }
133
+ else {
134
+ newBody = body + `\n${logHeader}\n${entry}`;
135
+ }
136
+ this.writeFile(filePath, frontmatter, newBody);
137
+ }
138
+ // ─── Create ───────────────────────────────────────────────────
139
+ async create(name, desc, state) {
140
+ const seq = this.nextSeq();
141
+ const slug = name
142
+ .toLowerCase()
143
+ .replace(/[^a-z0-9\u4e00-\u9fff]+/g, '-')
144
+ .replace(/^-|-$/g, '')
145
+ .slice(0, 40);
146
+ const filename = `${seq}-${slug || 'task'}.md`;
147
+ const dir = resolve(this.cardsDir, STATE_DIR[state]);
148
+ if (!existsSync(dir))
149
+ mkdirSync(dir, { recursive: true });
150
+ const frontmatter = {
151
+ seq,
152
+ name,
153
+ labels: [],
154
+ created: new Date().toISOString(),
155
+ claimed_by: null,
156
+ claimed_at: null,
157
+ };
158
+ const body = `## 描述\n\n${desc || '(无描述)'}\n\n## 检查清单\n\n## 日志\n`;
159
+ const filePath = resolve(dir, filename);
160
+ this.writeFile(filePath, frontmatter, body);
161
+ return {
162
+ id: `md-${seq}`,
163
+ seq: String(seq),
164
+ name,
165
+ desc: desc || '',
166
+ state,
167
+ labels: [],
168
+ meta: {},
169
+ };
170
+ }
171
+ // ─── Checklist ────────────────────────────────────────────────
172
+ async checklistCreate(seq, items) {
173
+ const { filePath } = this.findCardFile(seq);
174
+ const { frontmatter, body } = this.parseFile(filePath);
175
+ const checklistMd = items.map((item) => `- [ ] ${item}`).join('\n');
176
+ // Replace content after ## 检查清单 and before next ## heading
177
+ const newBody = this.replaceSection(body, '检查清单', checklistMd);
178
+ this.writeFile(filePath, frontmatter, newBody);
179
+ }
180
+ async checklistList(seq) {
181
+ const { filePath } = this.findCardFile(seq);
182
+ const { body } = this.parseFile(filePath);
183
+ return this.parseChecklist(body);
184
+ }
185
+ async checklistCheck(seq, itemId) {
186
+ await this.toggleChecklistItem(seq, parseInt(itemId, 10), true);
187
+ }
188
+ async checklistUncheck(seq, itemId) {
189
+ await this.toggleChecklistItem(seq, parseInt(itemId, 10), false);
190
+ }
191
+ async toggleChecklistItem(seq, index, checked) {
192
+ const { filePath } = this.findCardFile(seq);
193
+ const { frontmatter, body } = this.parseFile(filePath);
194
+ const re = /- \[([ xX])\] (.+)/g;
195
+ let count = 0;
196
+ const newBody = body.replace(re, (match, mark, text) => {
197
+ if (count++ === index) {
198
+ return `- [${checked ? 'x' : ' '}] ${text}`;
199
+ }
200
+ return match;
201
+ });
202
+ this.writeFile(filePath, frontmatter, newBody);
203
+ }
204
+ // ─── Meta ─────────────────────────────────────────────────────
205
+ async metaRead(seq) {
206
+ const { filePath } = this.findCardFile(seq);
207
+ const { frontmatter } = this.parseFile(filePath);
208
+ return frontmatter.meta || {};
209
+ }
210
+ async metaWrite(seq, data) {
211
+ const { filePath } = this.findCardFile(seq);
212
+ const { frontmatter, body } = this.parseFile(filePath);
213
+ frontmatter.meta = data;
214
+ this.writeFile(filePath, frontmatter, body);
215
+ }
216
+ // ─── File helpers ─────────────────────────────────────────────
217
+ /**
218
+ * Find the card file by seq across all state directories.
219
+ */
220
+ findCardFile(seq) {
221
+ for (const state of ALL_STATES) {
222
+ const dir = resolve(this.cardsDir, STATE_DIR[state]);
223
+ if (!existsSync(dir))
224
+ continue;
225
+ const file = readdirSync(dir).find((f) => f.startsWith(`${seq}-`) && f.endsWith('.md'));
226
+ if (file)
227
+ return { filePath: resolve(dir, file), currentState: state };
228
+ }
229
+ throw new Error(`Card seq:${seq} not found in cards/`);
230
+ }
231
+ /**
232
+ * Read a card file and return Card object.
233
+ */
234
+ readCard(filePath, state) {
235
+ const { frontmatter, body } = this.parseFile(filePath);
236
+ const desc = this.extractSection(body, '描述');
237
+ return {
238
+ id: `md-${frontmatter.seq}`,
239
+ seq: String(frontmatter.seq),
240
+ name: String(frontmatter.name || ''),
241
+ desc,
242
+ state,
243
+ labels: frontmatter.labels || [],
244
+ meta: frontmatter.meta || {},
245
+ };
246
+ }
247
+ /**
248
+ * Parse a markdown file into frontmatter + body.
249
+ */
250
+ parseFile(filePath) {
251
+ const content = readFileSync(filePath, 'utf-8');
252
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
253
+ if (!fmMatch) {
254
+ return { frontmatter: {}, body: content };
255
+ }
256
+ return {
257
+ frontmatter: this.parseYamlSimple(fmMatch[1]),
258
+ body: fmMatch[2],
259
+ };
260
+ }
261
+ /**
262
+ * Write frontmatter + body back to file.
263
+ */
264
+ writeFile(filePath, frontmatter, body) {
265
+ const yamlStr = this.serializeYamlSimple(frontmatter);
266
+ const content = `---\n${yamlStr}\n---\n${body}`;
267
+ writeFileSync(filePath, content);
268
+ }
269
+ /**
270
+ * Simple YAML parser (handles: strings, numbers, null, arrays of strings).
271
+ * Not a full YAML parser — covers our frontmatter needs.
272
+ */
273
+ parseYamlSimple(yaml) {
274
+ const result = {};
275
+ let currentKey = '';
276
+ let currentArray = null;
277
+ for (const line of yaml.split('\n')) {
278
+ const trimmed = line.trim();
279
+ // Array item
280
+ if (trimmed.startsWith('- ') && currentArray !== null) {
281
+ currentArray.push(trimmed.slice(2).trim());
282
+ continue;
283
+ }
284
+ // Save previous array
285
+ if (currentArray !== null) {
286
+ result[currentKey] = currentArray;
287
+ currentArray = null;
288
+ }
289
+ // Key: value
290
+ const kvMatch = trimmed.match(/^([a-z_]+):\s*(.*)$/);
291
+ if (!kvMatch)
292
+ continue;
293
+ const [, key, rawVal] = kvMatch;
294
+ const val = rawVal.trim();
295
+ if (val === '' || val === '[]') {
296
+ // Could be empty value or start of array
297
+ // Peek: if next line starts with " -", it's an array
298
+ currentKey = key;
299
+ currentArray = [];
300
+ continue;
301
+ }
302
+ if (val === 'null' || val === '~') {
303
+ result[key] = null;
304
+ }
305
+ else if (val === 'true') {
306
+ result[key] = true;
307
+ }
308
+ else if (val === 'false') {
309
+ result[key] = false;
310
+ }
311
+ else if (/^-?\d+$/.test(val)) {
312
+ result[key] = parseInt(val, 10);
313
+ }
314
+ else if (/^\[.*\]$/.test(val)) {
315
+ // Inline array: [a, b, c]
316
+ result[key] = val.slice(1, -1).split(',').map((s) => s.trim()).filter(Boolean);
317
+ }
318
+ else {
319
+ // String (strip quotes if present)
320
+ result[key] = val.replace(/^["']|["']$/g, '');
321
+ }
322
+ currentKey = key;
323
+ }
324
+ // Flush last array
325
+ if (currentArray !== null) {
326
+ result[currentKey] = currentArray;
327
+ }
328
+ return result;
329
+ }
330
+ /**
331
+ * Simple YAML serializer.
332
+ */
333
+ serializeYamlSimple(obj) {
334
+ const lines = [];
335
+ for (const [key, val] of Object.entries(obj)) {
336
+ if (val === null || val === undefined) {
337
+ lines.push(`${key}: null`);
338
+ }
339
+ else if (typeof val === 'boolean' || typeof val === 'number') {
340
+ lines.push(`${key}: ${val}`);
341
+ }
342
+ else if (typeof val === 'string') {
343
+ lines.push(`${key}: ${val}`);
344
+ }
345
+ else if (Array.isArray(val)) {
346
+ if (val.length === 0) {
347
+ lines.push(`${key}:`);
348
+ }
349
+ else {
350
+ lines.push(`${key}:`);
351
+ for (const item of val) {
352
+ lines.push(` - ${item}`);
353
+ }
354
+ }
355
+ }
356
+ else if (typeof val === 'object') {
357
+ // Nested object → serialize as inline JSON for simplicity
358
+ lines.push(`${key}: ${JSON.stringify(val)}`);
359
+ }
360
+ }
361
+ return lines.join('\n');
362
+ }
363
+ /**
364
+ * Extract content from a ## section (until next ## or end).
365
+ */
366
+ extractSection(body, heading) {
367
+ const re = new RegExp(`## ${heading}\\n([\\s\\S]*?)(?=\\n## |$)`);
368
+ const match = body.match(re);
369
+ return match ? match[1].trim() : '';
370
+ }
371
+ /**
372
+ * Replace content of a ## section.
373
+ */
374
+ replaceSection(body, heading, content) {
375
+ const re = new RegExp(`(## ${heading}\\n)[\\s\\S]*?(?=\\n## |$)`);
376
+ if (re.test(body)) {
377
+ return body.replace(re, `$1\n${content}\n`);
378
+ }
379
+ return body + `\n## ${heading}\n\n${content}\n`;
380
+ }
381
+ /**
382
+ * Parse checklist items from markdown body.
383
+ */
384
+ parseChecklist(body) {
385
+ const items = [];
386
+ const re = /- \[([ xX])\] (.+)/g;
387
+ let m;
388
+ let idx = 0;
389
+ while ((m = re.exec(body)) !== null) {
390
+ items.push({
391
+ id: String(idx++),
392
+ text: m[2].trim(),
393
+ checked: m[1] !== ' ',
394
+ });
395
+ }
396
+ return items;
397
+ }
398
+ /**
399
+ * Get next sequence number (atomic increment).
400
+ */
401
+ nextSeq() {
402
+ let current = 0;
403
+ if (existsSync(this.seqFile)) {
404
+ try {
405
+ current = parseInt(readFileSync(this.seqFile, 'utf-8').trim(), 10) || 0;
406
+ }
407
+ catch { /* start from 0 */ }
408
+ }
409
+ const next = current + 1;
410
+ writeFileSync(this.seqFile, `${next}\n`);
411
+ return next;
412
+ }
413
+ }
414
+ //# sourceMappingURL=MarkdownTaskBackend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MarkdownTaskBackend.js","sourceRoot":"","sources":["../../src/providers/MarkdownTaskBackend.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ProjectConfig } from '../core/config.js';
2
+ import type { Notifier } from '../interfaces/Notifier.js';
3
+ export declare class MatrixNotifier implements Notifier {
4
+ private readonly homeserver;
5
+ private readonly accessToken;
6
+ private readonly roomId;
7
+ private readonly enabled;
8
+ constructor(config: ProjectConfig);
9
+ /**
10
+ * Send a message to the configured Matrix room.
11
+ * Optionally prefix with a level indicator.
12
+ */
13
+ send(message: string, level?: 'info' | 'success' | 'warning' | 'error'): Promise<void>;
14
+ sendSuccess(message: string): Promise<void>;
15
+ sendWarning(message: string): Promise<void>;
16
+ sendError(message: string): Promise<void>;
17
+ /**
18
+ * Format items as a bulleted list and send as a single message.
19
+ */
20
+ sendDigest(items: {
21
+ title: string;
22
+ status: string;
23
+ }[]): Promise<void>;
24
+ /**
25
+ * Send a raw text message to the Matrix room via the Client-Server API.
26
+ * Errors are logged to stderr but never thrown — notifications are non-critical.
27
+ */
28
+ private sendToMatrix;
29
+ }
30
+ //# sourceMappingURL=MatrixNotifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixNotifier.d.ts","sourceRoot":"","sources":["../../src/providers/MatrixNotifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAU1D,qBAAa,cAAe,YAAW,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,MAAM,EAAE,aAAa;IAajC;;;OAGG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtF,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3E;;;OAGG;YACW,YAAY;CA8B3B"}
@@ -0,0 +1,82 @@
1
+ /** Level prefixes for formatted messages. */
2
+ const LEVEL_PREFIX = {
3
+ info: 'ℹ️',
4
+ success: '✅',
5
+ warning: '⚠️',
6
+ error: '❌',
7
+ };
8
+ export class MatrixNotifier {
9
+ homeserver;
10
+ accessToken;
11
+ roomId;
12
+ enabled;
13
+ constructor(config) {
14
+ this.homeserver = (config.raw.MATRIX_HOMESERVER ?? '').replace(/\/+$/, '');
15
+ this.accessToken = config.raw.MATRIX_ACCESS_TOKEN ?? '';
16
+ this.roomId = config.raw.MATRIX_ROOM_ID ?? '';
17
+ this.enabled = !!(this.homeserver && this.accessToken && this.roomId);
18
+ if (!this.enabled) {
19
+ process.stderr.write('MatrixNotifier: Missing MATRIX_HOMESERVER, MATRIX_ACCESS_TOKEN, or MATRIX_ROOM_ID — notifications disabled\n');
20
+ }
21
+ }
22
+ /**
23
+ * Send a message to the configured Matrix room.
24
+ * Optionally prefix with a level indicator.
25
+ */
26
+ async send(message, level) {
27
+ const prefix = level ? LEVEL_PREFIX[level] : undefined;
28
+ const body = prefix ? `${prefix} ${message}` : message;
29
+ await this.sendToMatrix(body);
30
+ }
31
+ async sendSuccess(message) {
32
+ await this.send(message, 'success');
33
+ }
34
+ async sendWarning(message) {
35
+ await this.send(message, 'warning');
36
+ }
37
+ async sendError(message) {
38
+ await this.send(message, 'error');
39
+ }
40
+ /**
41
+ * Format items as a bulleted list and send as a single message.
42
+ */
43
+ async sendDigest(items) {
44
+ if (items.length === 0)
45
+ return;
46
+ const lines = items.map((item) => `• [${item.status}] ${item.title}`);
47
+ const body = `Digest (${items.length} items):\n${lines.join('\n')}`;
48
+ await this.sendToMatrix(body);
49
+ }
50
+ /**
51
+ * Send a raw text message to the Matrix room via the Client-Server API.
52
+ * Errors are logged to stderr but never thrown — notifications are non-critical.
53
+ */
54
+ async sendToMatrix(body) {
55
+ if (!this.enabled)
56
+ return;
57
+ const txnId = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
58
+ const url = `${this.homeserver}/_matrix/client/v3/rooms/${encodeURIComponent(this.roomId)}/send/m.room.message/${txnId}`;
59
+ try {
60
+ const response = await fetch(url, {
61
+ method: 'PUT',
62
+ headers: {
63
+ 'Authorization': `Bearer ${this.accessToken}`,
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: JSON.stringify({
67
+ msgtype: 'm.text',
68
+ body,
69
+ }),
70
+ });
71
+ if (!response.ok) {
72
+ const text = await response.text().catch(() => '(no body)');
73
+ process.stderr.write(`MatrixNotifier: HTTP ${response.status} — ${text}\n`);
74
+ }
75
+ }
76
+ catch (err) {
77
+ const msg = err instanceof Error ? err.message : String(err);
78
+ process.stderr.write(`MatrixNotifier: Failed to send — ${msg}\n`);
79
+ }
80
+ }
81
+ }
82
+ //# sourceMappingURL=MatrixNotifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MatrixNotifier.js","sourceRoot":"","sources":["../../src/providers/MatrixNotifier.ts"],"names":[],"mappings":"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"}