katalyst-plugin-harness 0.1.1a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. katalyst_plugin_harness-0.1.1a1/.gitignore +123 -0
  2. katalyst_plugin_harness-0.1.1a1/PKG-INFO +15 -0
  3. katalyst_plugin_harness-0.1.1a1/pyproject.toml +48 -0
  4. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/__init__.py +7 -0
  5. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/adapters/__init__.py +1 -0
  6. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/adapters/jinja_settings.py +61 -0
  7. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/adapters/opkg.py +214 -0
  8. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/adapters/packages.py +62 -0
  9. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/adapters/taxonomy_catalog.py +206 -0
  10. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/cli.py +138 -0
  11. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/composition.py +80 -0
  12. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/creation/agent.yaml.j2 +20 -0
  13. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/creation/agent_skill.yaml.j2 +13 -0
  14. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/creation/harness.yaml.j2 +18 -0
  15. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/__init__.py +41 -0
  16. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/errors.py +17 -0
  17. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/model.py +153 -0
  18. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/package.py +238 -0
  19. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/reports.py +128 -0
  20. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/domain/wiring.py +140 -0
  21. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/__init__.py +15 -0
  22. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/harness.yaml +225 -0
  23. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/harness_relationships.yaml +57 -0
  24. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/released/0.1.0/SHA256SUMS +2 -0
  25. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/released/0.1.0/harness.yaml +225 -0
  26. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/linkml/released/0.1.0/harness_relationships.yaml +57 -0
  27. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/lint.py +48 -0
  28. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/mcp_tools.py +71 -0
  29. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/plugin.py +48 -0
  30. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/ports/__init__.py +8 -0
  31. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/ports/catalog.py +15 -0
  32. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/ports/openpackage.py +39 -0
  33. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/ports/packages.py +22 -0
  34. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/ports/templates.py +19 -0
  35. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/py.typed +0 -0
  36. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/schema.py +123 -0
  37. katalyst_plugin_harness-0.1.1a1/src/katalyst_plugin_harness/service.py +217 -0
  38. katalyst_plugin_harness-0.1.1a1/tests/conftest.py +22 -0
  39. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/README.md +11 -0
  40. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/_manifests/agents.yaml +95 -0
  41. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-code-reviewer.md +386 -0
  42. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-code-reviewer.yaml +34 -0
  43. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-architect.md +142 -0
  44. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-architect.yaml +25 -0
  45. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-backend.md +161 -0
  46. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-backend.yaml +25 -0
  47. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-commit.md +182 -0
  48. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-commit.yaml +24 -0
  49. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-deploy.md +117 -0
  50. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-deploy.yaml +25 -0
  51. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-design.md +168 -0
  52. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-design.yaml +25 -0
  53. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-devops.md +140 -0
  54. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-devops.yaml +26 -0
  55. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-feedback.md +148 -0
  56. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-feedback.yaml +25 -0
  57. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-frontend.md +215 -0
  58. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-frontend.yaml +29 -0
  59. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-implement.md +137 -0
  60. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-implement.yaml +25 -0
  61. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-operate.md +178 -0
  62. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-operate.yaml +24 -0
  63. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-orchestrate.md +125 -0
  64. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-orchestrate.yaml +25 -0
  65. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-pm.md +214 -0
  66. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-pm.yaml +25 -0
  67. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-product.md +148 -0
  68. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-product.yaml +25 -0
  69. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-qa-lead.md +147 -0
  70. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-qa-lead.yaml +25 -0
  71. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-qa.md +156 -0
  72. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-qa.yaml +25 -0
  73. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-release.md +146 -0
  74. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-release.yaml +24 -0
  75. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-review.md +206 -0
  76. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-review.yaml +26 -0
  77. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-security.md +148 -0
  78. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-security.yaml +25 -0
  79. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-tester.md +299 -0
  80. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-tester.yaml +25 -0
  81. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-verify.md +181 -0
  82. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge-verify.yaml +25 -0
  83. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge.md +273 -0
  84. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-forge.yaml +27 -0
  85. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-intake.md +258 -0
  86. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-intake.yaml +21 -0
  87. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-scribe.md +282 -0
  88. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-scribe.yaml +22 -0
  89. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-validator.md +259 -0
  90. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension-validator.yaml +21 -0
  91. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension.md +134 -0
  92. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-extension.yaml +27 -0
  93. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-analyzer.md +231 -0
  94. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-analyzer.yaml +22 -0
  95. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-intake.md +223 -0
  96. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-intake.yaml +23 -0
  97. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-scribe.md +462 -0
  98. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-scribe.yaml +22 -0
  99. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-validator.md +311 -0
  100. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type-validator.yaml +22 -0
  101. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type.md +126 -0
  102. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-layer-type.yaml +27 -0
  103. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-intake.md +594 -0
  104. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-intake.yaml +24 -0
  105. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-scribe.md +548 -0
  106. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-scribe.yaml +24 -0
  107. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-validator.md +270 -0
  108. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy-validator.yaml +21 -0
  109. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy.md +269 -0
  110. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-build-taxonomy.yaml +29 -0
  111. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-dependency-analyzer.md +321 -0
  112. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-dependency-analyzer.yaml +23 -0
  113. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-practice-auditor.md +138 -0
  114. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-practice-auditor.yaml +25 -0
  115. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-validator-fixer.md +342 -0
  116. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-validator-fixer.yaml +25 -0
  117. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-writer.md +316 -0
  118. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-tax-writer.yaml +22 -0
  119. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-adr.md +340 -0
  120. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-adr.yaml +24 -0
  121. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-capability.md +385 -0
  122. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-capability.yaml +25 -0
  123. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-ddd.md +519 -0
  124. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-ddd.yaml +26 -0
  125. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-expert.md +208 -0
  126. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-expert.yaml +29 -0
  127. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-nfr.md +352 -0
  128. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-nfr.yaml +24 -0
  129. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-adr.md +122 -0
  130. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-adr.yaml +23 -0
  131. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-api.md +95 -0
  132. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-api.yaml +23 -0
  133. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-auth.md +94 -0
  134. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-auth.yaml +23 -0
  135. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-bdd.md +141 -0
  136. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-bdd.yaml +27 -0
  137. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-config.md +97 -0
  138. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-config.yaml +25 -0
  139. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-ddd.md +155 -0
  140. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-ddd.yaml +27 -0
  141. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-docs.md +94 -0
  142. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-docs.yaml +23 -0
  143. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-domain.md +95 -0
  144. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-domain.yaml +25 -0
  145. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-nfr.md +145 -0
  146. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-nfr.yaml +23 -0
  147. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-system.md +135 -0
  148. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-system.yaml +25 -0
  149. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-ui.md +95 -0
  150. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-scan-ui.yaml +25 -0
  151. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-spec.md +466 -0
  152. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-spec.yaml +27 -0
  153. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-system.md +563 -0
  154. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-system.yaml +27 -0
  155. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-user-need.md +367 -0
  156. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-user-need.yaml +26 -0
  157. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-user-type.md +284 -0
  158. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent/kata-xray-user-type.yaml +23 -0
  159. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-feature/SKILL.md +278 -0
  160. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-feature/scripts/forge_run_report.py +132 -0
  161. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-feature.yaml +16 -0
  162. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-model-router/SKILL.md +322 -0
  163. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-model-router/scripts/dispatch.py +1044 -0
  164. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-model-router/scripts/doctor.py +465 -0
  165. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/forge-model-router.yaml +22 -0
  166. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-app-docker/SKILL.md +185 -0
  167. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-app-docker.yaml +14 -0
  168. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-astro/SKILL.md +331 -0
  169. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-astro.yaml +14 -0
  170. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-cicd/SKILL.md +111 -0
  171. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-cicd.yaml +15 -0
  172. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-circuit/SKILL.md +136 -0
  173. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-circuit.yaml +16 -0
  174. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-environments/SKILL.md +165 -0
  175. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-environments.yaml +13 -0
  176. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-extension-builder/SKILL.md +199 -0
  177. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-extension-builder.yaml +13 -0
  178. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/SKILL.md +247 -0
  179. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/scripts/forge-reconcile.mjs +226 -0
  180. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/scripts/forge-size-gate.sh +61 -0
  181. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/scripts/kata-gate.sh +232 -0
  182. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/scripts/marker-contract.mjs +380 -0
  183. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge/scripts/worktree-gate.sh +121 -0
  184. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-forge.yaml +21 -0
  185. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-iac-terragrunt/SKILL.md +167 -0
  186. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-iac-terragrunt.yaml +14 -0
  187. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-k8s-argocd/SKILL.md +159 -0
  188. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-k8s-argocd.yaml +14 -0
  189. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-k8s-kustomize/SKILL.md +152 -0
  190. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-k8s-kustomize.yaml +14 -0
  191. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-layer-type-builder/SKILL.md +176 -0
  192. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-layer-type-builder.yaml +13 -0
  193. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-navigator/SKILL.md +155 -0
  194. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-navigator.yaml +13 -0
  195. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-loader/SKILL.md +136 -0
  196. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-loader.yaml +14 -0
  197. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-reporter/SKILL.md +129 -0
  198. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-reporter.yaml +13 -0
  199. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-resolver/SKILL.md +296 -0
  200. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-resolver/context-sources.yaml +68 -0
  201. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-practice-resolver.yaml +15 -0
  202. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-taxonomy/SKILL.md +385 -0
  203. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-taxonomy.yaml +14 -0
  204. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-ux-audit/SKILL.md +173 -0
  205. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-ux-audit.yaml +14 -0
  206. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-writer/SKILL.md +291 -0
  207. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/agent_skill/katalyst-writer.yaml +15 -0
  208. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/harness/claude/agent.yaml.j2 +3 -0
  209. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/harness/claude.yaml +105 -0
  210. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/harness/opencode/agent.yaml.j2 +19 -0
  211. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/agentic/harness/opencode.yaml +90 -0
  212. katalyst_plugin_harness-0.1.1a1/tests/fixtures/collection/templates/manifest.json +26 -0
  213. katalyst_plugin_harness-0.1.1a1/tests/golden/installed-claude.yaml +752 -0
  214. katalyst_plugin_harness-0.1.1a1/tests/golden/installed-opencode.yaml +1340 -0
  215. katalyst_plugin_harness-0.1.1a1/tests/golden/package-claude.yaml +1213 -0
  216. katalyst_plugin_harness-0.1.1a1/tests/golden/package-opencode.yaml +1850 -0
  217. katalyst_plugin_harness-0.1.1a1/tests/harness_support.py +198 -0
  218. katalyst_plugin_harness-0.1.1a1/tests/test_harness_additions.py +92 -0
  219. katalyst_plugin_harness-0.1.1a1/tests/test_harness_cli.py +177 -0
  220. katalyst_plugin_harness-0.1.1a1/tests/test_harness_lint.py +66 -0
  221. katalyst_plugin_harness-0.1.1a1/tests/test_harness_package.py +282 -0
  222. katalyst_plugin_harness-0.1.1a1/tests/test_harness_real_opkg.py +128 -0
  223. katalyst_plugin_harness-0.1.1a1/tests/test_harness_sync.py +139 -0
  224. katalyst_plugin_harness-0.1.1a1/tests/test_opkg_resolution.py +102 -0
@@ -0,0 +1,123 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ # Not a Python build directory: Bard's SPA keeps shared helpers (utils.ts, download.ts) in
19
+ # src/lib, and ignoring it left a fresh clone unable to build or test the SPA.
20
+ !plugins/bard/web/src/lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ *.egg-info/
27
+ .installed.cfg
28
+ *.egg
29
+
30
+ # PyInstaller
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .nox/
42
+ .coverage
43
+ .coverage.*
44
+ .cache
45
+ nosetests.xml
46
+ coverage.xml
47
+ *.cover
48
+ *.py,cover
49
+ .hypothesis/
50
+ .pytest_cache/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Environments
57
+ .env
58
+ .venv
59
+ env/
60
+ venv/
61
+ ENV/
62
+ env.bak/
63
+ venv.bak/
64
+
65
+ # Spyder project settings
66
+ .spyderproject
67
+ .spyproject
68
+
69
+ # Rope project settings
70
+ .ropeproject
71
+
72
+ # mkdocs documentation
73
+ /site
74
+
75
+ # mypy / pyright
76
+ .mypy_cache/
77
+ .dmypy.json
78
+ dmypy.json
79
+ .pyright/
80
+
81
+ # Ruff
82
+ .ruff_cache/
83
+
84
+ # IDE
85
+ .idea/
86
+ .vscode/
87
+ *.swp
88
+ *.swo
89
+ *~
90
+
91
+ # OS
92
+ .DS_Store
93
+ Thumbs.db
94
+
95
+ # Local configuration
96
+ *.local
97
+
98
+ # Browser/Playwright state files
99
+ browser-state-*.json
100
+
101
+ # Agent harness scratch (run exhaust, never the design bundle)
102
+ .opencode/sessions/
103
+ .opencode/analysis/
104
+ .opencode/package-lock.json
105
+
106
+ # Build artifacts
107
+ site/
108
+ stack-tests/cucumber-report/
109
+ stack-tests/test-results/
110
+
111
+ # Generated artifacts (rebuild with `just generate-schemas`)
112
+ taxonomy/src/katalyst_taxonomy/engine/generated/
113
+ .worktrees/
114
+ .plan-74-75-76-77.md
115
+ .HANDOFF-scaffolding-wiring.md
116
+ .HANDOFF-2-cicd-migration.md
117
+ .HANDOFF-action-execution-fixes.md
118
+ .HANDOFF-bdd-coverage.md
119
+ .HANDOFF-*.md
120
+ docs/superpowers/
121
+
122
+ # Node dependencies — installed, never committed
123
+ node_modules/
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.5
2
+ Name: katalyst-plugin-harness
3
+ Version: 0.1.1a1
4
+ Summary: Katalyst harness plugin — install the taxonomy's agents and skills into coding-agent harnesses with OpenPackage
5
+ Author: eSimplicity
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Requires-Dist: click>=8.0
9
+ Requires-Dist: jinja2>=3.1
10
+ Requires-Dist: katalyst-core<1,>=0.1
11
+ Requires-Dist: katalyst-engine<6,>=5
12
+ Requires-Dist: katalyst-taxonomy-cli<3,>=2
13
+ Requires-Dist: katalyst-taxonomy-mcp<5,>=4
14
+ Requires-Dist: katalyst-taxonomy<6,>=5
15
+ Requires-Dist: pyyaml
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "katalyst-plugin-harness"
3
+ version = "0.1.1a1"
4
+ description = "Katalyst harness plugin — install the taxonomy's agents and skills into coding-agent harnesses with OpenPackage"
5
+ license = { text = "Proprietary" }
6
+ requires-python = ">=3.12"
7
+ authors = [
8
+ { name = "eSimplicity" }
9
+ ]
10
+ dependencies = [
11
+ # Bounded to the config-rooted runtime this plugin is written against.
12
+ "katalyst-taxonomy>=5,<6",
13
+ "katalyst-engine>=5,<6",
14
+ # Its MCP tools use the server's response helpers; its commands, the CLI context and options.
15
+ "katalyst-taxonomy-mcp>=4,<5",
16
+ "katalyst-taxonomy-cli>=2,<3",
17
+ "katalyst-core>=0.1,<1",
18
+ "pyyaml",
19
+ # A harness's settings for an agent are rendered from the Jinja template its node names.
20
+ "jinja2>=3.1",
21
+ "click>=8.0",
22
+ ]
23
+
24
+ [project.entry-points."katalyst_taxonomy.plugins"]
25
+ harness = "katalyst_plugin_harness:HarnessPlugin"
26
+
27
+ # agent, agent_skill and harness are ordinary registered kinds, declared like any bundle's,
28
+ # so any schema bundle's repository can carry agents.
29
+ [project.entry-points."katalyst_core.modules"]
30
+ # The schema, as LinkML modules on katalyst-core (the bundle builds its definitions
31
+ # from them).
32
+ harness = "katalyst_plugin_harness.linkml:MODULES"
33
+
34
+ [project.entry-points."katalyst_engine.bundles"]
35
+ harness-schema = "katalyst_plugin_harness.schema:HarnessSchemaBundle"
36
+
37
+ [project.entry-points."katalyst_taxonomy.cli"]
38
+ harness = "katalyst_plugin_harness.cli:create_group"
39
+
40
+ [build-system]
41
+ requires = ["hatchling"]
42
+ build-backend = "hatchling.build"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/katalyst_plugin_harness"]
46
+
47
+ [tool.hatch.build.targets.wheel.sources]
48
+ "src" = ""
@@ -0,0 +1,7 @@
1
+ """Katalyst harness plugin: the taxonomy's agents and skills, installed into each
2
+ coding-agent harness (OpenCode, Claude Code, ...) with OpenPackage.
3
+ """
4
+
5
+ from katalyst_plugin_harness.plugin import HarnessPlugin
6
+
7
+ __all__ = ["HarnessPlugin"]
@@ -0,0 +1 @@
1
+ """The harness plugin's adapters: OpenPackage, the package cache, Jinja, the taxonomy."""
@@ -0,0 +1,61 @@
1
+ """Jinja: a harness's settings for one agent or skill, rendered and read as YAML."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from pathlib import Path
7
+ from typing import Any, cast
8
+
9
+ import yaml
10
+ from jinja2 import Environment, FileSystemLoader, StrictUndefined, TemplateError
11
+
12
+ from katalyst_plugin_harness.domain.errors import HarnessError
13
+
14
+ __all__ = ["JinjaSettingsRenderer"]
15
+
16
+
17
+ class JinjaSettingsRenderer:
18
+ """Implements :class:`~katalyst_plugin_harness.ports.SettingsRenderer`.
19
+
20
+ Undefined names are errors (``StrictUndefined``): a template naming a field the node
21
+ does not have fails instead of rendering an empty value. An empty rendering is no
22
+ settings.
23
+ """
24
+
25
+ def __init__(self) -> None:
26
+ self._environments: dict[Path, Environment] = {}
27
+
28
+ def _environment(self, directory: Path) -> Environment:
29
+ environment = self._environments.get(directory)
30
+ if environment is None:
31
+ environment = Environment(
32
+ loader=FileSystemLoader(str(directory)),
33
+ undefined=StrictUndefined,
34
+ keep_trailing_newline=True,
35
+ autoescape=False,
36
+ )
37
+ self._environments[directory] = environment
38
+ return environment
39
+
40
+ def render(self, template: Path, context: Mapping[str, object]) -> Mapping[str, object]:
41
+ if not template.is_file():
42
+ raise HarnessError(f"harness template not found: {template}")
43
+ try:
44
+ text = (
45
+ self._environment(template.parent)
46
+ .get_template(template.name)
47
+ .render(**dict(context))
48
+ )
49
+ except TemplateError as exc:
50
+ raise HarnessError(f"{template}: {exc}") from exc
51
+ try:
52
+ loaded: object = yaml.safe_load(text)
53
+ except yaml.YAMLError as exc:
54
+ raise HarnessError(f"{template} did not render YAML: {exc}") from exc
55
+ if loaded is None:
56
+ return {}
57
+ if not isinstance(loaded, dict):
58
+ raise HarnessError(
59
+ f"{template} must render a mapping of settings, got {type(loaded).__name__}"
60
+ )
61
+ return cast("dict[str, Any]", loaded)
@@ -0,0 +1,214 @@
1
+ """OpenPackage (``opkg``) run as a subprocess: the pinned CLI, fetched with npm on first use.
2
+
3
+ Where ``opkg`` comes from, in order: ``KATALYST_OPKG`` (a path to an executable — for
4
+ machines whose endpoint security only allows an approved binary, and for offline use),
5
+ then the pinned version installed in the Katalyst cache
6
+ (``<cache home>/harness/opkg/<version>``), fetched there with npm the first time. An
7
+ ``opkg`` on ``PATH`` is deliberately not used: the pinned one is what is tested.
8
+
9
+ What OpenPackage installed is read from its index (``.openpackage/openpackage.index.yml``
10
+ in the workspace, or in the home directory for a global install), which it documents as
11
+ the record of every file a package put where.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import shutil
18
+ import subprocess
19
+ from collections.abc import Callable, Mapping
20
+ from pathlib import Path
21
+ from typing import Any, cast
22
+
23
+ import yaml
24
+
25
+ from katalyst_plugin_harness.domain.errors import (
26
+ OpenPackageError,
27
+ OpenPackageUnavailableError,
28
+ )
29
+ from katalyst_plugin_harness.domain.model import Scope
30
+
31
+ __all__ = [
32
+ "OPKG_ENV",
33
+ "OPKG_VERSION",
34
+ "SubprocessOpenPackage",
35
+ "opkg_cache_dir",
36
+ "resolve_opkg",
37
+ ]
38
+
39
+ #: The OpenPackage CLI the harness plugin is built and tested against.
40
+ OPKG_VERSION = "0.9.5"
41
+
42
+ #: Overrides where ``opkg`` comes from: a path to the executable.
43
+ OPKG_ENV = "KATALYST_OPKG"
44
+
45
+ _INDEX = Path(".openpackage") / "openpackage.index.yml"
46
+
47
+ #: How much of a failed run's output an error carries.
48
+ _TAIL_LINES = 30
49
+
50
+
51
+ def opkg_cache_dir(version: str = OPKG_VERSION) -> Path:
52
+ """Where the pinned ``opkg`` is installed: ``<cache home>/harness/opkg/<version>``."""
53
+ from katalyst_taxonomy.domain.homes import resolve_home
54
+
55
+ return resolve_home().cache_dir / "harness" / "opkg" / version
56
+
57
+
58
+ def _opkg_in(prefix: Path) -> Path | None:
59
+ binary = prefix / "node_modules" / ".bin" / "opkg"
60
+ return binary if binary.is_file() else None
61
+
62
+
63
+ def _fetch_opkg(
64
+ prefix: Path, version: str, echo: Callable[[str], None], which: Callable[[str], str | None]
65
+ ) -> Path:
66
+ npm = which("npm")
67
+ if npm is None:
68
+ raise OpenPackageUnavailableError(
69
+ f"OpenPackage (opkg {version}) is needed to install into a harness, and npm, "
70
+ f"which fetches it, is not on PATH (it comes with Node.js 20+). Install Node.js, "
71
+ f"or set {OPKG_ENV} to an opkg executable."
72
+ )
73
+ echo(f"Fetching OpenPackage {version} into {prefix} (first run only)…")
74
+ prefix.mkdir(parents=True, exist_ok=True)
75
+ result = subprocess.run(
76
+ [
77
+ npm,
78
+ "install",
79
+ "--prefix",
80
+ str(prefix),
81
+ "--no-save",
82
+ "--no-audit",
83
+ "--no-fund",
84
+ f"opkg@{version}",
85
+ ],
86
+ check=False,
87
+ capture_output=True,
88
+ text=True,
89
+ stdin=subprocess.DEVNULL,
90
+ )
91
+ binary = _opkg_in(prefix)
92
+ if result.returncode != 0 or binary is None:
93
+ raise OpenPackageUnavailableError(
94
+ f"Fetching OpenPackage {version} failed (npm exit {result.returncode}): "
95
+ f"{_tail(result.stdout + result.stderr)}\n"
96
+ f"Set {OPKG_ENV} to an opkg executable to use one you already have."
97
+ )
98
+ return binary
99
+
100
+
101
+ def resolve_opkg(
102
+ *,
103
+ env: Mapping[str, str] | None = None,
104
+ echo: Callable[[str], None] = print,
105
+ which: Callable[[str], str | None] = shutil.which,
106
+ cache_dir: Path | None = None,
107
+ ) -> Path:
108
+ """The ``opkg`` executable to run: ``KATALYST_OPKG``, else the pinned one (fetched).
109
+
110
+ Raises:
111
+ OpenPackageUnavailableError: ``KATALYST_OPKG`` names no file, or there is no
112
+ cached copy and no npm to fetch one with.
113
+ """
114
+ environ = os.environ if env is None else env
115
+ explicit = environ.get(OPKG_ENV, "").strip()
116
+ if explicit:
117
+ chosen = Path(explicit).expanduser()
118
+ if not chosen.is_file():
119
+ raise OpenPackageUnavailableError(f"{OPKG_ENV} names no file: {chosen}")
120
+ return chosen
121
+ prefix = cache_dir if cache_dir is not None else opkg_cache_dir()
122
+ cached = _opkg_in(prefix)
123
+ if cached is not None:
124
+ return cached
125
+ return _fetch_opkg(prefix, OPKG_VERSION, echo, which)
126
+
127
+
128
+ def _tail(output: str) -> str:
129
+ lines = [line for line in output.strip().splitlines() if line.strip()]
130
+ return "\n".join(lines[-_TAIL_LINES:])
131
+
132
+
133
+ class SubprocessOpenPackage:
134
+ """Implements :class:`~katalyst_plugin_harness.ports.OpenPackage` with the ``opkg`` CLI.
135
+
136
+ *resolve* finds the executable; it is called on the first install or uninstall, so
137
+ reading what is installed (``status``, a dry run) never fetches anything. *home* is
138
+ where a global install goes (default: the user's home).
139
+ """
140
+
141
+ def __init__(
142
+ self,
143
+ resolve: Callable[[], Path] = resolve_opkg,
144
+ *,
145
+ home: Path | None = None,
146
+ env: Mapping[str, str] | None = None,
147
+ ) -> None:
148
+ self._resolve = resolve
149
+ self._executable: Path | None = None
150
+ self._home = home
151
+ self._env = env
152
+
153
+ def _home_dir(self) -> Path:
154
+ return self._home if self._home is not None else Path.home()
155
+
156
+ def _run(self, args: list[str], *, scope: Scope, workspace: Path) -> None:
157
+ if self._executable is None:
158
+ self._executable = self._resolve()
159
+ command = [str(self._executable), *args, *(["--global"] if scope == "global" else [])]
160
+ environ = {**(os.environ if self._env is None else self._env), "NO_COLOR": "1"}
161
+ if self._home is not None:
162
+ environ["HOME"] = str(self._home)
163
+ try:
164
+ result = subprocess.run(
165
+ command,
166
+ cwd=workspace,
167
+ env=environ,
168
+ check=False,
169
+ capture_output=True,
170
+ text=True,
171
+ stdin=subprocess.DEVNULL,
172
+ )
173
+ except OSError as exc:
174
+ raise OpenPackageError(f"could not run {command[0]}: {exc}") from exc
175
+ if result.returncode != 0:
176
+ raise OpenPackageError(
177
+ f"opkg {args[0]} failed (exit {result.returncode}):\n"
178
+ f"{_tail(result.stdout + result.stderr)}"
179
+ )
180
+
181
+ def install(self, package_dir: Path, *, platform: str, scope: Scope, workspace: Path) -> None:
182
+ self._run(
183
+ ["install", str(package_dir), "--platforms", platform, "--force"],
184
+ scope=scope,
185
+ workspace=workspace,
186
+ )
187
+
188
+ def uninstall(self, package: str, *, scope: Scope, workspace: Path) -> None:
189
+ self._run(["uninstall", package], scope=scope, workspace=workspace)
190
+
191
+ def installed(
192
+ self, package: str, *, scope: Scope, workspace: Path
193
+ ) -> Mapping[str, tuple[str, ...]] | None:
194
+ index = (self._home_dir() if scope == "global" else workspace) / _INDEX
195
+ try:
196
+ loaded: object = yaml.safe_load(index.read_text(encoding="utf-8"))
197
+ except FileNotFoundError:
198
+ return None
199
+ except (OSError, yaml.YAMLError) as exc:
200
+ raise OpenPackageError(f"cannot read OpenPackage's index {index}: {exc}") from exc
201
+ packages = _mapping(_mapping(loaded).get("packages"))
202
+ if package not in packages:
203
+ return None
204
+ files = _mapping(_mapping(packages[package]).get("files"))
205
+ return {
206
+ str(source): tuple(str(t) for t in cast("list[Any]", targets))
207
+ if isinstance(targets, list)
208
+ else ()
209
+ for source, targets in files.items()
210
+ }
211
+
212
+
213
+ def _mapping(value: object) -> dict[str, Any]:
214
+ return cast("dict[str, Any]", value) if isinstance(value, dict) else {}
@@ -0,0 +1,62 @@
1
+ """Packages written to the Katalyst cache, one directory per harness of one repository.
2
+
3
+ ``<cache home>/harness/packages/<repository key>/<harness>/``: the key is derived from
4
+ the repository's path, so two repositories with a harness of the same name do not share a
5
+ package. A markdown file is its generated frontmatter followed by the body file's text;
6
+ every other file is copied as it is.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import shutil
13
+ from pathlib import Path
14
+
15
+ import yaml
16
+
17
+ from katalyst_plugin_harness.domain.package import MANIFEST, Package
18
+
19
+ __all__ = ["CachePackageStore", "markdown", "package_root"]
20
+
21
+
22
+ def package_root(workspace: Path) -> Path:
23
+ """Where the packages of the repository at *workspace* are built."""
24
+ from katalyst_taxonomy.domain.homes import resolve_home
25
+
26
+ key = hashlib.sha256(str(workspace.resolve()).encode()).hexdigest()[:16]
27
+ return resolve_home().cache_dir / "harness" / "packages" / key
28
+
29
+
30
+ def _yaml(data: object) -> str:
31
+ return yaml.safe_dump(data, sort_keys=False, width=100, allow_unicode=True)
32
+
33
+
34
+ def markdown(frontmatter: object, body: str) -> str:
35
+ """A markdown file: ``---`` frontmatter ``---``, a blank line, then *body*."""
36
+ return f"---\n{_yaml(frontmatter)}---\n\n{body.lstrip(chr(10))}"
37
+
38
+
39
+ class CachePackageStore:
40
+ """Implements :class:`~katalyst_plugin_harness.ports.PackageStore` under *root*."""
41
+
42
+ def __init__(self, root: Path) -> None:
43
+ self._root = root
44
+
45
+ def location(self, package: Package) -> Path:
46
+ return self._root / package.harness.name
47
+
48
+ def write(self, package: Package) -> Path:
49
+ directory = self.location(package)
50
+ if directory.exists():
51
+ shutil.rmtree(directory)
52
+ directory.mkdir(parents=True)
53
+ (directory / MANIFEST).write_text(_yaml(dict(package.manifest)), encoding="utf-8")
54
+ for item in package.files:
55
+ target = directory / item.path
56
+ target.parent.mkdir(parents=True, exist_ok=True)
57
+ if item.frontmatter is None:
58
+ shutil.copy2(item.source, target)
59
+ else:
60
+ body = item.source.read_text(encoding="utf-8")
61
+ target.write_text(markdown(dict(item.frontmatter), body), encoding="utf-8")
62
+ return directory