freeharness 0.4.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 (375) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +108 -0
  3. package/README.md +134 -0
  4. package/canonical/HARVEST.yaml +858 -0
  5. package/canonical/PROVENANCE.yaml +740 -0
  6. package/canonical/agents/README.md +95 -0
  7. package/canonical/agents/agentic-architect.md +18 -0
  8. package/canonical/agents/database-reviewer.md +41 -0
  9. package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
  10. package/canonical/agents/pr-reviewer.md +96 -0
  11. package/canonical/agents/python-reviewer.md +55 -0
  12. package/canonical/agents/report-formatter.md +19 -0
  13. package/canonical/agents/security-reviewer.md +53 -0
  14. package/canonical/agents/test-writer.md +34 -0
  15. package/canonical/commands/fh-context.md +37 -0
  16. package/canonical/evals/promptfoo.redteam.yaml +108 -0
  17. package/canonical/hooks/cost-prices.json +14 -0
  18. package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
  19. package/canonical/hooks/freeharness-config-guard.mjs +162 -0
  20. package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
  21. package/canonical/hooks/freeharness-converge.mjs +227 -0
  22. package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
  23. package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
  24. package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
  25. package/canonical/hooks/freeharness-precompact.mjs +323 -0
  26. package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
  27. package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
  28. package/canonical/hooks/freeharness-session-start +583 -0
  29. package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
  30. package/canonical/hooks/hooks.claude-code.json +17 -0
  31. package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
  32. package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
  33. package/canonical/hooks/hooks.converge.claude-code.json +15 -0
  34. package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
  35. package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
  36. package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
  37. package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
  38. package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
  39. package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
  40. package/canonical/mcp/servers.json +20 -0
  41. package/canonical/openspec/config.base.yaml +89 -0
  42. package/canonical/openspec/schema.spec-driven.yaml +277 -0
  43. package/canonical/openspec/templates/data-contract.md +36 -0
  44. package/canonical/openspec/templates/design.md +84 -0
  45. package/canonical/openspec/templates/eval-plan.md +33 -0
  46. package/canonical/openspec/templates/follow-ups.md +2 -0
  47. package/canonical/openspec/templates/proposal.md +45 -0
  48. package/canonical/openspec/templates/spec.md +42 -0
  49. package/canonical/openspec/templates/tasks.md +38 -0
  50. package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
  51. package/canonical/profiles/local-llamacpp.json +27 -0
  52. package/canonical/profiles/local-ollama.json +20 -0
  53. package/canonical/profiles/mcp.json +91 -0
  54. package/canonical/rules/CLAUDE.md +78 -0
  55. package/canonical/rules/project-CLAUDE.template.md +62 -0
  56. package/canonical/rules/routing.md +20 -0
  57. package/canonical/rules/safety.md +41 -0
  58. package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
  59. package/canonical/skills/agent-evaluation/SKILL.md +102 -0
  60. package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
  61. package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
  62. package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
  63. package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
  64. package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
  65. package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
  66. package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
  67. package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
  68. package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
  69. package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
  70. package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
  71. package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
  72. package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
  73. package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
  74. package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
  75. package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
  76. package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
  77. package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
  78. package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
  79. package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
  80. package/canonical/skills/agentic-architecture/SKILL.md +41 -0
  81. package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
  82. package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
  83. package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
  84. package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
  85. package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
  86. package/canonical/skills/code-review/SKILL.md +52 -0
  87. package/canonical/skills/code-review/evals/cases.yaml +197 -0
  88. package/canonical/skills/git-workflow/SKILL.md +41 -0
  89. package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
  90. package/canonical/skills/local-code/SKILL.md +24 -0
  91. package/canonical/skills/local-code/evals/cases.yaml +85 -0
  92. package/canonical/skills/local-code/scripts/query_llama.py +68 -0
  93. package/canonical/skills/report-formatting/SKILL.md +62 -0
  94. package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
  95. package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
  96. package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
  97. package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
  98. package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
  99. package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
  100. package/canonical/skills/report-formatting/reference/authoring.md +66 -0
  101. package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
  102. package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
  103. package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
  104. package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
  105. package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
  106. package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
  107. package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
  108. package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
  109. package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
  110. package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
  111. package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
  112. package/canonical/skills/report-formatting/scripts/package.json +17 -0
  113. package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
  114. package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
  115. package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
  116. package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
  117. package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
  118. package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
  119. package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
  120. package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
  121. package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
  122. package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
  123. package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
  124. package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
  125. package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
  126. package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
  127. package/canonical/skills/systematic-debugging/SKILL.md +44 -0
  128. package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
  129. package/canonical/skills/test-driven-development/SKILL.md +42 -0
  130. package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
  131. package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
  132. package/canonical/skills/verification-before-completion/SKILL.md +53 -0
  133. package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
  134. package/dist/adapters/content/language-lint.d.ts +46 -0
  135. package/dist/adapters/content/language-lint.js +191 -0
  136. package/dist/adapters/harness/claude-code.d.ts +57 -0
  137. package/dist/adapters/harness/claude-code.js +385 -0
  138. package/dist/adapters/harness/index.d.ts +3 -0
  139. package/dist/adapters/harness/index.js +17 -0
  140. package/dist/adapters/harness/opencode.d.ts +7 -0
  141. package/dist/adapters/harness/opencode.js +166 -0
  142. package/dist/adapters/harness/plugin.d.ts +22 -0
  143. package/dist/adapters/harness/plugin.js +257 -0
  144. package/dist/adapters/memory/doctor.d.ts +480 -0
  145. package/dist/adapters/memory/doctor.js +1217 -0
  146. package/dist/adapters/memory/vendored.d.ts +150 -0
  147. package/dist/adapters/memory/vendored.js +487 -0
  148. package/dist/adapters/package/node.d.ts +9 -0
  149. package/dist/adapters/package/node.js +20 -0
  150. package/dist/adapters/prompt/readline.d.ts +19 -0
  151. package/dist/adapters/prompt/readline.js +53 -0
  152. package/dist/adapters/sync/diff.d.ts +43 -0
  153. package/dist/adapters/sync/diff.js +380 -0
  154. package/dist/cli/cleanup.d.ts +86 -0
  155. package/dist/cli/cleanup.js +382 -0
  156. package/dist/cli/cost.d.ts +304 -0
  157. package/dist/cli/cost.js +501 -0
  158. package/dist/cli/doctor.d.ts +205 -0
  159. package/dist/cli/doctor.js +654 -0
  160. package/dist/cli/executor.d.ts +5 -0
  161. package/dist/cli/executor.js +48 -0
  162. package/dist/cli/plugin-validate.d.ts +37 -0
  163. package/dist/cli/plugin-validate.js +256 -0
  164. package/dist/cli/prefix.d.ts +68 -0
  165. package/dist/cli/prefix.js +218 -0
  166. package/dist/cli/profile.d.ts +170 -0
  167. package/dist/cli/profile.js +285 -0
  168. package/dist/cli/runner.d.ts +10 -0
  169. package/dist/cli/runner.js +27 -0
  170. package/dist/cli/uninstall.d.ts +65 -0
  171. package/dist/cli/uninstall.js +147 -0
  172. package/dist/index.d.ts +8 -0
  173. package/dist/index.js +989 -0
  174. package/dist/infra/dogfood.d.ts +31 -0
  175. package/dist/infra/dogfood.js +51 -0
  176. package/dist/infra/fsutil.d.ts +40 -0
  177. package/dist/infra/fsutil.js +143 -0
  178. package/dist/infra/manifest.d.ts +76 -0
  179. package/dist/infra/manifest.js +92 -0
  180. package/dist/infra/paths.d.ts +19 -0
  181. package/dist/infra/paths.js +74 -0
  182. package/dist/infra/routing.d.ts +4 -0
  183. package/dist/infra/routing.js +7 -0
  184. package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
  185. package/node_modules/@freeharness/core/dist/context.js +1 -0
  186. package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
  187. package/node_modules/@freeharness/core/dist/index.js +6 -0
  188. package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
  189. package/node_modules/@freeharness/core/dist/planner.js +18 -0
  190. package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
  191. package/node_modules/@freeharness/core/dist/ports.js +1 -0
  192. package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
  193. package/node_modules/@freeharness/core/dist/registry.js +124 -0
  194. package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
  195. package/node_modules/@freeharness/core/dist/tiers.js +99 -0
  196. package/node_modules/@freeharness/core/package.json +34 -0
  197. package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
  198. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
  199. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
  200. package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
  201. package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
  202. package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
  203. package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
  204. package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
  205. package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
  206. package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
  207. package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
  208. package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
  209. package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
  210. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
  211. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
  212. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
  213. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
  214. package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
  215. package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
  216. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
  217. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
  218. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
  219. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
  220. package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
  221. package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
  222. package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
  223. package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
  224. package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
  225. package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
  226. package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
  227. package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
  228. package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
  229. package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
  230. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
  231. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
  232. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
  233. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
  234. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
  235. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
  236. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
  237. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
  238. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
  239. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
  240. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
  241. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
  242. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
  243. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
  244. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
  245. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
  246. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
  247. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
  248. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
  249. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
  250. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
  251. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
  252. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
  253. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
  254. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
  255. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
  256. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
  257. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
  258. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
  259. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
  260. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
  261. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
  262. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
  263. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
  264. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
  265. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
  266. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
  267. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
  268. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
  269. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
  270. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
  271. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
  272. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
  273. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
  274. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
  275. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
  276. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
  277. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
  278. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
  279. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
  280. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
  281. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
  282. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
  283. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
  284. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
  285. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
  286. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
  287. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
  288. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
  289. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
  290. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
  291. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
  292. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
  293. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
  294. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
  295. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
  296. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
  297. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
  298. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
  299. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
  300. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
  301. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
  302. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
  303. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
  304. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
  305. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
  306. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
  307. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
  308. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
  309. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
  310. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
  311. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
  312. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
  313. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
  314. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
  315. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
  316. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
  317. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
  318. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
  319. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
  320. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
  321. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
  322. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
  323. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
  324. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
  325. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
  326. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
  327. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
  328. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
  329. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
  330. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
  331. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
  332. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
  333. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
  334. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
  335. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
  336. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
  337. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
  338. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
  339. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
  340. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
  341. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
  342. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
  343. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
  344. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
  345. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
  346. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
  347. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
  348. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
  349. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
  350. package/node_modules/@freeharness/sdd/package.json +57 -0
  351. package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
  352. package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
  353. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
  354. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
  355. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
  356. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
  357. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
  358. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
  359. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
  360. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
  361. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
  362. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
  363. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
  364. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
  365. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
  366. package/package.json +70 -0
  367. package/provenance/canonical.PROVENANCE.yaml +740 -0
  368. package/provenance/claude-mem.LICENSE.upstream +202 -0
  369. package/provenance/memory.PROVENANCE.yaml +399 -0
  370. package/provenance/sdd.PROVENANCE.yaml +175 -0
  371. package/vendor-licenses/caveman.LICENSE +27 -0
  372. package/vendor-licenses/deepseek-harness.LICENSE +21 -0
  373. package/vendor-licenses/ecc.LICENSE +21 -0
  374. package/vendor-licenses/pi.LICENSE +21 -0
  375. package/vendor-licenses/superpowers.LICENSE +21 -0
@@ -0,0 +1,123 @@
1
+ """Utilities for environment variable validation and MLflow configuration."""
2
+
3
+ import os
4
+
5
+ from packaging import version
6
+
7
+
8
+ def get_env_vars() -> dict[str, str | None]:
9
+ """Get MLflow environment variables.
10
+
11
+ Returns:
12
+ Dictionary with tracking_uri and experiment_id (may be None)
13
+ """
14
+ return {
15
+ "tracking_uri": os.getenv("MLFLOW_TRACKING_URI"),
16
+ "experiment_id": os.getenv("MLFLOW_EXPERIMENT_ID"),
17
+ }
18
+
19
+
20
+ def validate_env_vars(
21
+ require_tracking_uri: bool = True, require_experiment_id: bool = True
22
+ ) -> list[str]:
23
+ """Validate required environment variables are set.
24
+
25
+ Args:
26
+ require_tracking_uri: If True, MLFLOW_TRACKING_URI must be set
27
+ require_experiment_id: If True, MLFLOW_EXPERIMENT_ID must be set
28
+
29
+ Returns:
30
+ List of error messages (empty if valid)
31
+ """
32
+ errors = []
33
+ env_vars = get_env_vars()
34
+
35
+ if require_tracking_uri and not env_vars["tracking_uri"]:
36
+ errors.append("MLFLOW_TRACKING_URI is not set")
37
+
38
+ if require_experiment_id and not env_vars["experiment_id"]:
39
+ errors.append("MLFLOW_EXPERIMENT_ID is not set")
40
+
41
+ return errors
42
+
43
+
44
+ def validate_mlflow_version(min_version: str = "3.8.0") -> tuple[bool, str]:
45
+ """Check MLflow version compatibility.
46
+
47
+ Args:
48
+ min_version: Minimum required MLflow version
49
+
50
+ Returns:
51
+ Tuple of (is_valid, version_string)
52
+ """
53
+ try:
54
+ import mlflow
55
+
56
+ current_version = mlflow.__version__
57
+
58
+ # Remove dev/rc suffixes for comparison
59
+ clean_version = current_version.split("dev")[0].split("rc")[0]
60
+
61
+ is_valid = version.parse(clean_version) >= version.parse(min_version)
62
+ return is_valid, current_version
63
+ except ImportError:
64
+ return False, "not installed"
65
+
66
+
67
+ def test_mlflow_connection(tracking_uri: str, experiment_id: str) -> tuple[bool, str]:
68
+ """Test connection to MLflow tracking server.
69
+
70
+ Args:
71
+ tracking_uri: MLflow tracking URI
72
+ experiment_id: MLflow experiment ID
73
+
74
+ Returns:
75
+ Tuple of (success, error_message_or_experiment_name)
76
+ """
77
+ try:
78
+ from mlflow import MlflowClient
79
+
80
+ client = MlflowClient()
81
+ experiment = client.get_experiment(experiment_id)
82
+
83
+ if experiment:
84
+ return True, experiment.name
85
+ else:
86
+ return False, f"Experiment {experiment_id} not found"
87
+ except Exception as e:
88
+ return False, str(e)[:100]
89
+
90
+
91
+ def check_databricks_config() -> tuple[bool, str | None]:
92
+ """Check if running with Databricks configuration.
93
+
94
+ Returns:
95
+ Tuple of (is_databricks, profile_or_error_message)
96
+ """
97
+ tracking_uri = os.getenv("MLFLOW_TRACKING_URI", "")
98
+
99
+ # Check if tracking URI indicates Databricks
100
+ if "databricks" in tracking_uri.lower():
101
+ # Extract profile if present
102
+ if "databricks://" in tracking_uri:
103
+ profile = tracking_uri.split("databricks://")[1] if len(tracking_uri.split("databricks://")) > 1 else "DEFAULT"
104
+ return True, profile
105
+ return True, "databricks"
106
+
107
+ # Check for Databricks SDK/CLI
108
+ try:
109
+ import subprocess
110
+
111
+ result = subprocess.run(
112
+ ["databricks", "auth", "profiles"],
113
+ capture_output=True,
114
+ text=True,
115
+ timeout=5,
116
+ )
117
+ if result.returncode == 0:
118
+ profiles = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
119
+ return True, profiles[0] if profiles else None
120
+ except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.CalledProcessError):
121
+ pass
122
+
123
+ return False, None
@@ -0,0 +1,108 @@
1
+ """Utilities for tracing-related validation.
2
+
3
+ The coding agent should use Grep tool for discovery:
4
+ - Find autolog calls: grep -r "mlflow.*autolog" . --include="*.py"
5
+ - Find trace decorators: grep -r "@mlflow.trace" . --include="*.py"
6
+ - Find MLflow imports: grep -r "import mlflow" . --include="*.py"
7
+
8
+ This module provides validation helpers used by validation scripts.
9
+ """
10
+
11
+ import re
12
+ from pathlib import Path
13
+
14
+
15
+ def check_import_order(file_path: str, import_pattern: str = None) -> tuple[bool, str]:
16
+ """Verify autolog is called before library/module imports.
17
+
18
+ Args:
19
+ file_path: Path to file containing autolog call
20
+ import_pattern: Optional regex pattern to match imports (e.g., r"from .* import")
21
+ If None, checks for any "from ... import" after autolog
22
+
23
+ Returns:
24
+ Tuple of (is_correct, message)
25
+ """
26
+ try:
27
+ content = Path(file_path).read_text()
28
+ lines = content.split("\n")
29
+
30
+ autolog_line = None
31
+ first_import_line = None
32
+
33
+ for i, line in enumerate(lines, 1):
34
+ if "autolog()" in line:
35
+ autolog_line = i
36
+ # After finding autolog, look for any imports (customizable via pattern)
37
+ if autolog_line and "from" in line and "import" in line:
38
+ if import_pattern:
39
+ if re.search(import_pattern, line):
40
+ first_import_line = i
41
+ break
42
+ else:
43
+ first_import_line = i
44
+ break
45
+
46
+ if autolog_line and first_import_line:
47
+ if autolog_line < first_import_line:
48
+ return True, f"Autolog (line {autolog_line}) before imports (line {first_import_line})"
49
+ else:
50
+ return (
51
+ False,
52
+ f"Autolog (line {autolog_line}) after imports (line {first_import_line})",
53
+ )
54
+ elif autolog_line:
55
+ return True, f"Autolog found at line {autolog_line}"
56
+ else:
57
+ return False, "Autolog not found"
58
+
59
+ except Exception as e:
60
+ return True, f"Could not check import order: {e}" # Don't fail on errors
61
+
62
+
63
+
64
+
65
+ def check_session_id_capture(file_path: str) -> bool:
66
+ """Check if file has session ID tracking code.
67
+
68
+ Looks for: get_last_active_trace_id(), set_trace_tag(), session_id
69
+
70
+ Args:
71
+ file_path: Path to file to check
72
+
73
+ Returns:
74
+ True if all patterns found
75
+ """
76
+ try:
77
+ content = Path(file_path).read_text()
78
+
79
+ session_patterns = [
80
+ r"mlflow\.get_last_active_trace_id\(\)",
81
+ r"mlflow\.set_trace_tag\(",
82
+ r"session_id",
83
+ ]
84
+
85
+ return all(re.search(pattern, content) for pattern in session_patterns)
86
+ except Exception:
87
+ return False
88
+
89
+
90
+ def verify_mlflow_imports(file_paths: list[str]) -> dict[str, bool]:
91
+ """Check mlflow is imported in given files.
92
+
93
+ Args:
94
+ file_paths: List of file paths to check
95
+
96
+ Returns:
97
+ Dictionary mapping file_path to has_mlflow_import
98
+ """
99
+ results = {}
100
+
101
+ for file_path in file_paths:
102
+ try:
103
+ content = Path(file_path).read_text()
104
+ results[file_path] = "import mlflow" in content
105
+ except Exception:
106
+ results[file_path] = False
107
+
108
+ return results
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Validate MLflow tracing for your agent.
5
+
6
+ This is a template script. Fill in the TODO sections before running:
7
+ 1. Update the import statement with your agent's module and function
8
+ 2. Configure any dependencies (LLM providers, config, etc.)
9
+ 3. Adjust the function call to match your agent's signature
10
+ 4. Verify environment variables are set correctly
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import mlflow
16
+ from mlflow import MlflowClient
17
+
18
+ # TODO: Update these imports with your agent's module and entry point
19
+ # Example: from my_agent.agent import run_agent
20
+ from YOUR_MODULE import YOUR_ENTRY_POINT # <-- UPDATE THIS LINE
21
+
22
+ # Configuration
23
+ TEST_QUERY = "What is MLflow?"
24
+ TEST_SESSION_ID = "test-session-123"
25
+
26
+ # Verify environment variables
27
+ tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
28
+ experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
29
+
30
+ if not tracking_uri or not experiment_id:
31
+ print("✗ Missing required environment variables:")
32
+ print(" MLFLOW_TRACKING_URI:", tracking_uri or "(not set)")
33
+ print(" MLFLOW_EXPERIMENT_ID:", experiment_id or "(not set)")
34
+ print("\nRun scripts/setup_mlflow.py first")
35
+ sys.exit(1)
36
+
37
+ print("=" * 60)
38
+ print("MLflow Tracing Validation")
39
+ print("=" * 60)
40
+ print()
41
+ print(f"Tracking URI: {tracking_uri}")
42
+ print(f"Experiment ID: {experiment_id}")
43
+ print()
44
+
45
+ # TODO: Configure your agent's dependencies here
46
+ # IMPORTANT: Add any required setup before calling your agent
47
+ # Examples:
48
+ # from your_agent.llm import LLMConfig, LLMProvider
49
+ # llm_config = LLMConfig(model="gpt-4", temperature=0.0)
50
+ # llm_provider = LLMProvider(config=llm_config)
51
+ #
52
+ # from your_agent.config import AgentConfig
53
+ # agent_config = AgentConfig.from_env()
54
+
55
+ print("Running test query...")
56
+ print(f" Query: {TEST_QUERY}")
57
+ print(f" Session ID: {TEST_SESSION_ID}")
58
+ print()
59
+
60
+ try:
61
+ # TODO: Update this function call to match your agent's signature
62
+ # Examples:
63
+ # response = YOUR_ENTRY_POINT(TEST_QUERY, llm_provider)
64
+ # response = YOUR_ENTRY_POINT(TEST_QUERY, session_id=TEST_SESSION_ID)
65
+ # response = YOUR_ENTRY_POINT(TEST_QUERY, config=agent_config)
66
+
67
+ response = YOUR_ENTRY_POINT(TEST_QUERY) # <-- UPDATE THIS LINE
68
+
69
+ print("✓ Agent executed successfully")
70
+ print()
71
+
72
+ # Capture trace
73
+ trace_id = mlflow.get_last_active_trace_id()
74
+ if not trace_id:
75
+ print("✗ FAILED: No trace ID captured!")
76
+ print(" Check that mlflow.autolog() is called before agent execution")
77
+ sys.exit(1)
78
+
79
+ print(f"✓ Trace captured: {trace_id}")
80
+
81
+ # Get trace details
82
+ client = MlflowClient()
83
+ trace = client.get_trace(trace_id)
84
+
85
+ # Verify trace structure
86
+ print()
87
+ print("Verifying trace structure...")
88
+
89
+ if not trace.data.spans:
90
+ print("✗ FAILED: No spans found in trace")
91
+ sys.exit(1)
92
+
93
+ print(f"✓ Top-level span: {trace.data.spans[0].name} ({trace.data.spans[0].span_type})")
94
+
95
+ # Count total spans (including nested)
96
+ def count_spans(spans):
97
+ count = len(spans)
98
+ for span in spans:
99
+ if hasattr(span, 'spans') and span.spans:
100
+ count += count_spans(span.spans)
101
+ return count
102
+
103
+ total_spans = count_spans(trace.data.spans)
104
+ print(f"✓ Total spans: {total_spans}")
105
+
106
+ if total_spans < 2:
107
+ print("⚠ WARNING: Only 1 span found - autolog may not be working")
108
+ print(" Expected: @mlflow.trace decorator span + autolog library spans")
109
+ else:
110
+ print("✓ Multiple spans detected - autolog appears to be working")
111
+
112
+ # Print trace hierarchy
113
+ def print_hierarchy(spans, indent=0):
114
+ for span in spans:
115
+ prefix = " " + " " * indent
116
+ print(f"{prefix}- {span.name} ({span.span_type})")
117
+ if hasattr(span, 'spans') and span.spans:
118
+ print_hierarchy(span.spans, indent + 1)
119
+
120
+ print()
121
+ print(" Trace hierarchy:")
122
+ print_hierarchy(trace.data.spans)
123
+
124
+ # Check session ID (optional)
125
+ if "session_id" in trace.info.tags:
126
+ actual_session_id = trace.info.tags["session_id"]
127
+ print()
128
+ if actual_session_id == TEST_SESSION_ID:
129
+ print(f"✓ Session ID tagged: {actual_session_id}")
130
+ else:
131
+ print(f"⚠ Session ID mismatch: expected {TEST_SESSION_ID}, got {actual_session_id}")
132
+ else:
133
+ print()
134
+ print(" ℹ Note: No session_id tag found (optional for single-turn agents)")
135
+
136
+ print()
137
+ print("=" * 60)
138
+ print("✓ VALIDATION PASSED")
139
+ print("=" * 60)
140
+ print()
141
+ print("Your agent is properly integrated with MLflow tracing!")
142
+ print()
143
+
144
+ except Exception as e:
145
+ print(f"✗ FAILED: {str(e)}")
146
+ import traceback
147
+ traceback.print_exc()
148
+ sys.exit(1)
@@ -0,0 +1,240 @@
1
+ """
2
+ Validate authentication for agent evaluation.
3
+
4
+ This script tests authentication to required services:
5
+ - MLflow tracking server (Databricks or local)
6
+ - LLM provider (if configured)
7
+
8
+ Performs lightweight API calls to verify credentials before expensive operations.
9
+
10
+ Usage:
11
+ python scripts/validate_auth.py
12
+ """
13
+
14
+ import os
15
+ import sys
16
+
17
+ from utils import check_databricks_config, validate_env_vars
18
+
19
+
20
+ def check_databricks_auth():
21
+ """Test Databricks authentication."""
22
+ print("Testing Databricks authentication...")
23
+
24
+ is_databricks, profile = check_databricks_config()
25
+
26
+ if not is_databricks:
27
+ print(" ⊘ Not using Databricks (skipped)")
28
+ print()
29
+ return []
30
+
31
+ # Check for auth credentials
32
+ token = os.getenv("DATABRICKS_TOKEN")
33
+ host = os.getenv("DATABRICKS_HOST")
34
+
35
+ if not token and not host:
36
+ # Try using databricks SDK (more robust) or fallback to CLI
37
+ try:
38
+ # Try new Databricks SDK first
39
+ try:
40
+ from databricks import sdk
41
+
42
+ print(" ↻ Using Databricks SDK...")
43
+
44
+ # Try to create workspace client
45
+ try:
46
+ w = sdk.WorkspaceClient()
47
+ # Test with a simple API call
48
+ current_user = w.current_user.me()
49
+ print(f" ✓ Authenticated as: {current_user.user_name}")
50
+ print()
51
+ return []
52
+
53
+ except AttributeError as e:
54
+ # Handle NoneType error gracefully
55
+ if "'NoneType'" in str(e):
56
+ print(" ✗ Databricks configuration incomplete or corrupted")
57
+ print()
58
+ return ["Run: databricks auth login --profile DEFAULT"]
59
+ raise
60
+
61
+ except ImportError:
62
+ # Fall back to old databricks-cli
63
+ from databricks_cli.sdk.api_client import ApiClient
64
+
65
+ print(" ↻ Using Databricks CLI profile...")
66
+
67
+ try:
68
+ api_client = ApiClient()
69
+
70
+ # Check if api_client is properly initialized
71
+ if api_client is None or not hasattr(api_client, "host"):
72
+ print(" ✗ Databricks CLI profile not configured")
73
+ print()
74
+ return ["Run: databricks auth login --profile DEFAULT"]
75
+
76
+ except (AttributeError, TypeError) as e:
77
+ print(f" ✗ Profile configuration error: {str(e)[:80]}")
78
+ print()
79
+ return ["Run: databricks auth login --profile DEFAULT"]
80
+
81
+ # Test with MLflow client
82
+ from mlflow import MlflowClient
83
+
84
+ client = MlflowClient()
85
+ client.search_experiments(max_results=1)
86
+ print(" ✓ Databricks profile authenticated")
87
+ print()
88
+ return []
89
+
90
+ except ImportError:
91
+ print(" ✗ Neither databricks-sdk nor databricks-cli installed")
92
+ print()
93
+ return ["Install databricks SDK: pip install databricks-sdk"]
94
+ except Exception as e:
95
+ print(f" ✗ Authentication failed: {str(e)[:100]}")
96
+ print()
97
+ return ["Run: databricks auth login --profile DEFAULT"]
98
+
99
+ # Test with environment variables
100
+ try:
101
+ from mlflow import MlflowClient
102
+
103
+ client = MlflowClient()
104
+ client.search_experiments(max_results=1)
105
+
106
+ print(" ✓ Databricks token valid")
107
+ print()
108
+ return []
109
+
110
+ except Exception as e:
111
+ print(f" ✗ Token validation failed: {str(e)[:100]}")
112
+ print()
113
+ return [
114
+ "Check DATABRICKS_TOKEN is set correctly",
115
+ "Run: databricks auth login --host <workspace-url>",
116
+ ]
117
+
118
+
119
+ def check_mlflow_tracking():
120
+ """Test MLflow tracking server connectivity."""
121
+ print("Testing MLflow tracking server...")
122
+
123
+ # Use utility to validate env vars
124
+ errors = validate_env_vars()
125
+
126
+ if errors:
127
+ for error in errors:
128
+ print(f" ✗ {error}")
129
+ print()
130
+ return [f"Set environment variable: {error}" for error in errors]
131
+
132
+ tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
133
+ experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
134
+
135
+ try:
136
+ from mlflow import MlflowClient
137
+
138
+ client = MlflowClient()
139
+
140
+ # Test connectivity by getting experiment
141
+ experiment = client.get_experiment(experiment_id)
142
+
143
+ print(f" ✓ Connected to: {tracking_uri}")
144
+ print(f" ✓ Experiment: {experiment.name}")
145
+ print()
146
+ return []
147
+
148
+ except Exception as e:
149
+ error_msg = str(e)
150
+ print(f" ✗ Connection failed: {error_msg[:100]}")
151
+ print()
152
+
153
+ if "404" in error_msg or "not found" in error_msg.lower():
154
+ return [f"Experiment {experiment_id} not found - check MLFLOW_EXPERIMENT_ID"]
155
+ elif "401" in error_msg or "403" in error_msg or "authentication" in error_msg.lower():
156
+ return ["Authentication failed - check credentials"]
157
+ else:
158
+ return [f"Cannot connect to {tracking_uri} - check tracking URI and network"]
159
+
160
+
161
+ def check_llm_provider():
162
+ """Check LLM provider configuration (optional)."""
163
+ print("Checking LLM provider configuration...")
164
+
165
+ # Check for common LLM provider env vars
166
+ providers_found = []
167
+
168
+ if os.getenv("OPENAI_API_KEY"):
169
+ providers_found.append("OpenAI")
170
+
171
+ if os.getenv("ANTHROPIC_API_KEY"):
172
+ providers_found.append("Anthropic")
173
+
174
+ if os.getenv("DATABRICKS_TOKEN") or os.getenv("DATABRICKS_HOST"):
175
+ providers_found.append("Databricks")
176
+
177
+ if providers_found:
178
+ print(f" ✓ Found credentials for: {', '.join(providers_found)}")
179
+ print()
180
+ else:
181
+ print(" ⚠ No LLM provider credentials detected")
182
+ print(" This is OK if your agent uses Databricks profile auth")
183
+ print()
184
+
185
+ return [] # Warning only, not blocking
186
+
187
+
188
+ def main():
189
+ """Main validation workflow."""
190
+ print("=" * 60)
191
+ print("Authentication Validation")
192
+ print("=" * 60)
193
+ print()
194
+
195
+ all_issues = []
196
+
197
+ # Check 1: MLflow tracking
198
+ tracking_issues = check_mlflow_tracking()
199
+ all_issues.extend(tracking_issues)
200
+
201
+ # Check 2: Databricks auth (if using Databricks)
202
+ databricks_issues = check_databricks_auth()
203
+ all_issues.extend(databricks_issues)
204
+
205
+ # Check 3: LLM provider (optional check)
206
+ llm_issues = check_llm_provider()
207
+ all_issues.extend(llm_issues)
208
+
209
+ # Summary
210
+ print("=" * 60)
211
+ print("Validation Report")
212
+ print("=" * 60)
213
+ print()
214
+
215
+ if not all_issues:
216
+ print("✓ ALL AUTHENTICATION CHECKS PASSED")
217
+ print()
218
+ print("Your authentication is configured correctly.")
219
+ print()
220
+ print("Next steps:")
221
+ print(" 1. Integrate tracing: See references/tracing-integration.md")
222
+ print(" 2. Test runtime tracing: Edit and run scripts/validate_agent_tracing.py")
223
+ print()
224
+ else:
225
+ print(f"✗ Found {len(all_issues)} issue(s):")
226
+ print()
227
+ for i, issue in enumerate(all_issues, 1):
228
+ print(f" {i}. {issue}")
229
+ print()
230
+ print("=" * 60)
231
+ print("Fix the authentication issues above before proceeding.")
232
+ print("=" * 60)
233
+ print()
234
+ sys.exit(1)
235
+
236
+ print("=" * 60)
237
+
238
+
239
+ if __name__ == "__main__":
240
+ main()