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.
- package/LICENSE +21 -0
- package/NOTICE +108 -0
- package/README.md +134 -0
- package/canonical/HARVEST.yaml +858 -0
- package/canonical/PROVENANCE.yaml +740 -0
- package/canonical/agents/README.md +95 -0
- package/canonical/agents/agentic-architect.md +18 -0
- package/canonical/agents/database-reviewer.md +41 -0
- package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
- package/canonical/agents/pr-reviewer.md +96 -0
- package/canonical/agents/python-reviewer.md +55 -0
- package/canonical/agents/report-formatter.md +19 -0
- package/canonical/agents/security-reviewer.md +53 -0
- package/canonical/agents/test-writer.md +34 -0
- package/canonical/commands/fh-context.md +37 -0
- package/canonical/evals/promptfoo.redteam.yaml +108 -0
- package/canonical/hooks/cost-prices.json +14 -0
- package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
- package/canonical/hooks/freeharness-config-guard.mjs +162 -0
- package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
- package/canonical/hooks/freeharness-converge.mjs +227 -0
- package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
- package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
- package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
- package/canonical/hooks/freeharness-precompact.mjs +323 -0
- package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
- package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
- package/canonical/hooks/freeharness-session-start +583 -0
- package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
- package/canonical/hooks/hooks.claude-code.json +17 -0
- package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
- package/canonical/hooks/hooks.converge.claude-code.json +15 -0
- package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
- package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
- package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
- package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
- package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
- package/canonical/mcp/servers.json +20 -0
- package/canonical/openspec/config.base.yaml +89 -0
- package/canonical/openspec/schema.spec-driven.yaml +277 -0
- package/canonical/openspec/templates/data-contract.md +36 -0
- package/canonical/openspec/templates/design.md +84 -0
- package/canonical/openspec/templates/eval-plan.md +33 -0
- package/canonical/openspec/templates/follow-ups.md +2 -0
- package/canonical/openspec/templates/proposal.md +45 -0
- package/canonical/openspec/templates/spec.md +42 -0
- package/canonical/openspec/templates/tasks.md +38 -0
- package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
- package/canonical/profiles/local-llamacpp.json +27 -0
- package/canonical/profiles/local-ollama.json +20 -0
- package/canonical/profiles/mcp.json +91 -0
- package/canonical/rules/CLAUDE.md +78 -0
- package/canonical/rules/project-CLAUDE.template.md +62 -0
- package/canonical/rules/routing.md +20 -0
- package/canonical/rules/safety.md +41 -0
- package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
- package/canonical/skills/agent-evaluation/SKILL.md +102 -0
- package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
- package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
- package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
- package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
- package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
- package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
- package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
- package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
- package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
- package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
- package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
- package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
- package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
- package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
- package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
- package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
- package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
- package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
- package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
- package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
- package/canonical/skills/agentic-architecture/SKILL.md +41 -0
- package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
- package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
- package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
- package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
- package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
- package/canonical/skills/code-review/SKILL.md +52 -0
- package/canonical/skills/code-review/evals/cases.yaml +197 -0
- package/canonical/skills/git-workflow/SKILL.md +41 -0
- package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
- package/canonical/skills/local-code/SKILL.md +24 -0
- package/canonical/skills/local-code/evals/cases.yaml +85 -0
- package/canonical/skills/local-code/scripts/query_llama.py +68 -0
- package/canonical/skills/report-formatting/SKILL.md +62 -0
- package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
- package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
- package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
- package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
- package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
- package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
- package/canonical/skills/report-formatting/reference/authoring.md +66 -0
- package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
- package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
- package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
- package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
- package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
- package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
- package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
- package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
- package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
- package/canonical/skills/report-formatting/scripts/package.json +17 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
- package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
- package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
- package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
- package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
- package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
- package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
- package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
- package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
- package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
- package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
- package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
- package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
- package/canonical/skills/systematic-debugging/SKILL.md +44 -0
- package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
- package/canonical/skills/test-driven-development/SKILL.md +42 -0
- package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
- package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
- package/canonical/skills/verification-before-completion/SKILL.md +53 -0
- package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
- package/dist/adapters/content/language-lint.d.ts +46 -0
- package/dist/adapters/content/language-lint.js +191 -0
- package/dist/adapters/harness/claude-code.d.ts +57 -0
- package/dist/adapters/harness/claude-code.js +385 -0
- package/dist/adapters/harness/index.d.ts +3 -0
- package/dist/adapters/harness/index.js +17 -0
- package/dist/adapters/harness/opencode.d.ts +7 -0
- package/dist/adapters/harness/opencode.js +166 -0
- package/dist/adapters/harness/plugin.d.ts +22 -0
- package/dist/adapters/harness/plugin.js +257 -0
- package/dist/adapters/memory/doctor.d.ts +480 -0
- package/dist/adapters/memory/doctor.js +1217 -0
- package/dist/adapters/memory/vendored.d.ts +150 -0
- package/dist/adapters/memory/vendored.js +487 -0
- package/dist/adapters/package/node.d.ts +9 -0
- package/dist/adapters/package/node.js +20 -0
- package/dist/adapters/prompt/readline.d.ts +19 -0
- package/dist/adapters/prompt/readline.js +53 -0
- package/dist/adapters/sync/diff.d.ts +43 -0
- package/dist/adapters/sync/diff.js +380 -0
- package/dist/cli/cleanup.d.ts +86 -0
- package/dist/cli/cleanup.js +382 -0
- package/dist/cli/cost.d.ts +304 -0
- package/dist/cli/cost.js +501 -0
- package/dist/cli/doctor.d.ts +205 -0
- package/dist/cli/doctor.js +654 -0
- package/dist/cli/executor.d.ts +5 -0
- package/dist/cli/executor.js +48 -0
- package/dist/cli/plugin-validate.d.ts +37 -0
- package/dist/cli/plugin-validate.js +256 -0
- package/dist/cli/prefix.d.ts +68 -0
- package/dist/cli/prefix.js +218 -0
- package/dist/cli/profile.d.ts +170 -0
- package/dist/cli/profile.js +285 -0
- package/dist/cli/runner.d.ts +10 -0
- package/dist/cli/runner.js +27 -0
- package/dist/cli/uninstall.d.ts +65 -0
- package/dist/cli/uninstall.js +147 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +989 -0
- package/dist/infra/dogfood.d.ts +31 -0
- package/dist/infra/dogfood.js +51 -0
- package/dist/infra/fsutil.d.ts +40 -0
- package/dist/infra/fsutil.js +143 -0
- package/dist/infra/manifest.d.ts +76 -0
- package/dist/infra/manifest.js +92 -0
- package/dist/infra/paths.d.ts +19 -0
- package/dist/infra/paths.js +74 -0
- package/dist/infra/routing.d.ts +4 -0
- package/dist/infra/routing.js +7 -0
- package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/context.js +1 -0
- package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
- package/node_modules/@freeharness/core/dist/index.js +6 -0
- package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
- package/node_modules/@freeharness/core/dist/planner.js +18 -0
- package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
- package/node_modules/@freeharness/core/dist/ports.js +1 -0
- package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
- package/node_modules/@freeharness/core/dist/registry.js +124 -0
- package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/tiers.js +99 -0
- package/node_modules/@freeharness/core/package.json +34 -0
- package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
- package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
- package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
- package/node_modules/@freeharness/sdd/package.json +57 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
- package/package.json +70 -0
- package/provenance/canonical.PROVENANCE.yaml +740 -0
- package/provenance/claude-mem.LICENSE.upstream +202 -0
- package/provenance/memory.PROVENANCE.yaml +399 -0
- package/provenance/sdd.PROVENANCE.yaml +175 -0
- package/vendor-licenses/caveman.LICENSE +27 -0
- package/vendor-licenses/deepseek-harness.LICENSE +21 -0
- package/vendor-licenses/ecc.LICENSE +21 -0
- package/vendor-licenses/pi.LICENSE +21 -0
- package/vendor-licenses/superpowers.LICENSE +21 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate a template script for running agent evaluation.
|
|
3
|
+
|
|
4
|
+
This script creates a customized Python script that executes the agent
|
|
5
|
+
on an evaluation dataset and collects trace IDs for scoring.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python run_evaluation_template.py # Auto-detect everything
|
|
9
|
+
python run_evaluation_template.py --module my_agent.agent # Specify module
|
|
10
|
+
python run_evaluation_template.py --entry-point run_agent # Specify entry point
|
|
11
|
+
python run_evaluation_template.py --dataset-name my-dataset # Specify dataset
|
|
12
|
+
python run_evaluation_template.py --module my_agent --entry-point run_agent --dataset-name my-dataset
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import os
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
from utils import validate_env_vars
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def list_datasets() -> list[str]:
|
|
24
|
+
"""List available datasets in the experiment."""
|
|
25
|
+
try:
|
|
26
|
+
code = """
|
|
27
|
+
import os
|
|
28
|
+
from mlflow import MlflowClient
|
|
29
|
+
|
|
30
|
+
client = MlflowClient()
|
|
31
|
+
experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
|
|
32
|
+
|
|
33
|
+
datasets = client.search_datasets(experiment_ids=[experiment_id])
|
|
34
|
+
for dataset in datasets:
|
|
35
|
+
print(dataset.name)
|
|
36
|
+
"""
|
|
37
|
+
result = subprocess.run(["python", "-c", code], capture_output=True, text=True, check=True)
|
|
38
|
+
return [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
|
|
39
|
+
except Exception:
|
|
40
|
+
return []
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def generate_evaluation_code(
|
|
44
|
+
tracking_uri: str, experiment_id: str, dataset_name: str, agent_module: str, entry_point: str
|
|
45
|
+
) -> str:
|
|
46
|
+
"""Generate Python code for running evaluation."""
|
|
47
|
+
|
|
48
|
+
return f'''#!/usr/bin/env python3
|
|
49
|
+
"""
|
|
50
|
+
Run agent on evaluation dataset and collect traces.
|
|
51
|
+
|
|
52
|
+
Generated by run_evaluation_template.py
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
import os
|
|
56
|
+
import sys
|
|
57
|
+
import mlflow
|
|
58
|
+
from mlflow.genai.datasets import get_dataset
|
|
59
|
+
|
|
60
|
+
# Set environment variables
|
|
61
|
+
os.environ["MLFLOW_TRACKING_URI"] = "{tracking_uri}"
|
|
62
|
+
os.environ["MLFLOW_EXPERIMENT_ID"] = "{experiment_id}"
|
|
63
|
+
|
|
64
|
+
# Import agent
|
|
65
|
+
from {agent_module} import {entry_point}
|
|
66
|
+
|
|
67
|
+
# Configuration
|
|
68
|
+
DATASET_NAME = "{dataset_name}"
|
|
69
|
+
|
|
70
|
+
print("=" * 60)
|
|
71
|
+
print("Running Agent on Evaluation Dataset")
|
|
72
|
+
print("=" * 60)
|
|
73
|
+
print()
|
|
74
|
+
|
|
75
|
+
# Load dataset
|
|
76
|
+
# IMPORTANT: Do not modify this section. It uses the official MLflow API.
|
|
77
|
+
# Spark or databricks-sdk approaches are NOT recommended.
|
|
78
|
+
print("Loading evaluation dataset...")
|
|
79
|
+
try:
|
|
80
|
+
dataset = get_dataset(DATASET_NAME)
|
|
81
|
+
df = dataset.to_df()
|
|
82
|
+
print(f" Dataset: {{DATASET_NAME}}")
|
|
83
|
+
print(f" Total queries: {{len(df)}}")
|
|
84
|
+
print()
|
|
85
|
+
except Exception as e:
|
|
86
|
+
print(f"✗ Failed to load dataset: {{e}}")
|
|
87
|
+
print()
|
|
88
|
+
print("Common issues:")
|
|
89
|
+
print(" 1. Dataset name incorrect - check with: mlflow datasets list")
|
|
90
|
+
print(" 2. Not authenticated - run: databricks auth login")
|
|
91
|
+
print(" 3. Wrong experiment - verify MLFLOW_EXPERIMENT_ID")
|
|
92
|
+
sys.exit(1)
|
|
93
|
+
|
|
94
|
+
# TODO: Configure your agent's LLM provider or other dependencies here
|
|
95
|
+
# Example:
|
|
96
|
+
# from your_agent.llm import LLMConfig, LLMProvider
|
|
97
|
+
# llm_config = LLMConfig(model="gpt-4", temperature=0.0)
|
|
98
|
+
# llm_provider = LLMProvider(config=llm_config)
|
|
99
|
+
|
|
100
|
+
print("⚠ IMPORTANT: Configure your agent's dependencies above before running!")
|
|
101
|
+
print(" Update the TODO section with your agent's setup code")
|
|
102
|
+
print()
|
|
103
|
+
|
|
104
|
+
# Run agent on each query
|
|
105
|
+
trace_ids = []
|
|
106
|
+
successful = 0
|
|
107
|
+
failed = 0
|
|
108
|
+
|
|
109
|
+
print("Running agent on dataset queries...")
|
|
110
|
+
print()
|
|
111
|
+
|
|
112
|
+
for index, row in df.iterrows():
|
|
113
|
+
inputs = row['inputs']
|
|
114
|
+
|
|
115
|
+
# Extract query from inputs
|
|
116
|
+
query = inputs.get('query', inputs.get('question', str(inputs)))
|
|
117
|
+
|
|
118
|
+
print(f"[{{index + 1}}/{{len(df)}}] Query: {{query[:80]}}{{'...' if len(query) > 80 else ''}}")
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
# TODO: Adjust the function call to match your agent's signature
|
|
122
|
+
# Examples:
|
|
123
|
+
# response = {entry_point}(query, llm_provider)
|
|
124
|
+
# response = {entry_point}(query)
|
|
125
|
+
# response = {entry_point}(**inputs)
|
|
126
|
+
|
|
127
|
+
response = {entry_point}(query) # <-- UPDATE THIS LINE
|
|
128
|
+
|
|
129
|
+
# Capture trace ID
|
|
130
|
+
trace_id = mlflow.get_last_active_trace_id()
|
|
131
|
+
|
|
132
|
+
if trace_id:
|
|
133
|
+
trace_ids.append(trace_id)
|
|
134
|
+
successful += 1
|
|
135
|
+
print(f" ✓ Success (trace: {{trace_id}})")
|
|
136
|
+
else:
|
|
137
|
+
print(f" ✗ No trace captured")
|
|
138
|
+
failed += 1
|
|
139
|
+
|
|
140
|
+
except Exception as e:
|
|
141
|
+
print(f" ✗ Error: {{str(e)[:100]}}")
|
|
142
|
+
failed += 1
|
|
143
|
+
|
|
144
|
+
print()
|
|
145
|
+
|
|
146
|
+
# Summary
|
|
147
|
+
print("=" * 60)
|
|
148
|
+
print("Execution Summary")
|
|
149
|
+
print("=" * 60)
|
|
150
|
+
print(f" Total queries: {{len(df)}}")
|
|
151
|
+
print(f" Successful: {{successful}}")
|
|
152
|
+
print(f" Failed: {{failed}}")
|
|
153
|
+
print(f" Traces collected: {{len(trace_ids)}}")
|
|
154
|
+
print()
|
|
155
|
+
|
|
156
|
+
# Save trace IDs
|
|
157
|
+
if trace_ids:
|
|
158
|
+
traces_file = "evaluation_trace_ids.txt"
|
|
159
|
+
with open(traces_file, 'w') as f:
|
|
160
|
+
f.write(','.join(trace_ids))
|
|
161
|
+
|
|
162
|
+
print(f"Trace IDs saved to: {{traces_file}}")
|
|
163
|
+
print()
|
|
164
|
+
|
|
165
|
+
# Print evaluation command
|
|
166
|
+
print("=" * 60)
|
|
167
|
+
print("Next Step: Evaluate Traces with Scorers")
|
|
168
|
+
print("=" * 60)
|
|
169
|
+
print()
|
|
170
|
+
print("Run the following command to evaluate all traces:")
|
|
171
|
+
print()
|
|
172
|
+
print(f" mlflow traces evaluate \\\\")
|
|
173
|
+
print(f" --trace-ids {{','.join(trace_ids[:3])}}{{',...' if len(trace_ids) > 3 else ''}} \\\\")
|
|
174
|
+
print(f" --scorers <scorer1>,<scorer2>,... \\\\")
|
|
175
|
+
print(f" --output json")
|
|
176
|
+
print()
|
|
177
|
+
print("Replace <scorer1>,<scorer2>,... with your registered scorers")
|
|
178
|
+
print(" Example: RelevanceToQuery,Completeness,ToolUsageAppropriate")
|
|
179
|
+
print()
|
|
180
|
+
else:
|
|
181
|
+
print("✗ No traces were collected. Please check for errors above.")
|
|
182
|
+
print()
|
|
183
|
+
|
|
184
|
+
print("=" * 60)
|
|
185
|
+
'''
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def main():
|
|
189
|
+
"""Main workflow."""
|
|
190
|
+
# Parse command-line arguments
|
|
191
|
+
parser = argparse.ArgumentParser(
|
|
192
|
+
description="Generate evaluation execution template script",
|
|
193
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
194
|
+
)
|
|
195
|
+
parser.add_argument("--module", help="Agent module name (e.g., 'my_agent.agent')")
|
|
196
|
+
parser.add_argument("--entry-point", help="Entry point function name (e.g., 'run_agent')")
|
|
197
|
+
parser.add_argument("--dataset-name", help="Dataset name to use")
|
|
198
|
+
parser.add_argument("--output", default="run_agent_evaluation.py", help="Output file name")
|
|
199
|
+
args = parser.parse_args()
|
|
200
|
+
|
|
201
|
+
print("=" * 60)
|
|
202
|
+
print("MLflow Evaluation Execution Template Generator")
|
|
203
|
+
print("=" * 60)
|
|
204
|
+
print()
|
|
205
|
+
|
|
206
|
+
# Check environment
|
|
207
|
+
errors = validate_env_vars()
|
|
208
|
+
if errors:
|
|
209
|
+
print("✗ Environment validation failed:")
|
|
210
|
+
for error in errors:
|
|
211
|
+
print(f" - {error}")
|
|
212
|
+
print("\nRun scripts/setup_mlflow.py first")
|
|
213
|
+
sys.exit(1)
|
|
214
|
+
|
|
215
|
+
tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
|
|
216
|
+
experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
|
|
217
|
+
|
|
218
|
+
print(f"Tracking URI: {tracking_uri}")
|
|
219
|
+
print(f"Experiment ID: {experiment_id}")
|
|
220
|
+
print()
|
|
221
|
+
|
|
222
|
+
# Get agent module (must be specified manually)
|
|
223
|
+
print("Agent module configuration...")
|
|
224
|
+
agent_module = args.module
|
|
225
|
+
if not agent_module:
|
|
226
|
+
print(" ✗ Agent module not specified")
|
|
227
|
+
print(" Use --module to specify your agent module")
|
|
228
|
+
print(" Example: --module my_agent.agent")
|
|
229
|
+
print("\n To find your agent module:")
|
|
230
|
+
print(" grep -r 'def.*agent' . --include='*.py'")
|
|
231
|
+
sys.exit(1)
|
|
232
|
+
else:
|
|
233
|
+
print(f" ✓ Using specified: {agent_module}")
|
|
234
|
+
|
|
235
|
+
# Get entry point (must be specified manually)
|
|
236
|
+
print("\nEntry point configuration...")
|
|
237
|
+
entry_point = args.entry_point
|
|
238
|
+
if not entry_point:
|
|
239
|
+
print(" ✗ Entry point not specified")
|
|
240
|
+
print(" Use --entry-point to specify your agent's main function")
|
|
241
|
+
print(" Example: --entry-point run_agent")
|
|
242
|
+
print("\n To find entry points with @mlflow.trace:")
|
|
243
|
+
print(" grep -r '@mlflow.trace' . --include='*.py'")
|
|
244
|
+
sys.exit(1)
|
|
245
|
+
else:
|
|
246
|
+
print(f" ✓ Using specified: {entry_point}")
|
|
247
|
+
|
|
248
|
+
# Get dataset name
|
|
249
|
+
print("\nFetching available datasets...")
|
|
250
|
+
dataset_name = args.dataset_name
|
|
251
|
+
if not dataset_name:
|
|
252
|
+
datasets = list_datasets()
|
|
253
|
+
|
|
254
|
+
if datasets:
|
|
255
|
+
print(f"\n✓ Found {len(datasets)} dataset(s):")
|
|
256
|
+
for i, name in enumerate(datasets, 1):
|
|
257
|
+
print(f" {i}. {name}")
|
|
258
|
+
|
|
259
|
+
# Auto-select first dataset
|
|
260
|
+
dataset_name = datasets[0]
|
|
261
|
+
print(f"\n✓ Auto-selected: {dataset_name}")
|
|
262
|
+
print(" (Use --dataset-name to specify a different dataset)")
|
|
263
|
+
else:
|
|
264
|
+
print(" ✗ No datasets found")
|
|
265
|
+
print(" Please create a dataset first or specify with --dataset-name")
|
|
266
|
+
sys.exit(1)
|
|
267
|
+
else:
|
|
268
|
+
print(f" ✓ Using specified: {dataset_name}")
|
|
269
|
+
|
|
270
|
+
# Generate code
|
|
271
|
+
print("\n" + "=" * 60)
|
|
272
|
+
print("Generating Evaluation Execution Script")
|
|
273
|
+
print("=" * 60)
|
|
274
|
+
|
|
275
|
+
code = generate_evaluation_code(
|
|
276
|
+
tracking_uri, experiment_id, dataset_name, agent_module, entry_point
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Write to file
|
|
280
|
+
output_file = args.output
|
|
281
|
+
with open(output_file, "w") as f:
|
|
282
|
+
f.write(code)
|
|
283
|
+
|
|
284
|
+
print(f"\n✓ Script generated: {output_file}")
|
|
285
|
+
print()
|
|
286
|
+
|
|
287
|
+
# Make executable
|
|
288
|
+
try:
|
|
289
|
+
os.chmod(output_file, 0o755)
|
|
290
|
+
print(f"✓ Made executable: chmod +x {output_file}")
|
|
291
|
+
except Exception:
|
|
292
|
+
pass
|
|
293
|
+
|
|
294
|
+
print()
|
|
295
|
+
print("=" * 60)
|
|
296
|
+
print("Next Steps")
|
|
297
|
+
print("=" * 60)
|
|
298
|
+
print()
|
|
299
|
+
print(f"1. Review the generated script: {output_file}")
|
|
300
|
+
print("2. Update the TODO sections with your agent's setup code")
|
|
301
|
+
print("3. Update the agent call to match your signature")
|
|
302
|
+
print(f"4. Execute it: python {output_file}")
|
|
303
|
+
print("5. Use the trace IDs to run evaluation with scorers")
|
|
304
|
+
print()
|
|
305
|
+
print("=" * 60)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
if __name__ == "__main__":
|
|
309
|
+
main()
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MLflow environment setup script with auto-detection and convenience features.
|
|
3
|
+
|
|
4
|
+
This script configures MLFLOW_TRACKING_URI and MLFLOW_EXPERIMENT_ID
|
|
5
|
+
for agent evaluation using auto-detection with optional overrides.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Auto-detects Databricks profiles or local SQLite
|
|
9
|
+
- Search experiments by name (post-processes `mlflow experiments list` output)
|
|
10
|
+
- Single command instead of multiple CLI calls
|
|
11
|
+
- Creates experiments if they don't exist
|
|
12
|
+
|
|
13
|
+
Note: Uses MLflow CLI commands underneath (`mlflow experiments list`, `mlflow experiments create`).
|
|
14
|
+
For direct CLI usage, see MLflow documentation.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import os
|
|
19
|
+
import subprocess
|
|
20
|
+
import sys
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def parse_arguments():
|
|
25
|
+
"""Parse command-line arguments."""
|
|
26
|
+
parser = argparse.ArgumentParser(
|
|
27
|
+
description="Configure MLflow for agent evaluation with auto-detection"
|
|
28
|
+
)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--tracking-uri",
|
|
31
|
+
help="MLflow tracking URI (default: auto-detect from env/Databricks/local)",
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument("--experiment-id", help="Experiment ID to use (default: from env or search)")
|
|
34
|
+
parser.add_argument("--experiment-name", help="Experiment name (for search or creation)")
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--create", action="store_true", help="Create new experiment with --experiment-name"
|
|
37
|
+
)
|
|
38
|
+
return parser.parse_args()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def check_mlflow_installed() -> bool:
|
|
42
|
+
"""Check if MLflow >=3.6.0 is installed."""
|
|
43
|
+
try:
|
|
44
|
+
result = subprocess.run(["mlflow", "--version"], capture_output=True, text=True, check=True)
|
|
45
|
+
version = result.stdout.strip().split()[-1]
|
|
46
|
+
print(f"✓ MLflow {version} is installed")
|
|
47
|
+
return True
|
|
48
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
49
|
+
print("✗ MLflow is not installed")
|
|
50
|
+
print(" Install with: uv pip install mlflow")
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def detect_databricks_profiles() -> list[str]:
|
|
55
|
+
"""Detect available Databricks profiles."""
|
|
56
|
+
try:
|
|
57
|
+
result = subprocess.run(
|
|
58
|
+
["databricks", "auth", "profiles"], capture_output=True, text=True, check=True
|
|
59
|
+
)
|
|
60
|
+
lines = result.stdout.strip().split("\n")
|
|
61
|
+
# Skip first line (header: "Name Host Valid")
|
|
62
|
+
# and filter empty lines
|
|
63
|
+
return [line.strip() for line in lines[1:] if line.strip()]
|
|
64
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
65
|
+
return []
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def check_databricks_auth(profile: str) -> bool:
|
|
69
|
+
"""Check if a Databricks profile is authenticated."""
|
|
70
|
+
try:
|
|
71
|
+
# Try a simple API call to check auth
|
|
72
|
+
result = subprocess.run(
|
|
73
|
+
["databricks", "auth", "env", "-p", profile], capture_output=True, text=True, check=True
|
|
74
|
+
)
|
|
75
|
+
return "DATABRICKS_TOKEN" in result.stdout or "DATABRICKS_HOST" in result.stdout
|
|
76
|
+
except subprocess.CalledProcessError:
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def start_local_mlflow_server(port: int = 5050) -> bool:
|
|
81
|
+
"""Start local MLflow server in the background."""
|
|
82
|
+
print(f"\nStarting local MLflow server on port {port}...")
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
# Create mlruns directory if it doesn't exist
|
|
86
|
+
Path("./mlruns").mkdir(exist_ok=True)
|
|
87
|
+
|
|
88
|
+
# Start server in background
|
|
89
|
+
cmd = [
|
|
90
|
+
"mlflow",
|
|
91
|
+
"server",
|
|
92
|
+
"--port",
|
|
93
|
+
str(port),
|
|
94
|
+
"--backend-store-uri",
|
|
95
|
+
"sqlite:///mlflow.db",
|
|
96
|
+
"--default-artifact-root",
|
|
97
|
+
"./mlruns",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
print(f" Command: {' '.join(cmd)}")
|
|
101
|
+
print(" Running in background...")
|
|
102
|
+
|
|
103
|
+
# Note: In production, you might want to use nohup or subprocess.Popen with proper detachment
|
|
104
|
+
print("\n To start the server manually, run:")
|
|
105
|
+
print(f" {' '.join(cmd)} &")
|
|
106
|
+
print(f"\n Server will be available at: http://127.0.0.1:{port}")
|
|
107
|
+
|
|
108
|
+
return True
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print(f"✗ Error starting server: {e}")
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def auto_detect_tracking_uri() -> str:
|
|
115
|
+
"""Auto-detect best tracking URI.
|
|
116
|
+
|
|
117
|
+
Priority:
|
|
118
|
+
1. Existing MLFLOW_TRACKING_URI environment variable
|
|
119
|
+
2. DEFAULT Databricks profile
|
|
120
|
+
3. First available Databricks profile
|
|
121
|
+
4. Local SQLite (sqlite:///mlflow.db)
|
|
122
|
+
"""
|
|
123
|
+
# Priority 1: Use existing MLFLOW_TRACKING_URI if set
|
|
124
|
+
existing = os.getenv("MLFLOW_TRACKING_URI")
|
|
125
|
+
if existing:
|
|
126
|
+
print(f"✓ Using existing MLFLOW_TRACKING_URI: {existing}")
|
|
127
|
+
return existing
|
|
128
|
+
|
|
129
|
+
# Priority 2: Try DEFAULT Databricks profile
|
|
130
|
+
profiles = detect_databricks_profiles()
|
|
131
|
+
if profiles:
|
|
132
|
+
# Look for DEFAULT profile
|
|
133
|
+
if "DEFAULT" in profiles:
|
|
134
|
+
uri = "databricks://DEFAULT"
|
|
135
|
+
print(f"✓ Auto-detected Databricks profile: {uri}")
|
|
136
|
+
return uri
|
|
137
|
+
|
|
138
|
+
# Fallback to first profile
|
|
139
|
+
first_profile = profiles[0]
|
|
140
|
+
uri = f"databricks://{first_profile}"
|
|
141
|
+
print(f"✓ Auto-detected Databricks profile: {uri}")
|
|
142
|
+
return uri
|
|
143
|
+
|
|
144
|
+
# Priority 3: Fallback to local SQLite
|
|
145
|
+
uri = "sqlite:///mlflow.db"
|
|
146
|
+
print(f"✓ Auto-detected tracking URI: {uri}")
|
|
147
|
+
print(" (No Databricks profiles found, using local SQLite)")
|
|
148
|
+
return uri
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def configure_tracking_uri(args_uri: str | None = None) -> str:
|
|
152
|
+
"""Configure MLFLOW_TRACKING_URI with auto-detection.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
args_uri: Tracking URI from CLI arguments (optional)
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
Tracking URI to use
|
|
159
|
+
"""
|
|
160
|
+
print("\n" + "=" * 60)
|
|
161
|
+
print("Step 1: Configure MLFLOW_TRACKING_URI")
|
|
162
|
+
print("=" * 60)
|
|
163
|
+
print()
|
|
164
|
+
|
|
165
|
+
# If URI provided via CLI, use it
|
|
166
|
+
if args_uri:
|
|
167
|
+
print(f"✓ Using specified tracking URI: {args_uri}")
|
|
168
|
+
return args_uri
|
|
169
|
+
|
|
170
|
+
# Otherwise auto-detect
|
|
171
|
+
return auto_detect_tracking_uri()
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def list_experiments(tracking_uri: str) -> list[dict]:
|
|
175
|
+
"""List available experiments."""
|
|
176
|
+
try:
|
|
177
|
+
env = os.environ.copy()
|
|
178
|
+
env["MLFLOW_TRACKING_URI"] = tracking_uri
|
|
179
|
+
|
|
180
|
+
result = subprocess.run(
|
|
181
|
+
["mlflow", "experiments", "list"], capture_output=True, text=True, check=True, env=env
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
# Parse output (simplified)
|
|
185
|
+
lines = result.stdout.strip().split("\n")
|
|
186
|
+
experiments = []
|
|
187
|
+
|
|
188
|
+
for line in lines[2:]: # Skip header
|
|
189
|
+
if line.strip():
|
|
190
|
+
parts = [p.strip() for p in line.split("|") if p.strip()]
|
|
191
|
+
if len(parts) >= 2:
|
|
192
|
+
exp_id = parts[0]
|
|
193
|
+
name = parts[1]
|
|
194
|
+
experiments.append({"id": exp_id, "name": name})
|
|
195
|
+
|
|
196
|
+
return experiments
|
|
197
|
+
except Exception as e:
|
|
198
|
+
print(f"✗ Error listing experiments: {e}")
|
|
199
|
+
return []
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def create_experiment(tracking_uri: str, name: str) -> str | None:
|
|
203
|
+
"""Create a new experiment."""
|
|
204
|
+
try:
|
|
205
|
+
env = os.environ.copy()
|
|
206
|
+
env["MLFLOW_TRACKING_URI"] = tracking_uri
|
|
207
|
+
|
|
208
|
+
result = subprocess.run(
|
|
209
|
+
["mlflow", "experiments", "create", "-n", name],
|
|
210
|
+
capture_output=True,
|
|
211
|
+
text=True,
|
|
212
|
+
check=True,
|
|
213
|
+
env=env,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
# Extract experiment ID from output
|
|
217
|
+
for line in result.stdout.split("\n"):
|
|
218
|
+
if "Experiment" in line and "created" in line:
|
|
219
|
+
# Try to extract ID
|
|
220
|
+
words = line.split()
|
|
221
|
+
for i, word in enumerate(words):
|
|
222
|
+
if word.lower() == "id" and i + 1 < len(words):
|
|
223
|
+
return words[i + 1].strip()
|
|
224
|
+
|
|
225
|
+
# If can't parse, return None (but experiment was created)
|
|
226
|
+
return None
|
|
227
|
+
except subprocess.CalledProcessError as e:
|
|
228
|
+
print(f"✗ Error creating experiment: {e.stderr}")
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def configure_experiment_id(
|
|
233
|
+
tracking_uri: str,
|
|
234
|
+
args_exp_id: str | None = None,
|
|
235
|
+
args_exp_name: str | None = None,
|
|
236
|
+
create_new: bool = False,
|
|
237
|
+
) -> str:
|
|
238
|
+
"""Configure MLFLOW_EXPERIMENT_ID with auto-detection.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
tracking_uri: MLflow tracking URI
|
|
242
|
+
args_exp_id: Experiment ID from CLI arguments (optional)
|
|
243
|
+
args_exp_name: Experiment name from CLI arguments (optional)
|
|
244
|
+
create_new: Create new experiment with args_exp_name if not found
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Experiment ID to use
|
|
248
|
+
"""
|
|
249
|
+
print("\n" + "=" * 60)
|
|
250
|
+
print("Step 2: Configure MLFLOW_EXPERIMENT_ID")
|
|
251
|
+
print("=" * 60)
|
|
252
|
+
print()
|
|
253
|
+
|
|
254
|
+
# Priority 1: Use experiment ID from CLI args
|
|
255
|
+
if args_exp_id:
|
|
256
|
+
print(f"✓ Using specified experiment ID: {args_exp_id}")
|
|
257
|
+
return args_exp_id
|
|
258
|
+
|
|
259
|
+
# Priority 2: Use existing MLFLOW_EXPERIMENT_ID from environment
|
|
260
|
+
existing = os.getenv("MLFLOW_EXPERIMENT_ID")
|
|
261
|
+
if existing and not args_exp_name:
|
|
262
|
+
# Only use existing if not explicitly searching for a different experiment
|
|
263
|
+
print(f"✓ Using existing MLFLOW_EXPERIMENT_ID: {existing}")
|
|
264
|
+
return existing
|
|
265
|
+
|
|
266
|
+
# Priority 3: Create new experiment if --create and --experiment-name provided
|
|
267
|
+
if create_new and args_exp_name:
|
|
268
|
+
print(f"✓ Creating experiment: {args_exp_name}")
|
|
269
|
+
exp_id = create_experiment(tracking_uri, args_exp_name)
|
|
270
|
+
if exp_id:
|
|
271
|
+
print(f"✓ Experiment created with ID: {exp_id}")
|
|
272
|
+
return exp_id
|
|
273
|
+
else:
|
|
274
|
+
# Try to find it by name (might have been created but ID not parsed)
|
|
275
|
+
experiments = list_experiments(tracking_uri)
|
|
276
|
+
for exp in experiments:
|
|
277
|
+
if exp["name"] == args_exp_name:
|
|
278
|
+
print(f"✓ Found experiment ID: {exp['id']}")
|
|
279
|
+
return exp["id"]
|
|
280
|
+
print(f"✗ Failed to create or find experiment '{args_exp_name}'")
|
|
281
|
+
sys.exit(1)
|
|
282
|
+
|
|
283
|
+
# Priority 4: Search for experiment by name if provided
|
|
284
|
+
if args_exp_name:
|
|
285
|
+
print(f"✓ Searching for experiment: {args_exp_name}")
|
|
286
|
+
experiments = list_experiments(tracking_uri)
|
|
287
|
+
for exp in experiments:
|
|
288
|
+
if exp["name"] == args_exp_name:
|
|
289
|
+
print(f"✓ Found experiment ID: {exp['id']}")
|
|
290
|
+
return exp["id"]
|
|
291
|
+
|
|
292
|
+
# Not found - fail with clear message
|
|
293
|
+
print(f"✗ Experiment '{args_exp_name}' not found")
|
|
294
|
+
print(" Use --create flag to create it: --experiment-name '{args_exp_name}' --create")
|
|
295
|
+
sys.exit(1)
|
|
296
|
+
|
|
297
|
+
# Priority 5: Auto-select first available experiment
|
|
298
|
+
print("Auto-detecting experiment...")
|
|
299
|
+
experiments = list_experiments(tracking_uri)
|
|
300
|
+
|
|
301
|
+
if experiments:
|
|
302
|
+
# Use first experiment
|
|
303
|
+
exp = experiments[0]
|
|
304
|
+
print(f"✓ Auto-selected experiment: {exp['name']} (ID: {exp['id']})")
|
|
305
|
+
if len(experiments) > 1:
|
|
306
|
+
print(f" ({len(experiments) - 1} other experiment(s) available)")
|
|
307
|
+
return exp["id"]
|
|
308
|
+
|
|
309
|
+
# No experiments found - fail with clear message
|
|
310
|
+
print("✗ No experiments found")
|
|
311
|
+
print(" Create one with: --experiment-name <name> --create")
|
|
312
|
+
sys.exit(1)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def main():
|
|
316
|
+
"""Main setup flow with auto-detection."""
|
|
317
|
+
# Parse command-line arguments
|
|
318
|
+
args = parse_arguments()
|
|
319
|
+
|
|
320
|
+
print("=" * 60)
|
|
321
|
+
print("MLflow Environment Setup for Agent Evaluation")
|
|
322
|
+
print("=" * 60)
|
|
323
|
+
|
|
324
|
+
# Check MLflow installation
|
|
325
|
+
if not check_mlflow_installed():
|
|
326
|
+
sys.exit(1)
|
|
327
|
+
|
|
328
|
+
print()
|
|
329
|
+
|
|
330
|
+
# Configure tracking URI (auto-detects if not provided)
|
|
331
|
+
tracking_uri = configure_tracking_uri(args.tracking_uri)
|
|
332
|
+
|
|
333
|
+
# Configure experiment ID (auto-detects if not provided)
|
|
334
|
+
experiment_id = configure_experiment_id(
|
|
335
|
+
tracking_uri, args.experiment_id, args.experiment_name, args.create
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
# Summary
|
|
339
|
+
print("\n" + "=" * 60)
|
|
340
|
+
print("Setup Complete!")
|
|
341
|
+
print("=" * 60)
|
|
342
|
+
print()
|
|
343
|
+
print("Export these environment variables:")
|
|
344
|
+
print()
|
|
345
|
+
print(f'export MLFLOW_TRACKING_URI="{tracking_uri}"')
|
|
346
|
+
print(f'export MLFLOW_EXPERIMENT_ID="{experiment_id}"')
|
|
347
|
+
print()
|
|
348
|
+
print("Or add them to your shell configuration (~/.bashrc, ~/.zshrc, etc.)")
|
|
349
|
+
print("=" * 60)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
if __name__ == "__main__":
|
|
353
|
+
main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Shared utilities for agent evaluation scripts."""
|
|
2
|
+
|
|
3
|
+
from .env_validation import (
|
|
4
|
+
check_databricks_config,
|
|
5
|
+
get_env_vars,
|
|
6
|
+
test_mlflow_connection,
|
|
7
|
+
validate_env_vars,
|
|
8
|
+
validate_mlflow_version,
|
|
9
|
+
)
|
|
10
|
+
from .tracing_utils import (
|
|
11
|
+
check_import_order,
|
|
12
|
+
check_session_id_capture,
|
|
13
|
+
verify_mlflow_imports,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
# env_validation
|
|
18
|
+
"check_databricks_config",
|
|
19
|
+
"get_env_vars",
|
|
20
|
+
"test_mlflow_connection",
|
|
21
|
+
"validate_env_vars",
|
|
22
|
+
"validate_mlflow_version",
|
|
23
|
+
# tracing_utils (for validation scripts)
|
|
24
|
+
"check_import_order",
|
|
25
|
+
"check_session_id_capture",
|
|
26
|
+
"verify_mlflow_imports",
|
|
27
|
+
]
|