@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,21 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """JSON-output helper for the apothem CLI.
4
+
5
+ Writes a single JSON document to stdout terminated by a newline, so
6
+ shell consumers can ``jq .`` the result directly.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import sys
13
+
14
+
15
+ def emit_json(data: object) -> None:
16
+ """Serialize *data* to stdout as a JSON document followed by a newline.
17
+
18
+ Uses ``default=str`` so :class:`pathlib.Path` and other non-JSON-native
19
+ types round-trip to their string form rather than raising.
20
+ """
21
+ sys.stdout.write(json.dumps(data, default=str) + "\n")
@@ -0,0 +1,376 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Shared install/update materialization orchestrators.
4
+
5
+ ``_materialize`` drives a single-harness or batch install/update from the
6
+ shared profile (blast-radius preview, placeholder advisory, fail-fast batch
7
+ error handling — the first harness failure aborts the run and emits the
8
+ partial result accumulated so far, lifecycle envelope);
9
+ ``_dry_run_materialization`` returns a
10
+ no-write plan run. Both are consumed by the install / update / quickstart
11
+ command modules. Patchable-helper call sites resolve through the
12
+ ``apothem.cli`` package (``_pkg``)."""
13
+
14
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+ from typing import cast
18
+
19
+ import click
20
+
21
+ import apothem.cli as _pkg
22
+ from apothem.cli._common_flags import get_console
23
+ from apothem.cli._helpers import (
24
+ _EXIT_EXPECTED,
25
+ _EXIT_PARTIAL,
26
+ _Adapter,
27
+ _adapter_resolve_output_path,
28
+ _CliUserError,
29
+ _emit_expected_error,
30
+ _invoke_with_project,
31
+ _lifecycle_envelope,
32
+ _load_profile,
33
+ _materialization_error,
34
+ _partition_blast_radius,
35
+ _placeholder_advisory_entry,
36
+ _placeholder_identity_fields,
37
+ _profile_error,
38
+ _render_blast_radius,
39
+ _resolve_profile_path,
40
+ _resolve_project_root,
41
+ _result_dicts,
42
+ _warning_dicts,
43
+ )
44
+ from apothem.cli._json_formatter import emit_json
45
+ from apothem.harnesses._shared.install_driver import (
46
+ MaterializationError,
47
+ MaterializationResult,
48
+ MaterializationRun,
49
+ )
50
+ from apothem.lib.clean_slate import CleanSlateError, run_clean_slate
51
+ from apothem.lib.profile import ProfileValidationError
52
+
53
+
54
+ def _materialize(
55
+ harness: str,
56
+ profile: str | None,
57
+ dry_run: bool,
58
+ verb_present: str,
59
+ verb_past: str,
60
+ *,
61
+ fmt: str = "plain",
62
+ quiet: bool = False,
63
+ no_color: bool = False,
64
+ project: str | None = None,
65
+ clean: bool = False,
66
+ assume_yes: bool = False,
67
+ verbose: bool = False,
68
+ payload_sink: list[dict[str, object]] | None = None,
69
+ ) -> None:
70
+ """Install or update a harness adapter from the shared profile.
71
+
72
+ The command accepts a single harness id or ``all``. Profiles are
73
+ validated before dry-runs and writes, and JSON output always uses the
74
+ lifecycle envelope required by the product contract.
75
+ """
76
+ con = get_console(no_color=no_color, quiet=quiet)
77
+ profile_path = _resolve_profile_path(profile)
78
+ try:
79
+ project_root = _resolve_project_root(project)
80
+ shared_profile = _load_profile(profile_path)
81
+ selected = _pkg._selected_harness_ids(
82
+ harness,
83
+ shared_profile=shared_profile,
84
+ apply_excludes=harness.strip().lower() == "all",
85
+ )
86
+ _pkg._require_project_for_selection(selected, project_root)
87
+ adapters = [
88
+ (
89
+ harness_id,
90
+ _pkg._load_adapter_for_entry(_pkg.get_harness_entry(harness_id)),
91
+ )
92
+ for harness_id in selected
93
+ ]
94
+ except ProfileValidationError as exc:
95
+ _emit_expected_error(
96
+ command=verb_present,
97
+ fmt=fmt,
98
+ harness=harness,
99
+ profile_path=profile_path,
100
+ error=_profile_error(exc),
101
+ )
102
+ return
103
+ except _CliUserError as exc:
104
+ _emit_expected_error(
105
+ command=verb_present,
106
+ fmt=fmt,
107
+ harness=harness,
108
+ profile_path=profile_path,
109
+ error=exc.to_dict(),
110
+ )
111
+ return
112
+
113
+ # Opt-in clean-slate removal runs after the profile is loaded into memory
114
+ # (above) and before any fresh materialization below. The profile file is
115
+ # one of the bounded removal targets, so its bytes are captured here and
116
+ # restored after removal — the shared profile is the operator's identity
117
+ # source of truth, not stale install state, and the timestamped backup
118
+ # preserves every removed target for recovery.
119
+ if clean:
120
+ profile_bytes = profile_path.read_bytes() if profile_path.is_file() else None
121
+ try:
122
+ run_clean_slate(
123
+ Path.home(),
124
+ dry_run=dry_run,
125
+ assume_yes=assume_yes,
126
+ # Use the patchable seam (not raw sys.stdin.isatty()) so the
127
+ # clean-slate interactivity gate is test-reachable, matching the
128
+ # blast-radius confirmation below.
129
+ interactive=_pkg._stdin_is_interactive(),
130
+ echo=(con.print if fmt != "json" else None),
131
+ )
132
+ except CleanSlateError as exc:
133
+ _emit_expected_error(
134
+ command=verb_present,
135
+ fmt=fmt,
136
+ harness=harness,
137
+ profile_path=profile_path,
138
+ error=_CliUserError(
139
+ code="clean_slate.refused",
140
+ message="Clean-slate removal was refused.",
141
+ field="clean",
142
+ reason=str(exc),
143
+ fix="Re-run interactively, pass --yes for non-interactive use, "
144
+ "or correct the unsafe target before retrying.",
145
+ ).to_dict(),
146
+ )
147
+ return
148
+ if not dry_run and profile_bytes is not None:
149
+ profile_path.parent.mkdir(parents=True, exist_ok=True)
150
+ profile_path.write_bytes(profile_bytes)
151
+ if dry_run:
152
+ return
153
+
154
+ # Blast-radius disclosure (multi-harness install only). An ``all`` install
155
+ # fans out into mixed scopes: project-scope adapters write under --project,
156
+ # but user-scope adapters write under the operator's real home directory —
157
+ # a surprise worth disclosing before any byte is written. The grouped
158
+ # preview prints in plain mode; when the selection writes outside the
159
+ # supplied project root, an interactive confirmation guards the home-rooted
160
+ # writes. --yes, a non-interactive context, --dry-run, and --format json
161
+ # each bypass the prompt (dry-run and json still print/return the preview
162
+ # data without mutating). Single-named installs and update are out of scope.
163
+ if harness.strip().lower() == "all" and verb_present == "install" and fmt != "json":
164
+ within, outside = _partition_blast_radius(adapters, project_root)
165
+ _render_blast_radius(con, within, outside, project_root)
166
+ if not dry_run and outside and not assume_yes and _pkg._stdin_is_interactive():
167
+ click.confirm("Proceed and write these files?", abort=True)
168
+
169
+ all_files_written: list[str] = []
170
+ all_results: list[dict[str, object]] = []
171
+ all_warnings: list[dict[str, object]] = []
172
+
173
+ # Placeholder-identity advisory (install + update). When the loaded profile
174
+ # still carries the shipped scaffold identity, surface a single advisory so a
175
+ # fake identity is not silently projected — advisory only, never blocking
176
+ # (identity is never fabricated or coerced). It rides the JSON warnings array
177
+ # and prints once in plain mode, regardless of the harness selection.
178
+ placeholder_fields = _placeholder_identity_fields(shared_profile)
179
+ if placeholder_fields:
180
+ advisory = _placeholder_advisory_entry(profile_path, placeholder_fields)
181
+ all_warnings.append(advisory)
182
+ if fmt != "json":
183
+ con.print(f"[yellow]Note:[/] {advisory['message']}")
184
+ last_output_path: Path | None = None
185
+ last_materialization: MaterializationRun | None = None
186
+
187
+ for harness_id, adapter in adapters:
188
+ output_path = _adapter_resolve_output_path(adapter, project_root)
189
+ last_output_path = output_path
190
+ materialization: MaterializationRun | None
191
+
192
+ try:
193
+ if dry_run:
194
+ materialization = _dry_run_materialization(
195
+ harness_id,
196
+ adapter,
197
+ output_path,
198
+ project_root,
199
+ )
200
+ elif verb_present == "update":
201
+ maybe_run = _invoke_with_project(
202
+ adapter.update,
203
+ shared_profile,
204
+ project=project_root,
205
+ )
206
+ materialization = (
207
+ maybe_run if isinstance(maybe_run, MaterializationRun) else None
208
+ )
209
+ else:
210
+ maybe_run = _invoke_with_project(
211
+ adapter.install,
212
+ shared_profile,
213
+ project=project_root,
214
+ )
215
+ materialization = (
216
+ maybe_run if isinstance(maybe_run, MaterializationRun) else None
217
+ )
218
+ except MaterializationError as exc:
219
+ error = _materialization_error(exc, files_written=exc.run.files_written)
220
+ results = [*all_results, *_result_dicts(harness_id, exc.run)]
221
+ warnings = [*all_warnings, *_warning_dicts(harness_id, exc.run)]
222
+ files_written = [*all_files_written, *exc.run.files_written]
223
+ exit_code = _EXIT_PARTIAL if files_written else _EXIT_EXPECTED
224
+ _emit_expected_error(
225
+ command=verb_present,
226
+ fmt=fmt,
227
+ harness=harness,
228
+ profile_path=profile_path,
229
+ project_root=project_root,
230
+ error=error,
231
+ files_written=files_written,
232
+ results=results,
233
+ warnings=warnings,
234
+ exit_code=exit_code,
235
+ )
236
+ return
237
+ except NotImplementedError:
238
+ error = _CliUserError(
239
+ code="harness.not_implemented",
240
+ message="Apothem adapter is not implemented.",
241
+ field="harness",
242
+ reason=f"{harness_id} does not implement {verb_present}.",
243
+ fix="Choose another harness or update the adapter package.",
244
+ ).to_dict()
245
+ _emit_expected_error(
246
+ command=verb_present,
247
+ fmt=fmt,
248
+ harness=harness,
249
+ profile_path=profile_path,
250
+ project_root=project_root,
251
+ error=error,
252
+ files_written=all_files_written,
253
+ results=all_results,
254
+ warnings=all_warnings,
255
+ exit_code=_EXIT_PARTIAL if all_files_written else _EXIT_EXPECTED,
256
+ )
257
+ return
258
+ except _CliUserError as exc:
259
+ _emit_expected_error(
260
+ command=verb_present,
261
+ fmt=fmt,
262
+ harness=harness,
263
+ profile_path=profile_path,
264
+ project_root=project_root,
265
+ error=exc.to_dict(),
266
+ files_written=all_files_written,
267
+ results=all_results,
268
+ warnings=all_warnings,
269
+ exit_code=_EXIT_PARTIAL if all_files_written else _EXIT_EXPECTED,
270
+ )
271
+ return
272
+
273
+ last_materialization = materialization
274
+ if materialization is not None:
275
+ all_files_written.extend(materialization.files_written)
276
+ all_results.extend(_result_dicts(harness_id, materialization))
277
+ all_warnings.extend(_warning_dicts(harness_id, materialization))
278
+
279
+ if fmt != "json":
280
+ if materialization is not None and materialization.warnings:
281
+ if verbose:
282
+ for warning in materialization.warnings:
283
+ con.print(
284
+ f"[yellow]Warning:[/] {harness_id} - {warning.message}"
285
+ )
286
+ else:
287
+ count = len(materialization.warnings)
288
+ noun = "capability" if count == 1 else "capabilities"
289
+ con.print(
290
+ f"[dim]Note:[/] {harness_id} - {count} {noun} not "
291
+ "projected; pass --verbose for detail"
292
+ )
293
+ if dry_run:
294
+ con.print(
295
+ f"[bold yellow]DRY RUN[/] would {verb_present} "
296
+ f"[cyan]{harness_id}[/] -> {output_path}"
297
+ )
298
+ else:
299
+ con.print(
300
+ f"[green]✓[/] {verb_past} [cyan]{harness_id}[/] -> {output_path}"
301
+ )
302
+
303
+ if fmt == "json":
304
+ status = "dry_run" if dry_run else "success"
305
+ action = "dry_run" if dry_run else verb_past.lower()
306
+ payload = _lifecycle_envelope(
307
+ status=status,
308
+ command=verb_present,
309
+ action=action,
310
+ harness=harness,
311
+ profile_path=profile_path,
312
+ project_root=project_root,
313
+ files_written=all_files_written,
314
+ results=all_results,
315
+ warnings=all_warnings,
316
+ output_path=last_output_path if len(adapters) == 1 else None,
317
+ materialization=last_materialization if len(adapters) == 1 else None,
318
+ )
319
+ # When a caller supplies a sink (the guided ``quickstart`` flow), hand it
320
+ # the success envelope instead of emitting, so the caller can fold it into
321
+ # one combined JSON summary rather than printing two documents.
322
+ if payload_sink is not None:
323
+ payload_sink.append(payload)
324
+ else:
325
+ emit_json(payload)
326
+ elif len(adapters) > 1 and not quiet:
327
+ con.print(
328
+ f"[green]✓[/] {verb_past} {len(adapters)} harnesses "
329
+ f"({len(all_files_written)} files written)."
330
+ )
331
+
332
+ if clean and not dry_run and fmt != "json" and not quiet:
333
+ verify_harness = harness if harness.strip().lower() != "all" else "all"
334
+ con.print(
335
+ "[bold]Next step:[/] confirm the fresh install with "
336
+ f"[cyan]apothem verify --harness {verify_harness}[/]"
337
+ )
338
+
339
+
340
+ def _dry_run_materialization(
341
+ harness_id: str,
342
+ adapter: _Adapter,
343
+ output_path: Path,
344
+ project_root: Path | None,
345
+ ) -> MaterializationRun:
346
+ """Return a no-write materialization run using the adapter plan surface."""
347
+ plan_entries: list[dict[str, str]] = []
348
+ plan_fn = getattr(adapter, "plan", None)
349
+ if callable(plan_fn):
350
+ try:
351
+ candidate = _invoke_with_project(plan_fn, output_path, project=project_root)
352
+ except Exception as exc:
353
+ raise _CliUserError(
354
+ code="materialization.plan_failed",
355
+ message="Apothem dry-run planning failed.",
356
+ field="harness",
357
+ reason=str(exc),
358
+ fix="Check the harness adapter and project path before retrying.",
359
+ ) from exc
360
+ if isinstance(candidate, list):
361
+ plan_entries = cast("list[dict[str, str]]", candidate)
362
+ results = tuple(
363
+ MaterializationResult(
364
+ outcome="skipped",
365
+ operation=entry.get("mode", "plan"),
366
+ path=entry.get("target", str(output_path)),
367
+ source=entry.get("source"),
368
+ message="dry run: no filesystem changes made",
369
+ )
370
+ for entry in plan_entries
371
+ )
372
+ return MaterializationRun(
373
+ harness=_pkg.get_harness_entry(harness_id).package_key,
374
+ dry_run=True,
375
+ results=results,
376
+ )
@@ -0,0 +1,30 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ _apothem_completion() {
4
+ local IFS=$'\n'
5
+ local response
6
+
7
+ response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD _APOTHEM_COMPLETE=bash_complete $1)
8
+
9
+ for completion in $response; do
10
+ IFS=',' read type value <<< "$completion"
11
+
12
+ if [[ $type == 'dir' ]]; then
13
+ COMPREPLY=()
14
+ compopt -o dirnames
15
+ elif [[ $type == 'file' ]]; then
16
+ COMPREPLY=()
17
+ compopt -o default
18
+ elif [[ $type == 'plain' ]]; then
19
+ COMPREPLY+=($value)
20
+ fi
21
+ done
22
+
23
+ return 0
24
+ }
25
+
26
+ _apothem_completion_setup() {
27
+ complete -o nosort -F _apothem_completion apothem
28
+ }
29
+
30
+ _apothem_completion_setup;
@@ -0,0 +1,19 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ function _apothem_completion;
4
+ set -l response (env _APOTHEM_COMPLETE=fish_complete COMP_WORDS=(commandline -cp) COMP_CWORD=(commandline -t) apothem);
5
+
6
+ for completion in $response;
7
+ set -l metadata (string split "," $completion);
8
+
9
+ if test $metadata[1] = "dir";
10
+ __fish_complete_directories $metadata[2];
11
+ else if test $metadata[1] = "file";
12
+ __fish_complete_path $metadata[2];
13
+ else if test $metadata[1] = "plain";
14
+ echo $metadata[2];
15
+ end;
16
+ end;
17
+ end;
18
+
19
+ complete --no-files --command apothem --arguments "(_apothem_completion)";
@@ -0,0 +1,27 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ # SPDX-License-Identifier: MIT
4
+ # Apothem PowerShell completion stub.
5
+ #
6
+ # Click 8 does not ship a native PowerShell completer. Source this script
7
+ # from your $PROFILE to register dynamic completion for `apothem`. It
8
+ # shells out to the apothem binary with _APOTHEM_COMPLETE=powershell_complete
9
+ # on each TAB, asking Click to compute the candidate list. If your apothem
10
+ # entry-point is not on PATH, adjust the call path below.
11
+ Register-ArgumentCompleter -Native -CommandName apothem -ScriptBlock {
12
+ param($wordToComplete, $commandAst, $cursorPosition)
13
+ $env:_APOTHEM_COMPLETE = "powershell_complete"
14
+ $env:COMP_WORDS = $commandAst.ToString()
15
+ $env:COMP_CWORD = $commandAst.CommandElements.Count - 1
16
+ $result = apothem 2>$null
17
+ Remove-Item Env:_APOTHEM_COMPLETE -ErrorAction SilentlyContinue
18
+ Remove-Item Env:COMP_WORDS -ErrorAction SilentlyContinue
19
+ Remove-Item Env:COMP_CWORD -ErrorAction SilentlyContinue
20
+ foreach ($line in $result -split "`n") {
21
+ if ($line) {
22
+ [System.Management.Automation.CompletionResult]::new(
23
+ $line, $line, "ParameterValue", $line
24
+ )
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,42 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ #compdef apothem
4
+
5
+ _apothem_completion() {
6
+ local -a completions
7
+ local -a completions_with_descriptions
8
+ local -a response
9
+ (( ! $+commands[apothem] )) && return 1
10
+
11
+ response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) _APOTHEM_COMPLETE=zsh_complete apothem)}")
12
+
13
+ for type key descr in ${response}; do
14
+ if [[ "$type" == "plain" ]]; then
15
+ if [[ "$descr" == "_" ]]; then
16
+ completions+=("$key")
17
+ else
18
+ completions_with_descriptions+=("$key":"$descr")
19
+ fi
20
+ elif [[ "$type" == "dir" ]]; then
21
+ _path_files -/
22
+ elif [[ "$type" == "file" ]]; then
23
+ _path_files -f
24
+ fi
25
+ done
26
+
27
+ if [ -n "$completions_with_descriptions" ]; then
28
+ _describe -V unsorted completions_with_descriptions -U
29
+ fi
30
+
31
+ if [ -n "$completions" ]; then
32
+ compadd -U -V unsorted -a completions
33
+ fi
34
+ }
35
+
36
+ if [[ $zsh_eval_context[-1] == loadautofunc ]]; then
37
+ # autoload from fpath, call function directly
38
+ _apothem_completion "$@"
39
+ else
40
+ # eval/source/. command, register function for later
41
+ compdef _apothem_completion apothem
42
+ fi
@@ -0,0 +1,126 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Deterministic JSON exporter for source-generated documentation reference.
4
+
5
+ Runnable as ``python -m apothem.cli.reference_export <kind>`` where ``<kind>``
6
+ is one of ``cli`` or ``harnesses``. The emitter introspects Apothem's own Click
7
+ command tree and harness registry — the single source of truth — so the
8
+ generated reference pages cannot drift from the implementation.
9
+
10
+ Output is a single JSON document with stable key order and sorted collections,
11
+ so repeated runs against an unchanged tree are byte-identical.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import sys
18
+
19
+ import click
20
+
21
+ from apothem.cli import main as cli_main
22
+ from apothem.lib.harness_registry import iter_harness_entries
23
+
24
+ # Continuous-form CLI aliases (``Installing`` / ``installing`` and the
25
+ # capitalized / lowercase ``Updating`` / ``Uninstalling`` variants) duplicate
26
+ # the canonical lowercase verbs. They are excluded from the reference so each
27
+ # command appears exactly once under its canonical name.
28
+ _ALIAS_COMMAND_NAMES: frozenset[str] = frozenset(
29
+ {
30
+ "Installing",
31
+ "installing",
32
+ "Updating",
33
+ "updating",
34
+ "Uninstalling",
35
+ "uninstalling",
36
+ }
37
+ )
38
+
39
+
40
+ def _option_signatures(command: click.Command) -> list[str]:
41
+ """Return the sorted flag signatures declared by *command*.
42
+
43
+ Each entry is the comma-joined option declaration string (for example
44
+ ``--harness`` or ``-h, --help``). The implicit ``--help`` option Click adds
45
+ is included so the reference matches the observable CLI surface.
46
+ """
47
+ signatures: list[str] = []
48
+ for param in command.params:
49
+ if not isinstance(param, click.Option):
50
+ continue
51
+ signatures.append(", ".join(param.opts))
52
+ return sorted(signatures)
53
+
54
+
55
+ def _command_entry(name: str, command: click.Command) -> dict[str, object]:
56
+ """Build the deterministic export record for one leaf command."""
57
+ return {
58
+ "name": name,
59
+ "flags": _option_signatures(command),
60
+ "description": (command.help or command.short_help or "").strip(),
61
+ }
62
+
63
+
64
+ def _walk_commands(prefix: str, group: click.Group) -> list[dict[str, object]]:
65
+ """Recursively collect leaf-command records under *group*.
66
+
67
+ Sub-groups (``profile``, ``harnesses``) recurse so their subcommands are
68
+ emitted as ``profile show``, ``harnesses list``, and so on. Alias commands
69
+ are skipped at the top level.
70
+ """
71
+ entries: list[dict[str, object]] = []
72
+ for child_name in group.commands:
73
+ if not prefix and child_name in _ALIAS_COMMAND_NAMES:
74
+ continue
75
+ child = group.commands[child_name]
76
+ full_name = f"{prefix} {child_name}".strip()
77
+ if isinstance(child, click.Group):
78
+ entries.extend(_walk_commands(full_name, child))
79
+ else:
80
+ entries.append(_command_entry(full_name, child))
81
+ return entries
82
+
83
+
84
+ def export_cli() -> dict[str, object]:
85
+ """Return the deterministic CLI command-and-flag export."""
86
+ commands = _walk_commands("", cli_main)
87
+ commands.sort(key=lambda entry: str(entry["name"]))
88
+ return {"kind": "cli", "commands": commands}
89
+
90
+
91
+ def export_harnesses() -> dict[str, object]:
92
+ """Return the deterministic harness-adapter registry export."""
93
+ harnesses = [
94
+ {
95
+ "id": entry.public_id,
96
+ "display_name": entry.display_name,
97
+ "scope": entry.scope,
98
+ "output_format": entry.output_format,
99
+ "target_paths": sorted(entry.target_paths),
100
+ }
101
+ for entry in iter_harness_entries()
102
+ ]
103
+ harnesses.sort(key=lambda entry: str(entry["id"]))
104
+ return {"kind": "harnesses", "harnesses": harnesses}
105
+
106
+
107
+ _EXPORTERS = {
108
+ "cli": export_cli,
109
+ "harnesses": export_harnesses,
110
+ }
111
+
112
+
113
+ def main(argv: list[str] | None = None) -> int:
114
+ """Emit the requested export kind as deterministic JSON on stdout."""
115
+ args = sys.argv[1:] if argv is None else argv
116
+ if len(args) != 1 or args[0] not in _EXPORTERS:
117
+ kinds = ", ".join(sorted(_EXPORTERS))
118
+ sys.stderr.write(f"usage: python -m apothem.cli.reference_export <{kinds}>\n")
119
+ return 2
120
+ payload = _EXPORTERS[args[0]]()
121
+ sys.stdout.write(json.dumps(payload, indent=2, sort_keys=True) + "\n")
122
+ return 0
123
+
124
+
125
+ if __name__ == "__main__":
126
+ raise SystemExit(main())