tick-md 1.0.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 (82) hide show
  1. package/README.md +228 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +282 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/add.d.ts +15 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +95 -0
  9. package/dist/commands/add.js.map +1 -0
  10. package/dist/commands/agent.d.ts +20 -0
  11. package/dist/commands/agent.d.ts.map +1 -0
  12. package/dist/commands/agent.js +125 -0
  13. package/dist/commands/agent.js.map +1 -0
  14. package/dist/commands/claim.d.ts +9 -0
  15. package/dist/commands/claim.d.ts.map +1 -0
  16. package/dist/commands/claim.js +161 -0
  17. package/dist/commands/claim.js.map +1 -0
  18. package/dist/commands/done.d.ts +9 -0
  19. package/dist/commands/done.d.ts.map +1 -0
  20. package/dist/commands/done.js +152 -0
  21. package/dist/commands/done.js.map +1 -0
  22. package/dist/commands/graph.d.ts +9 -0
  23. package/dist/commands/graph.d.ts.map +1 -0
  24. package/dist/commands/graph.js +143 -0
  25. package/dist/commands/graph.js.map +1 -0
  26. package/dist/commands/init.d.ts +9 -0
  27. package/dist/commands/init.d.ts.map +1 -0
  28. package/dist/commands/init.js +78 -0
  29. package/dist/commands/init.js.map +1 -0
  30. package/dist/commands/list.d.ts +15 -0
  31. package/dist/commands/list.d.ts.map +1 -0
  32. package/dist/commands/list.js +104 -0
  33. package/dist/commands/list.js.map +1 -0
  34. package/dist/commands/status.d.ts +5 -0
  35. package/dist/commands/status.d.ts.map +1 -0
  36. package/dist/commands/status.js +137 -0
  37. package/dist/commands/status.js.map +1 -0
  38. package/dist/commands/sync.d.ts +13 -0
  39. package/dist/commands/sync.d.ts.map +1 -0
  40. package/dist/commands/sync.js +141 -0
  41. package/dist/commands/sync.js.map +1 -0
  42. package/dist/commands/validate.d.ts +8 -0
  43. package/dist/commands/validate.d.ts.map +1 -0
  44. package/dist/commands/validate.js +103 -0
  45. package/dist/commands/validate.js.map +1 -0
  46. package/dist/commands/watch.d.ts +10 -0
  47. package/dist/commands/watch.d.ts.map +1 -0
  48. package/dist/commands/watch.js +136 -0
  49. package/dist/commands/watch.js.map +1 -0
  50. package/dist/index.d.ts +4 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +4 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/parser/index.d.ts +3 -0
  55. package/dist/parser/index.d.ts.map +1 -0
  56. package/dist/parser/index.js +3 -0
  57. package/dist/parser/index.js.map +1 -0
  58. package/dist/parser/parse.d.ts +6 -0
  59. package/dist/parser/parse.d.ts.map +1 -0
  60. package/dist/parser/parse.js +178 -0
  61. package/dist/parser/parse.js.map +1 -0
  62. package/dist/parser/serialize.d.ts +10 -0
  63. package/dist/parser/serialize.d.ts.map +1 -0
  64. package/dist/parser/serialize.js +122 -0
  65. package/dist/parser/serialize.js.map +1 -0
  66. package/dist/types.d.ts +59 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +3 -0
  69. package/dist/types.js.map +1 -0
  70. package/dist/utils/git.d.ts +54 -0
  71. package/dist/utils/git.d.ts.map +1 -0
  72. package/dist/utils/git.js +192 -0
  73. package/dist/utils/git.js.map +1 -0
  74. package/dist/utils/lock.d.ts +47 -0
  75. package/dist/utils/lock.d.ts.map +1 -0
  76. package/dist/utils/lock.js +128 -0
  77. package/dist/utils/lock.js.map +1 -0
  78. package/dist/utils/validator.d.ts +17 -0
  79. package/dist/utils/validator.d.ts.map +1 -0
  80. package/dist/utils/validator.js +188 -0
  81. package/dist/utils/validator.js.map +1 -0
  82. package/package.json +56 -0
@@ -0,0 +1,103 @@
1
+ import * as fs from "node:fs";
2
+ import chalk from "chalk";
3
+ import { parseTickFile } from "../parser/parse.js";
4
+ import { validateTickFile } from "../utils/validator.js";
5
+ /**
6
+ * Validate the current TICK.md file
7
+ */
8
+ export async function validateCommand(options = {}) {
9
+ const tickPath = "TICK.md";
10
+ if (!fs.existsSync(tickPath)) {
11
+ console.error(chalk.red("✗ TICK.md not found"));
12
+ console.log(chalk.gray("Run 'tick init' to initialize a project"));
13
+ process.exit(1);
14
+ }
15
+ console.log(chalk.cyan("🔍 Validating TICK.md..."));
16
+ console.log();
17
+ try {
18
+ const content = fs.readFileSync(tickPath, "utf-8");
19
+ const tickFile = parseTickFile(content);
20
+ const result = validateTickFile(tickFile);
21
+ // Display errors
22
+ if (result.errors.length > 0) {
23
+ console.log(chalk.red.bold(`✗ ${result.errors.length} error(s) found:`));
24
+ console.log();
25
+ for (const error of result.errors) {
26
+ console.log(chalk.red(" ✗"), chalk.white.bold(error.message));
27
+ if (error.location) {
28
+ console.log(chalk.gray(` Location: ${error.location}`));
29
+ }
30
+ if (error.fix) {
31
+ console.log(chalk.cyan(` Fix: ${error.fix}`));
32
+ }
33
+ console.log();
34
+ }
35
+ }
36
+ // Display warnings
37
+ if (result.warnings.length > 0) {
38
+ console.log(chalk.yellow.bold(`⚠ ${result.warnings.length} warning(s) found:`));
39
+ console.log();
40
+ for (const warning of result.warnings) {
41
+ console.log(chalk.yellow(" ⚠"), chalk.white(warning.message));
42
+ if (warning.location) {
43
+ console.log(chalk.gray(` Location: ${warning.location}`));
44
+ }
45
+ if (warning.fix) {
46
+ console.log(chalk.cyan(` Fix: ${warning.fix}`));
47
+ }
48
+ console.log();
49
+ }
50
+ }
51
+ // Display summary
52
+ console.log(chalk.gray("─".repeat(60)));
53
+ if (result.valid && result.warnings.length === 0) {
54
+ console.log(chalk.green.bold("✓ TICK.md is valid!"));
55
+ console.log();
56
+ console.log(chalk.gray(` ${tickFile.tasks.length} tasks validated`));
57
+ console.log(chalk.gray(` ${tickFile.agents.length} agents registered`));
58
+ }
59
+ else if (result.valid) {
60
+ console.log(chalk.yellow.bold("✓ TICK.md is valid (with warnings)"));
61
+ console.log();
62
+ console.log(chalk.gray(` ${tickFile.tasks.length} tasks validated`));
63
+ console.log(chalk.gray(` ${tickFile.agents.length} agents registered`));
64
+ console.log(chalk.yellow(` ${result.warnings.length} warnings to address`));
65
+ }
66
+ else {
67
+ console.log(chalk.red.bold("✗ TICK.md has errors"));
68
+ console.log();
69
+ console.log(chalk.red(` ${result.errors.length} errors to fix`));
70
+ console.log(chalk.yellow(` ${result.warnings.length} warnings to address`));
71
+ process.exit(1);
72
+ }
73
+ // Verbose stats
74
+ if (options.verbose) {
75
+ console.log();
76
+ console.log(chalk.cyan.bold("Detailed Stats:"));
77
+ console.log();
78
+ const statuses = tickFile.tasks.reduce((acc, task) => {
79
+ acc[task.status] = (acc[task.status] || 0) + 1;
80
+ return acc;
81
+ }, {});
82
+ for (const [status, count] of Object.entries(statuses)) {
83
+ console.log(chalk.gray(` ${status}: ${count}`));
84
+ }
85
+ const blockedTasks = tickFile.tasks.filter((t) => t.status === "blocked");
86
+ if (blockedTasks.length > 0) {
87
+ console.log();
88
+ console.log(chalk.yellow(` ${blockedTasks.length} blocked tasks`));
89
+ }
90
+ const unassigned = tickFile.tasks.filter((t) => !t.assigned_to && t.status !== "done").length;
91
+ if (unassigned > 0) {
92
+ console.log(chalk.gray(` ${unassigned} unassigned tasks`));
93
+ }
94
+ }
95
+ console.log();
96
+ }
97
+ catch (error) {
98
+ console.error(chalk.red("✗ Failed to parse TICK.md"));
99
+ console.error(chalk.gray(error.message));
100
+ process.exit(1);
101
+ }
102
+ }
103
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TaskStatus } from "../types.js";
2
+ export interface WatchOptions {
3
+ interval?: number;
4
+ filter?: TaskStatus;
5
+ }
6
+ /**
7
+ * Watch TICK.md for changes and display updates in real-time
8
+ */
9
+ export declare function watchCommand(options?: WatchOptions): Promise<void>;
10
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAQ,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmG5E"}
@@ -0,0 +1,136 @@
1
+ import * as fs from "node:fs";
2
+ import chalk from "chalk";
3
+ import { parseTickFile } from "../parser/parse.js";
4
+ /**
5
+ * Watch TICK.md for changes and display updates in real-time
6
+ */
7
+ export async function watchCommand(options = {}) {
8
+ const tickPath = "TICK.md";
9
+ if (!fs.existsSync(tickPath)) {
10
+ console.error(chalk.red("✗ TICK.md not found"));
11
+ console.log(chalk.gray("Run 'tick init' to initialize a project"));
12
+ process.exit(1);
13
+ }
14
+ const interval = (options.interval || 5) * 1000; // Convert to ms
15
+ let lastContent = "";
16
+ let lastTasks = [];
17
+ console.log(chalk.cyan.bold("👀 Watching TICK.md for changes..."));
18
+ console.log(chalk.gray(`Polling every ${options.interval || 5}s · Press Ctrl+C to stop`));
19
+ console.log();
20
+ // Initial load
21
+ try {
22
+ lastContent = fs.readFileSync(tickPath, "utf-8");
23
+ const tickFile = parseTickFile(lastContent);
24
+ lastTasks = tickFile.tasks;
25
+ displaySummary(lastTasks, options.filter);
26
+ }
27
+ catch (error) {
28
+ console.error(chalk.red("✗ Failed to parse TICK.md"));
29
+ console.error(chalk.gray(error.message));
30
+ process.exit(1);
31
+ }
32
+ // Watch for changes
33
+ const watchInterval = setInterval(() => {
34
+ try {
35
+ const currentContent = fs.readFileSync(tickPath, "utf-8");
36
+ // Check if content changed
37
+ if (currentContent === lastContent) {
38
+ return;
39
+ }
40
+ lastContent = currentContent;
41
+ const tickFile = parseTickFile(currentContent);
42
+ const currentTasks = tickFile.tasks;
43
+ // Detect changes
44
+ const changes = detectChanges(lastTasks, currentTasks);
45
+ if (changes.length > 0) {
46
+ console.log(chalk.gray(`[${new Date().toLocaleTimeString()}]`));
47
+ for (const change of changes) {
48
+ switch (change.type) {
49
+ case "added":
50
+ console.log(chalk.green(` ✓ Added: ${change.task.id} - ${change.task.title}`));
51
+ break;
52
+ case "removed":
53
+ console.log(chalk.red(` ✗ Removed: ${change.task.id}`));
54
+ break;
55
+ case "status":
56
+ console.log(chalk.blue(` ⟳ ${change.task.id}: ${change.oldValue} → ${change.task.status}`));
57
+ break;
58
+ case "claimed":
59
+ console.log(chalk.yellow(` 🔒 ${change.task.id} claimed by ${change.task.claimed_by}`));
60
+ break;
61
+ case "released":
62
+ console.log(chalk.gray(` 🔓 ${change.task.id} released`));
63
+ break;
64
+ }
65
+ }
66
+ console.log();
67
+ displaySummary(currentTasks, options.filter);
68
+ }
69
+ lastTasks = currentTasks;
70
+ }
71
+ catch (error) {
72
+ console.error(chalk.red(`✗ Error reading TICK.md: ${error.message}`));
73
+ }
74
+ }, interval);
75
+ // Handle graceful shutdown
76
+ process.on("SIGINT", () => {
77
+ clearInterval(watchInterval);
78
+ console.log();
79
+ console.log(chalk.gray("Stopped watching"));
80
+ process.exit(0);
81
+ });
82
+ }
83
+ /**
84
+ * Detect changes between task lists
85
+ */
86
+ function detectChanges(oldTasks, newTasks) {
87
+ const changes = [];
88
+ const oldMap = new Map(oldTasks.map((t) => [t.id, t]));
89
+ const newMap = new Map(newTasks.map((t) => [t.id, t]));
90
+ // Check for added and modified tasks
91
+ for (const [id, newTask] of newMap) {
92
+ const oldTask = oldMap.get(id);
93
+ if (!oldTask) {
94
+ changes.push({ type: "added", task: newTask });
95
+ }
96
+ else {
97
+ // Check for status change
98
+ if (oldTask.status !== newTask.status) {
99
+ changes.push({ type: "status", task: newTask, oldValue: oldTask.status });
100
+ }
101
+ // Check for claim change
102
+ if (!oldTask.claimed_by && newTask.claimed_by) {
103
+ changes.push({ type: "claimed", task: newTask });
104
+ }
105
+ else if (oldTask.claimed_by && !newTask.claimed_by) {
106
+ changes.push({ type: "released", task: newTask });
107
+ }
108
+ }
109
+ }
110
+ // Check for removed tasks
111
+ for (const [id, oldTask] of oldMap) {
112
+ if (!newMap.has(id)) {
113
+ changes.push({ type: "removed", task: oldTask });
114
+ }
115
+ }
116
+ return changes;
117
+ }
118
+ /**
119
+ * Display task summary
120
+ */
121
+ function displaySummary(tasks, filter) {
122
+ const filteredTasks = filter ? tasks.filter((t) => t.status === filter) : tasks;
123
+ const byStatus = filteredTasks.reduce((acc, task) => {
124
+ acc[task.status] = (acc[task.status] || 0) + 1;
125
+ return acc;
126
+ }, {});
127
+ const parts = [
128
+ byStatus.todo ? chalk.white(`${byStatus.todo} todo`) : null,
129
+ byStatus.in_progress ? chalk.blue(`${byStatus.in_progress} in progress`) : null,
130
+ byStatus.blocked ? chalk.red(`${byStatus.blocked} blocked`) : null,
131
+ byStatus.done ? chalk.green(`${byStatus.done} done`) : null,
132
+ ].filter(Boolean);
133
+ console.log(chalk.gray(` Status: ${parts.join(" · ")}`));
134
+ console.log();
135
+ }
136
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { parseTickFile, serializeTickFile, generateDefaultTickFile } from "./parser/index.js";
2
+ export { initCommand } from "./commands/init.js";
3
+ export * from "./types.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { parseTickFile, serializeTickFile, generateDefaultTickFile } from "./parser/index.js";
2
+ export { initCommand } from "./commands/init.js";
3
+ export * from "./types.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,cAAc,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { parseTickFile } from "./parse.js";
2
+ export { serializeTickFile, generateDefaultTickFile } from "./serialize.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { parseTickFile } from "./parse.js";
2
+ export { serializeTickFile, generateDefaultTickFile } from "./serialize.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { TickFile } from "../types.js";
2
+ /**
3
+ * Parse a TICK.md file into structured data
4
+ */
5
+ export declare function parseTickFile(content: string): TickFile;
6
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/parser/parse.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EAUT,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAkCvD"}
@@ -0,0 +1,178 @@
1
+ import matter from "gray-matter";
2
+ import YAML from "yaml";
3
+ /**
4
+ * Parse a TICK.md file into structured data
5
+ */
6
+ export function parseTickFile(content) {
7
+ // Parse YAML frontmatter using gray-matter
8
+ const { data: frontmatter, content: body } = matter(content);
9
+ // Extract project metadata from frontmatter
10
+ const meta = {
11
+ project: frontmatter.project || "untitled",
12
+ title: frontmatter.title,
13
+ schema_version: frontmatter.schema_version || "1.0",
14
+ created: frontmatter.created || new Date().toISOString(),
15
+ updated: frontmatter.updated || new Date().toISOString(),
16
+ default_workflow: frontmatter.default_workflow || [
17
+ "backlog",
18
+ "todo",
19
+ "in_progress",
20
+ "review",
21
+ "done",
22
+ ],
23
+ id_prefix: frontmatter.id_prefix || "TASK",
24
+ next_id: frontmatter.next_id || 1,
25
+ };
26
+ // Parse agents table
27
+ const agents = parseAgentsTable(body);
28
+ // Parse task blocks
29
+ const tasks = parseTaskBlocks(body);
30
+ return {
31
+ meta,
32
+ agents,
33
+ tasks,
34
+ raw_content: content,
35
+ };
36
+ }
37
+ /**
38
+ * Parse the agents table from Markdown
39
+ * Format: | Agent | Type | Role | Status | Working On | Last Active | Trust Level |
40
+ */
41
+ function parseAgentsTable(content) {
42
+ const agents = [];
43
+ // Find the agents section (starts with ## Agents)
44
+ const agentsMatch = content.match(/##\s+Agents\s*\n\n([\s\S]*?)(?=\n##|\n---|\n###|$)/i);
45
+ if (!agentsMatch)
46
+ return agents;
47
+ const agentsSection = agentsMatch[1];
48
+ // Split into lines and find table rows
49
+ const lines = agentsSection.split("\n");
50
+ let inTable = false;
51
+ for (const line of lines) {
52
+ const trimmed = line.trim();
53
+ // Skip empty lines and header separator
54
+ if (!trimmed || trimmed.startsWith("|---") || trimmed.startsWith("| ---")) {
55
+ continue;
56
+ }
57
+ // Check if this is a table row
58
+ if (trimmed.startsWith("|")) {
59
+ const cells = trimmed
60
+ .split("|")
61
+ .map((c) => c.trim())
62
+ .filter((c) => c);
63
+ // Skip header row (contains "Agent" or "Type")
64
+ if (cells.some((c) => c === "Agent" ||
65
+ c === "Type" ||
66
+ c === "Role" ||
67
+ c === "Status" ||
68
+ c === "Working On")) {
69
+ inTable = true;
70
+ continue;
71
+ }
72
+ if (inTable && cells.length >= 6) {
73
+ const [name, type, roleStr, status, workingOn, lastActive, trustLevel] = cells;
74
+ // Parse roles (can be comma-separated)
75
+ const roles = roleStr.split(",").map((r) => r.trim());
76
+ agents.push({
77
+ name: name.trim(),
78
+ type: type.toLowerCase() || "bot",
79
+ roles,
80
+ status: status.toLowerCase() || "offline",
81
+ working_on: workingOn === "-" ? null : workingOn.trim(),
82
+ last_active: lastActive.trim(),
83
+ trust_level: trustLevel.toLowerCase() || "restricted",
84
+ });
85
+ }
86
+ }
87
+ }
88
+ return agents;
89
+ }
90
+ /**
91
+ * Parse task blocks from Markdown
92
+ * Format:
93
+ * ### TASK-001 · Task Title
94
+ * ```yaml
95
+ * id: TASK-001
96
+ * status: done
97
+ * ...
98
+ * ```
99
+ * > Task description
100
+ */
101
+ function parseTaskBlocks(content) {
102
+ const tasks = [];
103
+ // Find all task headers (### TASK-XXX · Title)
104
+ const taskHeaderRegex = /###\s+([A-Z]+-\d+)\s*·\s*(.+?)$/gm;
105
+ const matches = [...content.matchAll(taskHeaderRegex)];
106
+ for (let i = 0; i < matches.length; i++) {
107
+ const match = matches[i];
108
+ const taskId = match[1];
109
+ const taskTitle = match[2].trim();
110
+ const startIndex = match.index;
111
+ // Find the end of this task block (next task header or end of file)
112
+ const nextMatch = matches[i + 1];
113
+ const endIndex = nextMatch ? nextMatch.index : content.length;
114
+ const taskBlock = content.slice(startIndex, endIndex);
115
+ // Extract YAML metadata from code block
116
+ const yamlMatch = taskBlock.match(/```yaml\s*\n([\s\S]*?)\n```/);
117
+ if (!yamlMatch)
118
+ continue;
119
+ const yamlContent = yamlMatch[1];
120
+ let metadata;
121
+ try {
122
+ metadata = YAML.parse(yamlContent);
123
+ }
124
+ catch (error) {
125
+ console.warn(`Failed to parse YAML for ${taskId}:`, error);
126
+ continue;
127
+ }
128
+ // Extract description (text after ```, usually in blockquote)
129
+ const afterYaml = taskBlock.slice(taskBlock.indexOf("```", yamlMatch.index + 3) + 3);
130
+ const descMatch = afterYaml.match(/>\s*(.+?)(?=\n###|\n---|\n##|$)/s);
131
+ const description = descMatch
132
+ ? descMatch[1]
133
+ .split("\n")
134
+ .map((line) => line.replace(/^>\s*/, "").trim())
135
+ .filter((line) => line)
136
+ .join("\n")
137
+ : "";
138
+ // Build task object
139
+ const task = {
140
+ id: metadata.id || taskId,
141
+ title: taskTitle,
142
+ status: metadata.status || "backlog",
143
+ priority: metadata.priority || "medium",
144
+ assigned_to: metadata.assigned_to || null,
145
+ claimed_by: metadata.claimed_by || null,
146
+ created_by: metadata.created_by || "",
147
+ created_at: metadata.created_at || new Date().toISOString(),
148
+ updated_at: metadata.updated_at || new Date().toISOString(),
149
+ due_date: metadata.due_date,
150
+ tags: Array.isArray(metadata.tags) ? metadata.tags : [],
151
+ depends_on: Array.isArray(metadata.depends_on) ? metadata.depends_on : [],
152
+ blocks: Array.isArray(metadata.blocks) ? metadata.blocks : [],
153
+ estimated_hours: metadata.estimated_hours,
154
+ actual_hours: metadata.actual_hours,
155
+ detail_file: metadata.detail_file,
156
+ description: description.trim(),
157
+ history: parseHistory(metadata.history || []),
158
+ };
159
+ tasks.push(task);
160
+ }
161
+ return tasks;
162
+ }
163
+ /**
164
+ * Parse history entries from YAML array
165
+ */
166
+ function parseHistory(history) {
167
+ if (!Array.isArray(history))
168
+ return [];
169
+ return history.map((entry) => ({
170
+ ts: entry.ts || "",
171
+ who: entry.who || "",
172
+ action: entry.action || "",
173
+ note: entry.note,
174
+ from: entry.from,
175
+ to: entry.to,
176
+ }));
177
+ }
178
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/parser/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TickFile } from "../types.js";
2
+ /**
3
+ * Serialize a TickFile back to TICK.md format
4
+ */
5
+ export declare function serializeTickFile(tickFile: TickFile): string;
6
+ /**
7
+ * Generate a default TICK.md template for a new project
8
+ */
9
+ export declare function generateDefaultTickFile(projectName: string): string;
10
+ //# sourceMappingURL=serialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/parser/serialize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAA6B,MAAM,aAAa,CAAC;AAEvE;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAyG5D;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAkBnE"}
@@ -0,0 +1,122 @@
1
+ import YAML from "yaml";
2
+ /**
3
+ * Serialize a TickFile back to TICK.md format
4
+ */
5
+ export function serializeTickFile(tickFile) {
6
+ const parts = [];
7
+ // 1. Frontmatter
8
+ parts.push("---");
9
+ parts.push(`project: ${tickFile.meta.project}`);
10
+ if (tickFile.meta.title) {
11
+ parts.push(`title: ${tickFile.meta.title}`);
12
+ }
13
+ parts.push(`schema_version: "${tickFile.meta.schema_version}"`);
14
+ parts.push(`created: ${tickFile.meta.created}`);
15
+ parts.push(`updated: ${tickFile.meta.updated}`);
16
+ parts.push(`default_workflow: [${tickFile.meta.default_workflow.join(", ")}]`);
17
+ parts.push(`id_prefix: ${tickFile.meta.id_prefix}`);
18
+ parts.push(`next_id: ${tickFile.meta.next_id}`);
19
+ parts.push("---");
20
+ parts.push("");
21
+ // 2. Agents table
22
+ if (tickFile.agents.length > 0) {
23
+ parts.push("## Agents");
24
+ parts.push("");
25
+ parts.push("| Agent | Type | Role | Status | Working On | Last Active | Trust Level |");
26
+ parts.push("|-------|------|------|--------|------------|-------------|-------------|");
27
+ for (const agent of tickFile.agents) {
28
+ const roles = agent.roles.join(", ");
29
+ const workingOn = agent.working_on || "-";
30
+ parts.push(`| ${agent.name} | ${agent.type} | ${roles} | ${agent.status} | ${workingOn} | ${agent.last_active} | ${agent.trust_level} |`);
31
+ }
32
+ parts.push("");
33
+ parts.push("---");
34
+ parts.push("");
35
+ }
36
+ // 3. Tasks
37
+ if (tickFile.tasks.length > 0) {
38
+ parts.push("## Tasks");
39
+ parts.push("");
40
+ for (const task of tickFile.tasks) {
41
+ parts.push(`### ${task.id} · ${task.title}`);
42
+ parts.push("");
43
+ // Task YAML metadata
44
+ const metadata = {
45
+ id: task.id,
46
+ status: task.status,
47
+ priority: task.priority,
48
+ assigned_to: task.assigned_to,
49
+ claimed_by: task.claimed_by,
50
+ created_by: task.created_by,
51
+ created_at: task.created_at,
52
+ updated_at: task.updated_at,
53
+ };
54
+ if (task.due_date)
55
+ metadata.due_date = task.due_date;
56
+ if (task.tags.length > 0)
57
+ metadata.tags = task.tags;
58
+ if (task.depends_on.length > 0)
59
+ metadata.depends_on = task.depends_on;
60
+ if (task.blocks.length > 0)
61
+ metadata.blocks = task.blocks;
62
+ if (task.estimated_hours)
63
+ metadata.estimated_hours = task.estimated_hours;
64
+ if (task.actual_hours)
65
+ metadata.actual_hours = task.actual_hours;
66
+ if (task.detail_file)
67
+ metadata.detail_file = task.detail_file;
68
+ // Format history for better readability
69
+ if (task.history.length > 0) {
70
+ metadata.history = task.history.map((h) => {
71
+ const entry = {
72
+ ts: h.ts,
73
+ who: h.who,
74
+ action: h.action,
75
+ };
76
+ if (h.note)
77
+ entry.note = h.note;
78
+ if (h.from)
79
+ entry.from = h.from;
80
+ if (h.to)
81
+ entry.to = h.to;
82
+ return entry;
83
+ });
84
+ }
85
+ parts.push("```yaml");
86
+ parts.push(YAML.stringify(metadata).trim());
87
+ parts.push("```");
88
+ parts.push("");
89
+ // Task description
90
+ if (task.description) {
91
+ const descLines = task.description
92
+ .split("\n")
93
+ .map((line) => `> ${line}`)
94
+ .join("\n");
95
+ parts.push(descLines);
96
+ parts.push("");
97
+ }
98
+ }
99
+ }
100
+ return parts.join("\n");
101
+ }
102
+ /**
103
+ * Generate a default TICK.md template for a new project
104
+ */
105
+ export function generateDefaultTickFile(projectName) {
106
+ const now = new Date().toISOString();
107
+ const defaultFile = {
108
+ meta: {
109
+ project: projectName,
110
+ schema_version: "1.0",
111
+ created: now,
112
+ updated: now,
113
+ default_workflow: ["backlog", "todo", "in_progress", "review", "done"],
114
+ id_prefix: "TASK",
115
+ next_id: 1,
116
+ },
117
+ agents: [],
118
+ tasks: [],
119
+ };
120
+ return serializeTickFile(defaultFile);
121
+ }
122
+ //# sourceMappingURL=serialize.js.map