@schnick371/devsteps-shared 0.0.1 → 0.5.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 (104) hide show
  1. package/README.md +66 -7
  2. package/dist/core/add.d.ts +23 -0
  3. package/dist/core/add.d.ts.map +1 -0
  4. package/dist/core/add.js +102 -0
  5. package/dist/core/add.js.map +1 -0
  6. package/dist/core/archive.d.ts +24 -0
  7. package/dist/core/archive.d.ts.map +1 -0
  8. package/dist/core/archive.js +109 -0
  9. package/dist/core/archive.js.map +1 -0
  10. package/dist/core/bulk-update.d.ts +34 -0
  11. package/dist/core/bulk-update.d.ts.map +1 -0
  12. package/dist/core/bulk-update.js +141 -0
  13. package/dist/core/bulk-update.js.map +1 -0
  14. package/dist/core/context.d.ts +54 -0
  15. package/dist/core/context.d.ts.map +1 -0
  16. package/dist/core/context.js +198 -0
  17. package/dist/core/context.js.map +1 -0
  18. package/dist/core/get.d.ts +10 -0
  19. package/dist/core/get.d.ts.map +1 -0
  20. package/dist/core/get.js +28 -0
  21. package/dist/core/get.js.map +1 -0
  22. package/dist/core/index.d.ts +9 -0
  23. package/dist/core/index.d.ts.map +1 -0
  24. package/dist/core/index.js +9 -0
  25. package/dist/core/index.js.map +1 -0
  26. package/dist/core/list.d.ts +19 -0
  27. package/dist/core/list.d.ts.map +1 -0
  28. package/dist/core/list.js +64 -0
  29. package/dist/core/list.js.map +1 -0
  30. package/dist/core/update.d.ts +23 -0
  31. package/dist/core/update.d.ts.map +1 -0
  32. package/dist/core/update.js +118 -0
  33. package/dist/core/update.js.map +1 -0
  34. package/dist/core/validation.d.ts +28 -0
  35. package/dist/core/validation.d.ts.map +1 -0
  36. package/dist/core/validation.js +205 -0
  37. package/dist/core/validation.js.map +1 -0
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +5 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/schemas/index.d.ts +286 -0
  43. package/dist/schemas/index.d.ts.map +1 -0
  44. package/dist/schemas/index.js +200 -0
  45. package/dist/schemas/index.js.map +1 -0
  46. package/dist/schemas/project.d.ts +134 -0
  47. package/dist/schemas/project.d.ts.map +1 -0
  48. package/dist/schemas/project.js +54 -0
  49. package/dist/schemas/project.js.map +1 -0
  50. package/dist/schemas/relationships.d.ts +30 -0
  51. package/dist/schemas/relationships.d.ts.map +1 -0
  52. package/dist/schemas/relationships.js +41 -0
  53. package/dist/schemas/relationships.js.map +1 -0
  54. package/dist/types/commands.d.ts +92 -0
  55. package/dist/types/commands.d.ts.map +1 -0
  56. package/dist/types/commands.js +14 -0
  57. package/dist/types/commands.js.map +1 -0
  58. package/dist/types/index.d.ts +3 -0
  59. package/dist/types/index.d.ts.map +1 -0
  60. package/dist/types/index.js +2 -0
  61. package/dist/types/index.js.map +1 -0
  62. package/dist/utils/cache.d.ts +80 -0
  63. package/dist/utils/cache.d.ts.map +1 -0
  64. package/dist/utils/cache.js +169 -0
  65. package/dist/utils/cache.js.map +1 -0
  66. package/dist/utils/index.d.ts +72 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/index.js +148 -0
  69. package/dist/utils/index.js.map +1 -0
  70. package/package.json +48 -15
  71. package/src/core/add.js.map +1 -0
  72. package/src/core/add.ts +145 -0
  73. package/src/core/archive.js.map +1 -0
  74. package/src/core/archive.ts +153 -0
  75. package/src/core/bulk-update.js.map +1 -0
  76. package/src/core/bulk-update.ts +180 -0
  77. package/src/core/context.js.map +1 -0
  78. package/src/core/context.ts +269 -0
  79. package/src/core/get.js.map +1 -0
  80. package/src/core/get.ts +39 -0
  81. package/src/core/index.js.map +1 -0
  82. package/src/core/index.ts +26 -0
  83. package/src/core/list.js.map +1 -0
  84. package/src/core/list.ts +96 -0
  85. package/src/core/update.js.map +1 -0
  86. package/src/core/update.ts +154 -0
  87. package/src/core/validation.ts +252 -0
  88. package/src/index.js +21 -0
  89. package/src/index.js.map +1 -0
  90. package/src/index.ts +4 -0
  91. package/src/schemas/index.js.map +1 -0
  92. package/src/schemas/index.ts +226 -0
  93. package/src/schemas/project.js.map +1 -0
  94. package/src/schemas/project.ts +73 -0
  95. package/src/schemas/relationships.ts +48 -0
  96. package/src/types/commands.js.map +1 -0
  97. package/src/types/commands.ts +116 -0
  98. package/src/types/index.js.map +1 -0
  99. package/src/types/index.ts +13 -0
  100. package/src/utils/cache.js.map +1 -0
  101. package/src/utils/cache.ts +200 -0
  102. package/src/utils/index.js.map +1 -0
  103. package/src/utils/index.ts +170 -0
  104. package/index.js +0 -6
@@ -0,0 +1,198 @@
1
+ import { promises as fs } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { CACHE_CONFIG, getCache } from '../utils/cache.js';
4
+ /**
5
+ * Analyze packages from workspace (with caching)
6
+ */
7
+ export async function analyzePackages(projectDir) {
8
+ const cache = getCache();
9
+ const cacheKey = `package_analysis:${projectDir}`;
10
+ const packagesDir = path.join(projectDir, 'packages');
11
+ // Try cache first
12
+ const cached = cache.get(cacheKey, CACHE_CONFIG.PACKAGE_ANALYSIS_TTL, packagesDir);
13
+ if (cached) {
14
+ return cached;
15
+ }
16
+ const packages = [];
17
+ try {
18
+ const entries = await fs.readdir(packagesDir, { withFileTypes: true });
19
+ for (const entry of entries) {
20
+ if (entry.isDirectory()) {
21
+ const pkgPath = path.join(packagesDir, entry.name, 'package.json');
22
+ try {
23
+ const content = await fs.readFile(pkgPath, 'utf-8');
24
+ const pkg = JSON.parse(content);
25
+ packages.push({
26
+ name: pkg.name || entry.name,
27
+ purpose: pkg.description || 'No description',
28
+ dependencies: Object.keys(pkg.dependencies || {}),
29
+ });
30
+ }
31
+ catch {
32
+ // Skip if no package.json
33
+ }
34
+ }
35
+ }
36
+ }
37
+ catch {
38
+ // No packages directory
39
+ }
40
+ // Cache the result
41
+ cache.set(cacheKey, packages, packagesDir);
42
+ return packages;
43
+ }
44
+ /**
45
+ * Get item counts from index (with caching)
46
+ */
47
+ export async function getItemCounts(devcrumbsDir) {
48
+ const cache = getCache();
49
+ const cacheKey = `item_counts:${devcrumbsDir}`;
50
+ const indexPath = path.join(devcrumbsDir, 'index.json');
51
+ // Try cache first
52
+ const cached = cache.get(cacheKey, CACHE_CONFIG.ITEM_COUNTS_TTL, indexPath);
53
+ if (cached) {
54
+ return cached;
55
+ }
56
+ try {
57
+ const content = await fs.readFile(indexPath, 'utf-8');
58
+ const index = JSON.parse(content);
59
+ const counts = {
60
+ total: index.items.length,
61
+ by_type: {},
62
+ by_status: {},
63
+ };
64
+ for (const item of index.items) {
65
+ counts.by_type[item.type] = (counts.by_type[item.type] || 0) + 1;
66
+ counts.by_status[item.status] = (counts.by_status[item.status] || 0) + 1;
67
+ }
68
+ // Cache the result
69
+ cache.set(cacheKey, counts, indexPath);
70
+ return counts;
71
+ }
72
+ catch {
73
+ return { total: 0, by_type: {}, by_status: {} };
74
+ }
75
+ }
76
+ /**
77
+ * Get recent updates (last N days) (with caching)
78
+ */
79
+ export async function getRecentUpdates(devcrumbsDir, days) {
80
+ const cache = getCache();
81
+ const cacheKey = `recent_updates:${devcrumbsDir}:${days}`;
82
+ const indexPath = path.join(devcrumbsDir, 'index.json');
83
+ // Try cache first
84
+ const cached = cache.get(cacheKey, CACHE_CONFIG.RECENT_UPDATES_TTL, indexPath);
85
+ if (cached) {
86
+ return cached;
87
+ }
88
+ const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
89
+ try {
90
+ const content = await fs.readFile(indexPath, 'utf-8');
91
+ const index = JSON.parse(content);
92
+ const updates = index.items
93
+ .filter((item) => new Date(item.updated).getTime() > cutoff)
94
+ .sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime())
95
+ .slice(0, 10)
96
+ .map((item) => ({
97
+ id: item.id,
98
+ type: item.type,
99
+ title: item.title,
100
+ updated: item.updated,
101
+ }));
102
+ // Cache the result
103
+ cache.set(cacheKey, updates, indexPath);
104
+ return updates;
105
+ }
106
+ catch {
107
+ return [];
108
+ }
109
+ }
110
+ /**
111
+ * Read PROJECT.md if exists (with caching)
112
+ */
113
+ export async function readProjectMd(devcrumbsDir) {
114
+ const cache = getCache();
115
+ const cacheKey = `project_md:${devcrumbsDir}`;
116
+ const projectPath = path.join(devcrumbsDir, 'PROJECT.md');
117
+ // Try cache first
118
+ const cached = cache.get(cacheKey, CACHE_CONFIG.PROJECT_MD_TTL, projectPath);
119
+ if (cached !== null) {
120
+ return cached;
121
+ }
122
+ try {
123
+ const content = await fs.readFile(projectPath, 'utf-8');
124
+ // Parse markdown to extract context (simplified)
125
+ // In production, use a proper markdown parser
126
+ const techStack = {};
127
+ const packages = [];
128
+ // Extract tech stack (look for bullet points after "### Tech Stack")
129
+ const techStackMatch = content.match(/### Tech Stack\n([\s\S]*?)(?=\n###|$)/);
130
+ if (techStackMatch) {
131
+ const lines = techStackMatch[1].split('\n');
132
+ for (const line of lines) {
133
+ const match = line.match(/- \*\*(.+?)\*\*: (.+)/);
134
+ if (match) {
135
+ techStack[match[1]] = match[2];
136
+ }
137
+ }
138
+ }
139
+ // Extract project type
140
+ const projectTypeMatch = content.match(/### Project Type\n(.+)/);
141
+ const projectType = projectTypeMatch?.[1] || 'Unknown';
142
+ const result = {
143
+ tech_stack: techStack,
144
+ packages,
145
+ project_type: projectType,
146
+ };
147
+ // Cache the result
148
+ cache.set(cacheKey, result, projectPath);
149
+ return result;
150
+ }
151
+ catch {
152
+ // Cache the null result (file doesn't exist)
153
+ cache.set(cacheKey, null);
154
+ return null;
155
+ }
156
+ }
157
+ /**
158
+ * Estimate token count (rough approximation: 1 token ≈ 4 chars)
159
+ */
160
+ export function estimateTokens(obj) {
161
+ const str = JSON.stringify(obj);
162
+ return Math.ceil(str.length / 4);
163
+ }
164
+ /**
165
+ * Get quick context
166
+ */
167
+ export async function getQuickContext(projectDir, devcrumbsDir) {
168
+ const packages = await analyzePackages(projectDir);
169
+ const activeItems = await getItemCounts(devcrumbsDir);
170
+ const recentUpdates = await getRecentUpdates(devcrumbsDir, 7);
171
+ const staticContext = await readProjectMd(devcrumbsDir);
172
+ const response = {
173
+ context_level: 'quick',
174
+ tokens_used: 0,
175
+ dynamic_context: {
176
+ packages,
177
+ active_items: activeItems,
178
+ recent_updates: recentUpdates,
179
+ },
180
+ };
181
+ if (staticContext) {
182
+ response.static_context = staticContext;
183
+ }
184
+ response.tokens_used = estimateTokens(response);
185
+ // Add suggestions
186
+ const suggestions = [];
187
+ if (!staticContext) {
188
+ suggestions.push('Consider creating .devcrumbs/PROJECT.md for static context');
189
+ }
190
+ if (activeItems.by_status.blocked > 0) {
191
+ suggestions.push(`${activeItems.by_status.blocked} blocked items need attention`);
192
+ }
193
+ if (suggestions.length > 0) {
194
+ response.suggestions = suggestions;
195
+ }
196
+ return response;
197
+ }
198
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ItemMetadata } from '../schemas/index.js';
2
+ export interface GetItemResult {
3
+ metadata: ItemMetadata;
4
+ description: string;
5
+ }
6
+ /**
7
+ * Core business logic for getting an item
8
+ */
9
+ export declare function getItem(devcrumbsDir: string, itemId: string): Promise<GetItemResult>;
10
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../src/core/get.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAyB1F"}
@@ -0,0 +1,28 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { TYPE_TO_DIRECTORY, parseItemId } from '../utils/index.js';
4
+ /**
5
+ * Core business logic for getting an item
6
+ */
7
+ export async function getItem(devcrumbsDir, itemId) {
8
+ if (!existsSync(devcrumbsDir)) {
9
+ throw new Error('Project not initialized. Run devcrumbs-init first.');
10
+ }
11
+ const parsed = parseItemId(itemId);
12
+ if (!parsed) {
13
+ throw new Error(`Invalid item ID: ${itemId}`);
14
+ }
15
+ const typeFolder = TYPE_TO_DIRECTORY[parsed.type];
16
+ const metadataPath = join(devcrumbsDir, typeFolder, `${itemId}.json`);
17
+ const descriptionPath = join(devcrumbsDir, typeFolder, `${itemId}.md`);
18
+ if (!existsSync(metadataPath)) {
19
+ throw new Error(`Item not found: ${itemId}`);
20
+ }
21
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
22
+ const description = existsSync(descriptionPath) ? readFileSync(descriptionPath, 'utf-8') : '';
23
+ return {
24
+ metadata,
25
+ description,
26
+ };
27
+ }
28
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/core/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOnE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,YAAoB,EAAE,MAAc;IAChE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACxE,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;IACtE,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,GAAG,MAAM,KAAK,CAAC,CAAC;IAEvE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAiB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9F,OAAO;QACL,QAAQ;QACR,WAAW;KACZ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { addItem, type AddItemArgs, type AddItemResult } from './add.js';
2
+ export { getItem, type GetItemResult } from './get.js';
3
+ export { listItems, type ListItemsArgs, type ListItemsResult } from './list.js';
4
+ export { updateItem, type UpdateItemArgs, type UpdateItemResult } from './update.js';
5
+ export { archiveItem, type ArchiveItemResult, purgeItems, type PurgeItemsArgs, type PurgeItemsResult, } from './archive.js';
6
+ export { getQuickContext, analyzePackages, getItemCounts, getRecentUpdates, readProjectMd, estimateTokens, } from './context.js';
7
+ export { bulkUpdateItems, bulkAddTags, bulkRemoveTags, type BulkUpdateResult, } from './bulk-update.js';
8
+ export { validateRelationship, type ValidationResult, type WorkItem } from './validation.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EACL,WAAW,EACX,KAAK,iBAAiB,EACtB,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,WAAW,EACX,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { addItem } from './add.js';
2
+ export { getItem } from './get.js';
3
+ export { listItems } from './list.js';
4
+ export { updateItem } from './update.js';
5
+ export { archiveItem, purgeItems, } from './archive.js';
6
+ export { getQuickContext, analyzePackages, getItemCounts, getRecentUpdates, readProjectMd, estimateTokens, } from './context.js';
7
+ export { bulkUpdateItems, bulkAddTags, bulkRemoveTags, } from './bulk-update.js';
8
+ export { validateRelationship } from './validation.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwC,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,OAAO,EAAsB,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAA4C,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAA8C,MAAM,aAAa,CAAC;AACrF,OAAO,EACL,WAAW,EAEX,UAAU,GAGX,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,WAAW,EACX,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAwC,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { DevCrumbsIndex, EisenhowerQuadrant, ItemStatus, ItemType, Priority } from '../schemas/index.js';
2
+ export interface ListItemsArgs {
3
+ type?: ItemType;
4
+ status?: ItemStatus;
5
+ priority?: Priority;
6
+ assignee?: string;
7
+ tags?: string[];
8
+ eisenhower?: EisenhowerQuadrant;
9
+ limit?: number;
10
+ }
11
+ export interface ListItemsResult {
12
+ count: number;
13
+ items: DevCrumbsIndex['items'];
14
+ }
15
+ /**
16
+ * Core business logic for listing items with filters
17
+ */
18
+ export declare function listItems(devcrumbsDir: string, args?: ListItemsArgs): Promise<ListItemsResult>;
19
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/core/list.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,eAAe,CAAC,CA+D1B"}
@@ -0,0 +1,64 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { TYPE_TO_DIRECTORY } from '../utils/index.js';
4
+ /**
5
+ * Core business logic for listing items with filters
6
+ */
7
+ export async function listItems(devcrumbsDir, args = {}) {
8
+ if (!existsSync(devcrumbsDir)) {
9
+ throw new Error('Project not initialized. Run devcrumbs-init first.');
10
+ }
11
+ const indexPath = join(devcrumbsDir, 'index.json');
12
+ const index = JSON.parse(readFileSync(indexPath, 'utf-8'));
13
+ let items = [...index.items];
14
+ // Apply filters
15
+ if (args.type) {
16
+ items = items.filter((i) => i.type === args.type);
17
+ }
18
+ if (args.status) {
19
+ items = items.filter((i) => i.status === args.status);
20
+ }
21
+ if (args.priority) {
22
+ items = items.filter((i) => i.priority === args.priority);
23
+ }
24
+ if (args.assignee) {
25
+ // Load full metadata for assignee filter
26
+ items = items.filter((i) => {
27
+ const metadataPath = join(devcrumbsDir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
28
+ if (!existsSync(metadataPath))
29
+ return false;
30
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
31
+ return metadata.assignee === args.assignee;
32
+ });
33
+ }
34
+ if (args.tags && args.tags.length > 0) {
35
+ // Load full metadata for tags filter
36
+ const filterTags = args.tags;
37
+ items = items.filter((i) => {
38
+ const metadataPath = join(devcrumbsDir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
39
+ if (!existsSync(metadataPath))
40
+ return false;
41
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
42
+ return filterTags.every((tag) => metadata.tags.includes(tag));
43
+ });
44
+ }
45
+ if (args.eisenhower) {
46
+ // Load full metadata for eisenhower filter
47
+ items = items.filter((i) => {
48
+ const metadataPath = join(devcrumbsDir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
49
+ if (!existsSync(metadataPath))
50
+ return false;
51
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
52
+ return metadata.eisenhower === args.eisenhower;
53
+ });
54
+ }
55
+ // Apply limit
56
+ if (args.limit && args.limit > 0) {
57
+ items = items.slice(0, args.limit);
58
+ }
59
+ return {
60
+ count: items.length,
61
+ items,
62
+ };
63
+ }
64
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/core/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { EisenhowerQuadrant, ItemMetadata, ItemStatus, Priority } from '../schemas/index.js';
2
+ export interface UpdateItemArgs {
3
+ id: string;
4
+ status?: ItemStatus;
5
+ priority?: Priority;
6
+ eisenhower?: EisenhowerQuadrant;
7
+ superseded_by?: string;
8
+ title?: string;
9
+ description?: string;
10
+ append_description?: string;
11
+ assignee?: string;
12
+ tags?: string[];
13
+ affected_paths?: string[];
14
+ }
15
+ export interface UpdateItemResult {
16
+ metadata: ItemMetadata;
17
+ oldStatus: ItemStatus;
18
+ }
19
+ /**
20
+ * Core business logic for updating an item
21
+ */
22
+ export declare function updateItem(devcrumbsDir: string, args: UpdateItemArgs): Promise<UpdateItemResult>;
23
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/core/update.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAqH3B"}
@@ -0,0 +1,118 @@
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { TYPE_TO_DIRECTORY, getCurrentTimestamp, parseItemId } from '../utils/index.js';
4
+ /**
5
+ * Core business logic for updating an item
6
+ */
7
+ export async function updateItem(devcrumbsDir, args) {
8
+ if (!existsSync(devcrumbsDir)) {
9
+ throw new Error('Project not initialized. Run devcrumbs-init first.');
10
+ }
11
+ const parsed = parseItemId(args.id);
12
+ if (!parsed) {
13
+ throw new Error(`Invalid item ID: ${args.id}`);
14
+ }
15
+ const typeFolder = TYPE_TO_DIRECTORY[parsed.type];
16
+ const metadataPath = join(devcrumbsDir, typeFolder, `${args.id}.json`);
17
+ const descriptionPath = join(devcrumbsDir, typeFolder, `${args.id}.md`);
18
+ if (!existsSync(metadataPath)) {
19
+ throw new Error(`Item not found: ${args.id}`);
20
+ }
21
+ // Read and update metadata
22
+ const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
23
+ const oldStatus = metadata.status;
24
+ // Validate status transitions (parent-child rules)
25
+ if (args.status === 'done') {
26
+ // Helper function to validate children are complete
27
+ const validateChildren = (relationshipType) => {
28
+ const children = metadata.linked_items[relationshipType];
29
+ if (children.length > 0) {
30
+ const openChildren = [];
31
+ for (const childId of children) {
32
+ const childParsed = parseItemId(childId);
33
+ if (childParsed) {
34
+ const childFolder = TYPE_TO_DIRECTORY[childParsed.type];
35
+ const childPath = join(devcrumbsDir, childFolder, `${childId}.json`);
36
+ if (existsSync(childPath)) {
37
+ const childMeta = JSON.parse(readFileSync(childPath, 'utf-8'));
38
+ if (childMeta.status !== 'done' && childMeta.status !== 'cancelled' && childMeta.status !== 'obsolete') {
39
+ openChildren.push(childId);
40
+ }
41
+ }
42
+ }
43
+ }
44
+ if (openChildren.length > 0) {
45
+ const relationLabel = relationshipType === 'implemented-by' ? 'implementation' : 'test';
46
+ throw new Error(`Cannot close ${args.id}: ${openChildren.length} ${relationLabel} item(s) still open: ${openChildren.join(', ')}`);
47
+ }
48
+ }
49
+ };
50
+ // Validate implemented-by children (Scrum: Epic→Story, Story→Task; Waterfall: Requirement→Feature, Feature→Task)
51
+ if (['epic', 'story', 'requirement', 'feature'].includes(metadata.type)) {
52
+ validateChildren('implemented-by');
53
+ }
54
+ // Validate tested-by children (all parent types must have tests complete)
55
+ if (['epic', 'story', 'requirement', 'feature'].includes(metadata.type)) {
56
+ validateChildren('tested-by');
57
+ }
58
+ }
59
+ if (args.status)
60
+ metadata.status = args.status;
61
+ if (args.priority)
62
+ metadata.priority = args.priority;
63
+ if (args.eisenhower)
64
+ metadata.eisenhower = args.eisenhower;
65
+ if (args.superseded_by !== undefined)
66
+ metadata.superseded_by = args.superseded_by;
67
+ if (args.title)
68
+ metadata.title = args.title;
69
+ if (args.assignee !== undefined)
70
+ metadata.assignee = args.assignee;
71
+ if (args.tags)
72
+ metadata.tags = args.tags;
73
+ if (args.affected_paths)
74
+ metadata.affected_paths = args.affected_paths;
75
+ metadata.updated = getCurrentTimestamp();
76
+ writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
77
+ // Update description
78
+ if (args.description && args.append_description) {
79
+ throw new Error('Cannot use both description and append_description simultaneously');
80
+ }
81
+ if (args.description) {
82
+ // Replace entire description
83
+ writeFileSync(descriptionPath, args.description);
84
+ }
85
+ else if (args.append_description) {
86
+ // Append to existing (or create new if doesn't exist)
87
+ const existing = existsSync(descriptionPath)
88
+ ? readFileSync(descriptionPath, 'utf-8')
89
+ : '';
90
+ writeFileSync(descriptionPath, existing + args.append_description);
91
+ }
92
+ // Update index
93
+ const indexPath = join(devcrumbsDir, 'index.json');
94
+ const index = JSON.parse(readFileSync(indexPath, 'utf-8'));
95
+ const itemIndex = index.items.findIndex((i) => i.id === args.id);
96
+ if (itemIndex !== -1) {
97
+ if (args.status)
98
+ index.items[itemIndex].status = args.status;
99
+ if (args.priority)
100
+ index.items[itemIndex].priority = args.priority;
101
+ if (args.title)
102
+ index.items[itemIndex].title = args.title;
103
+ index.items[itemIndex].updated = metadata.updated;
104
+ // Update stats
105
+ if (args.status && oldStatus !== args.status) {
106
+ index.stats = index.stats || { total: 0, by_type: {}, by_status: {} };
107
+ index.stats.by_status[oldStatus] = (index.stats.by_status[oldStatus] || 1) - 1;
108
+ index.stats.by_status[args.status] = (index.stats.by_status[args.status] || 0) + 1;
109
+ }
110
+ }
111
+ index.last_updated = metadata.updated;
112
+ writeFileSync(indexPath, JSON.stringify(index, null, 2));
113
+ return {
114
+ metadata,
115
+ oldStatus,
116
+ };
117
+ }
118
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/core/update.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { ItemType, Methodology } from '../schemas/index.js';
2
+ /**
3
+ * Validation result with detailed error messaging
4
+ */
5
+ export interface ValidationResult {
6
+ valid: boolean;
7
+ error?: string;
8
+ suggestion?: string;
9
+ }
10
+ /**
11
+ * Minimal work item info needed for validation
12
+ */
13
+ export interface WorkItem {
14
+ id: string;
15
+ type: ItemType;
16
+ }
17
+ /**
18
+ * Validate relationship between two items based on methodology
19
+ * Only validates "implements" relationships - all other relations are flexible
20
+ *
21
+ * @param source - Item creating the relationship (child in hierarchy)
22
+ * @param target - Item being referenced (parent in hierarchy)
23
+ * @param relationType - Type of relationship
24
+ * @param methodology - Project methodology (scrum, waterfall, hybrid)
25
+ * @returns ValidationResult with valid flag and optional error/suggestion
26
+ */
27
+ export declare function validateRelationship(source: WorkItem, target: WorkItem, relationType: string, methodology: Methodology): ValidationResult;
28
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,QAAQ,EAChB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,GACvB,gBAAgB,CA8ClB"}