@ahmed-g-gad/apothem 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (674) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/LICENSE +21 -0
  3. package/LICENSES/MIT.txt +18 -0
  4. package/LICENSES/PSF-2.0.txt +47 -0
  5. package/README.md +549 -0
  6. package/bin/README.md +37 -0
  7. package/bin/apothem.mjs +78 -0
  8. package/package.json +75 -0
  9. package/pyproject.toml +347 -0
  10. package/src/apothem/README.md +52 -0
  11. package/src/apothem/__init__.py +66 -0
  12. package/src/apothem/__main__.py +28 -0
  13. package/src/apothem/_vendor/.keep +0 -0
  14. package/src/apothem/_vendor/__init__.py +25 -0
  15. package/src/apothem/_vendor/attr/__init__.py +104 -0
  16. package/src/apothem/_vendor/attr/__init__.pyi +389 -0
  17. package/src/apothem/_vendor/attr/_cmp.py +160 -0
  18. package/src/apothem/_vendor/attr/_cmp.pyi +13 -0
  19. package/src/apothem/_vendor/attr/_compat.py +99 -0
  20. package/src/apothem/_vendor/attr/_config.py +31 -0
  21. package/src/apothem/_vendor/attr/_funcs.py +497 -0
  22. package/src/apothem/_vendor/attr/_make.py +3406 -0
  23. package/src/apothem/_vendor/attr/_next_gen.py +674 -0
  24. package/src/apothem/_vendor/attr/_typing_compat.pyi +15 -0
  25. package/src/apothem/_vendor/attr/_version_info.py +89 -0
  26. package/src/apothem/_vendor/attr/_version_info.pyi +9 -0
  27. package/src/apothem/_vendor/attr/converters.py +162 -0
  28. package/src/apothem/_vendor/attr/converters.pyi +19 -0
  29. package/src/apothem/_vendor/attr/exceptions.py +95 -0
  30. package/src/apothem/_vendor/attr/exceptions.pyi +17 -0
  31. package/src/apothem/_vendor/attr/filters.py +72 -0
  32. package/src/apothem/_vendor/attr/filters.pyi +6 -0
  33. package/src/apothem/_vendor/attr/py.typed +0 -0
  34. package/src/apothem/_vendor/attr/setters.py +79 -0
  35. package/src/apothem/_vendor/attr/setters.pyi +20 -0
  36. package/src/apothem/_vendor/attr/validators.py +750 -0
  37. package/src/apothem/_vendor/attr/validators.pyi +140 -0
  38. package/src/apothem/_vendor/attr.LICENSE +21 -0
  39. package/src/apothem/_vendor/attrs/__init__.py +72 -0
  40. package/src/apothem/_vendor/attrs/__init__.pyi +314 -0
  41. package/src/apothem/_vendor/attrs/converters.py +3 -0
  42. package/src/apothem/_vendor/attrs/exceptions.py +3 -0
  43. package/src/apothem/_vendor/attrs/filters.py +3 -0
  44. package/src/apothem/_vendor/attrs/py.typed +0 -0
  45. package/src/apothem/_vendor/attrs/setters.py +3 -0
  46. package/src/apothem/_vendor/attrs/validators.py +3 -0
  47. package/src/apothem/_vendor/attrs.LICENSE +21 -0
  48. package/src/apothem/_vendor/jsonschema/__init__.py +120 -0
  49. package/src/apothem/_vendor/jsonschema/__main__.py +6 -0
  50. package/src/apothem/_vendor/jsonschema/_format.py +546 -0
  51. package/src/apothem/_vendor/jsonschema/_keywords.py +449 -0
  52. package/src/apothem/_vendor/jsonschema/_legacy_keywords.py +449 -0
  53. package/src/apothem/_vendor/jsonschema/_types.py +204 -0
  54. package/src/apothem/_vendor/jsonschema/_typing.py +29 -0
  55. package/src/apothem/_vendor/jsonschema/_utils.py +355 -0
  56. package/src/apothem/_vendor/jsonschema/benchmarks/__init__.py +5 -0
  57. package/src/apothem/_vendor/jsonschema/benchmarks/const_vs_enum.py +30 -0
  58. package/src/apothem/_vendor/jsonschema/benchmarks/contains.py +28 -0
  59. package/src/apothem/_vendor/jsonschema/benchmarks/import_benchmark.py +31 -0
  60. package/src/apothem/_vendor/jsonschema/benchmarks/issue232/issue.json +2653 -0
  61. package/src/apothem/_vendor/jsonschema/benchmarks/issue232.py +25 -0
  62. package/src/apothem/_vendor/jsonschema/benchmarks/json_schema_test_suite.py +12 -0
  63. package/src/apothem/_vendor/jsonschema/benchmarks/nested_schemas.py +56 -0
  64. package/src/apothem/_vendor/jsonschema/benchmarks/subcomponents.py +42 -0
  65. package/src/apothem/_vendor/jsonschema/benchmarks/unused_registry.py +35 -0
  66. package/src/apothem/_vendor/jsonschema/benchmarks/useless_applicator_schemas.py +106 -0
  67. package/src/apothem/_vendor/jsonschema/benchmarks/useless_keywords.py +32 -0
  68. package/src/apothem/_vendor/jsonschema/benchmarks/validator_creation.py +14 -0
  69. package/src/apothem/_vendor/jsonschema/cli.py +292 -0
  70. package/src/apothem/_vendor/jsonschema/exceptions.py +490 -0
  71. package/src/apothem/_vendor/jsonschema/protocols.py +230 -0
  72. package/src/apothem/_vendor/jsonschema/validators.py +1410 -0
  73. package/src/apothem/_vendor/jsonschema.LICENSE +19 -0
  74. package/src/apothem/_vendor/jsonschema_specifications/__init__.py +12 -0
  75. package/src/apothem/_vendor/jsonschema_specifications/_core.py +38 -0
  76. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/metaschema.json +42 -0
  77. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/applicator +56 -0
  78. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/content +17 -0
  79. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/core +57 -0
  80. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/format +14 -0
  81. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/meta-data +37 -0
  82. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft201909/vocabularies/validation +98 -0
  83. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/metaschema.json +58 -0
  84. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/applicator +48 -0
  85. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/content +17 -0
  86. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/core +51 -0
  87. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/format-annotation +14 -0
  88. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/format-assertion +14 -0
  89. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/meta-data +37 -0
  90. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/unevaluated +15 -0
  91. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft202012/vocabularies/validation +98 -0
  92. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft3/metaschema.json +172 -0
  93. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft4/metaschema.json +149 -0
  94. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft6/metaschema.json +153 -0
  95. package/src/apothem/_vendor/jsonschema_specifications/schemas/draft7/metaschema.json +166 -0
  96. package/src/apothem/_vendor/jsonschema_specifications.LICENSE +19 -0
  97. package/src/apothem/_vendor/referencing/__init__.py +7 -0
  98. package/src/apothem/_vendor/referencing/_attrs.py +31 -0
  99. package/src/apothem/_vendor/referencing/_attrs.pyi +21 -0
  100. package/src/apothem/_vendor/referencing/_core.py +739 -0
  101. package/src/apothem/_vendor/referencing/exceptions.py +165 -0
  102. package/src/apothem/_vendor/referencing/jsonschema.py +642 -0
  103. package/src/apothem/_vendor/referencing/py.typed +0 -0
  104. package/src/apothem/_vendor/referencing/retrieval.py +94 -0
  105. package/src/apothem/_vendor/referencing/typing.py +61 -0
  106. package/src/apothem/_vendor/referencing.LICENSE +19 -0
  107. package/src/apothem/_vendor/rpds/__init__.py +251 -0
  108. package/src/apothem/_vendor/typing_extensions.LICENSE +279 -0
  109. package/src/apothem/_vendor/typing_extensions.py +4317 -0
  110. package/src/apothem/_vendor/vendor.txt +22 -0
  111. package/src/apothem/_vendor/yaml/__init__.py +389 -0
  112. package/src/apothem/_vendor/yaml/composer.py +138 -0
  113. package/src/apothem/_vendor/yaml/constructor.py +748 -0
  114. package/src/apothem/_vendor/yaml/cyaml.py +100 -0
  115. package/src/apothem/_vendor/yaml/dumper.py +61 -0
  116. package/src/apothem/_vendor/yaml/emitter.py +1137 -0
  117. package/src/apothem/_vendor/yaml/error.py +74 -0
  118. package/src/apothem/_vendor/yaml/events.py +85 -0
  119. package/src/apothem/_vendor/yaml/loader.py +63 -0
  120. package/src/apothem/_vendor/yaml/nodes.py +48 -0
  121. package/src/apothem/_vendor/yaml/parser.py +588 -0
  122. package/src/apothem/_vendor/yaml/reader.py +185 -0
  123. package/src/apothem/_vendor/yaml/representer.py +388 -0
  124. package/src/apothem/_vendor/yaml/resolver.py +226 -0
  125. package/src/apothem/_vendor/yaml/scanner.py +1435 -0
  126. package/src/apothem/_vendor/yaml/serializer.py +110 -0
  127. package/src/apothem/_vendor/yaml/tokens.py +103 -0
  128. package/src/apothem/_vendor/yaml.LICENSE +20 -0
  129. package/src/apothem/agents/README.md +60 -0
  130. package/src/apothem/agents/codebase-explorer.md +91 -0
  131. package/src/apothem/agents/convention-auditor.md +93 -0
  132. package/src/apothem/agents/dependency-auditor.md +97 -0
  133. package/src/apothem/agents/fact-checker.md +84 -0
  134. package/src/apothem/agents/mcp-builder.md +86 -0
  135. package/src/apothem/agents/memory-auditor.md +93 -0
  136. package/src/apothem/agents/prompt-evaluator.md +87 -0
  137. package/src/apothem/agents/quality-gate.md +103 -0
  138. package/src/apothem/agents/refactor-surgeon.md +74 -0
  139. package/src/apothem/agents/research-scout.md +73 -0
  140. package/src/apothem/agents/security-scanner.md +83 -0
  141. package/src/apothem/agents/test-runner.md +84 -0
  142. package/src/apothem/audit/README.md +73 -0
  143. package/src/apothem/audit/_scan_lib.py +182 -0
  144. package/src/apothem/audit/analyze_graph.py +260 -0
  145. package/src/apothem/audit/build_capability_graph.py +607 -0
  146. package/src/apothem/audit/build_inventory.py +657 -0
  147. package/src/apothem/audit/build_plans_provenance.py +997 -0
  148. package/src/apothem/audit/check_links.py +389 -0
  149. package/src/apothem/audit/classify_artifacts.py +381 -0
  150. package/src/apothem/audit/deprecated-tokens.txt +10 -0
  151. package/src/apothem/audit/execute_plans_migration.py +491 -0
  152. package/src/apothem/audit/known-projects.txt +15 -0
  153. package/src/apothem/audit/render_capability_index.py +467 -0
  154. package/src/apothem/audit/render_inventory.py +405 -0
  155. package/src/apothem/audit/scan_ai_surfaces.py +1125 -0
  156. package/src/apothem/audit/scan_ai_surfaces_coarse.py +261 -0
  157. package/src/apothem/audit/scan_drift_features.py +143 -0
  158. package/src/apothem/audit/scan_frontmatter.py +293 -0
  159. package/src/apothem/audit/scan_header_coverage.py +1134 -0
  160. package/src/apothem/audit/scan_plan_leakage.py +540 -0
  161. package/src/apothem/audit/scan_plans_discipline.py +188 -0
  162. package/src/apothem/audit/scan_secrets_pii.py +245 -0
  163. package/src/apothem/audit/scan_stale_tokens.py +296 -0
  164. package/src/apothem/audit/synthesize_drift.py +205 -0
  165. package/src/apothem/benchmarks/README.md +33 -0
  166. package/src/apothem/benchmarks/__init__.py +3 -0
  167. package/src/apothem/benchmarks/bench_agents.py +63 -0
  168. package/src/apothem/benchmarks/bench_hooks.py +93 -0
  169. package/src/apothem/benchmarks/bench_install.py +58 -0
  170. package/src/apothem/benchmarks/bench_tests.py +93 -0
  171. package/src/apothem/benchmarks/bench_validate_ecosystem.py +84 -0
  172. package/src/apothem/cli/README.md +33 -0
  173. package/src/apothem/cli/__init__.py +229 -0
  174. package/src/apothem/cli/_cmd_completion.py +88 -0
  175. package/src/apothem/cli/_cmd_diff.py +181 -0
  176. package/src/apothem/cli/_cmd_doctor.py +143 -0
  177. package/src/apothem/cli/_cmd_harnesses.py +167 -0
  178. package/src/apothem/cli/_cmd_install.py +327 -0
  179. package/src/apothem/cli/_cmd_migrate_workspace.py +143 -0
  180. package/src/apothem/cli/_cmd_profile.py +341 -0
  181. package/src/apothem/cli/_cmd_status.py +180 -0
  182. package/src/apothem/cli/_cmd_uninstall.py +215 -0
  183. package/src/apothem/cli/_cmd_update.py +397 -0
  184. package/src/apothem/cli/_cmd_verify.py +194 -0
  185. package/src/apothem/cli/_common_flags.py +90 -0
  186. package/src/apothem/cli/_epilogs.py +296 -0
  187. package/src/apothem/cli/_helpers.py +857 -0
  188. package/src/apothem/cli/_json_formatter.py +21 -0
  189. package/src/apothem/cli/_materialize.py +376 -0
  190. package/src/apothem/cli/completions/apothem.bash +30 -0
  191. package/src/apothem/cli/completions/apothem.fish +19 -0
  192. package/src/apothem/cli/completions/apothem.ps1 +27 -0
  193. package/src/apothem/cli/completions/apothem.zsh +42 -0
  194. package/src/apothem/cli/reference_export.py +126 -0
  195. package/src/apothem/commands/README.md +125 -0
  196. package/src/apothem/commands/a11y-audit.md +203 -0
  197. package/src/apothem/commands/architecture-review.md +194 -0
  198. package/src/apothem/commands/audit.md +165 -0
  199. package/src/apothem/commands/code-audit.md +218 -0
  200. package/src/apothem/commands/code-review.md +193 -0
  201. package/src/apothem/commands/dependency-audit.md +209 -0
  202. package/src/apothem/commands/docs-review.md +199 -0
  203. package/src/apothem/commands/elevate.md +285 -0
  204. package/src/apothem/commands/eval.md +149 -0
  205. package/src/apothem/commands/fortress.md +172 -0
  206. package/src/apothem/commands/freshify.md +168 -0
  207. package/src/apothem/commands/github-deploy-fresh.md +178 -0
  208. package/src/apothem/commands/github-deploy-next.md +167 -0
  209. package/src/apothem/commands/perf-audit.md +198 -0
  210. package/src/apothem/commands/plan-amend.md +104 -0
  211. package/src/apothem/commands/plan-audit.md +127 -0
  212. package/src/apothem/commands/plan-design.md +257 -0
  213. package/src/apothem/commands/plan-execute.md +495 -0
  214. package/src/apothem/commands/plan-generate.md +351 -0
  215. package/src/apothem/commands/plan-review.md +555 -0
  216. package/src/apothem/commands/plan-spec.md +359 -0
  217. package/src/apothem/commands/plan-status.md +222 -0
  218. package/src/apothem/commands/plan.md +173 -0
  219. package/src/apothem/commands/projectify.md +142 -0
  220. package/src/apothem/commands/release-readiness.md +142 -0
  221. package/src/apothem/commands/research-analysis.md +241 -0
  222. package/src/apothem/commands/research-design.md +231 -0
  223. package/src/apothem/commands/research-disseminate.md +225 -0
  224. package/src/apothem/commands/research-experiment.md +232 -0
  225. package/src/apothem/commands/research-ideate.md +213 -0
  226. package/src/apothem/commands/research-paper.md +252 -0
  227. package/src/apothem/commands/research-proposal.md +220 -0
  228. package/src/apothem/commands/research-publish.md +255 -0
  229. package/src/apothem/commands/research-review.md +251 -0
  230. package/src/apothem/commands/research-sources.md +266 -0
  231. package/src/apothem/commands/research-spec.md +255 -0
  232. package/src/apothem/commands/research-synthesis.md +233 -0
  233. package/src/apothem/commands/research-theory.md +218 -0
  234. package/src/apothem/commands/research.md +181 -0
  235. package/src/apothem/commands/security-audit.md +196 -0
  236. package/src/apothem/commands/supply-chain-audit.md +192 -0
  237. package/src/apothem/commands/test-suite.md +146 -0
  238. package/src/apothem/commands/threat-model-audit.md +199 -0
  239. package/src/apothem/commands/ux-review.md +202 -0
  240. package/src/apothem/commands/workflow.md +162 -0
  241. package/src/apothem/conformity/README.md +173 -0
  242. package/src/apothem/conformity/__init__.py +1 -0
  243. package/src/apothem/conformity/_grep_base.py +93 -0
  244. package/src/apothem/conformity/agent_capability_grep.py +306 -0
  245. package/src/apothem/conformity/agents_md_coverage_grep.py +382 -0
  246. package/src/apothem/conformity/agnosticism_grep.py +311 -0
  247. package/src/apothem/conformity/always_on_budget_grep.py +318 -0
  248. package/src/apothem/conformity/bare_except_grep.py +115 -0
  249. package/src/apothem/conformity/binding_reciprocity_grep.py +151 -0
  250. package/src/apothem/conformity/brand_mark_grep.py +272 -0
  251. package/src/apothem/conformity/commented_out_code_grep.py +176 -0
  252. package/src/apothem/conformity/completion_claim_grep.py +169 -0
  253. package/src/apothem/conformity/conventional_commit_grep.py +319 -0
  254. package/src/apothem/conformity/copilot_instructions_presence_grep.py +324 -0
  255. package/src/apothem/conformity/cross_platform_matrix_grep.py +297 -0
  256. package/src/apothem/conformity/determinism_grep.py +306 -0
  257. package/src/apothem/conformity/diagram_staleness_grep.py +154 -0
  258. package/src/apothem/conformity/dynamism_grep.py +284 -0
  259. package/src/apothem/conformity/editorconfig_presence_grep.py +281 -0
  260. package/src/apothem/conformity/file_header_grep.py +502 -0
  261. package/src/apothem/conformity/freshness_token_grep.py +233 -0
  262. package/src/apothem/conformity/frontmatter_grep.py +274 -0
  263. package/src/apothem/conformity/frontmatter_value_grep.py +386 -0
  264. package/src/apothem/conformity/gate.py +1386 -0
  265. package/src/apothem/conformity/gitattributes_presence_grep.py +238 -0
  266. package/src/apothem/conformity/harden_runner_grep.py +320 -0
  267. package/src/apothem/conformity/hedging_grep.py +129 -0
  268. package/src/apothem/conformity/license_author_consistency_grep.py +204 -0
  269. package/src/apothem/conformity/link_check.py +327 -0
  270. package/src/apothem/conformity/magic_number_grep.py +182 -0
  271. package/src/apothem/conformity/multi_surface_coherence_grep.py +620 -0
  272. package/src/apothem/conformity/naming_grep.py +224 -0
  273. package/src/apothem/conformity/no_global_plans_grep.py +339 -0
  274. package/src/apothem/conformity/no_toplevel_docs_grep.py +120 -0
  275. package/src/apothem/conformity/oidc_trusted_publishing_grep.py +291 -0
  276. package/src/apothem/conformity/option_annotation_grep.py +352 -0
  277. package/src/apothem/conformity/orphan_output_grep.py +206 -0
  278. package/src/apothem/conformity/permissions_minimum_scope_grep.py +299 -0
  279. package/src/apothem/conformity/plain_language_grep.py +559 -0
  280. package/src/apothem/conformity/plan_next_step_consistency_grep.py +450 -0
  281. package/src/apothem/conformity/plan_suite_structure_grep.py +534 -0
  282. package/src/apothem/conformity/plans_discipline_language_grep.py +245 -0
  283. package/src/apothem/conformity/production_ready_pr_grep.py +200 -0
  284. package/src/apothem/conformity/recommend_next_step_grep.py +250 -0
  285. package/src/apothem/conformity/redundancy_grep.py +401 -0
  286. package/src/apothem/conformity/reference_token_grep.py +230 -0
  287. package/src/apothem/conformity/registry_capability_consistency_grep.py +368 -0
  288. package/src/apothem/conformity/secret_leak_grep.py +193 -0
  289. package/src/apothem/conformity/semver_stability_grep.py +358 -0
  290. package/src/apothem/conformity/smoke_install_grep.py +194 -0
  291. package/src/apothem/conformity/static_version_grep.py +284 -0
  292. package/src/apothem/conformity/token_efficiency_grep.py +185 -0
  293. package/src/apothem/conformity/unpinned_action_grep.py +115 -0
  294. package/src/apothem/conformity/user_confirm_grep.py +74 -0
  295. package/src/apothem/conformity/workflow_concurrency_grep.py +283 -0
  296. package/src/apothem/harnesses/README.md +63 -0
  297. package/src/apothem/harnesses/__init__.py +16 -0
  298. package/src/apothem/harnesses/_shared/README.md +36 -0
  299. package/src/apothem/harnesses/_shared/__init__.py +12 -0
  300. package/src/apothem/harnesses/_shared/install_driver.py +281 -0
  301. package/src/apothem/harnesses/_shared/install_driver_apply.py +612 -0
  302. package/src/apothem/harnesses/_shared/install_driver_backup.py +535 -0
  303. package/src/apothem/harnesses/_shared/install_driver_converters.py +310 -0
  304. package/src/apothem/harnesses/_shared/install_driver_lifecycle.py +495 -0
  305. package/src/apothem/harnesses/_shared/install_driver_materialize.py +675 -0
  306. package/src/apothem/harnesses/_shared/install_driver_merge.py +656 -0
  307. package/src/apothem/harnesses/_shared/install_driver_pathsafety.py +137 -0
  308. package/src/apothem/harnesses/_shared/install_driver_planvalidation.py +240 -0
  309. package/src/apothem/harnesses/_shared/install_driver_removal.py +366 -0
  310. package/src/apothem/harnesses/_shared/install_driver_treeops.py +248 -0
  311. package/src/apothem/harnesses/_shared/install_driver_types.py +330 -0
  312. package/src/apothem/harnesses/_shared/wrapper_factories.py +448 -0
  313. package/src/apothem/harnesses/antigravity/STANDARD-CONVENTION-PIN.md +91 -0
  314. package/src/apothem/harnesses/antigravity/__init__.py +70 -0
  315. package/src/apothem/harnesses/antigravity/capabilities.yml +40 -0
  316. package/src/apothem/harnesses/antigravity/install.py +63 -0
  317. package/src/apothem/harnesses/antigravity/templates/GEMINI.md +40 -0
  318. package/src/apothem/harnesses/antigravity/templates/plugin.json +5 -0
  319. package/src/apothem/harnesses/antigravity/uninstall.py +22 -0
  320. package/src/apothem/harnesses/antigravity/update.py +10 -0
  321. package/src/apothem/harnesses/antigravity/verify.py +11 -0
  322. package/src/apothem/harnesses/claude_code/STANDARD-CONVENTION-PIN.md +65 -0
  323. package/src/apothem/harnesses/claude_code/__init__.py +107 -0
  324. package/src/apothem/harnesses/claude_code/capabilities.yml +42 -0
  325. package/src/apothem/harnesses/claude_code/install.py +147 -0
  326. package/src/apothem/harnesses/claude_code/templates/settings.json +351 -0
  327. package/src/apothem/harnesses/claude_code/uninstall.py +23 -0
  328. package/src/apothem/harnesses/claude_code/update.py +10 -0
  329. package/src/apothem/harnesses/claude_code/verify.py +11 -0
  330. package/src/apothem/harnesses/codebuddy/STANDARD-CONVENTION-PIN.md +74 -0
  331. package/src/apothem/harnesses/codebuddy/__init__.py +49 -0
  332. package/src/apothem/harnesses/codebuddy/capabilities.yml +34 -0
  333. package/src/apothem/harnesses/codebuddy/install.py +40 -0
  334. package/src/apothem/harnesses/codebuddy/templates/apothem-rules.md +37 -0
  335. package/src/apothem/harnesses/codebuddy/uninstall.py +25 -0
  336. package/src/apothem/harnesses/codebuddy/update.py +10 -0
  337. package/src/apothem/harnesses/codebuddy/verify.py +11 -0
  338. package/src/apothem/harnesses/codex/STANDARD-CONVENTION-PIN.md +79 -0
  339. package/src/apothem/harnesses/codex/__init__.py +72 -0
  340. package/src/apothem/harnesses/codex/capabilities.yml +40 -0
  341. package/src/apothem/harnesses/codex/install.py +69 -0
  342. package/src/apothem/harnesses/codex/templates/AGENTS.md +40 -0
  343. package/src/apothem/harnesses/codex/templates/hooks.json +127 -0
  344. package/src/apothem/harnesses/codex/uninstall.py +23 -0
  345. package/src/apothem/harnesses/codex/update.py +10 -0
  346. package/src/apothem/harnesses/codex/verify.py +11 -0
  347. package/src/apothem/harnesses/cursor/STANDARD-CONVENTION-PIN.md +79 -0
  348. package/src/apothem/harnesses/cursor/__init__.py +48 -0
  349. package/src/apothem/harnesses/cursor/capabilities.yml +42 -0
  350. package/src/apothem/harnesses/cursor/install.py +38 -0
  351. package/src/apothem/harnesses/cursor/templates/apothem-rules.mdc +40 -0
  352. package/src/apothem/harnesses/cursor/uninstall.py +25 -0
  353. package/src/apothem/harnesses/cursor/update.py +10 -0
  354. package/src/apothem/harnesses/cursor/verify.py +11 -0
  355. package/src/apothem/harnesses/gemini_cli/STANDARD-CONVENTION-PIN.md +102 -0
  356. package/src/apothem/harnesses/gemini_cli/__init__.py +52 -0
  357. package/src/apothem/harnesses/gemini_cli/capabilities.yml +43 -0
  358. package/src/apothem/harnesses/gemini_cli/install.py +43 -0
  359. package/src/apothem/harnesses/gemini_cli/templates/GEMINI.md +38 -0
  360. package/src/apothem/harnesses/gemini_cli/uninstall.py +25 -0
  361. package/src/apothem/harnesses/gemini_cli/update.py +10 -0
  362. package/src/apothem/harnesses/gemini_cli/verify.py +11 -0
  363. package/src/apothem/harnesses/github_copilot/STANDARD-CONVENTION-PIN.md +84 -0
  364. package/src/apothem/harnesses/github_copilot/__init__.py +47 -0
  365. package/src/apothem/harnesses/github_copilot/capabilities.yml +42 -0
  366. package/src/apothem/harnesses/github_copilot/install.py +40 -0
  367. package/src/apothem/harnesses/github_copilot/templates/copilot-instructions.md +33 -0
  368. package/src/apothem/harnesses/github_copilot/uninstall.py +25 -0
  369. package/src/apothem/harnesses/github_copilot/update.py +10 -0
  370. package/src/apothem/harnesses/github_copilot/verify.py +11 -0
  371. package/src/apothem/harnesses/glm/STANDARD-CONVENTION-PIN.md +77 -0
  372. package/src/apothem/harnesses/glm/__init__.py +56 -0
  373. package/src/apothem/harnesses/glm/capabilities.yml +33 -0
  374. package/src/apothem/harnesses/glm/install.py +45 -0
  375. package/src/apothem/harnesses/glm/templates/glm.toml +58 -0
  376. package/src/apothem/harnesses/glm/uninstall.py +25 -0
  377. package/src/apothem/harnesses/glm/update.py +10 -0
  378. package/src/apothem/harnesses/glm/verify.py +11 -0
  379. package/src/apothem/harnesses/hermes/STANDARD-CONVENTION-PIN.md +57 -0
  380. package/src/apothem/harnesses/hermes/__init__.py +33 -0
  381. package/src/apothem/harnesses/hermes/capabilities.yml +36 -0
  382. package/src/apothem/harnesses/hermes/install.py +17 -0
  383. package/src/apothem/harnesses/hermes/materializer.py +35 -0
  384. package/src/apothem/harnesses/hermes/uninstall.py +33 -0
  385. package/src/apothem/harnesses/hermes/update.py +10 -0
  386. package/src/apothem/harnesses/hermes/verify.py +11 -0
  387. package/src/apothem/harnesses/kimi_code/STANDARD-CONVENTION-PIN.md +128 -0
  388. package/src/apothem/harnesses/kimi_code/__init__.py +59 -0
  389. package/src/apothem/harnesses/kimi_code/capabilities.yml +40 -0
  390. package/src/apothem/harnesses/kimi_code/install.py +42 -0
  391. package/src/apothem/harnesses/kimi_code/templates/AGENTS.md +43 -0
  392. package/src/apothem/harnesses/kimi_code/uninstall.py +27 -0
  393. package/src/apothem/harnesses/kimi_code/update.py +10 -0
  394. package/src/apothem/harnesses/kimi_code/verify.py +11 -0
  395. package/src/apothem/harnesses/kiro/STANDARD-CONVENTION-PIN.md +77 -0
  396. package/src/apothem/harnesses/kiro/__init__.py +49 -0
  397. package/src/apothem/harnesses/kiro/capabilities.yml +36 -0
  398. package/src/apothem/harnesses/kiro/install.py +39 -0
  399. package/src/apothem/harnesses/kiro/templates/apothem-rules.md +36 -0
  400. package/src/apothem/harnesses/kiro/uninstall.py +25 -0
  401. package/src/apothem/harnesses/kiro/update.py +10 -0
  402. package/src/apothem/harnesses/kiro/verify.py +11 -0
  403. package/src/apothem/harnesses/open_claw/STANDARD-CONVENTION-PIN.md +62 -0
  404. package/src/apothem/harnesses/open_claw/__init__.py +35 -0
  405. package/src/apothem/harnesses/open_claw/capabilities.yml +35 -0
  406. package/src/apothem/harnesses/open_claw/install.py +17 -0
  407. package/src/apothem/harnesses/open_claw/materializer.py +36 -0
  408. package/src/apothem/harnesses/open_claw/uninstall.py +32 -0
  409. package/src/apothem/harnesses/open_claw/update.py +10 -0
  410. package/src/apothem/harnesses/open_claw/verify.py +11 -0
  411. package/src/apothem/harnesses/opencode/STANDARD-CONVENTION-PIN.md +76 -0
  412. package/src/apothem/harnesses/opencode/__init__.py +35 -0
  413. package/src/apothem/harnesses/opencode/capabilities.yml +43 -0
  414. package/src/apothem/harnesses/opencode/install.py +17 -0
  415. package/src/apothem/harnesses/opencode/materializer.py +31 -0
  416. package/src/apothem/harnesses/opencode/uninstall.py +34 -0
  417. package/src/apothem/harnesses/opencode/update.py +10 -0
  418. package/src/apothem/harnesses/opencode/verify.py +11 -0
  419. package/src/apothem/harnesses/qwen_code/STANDARD-CONVENTION-PIN.md +87 -0
  420. package/src/apothem/harnesses/qwen_code/__init__.py +37 -0
  421. package/src/apothem/harnesses/qwen_code/capabilities.yml +43 -0
  422. package/src/apothem/harnesses/qwen_code/install.py +19 -0
  423. package/src/apothem/harnesses/qwen_code/materializer.py +174 -0
  424. package/src/apothem/harnesses/qwen_code/templates/QWEN.md +30 -0
  425. package/src/apothem/harnesses/qwen_code/uninstall.py +34 -0
  426. package/src/apothem/harnesses/qwen_code/update.py +10 -0
  427. package/src/apothem/harnesses/qwen_code/verify.py +11 -0
  428. package/src/apothem/harnesses/trae/STANDARD-CONVENTION-PIN.md +70 -0
  429. package/src/apothem/harnesses/trae/__init__.py +49 -0
  430. package/src/apothem/harnesses/trae/capabilities.yml +34 -0
  431. package/src/apothem/harnesses/trae/install.py +38 -0
  432. package/src/apothem/harnesses/trae/templates/apothem-rules.md +37 -0
  433. package/src/apothem/harnesses/trae/uninstall.py +25 -0
  434. package/src/apothem/harnesses/trae/update.py +10 -0
  435. package/src/apothem/harnesses/trae/verify.py +11 -0
  436. package/src/apothem/harnesses/windsurf/STANDARD-CONVENTION-PIN.md +91 -0
  437. package/src/apothem/harnesses/windsurf/__init__.py +52 -0
  438. package/src/apothem/harnesses/windsurf/capabilities.yml +40 -0
  439. package/src/apothem/harnesses/windsurf/install.py +41 -0
  440. package/src/apothem/harnesses/windsurf/templates/apothem-rules.md +37 -0
  441. package/src/apothem/harnesses/windsurf/uninstall.py +25 -0
  442. package/src/apothem/harnesses/windsurf/update.py +10 -0
  443. package/src/apothem/harnesses/windsurf/verify.py +11 -0
  444. package/src/apothem/harnesses/zed/STANDARD-CONVENTION-PIN.md +92 -0
  445. package/src/apothem/harnesses/zed/__init__.py +57 -0
  446. package/src/apothem/harnesses/zed/capabilities.yml +38 -0
  447. package/src/apothem/harnesses/zed/install.py +41 -0
  448. package/src/apothem/harnesses/zed/templates/apothem-rules.md +32 -0
  449. package/src/apothem/harnesses/zed/uninstall.py +28 -0
  450. package/src/apothem/harnesses/zed/update.py +10 -0
  451. package/src/apothem/harnesses/zed/verify.py +11 -0
  452. package/src/apothem/hooks/README.md +81 -0
  453. package/src/apothem/hooks/__init__.py +24 -0
  454. package/src/apothem/hooks/askuserquestion_validator.py +380 -0
  455. package/src/apothem/hooks/dispatch.py +296 -0
  456. package/src/apothem/hooks/emit_hook_context.py +444 -0
  457. package/src/apothem/hooks/hooks.json +318 -0
  458. package/src/apothem/hooks/lib/README.md +39 -0
  459. package/src/apothem/hooks/lib/__init__.py +18 -0
  460. package/src/apothem/hooks/lib/bootstrap.ps1 +129 -0
  461. package/src/apothem/hooks/lib/bootstrap.sh +103 -0
  462. package/src/apothem/hooks/lib/events.py +51 -0
  463. package/src/apothem/hooks/lib/find-pwsh.ps1 +78 -0
  464. package/src/apothem/hooks/lib/find-pwsh.sh +76 -0
  465. package/src/apothem/hooks/lib/find-python.ps1 +63 -0
  466. package/src/apothem/hooks/lib/find-python.sh +97 -0
  467. package/src/apothem/hooks/lib/log.py +43 -0
  468. package/src/apothem/hooks/lib/resolve_root.py +264 -0
  469. package/src/apothem/hooks/messages/postcompact.md +14 -0
  470. package/src/apothem/hooks/messages/posttooluse-proactive-compaction.md +46 -0
  471. package/src/apothem/hooks/messages/precompact.md +14 -0
  472. package/src/apothem/hooks/messages/pretooluse-askuserquestion-recommended.md +65 -0
  473. package/src/apothem/hooks/messages/pretooluse-bash-plan-guard.md +97 -0
  474. package/src/apothem/hooks/messages/pretooluse-bash.md +39 -0
  475. package/src/apothem/hooks/messages/pretooluse-conformity.md +70 -0
  476. package/src/apothem/hooks/messages/pretooluse-dependency-guard.md +21 -0
  477. package/src/apothem/hooks/messages/pretooluse-edit-header-guard.md +61 -0
  478. package/src/apothem/hooks/messages/pretooluse-edit.md +21 -0
  479. package/src/apothem/hooks/messages/pretooluse-eval-guard.md +39 -0
  480. package/src/apothem/hooks/messages/pretooluse-notebookedit.md +11 -0
  481. package/src/apothem/hooks/messages/pretooluse-write-header-guard.md +45 -0
  482. package/src/apothem/hooks/messages/pretooluse-write-plan-guard.md +72 -0
  483. package/src/apothem/hooks/messages/pretooluse-write.md +21 -0
  484. package/src/apothem/hooks/messages/sessionstart.md +15 -0
  485. package/src/apothem/hooks/messages/stop.md +27 -0
  486. package/src/apothem/hooks/proactive_compaction_tracker.py +327 -0
  487. package/src/apothem/hooks/session_start_bootstrap.py +472 -0
  488. package/src/apothem/lib/README.md +42 -0
  489. package/src/apothem/lib/__init__.py +13 -0
  490. package/src/apothem/lib/atomic_io.py +189 -0
  491. package/src/apothem/lib/auditor.py +687 -0
  492. package/src/apothem/lib/clean_slate.py +396 -0
  493. package/src/apothem/lib/contexts.py +352 -0
  494. package/src/apothem/lib/data_home.py +255 -0
  495. package/src/apothem/lib/frontmatter.py +101 -0
  496. package/src/apothem/lib/harness_materializer.py +213 -0
  497. package/src/apothem/lib/harness_protocol.py +59 -0
  498. package/src/apothem/lib/harness_registry.py +282 -0
  499. package/src/apothem/lib/harness_registry_data.py +843 -0
  500. package/src/apothem/lib/install_ledger.py +347 -0
  501. package/src/apothem/lib/learning.py +540 -0
  502. package/src/apothem/lib/memory.py +347 -0
  503. package/src/apothem/lib/parallel_sweep.py +234 -0
  504. package/src/apothem/lib/plan_tiers.py +200 -0
  505. package/src/apothem/lib/plugin_bootstrap.py +132 -0
  506. package/src/apothem/lib/plugin_tree.py +599 -0
  507. package/src/apothem/lib/profile.py +755 -0
  508. package/src/apothem/lib/profile_projection.py +198 -0
  509. package/src/apothem/lib/propagation-manifest.yaml +878 -0
  510. package/src/apothem/lib/propagation.py +220 -0
  511. package/src/apothem/lib/python_resolver.py +189 -0
  512. package/src/apothem/lib/reporter.py +62 -0
  513. package/src/apothem/lib/workspace_migration.py +323 -0
  514. package/src/apothem/output-styles/README.md +41 -0
  515. package/src/apothem/output-styles/concise-engineer.md +49 -0
  516. package/src/apothem/output-styles/default-architect.md +52 -0
  517. package/src/apothem/output-styles/default.md +113 -0
  518. package/src/apothem/output-styles/forensic-auditor.md +63 -0
  519. package/src/apothem/py.typed +0 -0
  520. package/src/apothem/rules/README.md +121 -0
  521. package/src/apothem/rules/agent-capability-discipline-matrix.md +89 -0
  522. package/src/apothem/rules/agent-capability-discipline.md +78 -0
  523. package/src/apothem/rules/agent-orchestration-patterns.md +144 -0
  524. package/src/apothem/rules/agent-orchestration.md +65 -0
  525. package/src/apothem/rules/agents-md-convention.md +86 -0
  526. package/src/apothem/rules/agile-sprints-elements.md +135 -0
  527. package/src/apothem/rules/agile-sprints.md +64 -0
  528. package/src/apothem/rules/agnostic-posture-checklist.md +47 -0
  529. package/src/apothem/rules/agnostic-posture.md +48 -0
  530. package/src/apothem/rules/authoritative-referencing-quotation.md +50 -0
  531. package/src/apothem/rules/authoritative-referencing.md +66 -0
  532. package/src/apothem/rules/authority-inquiry-categories.md +58 -0
  533. package/src/apothem/rules/authority-inquiry.md +54 -0
  534. package/src/apothem/rules/auto-memory-topic-files.md +86 -0
  535. package/src/apothem/rules/auto-memory.md +67 -0
  536. package/src/apothem/rules/bidirectional-binding.md +123 -0
  537. package/src/apothem/rules/canonical-layout-reporting-tiers.md +212 -0
  538. package/src/apothem/rules/canonical-layout.md +60 -0
  539. package/src/apothem/rules/clean-architecture-layers.md +186 -0
  540. package/src/apothem/rules/clean-room-generation-protocols.md +124 -0
  541. package/src/apothem/rules/clean-room-generation.md +59 -0
  542. package/src/apothem/rules/code-craft-conventions.md +101 -0
  543. package/src/apothem/rules/code-craft-markdown.md +138 -0
  544. package/src/apothem/rules/code-craft-python.md +154 -0
  545. package/src/apothem/rules/code-craft-shell.md +192 -0
  546. package/src/apothem/rules/cognitive-identity-techniques.md +180 -0
  547. package/src/apothem/rules/cognitive-identity.md +81 -0
  548. package/src/apothem/rules/context-management-budget.md +46 -0
  549. package/src/apothem/rules/context-management-protocol.md +161 -0
  550. package/src/apothem/rules/context-management-scratch.md +128 -0
  551. package/src/apothem/rules/context-management.md +85 -0
  552. package/src/apothem/rules/definitiveness-virtues.md +67 -0
  553. package/src/apothem/rules/definitiveness.md +58 -0
  554. package/src/apothem/rules/determinism.md +81 -0
  555. package/src/apothem/rules/disclosure-ledger-markers.md +58 -0
  556. package/src/apothem/rules/disclosure-ledger.md +52 -0
  557. package/src/apothem/rules/dynamism.md +38 -0
  558. package/src/apothem/rules/etc-extension.md +57 -0
  559. package/src/apothem/rules/expertise-posture-elements.md +68 -0
  560. package/src/apothem/rules/expertise-posture.md +54 -0
  561. package/src/apothem/rules/freshness-facade.md +64 -0
  562. package/src/apothem/rules/harness-adapter-shape-schemas.md +162 -0
  563. package/src/apothem/rules/harness-adapter-shape.md +42 -0
  564. package/src/apothem/rules/host-discovery-manifests.md +50 -0
  565. package/src/apothem/rules/host-discovery.md +56 -0
  566. package/src/apothem/rules/i18n-discipline-locale-cohorts.md +120 -0
  567. package/src/apothem/rules/i18n-discipline.md +70 -0
  568. package/src/apothem/rules/interactive-questions-canonical-shapes.md +590 -0
  569. package/src/apothem/rules/interactive-questions-detail.md +41 -0
  570. package/src/apothem/rules/interactive-questions-sweep-matchers.md +184 -0
  571. package/src/apothem/rules/interactive-questions.md +89 -0
  572. package/src/apothem/rules/large-file-generation.md +112 -0
  573. package/src/apothem/rules/large-file-reading.md +59 -0
  574. package/src/apothem/rules/living-docs.md +85 -0
  575. package/src/apothem/rules/multi-agent-workflow.md +57 -0
  576. package/src/apothem/rules/operational-mandates-expanded.md +78 -0
  577. package/src/apothem/rules/operational-mandates.md +88 -0
  578. package/src/apothem/rules/option-annotation-form.md +60 -0
  579. package/src/apothem/rules/option-annotation.md +45 -0
  580. package/src/apothem/rules/own-voice-reimplementation.md +86 -0
  581. package/src/apothem/rules/performance-discipline.md +91 -0
  582. package/src/apothem/rules/persistent-conventions-vigilance-checklist.md +54 -0
  583. package/src/apothem/rules/persistent-conventions-vigilance.md +61 -0
  584. package/src/apothem/rules/plain-language.md +56 -0
  585. package/src/apothem/rules/planning-techniques.md +130 -0
  586. package/src/apothem/rules/pre-emission-gate-bars.md +86 -0
  587. package/src/apothem/rules/pre-emission-gate.md +54 -0
  588. package/src/apothem/rules/production-ready-prs-surfaces.md +162 -0
  589. package/src/apothem/rules/production-ready-prs.md +83 -0
  590. package/src/apothem/rules/propagation.md +63 -0
  591. package/src/apothem/rules/recommend-next-step.md +106 -0
  592. package/src/apothem/rules/refactoring-discipline.md +76 -0
  593. package/src/apothem/rules/session-closure.md +44 -0
  594. package/src/apothem/rules/sota-elevation-exemplars.md +76 -0
  595. package/src/apothem/rules/sota-elevation.md +52 -0
  596. package/src/apothem/rules/source-accessibility.md +58 -0
  597. package/src/apothem/rules/surgical-manipulation.md +48 -0
  598. package/src/apothem/rules/systemic-participation-relations.md +108 -0
  599. package/src/apothem/rules/systemic-participation.md +70 -0
  600. package/src/apothem/rules/ten-dimension-check-dimensions.md +52 -0
  601. package/src/apothem/rules/ten-dimension-check.md +59 -0
  602. package/src/apothem/rules/token-budget-discipline.md +81 -0
  603. package/src/apothem/rules/token-efficiency-rewrite-protocol.md +79 -0
  604. package/src/apothem/rules/token-efficiency-rewrite.md +77 -0
  605. package/src/apothem/rules/tool-use-discipline.md +48 -0
  606. package/src/apothem/rules/visual-leverage.md +102 -0
  607. package/src/apothem/schemas/NOTICE.md +9 -0
  608. package/src/apothem/schemas/README.md +104 -0
  609. package/src/apothem/schemas/__init__.py +176 -0
  610. package/src/apothem/schemas/advisory-finding.schema.json +111 -0
  611. package/src/apothem/schemas/agent.schema.json +106 -0
  612. package/src/apothem/schemas/authorship-header.txt +1 -0
  613. package/src/apothem/schemas/cohort-manifest.yaml +248 -0
  614. package/src/apothem/schemas/cohort-metadata-vocabulary.yaml +168 -0
  615. package/src/apothem/schemas/cohort.schema.json +113 -0
  616. package/src/apothem/schemas/command.schema.json +68 -0
  617. package/src/apothem/schemas/compatibility-matrix.yaml +432 -0
  618. package/src/apothem/schemas/context-fragment.schema.json +64 -0
  619. package/src/apothem/schemas/freshness-token-denylist.txt +51 -0
  620. package/src/apothem/schemas/handoff-manifest.yaml +353 -0
  621. package/src/apothem/schemas/header-exceptions.txt +141 -0
  622. package/src/apothem/schemas/header-visibility.yaml +39 -0
  623. package/src/apothem/schemas/learning-signal.schema.json +46 -0
  624. package/src/apothem/schemas/memory-record.schema.json +61 -0
  625. package/src/apothem/schemas/output-style.schema.json +40 -0
  626. package/src/apothem/schemas/plan.schema.json +51 -0
  627. package/src/apothem/schemas/plugin.schema.json +83 -0
  628. package/src/apothem/schemas/profile.example.yaml +70 -0
  629. package/src/apothem/schemas/profile.minimal.yaml +6 -0
  630. package/src/apothem/schemas/profile.schema.json +396 -0
  631. package/src/apothem/schemas/reference-token-denylist.txt +25 -0
  632. package/src/apothem/schemas/skill.schema.json +75 -0
  633. package/src/apothem/skills/README.md +93 -0
  634. package/src/apothem/skills/dependency-upgrade/SKILL.md +105 -0
  635. package/src/apothem/skills/dev-toolkit/SKILL.md +120 -0
  636. package/src/apothem/skills/diagram-authoring/SKILL.md +113 -0
  637. package/src/apothem/skills/document-authoring/SKILL.md +118 -0
  638. package/src/apothem/skills/ecosystem-audit/SKILL.md +108 -0
  639. package/src/apothem/skills/ecosystem-audit/references/audit-fortress.md +85 -0
  640. package/src/apothem/skills/ecosystem-audit/references/procedure.md +162 -0
  641. package/src/apothem/skills/eval-harness/SKILL.md +88 -0
  642. package/src/apothem/skills/incident-runbook/SKILL.md +92 -0
  643. package/src/apothem/skills/multi-source-research/SKILL.md +90 -0
  644. package/src/apothem/skills/plan-suite/SKILL.md +118 -0
  645. package/src/apothem/skills/plan-suite/master_template.md +1324 -0
  646. package/src/apothem/skills/projectify/SKILL.md +117 -0
  647. package/src/apothem/skills/prompt-engineering/SKILL.md +122 -0
  648. package/src/apothem/skills/refactor-extract/SKILL.md +85 -0
  649. package/src/apothem/skills/research-suite/SKILL.md +170 -0
  650. package/src/apothem/skills/research-suite/references/directory-structure.md +47 -0
  651. package/src/apothem/skills/research-suite/references/lifecycle.md +67 -0
  652. package/src/apothem/skills/research-suite/references/principal-investigator-framework.md +37 -0
  653. package/src/apothem/skills/research-suite/references/rigor-mandates.md +30 -0
  654. package/src/apothem/skills/research-suite/research_template.md +476 -0
  655. package/src/apothem/skills/secret-rotation/SKILL.md +87 -0
  656. package/src/apothem/skills/source-synthesis/SKILL.md +92 -0
  657. package/src/apothem/skills/surgical-guard/SKILL.md +118 -0
  658. package/src/apothem/skills/test-authoring/SKILL.md +85 -0
  659. package/src/apothem/skills/vuln-triage/SKILL.md +91 -0
  660. package/src/apothem/skills/workflow/SKILL.md +139 -0
  661. package/src/apothem/statuslines/README.md +26 -0
  662. package/src/apothem/statuslines/__init__.py +20 -0
  663. package/src/apothem/statuslines/conformity.json +5 -0
  664. package/src/apothem/statuslines/render.py +334 -0
  665. package/src/apothem/statuslines/statusline.md +50 -0
  666. package/src/apothem/templates/README.md +43 -0
  667. package/src/apothem/templates/agents-md-template.md +80 -0
  668. package/src/apothem/templates/consideration-log.md +39 -0
  669. package/src/apothem/templates/expertise-gap-log.md +56 -0
  670. package/src/apothem/templates/master-index-template.md +93 -0
  671. package/src/apothem/templates/potency-map.md +53 -0
  672. package/src/apothem/templates/preservation-audit.md +60 -0
  673. package/src/apothem/templates/question-resolution-audit.md +52 -0
  674. package/src/apothem/templates/trace-matrix-template.md +77 -0
@@ -0,0 +1,675 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Install dispatch and the run_install orchestration entrypoint."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import contextlib
8
+ import json
9
+ from collections.abc import Callable
10
+ from pathlib import Path
11
+ from typing import Any, Final
12
+
13
+ from apothem.harnesses._shared import install_driver
14
+ from apothem.lib import atomic_io, install_ledger
15
+ from apothem.lib.data_home import resolve_install_data_home
16
+ from apothem.lib.install_ledger import LedgerRecord
17
+ from apothem.lib.propagation import (
18
+ HarnessRules,
19
+ InstallEntry,
20
+ resolve_target,
21
+ )
22
+
23
+ from .install_driver_apply import (
24
+ _COHORT_DOC_FILES,
25
+ apply_codex_agents,
26
+ apply_command_skills,
27
+ apply_gemini_agents,
28
+ apply_gemini_commands,
29
+ apply_markdown_commands,
30
+ apply_merge_tree_entries,
31
+ apply_opencode_agents,
32
+ apply_qwen_agents,
33
+ apply_replace_tree,
34
+ apply_write_text,
35
+ )
36
+ from .install_driver_backup import _compensating_rollback, _install_lock_path
37
+ from .install_driver_converters import (
38
+ _codex_agent_text,
39
+ _gemini_agent_text,
40
+ _gemini_command_text,
41
+ _generated_skill_text,
42
+ _native_markdown_command_text,
43
+ _opencode_agent_text,
44
+ _qwen_agent_text,
45
+ )
46
+ from .install_driver_merge import (
47
+ _merged_json_text,
48
+ _operator_owned_preview,
49
+ apply_sentinel_merge,
50
+ render_content_tokens,
51
+ )
52
+ from .install_driver_pathsafety import _allowed_write_root, _root_for
53
+ from .install_driver_planvalidation import (
54
+ _projected_profile_body,
55
+ _validate_install_plan,
56
+ make_ignore,
57
+ )
58
+ from .install_driver_treeops import (
59
+ _directory_contents_equal,
60
+ _single_file_directory_matches,
61
+ sweep_stale,
62
+ )
63
+ from .install_driver_types import (
64
+ AuthorizeFn,
65
+ IgnoreFn,
66
+ MaterializationError,
67
+ MaterializationOutcome,
68
+ MaterializationResult,
69
+ MaterializationRun,
70
+ _is_excluded_path,
71
+ _result,
72
+ _with_detail,
73
+ resolve_source,
74
+ )
75
+
76
+
77
+ def _capability_projection_results(harness_name: str) -> list[MaterializationResult]:
78
+ """Return registry capability warnings for unsupported projection cells."""
79
+ from apothem.lib.harness_registry import get_harness_entry
80
+
81
+ try:
82
+ entry = get_harness_entry(harness_name)
83
+ except KeyError:
84
+ return []
85
+ results: list[MaterializationResult] = []
86
+ for capability in sorted(entry.capability_status):
87
+ status = entry.capability_status[capability]
88
+ if status not in {"unsupported", "discovery-pending"}:
89
+ continue
90
+ rationale = entry.unsupported_rationale.get(
91
+ capability,
92
+ f"{capability} is not projected for {entry.public_id}.",
93
+ )
94
+ results.append(
95
+ MaterializationResult(
96
+ outcome="warning",
97
+ operation="capability_projection",
98
+ path=entry.capabilities_path,
99
+ message=rationale,
100
+ detail={"capability": capability, "status": status},
101
+ )
102
+ )
103
+ return results
104
+
105
+
106
+ #: The uniform message every dry-run result carries. A dry run writes nothing,
107
+ #: so the message states only that; the prospective ``outcome`` word
108
+ #: (``created`` / ``updated`` / ``unchanged``) carries the would-this-change
109
+ #: distinction, exactly as the stale-sweep dry-run results already do.
110
+ _DRY_RUN_MESSAGE: Final[str] = "dry run: no filesystem changes made"
111
+
112
+ #: Per-file directory modes whose native target keeps the source basename and
113
+ #: whose body is a pure (source_path -> text) conversion. ``gemini_commands``
114
+ #: is excluded — it renames to a ``.toml`` target and is handled inline.
115
+ _NATIVE_FILE_CONVERTERS: Final[dict[str, Callable[[Path], str]]] = {
116
+ "gemini_agents": _gemini_agent_text,
117
+ "opencode_agents": _opencode_agent_text,
118
+ "qwen_agents": _qwen_agent_text,
119
+ "markdown_commands": _native_markdown_command_text,
120
+ }
121
+
122
+
123
+ def _prospective_file_outcome(target: Path, content: bytes) -> MaterializationOutcome:
124
+ """Classify the no-write outcome of writing *content* to *target*.
125
+
126
+ Mirrors the create / update / no-op decision
127
+ :func:`install_driver_backup.write_bytes_safely` makes at write time —
128
+ absent target → ``created``; on-disk bytes equal → ``unchanged``; on-disk
129
+ bytes differ → ``updated`` — without touching the filesystem.
130
+ """
131
+ if not target.exists():
132
+ return "created"
133
+ try:
134
+ return "unchanged" if target.read_bytes() == content else "updated"
135
+ except OSError:
136
+ # An unreadable existing target would be backed up and overwritten.
137
+ return "updated"
138
+
139
+
140
+ def _aggregate_dir_outcome(
141
+ child_outcomes: list[MaterializationOutcome], *, target_dir: Path
142
+ ) -> MaterializationOutcome:
143
+ """Fold a directory entry's per-child outcomes into one entry outcome.
144
+
145
+ Every child unchanged (or an empty source directory) → the whole entry is
146
+ ``unchanged``. Otherwise the entry reports ``created`` when its target
147
+ directory does not yet exist (a fresh install) and ``updated`` when it
148
+ exists but its contents would change.
149
+ """
150
+ if not child_outcomes or all(outcome == "unchanged" for outcome in child_outcomes):
151
+ return "unchanged"
152
+ return "created" if not target_dir.exists() else "updated"
153
+
154
+
155
+ def _prospective_child_outcomes(
156
+ entry: InstallEntry,
157
+ *,
158
+ src: Path,
159
+ dst: Path,
160
+ ignore: IgnoreFn,
161
+ exclude: list[str],
162
+ root: Path,
163
+ harness_root: Path | None,
164
+ project_root: Path | None,
165
+ harness_name: str,
166
+ ) -> list[MaterializationOutcome]:
167
+ """Classify each child of a per-file directory mode without writing.
168
+
169
+ Each branch mirrors the matching ``apply_*`` function in
170
+ :mod:`install_driver_apply` — the same source enumeration, the same
171
+ cohort-doc exclusion, the same native-text conversion — so the no-write
172
+ classification tracks what the real install would decide.
173
+ """
174
+ outcomes: list[MaterializationOutcome] = []
175
+ if entry.mode == "merge_tree_entries":
176
+ for source_path in sorted(src.iterdir()):
177
+ if _is_excluded_path(source_path, exclude):
178
+ continue
179
+ if source_path.name in ignore(str(src), [source_path.name]):
180
+ continue
181
+ target = dst / source_path.name
182
+ if source_path.is_dir():
183
+ if _directory_contents_equal(source_path, target, ignore):
184
+ outcomes.append("unchanged")
185
+ else:
186
+ outcomes.append("updated" if target.exists() else "created")
187
+ elif source_path.is_file():
188
+ data = source_path.read_bytes()
189
+ if b"${" in data:
190
+ with contextlib.suppress(UnicodeDecodeError):
191
+ data = render_content_tokens(
192
+ data.decode("utf-8"),
193
+ harness_root=harness_root,
194
+ project_root=project_root,
195
+ ).encode("utf-8")
196
+ outcomes.append(_prospective_file_outcome(target, data))
197
+ return outcomes
198
+ for source_path in sorted(src.glob("*.md")):
199
+ if source_path.name in _COHORT_DOC_FILES:
200
+ continue
201
+ if entry.mode == "command_skills":
202
+ skill_dir = dst / source_path.stem
203
+ content = _generated_skill_text(
204
+ source_path, harness_name=harness_name, install_root=root
205
+ )
206
+ if _single_file_directory_matches(skill_dir, "SKILL.md", content):
207
+ outcomes.append("unchanged")
208
+ else:
209
+ outcomes.append("updated" if skill_dir.exists() else "created")
210
+ continue
211
+ if entry.mode == "codex_agents":
212
+ target = dst / f"{source_path.stem}.toml"
213
+ outcome = _prospective_file_outcome(
214
+ target, _codex_agent_text(source_path).encode("utf-8")
215
+ )
216
+ # A stale ``.md`` from a prior layout is removed before the ``.toml``
217
+ # is written, so its presence makes the child a change even when the
218
+ # rendered ``.toml`` already matches.
219
+ if outcome == "unchanged" and (dst / source_path.name).exists():
220
+ outcome = "updated"
221
+ outcomes.append(outcome)
222
+ continue
223
+ if entry.mode == "gemini_commands":
224
+ outcomes.append(
225
+ _prospective_file_outcome(
226
+ dst / f"{source_path.stem}.toml",
227
+ _gemini_command_text(source_path).encode("utf-8"),
228
+ )
229
+ )
230
+ continue
231
+ converter = _NATIVE_FILE_CONVERTERS.get(entry.mode)
232
+ if converter is not None:
233
+ outcomes.append(
234
+ _prospective_file_outcome(
235
+ dst / source_path.name, converter(source_path).encode("utf-8")
236
+ )
237
+ )
238
+ return outcomes
239
+
240
+
241
+ def _prospective_entry_outcome(
242
+ entry: InstallEntry,
243
+ *,
244
+ target: Path,
245
+ src: Path,
246
+ ignore: IgnoreFn,
247
+ exclude: list[str],
248
+ root: Path,
249
+ harness_root: Path | None,
250
+ project_root: Path | None,
251
+ harness_name: str,
252
+ ) -> MaterializationOutcome:
253
+ """Classify an Apothem-owned ``write_text`` or any tree entry, no writes.
254
+
255
+ Operator-owned ``write_text`` / ``sentinel_merge`` entries route through
256
+ :func:`_operator_owned_preview` instead (it also yields the unified diff);
257
+ this covers the Apothem-owned ``write_text`` direct copy and every directory
258
+ mode. The plan validator guarantees each source exists.
259
+ """
260
+ if entry.mode == "write_text":
261
+ content = render_content_tokens(
262
+ src.read_text(encoding="utf-8"),
263
+ harness_root=harness_root,
264
+ project_root=project_root,
265
+ )
266
+ if target.suffix.lower() == ".json" and target.exists():
267
+ with contextlib.suppress(json.JSONDecodeError, OSError):
268
+ content = _merged_json_text(target, content, prefer_existing=True)
269
+ return _prospective_file_outcome(target, content.encode("utf-8"))
270
+ if entry.mode == "replace_tree":
271
+ if target.exists() and _directory_contents_equal(src, target, ignore):
272
+ return "unchanged"
273
+ return "updated" if target.exists() else "created"
274
+ return _aggregate_dir_outcome(
275
+ _prospective_child_outcomes(
276
+ entry,
277
+ src=src,
278
+ dst=target,
279
+ ignore=ignore,
280
+ exclude=exclude,
281
+ root=root,
282
+ harness_root=harness_root,
283
+ project_root=project_root,
284
+ harness_name=harness_name,
285
+ ),
286
+ target_dir=target,
287
+ )
288
+
289
+
290
+ def _dry_run_results(
291
+ rules: HarnessRules,
292
+ *,
293
+ root: Path,
294
+ harness_root: Path | None,
295
+ project_root: Path | None,
296
+ harness_name: str,
297
+ profile_body: str | None,
298
+ ) -> list[MaterializationResult]:
299
+ """Return prospective no-write results for the validated plan.
300
+
301
+ Each install entry is classified against its current on-disk target —
302
+ ``created`` (target absent), ``updated`` (target present and differing), or
303
+ ``unchanged`` (target present and already matching) — by mirroring what the
304
+ matching ``apply_*`` function would decide, without touching the filesystem.
305
+ A re-preview after install therefore reports the unchanged targets as no-ops
306
+ instead of phantom writes. The plan validator has already run, so every
307
+ entry's source exists; *profile_body* is folded into ``sentinel_merge``
308
+ anchors so their classification matches the projected managed block.
309
+ """
310
+ ignore = make_ignore(rules.exclude, rules.per_directory_filters)
311
+ results: list[MaterializationResult] = []
312
+ for legacy in rules.stale_sweep:
313
+ stale = root / legacy
314
+ results.append(
315
+ _result(
316
+ "skipped" if stale.exists() else "unchanged",
317
+ "sweep_stale",
318
+ stale,
319
+ _DRY_RUN_MESSAGE,
320
+ )
321
+ )
322
+ for entry in rules.install:
323
+ target = resolve_target(
324
+ entry.target,
325
+ harness_root=harness_root,
326
+ project_root=project_root,
327
+ )
328
+ src = resolve_source(entry.source)
329
+ detail: dict[str, str] = {"ownership_class": entry.ownership_class}
330
+ outcome: MaterializationOutcome
331
+ operator_owned_write = entry.mode == "sentinel_merge" or (
332
+ entry.mode == "write_text" and entry.ownership_class == "operator-owned"
333
+ )
334
+ if operator_owned_write:
335
+ preview = _operator_owned_preview(
336
+ entry,
337
+ harness_root=harness_root,
338
+ project_root=project_root,
339
+ profile_body=profile_body,
340
+ )
341
+ if preview is None:
342
+ outcome = "skipped"
343
+ else:
344
+ target, outcome, diff, gate_required = preview
345
+ if entry.ownership_class == "operator-owned":
346
+ if diff:
347
+ detail["diff"] = diff
348
+ if gate_required:
349
+ detail["destructive_gate"] = "required"
350
+ else:
351
+ outcome = _prospective_entry_outcome(
352
+ entry,
353
+ target=target,
354
+ src=src,
355
+ ignore=ignore,
356
+ exclude=rules.exclude,
357
+ root=root,
358
+ harness_root=harness_root,
359
+ project_root=project_root,
360
+ harness_name=harness_name,
361
+ )
362
+ results.append(
363
+ _with_detail(
364
+ _result(outcome, entry.mode, target, _DRY_RUN_MESSAGE, source=src),
365
+ detail,
366
+ )
367
+ )
368
+ return results
369
+
370
+
371
+ def _dispatch_install_entry(
372
+ entry: InstallEntry,
373
+ ignore: IgnoreFn,
374
+ rules: HarnessRules,
375
+ *,
376
+ harness_root: Path | None,
377
+ project_root: Path | None,
378
+ harness_name: str,
379
+ authorize: AuthorizeFn | None = None,
380
+ profile_body: str | None = None,
381
+ ) -> list[MaterializationResult]:
382
+ """Apply one validated install entry and return structured results."""
383
+ if entry.mode == "write_text":
384
+ return apply_write_text(
385
+ entry,
386
+ harness_root=harness_root,
387
+ project_root=project_root,
388
+ harness_name=harness_name,
389
+ authorize=authorize,
390
+ )
391
+ if entry.mode == "sentinel_merge":
392
+ return apply_sentinel_merge(
393
+ entry,
394
+ harness_root=harness_root,
395
+ project_root=project_root,
396
+ harness_name=harness_name,
397
+ authorize=authorize,
398
+ profile_body=profile_body,
399
+ )
400
+ if entry.mode == "replace_tree":
401
+ return apply_replace_tree(
402
+ entry,
403
+ ignore,
404
+ harness_root=harness_root,
405
+ project_root=project_root,
406
+ harness_name=harness_name,
407
+ )
408
+ if entry.mode == "merge_tree_entries":
409
+ return apply_merge_tree_entries(
410
+ entry,
411
+ ignore,
412
+ rules.exclude,
413
+ harness_root=harness_root,
414
+ project_root=project_root,
415
+ harness_name=harness_name,
416
+ )
417
+ if entry.mode == "command_skills":
418
+ return apply_command_skills(
419
+ entry,
420
+ harness_root=harness_root,
421
+ project_root=project_root,
422
+ harness_name=harness_name,
423
+ )
424
+ if entry.mode == "codex_agents":
425
+ return apply_codex_agents(
426
+ entry,
427
+ harness_root=harness_root,
428
+ project_root=project_root,
429
+ harness_name=harness_name,
430
+ )
431
+ if entry.mode == "gemini_agents":
432
+ return apply_gemini_agents(
433
+ entry,
434
+ harness_root=harness_root,
435
+ project_root=project_root,
436
+ harness_name=harness_name,
437
+ )
438
+ if entry.mode == "opencode_agents":
439
+ return apply_opencode_agents(
440
+ entry,
441
+ harness_root=harness_root,
442
+ project_root=project_root,
443
+ harness_name=harness_name,
444
+ )
445
+ if entry.mode == "qwen_agents":
446
+ return apply_qwen_agents(
447
+ entry,
448
+ harness_root=harness_root,
449
+ project_root=project_root,
450
+ harness_name=harness_name,
451
+ )
452
+ if entry.mode == "gemini_commands":
453
+ return apply_gemini_commands(
454
+ entry,
455
+ harness_root=harness_root,
456
+ project_root=project_root,
457
+ harness_name=harness_name,
458
+ )
459
+ if entry.mode == "markdown_commands":
460
+ return apply_markdown_commands(
461
+ entry,
462
+ harness_root=harness_root,
463
+ project_root=project_root,
464
+ harness_name=harness_name,
465
+ )
466
+ raise ValueError(
467
+ f"unknown install entry mode '{entry.mode}' for source '{entry.source}'"
468
+ )
469
+
470
+
471
+ def _materialize_data_surfaces(
472
+ harness_name: str, root: Path, *, profile: dict[str, Any] | None = None
473
+ ) -> list[MaterializationResult]:
474
+ """Materialize the shared memory, contexts, and learning data surfaces.
475
+
476
+ Every target sharing *root* resolves to the SAME Apothem-owned working
477
+ directory (``<base>/.apothem/``, where *base* is derived from the profile's
478
+ ``workspace`` block) — seeded with an empty memory store, an empty contexts
479
+ store, and an empty learning store so the surfaces exist as concrete
480
+ artifacts after install. The seed is idempotent and non-destructive: an
481
+ operator's accumulated records, fragments, and captured learning signals are
482
+ never overwritten, so a re-install — or a second harness installing into the
483
+ same base — preserves them and reports ``unchanged``. Because the home is
484
+ shared, a write under one target is visible to every other target sharing
485
+ the base.
486
+
487
+ Seeding the learning surface captures nothing — it only creates the empty
488
+ store. Continuous-learning capture stays default-off: it activates only
489
+ when the operator sets ``enforcement.learning_loop`` and is gated at
490
+ :func:`apothem.lib.learning.capture`.
491
+
492
+ Args:
493
+ harness_name: The harness identifier whose install pass triggered the
494
+ materialization. Retained for the result message only — the home is
495
+ shared, not keyed by this identifier.
496
+ root: The install root (harness root or project root) the shared
497
+ working directory is anchored to under project-local scope.
498
+ profile: The install profile dict carrying the ``workspace`` block, or
499
+ ``None`` for the non-interactive path (project-local ``.apothem``).
500
+
501
+ Returns:
502
+ One materialization result per data surface (memory, contexts,
503
+ learning). An OS-level failure is reported as a ``warning`` result
504
+ rather than aborting the surrounding install pass.
505
+ """
506
+ from apothem.lib.contexts import ContextStore
507
+ from apothem.lib.learning import LearningStore
508
+ from apothem.lib.memory import MemoryStore
509
+
510
+ home_spec = resolve_install_data_home(root, profile=profile)
511
+ preexisting = home_spec.root.exists()
512
+ outcome: MaterializationOutcome = "unchanged" if preexisting else "created"
513
+ try:
514
+ home = home_spec.ensure()
515
+ memory_path = MemoryStore(home).ensure_initialized()
516
+ contexts_path = ContextStore(home).ensure_initialized()
517
+ learning_path = LearningStore(home).ensure_initialized()
518
+ except OSError as exc:
519
+ return [
520
+ _result(
521
+ "warning",
522
+ "data_surface",
523
+ home_spec.root,
524
+ f"could not materialize memory/contexts/learning data surfaces: {exc}",
525
+ )
526
+ ]
527
+ return [
528
+ _result(
529
+ outcome,
530
+ "data_surface",
531
+ memory_path,
532
+ "materialized memory surface data home",
533
+ ),
534
+ _result(
535
+ outcome,
536
+ "data_surface",
537
+ contexts_path,
538
+ "materialized contexts surface data home",
539
+ ),
540
+ _result(
541
+ outcome,
542
+ "data_surface",
543
+ learning_path,
544
+ "materialized learning surface data home",
545
+ ),
546
+ ]
547
+
548
+
549
+ def run_install(
550
+ harness_name: str,
551
+ *,
552
+ harness_root: Path | None = None,
553
+ project_root: Path | None = None,
554
+ dry_run: bool = False,
555
+ authorize: AuthorizeFn | None = None,
556
+ profile: dict[str, Any] | None = None,
557
+ ) -> MaterializationRun:
558
+ """Propagate *harness_name*'s convention surface to its install root.
559
+
560
+ User-scope callers pass ``harness_root`` (created if absent); project-scope
561
+ callers pass ``project_root`` (assumed to exist). The manifest's
562
+ stale-sweep entries are removed first, then each install entry is applied
563
+ in declaration order. Destructive replacements are reversible: existing
564
+ targets are copied to ``~/.apothem/backups/`` before replacement or
565
+ stale-sweep deletion.
566
+
567
+ When *profile* is supplied, its projected managed block is folded into every
568
+ ``sentinel_merge`` instruction anchor (alongside the template governance),
569
+ so the shared profile reaches the harness's instruction surface.
570
+
571
+ When *authorize* is supplied, every non-additive overwrite of an
572
+ operator-owned target is gated through it: returning ``False`` skips that
573
+ write and leaves the operator's file untouched. ``None`` (the default) is
574
+ the non-interactive path — operator content is merge-preserved and backed
575
+ up, never silently lost.
576
+ """
577
+ rules = install_driver.load_rules(harness_name)
578
+ profile_body = _projected_profile_body(harness_name, profile)
579
+ root = _root_for(harness_root, project_root)
580
+ results = _capability_projection_results(harness_name)
581
+ errors = _validate_install_plan(
582
+ rules,
583
+ root=root,
584
+ harness_root=harness_root,
585
+ project_root=project_root,
586
+ )
587
+ if errors:
588
+ run = MaterializationRun(
589
+ harness=harness_name,
590
+ dry_run=dry_run,
591
+ results=(*results, *errors),
592
+ )
593
+ first_error = errors[0]
594
+ raise MaterializationError(
595
+ f"materialization validation failed: {first_error.message}",
596
+ run,
597
+ )
598
+ if dry_run:
599
+ return MaterializationRun(
600
+ harness=harness_name,
601
+ dry_run=True,
602
+ results=(
603
+ *results,
604
+ *_dry_run_results(
605
+ rules,
606
+ root=root,
607
+ harness_root=harness_root,
608
+ project_root=project_root,
609
+ harness_name=harness_name,
610
+ profile_body=profile_body,
611
+ ),
612
+ ),
613
+ )
614
+ if harness_root is not None:
615
+ harness_root.mkdir(parents=True, exist_ok=True)
616
+ ignore = make_ignore(rules.exclude, rules.per_directory_filters)
617
+ write_root = _allowed_write_root(harness_root, project_root)
618
+
619
+ # Transactional pass: serialize concurrent installs into the same
620
+ # (harness, root) behind one advisory lock (a different root keys a different
621
+ # lock and is not blocked), and on a mid-pass failure restore every target
622
+ # written so far from its just-captured backup before re-raising — a partial
623
+ # install never leaves a half-materialized tree. The lock is released on
624
+ # success and on exception (context-manager exit).
625
+ with atomic_io.advisory_lock(_install_lock_path(harness_name, root)):
626
+ try:
627
+ results.extend(
628
+ sweep_stale(
629
+ rules.stale_sweep,
630
+ root,
631
+ harness_name=harness_name,
632
+ allowed_root=write_root,
633
+ )
634
+ )
635
+ for entry in rules.install:
636
+ entry_results = install_driver._dispatch_install_entry(
637
+ entry,
638
+ ignore,
639
+ rules,
640
+ harness_root=harness_root,
641
+ project_root=project_root,
642
+ harness_name=harness_name,
643
+ authorize=authorize,
644
+ profile_body=profile_body,
645
+ )
646
+ results.extend(entry_results)
647
+ entry_errors = [
648
+ result for result in entry_results if result.outcome == "error"
649
+ ]
650
+ if entry_errors:
651
+ raise MaterializationError(
652
+ f"materialization write failed: {entry_errors[0].message}",
653
+ MaterializationRun(
654
+ harness=harness_name,
655
+ dry_run=False,
656
+ results=tuple(results),
657
+ ),
658
+ )
659
+ results.extend(
660
+ _materialize_data_surfaces(harness_name, root, profile=profile)
661
+ )
662
+ except BaseException:
663
+ _compensating_rollback(results, allowed_root=write_root)
664
+ with contextlib.suppress(Exception):
665
+ install_ledger.append_record(
666
+ LedgerRecord.create(
667
+ harness=harness_name, root=root, kind="rollback"
668
+ )
669
+ )
670
+ raise
671
+ return MaterializationRun(
672
+ harness=harness_name,
673
+ dry_run=False,
674
+ results=tuple(results),
675
+ )