@agntk/agent-harness 0.1.1

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 (212) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +445 -0
  4. package/defaults/agents/summarizer.md +49 -0
  5. package/defaults/instincts/lead-with-answer.md +24 -0
  6. package/defaults/instincts/qualify-before-recommending.md +40 -0
  7. package/defaults/instincts/read-before-edit.md +23 -0
  8. package/defaults/instincts/search-before-create.md +23 -0
  9. package/defaults/playbooks/ship-feature.md +31 -0
  10. package/defaults/rules/ask-before-assuming.md +35 -0
  11. package/defaults/rules/operations.md +35 -0
  12. package/defaults/rules/respect-the-user.md +39 -0
  13. package/defaults/skills/business-analyst.md +181 -0
  14. package/defaults/skills/content-marketer.md +184 -0
  15. package/defaults/skills/research.md +34 -0
  16. package/defaults/tools/example-web-search.md +60 -0
  17. package/defaults/workflows/daily-reflection.md +54 -0
  18. package/dist/agent-framework-K4GUIICH.js +344 -0
  19. package/dist/agent-framework-K4GUIICH.js.map +1 -0
  20. package/dist/analytics-RPT73WNM.js +12 -0
  21. package/dist/analytics-RPT73WNM.js.map +1 -0
  22. package/dist/auto-processor-OLE45UI3.js +13 -0
  23. package/dist/auto-processor-OLE45UI3.js.map +1 -0
  24. package/dist/chunk-274RV3YO.js +162 -0
  25. package/dist/chunk-274RV3YO.js.map +1 -0
  26. package/dist/chunk-4CWAGBNS.js +168 -0
  27. package/dist/chunk-4CWAGBNS.js.map +1 -0
  28. package/dist/chunk-4FDUOGSZ.js +69 -0
  29. package/dist/chunk-4FDUOGSZ.js.map +1 -0
  30. package/dist/chunk-5H34JPMB.js +199 -0
  31. package/dist/chunk-5H34JPMB.js.map +1 -0
  32. package/dist/chunk-6EMOEYGU.js +102 -0
  33. package/dist/chunk-6EMOEYGU.js.map +1 -0
  34. package/dist/chunk-A7BJPQQ6.js +236 -0
  35. package/dist/chunk-A7BJPQQ6.js.map +1 -0
  36. package/dist/chunk-AGAAFJEO.js +76 -0
  37. package/dist/chunk-AGAAFJEO.js.map +1 -0
  38. package/dist/chunk-BSKDOFRT.js +65 -0
  39. package/dist/chunk-BSKDOFRT.js.map +1 -0
  40. package/dist/chunk-CHJ5GNZC.js +100 -0
  41. package/dist/chunk-CHJ5GNZC.js.map +1 -0
  42. package/dist/chunk-CSL3ERUI.js +307 -0
  43. package/dist/chunk-CSL3ERUI.js.map +1 -0
  44. package/dist/chunk-DA7IKHC4.js +229 -0
  45. package/dist/chunk-DA7IKHC4.js.map +1 -0
  46. package/dist/chunk-DGUM43GV.js +11 -0
  47. package/dist/chunk-DGUM43GV.js.map +1 -0
  48. package/dist/chunk-DTTXPHFW.js +211 -0
  49. package/dist/chunk-DTTXPHFW.js.map +1 -0
  50. package/dist/chunk-FD55B3IO.js +204 -0
  51. package/dist/chunk-FD55B3IO.js.map +1 -0
  52. package/dist/chunk-FLZU44SV.js +230 -0
  53. package/dist/chunk-FLZU44SV.js.map +1 -0
  54. package/dist/chunk-GJNNR2RA.js +200 -0
  55. package/dist/chunk-GJNNR2RA.js.map +1 -0
  56. package/dist/chunk-GNUSHD2Y.js +111 -0
  57. package/dist/chunk-GNUSHD2Y.js.map +1 -0
  58. package/dist/chunk-GUJTBGVS.js +2212 -0
  59. package/dist/chunk-GUJTBGVS.js.map +1 -0
  60. package/dist/chunk-IZ6UZ3ZL.js +207 -0
  61. package/dist/chunk-IZ6UZ3ZL.js.map +1 -0
  62. package/dist/chunk-JKMGYWXB.js +197 -0
  63. package/dist/chunk-JKMGYWXB.js.map +1 -0
  64. package/dist/chunk-KFX54TQM.js +165 -0
  65. package/dist/chunk-KFX54TQM.js.map +1 -0
  66. package/dist/chunk-M7NXUK55.js +199 -0
  67. package/dist/chunk-M7NXUK55.js.map +1 -0
  68. package/dist/chunk-MPZ3BPUI.js +374 -0
  69. package/dist/chunk-MPZ3BPUI.js.map +1 -0
  70. package/dist/chunk-OC6YSTDX.js +119 -0
  71. package/dist/chunk-OC6YSTDX.js.map +1 -0
  72. package/dist/chunk-RC6MEZB6.js +469 -0
  73. package/dist/chunk-RC6MEZB6.js.map +1 -0
  74. package/dist/chunk-RY3ZFII7.js +3440 -0
  75. package/dist/chunk-RY3ZFII7.js.map +1 -0
  76. package/dist/chunk-TAT6JU3X.js +167 -0
  77. package/dist/chunk-TAT6JU3X.js.map +1 -0
  78. package/dist/chunk-UDZIS2AQ.js +79 -0
  79. package/dist/chunk-UDZIS2AQ.js.map +1 -0
  80. package/dist/chunk-UPLBF4RZ.js +115 -0
  81. package/dist/chunk-UPLBF4RZ.js.map +1 -0
  82. package/dist/chunk-UWQTZMNI.js +154 -0
  83. package/dist/chunk-UWQTZMNI.js.map +1 -0
  84. package/dist/chunk-W4T7PGI2.js +346 -0
  85. package/dist/chunk-W4T7PGI2.js.map +1 -0
  86. package/dist/chunk-XTBKL5BI.js +111 -0
  87. package/dist/chunk-XTBKL5BI.js.map +1 -0
  88. package/dist/chunk-YIJY5DBV.js +399 -0
  89. package/dist/chunk-YIJY5DBV.js.map +1 -0
  90. package/dist/chunk-YUFNYN2H.js +242 -0
  91. package/dist/chunk-YUFNYN2H.js.map +1 -0
  92. package/dist/chunk-Z2PUCXTZ.js +94 -0
  93. package/dist/chunk-Z2PUCXTZ.js.map +1 -0
  94. package/dist/chunk-ZZJOFKAT.js +13 -0
  95. package/dist/chunk-ZZJOFKAT.js.map +1 -0
  96. package/dist/cli/index.js +3661 -0
  97. package/dist/cli/index.js.map +1 -0
  98. package/dist/config-WVMRUOCA.js +13 -0
  99. package/dist/config-WVMRUOCA.js.map +1 -0
  100. package/dist/context-loader-3ORBPMHJ.js +13 -0
  101. package/dist/context-loader-3ORBPMHJ.js.map +1 -0
  102. package/dist/conversation-QDEIDQPH.js +22 -0
  103. package/dist/conversation-QDEIDQPH.js.map +1 -0
  104. package/dist/cost-tracker-RS3W7SVY.js +24 -0
  105. package/dist/cost-tracker-RS3W7SVY.js.map +1 -0
  106. package/dist/delegate-VJCJLYEK.js +29 -0
  107. package/dist/delegate-VJCJLYEK.js.map +1 -0
  108. package/dist/emotional-state-VQVRA6ED.js +206 -0
  109. package/dist/emotional-state-VQVRA6ED.js.map +1 -0
  110. package/dist/env-discovery-2BLVMAIM.js +251 -0
  111. package/dist/env-discovery-2BLVMAIM.js.map +1 -0
  112. package/dist/export-6GCYHEHQ.js +165 -0
  113. package/dist/export-6GCYHEHQ.js.map +1 -0
  114. package/dist/graph-YUIPOSOO.js +14 -0
  115. package/dist/graph-YUIPOSOO.js.map +1 -0
  116. package/dist/harness-LCHA3DWP.js +10 -0
  117. package/dist/harness-LCHA3DWP.js.map +1 -0
  118. package/dist/harness-WE4SLCML.js +26 -0
  119. package/dist/harness-WE4SLCML.js.map +1 -0
  120. package/dist/health-NZ6WNIMV.js +23 -0
  121. package/dist/health-NZ6WNIMV.js.map +1 -0
  122. package/dist/index.d.ts +3612 -0
  123. package/dist/index.js +13501 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/indexer-LONANRRM.js +16 -0
  126. package/dist/indexer-LONANRRM.js.map +1 -0
  127. package/dist/instinct-learner-SRM72DHF.js +20 -0
  128. package/dist/instinct-learner-SRM72DHF.js.map +1 -0
  129. package/dist/intake-4M3HNU43.js +21 -0
  130. package/dist/intake-4M3HNU43.js.map +1 -0
  131. package/dist/intelligence-HJOCA4SJ.js +1081 -0
  132. package/dist/intelligence-HJOCA4SJ.js.map +1 -0
  133. package/dist/journal-WANJL3MI.js +24 -0
  134. package/dist/journal-WANJL3MI.js.map +1 -0
  135. package/dist/loader-C3TKIKZR.js +23 -0
  136. package/dist/loader-C3TKIKZR.js.map +1 -0
  137. package/dist/mcp-WTQJJZAO.js +15 -0
  138. package/dist/mcp-WTQJJZAO.js.map +1 -0
  139. package/dist/mcp-discovery-WPAQFL6S.js +377 -0
  140. package/dist/mcp-discovery-WPAQFL6S.js.map +1 -0
  141. package/dist/mcp-installer-6O2XXD3V.js +394 -0
  142. package/dist/mcp-installer-6O2XXD3V.js.map +1 -0
  143. package/dist/metrics-KXGNFAAB.js +20 -0
  144. package/dist/metrics-KXGNFAAB.js.map +1 -0
  145. package/dist/primitive-registry-I6VTIR4W.js +512 -0
  146. package/dist/primitive-registry-I6VTIR4W.js.map +1 -0
  147. package/dist/project-discovery-C4UMD7JI.js +246 -0
  148. package/dist/project-discovery-C4UMD7JI.js.map +1 -0
  149. package/dist/provider-LQHQX7Z7.js +26 -0
  150. package/dist/provider-LQHQX7Z7.js.map +1 -0
  151. package/dist/provider-SXPQZ74H.js +28 -0
  152. package/dist/provider-SXPQZ74H.js.map +1 -0
  153. package/dist/rate-limiter-RLRVM325.js +22 -0
  154. package/dist/rate-limiter-RLRVM325.js.map +1 -0
  155. package/dist/rule-engine-YGQ3RYZM.js +182 -0
  156. package/dist/rule-engine-YGQ3RYZM.js.map +1 -0
  157. package/dist/scaffold-A3VRRCBV.js +347 -0
  158. package/dist/scaffold-A3VRRCBV.js.map +1 -0
  159. package/dist/scheduler-XHHIVHRI.js +397 -0
  160. package/dist/scheduler-XHHIVHRI.js.map +1 -0
  161. package/dist/search-V3W5JMJG.js +75 -0
  162. package/dist/search-V3W5JMJG.js.map +1 -0
  163. package/dist/semantic-search-2DTOO5UX.js +241 -0
  164. package/dist/semantic-search-2DTOO5UX.js.map +1 -0
  165. package/dist/serve-DTQ3HENY.js +291 -0
  166. package/dist/serve-DTQ3HENY.js.map +1 -0
  167. package/dist/sessions-CZGVXKQE.js +21 -0
  168. package/dist/sessions-CZGVXKQE.js.map +1 -0
  169. package/dist/sources-RW5DT56F.js +32 -0
  170. package/dist/sources-RW5DT56F.js.map +1 -0
  171. package/dist/starter-packs-76YUVHEU.js +893 -0
  172. package/dist/starter-packs-76YUVHEU.js.map +1 -0
  173. package/dist/state-GMXILIHW.js +13 -0
  174. package/dist/state-GMXILIHW.js.map +1 -0
  175. package/dist/state-merge-NKO5FRBA.js +174 -0
  176. package/dist/state-merge-NKO5FRBA.js.map +1 -0
  177. package/dist/telemetry-UC6PBXC7.js +22 -0
  178. package/dist/telemetry-UC6PBXC7.js.map +1 -0
  179. package/dist/tool-executor-MJ7IG7PQ.js +28 -0
  180. package/dist/tool-executor-MJ7IG7PQ.js.map +1 -0
  181. package/dist/tools-DZ4KETET.js +20 -0
  182. package/dist/tools-DZ4KETET.js.map +1 -0
  183. package/dist/types-EW7AIB3R.js +18 -0
  184. package/dist/types-EW7AIB3R.js.map +1 -0
  185. package/dist/types-WGDLSPO6.js +16 -0
  186. package/dist/types-WGDLSPO6.js.map +1 -0
  187. package/dist/universal-installer-QGS4SJGX.js +578 -0
  188. package/dist/universal-installer-QGS4SJGX.js.map +1 -0
  189. package/dist/validator-7WXMDIHH.js +22 -0
  190. package/dist/validator-7WXMDIHH.js.map +1 -0
  191. package/dist/verification-gate-FYXUX6LH.js +246 -0
  192. package/dist/verification-gate-FYXUX6LH.js.map +1 -0
  193. package/dist/versioning-Z3XNE2Q2.js +271 -0
  194. package/dist/versioning-Z3XNE2Q2.js.map +1 -0
  195. package/dist/watcher-ISJC7YKL.js +109 -0
  196. package/dist/watcher-ISJC7YKL.js.map +1 -0
  197. package/dist/web-server-DD7ZOP46.js +28 -0
  198. package/dist/web-server-DD7ZOP46.js.map +1 -0
  199. package/package.json +76 -0
  200. package/sources.yaml +121 -0
  201. package/templates/assistant/CORE.md +24 -0
  202. package/templates/assistant/SYSTEM.md +24 -0
  203. package/templates/assistant/config.yaml +51 -0
  204. package/templates/base/CORE.md +17 -0
  205. package/templates/base/SYSTEM.md +24 -0
  206. package/templates/base/config.yaml +51 -0
  207. package/templates/claude-opus/config.yaml +51 -0
  208. package/templates/code-reviewer/CORE.md +25 -0
  209. package/templates/code-reviewer/SYSTEM.md +30 -0
  210. package/templates/code-reviewer/config.yaml +51 -0
  211. package/templates/gpt4/config.yaml +51 -0
  212. package/templates/local/config.yaml +51 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/universal-installer.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from 'fs';\nimport { join, basename, extname } from 'path';\nimport { tmpdir } from 'os';\nimport matter from 'gray-matter';\nimport { parse as parseYaml } from 'yaml';\nimport { fixCapability, installCapability, downloadCapability } from './intake.js';\nimport { autoProcessFile } from './auto-processor.js';\nimport { discoverSources, loadAllSources } from './sources.js';\nimport type { Source, SourceDiscoveryResult } from './sources.js';\nimport { log } from '../core/logger.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Detected source format of a file to be installed. */\nexport type SourceFormat =\n | 'harness' // Already harness convention (frontmatter + L0/L1)\n | 'claude-skill' // Claude Code SKILL.md (plain markdown, no frontmatter)\n | 'faf-yaml' // .faf YAML format\n | 'raw-markdown' // Plain markdown with no harness structure\n | 'bash-hook' // Bash/shell script (hook or workflow)\n | 'mcp-config' // MCP server configuration (JSON/YAML)\n | 'unknown';\n\n/** Result of format detection. */\nexport interface FormatDetection {\n /** Detected format */\n format: SourceFormat;\n /** Inferred primitive type (skill, agent, rule, etc.) */\n primitiveType: string | null;\n /** Confidence score (0-1) */\n confidence: number;\n /** Reasons for the detection */\n reasons: string[];\n}\n\n/** Result of a universal install operation. */\nexport interface UniversalInstallResult {\n /** Whether installation succeeded */\n installed: boolean;\n /** Source reference that was resolved */\n source: string;\n /** Detected format */\n format: FormatDetection;\n /** Path where the file was installed */\n destination: string;\n /** Fixes applied during normalization */\n fixes: string[];\n /** Errors encountered */\n errors: string[];\n /** Suggested dependencies to install */\n suggestedDependencies: string[];\n}\n\n/** Options for the universal installer. */\nexport interface UniversalInstallOptions {\n /** Override the detected primitive type (skill, rule, agent, etc.) */\n type?: string;\n /** Override the generated ID */\n id?: string;\n /** Force install even if validation has warnings */\n force?: boolean;\n /** Skip auto-fix (frontmatter, L0/L1 generation) */\n skipFix?: boolean;\n /** Additional tags to add */\n tags?: string[];\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst VALID_TYPES = ['rule', 'instinct', 'skill', 'playbook', 'workflow', 'tool', 'agent'];\n\nconst TYPE_DIRS: Record<string, string> = {\n rule: 'rules',\n instinct: 'instincts',\n skill: 'skills',\n playbook: 'playbooks',\n workflow: 'workflows',\n tool: 'tools',\n agent: 'agents',\n};\n\n// ─── Format Detection ────────────────────────────────────────────────────────\n\n/**\n * Detect the format of a file based on its content and extension.\n *\n * Detection heuristics:\n * - Has `---` frontmatter with `id:` + `status:` → harness convention\n * - Has `---` frontmatter but missing harness fields → raw-markdown\n * - `.faf` or `.yaml`/`.yml` with `type:` + `content:` keys → faf-yaml\n * - `.sh`/`.bash` or starts with `#!/` → bash-hook\n * - JSON/YAML with `mcpServers` or `servers` → mcp-config\n * - Plain markdown with no frontmatter → claude-skill or raw-markdown\n */\nexport function detectFormat(content: string, filename: string): FormatDetection {\n const ext = extname(filename).toLowerCase();\n const reasons: string[] = [];\n let format: SourceFormat = 'unknown';\n let primitiveType: string | null = null;\n let confidence = 0;\n\n // Check for bash/shell scripts\n if (ext === '.sh' || ext === '.bash' || content.trimStart().startsWith('#!/')) {\n format = 'bash-hook';\n primitiveType = 'workflow';\n confidence = 0.9;\n reasons.push('Shell script detected (shebang or .sh extension)');\n\n // Hooks are typically short scripts with specific patterns\n if (content.includes('hook') || content.includes('pre-commit') || content.includes('post-')) {\n primitiveType = 'workflow';\n reasons.push('Hook pattern detected in content');\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n // Check for JSON/YAML MCP configs\n if (ext === '.json') {\n try {\n const parsed = JSON.parse(content) as Record<string, unknown>;\n if (parsed.mcpServers || parsed.servers || parsed.command || parsed.args) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.9;\n reasons.push('MCP configuration JSON detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid JSON, continue\n }\n }\n\n // Check for .faf YAML format\n if (ext === '.faf' || ext === '.yaml' || ext === '.yml') {\n try {\n const parsed = parseYaml(content) as Record<string, unknown>;\n if (parsed.type && parsed.content) {\n format = 'faf-yaml';\n primitiveType = inferTypeFromFafType(String(parsed.type));\n confidence = 0.9;\n reasons.push(`.faf YAML format with type: ${parsed.type}`);\n return { format, primitiveType, confidence, reasons };\n }\n // YAML with mcpServers\n if (parsed.mcpServers || parsed.servers) {\n format = 'mcp-config';\n primitiveType = 'tool';\n confidence = 0.85;\n reasons.push('MCP configuration YAML detected');\n return { format, primitiveType, confidence, reasons };\n }\n } catch {\n // Not valid YAML, continue\n }\n }\n\n // Check for markdown content\n if (ext === '.md' || ext === '' || !ext) {\n // Try to parse frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n\n if (data.id && data.status) {\n // Has harness-style frontmatter\n format = 'harness';\n confidence = 0.95;\n reasons.push('Harness frontmatter detected (id + status fields)');\n\n // Detect type from tags\n const tags = Array.isArray(data.tags)\n ? (data.tags as string[]).map((t) => String(t).toLowerCase())\n : [];\n for (const type of VALID_TYPES) {\n if (tags.includes(type)) {\n primitiveType = type;\n break;\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n if (Object.keys(data).length > 0) {\n // Has some frontmatter but not harness convention\n format = 'raw-markdown';\n confidence = 0.7;\n reasons.push('Markdown with non-harness frontmatter');\n }\n } catch {\n // No frontmatter or parse error\n }\n\n // Check for Claude Code SKILL.md patterns\n if (format === 'unknown' || format === 'raw-markdown') {\n const isClaudeSkill = detectClaudeSkillPattern(content, filename);\n if (isClaudeSkill) {\n format = 'claude-skill';\n primitiveType = 'skill';\n confidence = 0.8;\n reasons.push('Claude Code SKILL.md pattern detected');\n return { format, primitiveType, confidence, reasons };\n }\n }\n\n // Plain markdown — infer type from content\n if (format === 'unknown') {\n format = 'raw-markdown';\n confidence = 0.5;\n reasons.push('Plain markdown without frontmatter');\n }\n\n // Try to infer type from content/filename\n if (!primitiveType) {\n primitiveType = inferTypeFromContent(content, filename);\n if (primitiveType) {\n reasons.push(`Type inferred from content/filename: ${primitiveType}`);\n }\n }\n\n return { format, primitiveType, confidence, reasons };\n }\n\n return { format, primitiveType, confidence, reasons };\n}\n\n// ─── Format Normalization ────────────────────────────────────────────────────\n\n/**\n * Normalize content from any detected format to harness convention.\n * Returns the normalized markdown content ready for writing.\n */\nexport function normalizeToHarness(\n content: string,\n filename: string,\n detection: FormatDetection,\n options?: UniversalInstallOptions,\n): { content: string; filename: string; fixes: string[] } {\n const fixes: string[] = [];\n const type = options?.type ?? detection.primitiveType;\n\n switch (detection.format) {\n case 'harness':\n // Already in harness format — just pass through\n return { content, filename, fixes: ['Already in harness format'] };\n\n case 'claude-skill':\n return normalizeClaudeSkill(content, filename, type, options, fixes);\n\n case 'faf-yaml':\n return normalizeFafYaml(content, filename, type, options, fixes);\n\n case 'raw-markdown':\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n\n case 'bash-hook':\n return normalizeBashHook(content, filename, type, options, fixes);\n\n case 'mcp-config':\n return normalizeMcpConfig(content, filename, options, fixes);\n\n default:\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n}\n\n/**\n * Convert Claude Code SKILL.md to harness convention.\n * Claude skills are plain markdown — add frontmatter + L0/L1.\n */\nfunction normalizeClaudeSkill(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Extract first heading as title\n const headingMatch = content.match(/^#\\s+(.+)$/m);\n const title = headingMatch ? headingMatch[1].trim() : id;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags,\n };\n\n // Generate L0 from title/first heading\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n\n // Generate L1 from first paragraph\n const paragraphs = content.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('#') && !trimmed.startsWith('<!--');\n });\n const l1 = paragraphs.length > 0\n ? paragraphs[0].replace(/\\n/g, ' ').trim().slice(0, 300)\n : '';\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) {\n body += `<!-- L1: ${l1} -->\\n`;\n }\n body += '\\n' + content;\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Added harness frontmatter (id, status, tags)');\n fixes.push(`Generated L0 from heading: \"${l0}\"`);\n if (l1) fixes.push('Generated L1 from first paragraph');\n\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert .faf YAML format to harness markdown.\n */\nfunction normalizeFafYaml(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n let parsed: Record<string, unknown>;\n try {\n parsed = parseYaml(content) as Record<string, unknown>;\n } catch {\n fixes.push('Failed to parse YAML — treating as raw markdown');\n return normalizeRawMarkdown(content, filename, type, options, fixes);\n }\n\n const id = options?.id ?? String(parsed.id ?? deriveId(filename));\n const fafType = String(parsed.type ?? 'skill');\n const primitiveType = type ?? inferTypeFromFafType(fafType) ?? 'skill';\n const title = String(parsed.title ?? parsed.name ?? id);\n const description = String(parsed.description ?? '');\n const fafContent = String(parsed.content ?? '');\n const fafTags = Array.isArray(parsed.tags)\n ? (parsed.tags as string[]).map(String)\n : [];\n\n const tags = [primitiveType, ...fafTags, ...(options?.tags ?? [])];\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = title.length > 120 ? title.slice(0, 117) + '...' : title;\n const l1 = description.length > 300 ? description.slice(0, 297) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n`;\n if (l1) body += `<!-- L1: ${l1} -->\\n`;\n body += `\\n# ${title}\\n\\n`;\n if (description) body += `${description}\\n\\n`;\n if (fafContent) body += fafContent + '\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted .faf YAML to harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Normalize raw markdown (no frontmatter or non-harness frontmatter).\n */\nfunction normalizeRawMarkdown(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'skill';\n const tags = [primitiveType, ...(options?.tags ?? [])];\n\n // Try to preserve any existing frontmatter\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n parsed = { data: {}, content, orig: '', excerpt: '', language: '', matter: '', stringify: () => '' } as ReturnType<typeof matter>;\n }\n\n const data = parsed.data as Record<string, unknown>;\n\n // Set required harness fields — options override existing values\n if (options?.id || !data.id) {\n data.id = id;\n fixes.push(`Set id: \"${id}\"`);\n }\n if (!data.status) {\n data.status = 'active';\n fixes.push('Added status: \"active\"');\n }\n if (!data.created) {\n data.created = new Date().toISOString().split('T')[0];\n fixes.push('Added created date');\n }\n if (!data.author || !['human', 'agent', 'infrastructure'].includes(String(data.author))) {\n data.author = 'human';\n fixes.push('Added author: \"human\"');\n }\n if (!Array.isArray(data.tags) || data.tags.length === 0) {\n data.tags = [...new Set(tags)];\n fixes.push(`Added tags: [${(data.tags as string[]).join(', ')}]`);\n }\n\n let body = parsed.content;\n\n // Add L0 if missing\n const l0Regex = /<!--\\s*L0:\\s*(.*?)\\s*-->/;\n if (!l0Regex.test(body)) {\n const headingMatch = body.match(/^#\\s+(.+)$/m);\n const firstLine = body.split('\\n').find((line) => line.trim().length > 0);\n const summary = headingMatch ? headingMatch[1].trim() : (firstLine?.trim() ?? id);\n const l0 = summary.length > 120 ? summary.slice(0, 117) + '...' : summary;\n body = `<!-- L0: ${l0} -->\\n${body}`;\n fixes.push(`Generated L0: \"${l0}\"`);\n }\n\n // Add L1 if missing\n const l1Regex = /<!--\\s*L1:\\s*([\\s\\S]*?)\\s*-->/;\n if (!l1Regex.test(body)) {\n const paragraphs = body.split(/\\n{2,}/).filter((p) => {\n const trimmed = p.trim();\n return trimmed.length > 0 && !trimmed.startsWith('<!--') && !trimmed.startsWith('#');\n });\n if (paragraphs.length > 0) {\n const para = paragraphs[0].replace(/\\n/g, ' ').trim();\n const l1 = para.length > 300 ? para.slice(0, 297) + '...' : para;\n const l0Pos = body.indexOf('-->');\n if (l0Pos !== -1) {\n const insertPos = l0Pos + 3;\n body = body.slice(0, insertPos) + `\\n<!-- L1: ${l1} -->` + body.slice(insertPos);\n } else {\n body = `<!-- L1: ${l1} -->\\n${body}`;\n }\n fixes.push('Generated L1 from first paragraph');\n }\n }\n\n const result = matter.stringify(body, data);\n const outFilename = ensureMdExtension(filename);\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Wrap a bash hook script in harness markdown.\n */\nfunction normalizeBashHook(\n content: string,\n filename: string,\n type: string | null,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const primitiveType = type ?? 'workflow';\n const tags = [primitiveType, 'hook', ...(options?.tags ?? [])];\n\n // Extract description from comments at top of script\n const commentLines = content.split('\\n')\n .filter((line) => line.startsWith('#') && !line.startsWith('#!'))\n .map((line) => line.replace(/^#\\s?/, '').trim())\n .filter((line) => line.length > 0);\n\n const description = commentLines.length > 0\n ? commentLines.slice(0, 3).join(' ')\n : `Bash hook: ${id}`;\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# ${id}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '```bash\\n';\n body += content;\n if (!content.endsWith('\\n')) body += '\\n';\n body += '```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Wrapped bash script in harness markdown');\n fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n/**\n * Convert an MCP config to harness tool documentation.\n */\nfunction normalizeMcpConfig(\n content: string,\n filename: string,\n options: UniversalInstallOptions | undefined,\n fixes: string[],\n): { content: string; filename: string; fixes: string[] } {\n const id = options?.id ?? deriveId(filename);\n const tags = ['tool', 'mcp', ...(options?.tags ?? [])];\n\n // Try to parse config\n let config: Record<string, unknown> = {};\n const ext = extname(filename).toLowerCase();\n try {\n if (ext === '.json') {\n config = JSON.parse(content) as Record<string, unknown>;\n } else {\n config = parseYaml(content) as Record<string, unknown>;\n }\n } catch {\n fixes.push('Failed to parse MCP config');\n }\n\n const serverName = String(config.name ?? config.command ?? id);\n const description = String(config.description ?? `MCP server: ${serverName}`);\n\n const frontmatter: Record<string, unknown> = {\n id,\n created: new Date().toISOString().split('T')[0],\n author: 'human',\n status: 'active',\n tags: [...new Set(tags)],\n };\n\n const l0 = description.length > 120 ? description.slice(0, 117) + '...' : description;\n\n let body = `<!-- L0: ${l0} -->\\n\\n`;\n body += `# MCP Server: ${serverName}\\n\\n`;\n body += `${description}\\n\\n`;\n body += '## Configuration\\n\\n';\n body += '```json\\n';\n body += JSON.stringify(config, null, 2);\n body += '\\n```\\n';\n\n const result = matter.stringify(body, frontmatter);\n fixes.push('Converted MCP config to harness tool documentation');\n fixes.push(`Added frontmatter (id: ${id})`);\n\n const outFilename = deriveId(filename) + '.md';\n return { content: result, filename: outFilename, fixes };\n}\n\n// ─── Source Resolution ───────────────────────────────────────────────────────\n\n/**\n * Resolve a source reference to a local file path.\n *\n * Supports:\n * - Local file paths (absolute or relative)\n * - HTTPS URLs (GitHub raw, any markdown URL)\n * - Source query (searches registered sources)\n *\n * @returns Path to a local file (downloaded if remote)\n */\nexport async function resolveSource(\n source: string,\n harnessDir: string,\n): Promise<{ localPath: string; originalSource: string; error?: string }> {\n // Case 1: Local file path\n if (existsSync(source)) {\n return { localPath: source, originalSource: source };\n }\n\n // Case 2: URL\n if (source.startsWith('https://') || source.startsWith('http://')) {\n // Convert GitHub URL to raw if needed\n const rawUrl = convertToRawUrl(source);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n\n // Case 3: Source registry lookup — search known sources\n const results = discoverSources(harnessDir, source, { maxResults: 1 });\n if (results.length > 0) {\n const hit = results[0];\n // If the source is a GitHub source, construct a raw URL\n if (hit.source.type === 'github') {\n const rawUrl = convertToRawUrl(hit.url);\n const result = await downloadCapability(rawUrl);\n if (result.downloaded) {\n return { localPath: result.localPath, originalSource: source };\n }\n return { localPath: '', originalSource: source, error: result.error };\n }\n return { localPath: '', originalSource: source, error: `Source \"${hit.source.name}\" is type \"${hit.source.type}\" — direct install not yet supported for this type` };\n }\n\n return { localPath: '', originalSource: source, error: `Could not resolve \"${source}\" — not a local file, URL, or known source` };\n}\n\n// ─── Main Install Function ───────────────────────────────────────────────────\n\n/**\n * Universal install: resolve → detect → normalize → fix → install.\n *\n * Accepts a local path, URL, or search query. Detects the format,\n * normalizes to harness convention, applies auto-fixes, and installs\n * to the correct directory.\n *\n * @param harnessDir - Harness directory\n * @param source - File path, URL, or name to install\n * @param options - Installation options\n * @returns Install result with status, fixes, errors, dependency hints\n */\nexport async function universalInstall(\n harnessDir: string,\n source: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n const result: UniversalInstallResult = {\n installed: false,\n source,\n format: { format: 'unknown', primitiveType: null, confidence: 0, reasons: [] },\n destination: '',\n fixes: [],\n errors: [],\n suggestedDependencies: [],\n };\n\n // Step 1: Resolve source to local file\n const resolved = await resolveSource(source, harnessDir);\n if (resolved.error || !resolved.localPath) {\n result.errors.push(resolved.error ?? 'Failed to resolve source');\n return result;\n }\n\n // Step 2: Read content\n let content: string;\n try {\n content = readFileSync(resolved.localPath, 'utf-8');\n } catch (err) {\n result.errors.push(`Failed to read file: ${err instanceof Error ? err.message : String(err)}`);\n return result;\n }\n\n if (content.trim().length === 0) {\n result.errors.push('File is empty');\n return result;\n }\n\n // Step 3: Detect format\n const filename = basename(resolved.localPath);\n const detection = detectFormat(content, filename);\n result.format = detection;\n\n // Step 4: Normalize to harness convention\n const normalized = normalizeToHarness(content, filename, detection, options);\n result.fixes.push(...normalized.fixes);\n\n // Step 5: Write normalized content to temp file for installation\n const tempDir = join(tmpdir(), 'harness-install');\n mkdirSync(tempDir, { recursive: true });\n const tempPath = join(tempDir, normalized.filename);\n writeFileSync(tempPath, normalized.content, 'utf-8');\n\n // Step 6: Apply auto-fix if not skipped\n if (!options?.skipFix) {\n const fixResult = fixCapability(tempPath);\n result.fixes.push(...fixResult.fixes_applied);\n\n if (!fixResult.valid && !options?.force) {\n result.errors.push(...fixResult.errors);\n return result;\n }\n }\n\n // Step 7: Install via existing pipeline\n const installResult = installCapability(harnessDir, tempPath);\n result.installed = installResult.installed;\n result.destination = installResult.destination;\n\n if (!installResult.installed) {\n result.errors.push(...installResult.evalResult.errors);\n // If force mode, try direct copy\n if (options?.force && detection.primitiveType) {\n const targetDir = join(harnessDir, TYPE_DIRS[detection.primitiveType] ?? 'skills');\n if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });\n const dest = join(targetDir, normalized.filename);\n copyFileSync(tempPath, dest);\n result.installed = true;\n result.destination = dest;\n result.fixes.push('Force-installed despite validation errors');\n }\n }\n\n // Step 8: Scan for dependency hints\n result.suggestedDependencies = extractDependencyHints(normalized.content);\n\n return result;\n}\n\n/**\n * Install from a URL (convenience wrapper).\n */\nexport async function installFromUrl(\n harnessDir: string,\n url: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, url, options);\n}\n\n/**\n * Install from a local file path (convenience wrapper).\n */\nexport async function installFromFile(\n harnessDir: string,\n filePath: string,\n options?: UniversalInstallOptions,\n): Promise<UniversalInstallResult> {\n return universalInstall(harnessDir, filePath, options);\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction deriveId(filename: string): string {\n const base = basename(filename).replace(/\\.(md|faf|yaml|yml|json|sh|bash)$/i, '');\n return base.replace(/[^a-z0-9-]/gi, '-').toLowerCase();\n}\n\nfunction ensureMdExtension(filename: string): string {\n if (filename.endsWith('.md')) return filename;\n return deriveId(filename) + '.md';\n}\n\n/**\n * Convert a GitHub URL to its raw content URL.\n *\n * Handles:\n * - github.com/owner/repo/blob/branch/path → raw.githubusercontent.com/owner/repo/branch/path\n * - Already raw.githubusercontent.com URLs → pass through\n * - Other URLs → pass through\n */\nexport function convertToRawUrl(url: string): string {\n // Already raw\n if (url.includes('raw.githubusercontent.com')) return url;\n\n // GitHub blob URL → raw\n const blobMatch = url.match(\n /^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/blob\\/(.+)$/,\n );\n if (blobMatch) {\n const [, owner, repo, rest] = blobMatch;\n return `https://raw.githubusercontent.com/${owner}/${repo}/${rest}`;\n }\n\n return url;\n}\n\n/**\n * Detect if content matches Claude Code SKILL.md patterns.\n * Claude skills are plain markdown with specific structural patterns.\n */\nfunction detectClaudeSkillPattern(content: string, filename: string): boolean {\n const nameLower = filename.toLowerCase();\n\n // Filename patterns\n if (nameLower === 'skill.md' || nameLower.endsWith('-skill.md') || nameLower.endsWith('_skill.md')) {\n return true;\n }\n\n // Content patterns common in Claude Code skills\n const patterns = [\n /^#\\s+.+skill/im,\n /instructions?\\s+for\\s+/i,\n /when\\s+(the\\s+)?user\\s+(asks?|wants?|needs?|requests?)/i,\n /you\\s+(should|must|will)\\s+/i,\n ];\n\n let matches = 0;\n for (const pattern of patterns) {\n if (pattern.test(content)) matches++;\n }\n\n // Need at least 2 pattern matches to classify as Claude skill\n // (plain markdown + instructional tone)\n return matches >= 2 && !content.startsWith('---');\n}\n\nfunction inferTypeFromFafType(fafType: string): string | null {\n const typeMap: Record<string, string> = {\n skill: 'skill',\n agent: 'agent',\n rule: 'rule',\n playbook: 'playbook',\n workflow: 'workflow',\n tool: 'tool',\n instinct: 'instinct',\n hook: 'workflow',\n template: 'skill',\n plugin: 'skill',\n };\n\n return typeMap[fafType.toLowerCase()] ?? null;\n}\n\nfunction inferTypeFromContent(content: string, filename: string): string | null {\n const lower = content.toLowerCase();\n const nameLower = filename.toLowerCase();\n\n // From filename\n if (nameLower.includes('rule')) return 'rule';\n if (nameLower.includes('agent')) return 'agent';\n if (nameLower.includes('playbook')) return 'playbook';\n if (nameLower.includes('workflow')) return 'workflow';\n if (nameLower.includes('instinct')) return 'instinct';\n if (nameLower.includes('tool')) return 'tool';\n if (nameLower.includes('skill')) return 'skill';\n\n // From content patterns\n if (lower.includes('# rule:') || lower.includes('## rules')) return 'rule';\n if (lower.includes('# agent:') || lower.includes('## agent')) return 'agent';\n if (lower.includes('# playbook:') || lower.includes('## playbook')) return 'playbook';\n if (lower.includes('# skill:') || lower.includes('## skill')) return 'skill';\n if (lower.includes('# workflow:') || lower.includes('## workflow')) return 'workflow';\n if (lower.includes('# tool:') || lower.includes('## tool')) return 'tool';\n\n // Default for markdown without clear type\n return null;\n}\n\n/**\n * Extract dependency hints from content.\n * Looks for references to tools, skills, or other primitives.\n */\nfunction extractDependencyHints(content: string): string[] {\n const hints: string[] = [];\n const seen = new Set<string>();\n\n // Look for \"requires:\" or \"depends:\" in frontmatter\n try {\n const parsed = matter(content);\n const data = parsed.data as Record<string, unknown>;\n if (Array.isArray(data.requires)) {\n for (const dep of data.requires as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.depends)) {\n for (const dep of data.depends as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n if (Array.isArray(data.related)) {\n for (const dep of data.related as string[]) {\n if (!seen.has(dep)) {\n hints.push(dep);\n seen.add(dep);\n }\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return hints;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ doctorHarness,
5
+ validateHarness
6
+ } from "./chunk-FLZU44SV.js";
7
+ import "./chunk-W4T7PGI2.js";
8
+ import "./chunk-5H34JPMB.js";
9
+ import "./chunk-4FDUOGSZ.js";
10
+ import "./chunk-UWQTZMNI.js";
11
+ import "./chunk-UDZIS2AQ.js";
12
+ import "./chunk-Z2PUCXTZ.js";
13
+ import "./chunk-UPLBF4RZ.js";
14
+ import "./chunk-BSKDOFRT.js";
15
+ import "./chunk-CHJ5GNZC.js";
16
+ import "./chunk-4CWAGBNS.js";
17
+ import "./chunk-ZZJOFKAT.js";
18
+ export {
19
+ doctorHarness,
20
+ validateHarness
21
+ };
22
+ //# sourceMappingURL=validator-7WXMDIHH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,246 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ loadDirectory
5
+ } from "./chunk-UPLBF4RZ.js";
6
+ import "./chunk-4CWAGBNS.js";
7
+ import "./chunk-ZZJOFKAT.js";
8
+
9
+ // src/runtime/verification-gate.ts
10
+ import { existsSync } from "fs";
11
+ import { join } from "path";
12
+ function extractGates(doc) {
13
+ const gates = [];
14
+ const body = doc.body;
15
+ const gateSectionRegex = /##\s+(?:Gate|Verification):\s*(.+)\n([\s\S]*?)(?=\n##\s|\n*$)/gi;
16
+ let match;
17
+ while ((match = gateSectionRegex.exec(body)) !== null) {
18
+ const stageName = match[1].trim();
19
+ const sectionBody = match[2];
20
+ const criteria = extractCriteriaFromSection(sectionBody);
21
+ if (criteria.length > 0) {
22
+ gates.push({
23
+ id: `${doc.frontmatter.id}:${slugify(stageName)}`,
24
+ stage: stageName,
25
+ sourceId: doc.frontmatter.id,
26
+ criteria
27
+ });
28
+ }
29
+ }
30
+ const acRegex = /###\s+(?:Acceptance Criteria|Gate)\s*(?::\s*(.+))?\n([\s\S]*?)(?=\n###?\s|\n*$)/gi;
31
+ while ((match = acRegex.exec(body)) !== null) {
32
+ const stageName = match[1]?.trim() ?? "default";
33
+ const sectionBody = match[2];
34
+ const criteria = extractCriteriaFromSection(sectionBody);
35
+ if (criteria.length > 0) {
36
+ const gateId = `${doc.frontmatter.id}:ac-${slugify(stageName)}`;
37
+ if (!gates.some((g) => g.id === gateId)) {
38
+ gates.push({
39
+ id: gateId,
40
+ stage: stageName,
41
+ sourceId: doc.frontmatter.id,
42
+ criteria
43
+ });
44
+ }
45
+ }
46
+ }
47
+ const inlineRegex = /<!--\s*gate:\s*(.+?)\s*-->/gi;
48
+ while ((match = inlineRegex.exec(body)) !== null) {
49
+ const desc = match[1].trim();
50
+ const gateId = `${doc.frontmatter.id}:inline-${slugify(desc.slice(0, 40))}`;
51
+ if (!gates.some((g) => g.id === gateId)) {
52
+ gates.push({
53
+ id: gateId,
54
+ stage: "inline",
55
+ sourceId: doc.frontmatter.id,
56
+ criteria: [{
57
+ description: desc,
58
+ manual: !desc.includes("`"),
59
+ command: extractInlineCommand(desc)
60
+ }]
61
+ });
62
+ }
63
+ }
64
+ const stepGates = extractStepGates(doc);
65
+ for (const gate of stepGates) {
66
+ if (!gates.some((g) => g.id === gate.id)) {
67
+ gates.push(gate);
68
+ }
69
+ }
70
+ return gates;
71
+ }
72
+ function extractCriteriaFromSection(section) {
73
+ const criteria = [];
74
+ for (const line of section.split("\n")) {
75
+ const trimmed = line.trim();
76
+ if (!trimmed) continue;
77
+ const listMatch = trimmed.match(/^[-*]\s+(?:\[[ x]]\s+)?(.+)/);
78
+ if (!listMatch) continue;
79
+ const desc = listMatch[1].trim();
80
+ if (!desc) continue;
81
+ const cmdMatch = desc.match(/`(.+?)`/);
82
+ const isManual = !cmdMatch;
83
+ const patternMatch = desc.match(/(?:should\s+(?:output|return|show)|expected:\s*)(.+?)(?:\)|$)/i);
84
+ criteria.push({
85
+ description: desc,
86
+ manual: isManual,
87
+ command: cmdMatch ? cmdMatch[1] : void 0,
88
+ expectedPattern: patternMatch ? patternMatch[1].trim() : void 0
89
+ });
90
+ }
91
+ return criteria;
92
+ }
93
+ function extractStepGates(doc) {
94
+ const gates = [];
95
+ const lines = doc.body.split("\n");
96
+ let currentStep = "";
97
+ let criteriaBuffer = [];
98
+ for (const line of lines) {
99
+ const trimmed = line.trim();
100
+ const stepMatch = trimmed.match(/^(?:\d+\.\s+\*\*(.+?)\*\*|##\s+Step\s+\d+:\s*(.+))/);
101
+ if (stepMatch) {
102
+ if (currentStep && criteriaBuffer.length > 0) {
103
+ gates.push({
104
+ id: `${doc.frontmatter.id}:step-${slugify(currentStep)}`,
105
+ stage: currentStep,
106
+ sourceId: doc.frontmatter.id,
107
+ criteria: [...criteriaBuffer]
108
+ });
109
+ criteriaBuffer = [];
110
+ }
111
+ currentStep = (stepMatch[1] ?? stepMatch[2]).trim();
112
+ continue;
113
+ }
114
+ const checkboxMatch = trimmed.match(/^[-*]\s+\[[ x]]\s+(.+)/);
115
+ if (checkboxMatch && currentStep) {
116
+ const desc = checkboxMatch[1].trim();
117
+ const cmdMatch = desc.match(/`(.+?)`/);
118
+ criteriaBuffer.push({
119
+ description: desc,
120
+ manual: !cmdMatch,
121
+ command: cmdMatch ? cmdMatch[1] : void 0
122
+ });
123
+ }
124
+ }
125
+ if (currentStep && criteriaBuffer.length > 0) {
126
+ gates.push({
127
+ id: `${doc.frontmatter.id}:step-${slugify(currentStep)}`,
128
+ stage: currentStep,
129
+ sourceId: doc.frontmatter.id,
130
+ criteria: [...criteriaBuffer]
131
+ });
132
+ }
133
+ return gates;
134
+ }
135
+ function extractInlineCommand(desc) {
136
+ const match = desc.match(/`(.+?)`/);
137
+ return match ? match[1] : void 0;
138
+ }
139
+ function slugify(text) {
140
+ return text.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").slice(0, 50).replace(/-+$/, "");
141
+ }
142
+ function loadGates(harnessDir) {
143
+ const gates = [];
144
+ const sources = [];
145
+ for (const dir of ["playbooks", "workflows"]) {
146
+ const fullPath = join(harnessDir, dir);
147
+ if (!existsSync(fullPath)) continue;
148
+ const docs = loadDirectory(fullPath);
149
+ for (const doc of docs) {
150
+ if (doc.frontmatter.status !== "active") continue;
151
+ const docGates = extractGates(doc);
152
+ if (docGates.length > 0) {
153
+ gates.push(...docGates);
154
+ if (!sources.includes(doc.frontmatter.id)) {
155
+ sources.push(doc.frontmatter.id);
156
+ }
157
+ }
158
+ }
159
+ }
160
+ return { gates, sources };
161
+ }
162
+ function getGatesForPlaybook(harnessDir, playbookId) {
163
+ const { gates } = loadGates(harnessDir);
164
+ return gates.filter((g) => g.sourceId === playbookId);
165
+ }
166
+ function checkGate(gate, manualResults, commandOutputs) {
167
+ const results = [];
168
+ const pendingManual = [];
169
+ for (const criterion of gate.criteria) {
170
+ if (criterion.manual) {
171
+ if (manualResults && manualResults.has(criterion.description)) {
172
+ const passed2 = manualResults.get(criterion.description);
173
+ results.push({
174
+ criterion: criterion.description,
175
+ passed: passed2,
176
+ detail: passed2 ? "Manually verified" : "Manual verification failed"
177
+ });
178
+ } else {
179
+ pendingManual.push(criterion.description);
180
+ results.push({
181
+ criterion: criterion.description,
182
+ passed: false,
183
+ detail: "Awaiting manual verification"
184
+ });
185
+ }
186
+ } else if (criterion.command && commandOutputs) {
187
+ const output = commandOutputs.get(criterion.command);
188
+ if (output === void 0) {
189
+ results.push({
190
+ criterion: criterion.description,
191
+ passed: false,
192
+ detail: `Command not executed: ${criterion.command}`
193
+ });
194
+ } else if (criterion.expectedPattern) {
195
+ try {
196
+ const regex = new RegExp(criterion.expectedPattern, "i");
197
+ const passed2 = regex.test(output);
198
+ results.push({
199
+ criterion: criterion.description,
200
+ passed: passed2,
201
+ detail: passed2 ? `Output matches expected pattern` : `Output does not match expected pattern: ${criterion.expectedPattern}`
202
+ });
203
+ } catch {
204
+ const passed2 = output.includes(criterion.expectedPattern);
205
+ results.push({
206
+ criterion: criterion.description,
207
+ passed: passed2,
208
+ detail: passed2 ? "Output contains expected text" : "Output missing expected text"
209
+ });
210
+ }
211
+ } else {
212
+ results.push({
213
+ criterion: criterion.description,
214
+ passed: true,
215
+ detail: "Command produced output"
216
+ });
217
+ }
218
+ } else {
219
+ results.push({
220
+ criterion: criterion.description,
221
+ passed: false,
222
+ detail: criterion.command ? `Command not executed: ${criterion.command}` : "No verification method"
223
+ });
224
+ }
225
+ }
226
+ const passed = results.every((r) => r.passed) && pendingManual.length === 0;
227
+ return {
228
+ gateId: gate.id,
229
+ stage: gate.stage,
230
+ passed,
231
+ results,
232
+ pendingManual
233
+ };
234
+ }
235
+ function checkAllGates(harnessDir, playbookId, manualResults, commandOutputs) {
236
+ const gates = getGatesForPlaybook(harnessDir, playbookId);
237
+ return gates.map((gate) => checkGate(gate, manualResults, commandOutputs));
238
+ }
239
+ export {
240
+ checkAllGates,
241
+ checkGate,
242
+ extractGates,
243
+ getGatesForPlaybook,
244
+ loadGates
245
+ };
246
+ //# sourceMappingURL=verification-gate-FYXUX6LH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/verification-gate.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { loadDirectory } from '../primitives/loader.js';\nimport type { HarnessDocument, HarnessConfig } from '../core/types.js';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface VerificationCriterion {\n /** Human-readable criterion description */\n description: string;\n /** Whether this criterion must be manually checked (vs auto-checkable) */\n manual: boolean;\n /** Optional command to run for automated verification */\n command?: string;\n /** Optional expected output pattern (regex) for automated verification */\n expectedPattern?: string;\n}\n\nexport interface VerificationGate {\n /** Gate ID derived from playbook/workflow stage */\n id: string;\n /** Stage name this gate guards (e.g., \"Build\", \"Verify\") */\n stage: string;\n /** Source playbook/workflow ID */\n sourceId: string;\n /** Acceptance criteria that must pass before proceeding */\n criteria: VerificationCriterion[];\n}\n\nexport interface GateCheckResult {\n gateId: string;\n stage: string;\n passed: boolean;\n /** Individual criterion results */\n results: Array<{\n criterion: string;\n passed: boolean;\n detail?: string;\n }>;\n /** Criteria that need manual verification */\n pendingManual: string[];\n}\n\nexport interface GateExtractResult {\n gates: VerificationGate[];\n /** Source playbook/workflow IDs that had gates */\n sources: string[];\n}\n\n// ─── Gate Extraction ─────────────────────────────────────────────────────────\n\n/**\n * Extract verification gates from a playbook or workflow document.\n *\n * Gates are detected from:\n * 1. `## Gate:` or `## Verification:` sections in the document body\n * 2. Acceptance criteria blocks (`### Acceptance Criteria` or `### Gate`)\n * 3. Inline gate markers: `<!-- gate: description -->` in the markdown\n * 4. Numbered steps with `[x]` checkbox markers (treated as manual criteria)\n */\nexport function extractGates(doc: HarnessDocument): VerificationGate[] {\n const gates: VerificationGate[] = [];\n const body = doc.body;\n\n // Strategy 1: Named gate sections\n const gateSectionRegex = /##\\s+(?:Gate|Verification):\\s*(.+)\\n([\\s\\S]*?)(?=\\n##\\s|\\n*$)/gi;\n let match: RegExpExecArray | null;\n\n while ((match = gateSectionRegex.exec(body)) !== null) {\n const stageName = match[1].trim();\n const sectionBody = match[2];\n const criteria = extractCriteriaFromSection(sectionBody);\n\n if (criteria.length > 0) {\n gates.push({\n id: `${doc.frontmatter.id}:${slugify(stageName)}`,\n stage: stageName,\n sourceId: doc.frontmatter.id,\n criteria,\n });\n }\n }\n\n // Strategy 2: Acceptance criteria subsections\n const acRegex = /###\\s+(?:Acceptance Criteria|Gate)\\s*(?::\\s*(.+))?\\n([\\s\\S]*?)(?=\\n###?\\s|\\n*$)/gi;\n\n while ((match = acRegex.exec(body)) !== null) {\n const stageName = match[1]?.trim() ?? 'default';\n const sectionBody = match[2];\n const criteria = extractCriteriaFromSection(sectionBody);\n\n if (criteria.length > 0) {\n const gateId = `${doc.frontmatter.id}:ac-${slugify(stageName)}`;\n // Avoid duplicates from strategy 1\n if (!gates.some((g) => g.id === gateId)) {\n gates.push({\n id: gateId,\n stage: stageName,\n sourceId: doc.frontmatter.id,\n criteria,\n });\n }\n }\n }\n\n // Strategy 3: Inline gate markers\n const inlineRegex = /<!--\\s*gate:\\s*(.+?)\\s*-->/gi;\n\n while ((match = inlineRegex.exec(body)) !== null) {\n const desc = match[1].trim();\n const gateId = `${doc.frontmatter.id}:inline-${slugify(desc.slice(0, 40))}`;\n\n if (!gates.some((g) => g.id === gateId)) {\n gates.push({\n id: gateId,\n stage: 'inline',\n sourceId: doc.frontmatter.id,\n criteria: [{\n description: desc,\n manual: !desc.includes('`'),\n command: extractInlineCommand(desc),\n }],\n });\n }\n }\n\n // Strategy 4: Steps with checkboxes between stages\n const stepGates = extractStepGates(doc);\n for (const gate of stepGates) {\n if (!gates.some((g) => g.id === gate.id)) {\n gates.push(gate);\n }\n }\n\n return gates;\n}\n\n/**\n * Extract criteria from a section body (bullet list parsing).\n */\nfunction extractCriteriaFromSection(section: string): VerificationCriterion[] {\n const criteria: VerificationCriterion[] = [];\n\n for (const line of section.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n // Bullet or numbered list items\n const listMatch = trimmed.match(/^[-*]\\s+(?:\\[[ x]]\\s+)?(.+)/);\n if (!listMatch) continue;\n\n const desc = listMatch[1].trim();\n if (!desc) continue;\n\n // Check if it's an automated criterion (contains backtick command)\n const cmdMatch = desc.match(/`(.+?)`/);\n const isManual = !cmdMatch;\n\n // Check for expected pattern: \"should output X\" or \"expected: X\"\n const patternMatch = desc.match(/(?:should\\s+(?:output|return|show)|expected:\\s*)(.+?)(?:\\)|$)/i);\n\n criteria.push({\n description: desc,\n manual: isManual,\n command: cmdMatch ? cmdMatch[1] : undefined,\n expectedPattern: patternMatch ? patternMatch[1].trim() : undefined,\n });\n }\n\n return criteria;\n}\n\n/**\n * Extract verification gates from step transitions.\n * Looks for numbered steps where intermediate verification steps exist.\n */\nfunction extractStepGates(doc: HarnessDocument): VerificationGate[] {\n const gates: VerificationGate[] = [];\n const lines = doc.body.split('\\n');\n let currentStep = '';\n let criteriaBuffer: VerificationCriterion[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Detect numbered step headers (e.g., \"1. **Understand**\" or \"## Step 1:\")\n const stepMatch = trimmed.match(/^(?:\\d+\\.\\s+\\*\\*(.+?)\\*\\*|##\\s+Step\\s+\\d+:\\s*(.+))/);\n if (stepMatch) {\n // Flush previous gate if criteria were collected\n if (currentStep && criteriaBuffer.length > 0) {\n gates.push({\n id: `${doc.frontmatter.id}:step-${slugify(currentStep)}`,\n stage: currentStep,\n sourceId: doc.frontmatter.id,\n criteria: [...criteriaBuffer],\n });\n criteriaBuffer = [];\n }\n currentStep = (stepMatch[1] ?? stepMatch[2]).trim();\n continue;\n }\n\n // Collect checkbox items within steps as criteria\n const checkboxMatch = trimmed.match(/^[-*]\\s+\\[[ x]]\\s+(.+)/);\n if (checkboxMatch && currentStep) {\n const desc = checkboxMatch[1].trim();\n const cmdMatch = desc.match(/`(.+?)`/);\n criteriaBuffer.push({\n description: desc,\n manual: !cmdMatch,\n command: cmdMatch ? cmdMatch[1] : undefined,\n });\n }\n }\n\n // Flush last step\n if (currentStep && criteriaBuffer.length > 0) {\n gates.push({\n id: `${doc.frontmatter.id}:step-${slugify(currentStep)}`,\n stage: currentStep,\n sourceId: doc.frontmatter.id,\n criteria: [...criteriaBuffer],\n });\n }\n\n return gates;\n}\n\n/**\n * Extract a command from an inline gate description (text between backticks).\n */\nfunction extractInlineCommand(desc: string): string | undefined {\n const match = desc.match(/`(.+?)`/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Convert text to a URL-safe slug.\n */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-')\n .slice(0, 50)\n .replace(/-+$/, '');\n}\n\n// ─── Gate Loading ────────────────────────────────────────────────────────────\n\n/**\n * Load all verification gates from playbooks and workflows in the harness.\n */\nexport function loadGates(harnessDir: string): GateExtractResult {\n const gates: VerificationGate[] = [];\n const sources: string[] = [];\n\n for (const dir of ['playbooks', 'workflows']) {\n const fullPath = join(harnessDir, dir);\n if (!existsSync(fullPath)) continue;\n\n const docs = loadDirectory(fullPath);\n for (const doc of docs) {\n if (doc.frontmatter.status !== 'active') continue;\n const docGates = extractGates(doc);\n if (docGates.length > 0) {\n gates.push(...docGates);\n if (!sources.includes(doc.frontmatter.id)) {\n sources.push(doc.frontmatter.id);\n }\n }\n }\n }\n\n return { gates, sources };\n}\n\n/**\n * Find gates for a specific playbook/workflow by ID.\n */\nexport function getGatesForPlaybook(harnessDir: string, playbookId: string): VerificationGate[] {\n const { gates } = loadGates(harnessDir);\n return gates.filter((g) => g.sourceId === playbookId);\n}\n\n// ─── Gate Checking ───────────────────────────────────────────────────────────\n\n/**\n * Check a verification gate against provided results.\n * For manual criteria, checks against the `manualResults` map.\n * For automated criteria, checks if the command output matches the expected pattern.\n *\n * @param gate - The gate to check\n * @param manualResults - Map of criterion description → pass/fail\n * @param commandOutputs - Map of command → actual output (for automated checks)\n */\nexport function checkGate(\n gate: VerificationGate,\n manualResults?: Map<string, boolean>,\n commandOutputs?: Map<string, string>,\n): GateCheckResult {\n const results: Array<{ criterion: string; passed: boolean; detail?: string }> = [];\n const pendingManual: string[] = [];\n\n for (const criterion of gate.criteria) {\n if (criterion.manual) {\n // Manual criterion — check if result was provided\n if (manualResults && manualResults.has(criterion.description)) {\n const passed = manualResults.get(criterion.description)!;\n results.push({\n criterion: criterion.description,\n passed,\n detail: passed ? 'Manually verified' : 'Manual verification failed',\n });\n } else {\n pendingManual.push(criterion.description);\n results.push({\n criterion: criterion.description,\n passed: false,\n detail: 'Awaiting manual verification',\n });\n }\n } else if (criterion.command && commandOutputs) {\n // Automated criterion — check command output\n const output = commandOutputs.get(criterion.command);\n if (output === undefined) {\n results.push({\n criterion: criterion.description,\n passed: false,\n detail: `Command not executed: ${criterion.command}`,\n });\n } else if (criterion.expectedPattern) {\n try {\n const regex = new RegExp(criterion.expectedPattern, 'i');\n const passed = regex.test(output);\n results.push({\n criterion: criterion.description,\n passed,\n detail: passed\n ? `Output matches expected pattern`\n : `Output does not match expected pattern: ${criterion.expectedPattern}`,\n });\n } catch {\n // Invalid regex — treat as string match\n const passed = output.includes(criterion.expectedPattern);\n results.push({\n criterion: criterion.description,\n passed,\n detail: passed ? 'Output contains expected text' : 'Output missing expected text',\n });\n }\n } else {\n // No expected pattern — command succeeded if output exists\n results.push({\n criterion: criterion.description,\n passed: true,\n detail: 'Command produced output',\n });\n }\n } else {\n // Automated criterion but no output available\n results.push({\n criterion: criterion.description,\n passed: false,\n detail: criterion.command ? `Command not executed: ${criterion.command}` : 'No verification method',\n });\n }\n }\n\n const passed = results.every((r) => r.passed) && pendingManual.length === 0;\n\n return {\n gateId: gate.id,\n stage: gate.stage,\n passed,\n results,\n pendingManual,\n };\n}\n\n/**\n * Check all gates for a playbook/workflow. Returns individual gate results.\n */\nexport function checkAllGates(\n harnessDir: string,\n playbookId: string,\n manualResults?: Map<string, boolean>,\n commandOutputs?: Map<string, string>,\n): GateCheckResult[] {\n const gates = getGatesForPlaybook(harnessDir, playbookId);\n return gates.map((gate) => checkGate(gate, manualResults, commandOutputs));\n}\n"],"mappings":"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","names":["passed"]}