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,382 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generate a template script for creating MLflow evaluation datasets.
|
|
3
|
+
|
|
4
|
+
This script creates a customized Python script for dataset creation,
|
|
5
|
+
handling both OSS MLflow and Databricks Unity Catalog scenarios.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
# Minimum required
|
|
9
|
+
python create_dataset_template.py --test-cases-file test_cases.txt
|
|
10
|
+
|
|
11
|
+
# With custom dataset name
|
|
12
|
+
python create_dataset_template.py --test-cases-file test_cases.txt --dataset-name my-eval
|
|
13
|
+
|
|
14
|
+
# For Databricks Unity Catalog
|
|
15
|
+
python create_dataset_template.py --test-cases-file test_cases.txt \\
|
|
16
|
+
--catalog main --schema ml --table eval_v1
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import datetime
|
|
21
|
+
import os
|
|
22
|
+
import subprocess
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
from utils import check_databricks_config, validate_env_vars
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def parse_arguments():
|
|
29
|
+
"""Parse command-line arguments."""
|
|
30
|
+
parser = argparse.ArgumentParser(description="Generate dataset creation script")
|
|
31
|
+
parser.add_argument(
|
|
32
|
+
"--test-cases-file",
|
|
33
|
+
required=True,
|
|
34
|
+
help="File with test cases (one per line, minimum 10)",
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"--dataset-name",
|
|
38
|
+
help="Dataset name (auto-generated if not provided)",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument("--catalog", help="UC catalog name (for Databricks)")
|
|
41
|
+
parser.add_argument("--schema", help="UC schema name (for Databricks)")
|
|
42
|
+
parser.add_argument("--table", help="UC table name (for Databricks)")
|
|
43
|
+
parser.add_argument("--output", default="create_evaluation_dataset.py", help="Output file name")
|
|
44
|
+
return parser.parse_args()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def load_test_cases_from_file(file_path: str) -> list[str]:
|
|
48
|
+
"""Load test cases from file (one per line)."""
|
|
49
|
+
try:
|
|
50
|
+
with open(file_path) as f:
|
|
51
|
+
test_cases = [line.strip() for line in f if line.strip()]
|
|
52
|
+
|
|
53
|
+
if len(test_cases) < 10:
|
|
54
|
+
print(f"✗ File has only {len(test_cases)} test cases (minimum: 10)")
|
|
55
|
+
print(" Please add more test cases to the file")
|
|
56
|
+
sys.exit(1)
|
|
57
|
+
|
|
58
|
+
print(f"✓ Loaded {len(test_cases)} test cases from {file_path}")
|
|
59
|
+
return test_cases
|
|
60
|
+
|
|
61
|
+
except FileNotFoundError:
|
|
62
|
+
print(f"✗ File not found: {file_path}")
|
|
63
|
+
sys.exit(1)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
print(f"✗ Error reading file: {e}")
|
|
66
|
+
sys.exit(1)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_uc_catalogs():
|
|
70
|
+
"""Get available Unity Catalog catalogs."""
|
|
71
|
+
try:
|
|
72
|
+
code = """
|
|
73
|
+
from databricks import sdk
|
|
74
|
+
w = sdk.WorkspaceClient()
|
|
75
|
+
catalogs = w.catalogs.list()
|
|
76
|
+
for catalog in catalogs:
|
|
77
|
+
print(catalog.name)
|
|
78
|
+
"""
|
|
79
|
+
result = subprocess.run(["python", "-c", code], capture_output=True, text=True, check=True)
|
|
80
|
+
return [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
|
|
81
|
+
except Exception:
|
|
82
|
+
return []
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def get_uc_schemas(catalog: str):
|
|
86
|
+
"""Get available schemas in a catalog."""
|
|
87
|
+
try:
|
|
88
|
+
code = f"""
|
|
89
|
+
from databricks import sdk
|
|
90
|
+
w = sdk.WorkspaceClient()
|
|
91
|
+
schemas = w.schemas.list(catalog_name='{catalog}')
|
|
92
|
+
for schema in schemas:
|
|
93
|
+
print(schema.name)
|
|
94
|
+
"""
|
|
95
|
+
result = subprocess.run(["python", "-c", code], capture_output=True, text=True, check=True)
|
|
96
|
+
return [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
|
|
97
|
+
except Exception:
|
|
98
|
+
return []
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def generate_dataset_creation_code(
|
|
102
|
+
tracking_uri: str,
|
|
103
|
+
experiment_id: str,
|
|
104
|
+
dataset_name: str,
|
|
105
|
+
test_cases: list[str],
|
|
106
|
+
catalog: str = None,
|
|
107
|
+
schema: str = None,
|
|
108
|
+
table: str = None,
|
|
109
|
+
) -> str:
|
|
110
|
+
"""Generate Python code for creating the dataset."""
|
|
111
|
+
|
|
112
|
+
# Escape test cases for Python code
|
|
113
|
+
test_cases_repr = repr(test_cases)
|
|
114
|
+
|
|
115
|
+
if catalog and schema and table:
|
|
116
|
+
# Databricks Unity Catalog version
|
|
117
|
+
uc_name = f"{catalog}.{schema}.{table}"
|
|
118
|
+
return f'''#!/usr/bin/env python3
|
|
119
|
+
"""
|
|
120
|
+
Create MLflow evaluation dataset.
|
|
121
|
+
|
|
122
|
+
Generated by create_dataset_template.py
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
import mlflow
|
|
126
|
+
from mlflow.genai.datasets import create_dataset
|
|
127
|
+
|
|
128
|
+
# Set tracking URI
|
|
129
|
+
mlflow.set_tracking_uri("{tracking_uri}")
|
|
130
|
+
|
|
131
|
+
# Configuration
|
|
132
|
+
DATASET_NAME = "{uc_name}"
|
|
133
|
+
EXPERIMENT_ID = "{experiment_id}"
|
|
134
|
+
|
|
135
|
+
# Test cases
|
|
136
|
+
TEST_CASES = {test_cases_repr}
|
|
137
|
+
|
|
138
|
+
print("=" * 60)
|
|
139
|
+
print("Creating MLflow Evaluation Dataset")
|
|
140
|
+
print("=" * 60)
|
|
141
|
+
print(f"Dataset: {{DATASET_NAME}}")
|
|
142
|
+
print(f"Test cases: {{len(TEST_CASES)}}")
|
|
143
|
+
print()
|
|
144
|
+
|
|
145
|
+
# Create dataset
|
|
146
|
+
print("Creating dataset...")
|
|
147
|
+
try:
|
|
148
|
+
dataset = create_dataset(
|
|
149
|
+
name=DATASET_NAME,
|
|
150
|
+
source={{
|
|
151
|
+
"inputs": [
|
|
152
|
+
{{"query": query}}
|
|
153
|
+
for query in TEST_CASES
|
|
154
|
+
]
|
|
155
|
+
}},
|
|
156
|
+
targets=[
|
|
157
|
+
{{"expected_output": "TODO: Add expected output"}}
|
|
158
|
+
for _ in TEST_CASES
|
|
159
|
+
],
|
|
160
|
+
experiment_id=[EXPERIMENT_ID]
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
print(f"✓ Dataset created: {{DATASET_NAME}}")
|
|
164
|
+
print(f" Location: Unity Catalog table")
|
|
165
|
+
print(f" Queries: {{len(TEST_CASES)}}")
|
|
166
|
+
print()
|
|
167
|
+
print("=" * 60)
|
|
168
|
+
print("Next Steps")
|
|
169
|
+
print("=" * 60)
|
|
170
|
+
print()
|
|
171
|
+
print("1. Verify dataset in Databricks Unity Catalog")
|
|
172
|
+
print(f"2. Use in evaluation: python scripts/run_evaluation_template.py --dataset-name {uc_name}")
|
|
173
|
+
print()
|
|
174
|
+
|
|
175
|
+
except Exception as e:
|
|
176
|
+
print(f"✗ Error creating dataset: {{e}}")
|
|
177
|
+
import traceback
|
|
178
|
+
traceback.print_exc()
|
|
179
|
+
exit(1)
|
|
180
|
+
'''
|
|
181
|
+
else:
|
|
182
|
+
# OSS MLflow version (non-UC)
|
|
183
|
+
return f'''#!/usr/bin/env python3
|
|
184
|
+
"""
|
|
185
|
+
Create MLflow evaluation dataset.
|
|
186
|
+
|
|
187
|
+
Generated by create_dataset_template.py
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
import mlflow
|
|
191
|
+
from mlflow.genai.datasets import create_dataset
|
|
192
|
+
|
|
193
|
+
# Set tracking URI
|
|
194
|
+
mlflow.set_tracking_uri("{tracking_uri}")
|
|
195
|
+
|
|
196
|
+
# Configuration
|
|
197
|
+
DATASET_NAME = "{dataset_name}"
|
|
198
|
+
EXPERIMENT_ID = "{experiment_id}"
|
|
199
|
+
|
|
200
|
+
# Test cases
|
|
201
|
+
TEST_CASES = {test_cases_repr}
|
|
202
|
+
|
|
203
|
+
print("=" * 60)
|
|
204
|
+
print("Creating MLflow Evaluation Dataset")
|
|
205
|
+
print("=" * 60)
|
|
206
|
+
print(f"Dataset: {{DATASET_NAME}}")
|
|
207
|
+
print(f"Test cases: {{len(TEST_CASES)}}")
|
|
208
|
+
print()
|
|
209
|
+
|
|
210
|
+
# Create dataset
|
|
211
|
+
print("Creating dataset...")
|
|
212
|
+
try:
|
|
213
|
+
dataset = create_dataset(
|
|
214
|
+
name=DATASET_NAME,
|
|
215
|
+
source={{
|
|
216
|
+
"inputs": [
|
|
217
|
+
{{"query": query}}
|
|
218
|
+
for query in TEST_CASES
|
|
219
|
+
]
|
|
220
|
+
}},
|
|
221
|
+
targets=[
|
|
222
|
+
{{"expected_output": "TODO: Add expected output"}}
|
|
223
|
+
for _ in TEST_CASES
|
|
224
|
+
],
|
|
225
|
+
experiment_id=[EXPERIMENT_ID]
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
print(f"✓ Dataset created: {{DATASET_NAME}}")
|
|
229
|
+
print(f" Queries: {{len(TEST_CASES)}}")
|
|
230
|
+
print()
|
|
231
|
+
print("=" * 60)
|
|
232
|
+
print("Next Steps")
|
|
233
|
+
print("=" * 60)
|
|
234
|
+
print()
|
|
235
|
+
print("1. Verify dataset: python scripts/list_datasets.py")
|
|
236
|
+
print(f"2. Use in evaluation: python scripts/run_evaluation_template.py --dataset-name {{DATASET_NAME}}")
|
|
237
|
+
print()
|
|
238
|
+
|
|
239
|
+
except Exception as e:
|
|
240
|
+
print(f"✗ Error creating dataset: {{e}}")
|
|
241
|
+
import traceback
|
|
242
|
+
traceback.print_exc()
|
|
243
|
+
exit(1)
|
|
244
|
+
'''
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def main():
|
|
248
|
+
"""Main workflow."""
|
|
249
|
+
args = parse_arguments()
|
|
250
|
+
|
|
251
|
+
print("=" * 60)
|
|
252
|
+
print("MLflow Dataset Creation Template Generator")
|
|
253
|
+
print("=" * 60)
|
|
254
|
+
print()
|
|
255
|
+
|
|
256
|
+
# Check environment
|
|
257
|
+
errors = validate_env_vars()
|
|
258
|
+
if errors:
|
|
259
|
+
print("✗ Environment validation failed:")
|
|
260
|
+
for error in errors:
|
|
261
|
+
print(f" - {error}")
|
|
262
|
+
print("\nRun scripts/setup_mlflow.py first")
|
|
263
|
+
sys.exit(1)
|
|
264
|
+
|
|
265
|
+
tracking_uri = os.getenv("MLFLOW_TRACKING_URI")
|
|
266
|
+
experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
|
|
267
|
+
|
|
268
|
+
print(f"Tracking URI: {tracking_uri}")
|
|
269
|
+
print(f"Experiment ID: {experiment_id}")
|
|
270
|
+
print()
|
|
271
|
+
|
|
272
|
+
# Load test cases
|
|
273
|
+
print("Loading test cases...")
|
|
274
|
+
test_cases = load_test_cases_from_file(args.test_cases_file)
|
|
275
|
+
print()
|
|
276
|
+
|
|
277
|
+
# Check if Databricks
|
|
278
|
+
is_databricks, profile = check_databricks_config()
|
|
279
|
+
|
|
280
|
+
# Handle dataset configuration
|
|
281
|
+
if is_databricks:
|
|
282
|
+
print("✓ Detected Databricks configuration")
|
|
283
|
+
print()
|
|
284
|
+
|
|
285
|
+
# Check if UC args provided
|
|
286
|
+
if args.catalog and args.schema and args.table:
|
|
287
|
+
catalog = args.catalog
|
|
288
|
+
schema = args.schema
|
|
289
|
+
table = args.table
|
|
290
|
+
print(f"Using Unity Catalog: {catalog}.{schema}.{table}")
|
|
291
|
+
elif args.catalog or args.schema or args.table:
|
|
292
|
+
print("✗ For Databricks UC, all three args are required:")
|
|
293
|
+
print(" --catalog, --schema, --table")
|
|
294
|
+
sys.exit(1)
|
|
295
|
+
else:
|
|
296
|
+
# Try to get catalogs
|
|
297
|
+
print("Fetching available catalogs...")
|
|
298
|
+
catalogs = get_uc_catalogs()
|
|
299
|
+
|
|
300
|
+
if not catalogs:
|
|
301
|
+
print("✗ Could not fetch catalogs")
|
|
302
|
+
print(" Please specify manually:")
|
|
303
|
+
print(" --catalog <catalog> --schema <schema> --table <table>")
|
|
304
|
+
sys.exit(1)
|
|
305
|
+
|
|
306
|
+
# Auto-select first catalog
|
|
307
|
+
catalog = catalogs[0]
|
|
308
|
+
print(f"✓ Found {len(catalogs)} catalog(s), using: {catalog}")
|
|
309
|
+
|
|
310
|
+
# Get schemas
|
|
311
|
+
print(f"Fetching schemas in {catalog}...")
|
|
312
|
+
schemas = get_uc_schemas(catalog)
|
|
313
|
+
|
|
314
|
+
if not schemas:
|
|
315
|
+
print("✗ Could not fetch schemas")
|
|
316
|
+
print(" Please specify manually:")
|
|
317
|
+
print(" --catalog <catalog> --schema <schema> --table <table>")
|
|
318
|
+
sys.exit(1)
|
|
319
|
+
|
|
320
|
+
# Auto-select first schema
|
|
321
|
+
schema = schemas[0]
|
|
322
|
+
print(f"✓ Found {len(schemas)} schema(s), using: {schema}")
|
|
323
|
+
|
|
324
|
+
# Auto-generate table name
|
|
325
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
326
|
+
table = f"eval_{timestamp}"
|
|
327
|
+
print(f"✓ Auto-generated table name: {table}")
|
|
328
|
+
|
|
329
|
+
print()
|
|
330
|
+
dataset_name = None # UC uses catalog.schema.table
|
|
331
|
+
else:
|
|
332
|
+
# Non-Databricks: use simple dataset name
|
|
333
|
+
catalog = schema = table = None
|
|
334
|
+
|
|
335
|
+
if args.dataset_name:
|
|
336
|
+
dataset_name = args.dataset_name
|
|
337
|
+
print(f"Using dataset name: {dataset_name}")
|
|
338
|
+
else:
|
|
339
|
+
# Auto-generate dataset name
|
|
340
|
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
341
|
+
dataset_name = f"agent-eval-{timestamp}"
|
|
342
|
+
print(f"✓ Auto-generated dataset name: {dataset_name}")
|
|
343
|
+
print()
|
|
344
|
+
|
|
345
|
+
# Generate code
|
|
346
|
+
print("=" * 60)
|
|
347
|
+
print("Generating Dataset Creation Script")
|
|
348
|
+
print("=" * 60)
|
|
349
|
+
|
|
350
|
+
code = generate_dataset_creation_code(
|
|
351
|
+
tracking_uri, experiment_id, dataset_name, test_cases, catalog, schema, table
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
# Write to file
|
|
355
|
+
output_file = args.output
|
|
356
|
+
with open(output_file, "w") as f:
|
|
357
|
+
f.write(code)
|
|
358
|
+
|
|
359
|
+
print(f"\n✓ Script generated: {output_file}")
|
|
360
|
+
print()
|
|
361
|
+
|
|
362
|
+
# Make executable
|
|
363
|
+
try:
|
|
364
|
+
os.chmod(output_file, 0o755)
|
|
365
|
+
print(f"✓ Made executable: chmod +x {output_file}")
|
|
366
|
+
except Exception:
|
|
367
|
+
pass
|
|
368
|
+
|
|
369
|
+
print()
|
|
370
|
+
print("=" * 60)
|
|
371
|
+
print("Next Steps")
|
|
372
|
+
print("=" * 60)
|
|
373
|
+
print()
|
|
374
|
+
print(f"1. Review the generated script: {output_file}")
|
|
375
|
+
print(f"2. Execute it: python {output_file}")
|
|
376
|
+
print("3. Verify dataset was created: python scripts/list_datasets.py")
|
|
377
|
+
print()
|
|
378
|
+
print("=" * 60)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
if __name__ == "__main__":
|
|
382
|
+
main()
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
"""
|
|
2
|
+
List and compare MLflow evaluation datasets in an experiment.
|
|
3
|
+
|
|
4
|
+
This script discovers existing datasets before prompting to create new ones,
|
|
5
|
+
preventing duplicate work and helping users make informed choices.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- Diversity metrics (query length variability, unique vocabulary)
|
|
9
|
+
- Timeout protection for large experiments
|
|
10
|
+
- Multiple output formats (table, JSON, names-only)
|
|
11
|
+
- Sample query preview
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
python scripts/list_datasets.py # Table format (default)
|
|
15
|
+
python scripts/list_datasets.py --format json # JSON output
|
|
16
|
+
python scripts/list_datasets.py --format names-only # Names only (for piping)
|
|
17
|
+
python scripts/list_datasets.py --detailed # Include diversity analysis
|
|
18
|
+
|
|
19
|
+
Environment variables required:
|
|
20
|
+
MLFLOW_TRACKING_URI
|
|
21
|
+
MLFLOW_EXPERIMENT_ID
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import json
|
|
26
|
+
import os
|
|
27
|
+
import signal
|
|
28
|
+
import sys
|
|
29
|
+
|
|
30
|
+
import numpy as np
|
|
31
|
+
|
|
32
|
+
from mlflow import MlflowClient
|
|
33
|
+
from mlflow.genai.datasets import get_dataset
|
|
34
|
+
from utils import validate_env_vars
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TimeoutError(Exception):
|
|
38
|
+
"""Custom timeout exception."""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def timeout_handler(signum, frame):
|
|
42
|
+
"""Handle timeout signal."""
|
|
43
|
+
raise TimeoutError()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def parse_arguments():
|
|
47
|
+
"""Parse command-line arguments."""
|
|
48
|
+
parser = argparse.ArgumentParser(description="List and compare MLflow evaluation datasets")
|
|
49
|
+
parser.add_argument("--dataset-name", help="Specific dataset to display")
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"--show-samples", type=int, default=5, help="Number of sample queries to show (default: 5)"
|
|
52
|
+
)
|
|
53
|
+
parser.add_argument(
|
|
54
|
+
"--format",
|
|
55
|
+
choices=["table", "json", "names-only"],
|
|
56
|
+
default="table",
|
|
57
|
+
help="Output format (default: table)",
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--timeout",
|
|
61
|
+
type=int,
|
|
62
|
+
default=30,
|
|
63
|
+
help="Timeout in seconds for dataset search (default: 30)",
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"--detailed", action="store_true", help="Include detailed diversity analysis (slower)"
|
|
67
|
+
)
|
|
68
|
+
return parser.parse_args()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def calculate_diversity_metrics(queries):
|
|
72
|
+
"""Calculate diversity metrics for a list of queries."""
|
|
73
|
+
if not queries:
|
|
74
|
+
return 0.0, 0.0, 0.0
|
|
75
|
+
|
|
76
|
+
# Query length statistics
|
|
77
|
+
lengths = [len(q) for q in queries]
|
|
78
|
+
avg_length = np.mean(lengths)
|
|
79
|
+
std_length = np.std(lengths)
|
|
80
|
+
|
|
81
|
+
# Unique word count (simple diversity measure)
|
|
82
|
+
all_words = set()
|
|
83
|
+
for query in queries:
|
|
84
|
+
words = query.lower().split()
|
|
85
|
+
all_words.update(words)
|
|
86
|
+
|
|
87
|
+
unique_word_ratio = len(all_words) / len(queries) if queries else 0
|
|
88
|
+
|
|
89
|
+
return avg_length, std_length, unique_word_ratio
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def classify_diversity(std_length, unique_word_ratio, query_count):
|
|
93
|
+
"""Classify diversity as HIGH, MEDIUM, or LOW."""
|
|
94
|
+
# Heuristics based on variability and vocabulary
|
|
95
|
+
if query_count < 5:
|
|
96
|
+
return "LOW (too few queries)"
|
|
97
|
+
|
|
98
|
+
if std_length > 30 and unique_word_ratio > 5:
|
|
99
|
+
return "HIGH"
|
|
100
|
+
elif std_length > 15 and unique_word_ratio > 3:
|
|
101
|
+
return "MEDIUM"
|
|
102
|
+
else:
|
|
103
|
+
return "LOW"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def get_datasets_with_timeout(client, experiment_ids, timeout_seconds):
|
|
107
|
+
"""Get datasets with timeout protection."""
|
|
108
|
+
# Set alarm for timeout
|
|
109
|
+
signal.signal(signal.SIGALRM, timeout_handler)
|
|
110
|
+
signal.alarm(timeout_seconds)
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
datasets = client.search_datasets(experiment_ids=experiment_ids)
|
|
114
|
+
signal.alarm(0) # Cancel alarm
|
|
115
|
+
return datasets
|
|
116
|
+
except TimeoutError:
|
|
117
|
+
signal.alarm(0)
|
|
118
|
+
print(f"⚠ Dataset search timed out after {timeout_seconds}s")
|
|
119
|
+
print(" Try: --timeout <seconds> to increase timeout")
|
|
120
|
+
return []
|
|
121
|
+
except Exception as e:
|
|
122
|
+
signal.alarm(0)
|
|
123
|
+
print(f"✗ Error searching datasets: {str(e)[:100]}")
|
|
124
|
+
return []
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def print_table_format(dataset_info, args):
|
|
128
|
+
"""Print datasets in table format."""
|
|
129
|
+
if not dataset_info:
|
|
130
|
+
print("\n✗ No datasets found in this experiment")
|
|
131
|
+
print("\nTo create a new dataset:")
|
|
132
|
+
print(" python scripts/create_dataset_template.py --test-cases-file test_cases.txt")
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
print(f"\n✓ Found {len(dataset_info)} dataset(s):")
|
|
136
|
+
print("=" * 80)
|
|
137
|
+
|
|
138
|
+
for i, info in enumerate(dataset_info, 1):
|
|
139
|
+
print(f"\n{i}. {info['name']}")
|
|
140
|
+
print(f" Queries: {info.get('count', '?')}")
|
|
141
|
+
|
|
142
|
+
if args.detailed:
|
|
143
|
+
if "avg_length" in info:
|
|
144
|
+
print(f" Avg length: {info['avg_length']:.1f} chars")
|
|
145
|
+
print(f" Std length: {info['std_length']:.1f} chars")
|
|
146
|
+
print(f" Unique words/query: {info['unique_word_ratio']:.1f}")
|
|
147
|
+
print(f" Diversity: {info.get('diversity', 'N/A')}")
|
|
148
|
+
|
|
149
|
+
if "samples" in info:
|
|
150
|
+
print(f"\n Sample queries:")
|
|
151
|
+
for j, sample in enumerate(info["samples"], 1):
|
|
152
|
+
preview = sample[:60] + "..." if len(sample) > 60 else sample
|
|
153
|
+
print(f" {j}. {preview}")
|
|
154
|
+
|
|
155
|
+
print("\n" + "=" * 80)
|
|
156
|
+
print("\nTo use a dataset in evaluation:")
|
|
157
|
+
print(' python scripts/run_evaluation_template.py --dataset-name "dataset_name"')
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def print_json_format(dataset_info):
|
|
161
|
+
"""Print datasets in JSON format."""
|
|
162
|
+
print(json.dumps(dataset_info, indent=2))
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def print_names_only(dataset_info):
|
|
166
|
+
"""Print dataset names only (one per line)."""
|
|
167
|
+
for info in dataset_info:
|
|
168
|
+
print(info["name"])
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main():
|
|
172
|
+
"""Main workflow."""
|
|
173
|
+
args = parse_arguments()
|
|
174
|
+
|
|
175
|
+
print("=" * 80)
|
|
176
|
+
print("MLflow Evaluation Datasets")
|
|
177
|
+
print("=" * 80)
|
|
178
|
+
|
|
179
|
+
# Check environment using utility
|
|
180
|
+
errors = validate_env_vars()
|
|
181
|
+
if errors:
|
|
182
|
+
print("\n✗ Environment validation failed:")
|
|
183
|
+
for error in errors:
|
|
184
|
+
print(f" - {error}")
|
|
185
|
+
print("\nRun scripts/setup_mlflow.py to configure environment")
|
|
186
|
+
sys.exit(1)
|
|
187
|
+
|
|
188
|
+
experiment_id = os.getenv("MLFLOW_EXPERIMENT_ID")
|
|
189
|
+
print(f"\nExperiment ID: {experiment_id}")
|
|
190
|
+
|
|
191
|
+
# Get datasets
|
|
192
|
+
print("\nSearching for datasets...")
|
|
193
|
+
client = MlflowClient()
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
if args.dataset_name:
|
|
197
|
+
# Search for specific dataset
|
|
198
|
+
print(f" Looking for: {args.dataset_name}")
|
|
199
|
+
datasets = get_datasets_with_timeout(client, [experiment_id], args.timeout)
|
|
200
|
+
datasets = [d for d in datasets if d.name == args.dataset_name]
|
|
201
|
+
|
|
202
|
+
if not datasets:
|
|
203
|
+
print(f"\n✗ Dataset '{args.dataset_name}' not found")
|
|
204
|
+
sys.exit(1)
|
|
205
|
+
else:
|
|
206
|
+
# Get all datasets
|
|
207
|
+
datasets = get_datasets_with_timeout(client, [experiment_id], args.timeout)
|
|
208
|
+
|
|
209
|
+
except Exception as e:
|
|
210
|
+
print(f"\n✗ Error: {str(e)[:200]}")
|
|
211
|
+
sys.exit(1)
|
|
212
|
+
|
|
213
|
+
# Process datasets
|
|
214
|
+
dataset_info = []
|
|
215
|
+
|
|
216
|
+
for dataset in datasets:
|
|
217
|
+
info = {"name": dataset.name}
|
|
218
|
+
|
|
219
|
+
# Try to load dataset for detailed info
|
|
220
|
+
if args.detailed or args.show_samples > 0:
|
|
221
|
+
try:
|
|
222
|
+
ds = get_dataset(dataset.name)
|
|
223
|
+
df = ds.to_df()
|
|
224
|
+
|
|
225
|
+
info["count"] = len(df)
|
|
226
|
+
|
|
227
|
+
# Extract queries (flexible extraction from various input formats)
|
|
228
|
+
queries = []
|
|
229
|
+
for _, row in df.iterrows():
|
|
230
|
+
inputs = row.get("inputs", {})
|
|
231
|
+
if isinstance(inputs, dict):
|
|
232
|
+
# Try common keys first, then use first non-empty value
|
|
233
|
+
query = (
|
|
234
|
+
inputs.get("query")
|
|
235
|
+
or inputs.get("question")
|
|
236
|
+
or inputs.get("input")
|
|
237
|
+
or inputs.get("prompt")
|
|
238
|
+
or next((v for v in inputs.values() if v), str(inputs))
|
|
239
|
+
)
|
|
240
|
+
queries.append(str(query))
|
|
241
|
+
else:
|
|
242
|
+
# If inputs is not a dict, use it directly
|
|
243
|
+
queries.append(str(inputs))
|
|
244
|
+
|
|
245
|
+
# Calculate diversity metrics
|
|
246
|
+
if queries and args.detailed:
|
|
247
|
+
avg_len, std_len, unique_ratio = calculate_diversity_metrics(queries)
|
|
248
|
+
info["avg_length"] = avg_len
|
|
249
|
+
info["std_length"] = std_len
|
|
250
|
+
info["unique_word_ratio"] = unique_ratio
|
|
251
|
+
info["diversity"] = classify_diversity(std_len, unique_ratio, len(queries))
|
|
252
|
+
|
|
253
|
+
# Sample queries
|
|
254
|
+
if queries and args.show_samples > 0:
|
|
255
|
+
info["samples"] = queries[: args.show_samples]
|
|
256
|
+
|
|
257
|
+
except Exception as e:
|
|
258
|
+
info["count"] = "?"
|
|
259
|
+
info["error"] = str(e)[:50]
|
|
260
|
+
|
|
261
|
+
dataset_info.append(info)
|
|
262
|
+
|
|
263
|
+
# Output in requested format
|
|
264
|
+
if args.format == "json":
|
|
265
|
+
print_json_format(dataset_info)
|
|
266
|
+
elif args.format == "names-only":
|
|
267
|
+
print_names_only(dataset_info)
|
|
268
|
+
else: # table
|
|
269
|
+
print_table_format(dataset_info, args)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
if __name__ == "__main__":
|
|
273
|
+
main()
|