calcifier 0.1.1__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 (268) hide show
  1. calcifier-0.1.1/.claude-plugin/marketplace.json +15 -0
  2. calcifier-0.1.1/.github/dependabot.yml +21 -0
  3. calcifier-0.1.1/.github/workflows/actionlint.yml +38 -0
  4. calcifier-0.1.1/.github/workflows/ci.yml +181 -0
  5. calcifier-0.1.1/.github/workflows/mutation.yml +116 -0
  6. calcifier-0.1.1/.github/workflows/publish.yml +127 -0
  7. calcifier-0.1.1/.github/workflows/zizmor.yml +29 -0
  8. calcifier-0.1.1/.gitignore +27 -0
  9. calcifier-0.1.1/AGENTS.md +53 -0
  10. calcifier-0.1.1/CHANGELOG.md +77 -0
  11. calcifier-0.1.1/CODE_OF_CONDUCT.md +73 -0
  12. calcifier-0.1.1/CONTRIBUTING.md +147 -0
  13. calcifier-0.1.1/LICENSE +21 -0
  14. calcifier-0.1.1/Makefile +95 -0
  15. calcifier-0.1.1/PKG-INFO +127 -0
  16. calcifier-0.1.1/README.md +99 -0
  17. calcifier-0.1.1/SECURITY.md +51 -0
  18. calcifier-0.1.1/SUPPORT.md +14 -0
  19. calcifier-0.1.1/docs/architecture.md +215 -0
  20. calcifier-0.1.1/docs/providers.md +127 -0
  21. calcifier-0.1.1/docs/recipes.md +202 -0
  22. calcifier-0.1.1/docs/trace-schema.json +768 -0
  23. calcifier-0.1.1/docs/usage.md +192 -0
  24. calcifier-0.1.1/plugins/calcifier/.claude-plugin/plugin.json +13 -0
  25. calcifier-0.1.1/plugins/calcifier/skills/calcifier/.calcifier/recipe.py +33 -0
  26. calcifier-0.1.1/plugins/calcifier/skills/calcifier/SKILL.md +43 -0
  27. calcifier-0.1.1/plugins/calcifier/skills/debug/.calcifier/recipe.py +38 -0
  28. calcifier-0.1.1/plugins/calcifier/skills/debug/SKILL.md +41 -0
  29. calcifier-0.1.1/plugins/calcifier/skills/exec/.calcifier/recipe.py +40 -0
  30. calcifier-0.1.1/plugins/calcifier/skills/exec/SKILL.md +46 -0
  31. calcifier-0.1.1/plugins/calcifier/skills/update/.calcifier/recipe.py +33 -0
  32. calcifier-0.1.1/plugins/calcifier/skills/update/SKILL.md +36 -0
  33. calcifier-0.1.1/pyproject.toml +141 -0
  34. calcifier-0.1.1/scripts/acceptance.py +687 -0
  35. calcifier-0.1.1/scripts/acceptance.sh +5 -0
  36. calcifier-0.1.1/scripts/compiler_replay.py +293 -0
  37. calcifier-0.1.1/scripts/mutation_shards.py +59 -0
  38. calcifier-0.1.1/scripts/mutation_threshold.py +111 -0
  39. calcifier-0.1.1/scripts/mutation_weights.json +327 -0
  40. calcifier-0.1.1/scripts/verify_artifacts.py +173 -0
  41. calcifier-0.1.1/src/calcifier/__init__.py +73 -0
  42. calcifier-0.1.1/src/calcifier/agent_config.py +263 -0
  43. calcifier-0.1.1/src/calcifier/agent_events.py +450 -0
  44. calcifier-0.1.1/src/calcifier/agent_providers.py +342 -0
  45. calcifier-0.1.1/src/calcifier/agents.py +227 -0
  46. calcifier-0.1.1/src/calcifier/artifact.py +313 -0
  47. calcifier-0.1.1/src/calcifier/atomic_io.py +31 -0
  48. calcifier-0.1.1/src/calcifier/baseline.py +159 -0
  49. calcifier-0.1.1/src/calcifier/budget.py +63 -0
  50. calcifier-0.1.1/src/calcifier/calcify.py +51 -0
  51. calcifier-0.1.1/src/calcifier/catalog.py +139 -0
  52. calcifier-0.1.1/src/calcifier/cli.py +787 -0
  53. calcifier-0.1.1/src/calcifier/cli_options.py +108 -0
  54. calcifier-0.1.1/src/calcifier/clock.py +79 -0
  55. calcifier-0.1.1/src/calcifier/compiler_activity.py +108 -0
  56. calcifier-0.1.1/src/calcifier/compiler_resources.py +98 -0
  57. calcifier-0.1.1/src/calcifier/composition.py +347 -0
  58. calcifier-0.1.1/src/calcifier/diagnostics.py +172 -0
  59. calcifier-0.1.1/src/calcifier/dry_run.py +500 -0
  60. calcifier-0.1.1/src/calcifier/effect_methods.py +39 -0
  61. calcifier-0.1.1/src/calcifier/exceptions.py +28 -0
  62. calcifier-0.1.1/src/calcifier/filesystem_contract.py +88 -0
  63. calcifier-0.1.1/src/calcifier/gate.py +996 -0
  64. calcifier-0.1.1/src/calcifier/graph.py +112 -0
  65. calcifier-0.1.1/src/calcifier/graph_build.py +241 -0
  66. calcifier-0.1.1/src/calcifier/graph_edges.py +34 -0
  67. calcifier-0.1.1/src/calcifier/hashing.py +9 -0
  68. calcifier-0.1.1/src/calcifier/instruction_context.py +197 -0
  69. calcifier-0.1.1/src/calcifier/json_config.py +16 -0
  70. calcifier-0.1.1/src/calcifier/metadata.py +235 -0
  71. calcifier-0.1.1/src/calcifier/mutations.py +318 -0
  72. calcifier-0.1.1/src/calcifier/native_events.py +299 -0
  73. calcifier-0.1.1/src/calcifier/output_annotations.py +149 -0
  74. calcifier-0.1.1/src/calcifier/outputs.py +550 -0
  75. calcifier-0.1.1/src/calcifier/parallel_contract.py +61 -0
  76. calcifier-0.1.1/src/calcifier/path_syntax.py +30 -0
  77. calcifier-0.1.1/src/calcifier/portable.py +373 -0
  78. calcifier-0.1.1/src/calcifier/prepared_context.py +82 -0
  79. calcifier-0.1.1/src/calcifier/prompts.py +370 -0
  80. calcifier-0.1.1/src/calcifier/py.typed +0 -0
  81. calcifier-0.1.1/src/calcifier/recipe.py +1217 -0
  82. calcifier-0.1.1/src/calcifier/recipe_ast.py +577 -0
  83. calcifier-0.1.1/src/calcifier/recipe_draft.py +218 -0
  84. calcifier-0.1.1/src/calcifier/registry.py +83 -0
  85. calcifier-0.1.1/src/calcifier/repair.py +534 -0
  86. calcifier-0.1.1/src/calcifier/run_result.py +119 -0
  87. calcifier-0.1.1/src/calcifier/runtime_conformance.py +135 -0
  88. calcifier-0.1.1/src/calcifier/side_effects.py +91 -0
  89. calcifier-0.1.1/src/calcifier/skill_frontmatter.py +89 -0
  90. calcifier-0.1.1/src/calcifier/skill_package.py +271 -0
  91. calcifier-0.1.1/src/calcifier/source_quality.py +392 -0
  92. calcifier-0.1.1/src/calcifier/subprocesses.py +407 -0
  93. calcifier-0.1.1/src/calcifier/taint.py +603 -0
  94. calcifier-0.1.1/src/calcifier/tools.py +456 -0
  95. calcifier-0.1.1/src/calcifier/trace.py +532 -0
  96. calcifier-0.1.1/src/calcifier/trace_export.py +203 -0
  97. calcifier-0.1.1/src/calcifier/trace_profile.py +83 -0
  98. calcifier-0.1.1/src/calcifier/trust.py +483 -0
  99. calcifier-0.1.1/src/calcifier/type_check.py +105 -0
  100. calcifier-0.1.1/src/calcifier/update.py +65 -0
  101. calcifier-0.1.1/src/calcifier/usage.py +61 -0
  102. calcifier-0.1.1/src/calcifier/validation.py +29 -0
  103. calcifier-0.1.1/src/calcifier/windows_job.py +202 -0
  104. calcifier-0.1.1/tests/__init__.py +0 -0
  105. calcifier-0.1.1/tests/conftest.py +202 -0
  106. calcifier-0.1.1/tests/corpus/changelog-entry/SKILL.md +13 -0
  107. calcifier-0.1.1/tests/corpus/changelog-entry/case.json +8 -0
  108. calcifier-0.1.1/tests/corpus/changelog-entry/draft.py +39 -0
  109. calcifier-0.1.1/tests/corpus/notes-summary/SKILL.md +13 -0
  110. calcifier-0.1.1/tests/corpus/notes-summary/case.json +3 -0
  111. calcifier-0.1.1/tests/corpus/notes-summary/draft.py +31 -0
  112. calcifier-0.1.1/tests/corpus/per-item-records/SKILL.md +13 -0
  113. calcifier-0.1.1/tests/corpus/per-item-records/case.json +25 -0
  114. calcifier-0.1.1/tests/corpus/per-item-records/draft.py +52 -0
  115. calcifier-0.1.1/tests/corpus/plugin-calcifier/SKILL.md +43 -0
  116. calcifier-0.1.1/tests/corpus/plugin-calcifier/case.json +3 -0
  117. calcifier-0.1.1/tests/corpus/plugin-calcifier/draft.py +24 -0
  118. calcifier-0.1.1/tests/corpus/plugin-debug/SKILL.md +41 -0
  119. calcifier-0.1.1/tests/corpus/plugin-debug/case.json +3 -0
  120. calcifier-0.1.1/tests/corpus/plugin-debug/draft.py +29 -0
  121. calcifier-0.1.1/tests/corpus/plugin-exec/SKILL.md +46 -0
  122. calcifier-0.1.1/tests/corpus/plugin-exec/case.json +3 -0
  123. calcifier-0.1.1/tests/corpus/plugin-exec/draft.py +31 -0
  124. calcifier-0.1.1/tests/corpus/plugin-update/SKILL.md +38 -0
  125. calcifier-0.1.1/tests/corpus/plugin-update/case.json +3 -0
  126. calcifier-0.1.1/tests/corpus/plugin-update/draft.py +24 -0
  127. calcifier-0.1.1/tests/corpus/release-digest/SKILL.md +13 -0
  128. calcifier-0.1.1/tests/corpus/release-digest/case.json +4 -0
  129. calcifier-0.1.1/tests/corpus/release-digest/children/release-notes/SKILL.md +12 -0
  130. calcifier-0.1.1/tests/corpus/release-digest/children/release-notes/case.json +3 -0
  131. calcifier-0.1.1/tests/corpus/release-digest/children/release-notes/draft.py +22 -0
  132. calcifier-0.1.1/tests/corpus/release-digest/draft.py +40 -0
  133. calcifier-0.1.1/tests/corpus/style-review/SKILL.md +19 -0
  134. calcifier-0.1.1/tests/corpus/style-review/case.json +3 -0
  135. calcifier-0.1.1/tests/corpus/style-review/draft.py +41 -0
  136. calcifier-0.1.1/tests/corpus/style-review/references/examples.md +4 -0
  137. calcifier-0.1.1/tests/corpus/style-review/references/style-guide.md +5 -0
  138. calcifier-0.1.1/tests/corpus/text-search/SKILL.md +14 -0
  139. calcifier-0.1.1/tests/corpus/text-search/case.json +3 -0
  140. calcifier-0.1.1/tests/corpus/text-search/draft.py +38 -0
  141. calcifier-0.1.1/tests/fixtures/sequencehash-sha256.json +56 -0
  142. calcifier-0.1.1/tests/fixtures/trivial_recipe.py +33 -0
  143. calcifier-0.1.1/tests/mutation_runner.py +228 -0
  144. calcifier-0.1.1/tests/mutation_sources.py +154 -0
  145. calcifier-0.1.1/tests/mutation_worker.py +34 -0
  146. calcifier-0.1.1/tests/support/SKILL.md +3 -0
  147. calcifier-0.1.1/tests/support/__init__.py +1 -0
  148. calcifier-0.1.1/tests/support/agents.py +55 -0
  149. calcifier-0.1.1/tests/support/ast.py +15 -0
  150. calcifier-0.1.1/tests/support/compiler.py +125 -0
  151. calcifier-0.1.1/tests/support/compiler_cases.py +149 -0
  152. calcifier-0.1.1/tests/support/recipes.py +158 -0
  153. calcifier-0.1.1/tests/support/skill_source.py +3 -0
  154. calcifier-0.1.1/tests/support/trust.py +26 -0
  155. calcifier-0.1.1/tests/test_acceptance_runner.py +697 -0
  156. calcifier-0.1.1/tests/test_agent_context_delivery.py +95 -0
  157. calcifier-0.1.1/tests/test_agent_timeout_budget.py +66 -0
  158. calcifier-0.1.1/tests/test_agents.py +1389 -0
  159. calcifier-0.1.1/tests/test_artifact.py +368 -0
  160. calcifier-0.1.1/tests/test_baseline.py +456 -0
  161. calcifier-0.1.1/tests/test_budget.py +195 -0
  162. calcifier-0.1.1/tests/test_catalog.py +259 -0
  163. calcifier-0.1.1/tests/test_cli.py +1338 -0
  164. calcifier-0.1.1/tests/test_cli_agent_budget.py +66 -0
  165. calcifier-0.1.1/tests/test_cli_options.py +39 -0
  166. calcifier-0.1.1/tests/test_cli_runtime_boundaries.py +270 -0
  167. calcifier-0.1.1/tests/test_clock.py +144 -0
  168. calcifier-0.1.1/tests/test_command_preflight.py +171 -0
  169. calcifier-0.1.1/tests/test_command_results.py +354 -0
  170. calcifier-0.1.1/tests/test_compilation_limits.py +177 -0
  171. calcifier-0.1.1/tests/test_compiler_activity.py +86 -0
  172. calcifier-0.1.1/tests/test_compiler_artifact_boundaries.py +125 -0
  173. calcifier-0.1.1/tests/test_compiler_context_boundaries.py +109 -0
  174. calcifier-0.1.1/tests/test_compiler_deadline.py +254 -0
  175. calcifier-0.1.1/tests/test_compiler_prompts.py +74 -0
  176. calcifier-0.1.1/tests/test_compiler_replay.py +73 -0
  177. calcifier-0.1.1/tests/test_compiler_resources.py +344 -0
  178. calcifier-0.1.1/tests/test_compiler_workflows.py +278 -0
  179. calcifier-0.1.1/tests/test_composition.py +1046 -0
  180. calcifier-0.1.1/tests/test_context_token_payloads.py +122 -0
  181. calcifier-0.1.1/tests/test_corpus.py +144 -0
  182. calcifier-0.1.1/tests/test_decorator_aliases.py +106 -0
  183. calcifier-0.1.1/tests/test_dry_run.py +763 -0
  184. calcifier-0.1.1/tests/test_dry_run_artifacts.py +114 -0
  185. calcifier-0.1.1/tests/test_dry_run_host_schemas.py +72 -0
  186. calcifier-0.1.1/tests/test_dry_run_provenance.py +99 -0
  187. calcifier-0.1.1/tests/test_effect_constructor_aliases.py +72 -0
  188. calcifier-0.1.1/tests/test_effect_methods.py +27 -0
  189. calcifier-0.1.1/tests/test_encoded_required_fields.py +138 -0
  190. calcifier-0.1.1/tests/test_gate.py +796 -0
  191. calcifier-0.1.1/tests/test_gate_source.py +1243 -0
  192. calcifier-0.1.1/tests/test_graph_build.py +226 -0
  193. calcifier-0.1.1/tests/test_hashing.py +16 -0
  194. calcifier-0.1.1/tests/test_host_results.py +200 -0
  195. calcifier-0.1.1/tests/test_mapping_transport.py +141 -0
  196. calcifier-0.1.1/tests/test_metadata.py +42 -0
  197. calcifier-0.1.1/tests/test_module_alias_preflight.py +62 -0
  198. calcifier-0.1.1/tests/test_mutation_gate.py +189 -0
  199. calcifier-0.1.1/tests/test_mutation_runner.py +520 -0
  200. calcifier-0.1.1/tests/test_mutation_sources.py +248 -0
  201. calcifier-0.1.1/tests/test_mutation_survivors.py +98 -0
  202. calcifier-0.1.1/tests/test_mutation_threshold.py +131 -0
  203. calcifier-0.1.1/tests/test_mutations.py +670 -0
  204. calcifier-0.1.1/tests/test_native_compilation.py +95 -0
  205. calcifier-0.1.1/tests/test_native_event_stream.py +461 -0
  206. calcifier-0.1.1/tests/test_native_schema_delivery.py +155 -0
  207. calcifier-0.1.1/tests/test_offline.py +47 -0
  208. calcifier-0.1.1/tests/test_output_type_aliases.py +100 -0
  209. calcifier-0.1.1/tests/test_outputs.py +497 -0
  210. calcifier-0.1.1/tests/test_outputs_answers.py +75 -0
  211. calcifier-0.1.1/tests/test_owner_failure_classes.py +213 -0
  212. calcifier-0.1.1/tests/test_parallel_command_policy.py +40 -0
  213. calcifier-0.1.1/tests/test_parallel_results.py +204 -0
  214. calcifier-0.1.1/tests/test_plain_helpers.py +109 -0
  215. calcifier-0.1.1/tests/test_plugin_dogfood.py +110 -0
  216. calcifier-0.1.1/tests/test_portable.py +753 -0
  217. calcifier-0.1.1/tests/test_prepared_context.py +101 -0
  218. calcifier-0.1.1/tests/test_prepared_workspace.py +74 -0
  219. calcifier-0.1.1/tests/test_prompts.py +277 -0
  220. calcifier-0.1.1/tests/test_public_recipe_surface.py +63 -0
  221. calcifier-0.1.1/tests/test_recipe.py +949 -0
  222. calcifier-0.1.1/tests/test_recipe_answers.py +406 -0
  223. calcifier-0.1.1/tests/test_recipe_body_effects.py +203 -0
  224. calcifier-0.1.1/tests/test_recipe_draft.py +200 -0
  225. calcifier-0.1.1/tests/test_repair.py +354 -0
  226. calcifier-0.1.1/tests/test_repair_indentation.py +103 -0
  227. calcifier-0.1.1/tests/test_repair_rendering.py +240 -0
  228. calcifier-0.1.1/tests/test_repair_targeting.py +185 -0
  229. calcifier-0.1.1/tests/test_report_tables.py +118 -0
  230. calcifier-0.1.1/tests/test_resource_sources.py +224 -0
  231. calcifier-0.1.1/tests/test_review_acceptance.py +137 -0
  232. calcifier-0.1.1/tests/test_runtime_conformance.py +188 -0
  233. calcifier-0.1.1/tests/test_runtime_conformance_acceptance.py +377 -0
  234. calcifier-0.1.1/tests/test_runtime_regressions.py +329 -0
  235. calcifier-0.1.1/tests/test_schema_keyword_fields.py +62 -0
  236. calcifier-0.1.1/tests/test_side_effects.py +129 -0
  237. calcifier-0.1.1/tests/test_side_effects_answers.py +266 -0
  238. calcifier-0.1.1/tests/test_skill_frontmatter.py +64 -0
  239. calcifier-0.1.1/tests/test_skill_package.py +564 -0
  240. calcifier-0.1.1/tests/test_skill_package_answers.py +45 -0
  241. calcifier-0.1.1/tests/test_source_construction.py +176 -0
  242. calcifier-0.1.1/tests/test_source_quality.py +446 -0
  243. calcifier-0.1.1/tests/test_source_repair_boundaries.py +62 -0
  244. calcifier-0.1.1/tests/test_static_path_and_call_boundaries.py +89 -0
  245. calcifier-0.1.1/tests/test_step.py +365 -0
  246. calcifier-0.1.1/tests/test_structured_output_roots.py +95 -0
  247. calcifier-0.1.1/tests/test_submodule_tool_preflight.py +69 -0
  248. calcifier-0.1.1/tests/test_subprocesses.py +354 -0
  249. calcifier-0.1.1/tests/test_subprocesses_answers.py +51 -0
  250. calcifier-0.1.1/tests/test_taint.py +1110 -0
  251. calcifier-0.1.1/tests/test_taint_artifacts.py +59 -0
  252. calcifier-0.1.1/tests/test_thin_scaffolding.py +309 -0
  253. calcifier-0.1.1/tests/test_tools.py +399 -0
  254. calcifier-0.1.1/tests/test_tools_answers.py +184 -0
  255. calcifier-0.1.1/tests/test_trace_accounting_boundaries.py +66 -0
  256. calcifier-0.1.1/tests/test_trace_export.py +537 -0
  257. calcifier-0.1.1/tests/test_trust.py +494 -0
  258. calcifier-0.1.1/tests/test_trust_answers.py +290 -0
  259. calcifier-0.1.1/tests/test_type_check.py +329 -0
  260. calcifier-0.1.1/tests/test_unused_capabilities.py +99 -0
  261. calcifier-0.1.1/tests/test_update.py +206 -0
  262. calcifier-0.1.1/tests/test_usage_accounting.py +234 -0
  263. calcifier-0.1.1/tests/test_validation.py +48 -0
  264. calcifier-0.1.1/tests/test_verify_artifacts.py +76 -0
  265. calcifier-0.1.1/tests/test_wall_budget_cli.py +132 -0
  266. calcifier-0.1.1/tests/test_windows_job.py +273 -0
  267. calcifier-0.1.1/tests/test_writable_agents.py +327 -0
  268. calcifier-0.1.1/uv.lock +612 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "calcifier",
3
+ "owner": {
4
+ "name": "Trail of Bits",
5
+ "url": "https://www.trailofbits.com"
6
+ },
7
+ "description": "Typed, executable Python recipes for Claude and Codex skills.",
8
+ "plugins": [
9
+ {
10
+ "name": "calcifier",
11
+ "source": "./plugins/calcifier",
12
+ "description": "Calcify, execute, debug, and update typed agent recipes"
13
+ }
14
+ ]
15
+ }
@@ -0,0 +1,21 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ cooldown:
8
+ default-days: 7
9
+ groups:
10
+ all:
11
+ patterns: ["*"]
12
+
13
+ - package-ecosystem: github-actions
14
+ directory: /
15
+ schedule:
16
+ interval: weekly
17
+ cooldown:
18
+ default-days: 7
19
+ groups:
20
+ all:
21
+ patterns: ["*"]
@@ -0,0 +1,38 @@
1
+ name: Actionlint
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ actionlint:
18
+ name: actionlint
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with:
23
+ persist-credentials: false
24
+
25
+ - name: Install actionlint
26
+ run: |
27
+ set -euo pipefail
28
+ # Pinned to actionlint v1.7.12 release tarball.
29
+ ACTIONLINT_VERSION="1.7.12"
30
+ ACTIONLINT_SHA256="8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8"
31
+ curl -fsSL -o actionlint.tar.gz \
32
+ "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
33
+ echo "${ACTIONLINT_SHA256} actionlint.tar.gz" | sha256sum -c -
34
+ tar -xzf actionlint.tar.gz actionlint
35
+ chmod +x actionlint
36
+
37
+ - name: Run actionlint
38
+ run: ./actionlint -color
@@ -0,0 +1,181 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ env:
17
+ PYTHONWARNDEFAULTENCODING: "1"
18
+
19
+ jobs:
20
+ lint:
21
+ name: Lint
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
25
+ with:
26
+ persist-credentials: false
27
+
28
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
29
+
30
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
31
+ with:
32
+ python-version: "3.13"
33
+
34
+ - run: uv sync --all-groups --locked
35
+
36
+ - run: make lockcheck lint portable
37
+
38
+ type-check:
39
+ name: Type check (ty)
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
43
+ with:
44
+ persist-credentials: false
45
+
46
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
47
+
48
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
49
+ with:
50
+ python-version: "3.13"
51
+
52
+ - run: uv sync --all-groups --locked
53
+
54
+ - run: make typecheck
55
+
56
+ test:
57
+ name: Test
58
+ runs-on: ubuntu-latest
59
+ strategy:
60
+ fail-fast: false
61
+ matrix:
62
+ # "Test (3.13)" and "Test (3.14)" are required status checks in the main
63
+ # branch ruleset; removing a version leaves its check pending forever.
64
+ python-version: ["3.13", "3.14"]
65
+ steps:
66
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
67
+ with:
68
+ persist-credentials: false
69
+
70
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
71
+
72
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
73
+ with:
74
+ python-version: ${{ matrix.python-version }}
75
+
76
+ - run: uv sync --all-groups --locked
77
+
78
+ - run: uv run pytest -q -n auto tests/
79
+
80
+ windows-test:
81
+ name: Windows test (3.13)
82
+ runs-on: windows-latest
83
+ steps:
84
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
85
+ with:
86
+ persist-credentials: false
87
+
88
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
89
+
90
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
91
+ with:
92
+ python-version: "3.13"
93
+
94
+ - run: uv sync --all-groups --locked
95
+
96
+ - run: uv run pytest -q -n auto tests/
97
+
98
+ dep-audit:
99
+ name: Dependency audit (pip-audit)
100
+ runs-on: ubuntu-latest
101
+ steps:
102
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
103
+ with:
104
+ persist-credentials: false
105
+
106
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
107
+
108
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
109
+ with:
110
+ python-version: "3.13"
111
+
112
+ - name: Export locked requirements
113
+ run: |
114
+ uv export --frozen --all-groups --format requirements-txt \
115
+ --no-emit-project -o requirements-frozen.txt
116
+
117
+ - name: Run pip-audit against the lockfile export
118
+ run: uvx pip-audit -r requirements-frozen.txt --disable-pip --strict
119
+
120
+ coverage:
121
+ name: Coverage
122
+ runs-on: ubuntu-latest
123
+ steps:
124
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
125
+ with:
126
+ persist-credentials: false
127
+
128
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
129
+
130
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
131
+ with:
132
+ python-version: "3.13"
133
+
134
+ - run: uv sync --all-groups --locked
135
+
136
+ - run: uv run coverage run --branch -m pytest -q tests/
137
+
138
+ - name: Coverage report (gate)
139
+ run: uv run coverage report
140
+
141
+ - name: Coverage XML for upload
142
+ run: uv run coverage xml -o coverage.xml
143
+
144
+ - name: Upload coverage XML
145
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
146
+ with:
147
+ name: coverage-xml
148
+ path: coverage.xml
149
+
150
+ build:
151
+ name: Build sdist + wheel
152
+ runs-on: ubuntu-latest
153
+ steps:
154
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
155
+ with:
156
+ persist-credentials: false
157
+
158
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
159
+
160
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
161
+ with:
162
+ python-version: "3.13"
163
+
164
+ - name: Seed deliberately dirty workstation state
165
+ run: |
166
+ mkdir -p .claude .hypothesis .vivisect
167
+ touch .claude/release-leak .hypothesis/release-leak .vivisect/release-leak
168
+
169
+ - run: uv build
170
+
171
+ - name: Verify artifact contents and version surfaces
172
+ run: uv run python scripts/verify_artifacts.py dist/
173
+
174
+ - run: uvx twine check dist/*
175
+
176
+ - name: Smoke-import the wheel
177
+ run: |
178
+ python -m venv /tmp/wheel-check
179
+ /tmp/wheel-check/bin/pip install dist/*.whl
180
+ /tmp/wheel-check/bin/python -c "import calcifier; print(calcifier.__version__)"
181
+ /tmp/wheel-check/bin/calcifier --version
@@ -0,0 +1,116 @@
1
+ name: Mutation Testing
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ # Finish the costly report; keep only the newest pending commit in this group.
12
+ cancel-in-progress: false
13
+
14
+ permissions:
15
+ contents: read
16
+
17
+ jobs:
18
+ gremlins:
19
+ name: Mutation shard (${{ matrix.operator }}, ${{ matrix.index }})
20
+ runs-on: ubuntu-latest
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ include:
25
+ # Balance complete modules by observed per-operator mutant runtime.
26
+ # Boolean has the most work; comparison was a single multi-hour job.
27
+ - {operator: comparison, index: 0, count: 4}
28
+ - {operator: comparison, index: 1, count: 4}
29
+ - {operator: comparison, index: 2, count: 4}
30
+ - {operator: comparison, index: 3, count: 4}
31
+ - {operator: arithmetic, index: 0, count: 2}
32
+ - {operator: arithmetic, index: 1, count: 2}
33
+ - {operator: boolean, index: 0, count: 8}
34
+ - {operator: boolean, index: 1, count: 8}
35
+ - {operator: boolean, index: 2, count: 8}
36
+ - {operator: boolean, index: 3, count: 8}
37
+ - {operator: boolean, index: 4, count: 8}
38
+ - {operator: boolean, index: 5, count: 8}
39
+ - {operator: boolean, index: 6, count: 8}
40
+ - {operator: boolean, index: 7, count: 8}
41
+ - {operator: boundary, index: 0, count: 2}
42
+ - {operator: boundary, index: 1, count: 2}
43
+ - {operator: return, index: 0, count: 4}
44
+ - {operator: return, index: 1, count: 4}
45
+ - {operator: return, index: 2, count: 4}
46
+ - {operator: return, index: 3, count: 4}
47
+ env:
48
+ ANTHROPIC_API_KEY: ""
49
+ OPENAI_API_KEY: ""
50
+ GREMLIN_OPERATORS: ${{ matrix.operator }}
51
+ GREMLIN_CACHE: "1"
52
+ SHARD_INDEX: ${{ matrix.index }}
53
+ SHARD_COUNT: ${{ matrix.count }}
54
+ steps:
55
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
56
+ with:
57
+ persist-credentials: false
58
+
59
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
60
+
61
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
62
+ with:
63
+ python-version: "3.13"
64
+
65
+ # Reuse results only when the complete code and test inputs match. The
66
+ # plugin also hashes each target and its covering tests internally.
67
+ - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
68
+ with:
69
+ path: .gremlins_cache
70
+ key: gremlins-${{ runner.os }}-py313-${{ matrix.operator }}-${{ matrix.index }}of${{ matrix.count }}-${{ hashFiles('uv.lock', 'pyproject.toml', 'Makefile', 'src/**', 'tests/**', 'plugins/**', 'scripts/mutation_shards.py', 'scripts/mutation_weights.json', '.github/workflows/mutation.yml') }}
71
+
72
+ - run: uv sync --all-groups --locked
73
+
74
+ - name: Mutate this operator's module partition
75
+ run: |
76
+ set -euo pipefail
77
+ MUTATION_RUN_TARGETS="$(python3 scripts/mutation_shards.py --operator "$GREMLIN_OPERATORS" --index "$SHARD_INDEX" --count "$SHARD_COUNT")"
78
+ export MUTATION_RUN_TARGETS
79
+ make mutate
80
+ test -s coverage/gremlins/gremlins.json
81
+
82
+ - name: Upload report
83
+ if: always() && hashFiles('coverage/gremlins/gremlins.json') != ''
84
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
85
+ with:
86
+ name: gremlins-report-${{ matrix.operator }}-${{ matrix.index }}
87
+ path: coverage/gremlins/
88
+
89
+ mutation-threshold:
90
+ name: Mutation Testing (pytest-gremlins)
91
+ if: always()
92
+ needs: gremlins
93
+ runs-on: ubuntu-latest
94
+ steps:
95
+ # A missing shard would silently shrink each module's denominator.
96
+ - name: Require every mutation shard
97
+ env:
98
+ SHARDS: ${{ needs.gremlins.result }}
99
+ run: test "$SHARDS" = success
100
+
101
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
102
+ with:
103
+ persist-credentials: false
104
+
105
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
106
+ with:
107
+ pattern: "gremlins-report-*"
108
+ path: coverage/shards
109
+
110
+ # Report-only until v0.1.0 ships: the per-module rate is printed but does not fail CI.
111
+ - name: Report the per-module kill rate
112
+ continue-on-error: true
113
+ run: |
114
+ set -euo pipefail
115
+ mapfile -d '' reports < <(find coverage/shards -name gremlins.json -print0)
116
+ python3 scripts/mutation_threshold.py "${reports[@]}" --min 90
@@ -0,0 +1,127 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ # Releases are immutable and serialized through the GitHub release event;
8
+ # we still set workflow-level concurrency so a botched re-tag of the same
9
+ # release cannot race a previous publish run.
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.event.release.tag_name }}
12
+ cancel-in-progress: false
13
+
14
+ permissions: {}
15
+
16
+ jobs:
17
+ build:
18
+ name: Build
19
+ runs-on: ubuntu-latest
20
+ permissions:
21
+ contents: read
22
+ env:
23
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
24
+ steps:
25
+ - name: Verify release tag is a vX.Y.Z[-pre] version
26
+ run: |
27
+ set -euo pipefail
28
+ if ! printf '%s\n' "$RELEASE_TAG" \
29
+ | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|rc)\.?[0-9]+)?$'; then
30
+ echo "release tag '$RELEASE_TAG' does not match a publishable pattern" >&2
31
+ exit 1
32
+ fi
33
+
34
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
35
+ with:
36
+ persist-credentials: false
37
+ fetch-depth: 0
38
+ ref: ${{ github.event.release.tag_name }}
39
+
40
+ - name: Verify annotated signed tag and main reachability
41
+ env:
42
+ GH_TOKEN: ${{ github.token }}
43
+ run: |
44
+ set -euo pipefail
45
+ git fetch --no-tags origin main
46
+ if [ "$(git cat-file -t "$RELEASE_TAG")" != tag ]; then
47
+ echo "$RELEASE_TAG is not an annotated tag" >&2
48
+ exit 1
49
+ fi
50
+ REF_JSON="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$RELEASE_TAG")"
51
+ TAG_OBJECT="$(printf '%s' "$REF_JSON" | jq -r '.object.sha')"
52
+ TAG_JSON="$(gh api "repos/$GITHUB_REPOSITORY/git/tags/$TAG_OBJECT")"
53
+ if [ "$(printf '%s' "$TAG_JSON" | jq -r '.verification.verified')" != true ]; then
54
+ printf '%s\n' "$TAG_JSON" | jq '.verification' >&2
55
+ exit 1
56
+ fi
57
+ TAG_COMMIT="$(printf '%s' "$TAG_JSON" | jq -r '.object.sha')"
58
+ git merge-base --is-ancestor "$TAG_COMMIT" origin/main
59
+ test "$TAG_COMMIT" = "$(git rev-parse HEAD)"
60
+
61
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
62
+ with:
63
+ # Release artifacts must not depend on caches writable by lower-trust workflows.
64
+ enable-cache: false
65
+
66
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
67
+ with:
68
+ python-version: "3.13"
69
+
70
+ - run: uv sync --all-groups --locked
71
+
72
+ - name: Verify every source version surface
73
+ run: uv run python scripts/verify_artifacts.py --source-only --release-tag "$RELEASE_TAG"
74
+
75
+ - name: Re-run release verification suite
76
+ run: |
77
+ make verify
78
+ uv run coverage run -m pytest -q tests/
79
+ uv run coverage report
80
+
81
+ - name: Audit locked dependencies
82
+ run: |
83
+ uv export --frozen --all-groups --format requirements-txt \
84
+ --no-emit-project -o requirements-frozen.txt
85
+ uvx pip-audit -r requirements-frozen.txt --disable-pip --strict
86
+
87
+ - run: uv build
88
+
89
+ - name: Verify artifact contents and versions
90
+ run: uv run python scripts/verify_artifacts.py dist/
91
+
92
+ - run: uvx twine check dist/*
93
+
94
+ - name: Smoke-import the wheel
95
+ run: |
96
+ set -euo pipefail
97
+ python -m venv /tmp/wheel-check
98
+ /tmp/wheel-check/bin/pip install dist/*.whl
99
+ /tmp/wheel-check/bin/calcifier --version
100
+
101
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
102
+ with:
103
+ name: dist
104
+ path: dist/
105
+
106
+ publish:
107
+ name: Publish
108
+ needs: build
109
+ runs-on: ubuntu-latest
110
+ environment: pypi
111
+ permissions:
112
+ id-token: write # OIDC trusted publishing for pypa/gh-action-pypi-publish.
113
+ attestations: write # actions/attest-build-provenance signs the wheel + sdist.
114
+ contents: read # Read-only checkout of release metadata.
115
+ steps:
116
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
117
+ with:
118
+ name: dist
119
+ path: dist/
120
+
121
+ - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
122
+ with:
123
+ subject-path: "dist/*"
124
+
125
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
126
+ with:
127
+ attestations: true
@@ -0,0 +1,29 @@
1
+ name: Zizmor
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions:
14
+ contents: read
15
+ actions: read # zizmor needs read access to introspect workflow metadata.
16
+
17
+ jobs:
18
+ zizmor:
19
+ name: Workflow Security Audit
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
23
+ with:
24
+ persist-credentials: false
25
+
26
+ - uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
27
+ with:
28
+ version: "1.30.1"
29
+ advanced-security: false
@@ -0,0 +1,27 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ dist/
7
+ build/
8
+ *.egg-info/
9
+ .calcifier-runtime/
10
+ coverage/
11
+ .gremlins_cache/
12
+ .claude/
13
+ .codex/
14
+ .remember/
15
+ .serena/
16
+ .uv-cache/
17
+ .vivisect/
18
+
19
+ # Coverage artifacts
20
+ .coverage
21
+ .coverage.*
22
+ coverage.xml
23
+ htmlcov/
24
+
25
+ # Generated benchmark reports
26
+ benchmarks/**/results/
27
+ benchmarks/**/*-results/
@@ -0,0 +1,53 @@
1
+ # Working on Calcifier
2
+
3
+ Calcifier turns a SKILL.md into a runnable Python workflow. Python handles
4
+ repeatable operations; agents handle understanding, interpretation, and uncertain
5
+ decisions. Preserve the skill's instructions, mandatory steps, and explicit
6
+ output requirements, including required fields and word counts.
7
+ Compiler behavior must stay independent of any particular skill or provider.
8
+
9
+ ## Code organization
10
+
11
+ - `src/calcifier/` contains the compiler, runtime, and public package.
12
+ [docs/architecture.md](docs/architecture.md) maps their module boundaries.
13
+ - `tests/` contains offline regression tests and neutral skill fixtures;
14
+ shared fixtures belong in `tests/support/`.
15
+ - `scripts/` contains development tools, not runtime dependencies.
16
+ - `docs/` contains detailed usage and design notes. Keep the README focused on
17
+ what Calcifier does, why someone would use it, and where to start.
18
+
19
+ ## Changes
20
+
21
+ - Prefer deleting duplication to adding abstractions. Use existing helpers and
22
+ module boundaries; avoid speculative frameworks and compatibility layers.
23
+ - Fix the general mechanism behind a failure. Do not add compiler rules, prompt
24
+ sentences, or tests tied to one skill's wording or domain.
25
+ - When a recipe uses an API naturally, prefer supporting that use over adding a
26
+ rejection rule. Before adding a check, see whether ty, the dry run, or repair
27
+ already catches the failure.
28
+ - Keep `calcifier.__all__` small. Generated recipes import only those names;
29
+ prefer extending an existing call over adding another public primitive.
30
+ - Preserve behavior and validation unless the task explicitly changes them.
31
+ Do not weaken an assertion or replace a failed result with an unverified one
32
+ to make tests pass. Compatibility work needs a supported API or format to serve.
33
+ - Keep rejection focused on behavioral defects: invalid code, certain runtime
34
+ failures, unsafe effects, and races. Formatting preferences and type precision
35
+ must not reject an otherwise runnable recipe.
36
+ - Always attempt the whole compiler dry run with stub agents and synthesized
37
+ inputs. Preserve its limits and report coverage gaps as unverified, never passed.
38
+ - Keep instruction handling direct; do not build fidelity proof machinery as a
39
+ substitute for compiling and running the recipe.
40
+
41
+ ## Verification and workflow
42
+
43
+ - Run focused tests while editing, then `gmake verify`. This checks the lock,
44
+ Ruff, ty, portable plugin recipes, and the test suite. CI reports mutation
45
+ rates; do not run mutation testing locally.
46
+ - Tests must use stub providers and never call live Claude/Codex CLIs. Write
47
+ byte-exact fixtures with explicit encoding/newline settings; cover LF and CRLF
48
+ when preserving source or resource bytes.
49
+ - Live acceptance is owner-run. Do not inspect held-out fixtures, cohort lists,
50
+ or results, and do not run them yourself. Test the acceptance runner only with
51
+ neutral fixtures. Offline checks do not establish answer quality.
52
+ - Work in an isolated checkout, preserve the owner's local changes, keep
53
+ generated evidence outside Git, and use normal pushes.
@@ -0,0 +1,77 @@
1
+ # Changelog
2
+
3
+ ## v0.1.1 — 2026-10-14
4
+
5
+ Release metadata update for the first PyPI publication. The v0.1.0 GitHub
6
+ release used an unsigned lightweight tag and failed the signed-tag publishing
7
+ check. This release contains the features documented below for v0.1.0.
8
+
9
+ ## v0.1.0 — 2026-10-14
10
+
11
+ First public release of Calcifier. Write Python workflows that combine
12
+ repeatable operations with agent reasoning, or compile them from existing
13
+ skills. Requires Python 3.13 or newer.
14
+
15
+ ### Added
16
+
17
+ - **Python recipes.** Author workflows directly with `@recipe` and typed `@step`
18
+ functions, ordinary Python control flow, and async functions. Entry signatures
19
+ define typed CLI inputs. `fail()` aborts; `emit()` exposes named artifacts.
20
+ - **Skill compilation.** Generate a reviewable Python recipe from a `SKILL.md`
21
+ and packaged resources. Repeatable operations move into Python; reasoning
22
+ stays with agents. Generation, static checks, whole-recipe stub execution,
23
+ and repairs share a bounded call/time budget.
24
+ - **Runnable fallback.** Compilation starts from one agent session with the
25
+ intact skill. Failed optimization retains that baseline and reports
26
+ `baseline_retained`; `--require-compiled` preserves it but exits nonzero.
27
+ - **Typed agent responses.** Closed `@output_type` records enforce required
28
+ fields, value types, and constraints such as allowed values and word counts.
29
+ Invalid responses receive one parse retry. Codex receives schemas through its
30
+ native structured-output channel; the host validates full Python types.
31
+ - **Agent roles and budgets.** Configure Claude, Codex, or custom argv adapters
32
+ by semantic role. Steps, parallel workers, and children share call and wall
33
+ limits. `--max-agent-calls` bounds charged attempts, including parse retries,
34
+ without increasing declared limits.
35
+ `Budget.remaining_wall_seconds()` exposes the active run's effective time left.
36
+ Custom command adapters receive their effective timeout in the call contract.
37
+ - **Instruction delivery.** File-based recipes pin original instructions and
38
+ references. `prepare_context()` bundles complete tasks and prior results
39
+ without duplicating prompts or changing the project working directory.
40
+ - **Declared effects.** Contained, atomic report writes; artifact verification;
41
+ host argv commands; and soft/hard dry-run modes. `--output-dir` redirects a
42
+ declared root and protects existing files.
43
+ - **Typed command results.** `run_command(..., output=T)` validates successful
44
+ JSON stdout. Compiler dry runs execute read-only commands and synthesize
45
+ suppressed mutating results, reporting unavailable inputs as unverified.
46
+ - **Parallel checkpoints.** Serial `on_result` callbacks checkpoint completed
47
+ workers; `reuse_existing=True` adopts byte-identical artifacts for updates.
48
+ - **Resources and composition.** Verified resource snapshots, pinned child
49
+ recipes, shared budgets/output roots, and dependency-ordered graph builds
50
+ with closed catalogs.
51
+ - **Diagnostics and traces.** Compiler telemetry and incremental versioned run
52
+ traces record attempts, artifacts, effects, timing, budgets, and observed
53
+ usage. Missing usage remains unknown. `profile` summarizes a trace.
54
+ - **CLI and plugin.** Compile, execute, debug, update-by-diff, portable lint,
55
+ graph builds, and profiling; four Claude Code plugin skills with recipes.
56
+
57
+ ### Security
58
+
59
+ - **Trust and integrity.** Execution requires consent for exact recipe bytes,
60
+ resources, and child pins. Compilation does not grant trust; adjacent trust
61
+ files have no authority. Recipes execute Python with host permissions; review
62
+ the source and dependencies before granting trust.
63
+ - **Behavioral checks.** Source checks reject certain runtime failures, unsafe
64
+ effects, model-controlled paths/commands, and races. Style and type precision
65
+ do not reject runnable candidates. Stub execution reports coverage gaps
66
+ without promoting them to passes.
67
+ - **Provider boundaries.** Host agents use explicit filesystem contracts and
68
+ clean settings. Subprocesses run without a shell under time/output limits.
69
+ - **Strict records and redaction.** Malformed trace/trust data fails closed.
70
+ Secret-like field names are redacted; free text still needs review.
71
+ - **Release provenance.** A signed-tag release workflow checks source and
72
+ artifact versions, uses PyPI trusted publishing and build attestations, and
73
+ builds without workflow caches.
74
+
75
+ See [usage](docs/usage.md), [architecture](docs/architecture.md), and
76
+ [providers](docs/providers.md) for contracts and limits. Compilation and offline
77
+ checks do not establish answer quality, instruction fidelity, or faster execution.