@mono-labs/tracker 0.1.269

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 (126) hide show
  1. package/README.md +1196 -0
  2. package/bin/tracker.js +2 -0
  3. package/dist/dashboard/cli.d.ts +2 -0
  4. package/dist/dashboard/cli.d.ts.map +1 -0
  5. package/dist/dashboard/cli.js +38 -0
  6. package/dist/dashboard/index.d.ts +3 -0
  7. package/dist/dashboard/index.d.ts.map +1 -0
  8. package/dist/dashboard/index.js +5 -0
  9. package/dist/dashboard/server.d.ts +3 -0
  10. package/dist/dashboard/server.d.ts.map +1 -0
  11. package/dist/dashboard/server.js +130 -0
  12. package/dist/dashboard/types.d.ts +13 -0
  13. package/dist/dashboard/types.d.ts.map +1 -0
  14. package/dist/dashboard/types.js +2 -0
  15. package/dist/dashboard/watcher.d.ts +7 -0
  16. package/dist/dashboard/watcher.d.ts.map +1 -0
  17. package/dist/dashboard/watcher.js +44 -0
  18. package/dist/executor/action-executor.d.ts +10 -0
  19. package/dist/executor/action-executor.d.ts.map +1 -0
  20. package/dist/executor/action-executor.js +19 -0
  21. package/dist/executor/actions/index.d.ts +4 -0
  22. package/dist/executor/actions/index.d.ts.map +1 -0
  23. package/dist/executor/actions/index.js +9 -0
  24. package/dist/executor/actions/remove-action.d.ts +4 -0
  25. package/dist/executor/actions/remove-action.d.ts.map +1 -0
  26. package/dist/executor/actions/remove-action.js +10 -0
  27. package/dist/executor/actions/rename-action.d.ts +4 -0
  28. package/dist/executor/actions/rename-action.d.ts.map +1 -0
  29. package/dist/executor/actions/rename-action.js +10 -0
  30. package/dist/executor/actions/replace-action.d.ts +4 -0
  31. package/dist/executor/actions/replace-action.d.ts.map +1 -0
  32. package/dist/executor/actions/replace-action.js +10 -0
  33. package/dist/executor/index.d.ts +4 -0
  34. package/dist/executor/index.d.ts.map +1 -0
  35. package/dist/executor/index.js +10 -0
  36. package/dist/index.d.ts +20 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +58 -0
  39. package/dist/manager/index.d.ts +7 -0
  40. package/dist/manager/index.d.ts.map +1 -0
  41. package/dist/manager/index.js +19 -0
  42. package/dist/manager/notation-manager.d.ts +18 -0
  43. package/dist/manager/notation-manager.d.ts.map +1 -0
  44. package/dist/manager/notation-manager.js +137 -0
  45. package/dist/manager/notation-manager.test.d.ts +2 -0
  46. package/dist/manager/notation-manager.test.d.ts.map +1 -0
  47. package/dist/manager/notation-manager.test.js +211 -0
  48. package/dist/manager/notation-updater.d.ts +6 -0
  49. package/dist/manager/notation-updater.d.ts.map +1 -0
  50. package/dist/manager/notation-updater.js +20 -0
  51. package/dist/manager/relationship-manager.d.ts +5 -0
  52. package/dist/manager/relationship-manager.d.ts.map +1 -0
  53. package/dist/manager/relationship-manager.js +46 -0
  54. package/dist/manager/stats.d.ts +3 -0
  55. package/dist/manager/stats.d.ts.map +1 -0
  56. package/dist/manager/stats.js +41 -0
  57. package/dist/manager/validator.d.ts +9 -0
  58. package/dist/manager/validator.d.ts.map +1 -0
  59. package/dist/manager/validator.js +62 -0
  60. package/dist/scanner/action-parser.d.ts +3 -0
  61. package/dist/scanner/action-parser.d.ts.map +1 -0
  62. package/dist/scanner/action-parser.js +97 -0
  63. package/dist/scanner/action-parser.test.d.ts +2 -0
  64. package/dist/scanner/action-parser.test.d.ts.map +1 -0
  65. package/dist/scanner/action-parser.test.js +94 -0
  66. package/dist/scanner/attribute-parser.d.ts +15 -0
  67. package/dist/scanner/attribute-parser.d.ts.map +1 -0
  68. package/dist/scanner/attribute-parser.js +183 -0
  69. package/dist/scanner/attribute-parser.test.d.ts +2 -0
  70. package/dist/scanner/attribute-parser.test.d.ts.map +1 -0
  71. package/dist/scanner/attribute-parser.test.js +93 -0
  72. package/dist/scanner/file-scanner.d.ts +3 -0
  73. package/dist/scanner/file-scanner.d.ts.map +1 -0
  74. package/dist/scanner/file-scanner.js +58 -0
  75. package/dist/scanner/index.d.ts +6 -0
  76. package/dist/scanner/index.d.ts.map +1 -0
  77. package/dist/scanner/index.js +11 -0
  78. package/dist/scanner/notation-parser.d.ts +3 -0
  79. package/dist/scanner/notation-parser.d.ts.map +1 -0
  80. package/dist/scanner/notation-parser.js +88 -0
  81. package/dist/scanner/notation-parser.test.d.ts +2 -0
  82. package/dist/scanner/notation-parser.test.d.ts.map +1 -0
  83. package/dist/scanner/notation-parser.test.js +153 -0
  84. package/dist/storage/config-loader.d.ts +3 -0
  85. package/dist/storage/config-loader.d.ts.map +1 -0
  86. package/dist/storage/config-loader.js +55 -0
  87. package/dist/storage/index.d.ts +3 -0
  88. package/dist/storage/index.d.ts.map +1 -0
  89. package/dist/storage/index.js +7 -0
  90. package/dist/storage/jsonl-storage.d.ts +11 -0
  91. package/dist/storage/jsonl-storage.d.ts.map +1 -0
  92. package/dist/storage/jsonl-storage.js +88 -0
  93. package/dist/storage/jsonl-storage.test.d.ts +2 -0
  94. package/dist/storage/jsonl-storage.test.d.ts.map +1 -0
  95. package/dist/storage/jsonl-storage.test.js +126 -0
  96. package/dist/types/action.d.ts +57 -0
  97. package/dist/types/action.d.ts.map +1 -0
  98. package/dist/types/action.js +13 -0
  99. package/dist/types/config.d.ts +11 -0
  100. package/dist/types/config.d.ts.map +1 -0
  101. package/dist/types/config.js +11 -0
  102. package/dist/types/enums.d.ts +40 -0
  103. package/dist/types/enums.d.ts.map +1 -0
  104. package/dist/types/enums.js +37 -0
  105. package/dist/types/index.d.ts +7 -0
  106. package/dist/types/index.d.ts.map +1 -0
  107. package/dist/types/index.js +13 -0
  108. package/dist/types/notation.d.ts +64 -0
  109. package/dist/types/notation.d.ts.map +1 -0
  110. package/dist/types/notation.js +2 -0
  111. package/dist/utils/date-parser.d.ts +3 -0
  112. package/dist/utils/date-parser.d.ts.map +1 -0
  113. package/dist/utils/date-parser.js +51 -0
  114. package/dist/utils/date-parser.test.d.ts +2 -0
  115. package/dist/utils/date-parser.test.d.ts.map +1 -0
  116. package/dist/utils/date-parser.test.js +34 -0
  117. package/dist/utils/id-generator.d.ts +3 -0
  118. package/dist/utils/id-generator.d.ts.map +1 -0
  119. package/dist/utils/id-generator.js +12 -0
  120. package/dist/utils/id-generator.test.d.ts +2 -0
  121. package/dist/utils/id-generator.test.d.ts.map +1 -0
  122. package/dist/utils/id-generator.test.js +30 -0
  123. package/dist/utils/index.d.ts +3 -0
  124. package/dist/utils/index.d.ts.map +1 -0
  125. package/dist/utils/index.js +9 -0
  126. package/package.json +60 -0
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseActions = parseActions;
4
+ const action_1 = require("../types/action");
5
+ function parseChainedCalls(raw) {
6
+ const calls = [];
7
+ const regex = /(\w+)\(([^)]*)\)/g;
8
+ let match;
9
+ while ((match = regex.exec(raw)) !== null) {
10
+ const method = match[1];
11
+ const argStr = match[2].trim();
12
+ const args = argStr
13
+ ? argStr.split(',').map((a) => a.trim().replace(/^['"]|['"]$/g, ''))
14
+ : [];
15
+ calls.push({ method, args });
16
+ }
17
+ return calls;
18
+ }
19
+ function buildActionArgs(calls) {
20
+ if (calls.length === 0)
21
+ return null;
22
+ const primary = calls[0];
23
+ const verb = primary.method.toLowerCase();
24
+ switch (verb) {
25
+ case 'replace':
26
+ return {
27
+ verb: action_1.ActionVerb.REPLACE,
28
+ target: primary.args[0] ?? '',
29
+ replacement: primary.args[1] ?? '',
30
+ };
31
+ case 'remove':
32
+ return {
33
+ verb: action_1.ActionVerb.REMOVE,
34
+ target: primary.args[0] ?? '',
35
+ };
36
+ case 'rename':
37
+ return {
38
+ verb: action_1.ActionVerb.RENAME,
39
+ from: primary.args[0] ?? '',
40
+ to: primary.args[1] ?? '',
41
+ };
42
+ case 'insert': {
43
+ const posCall = calls.find((c) => c.method === 'before' || c.method === 'after');
44
+ return {
45
+ verb: action_1.ActionVerb.INSERT,
46
+ content: primary.args[0] ?? '',
47
+ position: posCall?.method ?? 'after',
48
+ anchor: posCall?.args[0] ?? '',
49
+ };
50
+ }
51
+ case 'extract': {
52
+ const toCall = calls.find((c) => c.method === 'to');
53
+ return {
54
+ verb: action_1.ActionVerb.EXTRACT,
55
+ target: primary.args[0] ?? '',
56
+ destination: toCall?.args[0] ?? '',
57
+ };
58
+ }
59
+ case 'move': {
60
+ const toCall = calls.find((c) => c.method === 'to');
61
+ return {
62
+ verb: action_1.ActionVerb.MOVE,
63
+ target: primary.args[0] ?? '',
64
+ destination: toCall?.args[0] ?? '',
65
+ };
66
+ }
67
+ case 'wrapin':
68
+ case 'wrap': {
69
+ return {
70
+ verb: action_1.ActionVerb.WRAP_IN,
71
+ target: primary.args[0] ?? '',
72
+ wrapper: primary.args[1] ?? calls[1]?.args[0] ?? '',
73
+ };
74
+ }
75
+ default:
76
+ return {
77
+ verb: action_1.ActionVerb.GENERIC,
78
+ description: calls.map((c) => `${c.method}(${c.args.join(', ')})`).join('.'),
79
+ };
80
+ }
81
+ }
82
+ function parseActions(bodyLines) {
83
+ const actions = [];
84
+ for (const line of bodyLines) {
85
+ const trimmed = line.trim();
86
+ const actionMatch = trimmed.match(/^Action:\s*(.+)$/i);
87
+ if (!actionMatch)
88
+ continue;
89
+ const raw = actionMatch[1];
90
+ const calls = parseChainedCalls(raw);
91
+ const args = buildActionArgs(calls);
92
+ if (args) {
93
+ actions.push({ verb: args.verb, raw, args });
94
+ }
95
+ }
96
+ return actions;
97
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=action-parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-parser.test.d.ts","sourceRoot":"","sources":["../../src/scanner/action-parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const action_parser_1 = require("./action-parser");
5
+ (0, vitest_1.describe)('parseActions', () => {
6
+ (0, vitest_1.it)('parses replace action', () => {
7
+ const actions = (0, action_parser_1.parseActions)(['Action: replace(oldFunc, newFunc)']);
8
+ (0, vitest_1.expect)(actions).toHaveLength(1);
9
+ (0, vitest_1.expect)(actions[0].args).toEqual({
10
+ verb: 'replace',
11
+ target: 'oldFunc',
12
+ replacement: 'newFunc',
13
+ });
14
+ });
15
+ (0, vitest_1.it)('parses remove action', () => {
16
+ const actions = (0, action_parser_1.parseActions)(['Action: remove(deprecatedMethod)']);
17
+ (0, vitest_1.expect)(actions).toHaveLength(1);
18
+ (0, vitest_1.expect)(actions[0].args).toEqual({
19
+ verb: 'remove',
20
+ target: 'deprecatedMethod',
21
+ });
22
+ });
23
+ (0, vitest_1.it)('parses rename action', () => {
24
+ const actions = (0, action_parser_1.parseActions)(['Action: rename(oldName, newName)']);
25
+ (0, vitest_1.expect)(actions).toHaveLength(1);
26
+ (0, vitest_1.expect)(actions[0].args).toEqual({
27
+ verb: 'rename',
28
+ from: 'oldName',
29
+ to: 'newName',
30
+ });
31
+ });
32
+ (0, vitest_1.it)('parses insert with chained position', () => {
33
+ const actions = (0, action_parser_1.parseActions)(['Action: insert(validation).before(processData)']);
34
+ (0, vitest_1.expect)(actions).toHaveLength(1);
35
+ (0, vitest_1.expect)(actions[0].args).toEqual({
36
+ verb: 'insert',
37
+ content: 'validation',
38
+ position: 'before',
39
+ anchor: 'processData',
40
+ });
41
+ });
42
+ (0, vitest_1.it)('parses extract with chained to', () => {
43
+ const actions = (0, action_parser_1.parseActions)(['Action: extract(helperFn).to(utils)']);
44
+ (0, vitest_1.expect)(actions).toHaveLength(1);
45
+ (0, vitest_1.expect)(actions[0].args).toEqual({
46
+ verb: 'extract',
47
+ target: 'helperFn',
48
+ destination: 'utils',
49
+ });
50
+ });
51
+ (0, vitest_1.it)('parses move with chained to', () => {
52
+ const actions = (0, action_parser_1.parseActions)(['Action: move(Component).to(shared)']);
53
+ (0, vitest_1.expect)(actions).toHaveLength(1);
54
+ (0, vitest_1.expect)(actions[0].args).toEqual({
55
+ verb: 'move',
56
+ target: 'Component',
57
+ destination: 'shared',
58
+ });
59
+ });
60
+ (0, vitest_1.it)('parses wrap action', () => {
61
+ const actions = (0, action_parser_1.parseActions)(['Action: wrapIn(dangerousCall, tryCatch)']);
62
+ (0, vitest_1.expect)(actions).toHaveLength(1);
63
+ (0, vitest_1.expect)(actions[0].args).toEqual({
64
+ verb: 'wrapIn',
65
+ target: 'dangerousCall',
66
+ wrapper: 'tryCatch',
67
+ });
68
+ });
69
+ (0, vitest_1.it)('handles generic/unknown actions', () => {
70
+ const actions = (0, action_parser_1.parseActions)(['Action: customAction(arg1)']);
71
+ (0, vitest_1.expect)(actions).toHaveLength(1);
72
+ (0, vitest_1.expect)(actions[0].args.verb).toBe('generic');
73
+ });
74
+ (0, vitest_1.it)('handles multiple actions', () => {
75
+ const actions = (0, action_parser_1.parseActions)([
76
+ 'Action: replace(a, b)',
77
+ 'Some other text',
78
+ 'Action: remove(c)',
79
+ ]);
80
+ (0, vitest_1.expect)(actions).toHaveLength(2);
81
+ });
82
+ (0, vitest_1.it)('ignores non-action lines', () => {
83
+ const actions = (0, action_parser_1.parseActions)(['This is just a comment', '@author: Someone']);
84
+ (0, vitest_1.expect)(actions).toHaveLength(0);
85
+ });
86
+ (0, vitest_1.it)('handles empty input', () => {
87
+ const actions = (0, action_parser_1.parseActions)([]);
88
+ (0, vitest_1.expect)(actions).toHaveLength(0);
89
+ });
90
+ (0, vitest_1.it)('preserves raw action text', () => {
91
+ const actions = (0, action_parser_1.parseActions)(['Action: replace(foo, bar)']);
92
+ (0, vitest_1.expect)(actions[0].raw).toBe('replace(foo, bar)');
93
+ });
94
+ });
@@ -0,0 +1,15 @@
1
+ import type { Priority, RiskLevel, PerformanceImpact, TechnicalDebt } from '../types';
2
+ export interface ParsedAttributes {
3
+ author?: string;
4
+ assignee?: string;
5
+ priority?: Priority;
6
+ risk?: RiskLevel;
7
+ tags: string[];
8
+ dueDate?: string;
9
+ createdDate?: string;
10
+ performance?: PerformanceImpact;
11
+ debt?: TechnicalDebt;
12
+ relationships: string[];
13
+ }
14
+ export declare function parseAttributes(bodyLines: string[]): ParsedAttributes;
15
+ //# sourceMappingURL=attribute-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-parser.d.ts","sourceRoot":"","sources":["../../src/scanner/attribute-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAmB,iBAAiB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGtG,MAAM,WAAW,gBAAgB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAA;IACpB,aAAa,EAAE,MAAM,EAAE,CAAA;CACvB;AAoKD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAiBrE"}
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseAttributes = parseAttributes;
4
+ const utils_1 = require("../utils");
5
+ const PRIORITY_MAP = {
6
+ minimal: 'minimal',
7
+ m1: 'minimal',
8
+ low: 'low',
9
+ l2: 'low',
10
+ medium: 'medium',
11
+ med: 'medium',
12
+ m3: 'medium',
13
+ high: 'high',
14
+ h4: 'high',
15
+ critical: 'critical',
16
+ c5: 'critical',
17
+ };
18
+ const RISK_MAP = {
19
+ minimal: 'minimal',
20
+ m1: 'minimal',
21
+ low: 'low',
22
+ l2: 'low',
23
+ moderate: 'moderate',
24
+ mod: 'moderate',
25
+ m3: 'moderate',
26
+ severe: 'severe',
27
+ s2: 'severe',
28
+ critical: 'critical',
29
+ c3: 'critical',
30
+ };
31
+ function parsePerformance(value) {
32
+ const match = value.match(/^(\d+(?:\.\d+)?)\s*(ms|s|us)->(\d+(?:\.\d+)?)\s*(ms|s|us)$/);
33
+ if (!match)
34
+ return undefined;
35
+ return { before: match[1] + match[2], after: match[3] + match[4], unit: match[4] };
36
+ }
37
+ function parseDebt(value) {
38
+ const parts = value.split('|').map((s) => s.trim());
39
+ const hoursMatch = parts[0].match(/^(\d+(?:\.\d+)?)\s*h$/);
40
+ if (!hoursMatch)
41
+ return undefined;
42
+ let compounding = 'low';
43
+ for (const part of parts.slice(1)) {
44
+ const compMatch = part.match(/^compounding:\s*(low|medium|high)$/i);
45
+ if (compMatch)
46
+ compounding = compMatch[1].toLowerCase();
47
+ }
48
+ return { hours: parseFloat(hoursMatch[1]), compounding };
49
+ }
50
+ function applyKeyValue(key, value, attrs) {
51
+ const lowerKey = key.toLowerCase().trim();
52
+ switch (lowerKey) {
53
+ case 'author':
54
+ attrs.author = value;
55
+ break;
56
+ case 'assignee':
57
+ attrs.assignee = value;
58
+ break;
59
+ case 'priority':
60
+ attrs.priority = PRIORITY_MAP[value.toLowerCase()] ?? undefined;
61
+ break;
62
+ case 'risk':
63
+ attrs.risk = RISK_MAP[value.toLowerCase()] ?? undefined;
64
+ break;
65
+ case 'tags':
66
+ attrs.tags.push(...value.split(',').map((t) => t.trim()).filter(Boolean));
67
+ break;
68
+ case 'due':
69
+ case 'due date':
70
+ case 'duedate': {
71
+ const parsed = (0, utils_1.parseDate)(value);
72
+ if (parsed)
73
+ attrs.dueDate = parsed;
74
+ break;
75
+ }
76
+ case 'created':
77
+ case 'created date':
78
+ case 'createddate': {
79
+ const parsed = (0, utils_1.parseDate)(value);
80
+ if (parsed)
81
+ attrs.createdDate = parsed;
82
+ break;
83
+ }
84
+ case 'performance':
85
+ attrs.performance = parsePerformance(value) ?? attrs.performance;
86
+ break;
87
+ case 'debt':
88
+ case 'technical debt':
89
+ attrs.debt = parseDebt(value) ?? attrs.debt;
90
+ break;
91
+ case 'compounding':
92
+ if (attrs.debt) {
93
+ const rate = value.toLowerCase();
94
+ if (rate === 'low' || rate === 'medium' || rate === 'high') {
95
+ attrs.debt = { ...attrs.debt, compounding: rate };
96
+ }
97
+ }
98
+ break;
99
+ case 'blocks':
100
+ case 'blocked by':
101
+ case 'depends on':
102
+ case 'related':
103
+ attrs.relationships.push(...value.split(',').map((r) => r.trim()).filter(Boolean));
104
+ break;
105
+ }
106
+ }
107
+ function parseAtPrefix(line, attrs) {
108
+ const match = line.match(/^@(\w+):?\s+(.+)/);
109
+ if (!match)
110
+ return false;
111
+ applyKeyValue(match[1], match[2], attrs);
112
+ return true;
113
+ }
114
+ function parseCompactBracket(line, attrs) {
115
+ const match = line.match(/^\[(.+)\]$/);
116
+ if (!match)
117
+ return false;
118
+ const inner = match[1];
119
+ const segments = inner.split('|').map((s) => s.trim());
120
+ for (const seg of segments) {
121
+ // Arrow assignment: "Cody Jones → Austin Lowell"
122
+ const arrowMatch = seg.match(/^(.+?)\s*(?:→|->)+\s*(.+)$/);
123
+ if (arrowMatch) {
124
+ attrs.author = arrowMatch[1].trim();
125
+ attrs.assignee = arrowMatch[2].trim();
126
+ continue;
127
+ }
128
+ // Key: value
129
+ const kvMatch = seg.match(/^(\w[\w\s]*?):\s*(.+)$/);
130
+ if (kvMatch) {
131
+ applyKeyValue(kvMatch[1], kvMatch[2], attrs);
132
+ continue;
133
+ }
134
+ // Duration shorthand: 3d, 8h, 2w
135
+ const durationMatch = seg.match(/^(\d+[dhwmy])$/);
136
+ if (durationMatch) {
137
+ const debtMatch = seg.match(/^(\d+)h$/);
138
+ if (debtMatch) {
139
+ attrs.debt = { hours: parseInt(debtMatch[1], 10), compounding: 'low' };
140
+ }
141
+ else {
142
+ const parsed = (0, utils_1.parseDate)('+' + seg);
143
+ if (parsed)
144
+ attrs.dueDate = parsed;
145
+ }
146
+ continue;
147
+ }
148
+ // Priority/risk shorthand
149
+ const lower = seg.toLowerCase();
150
+ if (PRIORITY_MAP[lower]) {
151
+ attrs.priority = PRIORITY_MAP[lower];
152
+ }
153
+ else if (RISK_MAP[lower]) {
154
+ attrs.risk = RISK_MAP[lower];
155
+ }
156
+ }
157
+ return true;
158
+ }
159
+ function parseKeyValue(line, attrs) {
160
+ const match = line.match(/^([A-Z][\w\s]+):\s+(.+)/);
161
+ if (!match)
162
+ return false;
163
+ applyKeyValue(match[1], match[2], attrs);
164
+ return true;
165
+ }
166
+ function parseAttributes(bodyLines) {
167
+ const attrs = {
168
+ tags: [],
169
+ relationships: [],
170
+ };
171
+ for (const line of bodyLines) {
172
+ const trimmed = line.trim();
173
+ if (!trimmed)
174
+ continue;
175
+ // Try each strategy in order
176
+ if (parseAtPrefix(trimmed, attrs))
177
+ continue;
178
+ if (parseCompactBracket(trimmed, attrs))
179
+ continue;
180
+ parseKeyValue(trimmed, attrs);
181
+ }
182
+ return attrs;
183
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attribute-parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribute-parser.test.d.ts","sourceRoot":"","sources":["../../src/scanner/attribute-parser.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const attribute_parser_1 = require("./attribute-parser");
5
+ (0, vitest_1.describe)('parseAttributes', () => {
6
+ (0, vitest_1.describe)('@ prefix strategy', () => {
7
+ (0, vitest_1.it)('parses @author', () => {
8
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@author: Cody Jones']);
9
+ (0, vitest_1.expect)(attrs.author).toBe('Cody Jones');
10
+ });
11
+ (0, vitest_1.it)('parses @assignee', () => {
12
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@assignee: Austin Lowell']);
13
+ (0, vitest_1.expect)(attrs.assignee).toBe('Austin Lowell');
14
+ });
15
+ (0, vitest_1.it)('parses @priority', () => {
16
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@priority: critical']);
17
+ (0, vitest_1.expect)(attrs.priority).toBe('critical');
18
+ });
19
+ (0, vitest_1.it)('parses @tags', () => {
20
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@tags: perf, security, ux']);
21
+ (0, vitest_1.expect)(attrs.tags).toEqual(['perf', 'security', 'ux']);
22
+ });
23
+ (0, vitest_1.it)('parses @due with ISO date', () => {
24
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@due: 2026-03-01']);
25
+ (0, vitest_1.expect)(attrs.dueDate).toBe('2026-03-01');
26
+ });
27
+ (0, vitest_1.it)('parses @due with relative date', () => {
28
+ const attrs = (0, attribute_parser_1.parseAttributes)(['@due: +2w']);
29
+ (0, vitest_1.expect)(attrs.dueDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
30
+ });
31
+ });
32
+ (0, vitest_1.describe)('compact bracket strategy', () => {
33
+ (0, vitest_1.it)('parses arrow assignment', () => {
34
+ const attrs = (0, attribute_parser_1.parseAttributes)(['[Cody Jones → Austin Lowell | 3d | due: 2/24/2026]']);
35
+ (0, vitest_1.expect)(attrs.author).toBe('Cody Jones');
36
+ (0, vitest_1.expect)(attrs.assignee).toBe('Austin Lowell');
37
+ (0, vitest_1.expect)(attrs.dueDate).toBe('2026-02-24');
38
+ });
39
+ (0, vitest_1.it)('parses hour-based debt', () => {
40
+ const attrs = (0, attribute_parser_1.parseAttributes)(['[8h | compounding: high]']);
41
+ (0, vitest_1.expect)(attrs.debt).toEqual({ hours: 8, compounding: 'high' });
42
+ });
43
+ (0, vitest_1.it)('parses priority shorthand', () => {
44
+ const attrs = (0, attribute_parser_1.parseAttributes)(['[critical]']);
45
+ (0, vitest_1.expect)(attrs.priority).toBe('critical');
46
+ });
47
+ });
48
+ (0, vitest_1.describe)('key-value strategy', () => {
49
+ (0, vitest_1.it)('parses Priority: value', () => {
50
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Priority: high']);
51
+ (0, vitest_1.expect)(attrs.priority).toBe('high');
52
+ });
53
+ (0, vitest_1.it)('parses Tags: comma-separated', () => {
54
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Tags: ui, backend, api']);
55
+ (0, vitest_1.expect)(attrs.tags).toEqual(['ui', 'backend', 'api']);
56
+ });
57
+ (0, vitest_1.it)('parses Risk: value', () => {
58
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Risk: severe']);
59
+ (0, vitest_1.expect)(attrs.risk).toBe('severe');
60
+ });
61
+ (0, vitest_1.it)('parses Blocks relationship', () => {
62
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Blocks: N-abc123, N-def456']);
63
+ (0, vitest_1.expect)(attrs.relationships).toEqual(['N-abc123', 'N-def456']);
64
+ });
65
+ });
66
+ (0, vitest_1.describe)('performance impact', () => {
67
+ (0, vitest_1.it)('parses performance notation', () => {
68
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Performance: 2000ms->100ms']);
69
+ (0, vitest_1.expect)(attrs.performance).toEqual({ before: '2000ms', after: '100ms', unit: 'ms' });
70
+ });
71
+ });
72
+ (0, vitest_1.describe)('technical debt', () => {
73
+ (0, vitest_1.it)('parses debt with compounding', () => {
74
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Debt: 8h | compounding: high']);
75
+ (0, vitest_1.expect)(attrs.debt).toEqual({ hours: 8, compounding: 'high' });
76
+ });
77
+ (0, vitest_1.it)('parses debt without compounding', () => {
78
+ const attrs = (0, attribute_parser_1.parseAttributes)(['Debt: 4h']);
79
+ (0, vitest_1.expect)(attrs.debt).toEqual({ hours: 4, compounding: 'low' });
80
+ });
81
+ });
82
+ (0, vitest_1.describe)('edge cases', () => {
83
+ (0, vitest_1.it)('handles empty body', () => {
84
+ const attrs = (0, attribute_parser_1.parseAttributes)([]);
85
+ (0, vitest_1.expect)(attrs.tags).toEqual([]);
86
+ (0, vitest_1.expect)(attrs.relationships).toEqual([]);
87
+ });
88
+ (0, vitest_1.it)('handles blank lines', () => {
89
+ const attrs = (0, attribute_parser_1.parseAttributes)(['', ' ', '@author: Test']);
90
+ (0, vitest_1.expect)(attrs.author).toBe('Test');
91
+ });
92
+ });
93
+ });
@@ -0,0 +1,3 @@
1
+ import type { Notation, TrackerConfig } from '../types';
2
+ export declare function scanFiles(config: TrackerConfig, rootDir?: string): Promise<Notation[]>;
3
+ //# sourceMappingURL=file-scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-scanner.d.ts","sourceRoot":"","sources":["../../src/scanner/file-scanner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGvD,wBAAsB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAmB5F"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.scanFiles = scanFiles;
40
+ const fs = __importStar(require("fs"));
41
+ const fast_glob_1 = __importDefault(require("fast-glob"));
42
+ const notation_parser_1 = require("./notation-parser");
43
+ async function scanFiles(config, rootDir) {
44
+ const root = rootDir ?? config.rootDir;
45
+ const files = await (0, fast_glob_1.default)(config.include, {
46
+ cwd: root,
47
+ ignore: config.exclude,
48
+ absolute: true,
49
+ onlyFiles: true,
50
+ });
51
+ const allNotations = [];
52
+ for (const file of files) {
53
+ const content = await fs.promises.readFile(file, 'utf-8');
54
+ const notations = (0, notation_parser_1.parseFileContent)(file, content, config.idPrefix);
55
+ allNotations.push(...notations);
56
+ }
57
+ return allNotations;
58
+ }
@@ -0,0 +1,6 @@
1
+ export { parseAttributes } from './attribute-parser';
2
+ export type { ParsedAttributes } from './attribute-parser';
3
+ export { parseActions } from './action-parser';
4
+ export { parseFileContent } from './notation-parser';
5
+ export { scanFiles } from './file-scanner';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scanFiles = exports.parseFileContent = exports.parseActions = exports.parseAttributes = void 0;
4
+ var attribute_parser_1 = require("./attribute-parser");
5
+ Object.defineProperty(exports, "parseAttributes", { enumerable: true, get: function () { return attribute_parser_1.parseAttributes; } });
6
+ var action_parser_1 = require("./action-parser");
7
+ Object.defineProperty(exports, "parseActions", { enumerable: true, get: function () { return action_parser_1.parseActions; } });
8
+ var notation_parser_1 = require("./notation-parser");
9
+ Object.defineProperty(exports, "parseFileContent", { enumerable: true, get: function () { return notation_parser_1.parseFileContent; } });
10
+ var file_scanner_1 = require("./file-scanner");
11
+ Object.defineProperty(exports, "scanFiles", { enumerable: true, get: function () { return file_scanner_1.scanFiles; } });
@@ -0,0 +1,3 @@
1
+ import type { Notation } from '../types';
2
+ export declare function parseFileContent(filePath: string, content: string, idPrefix?: string): Notation[];
3
+ //# sourceMappingURL=notation-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notation-parser.d.ts","sourceRoot":"","sources":["../../src/scanner/notation-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,UAAU,CAAA;AAQpD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAY,GAAG,QAAQ,EAAE,CAoFtG"}