@organon-methodology/tools 0.3.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 (287) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +152 -0
  3. package/dist/cli/commands/coverage.d.ts +12 -0
  4. package/dist/cli/commands/coverage.d.ts.map +1 -0
  5. package/dist/cli/commands/coverage.js +80 -0
  6. package/dist/cli/commands/coverage.js.map +1 -0
  7. package/dist/cli/commands/find.d.ts +15 -0
  8. package/dist/cli/commands/find.d.ts.map +1 -0
  9. package/dist/cli/commands/find.js +81 -0
  10. package/dist/cli/commands/find.js.map +1 -0
  11. package/dist/cli/commands/generate-tests.d.ts +14 -0
  12. package/dist/cli/commands/generate-tests.d.ts.map +1 -0
  13. package/dist/cli/commands/generate-tests.js +87 -0
  14. package/dist/cli/commands/generate-tests.js.map +1 -0
  15. package/dist/cli/commands/generate.d.ts +15 -0
  16. package/dist/cli/commands/generate.d.ts.map +1 -0
  17. package/dist/cli/commands/generate.js +77 -0
  18. package/dist/cli/commands/generate.js.map +1 -0
  19. package/dist/cli/commands/health.d.ts +13 -0
  20. package/dist/cli/commands/health.d.ts.map +1 -0
  21. package/dist/cli/commands/health.js +79 -0
  22. package/dist/cli/commands/health.js.map +1 -0
  23. package/dist/cli/commands/init.d.ts +14 -0
  24. package/dist/cli/commands/init.d.ts.map +1 -0
  25. package/dist/cli/commands/init.js +132 -0
  26. package/dist/cli/commands/init.js.map +1 -0
  27. package/dist/cli/commands/mcp.d.ts +11 -0
  28. package/dist/cli/commands/mcp.d.ts.map +1 -0
  29. package/dist/cli/commands/mcp.js +26 -0
  30. package/dist/cli/commands/mcp.js.map +1 -0
  31. package/dist/cli/commands/query.d.ts +19 -0
  32. package/dist/cli/commands/query.d.ts.map +1 -0
  33. package/dist/cli/commands/query.js +103 -0
  34. package/dist/cli/commands/query.js.map +1 -0
  35. package/dist/cli/commands/upgrade.d.ts +13 -0
  36. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  37. package/dist/cli/commands/upgrade.js +162 -0
  38. package/dist/cli/commands/upgrade.js.map +1 -0
  39. package/dist/cli/commands/validate.d.ts +13 -0
  40. package/dist/cli/commands/validate.d.ts.map +1 -0
  41. package/dist/cli/commands/validate.js +89 -0
  42. package/dist/cli/commands/validate.js.map +1 -0
  43. package/dist/cli/commands/verify.d.ts +12 -0
  44. package/dist/cli/commands/verify.d.ts.map +1 -0
  45. package/dist/cli/commands/verify.js +67 -0
  46. package/dist/cli/commands/verify.js.map +1 -0
  47. package/dist/cli/index.d.ts +19 -0
  48. package/dist/cli/index.d.ts.map +1 -0
  49. package/dist/cli/index.js +59 -0
  50. package/dist/cli/index.js.map +1 -0
  51. package/dist/core/add-protocols-array.d.ts +17 -0
  52. package/dist/core/add-protocols-array.d.ts.map +1 -0
  53. package/dist/core/add-protocols-array.js +95 -0
  54. package/dist/core/add-protocols-array.js.map +1 -0
  55. package/dist/core/add-protocols-array.test.d.ts +2 -0
  56. package/dist/core/add-protocols-array.test.d.ts.map +1 -0
  57. package/dist/core/add-protocols-array.test.js +86 -0
  58. package/dist/core/add-protocols-array.test.js.map +1 -0
  59. package/dist/core/config.d.ts +44 -0
  60. package/dist/core/config.d.ts.map +1 -0
  61. package/dist/core/config.js +130 -0
  62. package/dist/core/config.js.map +1 -0
  63. package/dist/core/config.test.d.ts +2 -0
  64. package/dist/core/config.test.d.ts.map +1 -0
  65. package/dist/core/config.test.js +88 -0
  66. package/dist/core/config.test.js.map +1 -0
  67. package/dist/core/find.d.ts +29 -0
  68. package/dist/core/find.d.ts.map +1 -0
  69. package/dist/core/find.js +191 -0
  70. package/dist/core/find.js.map +1 -0
  71. package/dist/core/find.test.d.ts +2 -0
  72. package/dist/core/find.test.d.ts.map +1 -0
  73. package/dist/core/find.test.js +91 -0
  74. package/dist/core/find.test.js.map +1 -0
  75. package/dist/core/frontmatter-parser.d.ts +45 -0
  76. package/dist/core/frontmatter-parser.d.ts.map +1 -0
  77. package/dist/core/frontmatter-parser.js +122 -0
  78. package/dist/core/frontmatter-parser.js.map +1 -0
  79. package/dist/core/frontmatter-parser.test.d.ts +2 -0
  80. package/dist/core/frontmatter-parser.test.d.ts.map +1 -0
  81. package/dist/core/frontmatter-parser.test.js +200 -0
  82. package/dist/core/frontmatter-parser.test.js.map +1 -0
  83. package/dist/core/generate-frontmatter.d.ts +27 -0
  84. package/dist/core/generate-frontmatter.d.ts.map +1 -0
  85. package/dist/core/generate-frontmatter.js +219 -0
  86. package/dist/core/generate-frontmatter.js.map +1 -0
  87. package/dist/core/generate-frontmatter.test.d.ts +2 -0
  88. package/dist/core/generate-frontmatter.test.d.ts.map +1 -0
  89. package/dist/core/generate-frontmatter.test.js +161 -0
  90. package/dist/core/generate-frontmatter.test.js.map +1 -0
  91. package/dist/core/generate-tests.d.ts +41 -0
  92. package/dist/core/generate-tests.d.ts.map +1 -0
  93. package/dist/core/generate-tests.js +191 -0
  94. package/dist/core/generate-tests.js.map +1 -0
  95. package/dist/core/generate-tests.test.d.ts +2 -0
  96. package/dist/core/generate-tests.test.d.ts.map +1 -0
  97. package/dist/core/generate-tests.test.js +205 -0
  98. package/dist/core/generate-tests.test.js.map +1 -0
  99. package/dist/core/health.d.ts +16 -0
  100. package/dist/core/health.d.ts.map +1 -0
  101. package/dist/core/health.js +156 -0
  102. package/dist/core/health.js.map +1 -0
  103. package/dist/core/health.test.d.ts +2 -0
  104. package/dist/core/health.test.d.ts.map +1 -0
  105. package/dist/core/health.test.js +97 -0
  106. package/dist/core/health.test.js.map +1 -0
  107. package/dist/core/init.d.ts +25 -0
  108. package/dist/core/init.d.ts.map +1 -0
  109. package/dist/core/init.js +100 -0
  110. package/dist/core/init.js.map +1 -0
  111. package/dist/core/init.test.d.ts +8 -0
  112. package/dist/core/init.test.d.ts.map +1 -0
  113. package/dist/core/init.test.js +203 -0
  114. package/dist/core/init.test.js.map +1 -0
  115. package/dist/core/invariant-coverage.d.ts +41 -0
  116. package/dist/core/invariant-coverage.d.ts.map +1 -0
  117. package/dist/core/invariant-coverage.js +181 -0
  118. package/dist/core/invariant-coverage.js.map +1 -0
  119. package/dist/core/invariant-coverage.test.d.ts +2 -0
  120. package/dist/core/invariant-coverage.test.d.ts.map +1 -0
  121. package/dist/core/invariant-coverage.test.js +188 -0
  122. package/dist/core/invariant-coverage.test.js.map +1 -0
  123. package/dist/core/meta-invariants.test.d.ts +17 -0
  124. package/dist/core/meta-invariants.test.d.ts.map +1 -0
  125. package/dist/core/meta-invariants.test.js +191 -0
  126. package/dist/core/meta-invariants.test.js.map +1 -0
  127. package/dist/core/node-fs.d.ts +22 -0
  128. package/dist/core/node-fs.d.ts.map +1 -0
  129. package/dist/core/node-fs.js +47 -0
  130. package/dist/core/node-fs.js.map +1 -0
  131. package/dist/core/organon-invariants.test.d.ts +15 -0
  132. package/dist/core/organon-invariants.test.d.ts.map +1 -0
  133. package/dist/core/organon-invariants.test.js +149 -0
  134. package/dist/core/organon-invariants.test.js.map +1 -0
  135. package/dist/core/query.d.ts +35 -0
  136. package/dist/core/query.d.ts.map +1 -0
  137. package/dist/core/query.js +139 -0
  138. package/dist/core/query.js.map +1 -0
  139. package/dist/core/query.test.d.ts +2 -0
  140. package/dist/core/query.test.d.ts.map +1 -0
  141. package/dist/core/query.test.js +97 -0
  142. package/dist/core/query.test.js.map +1 -0
  143. package/dist/core/suggest-tools.d.ts +15 -0
  144. package/dist/core/suggest-tools.d.ts.map +1 -0
  145. package/dist/core/suggest-tools.js +139 -0
  146. package/dist/core/suggest-tools.js.map +1 -0
  147. package/dist/core/suggest-tools.test.d.ts +2 -0
  148. package/dist/core/suggest-tools.test.d.ts.map +1 -0
  149. package/dist/core/suggest-tools.test.js +122 -0
  150. package/dist/core/suggest-tools.test.js.map +1 -0
  151. package/dist/core/test-helpers.d.ts +63 -0
  152. package/dist/core/test-helpers.d.ts.map +1 -0
  153. package/dist/core/test-helpers.js +265 -0
  154. package/dist/core/test-helpers.js.map +1 -0
  155. package/dist/core/types.d.ts +277 -0
  156. package/dist/core/types.d.ts.map +1 -0
  157. package/dist/core/types.js +9 -0
  158. package/dist/core/types.js.map +1 -0
  159. package/dist/core/upgrade.d.ts +46 -0
  160. package/dist/core/upgrade.d.ts.map +1 -0
  161. package/dist/core/upgrade.js +227 -0
  162. package/dist/core/upgrade.js.map +1 -0
  163. package/dist/core/upgrade.test.d.ts +8 -0
  164. package/dist/core/upgrade.test.d.ts.map +1 -0
  165. package/dist/core/upgrade.test.js +370 -0
  166. package/dist/core/upgrade.test.js.map +1 -0
  167. package/dist/core/validate-frontmatter.d.ts +20 -0
  168. package/dist/core/validate-frontmatter.d.ts.map +1 -0
  169. package/dist/core/validate-frontmatter.js +529 -0
  170. package/dist/core/validate-frontmatter.js.map +1 -0
  171. package/dist/core/validate-frontmatter.test.d.ts +2 -0
  172. package/dist/core/validate-frontmatter.test.d.ts.map +1 -0
  173. package/dist/core/validate-frontmatter.test.js +366 -0
  174. package/dist/core/validate-frontmatter.test.js.map +1 -0
  175. package/dist/core/validate-workflow.d.ts +17 -0
  176. package/dist/core/validate-workflow.d.ts.map +1 -0
  177. package/dist/core/validate-workflow.js +233 -0
  178. package/dist/core/validate-workflow.js.map +1 -0
  179. package/dist/core/validate-workflow.test.d.ts +2 -0
  180. package/dist/core/validate-workflow.test.d.ts.map +1 -0
  181. package/dist/core/validate-workflow.test.js +205 -0
  182. package/dist/core/validate-workflow.test.js.map +1 -0
  183. package/dist/core/verify-tier4-tests.d.ts +34 -0
  184. package/dist/core/verify-tier4-tests.d.ts.map +1 -0
  185. package/dist/core/verify-tier4-tests.js +106 -0
  186. package/dist/core/verify-tier4-tests.js.map +1 -0
  187. package/dist/core/verify-tier4-tests.test.d.ts +2 -0
  188. package/dist/core/verify-tier4-tests.test.d.ts.map +1 -0
  189. package/dist/core/verify-tier4-tests.test.js +140 -0
  190. package/dist/core/verify-tier4-tests.test.js.map +1 -0
  191. package/dist/core/verify-triplets.d.ts +17 -0
  192. package/dist/core/verify-triplets.d.ts.map +1 -0
  193. package/dist/core/verify-triplets.js +217 -0
  194. package/dist/core/verify-triplets.js.map +1 -0
  195. package/dist/core/verify-triplets.test.d.ts +2 -0
  196. package/dist/core/verify-triplets.test.d.ts.map +1 -0
  197. package/dist/core/verify-triplets.test.js +147 -0
  198. package/dist/core/verify-triplets.test.js.map +1 -0
  199. package/dist/core/verify.d.ts +19 -0
  200. package/dist/core/verify.d.ts.map +1 -0
  201. package/dist/core/verify.js +162 -0
  202. package/dist/core/verify.js.map +1 -0
  203. package/dist/core/verify.test.d.ts +2 -0
  204. package/dist/core/verify.test.d.ts.map +1 -0
  205. package/dist/core/verify.test.js +147 -0
  206. package/dist/core/verify.test.js.map +1 -0
  207. package/dist/index.d.ts +31 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +27 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/mcp/prompts.d.ts +9 -0
  212. package/dist/mcp/prompts.d.ts.map +1 -0
  213. package/dist/mcp/prompts.js +265 -0
  214. package/dist/mcp/prompts.js.map +1 -0
  215. package/dist/mcp/resources.d.ts +7 -0
  216. package/dist/mcp/resources.d.ts.map +1 -0
  217. package/dist/mcp/resources.js +111 -0
  218. package/dist/mcp/resources.js.map +1 -0
  219. package/dist/mcp/server.d.ts +7 -0
  220. package/dist/mcp/server.d.ts.map +1 -0
  221. package/dist/mcp/server.js +31 -0
  222. package/dist/mcp/server.js.map +1 -0
  223. package/dist/mcp/tools.d.ts +7 -0
  224. package/dist/mcp/tools.d.ts.map +1 -0
  225. package/dist/mcp/tools.js +130 -0
  226. package/dist/mcp/tools.js.map +1 -0
  227. package/dist/templates/config.d.ts +6 -0
  228. package/dist/templates/config.d.ts.map +1 -0
  229. package/dist/templates/config.js +30 -0
  230. package/dist/templates/config.js.map +1 -0
  231. package/dist/templates/index.d.ts +7 -0
  232. package/dist/templates/index.d.ts.map +1 -0
  233. package/dist/templates/index.js +7 -0
  234. package/dist/templates/index.js.map +1 -0
  235. package/dist/templates/organon/claude-md.d.ts +7 -0
  236. package/dist/templates/organon/claude-md.d.ts.map +1 -0
  237. package/dist/templates/organon/claude-md.js +32 -0
  238. package/dist/templates/organon/claude-md.js.map +1 -0
  239. package/dist/templates/organon/ethos.d.ts +5 -0
  240. package/dist/templates/organon/ethos.d.ts.map +1 -0
  241. package/dist/templates/organon/ethos.js +69 -0
  242. package/dist/templates/organon/ethos.js.map +1 -0
  243. package/dist/templates/organon/index.d.ts +10 -0
  244. package/dist/templates/organon/index.d.ts.map +1 -0
  245. package/dist/templates/organon/index.js +10 -0
  246. package/dist/templates/organon/index.js.map +1 -0
  247. package/dist/templates/organon/observations-readme.d.ts +5 -0
  248. package/dist/templates/organon/observations-readme.d.ts.map +1 -0
  249. package/dist/templates/organon/observations-readme.js +25 -0
  250. package/dist/templates/organon/observations-readme.js.map +1 -0
  251. package/dist/templates/organon/philosophy.d.ts +5 -0
  252. package/dist/templates/organon/philosophy.d.ts.map +1 -0
  253. package/dist/templates/organon/philosophy.js +75 -0
  254. package/dist/templates/organon/philosophy.js.map +1 -0
  255. package/dist/templates/organon/protocols.d.ts +7 -0
  256. package/dist/templates/organon/protocols.d.ts.map +1 -0
  257. package/dist/templates/organon/protocols.js +197 -0
  258. package/dist/templates/organon/protocols.js.map +1 -0
  259. package/dist/templates/organon/readme.d.ts +5 -0
  260. package/dist/templates/organon/readme.d.ts.map +1 -0
  261. package/dist/templates/organon/readme.js +40 -0
  262. package/dist/templates/organon/readme.js.map +1 -0
  263. package/dist/templates/skills/domain-feature-design.d.ts +9 -0
  264. package/dist/templates/skills/domain-feature-design.d.ts.map +1 -0
  265. package/dist/templates/skills/domain-feature-design.js +123 -0
  266. package/dist/templates/skills/domain-feature-design.js.map +1 -0
  267. package/dist/templates/skills/index.d.ts +15 -0
  268. package/dist/templates/skills/index.d.ts.map +1 -0
  269. package/dist/templates/skills/index.js +35 -0
  270. package/dist/templates/skills/index.js.map +1 -0
  271. package/dist/templates/skills/organon-file-creation.d.ts +9 -0
  272. package/dist/templates/skills/organon-file-creation.d.ts.map +1 -0
  273. package/dist/templates/skills/organon-file-creation.js +138 -0
  274. package/dist/templates/skills/organon-file-creation.js.map +1 -0
  275. package/dist/templates/skills/quality-review.d.ts +9 -0
  276. package/dist/templates/skills/quality-review.d.ts.map +1 -0
  277. package/dist/templates/skills/quality-review.js +127 -0
  278. package/dist/templates/skills/quality-review.js.map +1 -0
  279. package/dist/templates/skills/session-compounding.d.ts +9 -0
  280. package/dist/templates/skills/session-compounding.d.ts.map +1 -0
  281. package/dist/templates/skills/session-compounding.js +118 -0
  282. package/dist/templates/skills/session-compounding.js.map +1 -0
  283. package/dist/templates/skills/verify-and-health.d.ts +9 -0
  284. package/dist/templates/skills/verify-and-health.d.ts.map +1 -0
  285. package/dist/templates/skills/verify-and-health.js +99 -0
  286. package/dist/templates/skills/verify-and-health.js.map +1 -0
  287. package/package.json +72 -0
@@ -0,0 +1,130 @@
1
+ /**
2
+ * OrganonConfig resolution.
3
+ *
4
+ * Discovery order:
5
+ * 1. Explicit config file path (--config flag)
6
+ * 2. organon.config.json in projectRoot
7
+ * 3. Convention-based defaults (scan for organon/, .claude/skills/, etc.)
8
+ */
9
+ import { z } from 'zod';
10
+ const CONFIG_FILENAME = 'organon.config.json';
11
+ const WorkflowPathsSchema = z.object({
12
+ claudeCode: z.string().optional(),
13
+ cursor: z.string().optional(),
14
+ generic: z.string().optional(),
15
+ }).strict();
16
+ const ConfigFileSchema = z.object({
17
+ methodology_version: z.string().optional(),
18
+ organonPaths: z.array(z.string()).optional(),
19
+ organonGlobs: z.array(z.string()).optional(),
20
+ ignorePatterns: z.array(z.string()).optional(),
21
+ workflowPaths: WorkflowPathsSchema.optional(),
22
+ freshnessThresholdHours: z.number().positive().optional(),
23
+ testGlobs: z.array(z.string()).optional(),
24
+ testIgnorePatterns: z.array(z.string()).optional(),
25
+ }).strict();
26
+ const DEFAULT_ORGANON_GLOBS = [
27
+ '**/ETHOS.md',
28
+ '**/PHILOSOPHY.md',
29
+ '**/PROTOCOL.md',
30
+ '**/PROTOCOLS.md',
31
+ '**/README.md',
32
+ '**/components.md',
33
+ ];
34
+ const DEFAULT_IGNORE_PATTERNS = [
35
+ '**/node_modules/**',
36
+ '**/dist/**',
37
+ '**/.git/**',
38
+ '**/coverage/**',
39
+ '*.test.*',
40
+ '*.spec.*',
41
+ ];
42
+ const CONVENTION_ORGANON_DIRS = [
43
+ 'organon',
44
+ 'book-llms',
45
+ ];
46
+ const CONVENTION_WORKFLOW_PATHS = {
47
+ claudeCode: '.claude/skills',
48
+ cursor: '.cursor/rules',
49
+ generic: 'organon/workflows',
50
+ };
51
+ /**
52
+ * Resolve config by merging file-based config with convention defaults.
53
+ */
54
+ export async function resolveConfig(projectRoot, fs, configPath) {
55
+ const fileConfig = await loadConfigFile(projectRoot, fs, configPath);
56
+ const conventionPaths = await discoverConventionPaths(projectRoot, fs);
57
+ const organonPaths = fileConfig?.organonPaths ?? conventionPaths;
58
+ const organonGlobs = fileConfig?.organonGlobs ?? DEFAULT_ORGANON_GLOBS;
59
+ const ignorePatterns = fileConfig?.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS;
60
+ const workflowPaths = {
61
+ ...CONVENTION_WORKFLOW_PATHS,
62
+ ...fileConfig?.workflowPaths,
63
+ };
64
+ const freshnessThresholdHours = fileConfig?.freshnessThresholdHours ?? 24;
65
+ const testGlobs = fileConfig?.testGlobs;
66
+ const testIgnorePatterns = fileConfig?.testIgnorePatterns;
67
+ return {
68
+ projectRoot,
69
+ organonPaths,
70
+ organonGlobs,
71
+ ignorePatterns,
72
+ workflowPaths,
73
+ freshnessThresholdHours,
74
+ testGlobs,
75
+ testIgnorePatterns,
76
+ };
77
+ }
78
+ async function loadConfigFile(projectRoot, fs, configPath) {
79
+ const path = configPath
80
+ ? joinPath(projectRoot, configPath)
81
+ : joinPath(projectRoot, CONFIG_FILENAME);
82
+ if (!await fs.exists(path)) {
83
+ return null;
84
+ }
85
+ const raw = await fs.readFile(path);
86
+ const parsed = JSON.parse(raw);
87
+ return ConfigFileSchema.parse(parsed);
88
+ }
89
+ async function discoverConventionPaths(projectRoot, fs) {
90
+ const found = [];
91
+ for (const dir of CONVENTION_ORGANON_DIRS) {
92
+ if (await fs.exists(joinPath(projectRoot, dir))) {
93
+ found.push(dir);
94
+ }
95
+ }
96
+ // Always include project root for top-level ETHOS.md etc.
97
+ if (!found.includes('.')) {
98
+ found.push('.');
99
+ }
100
+ return found;
101
+ }
102
+ /**
103
+ * Simple path join that handles both / and \ separators.
104
+ * Avoids importing node:path in the core module.
105
+ */
106
+ export function joinPath(...segments) {
107
+ return segments
108
+ .map((s, i) => (i === 0 ? s : s.replace(/^[/\\]+/, '')))
109
+ .join('/')
110
+ .replace(/\/+/g, '/');
111
+ }
112
+ /**
113
+ * Get the directory portion of a path.
114
+ */
115
+ export function dirName(path) {
116
+ const normalized = path.replace(/\\/g, '/');
117
+ const lastSlash = normalized.lastIndexOf('/');
118
+ if (lastSlash === -1)
119
+ return '.';
120
+ return normalized.substring(0, lastSlash);
121
+ }
122
+ /**
123
+ * Get the filename from a path.
124
+ */
125
+ export function baseName(path) {
126
+ const normalized = path.replace(/\\/g, '/');
127
+ const lastSlash = normalized.lastIndexOf('/');
128
+ return lastSlash === -1 ? normalized : normalized.substring(lastSlash + 1);
129
+ }
130
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/core/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { resolveConfig, joinPath, dirName, baseName } from './config.js';
3
+ import { MemoryFileSystem } from './test-helpers.js';
4
+ describe('resolveConfig', () => {
5
+ it('uses convention defaults when no config file exists', async () => {
6
+ const fs = new MemoryFileSystem({
7
+ '/project/organon/ETHOS.md': 'content',
8
+ '/project/book-llms/ETHOS.md': 'content',
9
+ });
10
+ const config = await resolveConfig('/project', fs);
11
+ expect(config.projectRoot).toBe('/project');
12
+ expect(config.organonPaths).toContain('organon');
13
+ expect(config.organonPaths).toContain('book-llms');
14
+ expect(config.organonPaths).toContain('.');
15
+ expect(config.freshnessThresholdHours).toBe(24);
16
+ });
17
+ it('loads config from organon.config.json', async () => {
18
+ const fs = new MemoryFileSystem({
19
+ '/project/organon.config.json': JSON.stringify({
20
+ organonPaths: ['docs'],
21
+ freshnessThresholdHours: 48,
22
+ }),
23
+ });
24
+ const config = await resolveConfig('/project', fs);
25
+ expect(config.organonPaths).toEqual(['docs']);
26
+ expect(config.freshnessThresholdHours).toBe(48);
27
+ });
28
+ it('loads config from custom path', async () => {
29
+ const fs = new MemoryFileSystem({
30
+ '/project/custom/config.json': JSON.stringify({
31
+ organonPaths: ['custom-docs'],
32
+ }),
33
+ });
34
+ const config = await resolveConfig('/project', fs, 'custom/config.json');
35
+ expect(config.organonPaths).toEqual(['custom-docs']);
36
+ });
37
+ it('includes default workflow paths', async () => {
38
+ const fs = new MemoryFileSystem();
39
+ const config = await resolveConfig('/project', fs);
40
+ expect(config.workflowPaths.claudeCode).toBe('.claude/skills');
41
+ expect(config.workflowPaths.cursor).toBe('.cursor/rules');
42
+ expect(config.workflowPaths.generic).toBe('organon/workflows');
43
+ });
44
+ it('merges config file workflow paths with defaults', async () => {
45
+ const fs = new MemoryFileSystem({
46
+ '/project/organon.config.json': JSON.stringify({
47
+ workflowPaths: { claudeCode: '.custom/skills' },
48
+ }),
49
+ });
50
+ const config = await resolveConfig('/project', fs);
51
+ expect(config.workflowPaths.claudeCode).toBe('.custom/skills');
52
+ expect(config.workflowPaths.cursor).toBe('.cursor/rules'); // still default
53
+ });
54
+ });
55
+ describe('joinPath', () => {
56
+ it('joins path segments', () => {
57
+ expect(joinPath('/project', 'book-llms', 'ETHOS.md')).toBe('/project/book-llms/ETHOS.md');
58
+ });
59
+ it('handles trailing slashes', () => {
60
+ expect(joinPath('/project/', 'file.md')).toBe('/project/file.md');
61
+ });
62
+ it('handles leading slashes on segments', () => {
63
+ expect(joinPath('/project', '/book-llms')).toBe('/project/book-llms');
64
+ });
65
+ });
66
+ describe('dirName', () => {
67
+ it('returns directory portion', () => {
68
+ expect(dirName('book-llms/ETHOS.md')).toBe('book-llms');
69
+ });
70
+ it('returns . for root-level file', () => {
71
+ expect(dirName('ETHOS.md')).toBe('.');
72
+ });
73
+ it('handles nested paths', () => {
74
+ expect(dirName('organon/domains/genesis/ETHOS.md')).toBe('organon/domains/genesis');
75
+ });
76
+ it('normalizes backslashes', () => {
77
+ expect(dirName('organon\\domains\\genesis\\ETHOS.md')).toBe('organon/domains/genesis');
78
+ });
79
+ });
80
+ describe('baseName', () => {
81
+ it('returns filename', () => {
82
+ expect(baseName('book-llms/ETHOS.md')).toBe('ETHOS.md');
83
+ });
84
+ it('returns the input for bare filenames', () => {
85
+ expect(baseName('ETHOS.md')).toBe('ETHOS.md');
86
+ });
87
+ });
88
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/core/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Cross-domain discovery.
3
+ *
4
+ * Rewritten (not ported) from Agent Tavern — the AT version was
5
+ * 60% AT-specific. This version operates on organon files + frontmatter
6
+ * rather than components.md or domain-specific structures.
7
+ *
8
+ * Search modes:
9
+ * by-file — find organons that govern a given file path
10
+ * by-scope — list all organons at a given scope level
11
+ * by-type — list all organons of a given type
12
+ * by-name — find organons matching a name pattern
13
+ */
14
+ import type { FileSystem, FindResult, FrontmatterScope, FrontmatterType, OrganonConfig } from './types.js';
15
+ export interface FindOptions {
16
+ projectRoot: string;
17
+ config: OrganonConfig;
18
+ fs: FileSystem;
19
+ /** Find organons that govern this file path */
20
+ file?: string;
21
+ /** Find all organons at this scope level */
22
+ scope?: FrontmatterScope;
23
+ /** Find all organons of this type */
24
+ type?: FrontmatterType;
25
+ /** Find organons matching this name (substring) */
26
+ name?: string;
27
+ }
28
+ export declare function find(options: FindOptions): Promise<FindResult>;
29
+ //# sourceMappingURL=find.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../src/core/find.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAEV,UAAU,EAEV,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EAEd,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,EAAE,EAAE,UAAU,CAAC;IACf,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,qCAAqC;IACrC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA2DpE"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Cross-domain discovery.
3
+ *
4
+ * Rewritten (not ported) from Agent Tavern — the AT version was
5
+ * 60% AT-specific. This version operates on organon files + frontmatter
6
+ * rather than components.md or domain-specific structures.
7
+ *
8
+ * Search modes:
9
+ * by-file — find organons that govern a given file path
10
+ * by-scope — list all organons at a given scope level
11
+ * by-type — list all organons of a given type
12
+ * by-name — find organons matching a name pattern
13
+ */
14
+ import { parseOrganonFile } from './frontmatter-parser.js';
15
+ import { joinPath, dirName } from './config.js';
16
+ // ---------------------------------------------------------------------------
17
+ // Main
18
+ // ---------------------------------------------------------------------------
19
+ export async function find(options) {
20
+ const { projectRoot, config, fs } = options;
21
+ const errors = [];
22
+ const warnings = [];
23
+ // Discover and parse all organon files
24
+ const allFiles = await discoverOrganonFiles(projectRoot, config, fs);
25
+ const parsed = [];
26
+ for (const file of allFiles) {
27
+ const absPath = joinPath(projectRoot, file);
28
+ try {
29
+ const content = await fs.readFile(absPath);
30
+ parsed.push(parseOrganonFile(file, content));
31
+ }
32
+ catch {
33
+ errors.push({
34
+ severity: 'error',
35
+ code: 'FILE_READ_ERROR',
36
+ message: `Cannot read file: ${file}`,
37
+ file,
38
+ });
39
+ }
40
+ }
41
+ let mode;
42
+ let matches;
43
+ if (options.file) {
44
+ mode = 'by-file';
45
+ matches = findByFile(options.file, parsed);
46
+ }
47
+ else if (options.scope) {
48
+ mode = 'by-scope';
49
+ matches = findByScope(options.scope, parsed);
50
+ }
51
+ else if (options.type) {
52
+ mode = 'by-type';
53
+ matches = findByType(options.type, parsed);
54
+ }
55
+ else if (options.name) {
56
+ mode = 'by-name';
57
+ matches = findByName(options.name, parsed);
58
+ }
59
+ else {
60
+ return {
61
+ success: false,
62
+ mode: 'by-name',
63
+ matches: [],
64
+ errors: [{
65
+ severity: 'error',
66
+ code: 'FIND_NO_CRITERIA',
67
+ message: 'Specify at least one search criterion: file, scope, type, or name',
68
+ }],
69
+ warnings: [],
70
+ };
71
+ }
72
+ return {
73
+ success: errors.length === 0,
74
+ mode,
75
+ matches,
76
+ errors,
77
+ warnings,
78
+ };
79
+ }
80
+ // ---------------------------------------------------------------------------
81
+ // Search implementations
82
+ // ---------------------------------------------------------------------------
83
+ /**
84
+ * Find organons that govern a given file path.
85
+ * Walks up the directory tree to find the nearest ETHOS.md,
86
+ * plus product-level constraints.
87
+ */
88
+ function findByFile(targetFile, parsed) {
89
+ const normalized = targetFile.replace(/\\/g, '/');
90
+ const matches = [];
91
+ // Always include product-level organons (root ETHOS.md, etc.)
92
+ const productFiles = parsed.filter((f) => f.frontmatter?.scope === 'product' ||
93
+ (f.frontmatter === null && isRootFile(f.path)));
94
+ for (const pf of productFiles) {
95
+ matches.push({
96
+ file: pf.path,
97
+ frontmatter: pf.frontmatter,
98
+ relevance: 'product-level constraint',
99
+ });
100
+ }
101
+ // Walk up the directory tree to find governing organons
102
+ let dir = dirName(normalized);
103
+ const visited = new Set();
104
+ while (dir && dir !== '.' && !visited.has(dir)) {
105
+ visited.add(dir);
106
+ const governing = parsed.filter((f) => {
107
+ const organonDir = dirName(f.path.replace(/\\/g, '/'));
108
+ return organonDir === dir;
109
+ });
110
+ for (const g of governing) {
111
+ if (!matches.find((m) => m.file === g.path)) {
112
+ matches.push({
113
+ file: g.path,
114
+ frontmatter: g.frontmatter,
115
+ relevance: `directory ancestor: ${dir}`,
116
+ });
117
+ }
118
+ }
119
+ // Move up
120
+ const lastSlash = dir.lastIndexOf('/');
121
+ dir = lastSlash > 0 ? dir.substring(0, lastSlash) : '';
122
+ }
123
+ // Find by domain name match in the path
124
+ for (const p of parsed) {
125
+ if (p.frontmatter?.scope === 'domain' && p.frontmatter?.name) {
126
+ if (normalized.includes(`/${p.frontmatter.name}/`) || normalized.includes(`\\${p.frontmatter.name}\\`)) {
127
+ if (!matches.find((m) => m.file === p.path)) {
128
+ matches.push({
129
+ file: p.path,
130
+ frontmatter: p.frontmatter,
131
+ relevance: `domain name match: ${p.frontmatter.name}`,
132
+ });
133
+ }
134
+ }
135
+ }
136
+ }
137
+ return matches;
138
+ }
139
+ function findByScope(scope, parsed) {
140
+ return parsed
141
+ .filter((f) => f.frontmatter?.scope === scope)
142
+ .map((f) => ({
143
+ file: f.path,
144
+ frontmatter: f.frontmatter,
145
+ relevance: `scope: ${scope}`,
146
+ }));
147
+ }
148
+ function findByType(type, parsed) {
149
+ return parsed
150
+ .filter((f) => f.frontmatter?.type === type)
151
+ .map((f) => ({
152
+ file: f.path,
153
+ frontmatter: f.frontmatter,
154
+ relevance: `type: ${type}`,
155
+ }));
156
+ }
157
+ function findByName(name, parsed) {
158
+ const lower = name.toLowerCase();
159
+ return parsed
160
+ .filter((f) => f.frontmatter?.name?.toLowerCase().includes(lower) ||
161
+ f.path.toLowerCase().includes(lower))
162
+ .map((f) => ({
163
+ file: f.path,
164
+ frontmatter: f.frontmatter,
165
+ relevance: `name match: ${name}`,
166
+ }));
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Helpers
170
+ // ---------------------------------------------------------------------------
171
+ function isRootFile(path) {
172
+ const normalized = path.replace(/\\/g, '/');
173
+ return !normalized.includes('/') || normalized.split('/').length <= 2;
174
+ }
175
+ async function discoverOrganonFiles(projectRoot, config, fs) {
176
+ const allFiles = new Set();
177
+ for (const organonPath of config.organonPaths) {
178
+ for (const pattern of config.organonGlobs) {
179
+ const fullPattern = organonPath === '.' ? pattern : `${organonPath}/${pattern}`;
180
+ const matches = await fs.glob(fullPattern, {
181
+ cwd: projectRoot,
182
+ ignore: config.ignorePatterns,
183
+ });
184
+ for (const m of matches) {
185
+ allFiles.add(m);
186
+ }
187
+ }
188
+ }
189
+ return [...allFiles].sort();
190
+ }
191
+ //# sourceMappingURL=find.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.js","sourceRoot":"","sources":["../../src/core/find.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=find.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.test.d.ts","sourceRoot":"","sources":["../../src/core/find.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,91 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { find } from './find.js';
3
+ import { MemoryFileSystem, makeEthos, makeReadme } from './test-helpers.js';
4
+ function makeConfig(projectRoot) {
5
+ return {
6
+ projectRoot,
7
+ organonPaths: ['.'],
8
+ organonGlobs: ['**/ETHOS.md', '**/README.md'],
9
+ ignorePatterns: [],
10
+ workflowPaths: {},
11
+ freshnessThresholdHours: 24,
12
+ };
13
+ }
14
+ describe('find', () => {
15
+ function makeFs() {
16
+ return new MemoryFileSystem({
17
+ '/project/ETHOS.md': makeEthos({ name: 'product', scope: 'product' }),
18
+ '/project/organon/domains/genesis/ETHOS.md': makeEthos({ name: 'genesis', scope: 'domain' }),
19
+ '/project/organon/domains/agents/ETHOS.md': makeEthos({ name: 'agents', scope: 'domain' }),
20
+ '/project/README.md': makeReadme({ name: 'root', scope: 'product' }),
21
+ });
22
+ }
23
+ describe('by-scope', () => {
24
+ it('finds all domain-scoped organons', async () => {
25
+ const fs = makeFs();
26
+ const config = makeConfig('/project');
27
+ const result = await find({ projectRoot: '/project', config, fs, scope: 'domain' });
28
+ expect(result.mode).toBe('by-scope');
29
+ expect(result.matches.length).toBe(2);
30
+ expect(result.matches.every((m) => m.frontmatter?.scope === 'domain')).toBe(true);
31
+ });
32
+ it('finds product-scoped organons', async () => {
33
+ const fs = makeFs();
34
+ const config = makeConfig('/project');
35
+ const result = await find({ projectRoot: '/project', config, fs, scope: 'product' });
36
+ expect(result.matches.length).toBeGreaterThanOrEqual(1);
37
+ });
38
+ });
39
+ describe('by-type', () => {
40
+ it('finds all constraints files', async () => {
41
+ const fs = makeFs();
42
+ const config = makeConfig('/project');
43
+ const result = await find({ projectRoot: '/project', config, fs, type: 'constraints' });
44
+ expect(result.mode).toBe('by-type');
45
+ expect(result.matches.length).toBe(3); // product + genesis + agents
46
+ expect(result.matches.every((m) => m.frontmatter?.type === 'constraints')).toBe(true);
47
+ });
48
+ });
49
+ describe('by-name', () => {
50
+ it('finds organons matching a name pattern', async () => {
51
+ const fs = makeFs();
52
+ const config = makeConfig('/project');
53
+ const result = await find({ projectRoot: '/project', config, fs, name: 'genesis' });
54
+ expect(result.mode).toBe('by-name');
55
+ expect(result.matches.length).toBeGreaterThanOrEqual(1);
56
+ expect(result.matches.some((m) => m.frontmatter?.name === 'genesis')).toBe(true);
57
+ });
58
+ it('returns empty for no match', async () => {
59
+ const fs = makeFs();
60
+ const config = makeConfig('/project');
61
+ const result = await find({ projectRoot: '/project', config, fs, name: 'nonexistent' });
62
+ expect(result.matches.length).toBe(0);
63
+ });
64
+ });
65
+ describe('by-file', () => {
66
+ it('finds governing organons for a file path', async () => {
67
+ const fs = makeFs();
68
+ const config = makeConfig('/project');
69
+ const result = await find({
70
+ projectRoot: '/project',
71
+ config,
72
+ fs,
73
+ file: 'organon/domains/genesis/something.ts',
74
+ });
75
+ expect(result.mode).toBe('by-file');
76
+ // Should include product-level and genesis-level
77
+ expect(result.matches.some((m) => m.frontmatter?.scope === 'product')).toBe(true);
78
+ expect(result.matches.some((m) => m.frontmatter?.name === 'genesis')).toBe(true);
79
+ });
80
+ });
81
+ describe('no criteria', () => {
82
+ it('returns error when no search criteria provided', async () => {
83
+ const fs = makeFs();
84
+ const config = makeConfig('/project');
85
+ const result = await find({ projectRoot: '/project', config, fs });
86
+ expect(result.success).toBe(false);
87
+ expect(result.errors).toContainEqual(expect.objectContaining({ code: 'FIND_NO_CRITERIA' }));
88
+ });
89
+ });
90
+ });
91
+ //# sourceMappingURL=find.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find.test.js","sourceRoot":"","sources":["../../src/core/find.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * YAML frontmatter extraction utility.
3
+ *
4
+ * Parses the --- delimited YAML block at the top of organon files.
5
+ * Returns typed Frontmatter or null if missing/invalid.
6
+ */
7
+ import type { Frontmatter, ParsedOrganonFile } from './types.js';
8
+ export interface ParseResult {
9
+ frontmatter: Frontmatter | null;
10
+ rawFrontmatter: string;
11
+ body: string;
12
+ }
13
+ /**
14
+ * Extract and parse YAML frontmatter from file content.
15
+ */
16
+ export declare function parseFrontmatter(content: string): ParseResult;
17
+ /**
18
+ * Build a ParsedOrganonFile from raw file content and path.
19
+ */
20
+ export declare function parseOrganonFile(path: string, content: string): ParsedOrganonFile;
21
+ /**
22
+ * Estimate token count from content.
23
+ * Heuristic: ~3.5 characters per token for markdown text.
24
+ * (Accounts for spaces, punctuation, and markdown syntax)
25
+ */
26
+ export declare function estimateTokens(content: string): number;
27
+ /**
28
+ * Count entries in a numbered/bulleted section.
29
+ * Matches patterns like:
30
+ * 1. **Name.**
31
+ * ### 1. Name
32
+ * - **Name.**
33
+ * ### Invariant 1:
34
+ */
35
+ export declare function countSectionEntries(sectionContent: string): number;
36
+ /**
37
+ * Extract a specific ## section from markdown content.
38
+ * Returns the content between the matched heading and the next ## heading (or EOF).
39
+ */
40
+ export declare function extractSection(content: string, heading: string): string | null;
41
+ /**
42
+ * Count rows in a markdown table (excluding header and separator rows).
43
+ */
44
+ export declare function countTableRows(sectionContent: string): number;
45
+ //# sourceMappingURL=frontmatter-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter-parser.d.ts","sourceRoot":"","sources":["../../src/core/frontmatter-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAIjE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAkB7D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAelE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAoB9E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CA6B7D"}