@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,319 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """Flag HEAD commit messages that drift from the Conventional-Commits grammar.
4
+
5
+ Why this enforcement exists. The apothem source repo
6
+ ratifies enterprise-grade Conventional-Commits discipline at the
7
+ project ``CLAUDE.md`` Coding Conventions block: every commit subject
8
+ follows ``<type>(<scope>): <subject>`` where type is drawn from the
9
+ closed set {feat, fix, chore, docs, refactor, test, perf, ci, build,
10
+ style, revert, release}, scope is optional kebab/comma-form, subject is <= 72
11
+ characters, written in imperative mood, and carries no trailing period.
12
+ Drift is silent in git history; the standalone validator reads the
13
+ HEAD commit message via ``git log -1 --pretty=%B`` and reports the
14
+ specific drift classes that fail.
15
+
16
+ Scope. Corpus-level standalone validator. Reads HEAD only. Merge commit
17
+ subjects (``Merge branch ...`` / ``Merge pull request ...``) pass
18
+ through — the merger does not author the merged content's subject form.
19
+ Shallow-clone or no-git contexts (no ``.git/``, empty repo) exit 0 with
20
+ an informational status so the validator never blocks a fresh clone or
21
+ a non-git working tree.
22
+
23
+ Exit semantics. Exits 0 when HEAD is conformant (or informationally
24
+ exempt). Exits 2 on any drift class. The exit-2 convention matches the
25
+ conformity-gate orchestrator's ``EXIT_FAIL`` constant.
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ import json
31
+ import re
32
+ import subprocess
33
+ import sys
34
+ from dataclasses import asdict, dataclass, field
35
+ from pathlib import Path
36
+ from typing import Final
37
+
38
+ GREP_NAME: Final[str] = "conventional-commit-grep"
39
+ RULE_ANCHOR: Final[str] = "CLAUDE.md Coding Conventions — Conventional Commits"
40
+
41
+ EXIT_PASS: Final[int] = 0
42
+ EXIT_FAIL: Final[int] = 2
43
+
44
+ # Bound the gate-path git invocation so a hung `git log` cannot block a
45
+ # commit indefinitely; a timeout is treated as a transient git error.
46
+ GIT_TIMEOUT_SECONDS: Final[int] = 5
47
+
48
+ ALLOWED_TYPES: Final[frozenset[str]] = frozenset(
49
+ {
50
+ "feat",
51
+ "fix",
52
+ "chore",
53
+ "docs",
54
+ "refactor",
55
+ "test",
56
+ "perf",
57
+ "ci",
58
+ "build",
59
+ "style",
60
+ "revert",
61
+ "release",
62
+ }
63
+ )
64
+
65
+ MAX_SUBJECT_LEN: Final[int] = 72
66
+
67
+ # Full Conventional-Commits subject form. The scope is optional and
68
+ # constrained to kebab-case / comma-separated lowercase ASCII tokens.
69
+ CONVENTIONAL_RE: Final[re.Pattern[str]] = re.compile(
70
+ r"^(?P<type>[a-z]+)(?:\((?P<scope>[^)]+)\))?(?P<bang>!?): (?P<subject>.+)$"
71
+ )
72
+
73
+ # Scope shape: lowercase letters, digits, hyphens, commas, forward
74
+ # slashes (e.g. ``harness/claude_code`` style). Uppercase or spaces
75
+ # trigger the scope-malformed drift class.
76
+ SCOPE_RE: Final[re.Pattern[str]] = re.compile(r"^[a-z0-9,\-/_]+$")
77
+
78
+ # Imperative-mood heuristic: forbid first verbs ending in -ed / -ing,
79
+ # and 3rd-person singular -s on common verbs. Heuristic only; intended
80
+ # to catch the most frequent drift forms (``added X``, ``adding X``,
81
+ # ``adds X``) without policing every English verb.
82
+ NON_IMPERATIVE_TAIL_RE: Final[re.Pattern[str]] = re.compile(
83
+ r"^(?P<verb>[a-z]+?)(?P<tail>ed|ing)$", re.IGNORECASE
84
+ )
85
+
86
+ # Common 3rd-person-singular verbs that surface as commit-message drift.
87
+ # Not exhaustive — intentionally narrow to avoid false positives on
88
+ # legitimate plural nouns acting as the first token (rare in imperative
89
+ # subjects but possible in chore/docs surfaces).
90
+ THIRD_PERSON_SINGULAR_VERBS: Final[frozenset[str]] = frozenset(
91
+ {
92
+ "adds",
93
+ "removes",
94
+ "updates",
95
+ "fixes",
96
+ "refactors",
97
+ "renames",
98
+ "moves",
99
+ "creates",
100
+ "deletes",
101
+ "introduces",
102
+ "implements",
103
+ "applies",
104
+ "changes",
105
+ "handles",
106
+ "wires",
107
+ "ensures",
108
+ "supports",
109
+ "enables",
110
+ "disables",
111
+ }
112
+ )
113
+
114
+ MERGE_PREFIXES: Final[tuple[str, ...]] = (
115
+ "Merge branch ",
116
+ "Merge pull request ",
117
+ "Merge remote-tracking branch ",
118
+ "Merge tag ",
119
+ # GitHub Actions checks out a synthetic `pull/N/merge` ref whose HEAD
120
+ # subject is `Merge <sha> into <sha>`; it is machine-authored, not a
121
+ # conventional commit. The generic "Merge " prefix covers this form (no
122
+ # conventional subject starts with a capitalized "Merge ").
123
+ "Merge ",
124
+ )
125
+
126
+
127
+ @dataclass(frozen=True)
128
+ class Drift:
129
+ """One drift class detected on the HEAD commit subject."""
130
+
131
+ klass: str
132
+ detail: str
133
+ subject: str
134
+ rule: str = RULE_ANCHOR
135
+
136
+
137
+ @dataclass(frozen=True)
138
+ class GrepResult:
139
+ grep: str
140
+ passed: bool
141
+ status: str
142
+ subject: str | None = None
143
+ drifts: list[Drift] = field(default_factory=list)
144
+
145
+ def to_json(self) -> str:
146
+ payload = {
147
+ "grep": self.grep,
148
+ "passed": self.passed,
149
+ "status": self.status,
150
+ "subject": self.subject,
151
+ "drifts": [asdict(d) for d in self.drifts],
152
+ }
153
+ return json.dumps(payload, indent=2)
154
+
155
+
156
+ def _read_head_subject(root: Path) -> tuple[str | None, str]:
157
+ """Return ``(subject, status)`` for the HEAD commit.
158
+
159
+ ``status`` is one of ``ok`` (subject populated), ``not-a-git-repo``,
160
+ ``no-commits-yet``, ``git-unavailable``. The subject is None for
161
+ every non-``ok`` status so the caller can short-circuit.
162
+ """
163
+ if not (root / ".git").exists():
164
+ return None, "not-a-git-repo"
165
+ try:
166
+ completed = subprocess.run(
167
+ ["git", "log", "-1", "--pretty=%B"], # noqa: S607 — literal git argv, trusted PATH lookup, no shell
168
+ cwd=str(root),
169
+ capture_output=True,
170
+ text=True,
171
+ check=False,
172
+ encoding="utf-8",
173
+ timeout=GIT_TIMEOUT_SECONDS,
174
+ )
175
+ except (OSError, subprocess.TimeoutExpired):
176
+ return None, "git-unavailable"
177
+ if completed.returncode != 0:
178
+ # Empty repo or other transient git error — never block.
179
+ return None, "no-commits-yet"
180
+ body = completed.stdout or ""
181
+ first_line = body.splitlines()[0] if body.strip() else ""
182
+ if not first_line:
183
+ return None, "no-commits-yet"
184
+ return first_line, "ok"
185
+
186
+
187
+ def _is_merge_subject(subject: str) -> bool:
188
+ return any(subject.startswith(prefix) for prefix in MERGE_PREFIXES)
189
+
190
+
191
+ def _classify_drift(subject: str) -> list[Drift]:
192
+ """Return every drift class the subject exhibits (empty list = clean)."""
193
+ drifts: list[Drift] = []
194
+ match = CONVENTIONAL_RE.match(subject)
195
+ if match is None:
196
+ drifts.append(
197
+ Drift(
198
+ klass="missing-type",
199
+ detail="subject does not match '<type>(<scope>)?: <subject>'",
200
+ subject=subject,
201
+ )
202
+ )
203
+ # Without a parsed shape the remaining drift classes are not
204
+ # individually decidable; return the structural failure alone.
205
+ return drifts
206
+
207
+ type_token = match.group("type")
208
+ scope_token = match.group("scope")
209
+ body_subject = match.group("subject")
210
+
211
+ if type_token not in ALLOWED_TYPES:
212
+ drifts.append(
213
+ Drift(
214
+ klass="invalid-type",
215
+ detail=f"type '{type_token}' not in {sorted(ALLOWED_TYPES)}",
216
+ subject=subject,
217
+ )
218
+ )
219
+
220
+ if scope_token is not None and not SCOPE_RE.match(scope_token):
221
+ drifts.append(
222
+ Drift(
223
+ klass="scope-malformed",
224
+ detail=(
225
+ f"scope '{scope_token}' contains characters outside [a-z0-9,-/_]"
226
+ ),
227
+ subject=subject,
228
+ )
229
+ )
230
+
231
+ if len(subject) > MAX_SUBJECT_LEN:
232
+ drifts.append(
233
+ Drift(
234
+ klass="subject-too-long",
235
+ detail=f"subject length {len(subject)} > {MAX_SUBJECT_LEN}",
236
+ subject=subject,
237
+ )
238
+ )
239
+
240
+ if body_subject.endswith("."):
241
+ drifts.append(
242
+ Drift(
243
+ klass="subject-ends-with-period",
244
+ detail="subject body ends with '.' — strip the trailing period",
245
+ subject=subject,
246
+ )
247
+ )
248
+
249
+ first_word = body_subject.split(" ", 1)[0] if body_subject else ""
250
+ if first_word:
251
+ tail = NON_IMPERATIVE_TAIL_RE.match(first_word)
252
+ lower = first_word.lower()
253
+ if tail is not None:
254
+ drifts.append(
255
+ Drift(
256
+ klass="non-imperative-verb",
257
+ detail=(
258
+ f"first word '{first_word}' ends with "
259
+ f"'-{tail.group('tail')}' — use imperative mood"
260
+ ),
261
+ subject=subject,
262
+ )
263
+ )
264
+ elif lower in THIRD_PERSON_SINGULAR_VERBS:
265
+ drifts.append(
266
+ Drift(
267
+ klass="non-imperative-verb",
268
+ detail=(
269
+ f"first word '{first_word}' is 3rd-person singular — "
270
+ "use imperative mood"
271
+ ),
272
+ subject=subject,
273
+ )
274
+ )
275
+
276
+ return drifts
277
+
278
+
279
+ def check_repo(root: Path) -> GrepResult:
280
+ """Inspect ``root``'s HEAD commit; return a structured result.
281
+
282
+ Pre-conditions: ``root`` is the working-tree directory.
283
+ Post-conditions: ``result.passed`` is True iff HEAD is conformant
284
+ or the repo state is informationally exempt (no .git, no commits).
285
+ """
286
+ subject, status = _read_head_subject(root)
287
+ if status != "ok" or subject is None:
288
+ return GrepResult(
289
+ grep=GREP_NAME,
290
+ passed=True,
291
+ status=status,
292
+ subject=None,
293
+ )
294
+ if _is_merge_subject(subject):
295
+ return GrepResult(
296
+ grep=GREP_NAME,
297
+ passed=True,
298
+ status="merge-commit",
299
+ subject=subject,
300
+ )
301
+ drifts = _classify_drift(subject)
302
+ return GrepResult(
303
+ grep=GREP_NAME,
304
+ passed=not drifts,
305
+ status="ok",
306
+ subject=subject,
307
+ drifts=drifts,
308
+ )
309
+
310
+
311
+ def _main(argv: list[str]) -> int:
312
+ root = Path(argv[1]) if len(argv) >= 2 else Path.cwd()
313
+ result = check_repo(root)
314
+ print(result.to_json())
315
+ return EXIT_PASS if result.passed else EXIT_FAIL
316
+
317
+
318
+ if __name__ == "__main__":
319
+ sys.exit(_main(sys.argv))
@@ -0,0 +1,324 @@
1
+ # SPDX-License-Identifier: MIT
2
+
3
+ """copilot-instructions-presence-grep: GitHub Copilot surface presence check.
4
+
5
+ Asserts that ``.github/copilot-instructions.md`` exists at the GitHub-canonical
6
+ path, begins with a canonical Markdown banner (the single-line SPDX header or
7
+ the HTML-comment authorship block), and carries the nine canonical level-2
8
+ sections in the prescribed order with exact heading text. The check is invoked
9
+ at orchestrator dispatch time (the orchestrator passes ``content`` and
10
+ ``path``); when ``path`` is absent the check reads
11
+ ``.github/copilot-instructions.md`` from the ecosystem root directly. The
12
+ validator is non-mutating; it only reports. Outside a repo checkout (e.g. the
13
+ installed conformity tree), hook-mode dispatches degrade to a pass-through —
14
+ there is no working-tree Copilot surface to assert against.
15
+
16
+ Verdict matrix:
17
+ pass — file exists, banner is a canonical Markdown variant, all
18
+ nine canonical sections present in order with exact headings.
19
+ fail — any of: file absent, banner absent or not a Markdown variant,
20
+ any canonical section absent, sections out of order, or a
21
+ section's heading text differs from the canonical form.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import re
27
+ import sys
28
+ from dataclasses import dataclass
29
+ from pathlib import Path
30
+ from typing import Final
31
+
32
+ from apothem.conformity._grep_base import GrepResult, run_grep
33
+
34
+ GREP_NAME: Final[str] = "copilot-instructions-presence-grep"
35
+ EXIT_PASS: Final[int] = 0
36
+ EXIT_FAIL: Final[int] = 2
37
+ STDIN_FLAG: Final[str] = "--stdin"
38
+
39
+ # Working-tree root anchor for the repo-root Copilot surface. In the repo
40
+ # checkout, parents[3] of ``src/apothem/conformity/<file>.py`` is the
41
+ # working-tree root where ``.github/copilot-instructions.md`` lives. In
42
+ # the installed tree (``<install-root>/apothem/conformity/``) the anchor
43
+ # is a coarse filesystem ancestor with no Copilot surface beneath it:
44
+ # hook-mode dispatches degrade to a pass-through via the relative_to()
45
+ # guard in _is_target_path(), and the surface check itself only runs when
46
+ # directly invoked against the target.
47
+ ECOSYSTEM_ROOT: Final[Path] = Path(__file__).resolve().parents[3]
48
+ TARGET_RELATIVE: Final[Path] = Path(".github") / "copilot-instructions.md"
49
+
50
+ # The nine canonical level-2 sections, in prescribed order, with their exact
51
+ # heading text. The order matches the canonical Copilot-instructions spec
52
+ # and the file as shipped on disk.
53
+ CANONICAL_SECTIONS: Final[tuple[str, ...]] = (
54
+ "Project Context",
55
+ "Coding Conventions",
56
+ "File Headers",
57
+ "Plans Discipline",
58
+ "Structured Inquiry Behavior",
59
+ "Forbidden Patterns",
60
+ "Output Format",
61
+ "Review Checklist",
62
+ "Pointers",
63
+ )
64
+
65
+ # The canonical Markdown banner comes in two accepted forms: the single-line
66
+ # SPDX header (``<!-- SPDX-License-Identifier: MIT -->`` — the per-file
67
+ # authorship form ratified at the File Headers discipline) and the
68
+ # HTML-comment block whose body is the hash-form authorship banner (open
69
+ # delimiter on its own line, AUTHOR_MARK between, close delimiter within the
70
+ # scan budget).
71
+ AUTHOR_MARK: Final[str] = "Copyright (c) Ahmed G. Gad"
72
+ SPDX_MARK: Final[str] = "SPDX-License-Identifier:"
73
+ HTML_OPEN: Final[str] = "<!--"
74
+ HTML_CLOSE: Final[str] = "-->"
75
+ BANNER_SCAN_LINE_BUDGET: Final[int] = 20
76
+
77
+ H2_LINE_RE: Final[re.Pattern[str]] = re.compile(r"^##\s+(.+?)\s*$")
78
+
79
+ RULE_FILE_ABSENT: Final[str] = "COPILOT_FILE_ABSENT"
80
+ RULE_BANNER_ABSENT: Final[str] = "COPILOT_BANNER_ABSENT"
81
+ RULE_SECTION_ABSENT: Final[str] = "COPILOT_SECTION_ABSENT"
82
+ RULE_SECTION_OUT_OF_ORDER: Final[str] = "COPILOT_SECTION_OUT_OF_ORDER"
83
+
84
+
85
+ @dataclass(frozen=True)
86
+ class Finding:
87
+ """One diagnostic finding for the presence check."""
88
+
89
+ line: int
90
+ match: str
91
+ context: str
92
+ rule: str
93
+
94
+
95
+ def _anchor_relative(path: Path) -> Path | None:
96
+ """Return *path* relative to the repo root or its matched hook scope, else None.
97
+
98
+ The apothem repo root is tried first; when the path is outside it, the
99
+ configured conformity scopes (hook-capable harness roots, via
100
+ ``gate.scope_relative_path``) are tried. ``None`` means the path is under no
101
+ anchor — there is no scope to resolve the Copilot surface against.
102
+ """
103
+ abs_path = path.resolve()
104
+ try:
105
+ return abs_path.relative_to(ECOSYSTEM_ROOT)
106
+ except ValueError:
107
+ pass
108
+ from apothem.conformity.gate import scope_relative_path
109
+
110
+ scoped = scope_relative_path(abs_path)
111
+ return scoped[1] if scoped is not None else None
112
+
113
+
114
+ def _is_target_path(path: Path) -> bool:
115
+ """Return True when *path* is the GitHub-canonical Copilot surface.
116
+
117
+ Scope-aware: the surface is recognised whether the path is under the apothem
118
+ repo root or under a hook scope (e.g. ``~/.claude/.github/copilot-instructions.md``).
119
+ """
120
+ rel = _anchor_relative(path)
121
+ return rel is not None and rel == TARGET_RELATIVE
122
+
123
+
124
+ def _check_banner(content_lines: list[str]) -> Finding | None:
125
+ """Verify the file opens with a canonical Markdown banner variant.
126
+
127
+ Two forms pass: the single-line SPDX header
128
+ (``<!-- SPDX-License-Identifier: MIT -->``) and the HTML-comment
129
+ block carrying the AUTHOR_MARK between its delimiters.
130
+ """
131
+ if not content_lines:
132
+ return Finding(
133
+ line=1,
134
+ match="",
135
+ context="file is empty; expected canonical Markdown banner at line 1",
136
+ rule=RULE_BANNER_ABSENT,
137
+ )
138
+ first_line = content_lines[0].strip()
139
+ if (
140
+ first_line.startswith(HTML_OPEN)
141
+ and first_line.endswith(HTML_CLOSE)
142
+ and SPDX_MARK in first_line
143
+ ):
144
+ # Single-line SPDX header form — canonical per the File Headers
145
+ # discipline; no block scan needed.
146
+ return None
147
+ if content_lines[0].strip() != HTML_OPEN:
148
+ return Finding(
149
+ line=1,
150
+ match=content_lines[0],
151
+ context=(
152
+ f"first line is not the canonical Markdown variant opener {HTML_OPEN!r}"
153
+ ),
154
+ rule=RULE_BANNER_ABSENT,
155
+ )
156
+ scan_end = min(len(content_lines), BANNER_SCAN_LINE_BUDGET)
157
+ saw_author_mark = False
158
+ saw_close = False
159
+ for idx in range(1, scan_end):
160
+ line = content_lines[idx]
161
+ if AUTHOR_MARK in line:
162
+ saw_author_mark = True
163
+ if line.strip() == HTML_CLOSE:
164
+ saw_close = True
165
+ break
166
+ if not saw_author_mark:
167
+ return Finding(
168
+ line=1,
169
+ match=content_lines[0],
170
+ context=(
171
+ f"banner opener present but {AUTHOR_MARK!r} not found within"
172
+ f" the first {BANNER_SCAN_LINE_BUDGET} lines"
173
+ ),
174
+ rule=RULE_BANNER_ABSENT,
175
+ )
176
+ if not saw_close:
177
+ return Finding(
178
+ line=1,
179
+ match=content_lines[0],
180
+ context=(
181
+ f"banner opener present but {HTML_CLOSE!r} not found within"
182
+ f" the first {BANNER_SCAN_LINE_BUDGET} lines"
183
+ ),
184
+ rule=RULE_BANNER_ABSENT,
185
+ )
186
+ return None
187
+
188
+
189
+ def _extract_h2_sequence(content_lines: list[str]) -> list[tuple[int, str]]:
190
+ """Return the (1-based line number, heading text) of every level-2 heading."""
191
+ headings: list[tuple[int, str]] = []
192
+ for idx, line in enumerate(content_lines, start=1):
193
+ match = H2_LINE_RE.match(line)
194
+ if match:
195
+ headings.append((idx, match.group(1)))
196
+ return headings
197
+
198
+
199
+ def _check_sections(content_lines: list[str]) -> list[Finding]:
200
+ """Verify every canonical section is present in the prescribed order."""
201
+ headings = _extract_h2_sequence(content_lines)
202
+ findings: list[Finding] = []
203
+
204
+ # Pass 1 — every canonical section must be present.
205
+ seen_lines: dict[str, int] = {text: line for line, text in headings}
206
+ for section in CANONICAL_SECTIONS:
207
+ if section not in seen_lines:
208
+ findings.append(
209
+ Finding(
210
+ line=0,
211
+ match="",
212
+ context=f"canonical section {section!r} absent",
213
+ rule=RULE_SECTION_ABSENT,
214
+ )
215
+ )
216
+
217
+ # Pass 2 — the canonical sections must appear in the prescribed order.
218
+ # Filter the heading sequence to canonical members and check the order.
219
+ canonical_seen = [
220
+ (line, text) for line, text in headings if text in CANONICAL_SECTIONS
221
+ ]
222
+ expected_order = [t for _, t in canonical_seen]
223
+ canonical_present = [s for s in CANONICAL_SECTIONS if s in seen_lines]
224
+ if expected_order != canonical_present:
225
+ first_mismatch_line = canonical_seen[0][0] if canonical_seen else 0
226
+ findings.append(
227
+ Finding(
228
+ line=first_mismatch_line,
229
+ match=", ".join(expected_order),
230
+ context=(
231
+ f"canonical sections out of order; observed "
232
+ f"{expected_order!r} but expected the order "
233
+ f"{canonical_present!r}"
234
+ ),
235
+ rule=RULE_SECTION_OUT_OF_ORDER,
236
+ )
237
+ )
238
+
239
+ return findings
240
+
241
+
242
+ def check(content: str, path: Path | None = None) -> GrepResult:
243
+ """Validate Copilot-surface presence and section structure.
244
+
245
+ Hook-mode pass-through. When *path* is set and does not name the
246
+ GitHub-canonical Copilot surface, the validator returns ``passed=True``
247
+ without reading anything else. The full structural check runs only on
248
+ direct dispatch against the target surface or on CLI mode without a
249
+ path argument (where the validator reads the on-disk surface).
250
+
251
+ Args:
252
+ content: In-flight body of the target surface (orchestrator
253
+ dispatch). When the orchestrator dispatches with no content
254
+ but the path matches the target, the on-disk body is read.
255
+ path: Absolute path of the file under dispatch; ``None`` in
256
+ ``--stdin`` mode.
257
+
258
+ Returns:
259
+ ``GrepResult`` with ``passed=True`` when the surface is
260
+ well-formed (or out-of-scope for this dispatch), ``passed=False``
261
+ with one ``Finding`` per defect otherwise.
262
+ """
263
+ target_path = ECOSYSTEM_ROOT / TARGET_RELATIVE
264
+
265
+ if path is not None and not _is_target_path(path):
266
+ if _anchor_relative(path) is None:
267
+ # Out-of-anchor write: no repo root or hook scope resolves the
268
+ # Copilot surface — record a visible skip, not a silent pass.
269
+ return GrepResult(
270
+ grep=GREP_NAME,
271
+ path=str(path),
272
+ passed=True,
273
+ note="check skipped (scope not resolvable)",
274
+ )
275
+ # In-anchor but not the Copilot surface: legitimately not applicable.
276
+ return GrepResult(grep=GREP_NAME, path=str(path), passed=True)
277
+
278
+ if path is not None and _is_target_path(path):
279
+ if content:
280
+ body = content
281
+ elif target_path.is_file():
282
+ body = target_path.read_text(encoding="utf-8")
283
+ else:
284
+ body = ""
285
+ report_path = path
286
+ else:
287
+ if not target_path.is_file():
288
+ return GrepResult(
289
+ grep=GREP_NAME,
290
+ path=str(target_path),
291
+ passed=False,
292
+ findings=[
293
+ Finding(
294
+ line=0,
295
+ match="",
296
+ context=(
297
+ f"{TARGET_RELATIVE.as_posix()} absent at the"
298
+ f" GitHub-canonical path"
299
+ ),
300
+ rule=RULE_FILE_ABSENT,
301
+ )
302
+ ],
303
+ )
304
+ body = target_path.read_text(encoding="utf-8")
305
+ report_path = target_path
306
+
307
+ content_lines = body.split("\n")
308
+
309
+ findings: list[Finding] = []
310
+ banner_finding = _check_banner(content_lines)
311
+ if banner_finding is not None:
312
+ findings.append(banner_finding)
313
+ findings.extend(_check_sections(content_lines))
314
+
315
+ return GrepResult(
316
+ grep=GREP_NAME,
317
+ path=str(report_path),
318
+ passed=not findings,
319
+ findings=findings,
320
+ )
321
+
322
+
323
+ if __name__ == "__main__":
324
+ sys.exit(run_grep(check, sys.argv))