@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,32 @@
1
+ <!-- SPDX-License-Identifier: MIT -->
2
+
3
+ # Apothem — Zed Bootstrap
4
+
5
+ This file is materialised by `apothem install --harness zed --project <path>` and lands at `<project>/.rules`, the current Zed project agent-instruction surface per https://zed.dev/docs/ai/instructions. Zed auto-includes this flat project-root file (alongside the `AGENTS.md` / `CLAUDE.md` family) as agent instructions; there is no per-tool rules directory, so the whole apothem surface lands in this single file. Any pre-existing `.rules` is backed up before this file replaces it.
6
+
7
+ ## What Apothem governs in this project
8
+
9
+ Apothem propagates a shared governance and convention surface across every supported AI harness in this project's host environment. Inside Zed, the surface manifests as this `.rules` instruction file:
10
+
11
+ - **Rules** — engineering rules applied on every interaction. The full rule cohort lives at the apothem source repository under `src/apothem/rules/`; this Zed-facing anchor names the disciplines the operator may consult in detail.
12
+ - **Skills, commands, agents** — reusable techniques, slash-style workflows, and persistent sub-agent definitions. Apothem's canonical-master cohort at the apothem source repository defines them; Zed does not auto-discover them as separate surfaces, so they manifest here as referenced discipline.
13
+ - **Context servers (MCP)** — Zed's MCP surface (`.zed/settings.json` `context_servers`) is operator-owned, not apothem-managed.
14
+ - **Global instructions** — Zed's global instruction surface (`~/.config/zed/AGENTS.md`) is operator-owned, not apothem-managed.
15
+
16
+ ## Engineering disciplines in force
17
+
18
+ Apothem's foundational mandates apply uniformly across every harness, including Zed:
19
+
20
+ - **Plans-Locality.** Plan-suite artefacts (PROGRESS.md, PLAN-NOTES.md, PHASE.md, REPORT.md) live under `<project>/.apothem/plans/{suite}/` — the sole canonical home; a legacy `<project>/.plans/` tree upgrades via `apothem migrate-workspace`. They never land in a global plans directory or any other global-ecosystem location.
21
+ - **Authority hygiene.** Never fabricate identity, scope, security posture, or version-pin data. Surface ambiguity through a question instead of inventing a plausible-looking value.
22
+ - **Definitiveness.** Hedging vocabulary (`maybe`, `might`, `usually`, `generally`, `typically`, `probably`) is eliminated where binding prescription is possible. Pre / post / failure conditions are stated on every contract.
23
+ - **Production-ready discipline.** Every change ships in production-ready form — tests, docs, CHANGELOG entry, conformant commit message, CI green — in the same change-set.
24
+ - **Plain-language.** Codebase artefacts and user-facing prose read as natural domain language with zero trace of internal planning structure.
25
+ - **Human-only authorship.** Git commit messages, PR descriptions, branch names, and tag annotations carry human contributors only — never the underlying language model, runtime, IDE extension, or any automated tool as a co-author.
26
+ - **Lean-context delegation.** Where the host provides delegated-worker dispatch, broad reads and heavy workloads route to a spawned worker by default so the main working context stays lean. The heavy parallel apparatus stays opt-in; routing delegable work away from the main thread is the standing posture once dispatch is available.
27
+ - **Observe-decide-act discipline.** Tool use runs as a loop — observe the current state, decide the next move from what was observed, then act — never an edit before a read or a result asserted before a check. Independent reads and searches run together in one pass, not one per turn; the loop closes on a verifiable condition (a gate green, a read confirmed), never a fixed number of tries. Advisory, never an auto-applied behavior.
28
+ - **Source accessibility.** When the authoritative source for a claim, convention, or version pin is closed, paywalled, login-gated, or otherwise unreachable, ask the operator for it in full rather than substituting a lower-trust open page. Trust outranks reachability.
29
+
30
+ ## Refreshing the file
31
+
32
+ Re-run `apothem install --harness zed --project <this-project-root>` to overwrite this file with the latest apothem template. The operation is idempotent. `apothem uninstall --harness zed --project <this-project-root>` renames the file to a timestamped backup; `apothem verify --harness zed --project <this-project-root>` checks the file is present and non-empty.
@@ -0,0 +1,28 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Uninstall logic for the zed harness adapter."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from pathlib import Path
8
+
9
+ from apothem.harnesses._shared import install_driver
10
+
11
+ _HARNESS_NAME: str = "zed"
12
+
13
+
14
+ def uninstall(output_path: Path, *, project: Path | None = None) -> None:
15
+ """Remove Apothem-managed Zed targets surgically.
16
+
17
+ Zed's flat-file divergence: the target is ``<project>/.rules`` (one
18
+ level below the project root), so the project root is the file's
19
+ direct parent — unlike the cohort's nested rules-directory targets. The
20
+ ``.rules`` ``sentinel_merge`` anchor is cleaned by the shared driver, which
21
+ strips only Apothem's managed block (operator prose survives), deletes an
22
+ Apothem-only file, and backs the file up under the Apothem backup root — no
23
+ whole-file ``.bak`` sibling is left beside the operator's file.
24
+ """
25
+ install_driver.run_uninstall(
26
+ _HARNESS_NAME,
27
+ project_root=project or output_path.parent,
28
+ )
@@ -0,0 +1,10 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Update logic for the zed harness adapter."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from apothem.harnesses._shared.wrapper_factories import make_update_project
8
+ from apothem.harnesses.zed.install import install
9
+
10
+ update = make_update_project(install)
@@ -0,0 +1,11 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Verify logic for the zed harness adapter."""
4
+
5
+ from __future__ import annotations
6
+
7
+ from apothem.harnesses._shared.wrapper_factories import make_verify_project
8
+
9
+ _HARNESS_NAME: str = "zed"
10
+
11
+ verify = make_verify_project(_HARNESS_NAME)
@@ -0,0 +1,81 @@
1
+ <!-- SPDX-License-Identifier: MIT -->
2
+
3
+ # hooks
4
+
5
+ > **Role.** The hook runtime. A unified Python dispatcher handles every
6
+ > harness hook event, emits per-event Markdown context, and runs the
7
+ > session-start bootstrap.
8
+
9
+ ```mermaid
10
+ %%{ init: { "theme": "neutral" } }%%
11
+ %% verified: 2026-06-23 %%
12
+ %% provenance: hooks/README.md — the hook-dispatch runtime flow %%
13
+ %% cross-reference: src/apothem/hooks/dispatch.py (router); src/apothem/hooks/lib/bootstrap.sh + bootstrap.ps1 (stubs); src/apothem/hooks/messages/ (per-event context) %%
14
+ flowchart TD
15
+ Event["Harness fires a hook event<br/>PreToolUse · PostToolUse · SessionStart · Stop · PreCompact · …"]
16
+ Stub["Bootstrap stub — lib/bootstrap.sh / bootstrap.ps1<br/>locates a Python interpreter, then execs the dispatcher<br/>(Claude Code settings.json invokes an install-resolved interpreter on dispatch.py directly)"]
17
+ Dispatch["dispatch.py — unified router<br/>routes each event to its handler"]
18
+ Context["Per-event Markdown context<br/>from messages/&lt;event&gt;.md"]
19
+ Bootstrap["session_start_bootstrap.py<br/>(SessionStart only)"]
20
+
21
+ Event --> Stub --> Dispatch
22
+ Dispatch -->|most events| Context
23
+ Dispatch -->|SessionStart| Bootstrap
24
+ ```
25
+
26
+ ## Entry points
27
+
28
+ | File | Purpose |
29
+ |------|---------|
30
+ | `dispatch.py` | Unified Python entrypoint for all hook events — routes each event to its handler. |
31
+ | `emit_hook_context.py` | Emit structured JSON context for hook events. |
32
+ | `session_start_bootstrap.py` | Session-start bootstrap hook for the Apothem ecosystem. |
33
+ | `__init__.py` | Package marker. |
34
+
35
+ ## `lib/` — dispatcher support
36
+
37
+ | File | Purpose |
38
+ |------|---------|
39
+ | `bootstrap.sh` / `bootstrap.ps1` | Shell bootstrap stubs that locate an interpreter (via the locators below) and `exec` the dispatcher. Shipped as the documented shell entry path; the Claude Code `settings.json` entries instead invoke an install-resolved absolute interpreter on `dispatch.py` directly. |
40
+ | `find-python.sh` / `find-python.ps1` | Python interpreter locators. |
41
+ | `find-pwsh.sh` / `find-pwsh.ps1` | PowerShell interpreter locators. |
42
+ | `events.py` | Single source of truth for the supported hook-event vocabulary. |
43
+ | `log.py` | Shared logger factory for the hook scripts. |
44
+ | `resolve_root.py` | Project-root resolution for the Apothem ecosystem. |
45
+ | `__init__.py` | Package marker. |
46
+
47
+ ## `messages/` — per-event context
48
+
49
+ Markdown context files emitted into the conversation for each hook event:
50
+
51
+ | File | Event |
52
+ |------|-------|
53
+ | `sessionstart.md` | SessionStart. |
54
+ | `stop.md` | Stop (session-end). |
55
+ | `precompact.md` / `postcompact.md` | PreCompact / PostCompact. |
56
+ | `pretooluse-write.md` / `pretooluse-write-header-guard.md` / `pretooluse-write-plan-guard.md` | PreToolUse Write / apply_patch — base context plus the authorship-header and plans-discipline guards. |
57
+ | `pretooluse-edit.md` / `pretooluse-edit-header-guard.md` | PreToolUse Edit — base context plus the authorship-header guard. |
58
+ | `pretooluse-notebookedit.md` | PreToolUse NotebookEdit. |
59
+ | `pretooluse-bash.md` / `pretooluse-bash-plan-guard.md` | PreToolUse Bash — base context plus the plans-discipline redirection guard. |
60
+ | `pretooluse-conformity.md` | PreToolUse conformity-gate context. |
61
+ | `pretooluse-dependency-guard.md` | PreToolUse Write / Edit — advisory flag on unpinned or untrusted dependency additions to manifests and lockfiles. |
62
+ | `pretooluse-eval-guard.md` | PreToolUse Write / Edit / Bash — advisory flag on dynamic evaluation of untrusted or model-derived input. |
63
+ | `pretooluse-askuserquestion-recommended.md` | PreToolUse AskUserQuestion — advisory `(Recommended)`-marker guard on rendered option sets. |
64
+ | `posttooluse-proactive-compaction.md` | PostToolUse — proactive-compaction tracker context (CM-19). |
65
+
66
+ ## Conventions
67
+
68
+ - The Claude Code `settings.json` hook entries invoke an install-resolved absolute CPython interpreter on `dispatch.py` directly — the `${PYTHON_BIN}` placeholder is substituted at install time (per `apothem.lib.python_resolver`) so no entry runs a bare `python`. The shell bootstrap stubs (`bootstrap.sh` / `bootstrap.ps1`) are the documented shell entry path that locates an interpreter and hands off to `dispatch.py`; they are not the `settings.json` entry point.
69
+
70
+ ## Operating in this folder
71
+
72
+ - **Fail-open is the dispatcher contract.** `dispatch.py::main` always exits 0; any uncaught exception is converted to a valid JSON failure envelope on stdout so the host harness never sees a raw traceback and never stalls. A handler that can raise past `main` is a contract breach — preserve the `# noqa: BLE001` intent-marker on the outermost boundary, and never widen the dispatcher's fail-open boundary.
73
+ - **The event vocabulary has one source of truth:** `lib/events.py` (`SUPPORTED_EVENTS`, `HOOK_SPECIFIC_OUTPUT_EVENTS`). Never hard-code an event-name list elsewhere; import from `events`.
74
+ - **Per-event timeout budgets bound runtime** (PreToolUse / PostToolUse / UserPromptSubmit / Notification tighter; SessionStart / PreCompact / PostCompact wider; Stop widest). A handler exceeding its event's budget is silently skipped by the runtime — keep handler work inside the budget; the per-event runtime benchmark is [`../benchmarks/bench_hooks.py`](../benchmarks/bench_hooks.py).
75
+ - **Adding an event:** extend `lib/events.py` first, then the dispatcher routing, then a `messages/<event>.md` context file. A new `messages/<event>.md` carries the markdown SPDX comment line and is registered in the table above in the same change.
76
+ - Validate a change with `python -m ruff check`, `python -m mypy` (cli + harnesses scope), and `python -m pytest`. Surface any unresolved decision as `TODO(clarify): ...` rather than guessing.
77
+
78
+ ## Related
79
+
80
+ - [`conformity/gate.py`](../conformity/gate.py) — the conformity gate the PreToolUse Write/Edit hooks invoke.
81
+ - [`benchmarks/bench_hooks.py`](../benchmarks/bench_hooks.py) — the per-event hook-handler runtime benchmark.
@@ -0,0 +1,24 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Hook dispatcher and per-event context emitters.
4
+
5
+ This package carries the apothem hook-event pipeline. The runtime
6
+ entry-points are:
7
+
8
+ * ``apothem.hooks.dispatch`` — the harness-side dispatcher. Harness
9
+ hook entries invoke the materialized copy by absolute script path
10
+ (``<harness-root>/apothem/hooks/dispatch.py`` or the harness's hook
11
+ subtree), so no importable ``apothem`` package is required on the
12
+ host. Receives an event name and an optional message name; emits the
13
+ per-event Markdown context to stdout for the harness to surface in
14
+ the operator's chat session.
15
+ * ``apothem.hooks.emit_hook_context`` — the per-event context emitter
16
+ that materializes a Markdown payload from the bundled message
17
+ fixtures and the live ecosystem state.
18
+ * ``apothem.hooks.session_start_bootstrap`` — the SessionStart-event
19
+ bootstrap that surfaces the conformity posture, memory summary, plan
20
+ summary, and session-source banner at every fresh session.
21
+
22
+ Shared helpers live under ``apothem.hooks.lib`` (event taxonomy,
23
+ logging, root resolution).
24
+ """
@@ -0,0 +1,380 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Call-time validator for the ``AskUserQuestion`` tool's option payload.
4
+
5
+ Why this validator exists. The option-annotation matchers
6
+ (``conformity/option_annotation_grep.py``) scan committed ``*.md`` artifacts —
7
+ they verify the canonical ``(Recommended)`` marker on rendered option sets that
8
+ already live in the tree. Nothing inspected the LIVE ``AskUserQuestion`` tool
9
+ payload at the moment the agent asks the operator, so a malformed or absent
10
+ marker reached the operator unchecked. This module is the dispatch-routed
11
+ ``PreToolUse`` handler that closes that gap: it receives the tool input (a
12
+ ``questions`` array, each question carrying ``options[].label`` and
13
+ ``multiSelect``), validates marker well-formedness against the canonical rule,
14
+ and emits an advisory ``systemMessage`` (default) or — under the repo's strict
15
+ opt-in — a blocking ``decision`` envelope.
16
+
17
+ What it CAN guarantee. Well-formedness: a marker present on a label is in the
18
+ canonical form (capital ``(Recommended)``, exact end-of-label placement, one
19
+ leading space, not on a destructive option, at most one per single-select
20
+ question). These are objectively decidable from the payload alone.
21
+
22
+ What it CANNOT guarantee. The native ``AskUserQuestion`` payload carries no
23
+ separate "recommended" field — the marker IS the only signal of which option is
24
+ recommended. So this validator cannot prove a missing marker is a defect: a
25
+ single-select question with two substantive options and zero markers is merely
26
+ *advised* (a NUDGE) to mark its recommended option, never blocked. Forcing a
27
+ recommendation to exist is a behavioral-convention obligation the rules carry,
28
+ not a fact this runtime check can decide.
29
+
30
+ Contract. Fast (sub-second; pure-Python regex over a small payload),
31
+ idempotent, and FAIL-OPEN: any exception → allow the call (an empty envelope),
32
+ never crash the operator's question. The strict opt-in mirrors the conformity
33
+ gate's: the ``--strict`` flag or a truthy ``APOTHEM_CONFORMITY_STRICT``
34
+ environment variable escalates WELL-FORMEDNESS findings (never the NUDGE) to a
35
+ ``decision: block``.
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ import json
41
+ import os
42
+ import re
43
+ import sys
44
+ from dataclasses import dataclass, field
45
+ from typing import Final
46
+
47
+ # Strict opt-in mirrors the conformity gate's (``conformity/gate.py``). Reused
48
+ # verbatim here so the AskUserQuestion validator and the per-Write gate share
49
+ # one strict-mode contract: the operator enables blocking once, for both.
50
+ STRICT_ENV: Final[str] = "APOTHEM_CONFORMITY_STRICT"
51
+ _STRICT_TRUTHY: Final[frozenset[str]] = frozenset({"1", "true", "yes", "on"})
52
+
53
+ # Canonical recommended-marker forms, kept in lockstep with the static matcher
54
+ # at ``conformity/option_annotation_grep.py``. The canonical postfix is capital
55
+ # ``(Recommended)`` at the exact end of the label with one leading space; the
56
+ # lowercase ``(recommended)`` form is a banned variant. We re-derive the same
57
+ # anchored patterns here because the static matcher operates on Markdown lines
58
+ # (``- `Label`:``) while this validator operates on a structured label string,
59
+ # so the line-shaped label regexes there do not apply — but the postfix rules
60
+ # (case, bracket, end-anchor) are identical and MUST NOT diverge.
61
+ _CANONICAL_POSTFIX_RE: Final[re.Pattern[str]] = re.compile(r" \(Recommended\)$")
62
+ _LOWERCASE_POSTFIX_RE: Final[re.Pattern[str]] = re.compile(r"\(recommended\)\s*$")
63
+ # Any non-canonical bracketing / spacing of the recommended token at the label
64
+ # tail: ``[Recommended]``, ``(Rec)``, ``(Recommended )``, ``( Recommended )`` —
65
+ # anything that names "recommend" near the tail but is not the exact canonical
66
+ # ``" (Recommended)"`` postfix.
67
+ _NONCANONICAL_TAIL_RE: Final[re.Pattern[str]] = re.compile(
68
+ r"[\[(]\s*rec(?:ommend(?:ed)?)?\s*[\])]\s*$", re.IGNORECASE
69
+ )
70
+
71
+ # Destructive-intent label tokens. A recommended marker on a clearly-destructive
72
+ # option contradicts the no-default floor for irreversible operations
73
+ # (``rules/interactive-questions-canonical-shapes.md`` §5.8): a recommendation
74
+ # marker on an irreversible action steers the operator toward the dangerous path.
75
+ _DESTRUCTIVE_LABEL_RE: Final[re.Pattern[str]] = re.compile(
76
+ r"\b("
77
+ r"delete|remove|retire|discard|destroy|wipe|erase|drop|purge|"
78
+ r"overwrite|reset|revert|rm|truncate|force[- ]?push"
79
+ r")\b",
80
+ re.IGNORECASE,
81
+ )
82
+
83
+ # A "substantive" option for the NUDGE heuristic: anything that is not the
84
+ # harness-implicit free-text escape hatch (the ``Other`` option the tool adds).
85
+ _IMPLICIT_OTHER_RE: Final[re.Pattern[str]] = re.compile(r"^\s*other\s*$", re.IGNORECASE)
86
+
87
+
88
+ @dataclass(frozen=True)
89
+ class Finding:
90
+ """One validation result against the canonical marker rules.
91
+
92
+ ``severity`` is ``"finding"`` for an objectively-decidable well-formedness
93
+ violation (escalatable to a block under strict mode) or ``"nudge"`` for the
94
+ heuristic missing-marker advisory (never escalated — it can only advise).
95
+ """
96
+
97
+ severity: str
98
+ kind: str
99
+ question_index: int
100
+ label: str
101
+ detail: str
102
+
103
+
104
+ @dataclass(frozen=True)
105
+ class ValidationResult:
106
+ """Aggregate outcome of validating one ``AskUserQuestion`` payload."""
107
+
108
+ findings: list[Finding] = field(default_factory=list)
109
+
110
+ @property
111
+ def wellformedness_findings(self) -> list[Finding]:
112
+ """Objectively-decidable violations (block-eligible under strict mode)."""
113
+ return [f for f in self.findings if f.severity == "finding"]
114
+
115
+ @property
116
+ def nudges(self) -> list[Finding]:
117
+ """Heuristic missing-marker advisories (never block)."""
118
+ return [f for f in self.findings if f.severity == "nudge"]
119
+
120
+
121
+ def strict_enabled(argv: list[str] | None = None) -> bool:
122
+ """Return True when the strict opt-in is active.
123
+
124
+ Mirrors ``conformity/gate.py``: the ``--strict`` flag or a truthy
125
+ ``APOTHEM_CONFORMITY_STRICT`` environment variable enables blocking.
126
+ """
127
+ args = argv if argv is not None else sys.argv[1:]
128
+ if "--strict" in args:
129
+ return True
130
+ return os.environ.get(STRICT_ENV, "").strip().lower() in _STRICT_TRUTHY
131
+
132
+
133
+ def _label_is_canonical_marked(label: str) -> bool:
134
+ """True iff the label ends with the exact canonical ``" (Recommended)"``."""
135
+ return _CANONICAL_POSTFIX_RE.search(label) is not None
136
+
137
+
138
+ def _label_has_lowercase_marker(label: str) -> bool:
139
+ """True iff the label ends with the banned lowercase ``(recommended)``."""
140
+ return _LOWERCASE_POSTFIX_RE.search(label) is not None
141
+
142
+
143
+ def _label_has_noncanonical_marker(label: str) -> bool:
144
+ """True iff the label tail names a recommended token in a non-canonical form.
145
+
146
+ Catches ``[Recommended]``, ``(Rec)``, ``(Recommended )``, ``( Recommended )``
147
+ and similar bracketed tail variants. The canonical ``" (Recommended)"`` form
148
+ is excluded (it is the legitimate postfix); the lowercase variant is reported
149
+ separately as ``non-canonical-postfix-case`` so its detail is precise.
150
+ """
151
+ if _label_is_canonical_marked(label):
152
+ return False
153
+ if _label_has_lowercase_marker(label):
154
+ return False
155
+ return _NONCANONICAL_TAIL_RE.search(label) is not None
156
+
157
+
158
+ def _is_destructive_label(label: str) -> bool:
159
+ """True iff the label names a clearly-destructive / irreversible action."""
160
+ return _DESTRUCTIVE_LABEL_RE.search(label) is not None
161
+
162
+
163
+ def _is_substantive_option(label: str) -> bool:
164
+ """True iff the option is a real choice, not the implicit ``Other`` escape."""
165
+ return bool(label.strip()) and _IMPLICIT_OTHER_RE.match(label) is None
166
+
167
+
168
+ def _option_labels(question: dict[str, object]) -> list[str]:
169
+ """Extract the option labels from one question, tolerating shape drift."""
170
+ raw_options = question.get("options")
171
+ if not isinstance(raw_options, list):
172
+ return []
173
+ labels: list[str] = []
174
+ for option in raw_options:
175
+ if isinstance(option, str):
176
+ labels.append(option)
177
+ elif isinstance(option, dict):
178
+ label = option.get("label")
179
+ if isinstance(label, str):
180
+ labels.append(label)
181
+ return labels
182
+
183
+
184
+ def _validate_question(index: int, question: dict[str, object]) -> list[Finding]:
185
+ """Validate one question's option labels against the canonical marker rules."""
186
+ findings: list[Finding] = []
187
+ labels = _option_labels(question)
188
+ if not labels:
189
+ return findings
190
+ multi_select = bool(question.get("multiSelect", False))
191
+
192
+ canonical_marked = 0
193
+ for label in labels:
194
+ if _label_has_lowercase_marker(label):
195
+ findings.append(
196
+ Finding(
197
+ severity="finding",
198
+ kind="non-canonical-postfix-case",
199
+ question_index=index,
200
+ label=label,
201
+ detail=(
202
+ "label uses lowercase (recommended); the canonical form "
203
+ "is the capital (Recommended) postfix"
204
+ ),
205
+ )
206
+ )
207
+ elif _label_has_noncanonical_marker(label):
208
+ findings.append(
209
+ Finding(
210
+ severity="finding",
211
+ kind="non-canonical-postfix-form",
212
+ question_index=index,
213
+ label=label,
214
+ detail=(
215
+ "label names a recommended token in a non-canonical "
216
+ "bracket/spacing form; the canonical form is the exact "
217
+ '" (Recommended)" postfix with one leading space at the '
218
+ "end of the label"
219
+ ),
220
+ )
221
+ )
222
+ elif _label_is_canonical_marked(label):
223
+ canonical_marked += 1
224
+ if _is_destructive_label(label):
225
+ findings.append(
226
+ Finding(
227
+ severity="finding",
228
+ kind="recommended-on-destructive",
229
+ question_index=index,
230
+ label=label,
231
+ detail=(
232
+ "the (Recommended) marker rides a clearly-destructive "
233
+ "option; an irreversible action must not be the "
234
+ "recommended (and easy) path"
235
+ ),
236
+ )
237
+ )
238
+
239
+ if not multi_select and canonical_marked > 1:
240
+ findings.append(
241
+ Finding(
242
+ severity="finding",
243
+ kind="single-select-multi-recommended",
244
+ question_index=index,
245
+ label="",
246
+ detail=(
247
+ f"single-select question carries {canonical_marked} "
248
+ "(Recommended) markers; at most one is permitted "
249
+ "(set multiSelect: true to recommend several)"
250
+ ),
251
+ )
252
+ )
253
+
254
+ # NUDGE: a single-select question with two or more substantive options and
255
+ # zero markers. Heuristic only — the native payload carries no separate
256
+ # "recommended" field, so a missing marker cannot be proven a defect.
257
+ substantive = [lab for lab in labels if _is_substantive_option(lab)]
258
+ if not multi_select and len(substantive) >= 2 and canonical_marked == 0:
259
+ findings.append(
260
+ Finding(
261
+ severity="nudge",
262
+ kind="no-recommended-marker",
263
+ question_index=index,
264
+ label="",
265
+ detail=(
266
+ f"single-select question offers {len(substantive)} "
267
+ "substantive options but marks none (Recommended); the "
268
+ "option-annotation discipline advises marking the "
269
+ "recommended option so the operator sees the agent's "
270
+ "evaluation"
271
+ ),
272
+ )
273
+ )
274
+ return findings
275
+
276
+
277
+ def validate_payload(payload: dict[str, object] | None) -> ValidationResult:
278
+ """Validate an ``AskUserQuestion`` tool payload's option markers.
279
+
280
+ Pre-condition: *payload* is the harness ``PreToolUse`` stdin object (or
281
+ ``None`` when stdin carried no parseable object). Post-condition: every
282
+ well-formedness violation and missing-marker nudge across every question is
283
+ enumerated; an unparseable or shapeless payload yields an empty result
284
+ (fail-open — nothing to validate).
285
+ """
286
+ if not payload:
287
+ return ValidationResult()
288
+ tool_input = payload.get("tool_input")
289
+ if not isinstance(tool_input, dict):
290
+ return ValidationResult()
291
+ questions = tool_input.get("questions")
292
+ if not isinstance(questions, list):
293
+ return ValidationResult()
294
+ findings: list[Finding] = []
295
+ for index, question in enumerate(questions):
296
+ if isinstance(question, dict):
297
+ findings.extend(_validate_question(index, question))
298
+ return ValidationResult(findings=findings)
299
+
300
+
301
+ def _read_payload() -> dict[str, object] | None:
302
+ """Read and parse the hook's stdin JSON payload, fail-open on any error."""
303
+ try:
304
+ if sys.stdin.isatty():
305
+ return None
306
+ raw = sys.stdin.read()
307
+ except OSError:
308
+ return None
309
+ if not raw or not raw.strip():
310
+ return None
311
+ try:
312
+ parsed = json.loads(raw)
313
+ except (json.JSONDecodeError, ValueError):
314
+ return None
315
+ return parsed if isinstance(parsed, dict) else None
316
+
317
+
318
+ def _format_findings(findings: list[Finding]) -> str:
319
+ """Render findings as one human-readable line each."""
320
+ lines: list[str] = []
321
+ for finding in findings:
322
+ label = f" label={finding.label!r}" if finding.label else ""
323
+ lines.append(
324
+ f" - [Q{finding.question_index}] {finding.kind}{label}: {finding.detail}"
325
+ )
326
+ return "\n".join(lines)
327
+
328
+
329
+ def build_envelope(result: ValidationResult, *, strict: bool) -> dict[str, object]:
330
+ """Map a validation result to a hook-output envelope.
331
+
332
+ Default (advisory): a ``systemMessage`` surfacing well-formedness findings
333
+ and nudges; the question proceeds. Strict: a ``decision: block`` envelope
334
+ when well-formedness findings exist (nudges never block). A clean result
335
+ yields an empty envelope (the question proceeds silently).
336
+ """
337
+ wellformedness = result.wellformedness_findings
338
+ nudges = result.nudges
339
+ if strict and wellformedness:
340
+ reason_lines = [
341
+ "Apothem AskUserQuestion guard (strict): the option set carries "
342
+ "(Recommended)-marker well-formedness violation(s). Fix the "
343
+ "label(s) and re-ask:",
344
+ _format_findings(wellformedness),
345
+ ]
346
+ if nudges:
347
+ reason_lines.append("Advisory (not blocking):\n" + _format_findings(nudges))
348
+ return {"decision": "block", "reason": "\n".join(reason_lines)}
349
+
350
+ advisory: list[Finding] = [*wellformedness, *nudges]
351
+ if not advisory:
352
+ return {}
353
+ header = (
354
+ "Apothem AskUserQuestion guard (advisory): review the "
355
+ "(Recommended)-marker finding(s) below; the question proceeds. "
356
+ "Set APOTHEM_CONFORMITY_STRICT=1 (or pass --strict) to block on "
357
+ "well-formedness violations."
358
+ )
359
+ return {"systemMessage": header + "\n" + _format_findings(advisory)}
360
+
361
+
362
+ def main(argv: list[str] | None = None) -> None:
363
+ """Entry point. Validates the payload and emits one envelope; never raises.
364
+
365
+ FAIL-OPEN: any unexpected exception is swallowed and an empty (allow)
366
+ envelope is written, so a validator bug never crashes the operator's
367
+ question.
368
+ """
369
+ try:
370
+ strict = strict_enabled(argv)
371
+ payload = _read_payload()
372
+ result = validate_payload(payload)
373
+ envelope = build_envelope(result, strict=strict)
374
+ sys.stdout.write(json.dumps(envelope, separators=(",", ":")) + "\n")
375
+ except Exception: # noqa: BLE001, RUF100 - fail-open boundary: a validator error must never block the operator's question; emit an allow envelope and proceed (BLE001 is the intent marker; RUF100 self-suppresses because ruff's BLE family is not active)
376
+ sys.stdout.write("{}\n")
377
+
378
+
379
+ if __name__ == "__main__":
380
+ main()