@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,296 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Detect hard-coded model identifiers, version pins, and stale dates.
4
+
5
+ Why this scan exists. Narrative artifacts that bake a specific model
6
+ identifier (``claude-3-opus-20240229``), a SemVer literal embedded in
7
+ prose ("requires foo >= 1.2.3"), or an "as of <date>" claim referring
8
+ to a date older than twelve months become stale silently. Stale claims
9
+ mislead readers and violate the visual-leverage staleness invariant
10
+ that says current-reality assertions carry their own freshness proof.
11
+ This scan surfaces every occurrence so refit phases can replace each
12
+ with a parameterised reference, a relative date, or an updated value
13
+ with a fresh verification stamp.
14
+
15
+ What this scan covers. Three regex families:
16
+
17
+ - **Model-identifier literals.** ``claude-(2|3|3-opus|3-5-sonnet|3-5-haiku
18
+ |3-7-sonnet|opus-4|sonnet-4|haiku-4|opus-4-1|sonnet-4-1|opus-4-5|sonnet-4-5
19
+ |opus-4-7|sonnet-4-6|haiku-4-5)`` and dated suffixes like
20
+ ``-20240229``. Any literal occurrence is a finding (the ecosystem
21
+ resolves model selection through the host's settings; a baked
22
+ identifier defeats that surface).
23
+ - **SemVer-in-prose.** A SemVer triple appearing inside narrative
24
+ Markdown that is not adjacent to a known version-pinning surface
25
+ (``CHANGELOG.md`` entries are exempt; lines containing ``version:``
26
+ or ``semver:`` keys are exempt).
27
+ - **Stale "as-of" date claims.** ``\\bas of (\\d{4}-\\d{2}-\\d{2})\\b`` and
28
+ ``\\bverified:?\\s+(\\d{4}-\\d{2}-\\d{2})\\b`` patterns; any matched
29
+ date older than 12 months from the run's wall-clock is a finding.
30
+
31
+ What this scan excludes. The repository's own ``CHANGELOG.md`` (where
32
+ SemVer literals legitimately mark release entries) and lines containing
33
+ the literal phrase ``deprecated:`` (which document retirement, not
34
+ current behavior). Memory and plan-artifact records are excluded by
35
+ the shared narrative-surface filter.
36
+ """
37
+
38
+ from __future__ import annotations
39
+
40
+ import argparse
41
+ import re
42
+ import sys
43
+ from datetime import date, datetime, timedelta, timezone
44
+ from pathlib import Path
45
+ from typing import Any
46
+
47
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
48
+
49
+ from _scan_lib import (
50
+ CONTENT_ROOT,
51
+ NARRATIVE_CLASSES,
52
+ SEVERITY_MEDIUM,
53
+ Hit,
54
+ WalkCallback,
55
+ emit_json,
56
+ load_inventory,
57
+ walk_narrative_surfaces,
58
+ )
59
+
60
+ # Match Anthropic-family model identifiers including dated suffixes.
61
+ # Cover the full pre-4 family plus the 4.x cohort (opus / sonnet / haiku
62
+ # at the 4-0 / 4-1 / 4-5 / 4-6 / 4-7 minor-version axis as documented in
63
+ # the active CLAUDE.md environment block).
64
+ _MODEL_PATTERN = re.compile(
65
+ r"\bclaude-("
66
+ r"2(?:\.\d+)?(?:-\w+)*"
67
+ r"|3-(?:opus|sonnet|haiku)(?:-\d{8})?"
68
+ r"|3[-.]5-(?:opus|sonnet|haiku)(?:-\d{8})?"
69
+ r"|3[-.]7-(?:opus|sonnet|haiku)(?:-\d{8})?"
70
+ r"|(?:opus|sonnet|haiku)-4(?:[-.]\d+)?(?:-\d{8})?(?:\[[^\]]+\])?"
71
+ r")\b"
72
+ )
73
+
74
+ # SemVer triple captured in two narrowly-scoped contexts:
75
+ # (a) v-prefixed (`v1.2.3` / `v1.2.3-rc1`) — the canonical pin shape.
76
+ # (b) bare triple anchored to a version-context keyword on the same
77
+ # line (``version``, ``release``, ``upgraded to``, ``bump to``).
78
+ # A bare ``X.Y.Z`` without context is far more often a section number
79
+ # (``§4.8.6``), an issue reference (``#1.2.3``), or a regex / literal
80
+ # than a stale version pin; constraining context kills the false-positive
81
+ # class that dominated the un-constrained match.
82
+ _SEMVER_V_PREFIXED = re.compile(
83
+ r"(?<![\w.])v(\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?)\b"
84
+ )
85
+ _SEMVER_BARE = re.compile(r"(?<![\w.§#])(\d+\.\d+\.\d+(?:-[\w.]+)?(?:\+[\w.]+)?)\b")
86
+ _VERSION_CONTEXT_RE = re.compile(
87
+ r"\b(version|release|upgrade(?:d)? to|bump(?:ed)? to|requires|"
88
+ r"depends on|pin(?:ned)? to)\b",
89
+ re.IGNORECASE,
90
+ )
91
+
92
+ # Phrases that anchor a date reference to a freshness claim.
93
+ _AS_OF_PATTERN = re.compile(
94
+ r"\b(?:as of|valid as of|verified|verified:|last verified|"
95
+ r"last updated|updated:?)\s+(\d{4}-\d{2}-\d{2})\b",
96
+ re.IGNORECASE,
97
+ )
98
+
99
+ # Lines exempt from the SemVer-in-prose finding because they live in
100
+ # legitimate version-pinning contexts.
101
+ _SEMVER_EXEMPT_PATTERNS = (
102
+ re.compile(r"^\s*version\s*:\s*", re.IGNORECASE),
103
+ re.compile(r"^\s*semver\s*:\s*", re.IGNORECASE),
104
+ re.compile(r"^\s*##\s*\[\d", re.IGNORECASE), # CHANGELOG ## [0.1.5]
105
+ re.compile(r"\bdeprecated:?\b", re.IGNORECASE),
106
+ )
107
+
108
+ # File-level exemption: the project's CHANGELOG legitimately enumerates
109
+ # SemVer release entries; date claims there are release dates, not
110
+ # freshness claims.
111
+ _FILE_EXEMPT_FROM_SEMVER = frozenset({"CHANGELOG.md"})
112
+
113
+ # URL prefixes that anchor version strings to legitimate references
114
+ # (badge image URLs, package-registry links, GitHub release pages, etc.).
115
+ # A SemVer match inside a URL is not narrative drift.
116
+ _URL_MARKER_RE = re.compile(r"https?://|\bshields\.io|\bbadgen\.net")
117
+
118
+ # A SemVer match is suppressed when the only context is a configuration
119
+ # surface that legitimately pins versions: lock files, manifests, hook
120
+ # configs. We restrict the SemVer-in-prose scan to Markdown files only;
121
+ # this set captures the Markdown-extension whitelist.
122
+ _SEMVER_SCAN_SUFFIXES = frozenset({".md", ".markdown"})
123
+
124
+
125
+ def _stale_date_threshold() -> date:
126
+ """Return the cutoff date older than which 'as-of' claims are stale.
127
+
128
+ Twelve months is the staleness window applied uniformly across the
129
+ audit. A shorter window would over-flag legitimate stable claims;
130
+ a longer one would let genuinely-stale assertions persist.
131
+ """
132
+ return datetime.now(timezone.utc).date() - timedelta(days=365)
133
+
134
+
135
+ def _scan_model_ids(rel: str, lineno: int, line: str) -> list[Hit]:
136
+ """Emit a hit per literal model identifier on the line."""
137
+ hits: list[Hit] = []
138
+ for match in _MODEL_PATTERN.finditer(line):
139
+ token = match.group(0)
140
+ hits.append(
141
+ Hit(
142
+ file=rel,
143
+ line=lineno,
144
+ signal=f"hard-coded-model-identifier: {token}",
145
+ severity=SEVERITY_MEDIUM,
146
+ remediation=(
147
+ "Replace the literal model identifier with a reference"
148
+ " resolved through the host's model selection surface;"
149
+ " bake-in defeats the indirection that lets operators"
150
+ " upgrade."
151
+ ),
152
+ )
153
+ )
154
+ return hits
155
+
156
+
157
+ def _scan_semver_prose(rel: str, lineno: int, line: str) -> list[Hit]:
158
+ """Emit a hit per SemVer literal that is not URL-anchored or
159
+ inside a configuration-pin context.
160
+
161
+ Two match channels: ``v``-prefixed pins (always flagged when not in
162
+ an exempt context) and bare triples (flagged only when a
163
+ version-context keyword appears on the same line).
164
+ """
165
+ if any(p.search(line) for p in _SEMVER_EXEMPT_PATTERNS):
166
+ return []
167
+ if _URL_MARKER_RE.search(line):
168
+ return []
169
+ hits: list[Hit] = []
170
+ for match in _SEMVER_V_PREFIXED.finditer(line):
171
+ token = match.group(0)
172
+ hits.append(_semver_hit(rel, lineno, token))
173
+ if _VERSION_CONTEXT_RE.search(line):
174
+ for match in _SEMVER_BARE.finditer(line):
175
+ token = match.group(0)
176
+ hits.append(_semver_hit(rel, lineno, token))
177
+ return hits
178
+
179
+
180
+ def _semver_hit(rel: str, lineno: int, token: str) -> Hit:
181
+ """Construct the canonical SemVer-in-prose hit record."""
182
+ return Hit(
183
+ file=rel,
184
+ line=lineno,
185
+ signal=f"semver-in-prose: {token}",
186
+ severity=SEVERITY_MEDIUM,
187
+ remediation=(
188
+ "Move the version pin to a configuration surface"
189
+ " (manifest, schema, version file) or convert the"
190
+ " prose claim into a parameterised reference."
191
+ ),
192
+ )
193
+
194
+
195
+ def _scan_stale_dates(
196
+ rel: str, lineno: int, line: str, stale_cutoff: date
197
+ ) -> list[Hit]:
198
+ """Emit a hit per 'as-of' claim whose date predates the staleness
199
+ cutoff."""
200
+ hits: list[Hit] = []
201
+ for match in _AS_OF_PATTERN.finditer(line):
202
+ date_str = match.group(1)
203
+ try:
204
+ claim_date = date.fromisoformat(date_str)
205
+ except ValueError:
206
+ continue
207
+ if claim_date >= stale_cutoff:
208
+ continue
209
+ age_days = (stale_cutoff - claim_date).days + 365
210
+ hits.append(
211
+ Hit(
212
+ file=rel,
213
+ line=lineno,
214
+ signal=(
215
+ f"stale-as-of-claim: {date_str} (~{age_days // 30} months old)"
216
+ ),
217
+ severity=SEVERITY_MEDIUM,
218
+ remediation=(
219
+ "Re-verify the claim against current state and update"
220
+ " the date stamp, or restate the claim with a"
221
+ " parameterised reference that does not require"
222
+ " periodic re-verification."
223
+ ),
224
+ )
225
+ )
226
+ return hits
227
+
228
+
229
+ def _is_markdown(path_str: str) -> bool:
230
+ """Return True if the file path looks like a Markdown document."""
231
+ return Path(path_str).suffix.lower() in _SEMVER_SCAN_SUFFIXES
232
+
233
+
234
+ def _scan_callback(stale_cutoff: date) -> WalkCallback:
235
+ """Build the per-file scanner closure."""
236
+
237
+ def _walk(path: Path, record: dict[str, Any], content: str) -> list[Hit]:
238
+ rel = record["path"]
239
+ is_md = _is_markdown(rel)
240
+ file_exempt_semver = Path(rel).name in _FILE_EXEMPT_FROM_SEMVER
241
+ in_fence = False
242
+ hits: list[Hit] = []
243
+ for lineno, line in enumerate(content.splitlines(), start=1):
244
+ if line.lstrip().startswith("```"):
245
+ in_fence = not in_fence
246
+ continue
247
+ hits.extend(_scan_model_ids(rel, lineno, line))
248
+ if is_md and not in_fence and not file_exempt_semver:
249
+ hits.extend(_scan_semver_prose(rel, lineno, line))
250
+ hits.extend(_scan_stale_dates(rel, lineno, line, stale_cutoff))
251
+ return hits
252
+
253
+ return _walk
254
+
255
+
256
+ def main(argv: list[str] | None = None) -> int:
257
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
258
+ parser.add_argument(
259
+ "--inventory",
260
+ type=Path,
261
+ default=Path(".audit/inventory.json"),
262
+ )
263
+ parser.add_argument("--root", type=Path, default=CONTENT_ROOT)
264
+ parser.add_argument(
265
+ "--output",
266
+ type=Path,
267
+ default=Path(".audit/drift-stale-tokens.json"),
268
+ )
269
+ args = parser.parse_args(argv)
270
+
271
+ if not args.inventory.exists():
272
+ print(
273
+ f"error: inventory not found at {args.inventory}",
274
+ file=sys.stderr,
275
+ )
276
+ return 1
277
+
278
+ records, sha = load_inventory(args.inventory)
279
+ cutoff = _stale_date_threshold()
280
+ hits = walk_narrative_surfaces(records, args.root, _scan_callback(cutoff))
281
+ emit_json(args.output, "scan_stale_tokens", hits, sha)
282
+ narrative_count = sum(1 for r in records if r.get("class") in NARRATIVE_CLASSES)
283
+ by_signal: dict[str, int] = {}
284
+ for h in hits:
285
+ kind = h.signal.split(":", 1)[0]
286
+ by_signal[kind] = by_signal.get(kind, 0) + 1
287
+ summary = ", ".join(f"{k}={v}" for k, v in sorted(by_signal.items()))
288
+ print(
289
+ f"scan_stale_tokens: {len(hits)} hit(s) across "
290
+ f"{narrative_count} narrative files [{summary or 'none'}]"
291
+ )
292
+ return 0
293
+
294
+
295
+ if __name__ == "__main__":
296
+ raise SystemExit(main())
@@ -0,0 +1,205 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Synthesise the eight drift-scan outputs into a single findings doc.
4
+
5
+ Why this tool exists. The eight drift scans each emit a per-scan
6
+ JSON document; the audit-gate consolidation needs one human-readable
7
+ view ranking every finding by severity, grouping by file, and
8
+ pointing at the right refit pass. This tool produces
9
+ ``drift-findings.md`` — the canonical synthesis surface.
10
+
11
+ Severity ranking:
12
+
13
+ - HIGH: secret leaks, conflicting directives, broken internal links,
14
+ plans-discipline violations, missing CLAUDE.md mandatory blocks.
15
+ - MEDIUM: stale tokens, frontmatter violations, AI-surfaces drift,
16
+ most non-banner emails, model identifiers.
17
+ - LOW: optional-surface presence informational hits, smart-quote /
18
+ whitespace issues (none currently scanned).
19
+
20
+ What this tool does NOT do. It does not assign verdicts (the
21
+ classification-matrix is the verdict surface) and it does not
22
+ re-run the scans (each scanner runs independently first).
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import argparse
28
+ import json
29
+ from collections import defaultdict
30
+ from collections.abc import Iterable
31
+ from dataclasses import dataclass
32
+ from pathlib import Path
33
+ from typing import Any, Final
34
+
35
+ _SCAN_FILES: Final[list[tuple[str, str]]] = [
36
+ ("scan_drift_features", ".audit/drift-feature-refs.json"),
37
+ ("scan_stale_tokens", ".audit/drift-stale-tokens.json"),
38
+ ("check_links", ".audit/drift-broken-links.json"),
39
+ ("scan_frontmatter", ".audit/drift-frontmatter.json"),
40
+ ("conflicting-directives", ".audit/drift-conflicting-directives.json"),
41
+ ("scan_secrets_pii", ".audit/drift-secrets-pii.json"),
42
+ ("scan_plans_discipline", ".audit/drift-plans-discipline.json"),
43
+ ("scan_ai_surfaces_coarse", ".audit/drift-ai-surfaces-coarse.json"),
44
+ ]
45
+
46
+ _SEVERITY_ORDER: Final[list[str]] = ["HIGH", "MEDIUM", "LOW"]
47
+
48
+
49
+ @dataclass(frozen=True)
50
+ class Finding:
51
+ scanner: str
52
+ file: str
53
+ line: int
54
+ signal: str
55
+ severity: str
56
+ remediation: str
57
+
58
+
59
+ def _load_scan(scanner: str, path: Path) -> tuple[list[Finding], dict[str, Any]]:
60
+ """Return ``(findings, envelope)`` for one scan's output."""
61
+ if not path.exists():
62
+ return [], {"missing": True}
63
+ payload = json.loads(path.read_text(encoding="utf-8"))
64
+ findings = [
65
+ Finding(
66
+ scanner=scanner,
67
+ file=h.get("file", ""),
68
+ line=int(h.get("line", 0) or 0),
69
+ signal=h.get("signal", ""),
70
+ severity=h.get("severity", "LOW"),
71
+ remediation=h.get("remediation", ""),
72
+ )
73
+ for h in payload.get("hits", [])
74
+ ]
75
+ envelope = {
76
+ "scanner": scanner,
77
+ "hit-count": payload.get("hit-count", len(findings)),
78
+ "missing": False,
79
+ }
80
+ return findings, envelope
81
+
82
+
83
+ def _gather(audit_root: Path) -> tuple[list[Finding], list[dict[str, Any]]]:
84
+ all_findings: list[Finding] = []
85
+ envelopes: list[dict[str, Any]] = []
86
+ for scanner, rel_path in _SCAN_FILES:
87
+ findings, envelope = _load_scan(scanner, audit_root / Path(rel_path).name)
88
+ all_findings.extend(findings)
89
+ envelopes.append(envelope)
90
+ return all_findings, envelopes
91
+
92
+
93
+ def _group_by_severity(
94
+ findings: Iterable[Finding],
95
+ ) -> dict[str, list[Finding]]:
96
+ by_sev: dict[str, list[Finding]] = defaultdict(list)
97
+ for f in findings:
98
+ by_sev[f.severity].append(f)
99
+ return by_sev
100
+
101
+
102
+ def _group_by_scanner(
103
+ findings: Iterable[Finding],
104
+ ) -> dict[str, list[Finding]]:
105
+ by_scanner: dict[str, list[Finding]] = defaultdict(list)
106
+ for f in findings:
107
+ by_scanner[f.scanner].append(f)
108
+ return by_scanner
109
+
110
+
111
+ def _emit_markdown(
112
+ findings: list[Finding],
113
+ envelopes: list[dict[str, Any]],
114
+ out_path: Path,
115
+ ) -> None:
116
+ by_sev = _group_by_severity(findings)
117
+ by_scanner = _group_by_scanner(findings)
118
+ lines: list[str] = []
119
+ lines.append("# Drift Findings")
120
+ lines.append("")
121
+ lines.append(
122
+ "Synthesised from the eight drift scans. Severity ranking per"
123
+ " the synthesis-pass criteria; grouping is by severity first,"
124
+ " then by scanner, then by file."
125
+ )
126
+ lines.append("")
127
+ lines.append("## Per-scan summary")
128
+ lines.append("")
129
+ lines.append("| Scanner | Hit count | Status |")
130
+ lines.append("|---------|----------:|--------|")
131
+ for env in envelopes:
132
+ if env.get("missing"):
133
+ lines.append(f"| `{env['scanner']}` | — | output absent |")
134
+ else:
135
+ lines.append(f"| `{env['scanner']}` | {env['hit-count']} | scan ran |")
136
+ lines.append("")
137
+ lines.append("## Severity totals")
138
+ lines.append("")
139
+ lines.append("| Severity | Count |")
140
+ lines.append("|----------|------:|")
141
+ for sev in _SEVERITY_ORDER:
142
+ lines.append(f"| {sev} | {len(by_sev.get(sev, []))} |")
143
+ lines.append("")
144
+ for sev in _SEVERITY_ORDER:
145
+ sev_findings = by_sev.get(sev, [])
146
+ if not sev_findings:
147
+ continue
148
+ lines.append(f"## {sev} severity ({len(sev_findings)} findings)")
149
+ lines.append("")
150
+ per_scanner = _group_by_scanner(sev_findings)
151
+ for scanner in sorted(per_scanner.keys()):
152
+ scanner_findings = per_scanner[scanner]
153
+ lines.append(f"### `{scanner}` — {len(scanner_findings)} {sev} hit(s)")
154
+ lines.append("")
155
+ lines.append("| File | Line | Signal | Remediation |")
156
+ lines.append("|------|-----:|--------|-------------|")
157
+ for f in sorted(scanner_findings, key=lambda x: (x.file, x.line)):
158
+ signal = f.signal.replace("|", r"\|")
159
+ remediation = f.remediation.replace("|", r"\|")
160
+ # Truncate long signal text for table readability.
161
+ if len(signal) > 100:
162
+ signal = signal[:97] + "..."
163
+ if len(remediation) > 140:
164
+ remediation = remediation[:137] + "..."
165
+ lines.append(f"| `{f.file}` | {f.line} | {signal} | {remediation} |")
166
+ lines.append("")
167
+ lines.append("## Per-scanner total")
168
+ lines.append("")
169
+ lines.append("| Scanner | Total hits |")
170
+ lines.append("|---------|-----------:|")
171
+ for scanner in sorted(by_scanner.keys()):
172
+ lines.append(f"| `{scanner}` | {len(by_scanner[scanner])} |")
173
+ lines.append("")
174
+ out_path.parent.mkdir(parents=True, exist_ok=True)
175
+ out_path.write_text("\n".join(lines) + "\n", encoding="utf-8")
176
+
177
+
178
+ def main(argv: list[str] | None = None) -> int:
179
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
180
+ parser.add_argument(
181
+ "--audit-dir",
182
+ type=Path,
183
+ default=Path(".audit"),
184
+ )
185
+ parser.add_argument(
186
+ "--output",
187
+ type=Path,
188
+ default=Path(".audit/drift-findings.md"),
189
+ )
190
+ args = parser.parse_args(argv)
191
+
192
+ findings, envelopes = _gather(args.audit_dir)
193
+ _emit_markdown(findings, envelopes, args.output)
194
+
195
+ by_sev = _group_by_severity(findings)
196
+ summary = ", ".join(f"{sev}={len(by_sev.get(sev, []))}" for sev in _SEVERITY_ORDER)
197
+ print(
198
+ f"synthesize_drift: {len(findings)} total findings "
199
+ f"[{summary}] across {len(envelopes)} scans -> {args.output}"
200
+ )
201
+ return 0
202
+
203
+
204
+ if __name__ == "__main__":
205
+ raise SystemExit(main())
@@ -0,0 +1,33 @@
1
+ <!-- SPDX-License-Identifier: MIT -->
2
+
3
+ # benchmarks
4
+
5
+ > **Role.** Per-class performance benchmark drivers. Each script runs an artifact class's representative invocations, measures runtime, compares against the class budget declared in `rules/performance-discipline.md` §1, and exits 0 on PASS / non-zero on FAIL with a measured-vs-budget delta.
6
+
7
+ ## Files
8
+
9
+ | File | Purpose |
10
+ |------|---------|
11
+ | `bench_hooks.py` | Hook-handler runtime benchmark against the per-event budgets (`--event=<name>`). |
12
+ | `bench_tests.py` | Test-suite runtime benchmark against the per-suite budgets (full suite and per-module). |
13
+ | `bench_agents.py` | Agent-spawn runtime benchmark against the per-spawn budget. |
14
+ | `bench_validate_ecosystem.py` | Verify-ecosystem-sweep runtime benchmark against the composite and per-check budgets. |
15
+ | `__init__.py` | Package marker. |
16
+
17
+ ## Conventions
18
+
19
+ - Budgets are operator-editorial at apply time; the recommended baselines align with the hook-timeout values in the harness configuration and `rules/performance-discipline.md` §1.
20
+ - Budget exceedances surface as high-priority Performance-axis findings.
21
+
22
+ ## Operating in this folder
23
+
24
+ - **Budget constant is the single source.** Each driver declares its class's budget as a module-level `Final` constant; it stays aligned with the budget table in `../rules/performance-discipline.md` §1 and the harness hook-timeout values — a budget change is mirrored in both places in the same change-set.
25
+ - **Exit code is the verdict.** 0 = PASS, non-zero = FAIL with a measured-vs-budget delta line. A scaffold driver with no wired fixture reports the budget and exits 0 so the verifier surface stays usable.
26
+ - **Path resolution is anchored relative to `__file__`** (the drivers sit four parents below the repository root); do not hard-code an absolute path.
27
+ - **Adding a driver:** declare the class's budget constant, implement the measurement against the representative invocation, and return the exit-code verdict with a delta line on FAIL. **Revising a budget:** cite a concrete driver (measured workload increase, infrastructure change, dependency upgrade, or rule citation) and update the rule table in the same change-set.
28
+ - Validate a change with `python -m ruff check`, `python -m mypy` for the in-scope modules, and `python -m pytest` (benchmark-driver tests).
29
+
30
+ ## Related
31
+
32
+ - [`rules/performance-discipline.md`](../rules/performance-discipline.md) — the per-class budget table the drivers verify.
33
+ - [`hooks/`](../hooks/) — the hook handlers `bench_hooks.py` measures.
@@ -0,0 +1,3 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Per-class performance-budget verifiers for the ecosystem."""
@@ -0,0 +1,63 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Agent-spawn runtime benchmark per the per-spawn budget in
4
+ `src/apothem/rules/performance-discipline.md` §1.
5
+
6
+ Spawn budget: 60 seconds for any of the four agent patterns
7
+ (research / audit / quality / generation).
8
+
9
+ Agent spawns are exercised through the host harness rather than via a
10
+ direct subprocess call; the script stands as a budget anchor with a
11
+ representative-invocation hook that operators wire to their harness.
12
+ When no harness fixture is provided, the script reports the budget and
13
+ exits with the scaffold marker (return code 0) so the verifier surface
14
+ remains usable while detailed fixtures land.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import argparse
20
+ from typing import Final
21
+
22
+ _BUDGET: Final[float] = 60.0
23
+ _PATTERNS: Final[tuple[str, ...]] = ("research", "audit", "quality", "generation")
24
+
25
+
26
+ def _representative_spawn() -> float | None:
27
+ """Return wall-clock seconds for a representative agent spawn.
28
+
29
+ Returns ``None`` when no harness fixture is wired; the caller then
30
+ reports the budget without a measurement.
31
+ """
32
+ # Harness fixtures are operator-editorial; without one wired, no
33
+ # measurement is attempted. Wire a representative spawn through the
34
+ # host harness here when one becomes available.
35
+ return None
36
+
37
+
38
+ def main(argv: list[str] | None = None) -> int:
39
+ parser = argparse.ArgumentParser(prog="bench_agents")
40
+ parser.add_argument(
41
+ "--pattern",
42
+ required=True,
43
+ choices=_PATTERNS,
44
+ help="Agent pattern to benchmark.",
45
+ )
46
+ args = parser.parse_args(argv)
47
+
48
+ elapsed = _representative_spawn()
49
+ if elapsed is None:
50
+ print(
51
+ f"SCAFFOLD: pattern={args.pattern} budget={_BUDGET}s "
52
+ "(no harness fixture wired; measurement skipped)"
53
+ )
54
+ return 0
55
+ if elapsed <= _BUDGET:
56
+ print(f"PASS: agent {args.pattern} = {elapsed:.3f}s (budget {_BUDGET}s)")
57
+ return 0
58
+ print(f"FAIL: agent {args.pattern} = {elapsed:.3f}s exceeds budget {_BUDGET}s")
59
+ return 1
60
+
61
+
62
+ if __name__ == "__main__":
63
+ raise SystemExit(main())