ai-kit-python 1.4.2__py3-none-any.whl
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.
- ai_kit_python-1.4.2.dist-info/METADATA +132 -0
- ai_kit_python-1.4.2.dist-info/RECORD +278 -0
- ai_kit_python-1.4.2.dist-info/WHEEL +5 -0
- ai_kit_python-1.4.2.dist-info/entry_points.txt +2 -0
- ai_kit_python-1.4.2.dist-info/licenses/LICENSE +21 -0
- ai_kit_python-1.4.2.dist-info/licenses/template/ai-kit/vendor/security-audit/LICENSE +21 -0
- ai_kit_python-1.4.2.dist-info/licenses/template/ai-kit/vendor/strix/LICENSE +201 -0
- ai_kit_python-1.4.2.dist-info/top_level.txt +1 -0
- aikit/.agents/skills/go-work/SKILL.md +8 -0
- aikit/.agents/skills/laravel-work/SKILL.md +8 -0
- aikit/.agents/skills/moodle-work/SKILL.md +8 -0
- aikit/.agents/skills/project-continuity/SKILL.md +34 -0
- aikit/.agents/skills/python-work/SKILL.md +8 -0
- aikit/.dockerignore +90 -0
- aikit/.gitattributes +3 -0
- aikit/.github/workflows/check-kit.yml +70 -0
- aikit/.github/workflows/publish-pypi.yml +108 -0
- aikit/.gitignore +60 -0
- aikit/BOOTSTRAP_PROMPT.md +18 -0
- aikit/CHANGELOG.md +85 -0
- aikit/CLAUDE.md +3 -0
- aikit/CONTRIBUTING.md +46 -0
- aikit/Dockerfile +44 -0
- aikit/KIMI.md +3 -0
- aikit/LICENSE +21 -0
- aikit/MANIFEST.in +22 -0
- aikit/MANUS.md +3 -0
- aikit/Makefile +70 -0
- aikit/README.md +1161 -0
- aikit/SECURITY.md +8 -0
- aikit/SKILL.md +105 -0
- aikit/VERSION +1 -0
- aikit/__init__.py +1 -0
- aikit/ai-kit/ADAPTERS.md +5 -0
- aikit/ai-kit/CONTAINERS.md +5 -0
- aikit/ai-kit/ENGINEERING.md +5 -0
- aikit/ai-kit/INTENT.md +5 -0
- aikit/ai-kit/MODELS.md +5 -0
- aikit/ai-kit/SKILLS.md +5 -0
- aikit/ai-kit/stacks/GO.md +5 -0
- aikit/ai-kit/stacks/LARAVEL.md +5 -0
- aikit/ai-kit/stacks/MOODLE.md +5 -0
- aikit/ai-kit/stacks/PYTHON.md +5 -0
- aikit/aikit_cli.py +59 -0
- aikit/deploy/k8s/install-preview-job.yaml +56 -0
- aikit/docker/build-requirements.txt +4 -0
- aikit/docker/check_version.py +29 -0
- aikit/docker/pypi-requirements.txt +3 -0
- aikit/docs/ADAPTER_PATH_FIX.md +23 -0
- aikit/docs/BENCHMARK.md +106 -0
- aikit/docs/CONTEXT7.md +33 -0
- aikit/docs/DECISIONS.md +22 -0
- aikit/docs/DEVELOPMENT_PLAN.md +16 -0
- aikit/docs/DIALOGUE_MEMORY.md +70 -0
- aikit/docs/DOCKER.md +74 -0
- aikit/docs/DOCKER_HUB_OVERVIEW.md +311 -0
- aikit/docs/EVALUATION.md +30 -0
- aikit/docs/IMPLEMENTATION.md +134 -0
- aikit/docs/MANUS_REVIEW.md +46 -0
- aikit/docs/PYPI.md +87 -0
- aikit/docs/PYPI_DESCRIPTION.md +103 -0
- aikit/docs/SECURITY_AUDIT.md +26 -0
- aikit/docs/STRIX.md +28 -0
- aikit/docs/V0_5_0.md +27 -0
- aikit/docs/V0_6_4.md +25 -0
- aikit/docs/V1_4_0.md +73 -0
- aikit/docs/V1_4_1.md +55 -0
- aikit/docs/V1_4_2.md +33 -0
- aikit/docs/WEB_DESIGN.md +72 -0
- aikit/docs/WINDOWS_CI_FIX.md +39 -0
- aikit/docs/adr/0000-template.md +24 -0
- aikit/docs/adr/0001-adaptive-model-routing.md +30 -0
- aikit/docs/adr/0002-template-separation.md +24 -0
- aikit/docs/adr/0003-agent-registry-and-router.md +24 -0
- aikit/docs/adr/0004-onboarding-and-project-facts.md +24 -0
- aikit/docs/adr/0005-client-settings-ownership.md +30 -0
- aikit/docs/adr/0006-routing-evidence-and-local-measurements.md +26 -0
- aikit/docs/adr/0007-generated-client-configuration-and-presets.md +34 -0
- aikit/docs/adr/0008-unified-cli-and-fact-drift.md +20 -0
- aikit/docs/adr/0009-provider-review-doctor-fix-and-ci-self-install.md +20 -0
- aikit/docs/adr/0010-metrics-analysis-and-gemini-verification.md +20 -0
- aikit/docs/adr/0011-evidence-lifecycle-and-evaluation.md +20 -0
- aikit/docs/adr/0012-measurement-led-routing.md +31 -0
- aikit/docs/adr/0013-docker-cli-image.md +24 -0
- aikit/docs/adr/0014-local-dialogue-memory.md +22 -0
- aikit/docs/history/original-bundle-checks.md +11 -0
- aikit/docs/history/v0.1-changelog.txt +37 -0
- aikit/docs/history/v0.10-changelog.md +12 -0
- aikit/docs/history/v0.2-changelog.md +35 -0
- aikit/docs/history/v0.3-changelog.md +25 -0
- aikit/docs/history/v0.4-changelog.md +31 -0
- aikit/docs/history/v0.5-changelog.md +14 -0
- aikit/docs/history/v0.6.4-changelog.md +12 -0
- aikit/docs/history/v0.6.5-v0.9-changelog.md +35 -0
- aikit/docs/history/v1.1.0-changelog.md +12 -0
- aikit/docs/history/v1.2.0-changelog.md +11 -0
- aikit/docs/history/verification-before-measurements.md +53 -0
- aikit/integrations/CONVENTIONS.md +3 -0
- aikit/integrations/README.md +7 -0
- aikit/integrations/agents.json +136 -0
- aikit/integrations/ai-kit-check.yml +66 -0
- aikit/integrations/ai-kit-cline.md +4 -0
- aikit/integrations/ai-kit-roo.md +4 -0
- aikit/integrations/ai-kit-windsurf.md +4 -0
- aikit/integrations/ai-kit.mdc +6 -0
- aikit/integrations/claude-settings.data-ask.json +23 -0
- aikit/integrations/claude-settings.git-ask.json +10 -0
- aikit/integrations/copilot-instructions.md +3 -0
- aikit/integrations/security-audit.json +135 -0
- aikit/integrations/strix.json +69 -0
- aikit/pyproject.toml +60 -0
- aikit/scripts/__init__.py +1 -0
- aikit/scripts/adapters.py +184 -0
- aikit/scripts/adaptive.py +167 -0
- aikit/scripts/adr.py +61 -0
- aikit/scripts/benchmark.py +543 -0
- aikit/scripts/changelog.py +55 -0
- aikit/scripts/check_distribution.py +178 -0
- aikit/scripts/check_kit.py +406 -0
- aikit/scripts/context.py +184 -0
- aikit/scripts/docker_test_usage.py +55 -0
- aikit/scripts/doctor.py +313 -0
- aikit/scripts/evaluate.py +125 -0
- aikit/scripts/install.py +1584 -0
- aikit/scripts/learning.py +260 -0
- aikit/scripts/memory.py +344 -0
- aikit/scripts/memory_import.py +177 -0
- aikit/scripts/memory_store.py +125 -0
- aikit/scripts/metrics.py +351 -0
- aikit/scripts/router.py +399 -0
- aikit/template/.agents/hooks/session-start.md +3 -0
- aikit/template/.agents/hooks/session-start.sh +21 -0
- aikit/template/.agents/skills/ai-kit-bootstrap/SKILL.md +14 -0
- aikit/template/.agents/skills/ai-kit-review/SKILL.md +11 -0
- aikit/template/.agents/skills/ai-kit-sync-context/SKILL.md +12 -0
- aikit/template/.agents/skills/context7-docs/SKILL.md +11 -0
- aikit/template/.agents/skills/design-extract/SKILL.md +9 -0
- aikit/template/.agents/skills/dotnet-work/SKILL.md +9 -0
- aikit/template/.agents/skills/filament-work/SKILL.md +9 -0
- aikit/template/.agents/skills/frontend-work/SKILL.md +9 -0
- aikit/template/.agents/skills/go-work/SKILL.md +9 -0
- aikit/template/.agents/skills/infra-work/SKILL.md +9 -0
- aikit/template/.agents/skills/java-work/SKILL.md +9 -0
- aikit/template/.agents/skills/laravel-blade-ui/SKILL.md +9 -0
- aikit/template/.agents/skills/laravel-work/SKILL.md +10 -0
- aikit/template/.agents/skills/library-work/SKILL.md +9 -0
- aikit/template/.agents/skills/moodle-work/SKILL.md +9 -0
- aikit/template/.agents/skills/php-work/SKILL.md +9 -0
- aikit/template/.agents/skills/project-continuity/SKILL.md +21 -0
- aikit/template/.agents/skills/python-work/SKILL.md +9 -0
- aikit/template/.agents/skills/rust-work/SKILL.md +9 -0
- aikit/template/.agents/skills/security-audit/SKILL.md +16 -0
- aikit/template/.agents/skills/security-audit/agents/openai.yaml +2 -0
- aikit/template/.agents/skills/strix/SKILL.md +16 -0
- aikit/template/.agents/skills/strix/agents/openai.yaml +2 -0
- aikit/template/.agents/skills/ui-review/SKILL.md +9 -0
- aikit/template/.agents/skills/web-design/SKILL.md +9 -0
- aikit/template/AGENTS.md +16 -0
- aikit/template/CHANGELOG.md +6 -0
- aikit/template/CLAUDE.md +5 -0
- aikit/template/GEMINI.md +4 -0
- aikit/template/KIMI.md +4 -0
- aikit/template/MANUS.md +4 -0
- aikit/template/PROJECT_CONTEXT.md +35 -0
- aikit/template/README.md +6 -0
- aikit/template/WIKI.md +37 -0
- aikit/template/ai-kit/ADAPTERS.md +100 -0
- aikit/template/ai-kit/BOOTSTRAP.md +15 -0
- aikit/template/ai-kit/CONTAINERS.md +63 -0
- aikit/template/ai-kit/CONTEXT7.md +96 -0
- aikit/template/ai-kit/CORE.md +23 -0
- aikit/template/ai-kit/ENGINEERING.md +34 -0
- aikit/template/ai-kit/MCP.md +17 -0
- aikit/template/ai-kit/METRICS.md +83 -0
- aikit/template/ai-kit/SECURITY-AUDIT.md +21 -0
- aikit/template/ai-kit/SECURITY.md +34 -0
- aikit/template/ai-kit/SKILLS.md +37 -0
- aikit/template/ai-kit/STRIX.md +44 -0
- aikit/template/ai-kit/UPSTREAM.md +38 -0
- aikit/template/ai-kit/WEB-DESIGN.md +37 -0
- aikit/template/ai-kit/profiles/OWNER.md +19 -0
- aikit/template/ai-kit/project.json +14 -0
- aikit/template/ai-kit/router/POLICY.md +79 -0
- aikit/template/ai-kit/router/providers/anthropic.json +44 -0
- aikit/template/ai-kit/router/providers/anthropic.md +14 -0
- aikit/template/ai-kit/router/providers/gemini.json +13 -0
- aikit/template/ai-kit/router/providers/gemini.md +10 -0
- aikit/template/ai-kit/router/providers/kimi.json +26 -0
- aikit/template/ai-kit/router/providers/kimi.md +13 -0
- aikit/template/ai-kit/router/providers/local.json +18 -0
- aikit/template/ai-kit/router/providers/local.md +10 -0
- aikit/template/ai-kit/router/providers/openai.json +48 -0
- aikit/template/ai-kit/router/providers/openai.md +14 -0
- aikit/template/ai-kit/router/routing.json +11 -0
- aikit/template/ai-kit/router/selection.json +14 -0
- aikit/template/ai-kit/settings.json +11 -0
- aikit/template/ai-kit/stacks/DOTNET.md +13 -0
- aikit/template/ai-kit/stacks/FILAMENT.md +18 -0
- aikit/template/ai-kit/stacks/FRONTEND.md +9 -0
- aikit/template/ai-kit/stacks/GO.md +19 -0
- aikit/template/ai-kit/stacks/INFRA.md +12 -0
- aikit/template/ai-kit/stacks/JAVA.md +13 -0
- aikit/template/ai-kit/stacks/LARAVEL.md +15 -0
- aikit/template/ai-kit/stacks/LIBRARY.md +9 -0
- aikit/template/ai-kit/stacks/MOODLE.md +12 -0
- aikit/template/ai-kit/stacks/PHP.md +11 -0
- aikit/template/ai-kit/stacks/PYTHON.md +11 -0
- aikit/template/ai-kit/stacks/RUST.md +18 -0
- aikit/template/ai-kit/vendor/security-audit/AI-AND-LLM.md +83 -0
- aikit/template/ai-kit/vendor/security-audit/ATTACK-CLASSES.md +130 -0
- aikit/template/ai-kit/vendor/security-audit/CLIENT-SIDE.md +83 -0
- aikit/template/ai-kit/vendor/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- aikit/template/ai-kit/vendor/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- aikit/template/ai-kit/vendor/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- aikit/template/ai-kit/vendor/security-audit/HUNTING.md +251 -0
- aikit/template/ai-kit/vendor/security-audit/LICENSE +21 -0
- aikit/template/ai-kit/vendor/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- aikit/template/ai-kit/vendor/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- aikit/template/ai-kit/vendor/security-audit/RECONNAISSANCE.md +156 -0
- aikit/template/ai-kit/vendor/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- aikit/template/ai-kit/vendor/security-audit/SKILL.md +192 -0
- aikit/template/ai-kit/vendor/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- aikit/template/ai-kit/vendor/security-audit/VALIDATION-AND-REPORTING.md +186 -0
- aikit/template/ai-kit/vendor/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- aikit/template/ai-kit/vendor/security-audit/report-schema.json +461 -0
- aikit/template/ai-kit/vendor/security-audit/validate-coverage-ledger.cjs +872 -0
- aikit/template/ai-kit/vendor/security-audit/validate-coverage-ledger.test.cjs +740 -0
- aikit/template/ai-kit/vendor/security-audit/validate-findings.cjs +773 -0
- aikit/template/ai-kit/vendor/security-audit/validate-findings.test.cjs +652 -0
- aikit/template/ai-kit/vendor/strix/LICENSE +201 -0
- aikit/template/ai-kit/vendor/strix/api-security-testing/SKILL.md +61 -0
- aikit/template/ai-kit/vendor/strix/application-security-testing/SKILL.md +66 -0
- aikit/template/ai-kit/vendor/strix/ci-security-scanning-with-strix/SKILL.md +149 -0
- aikit/template/ai-kit/vendor/strix/find-security-vulnerabilities-in-code/SKILL.md +62 -0
- aikit/template/ai-kit/vendor/strix/fix-security-vulnerabilities-with-strix/SKILL.md +77 -0
- aikit/template/ai-kit/vendor/strix/managed-pentesting-with-strix/SKILL.md +321 -0
- aikit/template/ai-kit/vendor/strix/owasp-top-10-testing/SKILL.md +64 -0
- aikit/template/ai-kit/vendor/strix/penetration-testing-with-strix/SKILL.md +162 -0
- aikit/template/ai-kit/vendor/strix/web-app-penetration-testing/SKILL.md +54 -0
- aikit/template/ai-kit/web-design/LARAVEL.md +51 -0
- aikit/template/ai-kit/web-design/LIBRARIES.md +39 -0
- aikit/template/ai-kit/web-design/REVIEW.md +37 -0
- aikit/template/ai-kit/web-design/TOOLS.md +43 -0
- aikit/template/docs/DECISIONS.md +7 -0
- aikit/template/docs/adr/0000-template.md +20 -0
- aikit/template/docs/design/ACCEPTANCE.md +24 -0
- aikit/template/docs/design/BRIEF.md +26 -0
- aikit/template/docs/design/SYSTEM.md +30 -0
- aikit/templates/agent-secrets.ignore +19 -0
- aikit/templates/gitignore.private +160 -0
- aikit/templates/gitignore.team +139 -0
- aikit/tests/build_distribution.py +73 -0
- aikit/tests/docker_smoke.py +172 -0
- aikit/tests/fixtures/create-junction.ps1 +18 -0
- aikit/tests/fixtures/golden/claude-settings-local.json +58 -0
- aikit/tests/test_adapters.py +105 -0
- aikit/tests/test_aikit.py +79 -0
- aikit/tests/test_benchmark.py +241 -0
- aikit/tests/test_check_kit.py +203 -0
- aikit/tests/test_context.py +76 -0
- aikit/tests/test_context7.py +153 -0
- aikit/tests/test_context_selection.py +70 -0
- aikit/tests/test_distribution.py +181 -0
- aikit/tests/test_docker_image.py +63 -0
- aikit/tests/test_docker_test_usage.py +54 -0
- aikit/tests/test_doctor.py +148 -0
- aikit/tests/test_evaluate.py +66 -0
- aikit/tests/test_install.py +939 -0
- aikit/tests/test_learning.py +247 -0
- aikit/tests/test_memory.py +371 -0
- aikit/tests/test_metrics.py +209 -0
- aikit/tests/test_native.py +342 -0
- aikit/tests/test_onboarding.py +301 -0
- aikit/tests/test_router.py +336 -0
- aikit/tests/test_security_audit.py +237 -0
- aikit/tests/test_strix.py +245 -0
- aikit/tests/test_web_design.py +219 -0
- aikit/tests/wheel_smoke.py +104 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Exercise the installed-project health check."""
|
|
2
|
+
import contextlib
|
|
3
|
+
import io
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import shutil
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
import unittest
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
|
12
|
+
import doctor
|
|
13
|
+
import install
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DoctorTests(unittest.TestCase):
|
|
17
|
+
def setUp(self):
|
|
18
|
+
self.temp = tempfile.TemporaryDirectory(prefix="ai-kit-doctor-")
|
|
19
|
+
self.addCleanup(self.temp.cleanup)
|
|
20
|
+
self.base = Path(self.temp.name).resolve()
|
|
21
|
+
self.target = self.base / "project with spaces"
|
|
22
|
+
self.source = self.base / "reference"
|
|
23
|
+
shutil.copytree(install.ROOT, self.source, ignore=shutil.ignore_patterns("__pycache__", ".git"))
|
|
24
|
+
self.initial_version = (self.source / "VERSION").read_text(encoding="utf-8").strip()
|
|
25
|
+
|
|
26
|
+
def apply(self, **options):
|
|
27
|
+
plan = install.build_plan(self.target, root=self.source, **options)
|
|
28
|
+
self.assertTrue(install.apply_plan(plan))
|
|
29
|
+
return plan
|
|
30
|
+
|
|
31
|
+
def write(self, path, data):
|
|
32
|
+
destination = self.target / path
|
|
33
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
destination.write_bytes(data)
|
|
35
|
+
|
|
36
|
+
def examine(self):
|
|
37
|
+
return doctor.examine(self.target, root=self.source)
|
|
38
|
+
|
|
39
|
+
def test_healthy_installation_reports_no_errors_or_warnings(self):
|
|
40
|
+
self.apply()
|
|
41
|
+
# Runtime experiment notes are private data, not managed instruction/link sources.
|
|
42
|
+
self.write("ai-kit/.metrics/private-notes.md", b"[Runtime reference](missing.md)\n\xff")
|
|
43
|
+
report = self.examine()
|
|
44
|
+
self.assertEqual(report["errors"], [])
|
|
45
|
+
self.assertEqual(report["warnings"], [])
|
|
46
|
+
self.assertEqual(report["installed_version"], self.initial_version)
|
|
47
|
+
|
|
48
|
+
def test_module_map_drift_is_reported(self):
|
|
49
|
+
self.write("go.mod", b"module example.test/app\n\ngo 1.21\n")
|
|
50
|
+
self.apply()
|
|
51
|
+
report = self.examine()
|
|
52
|
+
self.assertFalse(any("module maps differ" in warning for warning in report["warnings"]))
|
|
53
|
+
project = json.loads((self.target / "ai-kit/project.json").read_text(encoding="utf-8"))
|
|
54
|
+
project["modules"][0]["path"] = "/api/"
|
|
55
|
+
(self.target / "ai-kit/project.json").write_text(json.dumps(project) + "\n", encoding="utf-8")
|
|
56
|
+
report = self.examine()
|
|
57
|
+
self.assertTrue(any("module maps differ" in warning for warning in report["warnings"]))
|
|
58
|
+
|
|
59
|
+
def test_user_edits_to_client_settings_are_not_reported(self):
|
|
60
|
+
self.apply(agents=["claude"], extras=["guards", "session-start"])
|
|
61
|
+
path = self.target / ".claude/settings.local.json"
|
|
62
|
+
settings = json.loads(path.read_text(encoding="utf-8"))
|
|
63
|
+
settings["model"] = "user-choice"
|
|
64
|
+
path.write_text(json.dumps(settings) + "\n", encoding="utf-8")
|
|
65
|
+
self.assertEqual(self.examine()["warnings"], [])
|
|
66
|
+
|
|
67
|
+
def test_removed_managed_client_entry_is_reported(self):
|
|
68
|
+
self.apply(agents=["claude"], extras=["guards"])
|
|
69
|
+
path = self.target / ".claude/settings.local.json"
|
|
70
|
+
settings = json.loads(path.read_text(encoding="utf-8"))
|
|
71
|
+
settings["permissions"]["ask"].remove("Bash(git push *)")
|
|
72
|
+
path.write_text(json.dumps(settings) + "\n", encoding="utf-8")
|
|
73
|
+
self.assertIn("AI-KIT entry missing from .claude/settings.local.json: permissions.ask Bash(git push *)",
|
|
74
|
+
self.examine()["warnings"])
|
|
75
|
+
path.write_text("[]\n", encoding="utf-8")
|
|
76
|
+
self.assertTrue(any(w.startswith("Cannot read AI-KIT entries") for w in self.examine()["warnings"]))
|
|
77
|
+
|
|
78
|
+
def test_missing_installation_is_reported(self):
|
|
79
|
+
self.target.mkdir(parents=True)
|
|
80
|
+
report = self.examine()
|
|
81
|
+
self.assertTrue(any("No installer state" in error for error in report["errors"]))
|
|
82
|
+
|
|
83
|
+
def test_modified_managed_file_is_reported(self):
|
|
84
|
+
self.apply()
|
|
85
|
+
self.write("ai-kit/CORE.md", b"Locally edited core\n")
|
|
86
|
+
report = self.examine()
|
|
87
|
+
self.assertTrue(any("Modified after installation" in warning and "ai-kit/CORE.md" in warning
|
|
88
|
+
for warning in report["warnings"]))
|
|
89
|
+
|
|
90
|
+
def test_accepted_local_adaptation_is_not_a_modification_warning(self):
|
|
91
|
+
self.apply()
|
|
92
|
+
self.write("ai-kit/CORE.md", b"Reviewed semantic merge\n")
|
|
93
|
+
self.apply(accept_local=["ai-kit/CORE.md"])
|
|
94
|
+
report = self.examine()
|
|
95
|
+
self.assertEqual(report["errors"], [])
|
|
96
|
+
self.assertFalse(any("Modified after installation" in warning for warning in report["warnings"]))
|
|
97
|
+
|
|
98
|
+
def test_missing_owned_document_is_reported(self):
|
|
99
|
+
self.apply()
|
|
100
|
+
(self.target / "WIKI.md").unlink()
|
|
101
|
+
report = self.examine()
|
|
102
|
+
self.assertTrue(any("Owned project document missing: WIKI.md" in warning
|
|
103
|
+
for warning in report["warnings"]))
|
|
104
|
+
|
|
105
|
+
def test_broken_kit_link_is_reported(self):
|
|
106
|
+
self.apply()
|
|
107
|
+
self.write("WIKI.md", b"[Missing](no-such-file.md)\n")
|
|
108
|
+
report = self.examine()
|
|
109
|
+
self.assertTrue(any("missing link" in warning and "WIKI.md" in warning
|
|
110
|
+
for warning in report["warnings"]))
|
|
111
|
+
|
|
112
|
+
def test_stale_provider_verification_is_reported(self):
|
|
113
|
+
self.apply()
|
|
114
|
+
provider = self.target / "ai-kit" / "router" / "providers" / "openai.json"
|
|
115
|
+
config = json.loads(provider.read_text(encoding="utf-8"))
|
|
116
|
+
config["verified_documentation_date"] = "2025-01-01"
|
|
117
|
+
provider.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8")
|
|
118
|
+
report = self.examine()
|
|
119
|
+
self.assertTrue(any("older than" in warning for warning in report["warnings"]))
|
|
120
|
+
|
|
121
|
+
def test_main_returns_one_when_errors_exist(self):
|
|
122
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
123
|
+
self.assertEqual(doctor.main([str(self.target), "--root", str(self.source)]), 1)
|
|
124
|
+
|
|
125
|
+
def test_main_returns_zero_for_healthy_installation(self):
|
|
126
|
+
self.apply()
|
|
127
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
128
|
+
self.assertEqual(doctor.main([str(self.target), "--root", str(self.source)]), 0)
|
|
129
|
+
|
|
130
|
+
def test_fix_restores_missing_managed_file(self):
|
|
131
|
+
self.apply()
|
|
132
|
+
(self.target / "ai-kit/CORE.md").unlink()
|
|
133
|
+
self.assertTrue(any("Missing managed file: ai-kit/CORE.md" in error
|
|
134
|
+
for error in self.examine()["errors"]))
|
|
135
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
136
|
+
code = doctor.main([str(self.target), "--root", str(self.source), "--fix"])
|
|
137
|
+
self.assertEqual(code, 0)
|
|
138
|
+
self.assertTrue((self.target / "ai-kit/CORE.md").is_file())
|
|
139
|
+
self.assertEqual(self.examine()["errors"], [])
|
|
140
|
+
|
|
141
|
+
def test_fix_is_a_noop_for_a_healthy_installation(self):
|
|
142
|
+
self.apply()
|
|
143
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
144
|
+
self.assertEqual(doctor.main([str(self.target), "--root", str(self.source), "--fix"]), 0)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
if __name__ == "__main__":
|
|
148
|
+
unittest.main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Exercise private task packs and measurement-pair coverage reports."""
|
|
2
|
+
import contextlib
|
|
3
|
+
import io
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import sys
|
|
7
|
+
import tempfile
|
|
8
|
+
import unittest
|
|
9
|
+
|
|
10
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
|
11
|
+
import evaluate
|
|
12
|
+
import metrics
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def record(task_id, arm, outcome="correct"):
|
|
16
|
+
return {"schema": 2, "task_id": task_id, "experiment": "trial", "arm": arm,
|
|
17
|
+
"kit_version": "test", "outcome": outcome, "checks": "passed" if outcome == "correct" else "failed",
|
|
18
|
+
"rework": 0, "escalations": 0,
|
|
19
|
+
"attempts": [{"provider": "provider", "model": "model", "effort": None,
|
|
20
|
+
"disposition": "succeeded" if outcome == "correct" else "failed",
|
|
21
|
+
"duration_seconds": None, "input_tokens": None, "cached_input_tokens": None,
|
|
22
|
+
"output_tokens": None, "reasoning_tokens": None, "cost": None}]}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class EvaluationTests(unittest.TestCase):
|
|
26
|
+
def setUp(self):
|
|
27
|
+
self.temp = tempfile.TemporaryDirectory(prefix="ai-kit-evaluate-")
|
|
28
|
+
self.addCleanup(self.temp.cleanup)
|
|
29
|
+
self.root = Path(self.temp.name).resolve()
|
|
30
|
+
self.project = self.root / "project"
|
|
31
|
+
self.project.mkdir()
|
|
32
|
+
self.pack_path = self.root / "tasks.json"
|
|
33
|
+
|
|
34
|
+
def test_scaffold_is_preview_first_and_refuses_overwrite(self):
|
|
35
|
+
plan = evaluate.scaffold_plan(self.pack_path, "trial", ["task-01", "task-02"])
|
|
36
|
+
self.assertTrue(plan["changed"])
|
|
37
|
+
self.assertFalse(self.pack_path.exists())
|
|
38
|
+
self.assertTrue(evaluate.apply_scaffold(plan))
|
|
39
|
+
self.assertTrue(self.pack_path.is_file())
|
|
40
|
+
with self.assertRaises(ValueError):
|
|
41
|
+
evaluate.scaffold_plan(self.pack_path, "other", ["task-01"])
|
|
42
|
+
|
|
43
|
+
def test_coverage_reports_missing_baseline_kit_pairs_and_unexpected_records(self):
|
|
44
|
+
plan = evaluate.scaffold_plan(self.pack_path, "trial", ["task-01", "task-02"])
|
|
45
|
+
evaluate.apply_scaffold(plan)
|
|
46
|
+
metrics.record_task(self.project, record("task-01", "baseline"), apply=True)
|
|
47
|
+
metrics.record_task(self.project, record("task-01", "kit"), apply=True)
|
|
48
|
+
metrics.record_task(self.project, record("task-02", "baseline", "incorrect"), apply=True)
|
|
49
|
+
metrics.record_task(self.project, record("other", "kit"), apply=True)
|
|
50
|
+
report = evaluate.coverage(self.project, self.pack_path)
|
|
51
|
+
self.assertEqual(report["complete_pairs"], 1)
|
|
52
|
+
self.assertEqual(report["missing"], [{"task_id": "task-02", "arms": ["kit"]}])
|
|
53
|
+
self.assertEqual(report["unexpected_records"], [{"task_id": "other", "arm": "kit"}])
|
|
54
|
+
self.assertEqual(report["reviewed_outcomes"], {"correct": 2, "incorrect": 1, "incomplete": 0})
|
|
55
|
+
|
|
56
|
+
def test_validation_and_cli_reject_nonopaque_task_content(self):
|
|
57
|
+
with self.assertRaises(ValueError):
|
|
58
|
+
evaluate.validate_pack({"schema": 1, "experiment": "trial", "arms": ["baseline", "kit"],
|
|
59
|
+
"tasks": [{"task_id": "please fix payment bug"}]})
|
|
60
|
+
with contextlib.redirect_stderr(io.StringIO()):
|
|
61
|
+
self.assertEqual(evaluate.main(["scaffold", "--output", str(self.pack_path), "--experiment", "trial",
|
|
62
|
+
"--task", "task one"]), 1)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
unittest.main()
|