@context-forge/core 0.1.1 → 0.2.2

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 (154) hide show
  1. package/README.md +12 -1
  2. package/dist/config/ConfigKeys.d.ts +9 -0
  3. package/dist/config/ConfigKeys.d.ts.map +1 -0
  4. package/dist/config/ConfigKeys.js +24 -0
  5. package/dist/config/ConfigKeys.js.map +1 -0
  6. package/dist/config/ConfigManager.d.ts +18 -0
  7. package/dist/config/ConfigManager.d.ts.map +1 -0
  8. package/dist/config/ConfigManager.js +129 -0
  9. package/dist/config/ConfigManager.js.map +1 -0
  10. package/dist/config/configPaths.d.ts +5 -0
  11. package/dist/config/configPaths.d.ts.map +1 -0
  12. package/dist/config/configPaths.js +11 -0
  13. package/dist/config/configPaths.js.map +1 -0
  14. package/dist/config/index.d.ts +4 -0
  15. package/dist/config/index.d.ts.map +1 -0
  16. package/dist/config/index.js +4 -0
  17. package/dist/config/index.js.map +1 -0
  18. package/dist/guides/GuideDetector.d.ts +20 -0
  19. package/dist/guides/GuideDetector.d.ts.map +1 -0
  20. package/dist/guides/GuideDetector.js +142 -0
  21. package/dist/guides/GuideDetector.js.map +1 -0
  22. package/dist/guides/GuideManager.d.ts +21 -0
  23. package/dist/guides/GuideManager.d.ts.map +1 -0
  24. package/dist/guides/GuideManager.js +88 -0
  25. package/dist/guides/GuideManager.js.map +1 -0
  26. package/dist/guides/gitExec.d.ts +15 -0
  27. package/dist/guides/gitExec.d.ts.map +1 -0
  28. package/dist/guides/gitExec.js +39 -0
  29. package/dist/guides/gitExec.js.map +1 -0
  30. package/dist/guides/index.d.ts +4 -0
  31. package/dist/guides/index.d.ts.map +1 -0
  32. package/dist/guides/index.js +5 -0
  33. package/dist/guides/index.js.map +1 -0
  34. package/dist/guides/strategies/CloneStrategy.d.ts +7 -0
  35. package/dist/guides/strategies/CloneStrategy.d.ts.map +1 -0
  36. package/dist/guides/strategies/CloneStrategy.js +80 -0
  37. package/dist/guides/strategies/CloneStrategy.js.map +1 -0
  38. package/dist/guides/strategies/SubmoduleStrategy.d.ts +7 -0
  39. package/dist/guides/strategies/SubmoduleStrategy.d.ts.map +1 -0
  40. package/dist/guides/strategies/SubmoduleStrategy.js +74 -0
  41. package/dist/guides/strategies/SubmoduleStrategy.js.map +1 -0
  42. package/dist/guides/strategies/TarballStrategy.d.ts +19 -0
  43. package/dist/guides/strategies/TarballStrategy.d.ts.map +1 -0
  44. package/dist/guides/strategies/TarballStrategy.js +118 -0
  45. package/dist/guides/strategies/TarballStrategy.js.map +1 -0
  46. package/dist/guides/types.d.ts +44 -0
  47. package/dist/guides/types.d.ts.map +1 -0
  48. package/dist/guides/types.js +7 -0
  49. package/dist/guides/types.js.map +1 -0
  50. package/dist/index.d.ts +3 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +4 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/introspection/ArtifactIntrospector.d.ts +20 -0
  55. package/dist/introspection/ArtifactIntrospector.d.ts.map +1 -0
  56. package/dist/introspection/ArtifactIntrospector.js +140 -0
  57. package/dist/introspection/ArtifactIntrospector.js.map +1 -0
  58. package/dist/introspection/FutureWorkCollector.d.ts +7 -0
  59. package/dist/introspection/FutureWorkCollector.d.ts.map +1 -0
  60. package/dist/introspection/FutureWorkCollector.js +116 -0
  61. package/dist/introspection/FutureWorkCollector.js.map +1 -0
  62. package/dist/introspection/ProjectModelBuilder.d.ts +32 -0
  63. package/dist/introspection/ProjectModelBuilder.d.ts.map +1 -0
  64. package/dist/introspection/ProjectModelBuilder.js +321 -0
  65. package/dist/introspection/ProjectModelBuilder.js.map +1 -0
  66. package/dist/introspection/index.d.ts +4 -0
  67. package/dist/introspection/index.d.ts.map +1 -0
  68. package/dist/introspection/index.js +5 -0
  69. package/dist/introspection/index.js.map +1 -0
  70. package/dist/introspection/interfaces.d.ts +18 -0
  71. package/dist/introspection/interfaces.d.ts.map +1 -0
  72. package/dist/introspection/interfaces.js +2 -0
  73. package/dist/introspection/interfaces.js.map +1 -0
  74. package/dist/introspection/parsers/documentDetector.d.ts +12 -0
  75. package/dist/introspection/parsers/documentDetector.d.ts.map +1 -0
  76. package/dist/introspection/parsers/documentDetector.js +66 -0
  77. package/dist/introspection/parsers/documentDetector.js.map +1 -0
  78. package/dist/introspection/parsers/frontmatterParser.d.ts +8 -0
  79. package/dist/introspection/parsers/frontmatterParser.d.ts.map +1 -0
  80. package/dist/introspection/parsers/frontmatterParser.js +43 -0
  81. package/dist/introspection/parsers/frontmatterParser.js.map +1 -0
  82. package/dist/introspection/parsers/futureWorkParser.d.ts +8 -0
  83. package/dist/introspection/parsers/futureWorkParser.d.ts.map +1 -0
  84. package/dist/introspection/parsers/futureWorkParser.js +75 -0
  85. package/dist/introspection/parsers/futureWorkParser.js.map +1 -0
  86. package/dist/introspection/parsers/slicePlanParser.d.ts +8 -0
  87. package/dist/introspection/parsers/slicePlanParser.d.ts.map +1 -0
  88. package/dist/introspection/parsers/slicePlanParser.js +51 -0
  89. package/dist/introspection/parsers/slicePlanParser.js.map +1 -0
  90. package/dist/introspection/parsers/statusNormalizer.d.ts +4 -0
  91. package/dist/introspection/parsers/statusNormalizer.d.ts.map +1 -0
  92. package/dist/introspection/parsers/statusNormalizer.js +23 -0
  93. package/dist/introspection/parsers/statusNormalizer.js.map +1 -0
  94. package/dist/introspection/parsers/taskFileParser.d.ts +13 -0
  95. package/dist/introspection/parsers/taskFileParser.d.ts.map +1 -0
  96. package/dist/introspection/parsers/taskFileParser.js +66 -0
  97. package/dist/introspection/parsers/taskFileParser.js.map +1 -0
  98. package/dist/introspection/types.d.ts +178 -0
  99. package/dist/introspection/types.d.ts.map +1 -0
  100. package/dist/introspection/types.js +2 -0
  101. package/dist/introspection/types.js.map +1 -0
  102. package/dist/node.d.ts +10 -0
  103. package/dist/node.d.ts.map +1 -1
  104. package/dist/node.js +13 -0
  105. package/dist/node.js.map +1 -1
  106. package/dist/schema/projectSchema.d.ts +54 -0
  107. package/dist/schema/projectSchema.d.ts.map +1 -0
  108. package/dist/schema/projectSchema.js +127 -0
  109. package/dist/schema/projectSchema.js.map +1 -0
  110. package/dist/services/ContextGenerator.d.ts.map +1 -1
  111. package/dist/services/ContextGenerator.js +3 -5
  112. package/dist/services/ContextGenerator.js.map +1 -1
  113. package/dist/services/ContextIntegrator.d.ts.map +1 -1
  114. package/dist/services/ContextIntegrator.js +10 -14
  115. package/dist/services/ContextIntegrator.js.map +1 -1
  116. package/dist/services/ContextTemplateEngine.d.ts.map +1 -1
  117. package/dist/services/ContextTemplateEngine.js +8 -21
  118. package/dist/services/ContextTemplateEngine.js.map +1 -1
  119. package/dist/services/CoreServiceFactory.d.ts +3 -0
  120. package/dist/services/CoreServiceFactory.d.ts.map +1 -1
  121. package/dist/services/CoreServiceFactory.js +19 -1
  122. package/dist/services/CoreServiceFactory.js.map +1 -1
  123. package/dist/services/ProjectPathService.d.ts +1 -1
  124. package/dist/services/ProjectPathService.d.ts.map +1 -1
  125. package/dist/services/ProjectPathService.js +2 -4
  126. package/dist/services/ProjectPathService.js.map +1 -1
  127. package/dist/services/SectionBuilder.d.ts +0 -4
  128. package/dist/services/SectionBuilder.d.ts.map +1 -1
  129. package/dist/services/SectionBuilder.js +8 -35
  130. package/dist/services/SectionBuilder.js.map +1 -1
  131. package/dist/services/SystemPromptParser.d.ts +1 -2
  132. package/dist/services/SystemPromptParser.d.ts.map +1 -1
  133. package/dist/services/SystemPromptParser.js +3 -14
  134. package/dist/services/SystemPromptParser.js.map +1 -1
  135. package/dist/services/TemplateProcessor.d.ts.map +1 -1
  136. package/dist/services/TemplateProcessor.js +12 -11
  137. package/dist/services/TemplateProcessor.js.map +1 -1
  138. package/dist/services/constants.d.ts.map +1 -1
  139. package/dist/services/constants.js +0 -6
  140. package/dist/services/constants.js.map +1 -1
  141. package/dist/services/interfaces.d.ts +1 -1
  142. package/dist/services/interfaces.d.ts.map +1 -1
  143. package/dist/storage/FileProjectStore.d.ts.map +1 -1
  144. package/dist/storage/FileProjectStore.js +25 -8
  145. package/dist/storage/FileProjectStore.js.map +1 -1
  146. package/dist/types/context.d.ts +4 -6
  147. package/dist/types/context.d.ts.map +1 -1
  148. package/dist/types/project.d.ts +15 -11
  149. package/dist/types/project.d.ts.map +1 -1
  150. package/dist/types/sections.d.ts +0 -1
  151. package/dist/types/sections.d.ts.map +1 -1
  152. package/dist/types/sections.js +0 -1
  153. package/dist/types/sections.js.map +1 -1
  154. package/package.json +5 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitExec.js","sourceRoot":"","sources":["../../src/guides/gitExec.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAOzC;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,IAAc,EAAE,GAAW;IACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACvD,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CACJ,IAAI,KAAK,CACP,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,CAC5E,CACF,CAAC;gBACF,OAAO;YACT,CAAC;YACD,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GuideManager } from './GuideManager.js';
2
+ export { GuideDetector } from './GuideDetector.js';
3
+ export { type GuideInfo, type GuideMethod, type InstallResult, type UpdateResult, type DetectionResult, type InstallStrategy, DEFAULT_SOURCE_GIT, DEFAULT_SOURCE_API, GUIDE_RELATIVE_PATH, VERSION_MARKER_FILE, } from './types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ // Guide management — public exports
2
+ export { GuideManager } from './GuideManager.js';
3
+ export { GuideDetector } from './GuideDetector.js';
4
+ export { DEFAULT_SOURCE_GIT, DEFAULT_SOURCE_API, GUIDE_RELATIVE_PATH, VERSION_MARKER_FILE, } from './types.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAOL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { InstallStrategy, InstallResult, UpdateResult, DetectionResult } from '../types.js';
2
+ export declare class CloneStrategy implements InstallStrategy {
3
+ detect(_projectPath: string, targetDir: string): Promise<DetectionResult | null>;
4
+ install(_projectPath: string, source: string, targetDir: string): Promise<InstallResult>;
5
+ update(_projectPath: string, targetDir: string): Promise<UpdateResult>;
6
+ }
7
+ //# sourceMappingURL=CloneStrategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloneStrategy.d.ts","sourceRoot":"","sources":["../../../src/guides/strategies/CloneStrategy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGjG,qBAAa,aAAc,YAAW,eAAe;IAC7C,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAsBhF,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAoBxF,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CA0C7E"}
@@ -0,0 +1,80 @@
1
+ // Clone-based guide installation strategy
2
+ import { existsSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { gitExec, isGitAvailable } from '../gitExec.js';
5
+ export class CloneStrategy {
6
+ async detect(_projectPath, targetDir) {
7
+ if (!existsSync(join(targetDir, '.git')))
8
+ return null;
9
+ let version = null;
10
+ try {
11
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
12
+ version = stdout || null;
13
+ }
14
+ catch {
15
+ // No tags
16
+ }
17
+ let source = null;
18
+ try {
19
+ const { stdout } = await gitExec(['remote', 'get-url', 'origin'], targetDir);
20
+ source = stdout || null;
21
+ }
22
+ catch {
23
+ // No remote
24
+ }
25
+ return { method: 'clone', version, source };
26
+ }
27
+ async install(_projectPath, source, targetDir) {
28
+ if (!(await isGitAvailable())) {
29
+ throw new Error('git is not available. Install git or use the "manual" strategy instead.');
30
+ }
31
+ await gitExec(['clone', source, targetDir], process.cwd());
32
+ let version = null;
33
+ try {
34
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
35
+ version = stdout || null;
36
+ }
37
+ catch {
38
+ // No tags
39
+ }
40
+ return { success: true, version, method: 'clone', path: targetDir };
41
+ }
42
+ async update(_projectPath, targetDir) {
43
+ let previousVersion = null;
44
+ try {
45
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
46
+ previousVersion = stdout || null;
47
+ }
48
+ catch {
49
+ // No previous version
50
+ }
51
+ // Fetch latest from remote, then try pull. If pull fails (e.g. detached HEAD),
52
+ // fetch + checkout the latest tag instead.
53
+ await gitExec(['fetch', '--tags', 'origin'], targetDir);
54
+ try {
55
+ await gitExec(['pull', '--ff-only'], targetDir);
56
+ }
57
+ catch {
58
+ // Detached HEAD or no tracking branch — checkout latest tag
59
+ const { stdout: latestTag } = await gitExec(['describe', '--tags', '--abbrev=0', 'origin/HEAD'], targetDir).catch(async () => {
60
+ // origin/HEAD may not exist; fall back to sorting tags
61
+ const { stdout: tags } = await gitExec(['tag', '--sort=-v:refname'], targetDir);
62
+ const first = tags.split('\n')[0]?.trim();
63
+ if (!first)
64
+ throw new Error('No tags found after fetch');
65
+ return { stdout: first, stderr: '' };
66
+ });
67
+ await gitExec(['checkout', latestTag], targetDir);
68
+ }
69
+ let newVersion = null;
70
+ try {
71
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
72
+ newVersion = stdout || null;
73
+ }
74
+ catch {
75
+ // No new version
76
+ }
77
+ return { success: true, previousVersion, newVersion, method: 'clone' };
78
+ }
79
+ }
80
+ //# sourceMappingURL=CloneStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CloneStrategy.js","sourceRoot":"","sources":["../../../src/guides/strategies/CloneStrategy.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExD,MAAM,OAAO,aAAa;IACxB,KAAK,CAAC,MAAM,CAAC,YAAoB,EAAE,SAAiB;QAClD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtD,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;YAClF,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;QAED,IAAI,MAAM,GAAkB,IAAI,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;YAC7E,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;QAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,YAAoB,EAAE,MAAc,EAAE,SAAiB;QACnE,IAAI,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAE3D,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;YAClF,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,UAAU;QACZ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,YAAoB,EAAE,SAAiB;QAClD,IAAI,eAAe,GAAkB,IAAI,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;YAClF,eAAe,GAAG,MAAM,IAAI,IAAI,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,sBAAsB;QACxB,CAAC;QAED,+EAA+E;QAC/E,2CAA2C;QAC3C,MAAM,OAAO,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,SAAS,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;YAC5D,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,OAAO,CACzC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,EACnD,SAAS,CACV,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;gBACjB,uDAAuD;gBACvD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CACpC,CAAC,KAAK,EAAE,mBAAmB,CAAC,EAC5B,SAAS,CACV,CAAC;gBACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;gBAC1C,IAAI,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;gBACzD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;YACvC,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;QACpD,CAAC;QAED,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;YAClF,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACzE,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { InstallStrategy, InstallResult, UpdateResult, DetectionResult } from '../types.js';
2
+ export declare class SubmoduleStrategy implements InstallStrategy {
3
+ detect(projectPath: string, targetDir: string): Promise<DetectionResult | null>;
4
+ install(projectPath: string, source: string, targetDir: string): Promise<InstallResult>;
5
+ update(projectPath: string, targetDir: string): Promise<UpdateResult>;
6
+ }
7
+ //# sourceMappingURL=SubmoduleStrategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubmoduleStrategy.d.ts","sourceRoot":"","sources":["../../../src/guides/strategies/SubmoduleStrategy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAIjG,qBAAa,iBAAkB,YAAW,eAAe;IACjD,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA2B/E,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA0BvF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAqB5E"}
@@ -0,0 +1,74 @@
1
+ // Submodule-based guide installation strategy
2
+ import { existsSync, readFileSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { GUIDE_RELATIVE_PATH } from '../types.js';
5
+ import { gitExec, isGitAvailable, isGitRepo } from '../gitExec.js';
6
+ export class SubmoduleStrategy {
7
+ async detect(projectPath, targetDir) {
8
+ const gitmodulesPath = join(projectPath, '.gitmodules');
9
+ if (!existsSync(gitmodulesPath))
10
+ return null;
11
+ try {
12
+ const content = readFileSync(gitmodulesPath, 'utf-8');
13
+ if (!content.includes(GUIDE_RELATIVE_PATH))
14
+ return null;
15
+ let version = null;
16
+ try {
17
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
18
+ version = stdout || null;
19
+ }
20
+ catch {
21
+ // No tags or not initialized
22
+ }
23
+ // Extract URL from .gitmodules
24
+ let source = null;
25
+ const urlMatch = /url\s*=\s*(.+)/.exec(content);
26
+ if (urlMatch)
27
+ source = urlMatch[1].trim();
28
+ return { method: 'submodule', version, source };
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ async install(projectPath, source, targetDir) {
35
+ if (!(await isGitAvailable())) {
36
+ throw new Error('git is not available. Install git or use the "manual" strategy instead.');
37
+ }
38
+ if (!(await isGitRepo(projectPath))) {
39
+ throw new Error(`"${projectPath}" is not a git repository. ` +
40
+ 'The submodule strategy requires a git repo. Use --strategy clone or --strategy manual instead.');
41
+ }
42
+ await gitExec(['submodule', 'add', source, GUIDE_RELATIVE_PATH], projectPath);
43
+ let version = null;
44
+ try {
45
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
46
+ version = stdout || null;
47
+ }
48
+ catch {
49
+ // No tags available
50
+ }
51
+ return { success: true, version, method: 'submodule', path: targetDir };
52
+ }
53
+ async update(projectPath, targetDir) {
54
+ let previousVersion = null;
55
+ try {
56
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
57
+ previousVersion = stdout || null;
58
+ }
59
+ catch {
60
+ // No previous version
61
+ }
62
+ await gitExec(['submodule', 'update', '--remote', GUIDE_RELATIVE_PATH], projectPath);
63
+ let newVersion = null;
64
+ try {
65
+ const { stdout } = await gitExec(['describe', '--tags', '--abbrev=0'], targetDir);
66
+ newVersion = stdout || null;
67
+ }
68
+ catch {
69
+ // No new version
70
+ }
71
+ return { success: true, previousVersion, newVersion, method: 'submodule' };
72
+ }
73
+ }
74
+ //# sourceMappingURL=SubmoduleStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubmoduleStrategy.js","sourceRoot":"","sources":["../../../src/guides/strategies/SubmoduleStrategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { InstallStrategy, InstallResult, UpdateResult, DetectionResult } from '../types.js';
2
+ /**
3
+ * Parse owner/repo from a GitHub source URL.
4
+ * Supports: https://github.com/{owner}/{repo}.git and https://github.com/{owner}/{repo}
5
+ */
6
+ export declare function parseGitHubOwnerRepo(source: string): {
7
+ owner: string;
8
+ repo: string;
9
+ };
10
+ export declare class TarballStrategy implements InstallStrategy {
11
+ detect(_projectPath: string, targetDir: string): Promise<DetectionResult | null>;
12
+ install(_projectPath: string, source: string, targetDir: string): Promise<InstallResult>;
13
+ update(_projectPath: string, targetDir: string): Promise<UpdateResult>;
14
+ /** Fetch latest tag from remote using git ls-remote */
15
+ private fetchLatestTag;
16
+ /** Download tarball from GitHub API and extract to targetDir */
17
+ private downloadAndExtract;
18
+ }
19
+ //# sourceMappingURL=TarballStrategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TarballStrategy.d.ts","sourceRoot":"","sources":["../../../src/guides/strategies/TarballStrategy.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAIjG;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAMpF;AAED,qBAAa,eAAgB,YAAW,eAAe;IAC/C,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAYhF,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAaxF,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA4B5E,uDAAuD;YACzC,cAAc;IAgC5B,gEAAgE;YAClD,kBAAkB;CAgCjC"}
@@ -0,0 +1,118 @@
1
+ // Tarball-based (manual) guide installation strategy
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from 'fs';
3
+ import { join } from 'path';
4
+ import { createGunzip } from 'zlib';
5
+ import { Readable } from 'stream';
6
+ import { pipeline } from 'stream/promises';
7
+ import { extract } from 'tar';
8
+ import { VERSION_MARKER_FILE, DEFAULT_SOURCE_GIT } from '../types.js';
9
+ import { gitExec } from '../gitExec.js';
10
+ /**
11
+ * Parse owner/repo from a GitHub source URL.
12
+ * Supports: https://github.com/{owner}/{repo}.git and https://github.com/{owner}/{repo}
13
+ */
14
+ export function parseGitHubOwnerRepo(source) {
15
+ const match = /github\.com\/([^/]+)\/([^/.]+)/.exec(source);
16
+ if (!match) {
17
+ throw new Error(`Cannot parse GitHub owner/repo from source URL: ${source}`);
18
+ }
19
+ return { owner: match[1], repo: match[2] };
20
+ }
21
+ export class TarballStrategy {
22
+ async detect(_projectPath, targetDir) {
23
+ const markerPath = join(targetDir, VERSION_MARKER_FILE);
24
+ if (!existsSync(markerPath))
25
+ return null;
26
+ try {
27
+ const version = readFileSync(markerPath, 'utf-8').trim() || null;
28
+ return { method: 'manual', version, source: null };
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ async install(_projectPath, source, targetDir) {
35
+ const resolvedSource = source || DEFAULT_SOURCE_GIT;
36
+ const latestTag = await this.fetchLatestTag(resolvedSource);
37
+ if (!latestTag) {
38
+ throw new Error('Could not determine latest version from remote.');
39
+ }
40
+ await this.downloadAndExtract(resolvedSource, latestTag, targetDir);
41
+ writeFileSync(join(targetDir, VERSION_MARKER_FILE), latestTag, 'utf-8');
42
+ return { success: true, version: latestTag, method: 'manual', path: targetDir };
43
+ }
44
+ async update(_projectPath, targetDir) {
45
+ const markerPath = join(targetDir, VERSION_MARKER_FILE);
46
+ let previousVersion = null;
47
+ try {
48
+ previousVersion = readFileSync(markerPath, 'utf-8').trim() || null;
49
+ }
50
+ catch {
51
+ // No previous version
52
+ }
53
+ // Determine source from the default (marker doesn't store it)
54
+ const source = DEFAULT_SOURCE_GIT;
55
+ const latestTag = await this.fetchLatestTag(source);
56
+ if (!latestTag) {
57
+ throw new Error('Could not determine latest version from remote.');
58
+ }
59
+ if (previousVersion === latestTag) {
60
+ return { success: true, previousVersion, newVersion: latestTag, method: 'manual' };
61
+ }
62
+ // Remove existing contents and re-download
63
+ rmSync(targetDir, { recursive: true, force: true });
64
+ await this.downloadAndExtract(source, latestTag, targetDir);
65
+ writeFileSync(join(targetDir, VERSION_MARKER_FILE), latestTag, 'utf-8');
66
+ return { success: true, previousVersion, newVersion: latestTag, method: 'manual' };
67
+ }
68
+ /** Fetch latest tag from remote using git ls-remote */
69
+ async fetchLatestTag(source) {
70
+ try {
71
+ const { stdout } = await gitExec(['ls-remote', '--tags', '--sort=-v:refname', source], process.cwd());
72
+ const tagPattern = /refs\/tags\/(v?\d+\.\d+\.\d+)$/;
73
+ const tags = [];
74
+ for (const line of stdout.split('\n')) {
75
+ const match = tagPattern.exec(line.trim());
76
+ if (match)
77
+ tags.push(match[1]);
78
+ }
79
+ if (tags.length === 0)
80
+ return null;
81
+ // Sort descending
82
+ tags.sort((a, b) => {
83
+ const pa = a.replace(/^v/, '').split('.').map(Number);
84
+ const pb = b.replace(/^v/, '').split('.').map(Number);
85
+ for (let i = 0; i < 3; i++) {
86
+ if (pa[i] !== pb[i])
87
+ return pb[i] - pa[i];
88
+ }
89
+ return 0;
90
+ });
91
+ return tags[0];
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ /** Download tarball from GitHub API and extract to targetDir */
98
+ async downloadAndExtract(source, tag, targetDir) {
99
+ const { owner, repo } = parseGitHubOwnerRepo(source);
100
+ const url = `https://api.github.com/repos/${owner}/${repo}/tarball/${tag}`;
101
+ const response = await fetch(url, {
102
+ headers: { Accept: 'application/vnd.github+json' },
103
+ redirect: 'follow',
104
+ });
105
+ if (!response.ok) {
106
+ throw new Error(`Failed to download tarball: ${response.status} ${response.statusText}`);
107
+ }
108
+ if (!response.body) {
109
+ throw new Error('Empty response body when downloading tarball');
110
+ }
111
+ mkdirSync(targetDir, { recursive: true });
112
+ // GitHub tarballs have a top-level directory like {owner}-{repo}-{hash}/
113
+ // We strip 1 level and extract directly into targetDir
114
+ const nodeStream = Readable.fromWeb(response.body);
115
+ await pipeline(nodeStream, createGunzip(), extract({ cwd: targetDir, strip: 1 }));
116
+ }
117
+ }
118
+ //# sourceMappingURL=TarballStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TarballStrategy.js","sourceRoot":"","sources":["../../../src/guides/strategies/TarballStrategy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /** Installation method used for the ai-project-guide */
2
+ export type GuideMethod = 'submodule' | 'clone' | 'manual';
3
+ /** Full status of a guide installation */
4
+ export interface GuideInfo {
5
+ installed: boolean;
6
+ method: GuideMethod | null;
7
+ version: string | null;
8
+ path: string;
9
+ source: string;
10
+ latestVersion: string | null;
11
+ updateAvailable: boolean;
12
+ usingBundledPrompt: boolean;
13
+ }
14
+ /** Result of a guide installation */
15
+ export interface InstallResult {
16
+ success: boolean;
17
+ version: string | null;
18
+ method: GuideMethod;
19
+ path: string;
20
+ }
21
+ /** Result of a guide update */
22
+ export interface UpdateResult {
23
+ success: boolean;
24
+ previousVersion: string | null;
25
+ newVersion: string | null;
26
+ method: GuideMethod;
27
+ }
28
+ /** Detection result returned by a strategy's detect() method */
29
+ export interface DetectionResult {
30
+ method: GuideMethod;
31
+ version: string | null;
32
+ source: string | null;
33
+ }
34
+ /** Strategy interface for guide installation methods */
35
+ export interface InstallStrategy {
36
+ install(projectPath: string, source: string, targetDir: string): Promise<InstallResult>;
37
+ update(projectPath: string, targetDir: string): Promise<UpdateResult>;
38
+ detect(projectPath: string, targetDir: string): Promise<DetectionResult | null>;
39
+ }
40
+ export declare const DEFAULT_SOURCE_GIT = "https://github.com/ecorkran/ai-project-guide.git";
41
+ export declare const DEFAULT_SOURCE_API = "https://api.github.com/repos/ecorkran/ai-project-guide";
42
+ export declare const GUIDE_RELATIVE_PATH = "project-documents/ai-project-guide";
43
+ export declare const VERSION_MARKER_FILE = ".context-forge-guide-version";
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/guides/types.ts"],"names":[],"mappings":"AAEA,wDAAwD;AACxD,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE3D,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,WAAW,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+BAA+B;AAC/B,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACxF,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACtE,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;CACjF;AAGD,eAAO,MAAM,kBAAkB,qDAAqD,CAAC;AACrF,eAAO,MAAM,kBAAkB,2DAA2D,CAAC;AAC3F,eAAO,MAAM,mBAAmB,uCAAuC,CAAC;AACxE,eAAO,MAAM,mBAAmB,iCAAiC,CAAC"}
@@ -0,0 +1,7 @@
1
+ // Guide management types and strategy interface
2
+ // Constants
3
+ export const DEFAULT_SOURCE_GIT = 'https://github.com/ecorkran/ai-project-guide.git';
4
+ export const DEFAULT_SOURCE_API = 'https://api.github.com/repos/ecorkran/ai-project-guide';
5
+ export const GUIDE_RELATIVE_PATH = 'project-documents/ai-project-guide';
6
+ export const VERSION_MARKER_FILE = '.context-forge-guide-version';
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/guides/types.ts"],"names":[],"mappings":"AAAA,gDAAgD;AA+ChD,YAAY;AACZ,MAAM,CAAC,MAAM,kBAAkB,GAAG,kDAAkD,CAAC;AACrF,MAAM,CAAC,MAAM,kBAAkB,GAAG,wDAAwD,CAAC;AAC3F,MAAM,CAAC,MAAM,mBAAmB,GAAG,oCAAoC,CAAC;AACxE,MAAM,CAAC,MAAM,mBAAmB,GAAG,8BAA8B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export * from './types/index.js';
2
2
  export * from './services/index.js';
3
3
  export type { IProjectStore, IStorageService, StorageReadResult } from './storage/interfaces.js';
4
+ export * from './introspection/index.js';
5
+ export type { GuideInfo, GuideMethod, InstallResult, UpdateResult } from './guides/types.js';
6
+ export * from './schema/projectSchema.js';
4
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AAGpC,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AAGpC,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjG,cAAc,0BAA0B,CAAC;AAGzC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG7F,cAAc,2BAA2B,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  // @context-forge/core — context assembly engine
2
2
  export * from './types/index.js';
3
3
  export * from './services/index.js';
4
+ // Introspection types and interfaces (browser-safe — no fs dependencies)
5
+ export * from './introspection/index.js';
6
+ // Project schema (field metadata, aliases, phase maps)
7
+ export * from './schema/projectSchema.js';
4
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AAKpC,yEAAyE;AACzE,cAAc,0BAA0B,CAAC;AAKzC,uDAAuD;AACvD,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { ProjectData } from '../types/project.js';
2
+ import type { IArtifactIntrospector } from './interfaces.js';
3
+ import type { SlicePlanResult, TaskFileResult, FrontmatterResult, FutureWorkResult, DocumentDetectionResult, IntrospectionSummary } from './types.js';
4
+ /**
5
+ * Orchestrator that delegates to individual parser functions.
6
+ * Each method resolves file paths from projectPath as needed.
7
+ */
8
+ export declare class ArtifactIntrospector implements IArtifactIntrospector {
9
+ parseSlicePlan(slicePlanPath: string): Promise<SlicePlanResult>;
10
+ parseTaskFile(taskFilePaths: string | string[]): Promise<TaskFileResult>;
11
+ parseFrontmatter(filePath: string): Promise<FrontmatterResult>;
12
+ parseFutureWork(slicePlanPath: string, nextIndex?: number): Promise<FutureWorkResult>;
13
+ detectDocuments(projectPath: string, sliceIndex: number): Promise<DocumentDetectionResult>;
14
+ /**
15
+ * Generate an introspection summary for a project.
16
+ * Each operation is individually try/caught — failure in one doesn't prevent others.
17
+ */
18
+ summarize(project: ProjectData): Promise<IntrospectionSummary>;
19
+ }
20
+ //# sourceMappingURL=ArtifactIntrospector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArtifactIntrospector.d.ts","sourceRoot":"","sources":["../../src/introspection/ArtifactIntrospector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAOpB;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,qBAAqB;IAC1D,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI/D,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAIxE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAI9D,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIrF,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAIhG;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAsGrE"}
@@ -0,0 +1,140 @@
1
+ import { join } from 'node:path';
2
+ import { parseSlicePlan } from './parsers/slicePlanParser.js';
3
+ import { parseTaskFile } from './parsers/taskFileParser.js';
4
+ import { parseFrontmatter } from './parsers/frontmatterParser.js';
5
+ import { parseFutureWork } from './parsers/futureWorkParser.js';
6
+ import { detectDocuments, checkFileExists } from './parsers/documentDetector.js';
7
+ /**
8
+ * Orchestrator that delegates to individual parser functions.
9
+ * Each method resolves file paths from projectPath as needed.
10
+ */
11
+ export class ArtifactIntrospector {
12
+ async parseSlicePlan(slicePlanPath) {
13
+ return parseSlicePlan(slicePlanPath);
14
+ }
15
+ async parseTaskFile(taskFilePaths) {
16
+ return parseTaskFile(taskFilePaths);
17
+ }
18
+ async parseFrontmatter(filePath) {
19
+ return parseFrontmatter(filePath);
20
+ }
21
+ async parseFutureWork(slicePlanPath, nextIndex) {
22
+ return parseFutureWork(slicePlanPath, nextIndex);
23
+ }
24
+ async detectDocuments(projectPath, sliceIndex) {
25
+ return detectDocuments(projectPath, sliceIndex);
26
+ }
27
+ /**
28
+ * Generate an introspection summary for a project.
29
+ * Each operation is individually try/caught — failure in one doesn't prevent others.
30
+ */
31
+ async summarize(project) {
32
+ const summary = {
33
+ artifacts: {
34
+ hasSlicePlan: false,
35
+ hasHLD: false,
36
+ hasArch: false,
37
+ hasSpec: false,
38
+ hasCurrentSliceDesign: false,
39
+ hasCurrentTaskFile: false,
40
+ },
41
+ };
42
+ const projectPath = project.projectPath;
43
+ if (!projectPath)
44
+ return summary;
45
+ // Parse slice plan if available
46
+ try {
47
+ if (project.fileSlicePlan) {
48
+ const planPath = join(projectPath, project.fileSlicePlan);
49
+ const planResult = await parseSlicePlan(planPath);
50
+ if (planResult.totalSlices > 0) {
51
+ summary.slicePlan = {
52
+ totalSlices: planResult.totalSlices,
53
+ completedSlices: planResult.completedSlices,
54
+ summary: `${planResult.completedSlices} of ${planResult.totalSlices} slices complete`,
55
+ };
56
+ }
57
+ }
58
+ }
59
+ catch {
60
+ // Slice plan parsing failed — continue with other operations
61
+ }
62
+ // Parse task file if available
63
+ try {
64
+ if (project.fileTasks) {
65
+ // Detect actual task file(s) using the slice index
66
+ const sliceIndex = extractSliceIndex(project.fileSlice);
67
+ let taskPaths = [];
68
+ if (sliceIndex !== null) {
69
+ const docs = await detectDocuments(projectPath, sliceIndex);
70
+ if (docs.taskFile) {
71
+ taskPaths = docs.taskFile.map((p) => join(projectPath, p));
72
+ }
73
+ }
74
+ // Fall back to direct path if detection found nothing
75
+ if (taskPaths.length === 0) {
76
+ taskPaths = [join(projectPath, 'project-documents/user/tasks', project.fileTasks)];
77
+ }
78
+ const taskResult = await parseTaskFile(taskPaths);
79
+ if (taskResult.totalTasks > 0) {
80
+ summary.currentTasks = {
81
+ totalTasks: taskResult.totalTasks,
82
+ completedTasks: taskResult.completedTasks,
83
+ inferredStatus: taskResult.inferredStatus,
84
+ summary: `${taskResult.completedTasks} of ${taskResult.totalTasks} tasks done`,
85
+ };
86
+ }
87
+ }
88
+ }
89
+ catch {
90
+ // Task parsing failed — continue with other operations
91
+ }
92
+ // Check artifact existence
93
+ try {
94
+ if (project.fileSlicePlan) {
95
+ summary.artifacts.hasSlicePlan = await checkFileExists(projectPath, project.fileSlicePlan);
96
+ }
97
+ }
98
+ catch { /* continue */ }
99
+ try {
100
+ if (project.fileHLD) {
101
+ summary.artifacts.hasHLD = await checkFileExists(projectPath, project.fileHLD);
102
+ }
103
+ }
104
+ catch { /* continue */ }
105
+ try {
106
+ if (project.fileArch) {
107
+ summary.artifacts.hasArch = await checkFileExists(projectPath, project.fileArch);
108
+ }
109
+ }
110
+ catch { /* continue */ }
111
+ try {
112
+ if (project.fileSpec) {
113
+ summary.artifacts.hasSpec = await checkFileExists(projectPath, project.fileSpec);
114
+ }
115
+ }
116
+ catch { /* continue */ }
117
+ // Check current slice design and task file existence
118
+ try {
119
+ const sliceIndex = extractSliceIndex(project.fileSlice);
120
+ if (sliceIndex !== null) {
121
+ const docs = await detectDocuments(projectPath, sliceIndex);
122
+ summary.artifacts.hasCurrentSliceDesign = docs.sliceDesign !== null;
123
+ summary.artifacts.hasCurrentTaskFile = docs.taskFile !== null;
124
+ }
125
+ }
126
+ catch { /* continue */ }
127
+ return summary;
128
+ }
129
+ }
130
+ /**
131
+ * Extract the numeric slice index from a fileSlice value like "163-slice.artifact-introspection.md".
132
+ * Returns null if no leading number found.
133
+ */
134
+ function extractSliceIndex(fileSlice) {
135
+ if (!fileSlice)
136
+ return null;
137
+ const match = /^(\d+)-/.exec(fileSlice);
138
+ return match ? parseInt(match[1], 10) : null;
139
+ }
140
+ //# sourceMappingURL=ArtifactIntrospector.js.map