coding-os 0.3.2__py3-none-any.whl

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 (1304) hide show
  1. adapters/claude/README.md +6 -0
  2. adapters/claude/_install_helpers/extract_stacks.py +43 -0
  3. adapters/claude/_install_helpers/update_mcp_json.py +75 -0
  4. adapters/claude/adapter.yaml +164 -0
  5. adapters/claude/hooks/README.md +40 -0
  6. adapters/claude/hooks/agent_memory_sync.py +131 -0
  7. adapters/claude/hooks/ensure-agent-memory-link.sh +36 -0
  8. adapters/claude/hooks/sync-agent-memory.sh +21 -0
  9. adapters/claude/install.sh +86 -0
  10. adapters/claude/sdk_dispatcher.py +871 -0
  11. adapters/claude/settings.local.template.json +31 -0
  12. adapters/claude/settings.template.json +808 -0
  13. adapters/claude/update_mcp_json.py +85 -0
  14. adapters/codex/adapter.yaml +254 -0
  15. adapters/codex/chat_provider.py +230 -0
  16. adapters/codex/commands/formula-f1.md +129 -0
  17. adapters/codex/commands/formula-f10.md +100 -0
  18. adapters/codex/commands/formula-f11.md +123 -0
  19. adapters/codex/commands/formula-f2.md +139 -0
  20. adapters/codex/commands/formula-f3.md +127 -0
  21. adapters/codex/commands/formula-f4.md +101 -0
  22. adapters/codex/commands/formula-f5.md +135 -0
  23. adapters/codex/commands/formula-f6.md +147 -0
  24. adapters/codex/commands/formula-f7.md +111 -0
  25. adapters/codex/commands/formula-f8.md +133 -0
  26. adapters/codex/commands/formula-f9.md +112 -0
  27. adapters/codex/enable_codex_hooks.py +94 -0
  28. adapters/codex/ensure_codex_mcp.py +124 -0
  29. adapters/codex/hooks/codex-merge-hook-output.py +72 -0
  30. adapters/codex/hooks/codex-normalize-edit.py +96 -0
  31. adapters/codex/hooks/codex-postedit-dispatch.sh +75 -0
  32. adapters/codex/hooks/codex-posttool-dispatch.sh +70 -0
  33. adapters/codex/hooks/codex-preedit-dispatch.sh +83 -0
  34. adapters/codex/hooks/codex-pretool-dispatch.sh +82 -0
  35. adapters/codex/hooks/codex-sessionend-dispatch.sh +20 -0
  36. adapters/codex/hooks/codex-sessionstart-dispatch.sh +68 -0
  37. adapters/codex/hooks/codex-stop-dispatch.sh +73 -0
  38. adapters/codex/hooks/codex-userpromptsubmit-dispatch.sh +74 -0
  39. adapters/codex/hooks.template.json +208 -0
  40. adapters/codex/install.sh +83 -0
  41. adapters/codex/sdk_dispatcher.py +449 -0
  42. board_os/__init__.py +39 -0
  43. board_os/_agent_runtime.py +256 -0
  44. board_os/config.py +421 -0
  45. board_os/git_coherence.py +107 -0
  46. board_os/hub_adapter_manifest.py +140 -0
  47. board_os/mcp_tools.py +3228 -0
  48. board_os/migration.py +166 -0
  49. board_os/parser.py +317 -0
  50. board_os/presence.py +156 -0
  51. board_os/sync.py +320 -0
  52. board_os/transition_gates.py +224 -0
  53. board_os/transition_gates_cli.py +272 -0
  54. board_os/transition_gates_validator.py +551 -0
  55. board_os/verify_suites.py +126 -0
  56. board_os/verify_suites_cli.py +328 -0
  57. board_os/workflow.py +967 -0
  58. cli/__init__.py +0 -0
  59. cli/_data_types.py +248 -0
  60. cli/_init_helpers.py +587 -0
  61. cli/_resources.py +100 -0
  62. cli/adapter_registry.py +239 -0
  63. cli/add_stack.py +315 -0
  64. cli/aggregator.py +438 -0
  65. cli/board_commands.py +1218 -0
  66. cli/brain_commands.py +255 -0
  67. cli/cognition.py +345 -0
  68. cli/config_composer.py +349 -0
  69. cli/core_version.py +41 -0
  70. cli/cron_commands.py +278 -0
  71. cli/db_reset.py +298 -0
  72. cli/doc_commands.py +111 -0
  73. cli/doctor.py +2953 -0
  74. cli/doctor_board.py +365 -0
  75. cli/doctor_extras.py +1121 -0
  76. cli/doctor_graph.py +608 -0
  77. cli/doctor_tokens.py +254 -0
  78. cli/graph_commands.py +1265 -0
  79. cli/hook_renderer.py +393 -0
  80. cli/hub_commands.py +580 -0
  81. cli/list_adapters.py +79 -0
  82. cli/list_stacks.py +105 -0
  83. cli/logs_commands.py +89 -0
  84. cli/main.py +3070 -0
  85. cli/materialize_file.py +65 -0
  86. cli/mcp_start.py +153 -0
  87. cli/module_commands.py +513 -0
  88. cli/pr_commands.py +2024 -0
  89. cli/preset_commands.py +126 -0
  90. cli/preset_registry.py +171 -0
  91. cli/project_overrides.py +119 -0
  92. cli/registry.py +365 -0
  93. cli/remove_stack.py +492 -0
  94. cli/renderer.py +620 -0
  95. cli/setup.py +464 -0
  96. cli/skill_commands.py +689 -0
  97. cli/skill_registry.py +235 -0
  98. cli/skills_list.py +332 -0
  99. cli/stack_lint.py +351 -0
  100. cli/stack_registry.py +688 -0
  101. cli/subsystems.py +335 -0
  102. cli/sync_all.py +310 -0
  103. cli/tail_command.py +410 -0
  104. cli/update.py +608 -0
  105. cli/verify_since_edit.py +439 -0
  106. coding_os-0.3.2.dist-info/METADATA +508 -0
  107. coding_os-0.3.2.dist-info/RECORD +1304 -0
  108. coding_os-0.3.2.dist-info/WHEEL +5 -0
  109. coding_os-0.3.2.dist-info/entry_points.txt +5 -0
  110. coding_os-0.3.2.dist-info/licenses/LICENSE +201 -0
  111. coding_os-0.3.2.dist-info/top_level.txt +10 -0
  112. core/__init__.py +0 -0
  113. core/board_os/__init__.py +39 -0
  114. core/board_os/_agent_runtime.py +256 -0
  115. core/board_os/config.py +421 -0
  116. core/board_os/git_coherence.py +107 -0
  117. core/board_os/hub_adapter_manifest.py +140 -0
  118. core/board_os/mcp_tools.py +3228 -0
  119. core/board_os/migration.py +166 -0
  120. core/board_os/parser.py +317 -0
  121. core/board_os/presence.py +156 -0
  122. core/board_os/sync.py +320 -0
  123. core/board_os/transition-gates.yaml +176 -0
  124. core/board_os/transition_gates.py +224 -0
  125. core/board_os/transition_gates_cli.py +272 -0
  126. core/board_os/transition_gates_validator.py +551 -0
  127. core/board_os/verify-suites.yaml +113 -0
  128. core/board_os/verify_suites.py +126 -0
  129. core/board_os/verify_suites_cli.py +328 -0
  130. core/board_os/workflow.py +967 -0
  131. core/commands/board.md +27 -0
  132. core/commands/classify.md +23 -0
  133. core/commands/compose.md +23 -0
  134. core/commands/daily.md +31 -0
  135. core/commands/diagnose.md +7 -0
  136. core/commands/memory-search.md +23 -0
  137. core/commands/new-project.md +33 -0
  138. core/commands/retro.md +38 -0
  139. core/commands/review.md +14 -0
  140. core/commands/task.md +17 -0
  141. core/commands/verify.md +34 -0
  142. core/docs/thinking_os-final-edition.md +1449 -0
  143. core/doctor-config.yaml +74 -0
  144. core/graph_os/__init__.py +29 -0
  145. core/graph_os/backend.py +233 -0
  146. core/graph_os/backends/__init__.py +13 -0
  147. core/graph_os/backends/sqlite_backend.py +1053 -0
  148. core/graph_os/bench/__init__.py +17 -0
  149. core/graph_os/bench/fixtures.py +56 -0
  150. core/graph_os/bench/harness.py +95 -0
  151. core/graph_os/bench/persian_precision.py +142 -0
  152. core/graph_os/bench/scale_500k.py +120 -0
  153. core/graph_os/bench/token_cost.py +170 -0
  154. core/graph_os/bench/viewer_fps.py +110 -0
  155. core/graph_os/communities.py +410 -0
  156. core/graph_os/enterprise.py +218 -0
  157. core/graph_os/entry_points.py +226 -0
  158. core/graph_os/extractors/__init__.py +25 -0
  159. core/graph_os/extractors/code_generic.py +914 -0
  160. core/graph_os/extractors/code_go.py +1422 -0
  161. core/graph_os/extractors/code_json.py +340 -0
  162. core/graph_os/extractors/code_php.py +979 -0
  163. core/graph_os/extractors/code_python.py +1454 -0
  164. core/graph_os/extractors/code_shell.py +538 -0
  165. core/graph_os/extractors/code_toml.py +302 -0
  166. core/graph_os/extractors/code_ts.py +1665 -0
  167. core/graph_os/extractors/code_yaml.py +394 -0
  168. core/graph_os/extractors/contracts.py +1592 -0
  169. core/graph_os/extractors/md_links.py +890 -0
  170. core/graph_os/extractors/task_deps.py +345 -0
  171. core/graph_os/groups/__init__.py +22 -0
  172. core/graph_os/groups/cross_repo.py +156 -0
  173. core/graph_os/groups/manifest.py +141 -0
  174. core/graph_os/ingest/__init__.py +19 -0
  175. core/graph_os/ingest/base.py +306 -0
  176. core/graph_os/ingest/github.py +112 -0
  177. core/graph_os/ingest/zip.py +95 -0
  178. core/graph_os/toolchain.py +393 -0
  179. core/graph_os/tools/__init__.py +9 -0
  180. core/graph_os/tools/graph.py +5573 -0
  181. core/graph_os/tools/reindex_dispatch.py +730 -0
  182. core/graph_os/tree_sitter_overlay.py +235 -0
  183. core/graph_os/types.py +252 -0
  184. core/graph_os/vec_index.py +277 -0
  185. core/graph_os/viewer/__init__.py +12 -0
  186. core/graph_os/viewer/exporter.py +93 -0
  187. core/graph_os/viewer/template.py +189 -0
  188. core/hooks/_helpers/_paths.py +40 -0
  189. core/hooks/_helpers/advance_role.py +72 -0
  190. core/hooks/_helpers/auto_compose.py +228 -0
  191. core/hooks/_helpers/auto_validate_lessons.py +55 -0
  192. core/hooks/_helpers/branch_guard_check.py +796 -0
  193. core/hooks/_helpers/check_commit_message.py +108 -0
  194. core/hooks/_helpers/check_dangerous_rm.py +80 -0
  195. core/hooks/_helpers/check_git_bypass.py +154 -0
  196. core/hooks/_helpers/check_git_destructive.py +77 -0
  197. core/hooks/_helpers/check_settings_write.py +97 -0
  198. core/hooks/_helpers/consume_override.py +51 -0
  199. core/hooks/_helpers/context_budget.py +77 -0
  200. core/hooks/_helpers/cos_say_json.py +103 -0
  201. core/hooks/_helpers/destructive_edit_check.py +163 -0
  202. core/hooks/_helpers/detect_status_transition.py +82 -0
  203. core/hooks/_helpers/digest_regen.py +56 -0
  204. core/hooks/_helpers/doc_sync_check.py +498 -0
  205. core/hooks/_helpers/drain_embedding_outbox.py +52 -0
  206. core/hooks/_helpers/extract_additional_context.py +51 -0
  207. core/hooks/_helpers/extract_commit_msg_arg.py +74 -0
  208. core/hooks/_helpers/git_command_parse.py +424 -0
  209. core/hooks/_helpers/git_settings_fields.py +47 -0
  210. core/hooks/_helpers/graph_context_match.py +37 -0
  211. core/hooks/_helpers/graph_marker_check.py +70 -0
  212. core/hooks/_helpers/jit_recall.py +56 -0
  213. core/hooks/_helpers/json_field.py +41 -0
  214. core/hooks/_helpers/narrative_signal.py +59 -0
  215. core/hooks/_helpers/observation_count.py +31 -0
  216. core/hooks/_helpers/pre_commit_batch.py +177 -0
  217. core/hooks/_helpers/pre_commit_fake_input.py +42 -0
  218. core/hooks/_helpers/presence_gc.py +102 -0
  219. core/hooks/_helpers/presence_write.py +167 -0
  220. core/hooks/_helpers/recover_indirect.py +35 -0
  221. core/hooks/_helpers/routing_evolution.py +104 -0
  222. core/hooks/_helpers/session_recap.py +72 -0
  223. core/hooks/_helpers/skill_primer.py +229 -0
  224. core/hooks/_helpers/task_sync.py +59 -0
  225. core/hooks/_helpers/tool_failure_capture.py +147 -0
  226. core/hooks/_helpers/trajectory_autosnap.py +278 -0
  227. core/hooks/_helpers/trajectory_startup.py +62 -0
  228. core/hooks/_helpers/turn_summary.py +82 -0
  229. core/hooks/_helpers/validate_task_frontmatter.py +98 -0
  230. core/hooks/_helpers/wip_limit_check.py +103 -0
  231. core/hooks/_helpers/wip_lines.py +53 -0
  232. core/hooks/_helpers/work_log_append.py +89 -0
  233. core/hooks/_helpers/wrap_dispatch_output.py +82 -0
  234. core/hooks/advance-role.sh +48 -0
  235. core/hooks/agent-presence.sh +179 -0
  236. core/hooks/auto-brain-decay.sh +184 -0
  237. core/hooks/auto-compose-roles.sh +83 -0
  238. core/hooks/auto-graph-reconcile-shell.sh +119 -0
  239. core/hooks/auto-regen-doc-index.sh +120 -0
  240. core/hooks/auto-reindex-docs.sh +130 -0
  241. core/hooks/auto-task-sync.sh +56 -0
  242. core/hooks/auto-trace-rotate.sh +88 -0
  243. core/hooks/block-bad-patterns.sh +212 -0
  244. core/hooks/block-dangerous-commands.sh +182 -0
  245. core/hooks/block-hardcoded-literals.sh +90 -0
  246. core/hooks/block-migration-conflict.sh +114 -0
  247. core/hooks/block-protected-files.sh +129 -0
  248. core/hooks/block-secrets.sh +185 -0
  249. core/hooks/block-shared-tree-edit.sh +75 -0
  250. core/hooks/block-uv-heredoc.sh +78 -0
  251. core/hooks/branch-guard.sh +122 -0
  252. core/hooks/capture-observation.sh +76 -0
  253. core/hooks/capture-tool-failure.sh +24 -0
  254. core/hooks/capture-work-log.sh +89 -0
  255. core/hooks/check-agents-md-refs.sh +75 -0
  256. core/hooks/check-agents-md-size.sh +49 -0
  257. core/hooks/check-capture-worked.sh +148 -0
  258. core/hooks/check-doc-size.sh +61 -0
  259. core/hooks/check-mcp-extras.sh +92 -0
  260. core/hooks/check-state.sh +87 -0
  261. core/hooks/classify-task-mode.sh +103 -0
  262. core/hooks/cos-env.sh +1301 -0
  263. core/hooks/drain-embedding-outbox.sh +24 -0
  264. core/hooks/enforce-anti-ambiguity.sh +74 -0
  265. core/hooks/enforce-commit-message.sh +73 -0
  266. core/hooks/enforce-doc-anchor.sh +224 -0
  267. core/hooks/enforce-doc-sync.sh +206 -0
  268. core/hooks/enforce-graph-context.sh +89 -0
  269. core/hooks/enforce-graph-first-read.sh +94 -0
  270. core/hooks/enforce-memory-check.sh +128 -0
  271. core/hooks/enforce-rename-plan.sh +78 -0
  272. core/hooks/enforce-scaffold-boundary.sh +68 -0
  273. core/hooks/enforce-skill.sh +125 -0
  274. core/hooks/enforce-task-body.sh +52 -0
  275. core/hooks/enforce-task-start.sh +81 -0
  276. core/hooks/enforce-task-transition.sh +75 -0
  277. core/hooks/enforce-template.sh +143 -0
  278. core/hooks/enforce-verify.sh +112 -0
  279. core/hooks/enforce-wip-limit.sh +43 -0
  280. core/hooks/enforce-zoom.sh +69 -0
  281. core/hooks/ensure-hub-up.sh +67 -0
  282. core/hooks/inject-mcp-caller-session.sh +70 -0
  283. core/hooks/jit-recall.sh +65 -0
  284. core/hooks/link-commit-to-task.sh +143 -0
  285. core/hooks/lint-task.sh +40 -0
  286. core/hooks/nudge-docs-first.sh +71 -0
  287. core/hooks/nudge-git-mode.sh +29 -0
  288. core/hooks/nudge-graph-os.sh +118 -0
  289. core/hooks/nudge-learn-narrative.sh +36 -0
  290. core/hooks/nudge-model-routing.sh +32 -0
  291. core/hooks/nudge-reentry.sh +101 -0
  292. core/hooks/nudge-reuse-first.sh +68 -0
  293. core/hooks/nudge-task-discovery.sh +81 -0
  294. core/hooks/nudge-thinking-os.sh +109 -0
  295. core/hooks/pr-reap.sh +23 -0
  296. core/hooks/reclaim-sweep.sh +58 -0
  297. core/hooks/record-verify-auto.sh +77 -0
  298. core/hooks/record-verify.sh +74 -0
  299. core/hooks/regen-reminder.sh +104 -0
  300. core/hooks/registry.yaml +1262 -0
  301. core/hooks/remind-daily.sh +27 -0
  302. core/hooks/remind-dogfood.sh +70 -0
  303. core/hooks/remind-learn-validate.sh +94 -0
  304. core/hooks/rules-primer.sh +50 -0
  305. core/hooks/search-enforce-inventory.sh +108 -0
  306. core/hooks/search-verify-remaining.sh +132 -0
  307. core/hooks/session-context.sh +729 -0
  308. core/hooks/session-end.sh +145 -0
  309. core/hooks/session-skill-primer.sh +43 -0
  310. core/hooks/snapshot-transcript.sh +56 -0
  311. core/hooks/sync-task-current.sh +85 -0
  312. core/hooks/test-first-reminder.sh +120 -0
  313. core/hooks/test-governor.sh +173 -0
  314. core/hooks/thinking_os-gate.sh +52 -0
  315. core/hooks/track-backtrack.sh +35 -0
  316. core/hooks/track-discovery.sh +121 -0
  317. core/hooks/track-skill.sh +53 -0
  318. core/hooks/validate-task-frontmatter.sh +49 -0
  319. core/hooks/verify-rename-callers.sh +119 -0
  320. core/hooks/warn-abandoned-task.sh +99 -0
  321. core/hooks/warn-destructive-edit.sh +64 -0
  322. core/hooks/warn-diff-size.sh +43 -0
  323. core/hooks/warn-graph-empty.sh +81 -0
  324. core/hooks/warn-mcp-down.sh +190 -0
  325. core/hooks/write-state.sh +55 -0
  326. core/logging_os/__init__.py +33 -0
  327. core/logging_os/api.py +127 -0
  328. core/logging_os/bridge.py +80 -0
  329. core/logging_os/config.py +172 -0
  330. core/logging_os/fingerprint.py +25 -0
  331. core/logging_os/redact.py +53 -0
  332. core/logging_os/render.py +83 -0
  333. core/logging_os/sinks.py +164 -0
  334. core/rules/anti-overengineering.md +44 -0
  335. core/rules/api-contract-discipline.md +41 -0
  336. core/rules/dimension-registry.md +155 -0
  337. core/rules/git-workflow.md +57 -0
  338. core/rules/memory.md +46 -0
  339. core/rules/model-routing.md +22 -0
  340. core/rules/skill-enforcement.md +75 -0
  341. core/rules/test-discipline.md +38 -0
  342. core/rules/thinking_os.md +48 -0
  343. core/rules/transparency-banner.md +37 -0
  344. core/runtime_paths.yaml +36 -0
  345. core/scaffold_manifest.json +14430 -0
  346. core/scheduled/__init__.py +0 -0
  347. core/scheduled/_activity.py +126 -0
  348. core/scheduled/_state.py +113 -0
  349. core/scheduled/config.py +86 -0
  350. core/scheduled/dep_reconcile.py +135 -0
  351. core/scheduled/error_sweep.py +137 -0
  352. core/scheduled/nightly.py +930 -0
  353. core/scheduled/responsive_extract.py +65 -0
  354. core/schemas/adapter.schema.json +269 -0
  355. core/schemas/preset.schema.json +50 -0
  356. core/schemas/skill.schema.json +81 -0
  357. core/schemas/stack.schema.json +404 -0
  358. core/scripts/_lib.sh +9 -0
  359. core/scripts/docs-lint.sh +228 -0
  360. core/scripts/docs-nav-fix.sh +133 -0
  361. core/scripts/docs-staleness-check.sh +154 -0
  362. core/scripts/install-adapter.sh +266 -0
  363. core/scripts/link-stack-skills.sh +52 -0
  364. core/scripts/log-latest.sh +106 -0
  365. core/scripts/log-search.sh +89 -0
  366. core/scripts/log-write.sh +134 -0
  367. core/scripts/ref-resolve.sh +71 -0
  368. core/skills/a11y/SKILL.md +305 -0
  369. core/skills/a11y/assets/a11y-checklist.md +137 -0
  370. core/skills/a11y/references/aria-and-focus.md +247 -0
  371. core/skills/a11y/references/rn-accessibility.md +343 -0
  372. core/skills/a11y/references/screen-reader-testing.md +190 -0
  373. core/skills/agent-memory/SKILL.md +191 -0
  374. core/skills/agent-memory/assets/memory-checklist.md +21 -0
  375. core/skills/agent-memory/references/memory-recipes.md +57 -0
  376. core/skills/api-design/SKILL.md +232 -0
  377. core/skills/api-design/assets/api-design-checklist.md +110 -0
  378. core/skills/api-design/references/error-envelope.md +381 -0
  379. core/skills/api-design/references/idempotency-pagination.md +312 -0
  380. core/skills/api-design/references/rest-contracts.md +426 -0
  381. core/skills/auth-patterns/SKILL.md +352 -0
  382. core/skills/auth-patterns/assets/auth-checklist.md +118 -0
  383. core/skills/auth-patterns/references/jwt-and-service-tokens.md +343 -0
  384. core/skills/auth-patterns/references/passkeys-2fa.md +289 -0
  385. core/skills/auth-patterns/references/sessions-vs-jwt.md +230 -0
  386. core/skills/auth-patterns/scripts/cookie-flag-check.py +146 -0
  387. core/skills/backend-fundamentals/SKILL.md +238 -0
  388. core/skills/backend-fundamentals/assets/backend-checklist.md +27 -0
  389. core/skills/backend-fundamentals/references/backend-patterns.md +56 -0
  390. core/skills/backend-fundamentals/scripts/check_layering.py +83 -0
  391. core/skills/clean-code/SKILL.md +642 -0
  392. core/skills/clean-code/scripts/audit-fail-closed.py +167 -0
  393. core/skills/codebase-explorer/SKILL.md +89 -0
  394. core/skills/codebase-explorer/assets/reading-checklist.md +24 -0
  395. core/skills/codebase-explorer/references/reading-strategies.md +52 -0
  396. core/skills/codebase-explorer/scripts/outline.py +99 -0
  397. core/skills/db-design/SKILL.md +327 -0
  398. core/skills/db-design/assets/migration-template.sql +49 -0
  399. core/skills/db-design/references/migration-discipline.md +290 -0
  400. core/skills/db-design/references/postgres-patterns.md +340 -0
  401. core/skills/db-design/scripts/migration-safety.sh +150 -0
  402. core/skills/deployment-cicd/SKILL.md +260 -0
  403. core/skills/deployment-cicd/assets/deploy-checklist.md +26 -0
  404. core/skills/deployment-cicd/references/pipeline-and-release.md +54 -0
  405. core/skills/deployment-cicd/scripts/lint_workflow.py +79 -0
  406. core/skills/docker/SKILL.md +114 -0
  407. core/skills/docker/assets/dockerfile-checklist.md +31 -0
  408. core/skills/docker/references/compose-patterns.md +66 -0
  409. core/skills/docker/references/dockerfile-optimization.md +64 -0
  410. core/skills/docker/scripts/lint_dockerfile.sh +48 -0
  411. core/skills/docker/versions.json +16 -0
  412. core/skills/end-to-end-testing/SKILL.md +101 -0
  413. core/skills/end-to-end-testing/assets/e2e-checklist.md +23 -0
  414. core/skills/end-to-end-testing/references/maestro.md +63 -0
  415. core/skills/end-to-end-testing/references/playwright.md +68 -0
  416. core/skills/end-to-end-testing/scripts/lint_e2e.py +88 -0
  417. core/skills/end-to-end-testing/versions.json +16 -0
  418. core/skills/frontend-design/SKILL.md +76 -0
  419. core/skills/frontend-design/assets/design-checklist.md +29 -0
  420. core/skills/frontend-design/references/design-principles.md +65 -0
  421. core/skills/frontend-design/scripts/check_contrast.py +89 -0
  422. core/skills/frontend-fundamentals/SKILL.md +213 -0
  423. core/skills/frontend-fundamentals/assets/frontend-checklist.md +25 -0
  424. core/skills/frontend-fundamentals/references/rendering-and-state.md +66 -0
  425. core/skills/frontend-fundamentals/scripts/check_frontend.py +86 -0
  426. core/skills/graph-explorer/SKILL.md +215 -0
  427. core/skills/graph-explorer/scripts/explain-impact.sh +64 -0
  428. core/skills/graphql/SKILL.md +187 -0
  429. core/skills/grpc-microservices/SKILL.md +174 -0
  430. core/skills/hexagonal-architecture/SKILL.md +199 -0
  431. core/skills/hexagonal-architecture/assets/folder-scaffold.md +233 -0
  432. core/skills/hexagonal-architecture/references/anti-patterns.md +129 -0
  433. core/skills/hexagonal-architecture/references/go-fiber-layout.md +429 -0
  434. core/skills/hexagonal-architecture/references/python-fastapi-layout.md +453 -0
  435. core/skills/hexagonal-architecture/references/react-native-layout.md +428 -0
  436. core/skills/i18n/SKILL.md +126 -0
  437. core/skills/incident-response/SKILL.md +225 -0
  438. core/skills/incident-response/assets/incident-checklist.md +29 -0
  439. core/skills/incident-response/references/severity-and-runbook.md +53 -0
  440. core/skills/incident-response/scripts/classify_severity.py +86 -0
  441. core/skills/linux-sysadmin/SKILL.md +115 -0
  442. core/skills/linux-sysadmin/assets/hardening-checklist.md +29 -0
  443. core/skills/linux-sysadmin/references/ssh-hardening.md +62 -0
  444. core/skills/linux-sysadmin/references/systemd-and-services.md +77 -0
  445. core/skills/linux-sysadmin/scripts/triage.sh +50 -0
  446. core/skills/linux-sysadmin/versions.json +17 -0
  447. core/skills/llm-patterns/SKILL.md +410 -0
  448. core/skills/llm-patterns/assets/llm-feature-checklist.md +26 -0
  449. core/skills/llm-patterns/references/rag-and-evals.md +59 -0
  450. core/skills/llm-patterns/scripts/estimate_tokens.py +75 -0
  451. core/skills/messaging-queues/SKILL.md +142 -0
  452. core/skills/mobile-fundamentals/SKILL.md +406 -0
  453. core/skills/mobile-fundamentals/assets/mobile-launch-checklist.md +130 -0
  454. core/skills/mobile-fundamentals/references/navigation-and-deep-links.md +337 -0
  455. core/skills/mobile-fundamentals/references/offline-sync.md +339 -0
  456. core/skills/node-backend/SKILL.md +114 -0
  457. core/skills/node-backend/assets/node-checklist.md +25 -0
  458. core/skills/node-backend/references/async-and-errors.md +67 -0
  459. core/skills/node-backend/references/event-loop.md +65 -0
  460. core/skills/node-backend/scripts/check_package.py +78 -0
  461. core/skills/node-backend/versions.json +17 -0
  462. core/skills/observability/SKILL.md +289 -0
  463. core/skills/observability/assets/observability-checklist.md +27 -0
  464. core/skills/observability/references/instrumentation.md +57 -0
  465. core/skills/observability/scripts/lint_logging.py +77 -0
  466. core/skills/payments/SKILL.md +102 -0
  467. core/skills/performance/SKILL.md +305 -0
  468. core/skills/performance/assets/perf-checklist.md +143 -0
  469. core/skills/performance/references/mobile-performance.md +249 -0
  470. core/skills/performance/references/web-vitals.md +209 -0
  471. core/skills/php/SKILL.md +116 -0
  472. core/skills/php/assets/php-checklist.md +26 -0
  473. core/skills/php/references/modern-php.md +64 -0
  474. core/skills/php/references/security.md +72 -0
  475. core/skills/php/scripts/scan_php_smells.py +99 -0
  476. core/skills/php/versions.json +9 -0
  477. core/skills/pr-mode-driver/SKILL.md +65 -0
  478. core/skills/realtime-websockets/SKILL.md +152 -0
  479. core/skills/redis/SKILL.md +105 -0
  480. core/skills/redis/assets/redis-checklist.md +27 -0
  481. core/skills/redis/references/operations.md +66 -0
  482. core/skills/redis/references/patterns.md +62 -0
  483. core/skills/redis/scripts/analyze_info.py +101 -0
  484. core/skills/redis/versions.json +9 -0
  485. core/skills/search/SKILL.md +91 -0
  486. core/skills/search/references/grep.md +76 -0
  487. core/skills/search/scripts/verify-count.sh +73 -0
  488. core/skills/search-infra/SKILL.md +109 -0
  489. core/skills/security-mobile/SKILL.md +394 -0
  490. core/skills/security-mobile/assets/mobile-security-checklist.md +117 -0
  491. core/skills/security-mobile/references/masvs-l1-checklist.md +127 -0
  492. core/skills/security-web/SKILL.md +217 -0
  493. core/skills/security-web/assets/security-web-checklist.md +167 -0
  494. core/skills/security-web/references/owasp-top-10.md +551 -0
  495. core/skills/security-web/references/supply-chain.md +179 -0
  496. core/skills/security-web/scripts/csp-check.sh +153 -0
  497. core/skills/shell-scripting/SKILL.md +128 -0
  498. core/skills/shell-scripting/assets/script-checklist.md +33 -0
  499. core/skills/shell-scripting/references/argument-parsing.md +84 -0
  500. core/skills/shell-scripting/references/bash-robustness.md +78 -0
  501. core/skills/shell-scripting/scripts/lint_script.sh +53 -0
  502. core/skills/shell-scripting/scripts/new_script.py +131 -0
  503. core/skills/shell-scripting/versions.json +23 -0
  504. core/skills/sql-authoring/SKILL.md +104 -0
  505. core/skills/sql-authoring/assets/query-review-checklist.md +26 -0
  506. core/skills/sql-authoring/references/query-patterns.md +89 -0
  507. core/skills/sql-authoring/references/reading-explain.md +52 -0
  508. core/skills/sql-authoring/scripts/analyze_plan.py +100 -0
  509. core/skills/sql-authoring/versions.json +17 -0
  510. core/skills/state-management/SKILL.md +428 -0
  511. core/skills/state-management/references/tanstack-query-recipes.md +301 -0
  512. core/skills/state-management/references/zustand-recipes.md +364 -0
  513. core/skills/supabase/SKILL.md +108 -0
  514. core/skills/supabase/assets/supabase-checklist.md +26 -0
  515. core/skills/supabase/references/realtime-and-storage.md +55 -0
  516. core/skills/supabase/references/rls-and-auth.md +65 -0
  517. core/skills/supabase/scripts/check_rls.py +88 -0
  518. core/skills/supabase/versions.json +9 -0
  519. core/skills/task-driver/SKILL.md +272 -0
  520. core/skills/task-driver/scripts/task-lint.sh +163 -0
  521. core/skills/technical-writing/SKILL.md +85 -0
  522. core/skills/technical-writing/assets/doc-checklist.md +29 -0
  523. core/skills/technical-writing/references/doc-anatomy.md +53 -0
  524. core/skills/technical-writing/references/writing-craft.md +59 -0
  525. core/skills/technical-writing/scripts/new_doc.py +81 -0
  526. core/skills/terraform-k8s/SKILL.md +133 -0
  527. core/skills/testing-strategy/SKILL.md +266 -0
  528. core/skills/testing-strategy/assets/test-review-checklist.md +25 -0
  529. core/skills/testing-strategy/references/test-types.md +52 -0
  530. core/skills/testing-strategy/scripts/coverage_gate.py +79 -0
  531. core/skills/thinking_os/SKILL.md +288 -0
  532. core/skills/thinking_os/scripts/classify.sh +122 -0
  533. core/skills/typescript/SKILL.md +110 -0
  534. core/skills/typescript/assets/typescript-checklist.md +24 -0
  535. core/skills/typescript/references/strictness.md +53 -0
  536. core/skills/typescript/references/type-system.md +86 -0
  537. core/skills/typescript/scripts/check_tsconfig.py +92 -0
  538. core/skills/typescript/versions.json +9 -0
  539. core/subsystems.yaml +202 -0
  540. core/thinking_os/__init__.py +1 -0
  541. core/thinking_os/_agent_markers.py +32 -0
  542. core/thinking_os/agents/README.md +71 -0
  543. core/thinking_os/agents/analyst.md +139 -0
  544. core/thinking_os/agents/architect.md +127 -0
  545. core/thinking_os/agents/debugger.md +111 -0
  546. core/thinking_os/agents/deployer.md +112 -0
  547. core/thinking_os/agents/distiller.md +28 -0
  548. core/thinking_os/agents/documenter.md +101 -0
  549. core/thinking_os/agents/implementer.md +135 -0
  550. core/thinking_os/agents/internal/session_observer.md +39 -0
  551. core/thinking_os/agents/observer.md +100 -0
  552. core/thinking_os/agents/onboarder.md +81 -0
  553. core/thinking_os/agents/refactorer.md +123 -0
  554. core/thinking_os/agents/repairer.md +47 -0
  555. core/thinking_os/agents/researcher.md +129 -0
  556. core/thinking_os/agents/reviewer.md +147 -0
  557. core/thinking_os/agents/security_auditor.md +133 -0
  558. core/thinking_os/background.py +405 -0
  559. core/thinking_os/bootstrap_outcomes.py +200 -0
  560. core/thinking_os/budget.py +302 -0
  561. core/thinking_os/capture.py +495 -0
  562. core/thinking_os/cognition.py +516 -0
  563. core/thinking_os/cognition_schemas.py +517 -0
  564. core/thinking_os/compress.py +192 -0
  565. core/thinking_os/concepts.py +233 -0
  566. core/thinking_os/dashboard.py +159 -0
  567. core/thinking_os/database.py +2883 -0
  568. core/thinking_os/decay.py +393 -0
  569. core/thinking_os/digest.py +295 -0
  570. core/thinking_os/dispatcher.py +192 -0
  571. core/thinking_os/dispatcher_helpers.py +48 -0
  572. core/thinking_os/dispatchers/__init__.py +3 -0
  573. core/thinking_os/dispatchers/default.py +47 -0
  574. core/thinking_os/distill.py +192 -0
  575. core/thinking_os/doc_indexer.py +905 -0
  576. core/thinking_os/embeddings.py +943 -0
  577. core/thinking_os/formula_composer.py +556 -0
  578. core/thinking_os/gate_marker.py +75 -0
  579. core/thinking_os/graph.py +296 -0
  580. core/thinking_os/graph_indexer.py +360 -0
  581. core/thinking_os/health_check.py +517 -0
  582. core/thinking_os/impact.py +119 -0
  583. core/thinking_os/memory_gc.py +356 -0
  584. core/thinking_os/migrator_embeddings.py +318 -0
  585. core/thinking_os/precision.py +194 -0
  586. core/thinking_os/presets/registry.yaml +127 -0
  587. core/thinking_os/record_outcome.py +399 -0
  588. core/thinking_os/repair.py +105 -0
  589. core/thinking_os/retrieval_quality.py +239 -0
  590. core/thinking_os/roles/analyst.yaml +83 -0
  591. core/thinking_os/roles/architect.yaml +88 -0
  592. core/thinking_os/roles/debugger.yaml +71 -0
  593. core/thinking_os/roles/deployer.yaml +71 -0
  594. core/thinking_os/roles/documenter.yaml +72 -0
  595. core/thinking_os/roles/implementer.yaml +83 -0
  596. core/thinking_os/roles/observer.yaml +70 -0
  597. core/thinking_os/roles/refactorer.yaml +71 -0
  598. core/thinking_os/roles/researcher.yaml +72 -0
  599. core/thinking_os/roles/reviewer.yaml +79 -0
  600. core/thinking_os/roles/security_auditor.yaml +83 -0
  601. core/thinking_os/roles_state.py +168 -0
  602. core/thinking_os/sanitizer.py +320 -0
  603. core/thinking_os/server.py +3160 -0
  604. core/thinking_os/session_enrich.py +272 -0
  605. core/thinking_os/session_observe_worker.py +111 -0
  606. core/thinking_os/session_startup.py +74 -0
  607. core/thinking_os/session_summary.py +245 -0
  608. core/thinking_os/situations/registry.yaml +99 -0
  609. core/thinking_os/task_analyzer.py +462 -0
  610. core/thinking_os/task_parser.py +342 -0
  611. core/thinking_os/task_sync.py +73 -0
  612. core/thinking_os/tools/__init__.py +6 -0
  613. core/thinking_os/tools/_shared.py +947 -0
  614. core/thinking_os/tools/cognition.py +1867 -0
  615. core/thinking_os/tools/docs.py +770 -0
  616. core/thinking_os/tools/learning.py +2078 -0
  617. core/thinking_os/tools/logs.py +79 -0
  618. core/thinking_os/tools/memory.py +840 -0
  619. core/thinking_os/tools/metrics.py +200 -0
  620. core/thinking_os/tools/retrieve.py +415 -0
  621. core/thinking_os/tools/routing.py +658 -0
  622. core/thinking_os/tools/tasks.py +449 -0
  623. core/thinking_os/tools/trajectory.py +181 -0
  624. core/thinking_os/tracing.py +235 -0
  625. core/web/__init__.py +5 -0
  626. core/web/_cache.py +118 -0
  627. core/web/_deps.py +56 -0
  628. core/web/_envelope.py +85 -0
  629. core/web/_project_context.py +140 -0
  630. core/web/chat_providers.py +108 -0
  631. core/web/init_jobs.py +216 -0
  632. core/web/routes/__init__.py +25 -0
  633. core/web/routes/_bounded_read.py +76 -0
  634. core/web/routes/board.py +1089 -0
  635. core/web/routes/cognition.py +1838 -0
  636. core/web/routes/config.py +635 -0
  637. core/web/routes/graph.py +513 -0
  638. core/web/routes/health.py +180 -0
  639. core/web/routes/hooks.py +288 -0
  640. core/web/routes/hub.py +1219 -0
  641. core/web/routes/logs.py +374 -0
  642. core/web/routes/metrics.py +43 -0
  643. core/web/routes/observability.py +400 -0
  644. core/web/routes/patterns.py +227 -0
  645. core/web/routes/presence.py +609 -0
  646. core/web/routes/roles.py +446 -0
  647. core/web/routes/scheduled.py +261 -0
  648. core/web/routes/search.py +238 -0
  649. core/web/routes/sessions.py +220 -0
  650. core/web/routes/settings.py +363 -0
  651. core/web/routes/stream.py +547 -0
  652. core/web/security.py +157 -0
  653. core/web/server.py +283 -0
  654. graph_os/__init__.py +29 -0
  655. graph_os/backend.py +233 -0
  656. graph_os/backends/__init__.py +13 -0
  657. graph_os/backends/sqlite_backend.py +1053 -0
  658. graph_os/communities.py +410 -0
  659. graph_os/enterprise.py +218 -0
  660. graph_os/entry_points.py +226 -0
  661. graph_os/extractors/__init__.py +25 -0
  662. graph_os/extractors/code_generic.py +914 -0
  663. graph_os/extractors/code_go.py +1422 -0
  664. graph_os/extractors/code_json.py +340 -0
  665. graph_os/extractors/code_php.py +979 -0
  666. graph_os/extractors/code_python.py +1454 -0
  667. graph_os/extractors/code_shell.py +538 -0
  668. graph_os/extractors/code_toml.py +302 -0
  669. graph_os/extractors/code_ts.py +1665 -0
  670. graph_os/extractors/code_yaml.py +394 -0
  671. graph_os/extractors/contracts.py +1592 -0
  672. graph_os/extractors/md_links.py +890 -0
  673. graph_os/extractors/task_deps.py +345 -0
  674. graph_os/groups/__init__.py +22 -0
  675. graph_os/groups/cross_repo.py +156 -0
  676. graph_os/groups/manifest.py +141 -0
  677. graph_os/ingest/__init__.py +19 -0
  678. graph_os/ingest/base.py +306 -0
  679. graph_os/ingest/github.py +112 -0
  680. graph_os/ingest/zip.py +95 -0
  681. graph_os/toolchain.py +393 -0
  682. graph_os/tools/__init__.py +9 -0
  683. graph_os/tools/graph.py +5573 -0
  684. graph_os/tools/reindex_dispatch.py +730 -0
  685. graph_os/tree_sitter_overlay.py +235 -0
  686. graph_os/types.py +252 -0
  687. graph_os/vec_index.py +277 -0
  688. graph_os/viewer/__init__.py +12 -0
  689. graph_os/viewer/exporter.py +93 -0
  690. graph_os/viewer/template.py +189 -0
  691. scheduled/__init__.py +0 -0
  692. scheduled/_activity.py +126 -0
  693. scheduled/_state.py +113 -0
  694. scheduled/config.py +86 -0
  695. scheduled/dep_reconcile.py +135 -0
  696. scheduled/error_sweep.py +137 -0
  697. scheduled/nightly.py +930 -0
  698. scheduled/responsive_extract.py +65 -0
  699. scripts/__init__.py +4 -0
  700. scripts/_commit_msg_body.sh +31 -0
  701. scripts/_post_commit_body.sh +49 -0
  702. scripts/_pre_commit_body.sh +121 -0
  703. scripts/_prepare_commit_msg_body.sh +53 -0
  704. scripts/audit_mcp_tools.py +693 -0
  705. scripts/bench_sdk_dispatcher.py +177 -0
  706. scripts/capture_golden.py +169 -0
  707. scripts/check_graph_phantoms.py +75 -0
  708. scripts/dev/audit_doc_links.py +359 -0
  709. scripts/dev/audit_scaffold_module_tags.py +107 -0
  710. scripts/dev/backfill_doc_headers.py +328 -0
  711. scripts/dev/backfill_nav_lines.py +119 -0
  712. scripts/dev/fix_nav_placement.py +106 -0
  713. scripts/dev/inspect_sdk_options.py +45 -0
  714. scripts/dev/migrate_check_ids.py +170 -0
  715. scripts/dev/strip_purpose_blocks.py +154 -0
  716. scripts/dump_openapi.py +66 -0
  717. scripts/e2e_dispatch_tool.py +195 -0
  718. scripts/generate_manifest.py +166 -0
  719. scripts/golden_sections.py +20 -0
  720. scripts/graph_demo.py +161 -0
  721. scripts/install-git-hooks.sh +47 -0
  722. scripts/migrate_embeddings_minilm_to_bge_m3.py +84 -0
  723. scripts/operational_eval.py +445 -0
  724. scripts/probe_agent_session_resolver.py +59 -0
  725. scripts/prune_deleted_path.py +127 -0
  726. scripts/refactor_agent_dual_mode.py +171 -0
  727. scripts/refresh_skill_versions.py +302 -0
  728. scripts/regen_doc_index.py +209 -0
  729. scripts/regen_doctor_schema.py +62 -0
  730. scripts/regen_rules.py +94 -0
  731. scripts/rename_formulas_to_semantic.py +241 -0
  732. scripts/smoke_db_connections.py +183 -0
  733. scripts/smoke_doc_header.py +72 -0
  734. scripts/smoke_graph_e2e.py +374 -0
  735. scripts/smoke_sdk_dispatch.py +84 -0
  736. scripts/smoke_uid_resolver.py +164 -0
  737. scripts/verify_dispatchers.py +244 -0
  738. scripts/verify_phase_c_e2e.py +436 -0
  739. templates/__init__.py +6 -0
  740. templates/_base/Makefile.base +353 -0
  741. templates/_base/base.yaml +59 -0
  742. templates/_base/coding-os.yaml.template +39 -0
  743. templates/_base/dimension-registry.template.md +68 -0
  744. templates/_base/domain-config.template.json +46 -0
  745. templates/_base/fragments/anatomy-map.md.tmpl +11 -0
  746. templates/_base/fragments/context-discipline.md.tmpl +3 -0
  747. templates/_base/fragments/core-loop.md.tmpl +52 -0
  748. templates/_base/fragments/engineering-routing.md.tmpl +3 -0
  749. templates/_base/fragments/header.md.tmpl +6 -0
  750. templates/_base/fragments/identity.md.tmpl +3 -0
  751. templates/_base/fragments/principles.md.tmpl +3 -0
  752. templates/_base/fragments/retrieval-routing.md.tmpl +23 -0
  753. templates/_base/fragments/session-handoff.md.tmpl +3 -0
  754. templates/_base/fragments/skills.md.tmpl +3 -0
  755. templates/_base/fragments/ssot-map.md.tmpl +3 -0
  756. templates/_base/fragments/stop-conditions.md.tmpl +3 -0
  757. templates/_base/fragments/subagent-dispatch.md.tmpl +3 -0
  758. templates/_base/fragments/task-authoring.md.tmpl +69 -0
  759. templates/_base/fragments/task-logging.md.tmpl +8 -0
  760. templates/_base/fragments/tool-routing.md.tmpl +9 -0
  761. templates/_base/fragments/verification-matrix.md.tmpl +12 -0
  762. templates/_base/lang/dart/analysis_options.yaml +7 -0
  763. templates/_base/lang/php/phpcs.xml.dist +10 -0
  764. templates/_base/lang/python/pyproject.toml +19 -0
  765. templates/_base/lang/rust/clippy.toml +5 -0
  766. templates/_base/lang/rust/rustfmt.toml +3 -0
  767. templates/_base/lang/typescript/eslint.config.js +26 -0
  768. templates/_base/lang/typescript/tsconfig.json +15 -0
  769. templates/_base/lang/typescript/vitest.config.ts +10 -0
  770. templates/_base/scaffold/changes.log +1 -0
  771. templates/_base/scaffold/docs/00-index.md +55 -0
  772. templates/_base/scaffold/docs/_meta/feature-dependency-tree.md +30 -0
  773. templates/_base/scaffold/docs/_meta/foundation-map.md +56 -0
  774. templates/_base/scaffold/docs/_meta/questions.md +8 -0
  775. templates/_base/scaffold/docs/_meta/roadmap.md +33 -0
  776. templates/_base/scaffold/docs/api-contracts/00-index.md +58 -0
  777. templates/_base/scaffold/docs/api-contracts/error-format.md +58 -0
  778. templates/_base/scaffold/docs/architecture/00-index.md +42 -0
  779. templates/_base/scaffold/docs/architecture/adr/00-index.md +39 -0
  780. templates/_base/scaffold/docs/engineering/00-index.md +9 -0
  781. templates/_base/scaffold/docs/governance/00-index.md +55 -0
  782. templates/_base/scaffold/docs/governance/_templates/doc-cheat-sheet.md +202 -0
  783. templates/_base/scaffold/docs/governance/_templates/playbook-template.md +81 -0
  784. templates/_base/scaffold/docs/governance/_templates/post-mortem-template.md +85 -0
  785. templates/_base/scaffold/docs/governance/_templates/runbook-template.md +88 -0
  786. templates/_base/scaffold/docs/governance/_templates/security-review-template.md +111 -0
  787. templates/_base/scaffold/docs/governance/_templates/task-detail.md +61 -0
  788. templates/_base/scaffold/docs/governance/agent-workflow.md +101 -0
  789. templates/_base/scaffold/docs/governance/anatomy-contract.md +150 -0
  790. templates/_base/scaffold/docs/governance/critical-rules.md +224 -0
  791. templates/_base/scaffold/docs/governance/decision-records.md +58 -0
  792. templates/_base/scaffold/docs/governance/docs-first-protocol.md +157 -0
  793. templates/_base/scaffold/docs/governance/docs-system.md +151 -0
  794. templates/_base/scaffold/docs/governance/gdpr-compliance.md +66 -0
  795. templates/_base/scaffold/docs/governance/mcp-tool-inventory.md +112 -0
  796. templates/_base/scaffold/docs/governance/risk-register.md +26 -0
  797. templates/_base/scaffold/docs/governance/scaffold-boundary-contract.md +161 -0
  798. templates/_base/scaffold/docs/governance/task-lifecycle.md +125 -0
  799. templates/_base/scaffold/docs/governance/wrapper-derivation.md +50 -0
  800. templates/_base/scaffold/docs/insights/00-index.md +17 -0
  801. templates/_base/scaffold/docs/ops/00-index.md +59 -0
  802. templates/_base/scaffold/docs/ops/runbooks/00-index.md +9 -0
  803. templates/_base/scaffold/docs/playbooks/00-index.md +12 -0
  804. templates/_base/scaffold/docs/playbooks/research-validation.md +29 -0
  805. templates/_base/scaffold/docs/playbooks/security-review.md +41 -0
  806. templates/_base/scaffold/docs/prd/00-index.md +43 -0
  807. templates/_base/scaffold/docs/prd/01-snapshot-vision.md +56 -0
  808. templates/_base/scaffold/docs/workflow/workflow-guide.md +138 -0
  809. templates/_base/scaffold/src/shared/README.md +23 -0
  810. templates/_base/skill-enforcement.template.md +14 -0
  811. templates/_base/task-detail.template.md +61 -0
  812. templates/_presets/ai-saas.yaml +9 -0
  813. templates/_presets/django-next.yaml +8 -0
  814. templates/_presets/dotnet-react.yaml +8 -0
  815. templates/_presets/flutter-baas.yaml +8 -0
  816. templates/_presets/go-react.yaml +8 -0
  817. templates/_presets/hexagonal-product.yaml +16 -0
  818. templates/_presets/jamstack.yaml +8 -0
  819. templates/_presets/laravel-vue.yaml +8 -0
  820. templates/_presets/mean.yaml +8 -0
  821. templates/_presets/mern.yaml +9 -0
  822. templates/_presets/nest-angular.yaml +8 -0
  823. templates/_presets/nextjs-fastapi.yaml +10 -0
  824. templates/_presets/nuxt-fullstack.yaml +9 -0
  825. templates/_presets/pern.yaml +9 -0
  826. templates/_presets/rails-react.yaml +8 -0
  827. templates/_presets/rn-api.yaml +8 -0
  828. templates/_presets/rust-svelte.yaml +8 -0
  829. templates/_presets/spring-react.yaml +8 -0
  830. templates/_presets/t3-style.yaml +9 -0
  831. templates/_presets/tall.yaml +8 -0
  832. templates/_presets/wordpress-cms.yaml +8 -0
  833. templates/angular/rules/frontend.md +19 -0
  834. templates/angular/scaffold/docs/engineering/accessibility.md +46 -0
  835. templates/angular/scaffold/docs/engineering/angular-rules.md +35 -0
  836. templates/angular/scaffold/docs/playbooks/angular-app.md +42 -0
  837. templates/angular/scaffold/src/frontend/angular.json +52 -0
  838. templates/angular/scaffold/src/frontend/package.json +28 -0
  839. templates/angular/scaffold/src/frontend/src/app/app.component.ts +19 -0
  840. templates/angular/scaffold/src/frontend/src/app/app.config.ts +22 -0
  841. templates/angular/scaffold/src/frontend/src/app/app.routes.ts +8 -0
  842. templates/angular/scaffold/src/frontend/src/app/core/global-error-handler.ts +12 -0
  843. templates/angular/scaffold/src/frontend/src/app/health/health.component.ts +14 -0
  844. templates/angular/scaffold/src/frontend/src/app/health/health.service.spec.ts +16 -0
  845. templates/angular/scaffold/src/frontend/src/app/health/health.service.ts +10 -0
  846. templates/angular/scaffold/src/frontend/src/index.html +11 -0
  847. templates/angular/scaffold/src/frontend/src/main.ts +9 -0
  848. templates/angular/scaffold/src/frontend/src/styles.css +14 -0
  849. templates/angular/scaffold/src/frontend/tsconfig.app.json +8 -0
  850. templates/angular/scaffold/src/frontend/tsconfig.json +27 -0
  851. templates/angular/scaffold/src/frontend/tsconfig.spec.json +8 -0
  852. templates/angular/scaffold-boundary.yaml +27 -0
  853. templates/angular/skills/angular/SKILL.md +79 -0
  854. templates/angular/skills/angular/references/anatomy.md +69 -0
  855. templates/angular/stack.yaml +75 -0
  856. templates/aspnet-core/rules/backend.md +20 -0
  857. templates/aspnet-core/scaffold/docs/engineering/aspnet-core-rules.md +36 -0
  858. templates/aspnet-core/scaffold/docs/playbooks/aspnet-core-service.md +40 -0
  859. templates/aspnet-core/scaffold/src/backend/Backend.csproj +11 -0
  860. templates/aspnet-core/scaffold/src/backend/Backend.sln +27 -0
  861. templates/aspnet-core/scaffold/src/backend/Common/ExceptionHandlingMiddleware.cs +35 -0
  862. templates/aspnet-core/scaffold/src/backend/Features/Health/HealthEndpoints.cs +10 -0
  863. templates/aspnet-core/scaffold/src/backend/Features/Health/HealthService.cs +9 -0
  864. templates/aspnet-core/scaffold/src/backend/Program.cs +22 -0
  865. templates/aspnet-core/scaffold/src/backend/tests/Backend.Tests/Backend.Tests.csproj +22 -0
  866. templates/aspnet-core/scaffold/src/backend/tests/Backend.Tests/HealthServiceTests.cs +15 -0
  867. templates/aspnet-core/scaffold-boundary.yaml +24 -0
  868. templates/aspnet-core/skills/aspnet-core/SKILL.md +80 -0
  869. templates/aspnet-core/skills/aspnet-core/references/anatomy.md +65 -0
  870. templates/aspnet-core/stack.yaml +68 -0
  871. templates/astro/rules/frontend.md +20 -0
  872. templates/astro/scaffold/docs/engineering/astro-rules.md +40 -0
  873. templates/astro/scaffold/docs/playbooks/astro-app.md +57 -0
  874. templates/astro/scaffold/docs/playbooks/content-seo.md +37 -0
  875. templates/astro/scaffold/src/frontend/astro.config.mjs +10 -0
  876. templates/astro/scaffold/src/frontend/package.json +23 -0
  877. templates/astro/scaffold/src/frontend/src/components/Greeting.astro +13 -0
  878. templates/astro/scaffold/src/frontend/src/content/posts/hello.md +10 -0
  879. templates/astro/scaffold/src/frontend/src/content.config.ts +19 -0
  880. templates/astro/scaffold/src/frontend/src/lib/problem.test.ts +39 -0
  881. templates/astro/scaffold/src/frontend/src/lib/problem.ts +30 -0
  882. templates/astro/scaffold/src/frontend/src/pages/api/health.ts +13 -0
  883. templates/astro/scaffold/src/frontend/src/pages/index.astro +21 -0
  884. templates/astro/scaffold/src/frontend/tsconfig.json +9 -0
  885. templates/astro/scaffold/src/frontend/vitest.config.ts +10 -0
  886. templates/astro/scaffold-boundary.yaml +28 -0
  887. templates/astro/skills/astro/SKILL.md +71 -0
  888. templates/astro/skills/astro/references/anatomy.md +66 -0
  889. templates/astro/stack.yaml +75 -0
  890. templates/csharp-plain/scaffold/src/backend/Backend.csproj +12 -0
  891. templates/csharp-plain/scaffold/src/backend/Program.cs +1 -0
  892. templates/csharp-plain/scaffold-boundary.yaml +23 -0
  893. templates/csharp-plain/stack.yaml +50 -0
  894. templates/django/rules/backend.md +18 -0
  895. templates/django/scaffold/docs/engineering/anti-ambiguity.md +74 -0
  896. templates/django/scaffold/docs/engineering/backend-rules.md +133 -0
  897. templates/django/scaffold/docs/engineering/glossary.md +51 -0
  898. templates/django/scaffold/docs/engineering/logging-standards.md +107 -0
  899. templates/django/scaffold/docs/engineering/naming-conventions.md +68 -0
  900. templates/django/scaffold/docs/engineering/secrets-rotation-runbook.md +142 -0
  901. templates/django/scaffold/docs/playbooks/backend-api.md +119 -0
  902. templates/django/scaffold/src/backend/config/__init__.py +0 -0
  903. templates/django/scaffold/src/backend/config/settings.py +31 -0
  904. templates/django/scaffold/src/backend/config/urls.py +11 -0
  905. templates/django/scaffold/src/backend/config/wsgi.py +6 -0
  906. templates/django/scaffold/src/backend/manage.py +14 -0
  907. templates/django/scaffold/src/backend/pyproject.toml +37 -0
  908. templates/django/scaffold/src/backend/tests/test_health.py +4 -0
  909. templates/django/scaffold-boundary.yaml +25 -0
  910. templates/django/skills/python-django/SKILL.md +450 -0
  911. templates/django/skills/python-django/references/anatomy.md +117 -0
  912. templates/django/skills/python-django/scripts/new_endpoint.py +89 -0
  913. templates/django/stack.yaml +73 -0
  914. templates/fastapi/rules/backend.md +18 -0
  915. templates/fastapi/scaffold/docs/engineering/fastapi-rules.md +37 -0
  916. templates/fastapi/scaffold/docs/playbooks/fastapi-service.md +30 -0
  917. templates/fastapi/scaffold/src/backend/app/__init__.py +0 -0
  918. templates/fastapi/scaffold/src/backend/app/main.py +8 -0
  919. templates/fastapi/scaffold/src/backend/pyproject.toml +39 -0
  920. templates/fastapi/scaffold/src/backend/tests/test_health.py +11 -0
  921. templates/fastapi/scaffold-boundary.yaml +25 -0
  922. templates/fastapi/skills/python-fastapi/SKILL.md +75 -0
  923. templates/fastapi/skills/python-fastapi/references/anatomy.md +117 -0
  924. templates/fastapi/skills/python-fastapi/scripts/new_endpoint.py +101 -0
  925. templates/fastapi/stack.yaml +57 -0
  926. templates/flutter/rules/mobile.md +26 -0
  927. templates/flutter/scaffold/docs/engineering/flutter-rules.md +35 -0
  928. templates/flutter/scaffold/docs/playbooks/flutter-app.md +45 -0
  929. templates/flutter/scaffold/src/mobile/lib/core/error_mapper.dart +17 -0
  930. templates/flutter/scaffold/src/mobile/lib/core/router.dart +13 -0
  931. templates/flutter/scaffold/src/mobile/lib/main.dart +22 -0
  932. templates/flutter/scaffold/src/mobile/lib/screens/health_screen.dart +32 -0
  933. templates/flutter/scaffold/src/mobile/lib/services/health_service.dart +11 -0
  934. templates/flutter/scaffold/src/mobile/lib/state/health_provider.dart +13 -0
  935. templates/flutter/scaffold/src/mobile/pubspec.yaml +22 -0
  936. templates/flutter/scaffold/src/mobile/test/health_provider_test.dart +90 -0
  937. templates/flutter/scaffold-boundary.yaml +28 -0
  938. templates/flutter/skills/flutter/SKILL.md +76 -0
  939. templates/flutter/skills/flutter/references/anatomy.md +64 -0
  940. templates/flutter/stack.yaml +70 -0
  941. templates/go/rules/backend.md +19 -0
  942. templates/go/scaffold/docs/engineering/go-rules.md +45 -0
  943. templates/go/scaffold/docs/playbooks/go-service.md +30 -0
  944. templates/go/scaffold/src/backend/cmd/api/main.go +22 -0
  945. templates/go/scaffold/src/backend/cmd/api/main_test.go +20 -0
  946. templates/go/scaffold/src/backend/go.mod +3 -0
  947. templates/go/scaffold-boundary.yaml +25 -0
  948. templates/go/skills/go-patterns/SKILL.md +68 -0
  949. templates/go/skills/go-patterns/assets/go-checklist.md +29 -0
  950. templates/go/skills/go-patterns/references/anatomy.md +115 -0
  951. templates/go/skills/go-patterns/references/go-2026-idioms.md +92 -0
  952. templates/go/skills/go-patterns/scripts/new_endpoint.py +117 -0
  953. templates/go/skills/go-patterns/versions.json +16 -0
  954. templates/go/stack.yaml +54 -0
  955. templates/go-fiber/rules/backend.md +20 -0
  956. templates/go-fiber/scaffold/docs/engineering/fiber-rules.md +97 -0
  957. templates/go-fiber/scaffold/docs/playbooks/fiber-service.md +149 -0
  958. templates/go-fiber/scaffold/src/backend/cmd/api/main.go +21 -0
  959. templates/go-fiber/scaffold/src/backend/cmd/api/main_test.go +17 -0
  960. templates/go-fiber/scaffold/src/backend/go.mod +23 -0
  961. templates/go-fiber/scaffold/src/backend/go.sum +49 -0
  962. templates/go-fiber/scaffold-boundary.yaml +26 -0
  963. templates/go-fiber/skills/go-fiber/SKILL.md +203 -0
  964. templates/go-fiber/skills/go-fiber/assets/fiber-checklist.md +26 -0
  965. templates/go-fiber/skills/go-fiber/references/anatomy.md +116 -0
  966. templates/go-fiber/skills/go-fiber/references/fiber-v3-patterns.md +89 -0
  967. templates/go-fiber/skills/go-fiber/scripts/new_endpoint.py +107 -0
  968. templates/go-fiber/skills/go-fiber/versions.json +16 -0
  969. templates/go-fiber/stack.yaml +59 -0
  970. templates/go-plain/scaffold/src/backend/go.mod +3 -0
  971. templates/go-plain/scaffold/src/backend/main.go +7 -0
  972. templates/go-plain/scaffold-boundary.yaml +22 -0
  973. templates/go-plain/stack.yaml +51 -0
  974. templates/java-plain/scaffold/src/backend/mvnw +302 -0
  975. templates/java-plain/scaffold/src/backend/pom.xml +41 -0
  976. templates/java-plain/scaffold/src/backend/src/main/java/com/example/app/Main.java +10 -0
  977. templates/java-plain/scaffold-boundary.yaml +23 -0
  978. templates/java-plain/stack.yaml +51 -0
  979. templates/laravel/rules/backend.md +20 -0
  980. templates/laravel/scaffold/docs/engineering/laravel-rules.md +28 -0
  981. templates/laravel/scaffold/docs/playbooks/laravel-service.md +28 -0
  982. templates/laravel/scaffold/src/backend/app/Exceptions/Handler.php +27 -0
  983. templates/laravel/scaffold/src/backend/app/Http/Controllers/HealthController.php +15 -0
  984. templates/laravel/scaffold/src/backend/app/Support/HealthStatus.php +14 -0
  985. templates/laravel/scaffold/src/backend/composer.json +24 -0
  986. templates/laravel/scaffold/src/backend/phpunit.xml +10 -0
  987. templates/laravel/scaffold/src/backend/public/index.php +8 -0
  988. templates/laravel/scaffold/src/backend/routes/api.php +7 -0
  989. templates/laravel/scaffold/src/backend/tests/Unit/HealthStatusTest.php +16 -0
  990. templates/laravel/scaffold-boundary.yaml +23 -0
  991. templates/laravel/skills/laravel/SKILL.md +56 -0
  992. templates/laravel/skills/laravel/references/anatomy.md +65 -0
  993. templates/laravel/stack.yaml +66 -0
  994. templates/meta/rules/graph-first.md +27 -0
  995. templates/meta/rules/hook-author.md +19 -0
  996. templates/meta/rules/mcp-tool-author.md +18 -0
  997. templates/meta/rules/meta-engineering.md +17 -0
  998. templates/meta/scaffold-boundary.yaml +55 -0
  999. templates/meta/skills/claude-sdk-integration/SKILL.md +163 -0
  1000. templates/meta/skills/claude-sdk-integration/assets/sdk-checklist.md +27 -0
  1001. templates/meta/skills/claude-sdk-integration/scripts/check_model_ids.py +97 -0
  1002. templates/meta/skills/graph-os-authoring/SKILL.md +278 -0
  1003. templates/meta/skills/graph-os-authoring/assets/graph-os-checklist.md +25 -0
  1004. templates/meta/skills/graph-os-authoring/scripts/new_extractor.py +76 -0
  1005. templates/meta/skills/hook-authoring/SKILL.md +292 -0
  1006. templates/meta/skills/hook-authoring/assets/hook-checklist.md +30 -0
  1007. templates/meta/skills/hook-authoring/scripts/new_hook.sh +75 -0
  1008. templates/meta/skills/mcp-tool-authoring/SKILL.md +301 -0
  1009. templates/meta/skills/mcp-tool-authoring/assets/mcp-tool-checklist.md +29 -0
  1010. templates/meta/skills/mcp-tool-authoring/scripts/new_tool.py +74 -0
  1011. templates/meta/skills/meta-engineering/SKILL.md +151 -0
  1012. templates/meta/skills/meta-engineering/assets/meta-edit-checklist.md +28 -0
  1013. templates/meta/skills/meta-engineering/scripts/which_layer.py +61 -0
  1014. templates/meta/skills/python-meta-server/SKILL.md +162 -0
  1015. templates/meta/skills/python-meta-server/assets/meta-server-checklist.md +28 -0
  1016. templates/meta/skills/python-meta-server/scripts/check_envelope.py +91 -0
  1017. templates/meta/skills/react-vite-hub/SKILL.md +140 -0
  1018. templates/meta/skills/react-vite-hub/assets/hub-ui-checklist.md +23 -0
  1019. templates/meta/skills/react-vite-hub/scripts/check_vite_env.py +73 -0
  1020. templates/meta/stack.yaml +119 -0
  1021. templates/nestjs/rules/backend.md +20 -0
  1022. templates/nestjs/scaffold/docs/engineering/nestjs-rules.md +33 -0
  1023. templates/nestjs/scaffold/docs/playbooks/nestjs-service.md +39 -0
  1024. templates/nestjs/scaffold/src/backend/nest-cli.json +5 -0
  1025. templates/nestjs/scaffold/src/backend/package.json +28 -0
  1026. templates/nestjs/scaffold/src/backend/src/app.module.ts +9 -0
  1027. templates/nestjs/scaffold/src/backend/src/common/all-exceptions.filter.ts +59 -0
  1028. templates/nestjs/scaffold/src/backend/src/health/health.controller.ts +14 -0
  1029. templates/nestjs/scaffold/src/backend/src/health/health.module.ts +10 -0
  1030. templates/nestjs/scaffold/src/backend/src/health/health.service.spec.ts +21 -0
  1031. templates/nestjs/scaffold/src/backend/src/health/health.service.ts +9 -0
  1032. templates/nestjs/scaffold/src/backend/src/main.ts +26 -0
  1033. templates/nestjs/scaffold/src/backend/tsconfig.json +16 -0
  1034. templates/nestjs/scaffold/src/backend/vitest.config.ts +9 -0
  1035. templates/nestjs/scaffold-boundary.yaml +25 -0
  1036. templates/nestjs/skills/nestjs/SKILL.md +67 -0
  1037. templates/nestjs/skills/nestjs/references/anatomy.md +65 -0
  1038. templates/nestjs/stack.yaml +68 -0
  1039. templates/nextjs/rules/frontend.md +18 -0
  1040. templates/nextjs/scaffold/docs/design/00-index.md +23 -0
  1041. templates/nextjs/scaffold/docs/design/colors-tokens.md +141 -0
  1042. templates/nextjs/scaffold/docs/design/components-patterns.md +159 -0
  1043. templates/nextjs/scaffold/docs/design/motion-accessibility.md +137 -0
  1044. templates/nextjs/scaffold/docs/design/typography-spacing.md +107 -0
  1045. templates/nextjs/scaffold/docs/engineering/accessibility-web.md +56 -0
  1046. templates/nextjs/scaffold/docs/engineering/copywriting-standard.md +102 -0
  1047. templates/nextjs/scaffold/docs/engineering/formatting-rules.md +89 -0
  1048. templates/nextjs/scaffold/docs/engineering/frontend-rendering-rules.md +80 -0
  1049. templates/nextjs/scaffold/docs/engineering/frontend-rules.md +183 -0
  1050. templates/nextjs/scaffold/docs/engineering/i18n-policy.md +99 -0
  1051. templates/nextjs/scaffold/docs/pages-content-spec/00-index.md +78 -0
  1052. templates/nextjs/scaffold/docs/playbooks/content-seo.md +55 -0
  1053. templates/nextjs/scaffold/docs/playbooks/docs-governance.md +51 -0
  1054. templates/nextjs/scaffold/docs/playbooks/frontend-ui.md +63 -0
  1055. templates/nextjs/scaffold/src/frontend/app/layout.tsx +14 -0
  1056. templates/nextjs/scaffold/src/frontend/app/page.tsx +3 -0
  1057. templates/nextjs/scaffold/src/frontend/eslint.config.js +17 -0
  1058. templates/nextjs/scaffold/src/frontend/lib/greeting.test.ts +9 -0
  1059. templates/nextjs/scaffold/src/frontend/lib/greeting.ts +3 -0
  1060. templates/nextjs/scaffold/src/frontend/package.json +28 -0
  1061. templates/nextjs/scaffold/src/frontend/tsconfig.json +18 -0
  1062. templates/nextjs/scaffold/src/frontend/vitest.config.ts +10 -0
  1063. templates/nextjs/scaffold-boundary.yaml +30 -0
  1064. templates/nextjs/skills/nextjs-react/SKILL.md +485 -0
  1065. templates/nextjs/skills/nextjs-react/references/anatomy.md +116 -0
  1066. templates/nextjs/skills/nextjs-react/scripts/new_component.py +72 -0
  1067. templates/nextjs/stack.yaml +81 -0
  1068. templates/node-express/rules/backend.md +20 -0
  1069. templates/node-express/scaffold/docs/engineering/express-rules.md +30 -0
  1070. templates/node-express/scaffold/docs/playbooks/express-service.md +35 -0
  1071. templates/node-express/scaffold/src/backend/package.json +24 -0
  1072. templates/node-express/scaffold/src/backend/src/index.ts +17 -0
  1073. templates/node-express/scaffold/src/backend/src/middleware/error-handler.ts +12 -0
  1074. templates/node-express/scaffold/src/backend/src/routes/health.test.ts +33 -0
  1075. templates/node-express/scaffold/src/backend/src/routes/health.ts +7 -0
  1076. templates/node-express/scaffold/src/backend/tsconfig.json +15 -0
  1077. templates/node-express/scaffold/src/backend/types/express-bootstrap.d.ts +21 -0
  1078. templates/node-express/scaffold-boundary.yaml +25 -0
  1079. templates/node-express/skills/node-express/SKILL.md +70 -0
  1080. templates/node-express/skills/node-express/references/anatomy.md +63 -0
  1081. templates/node-express/stack.yaml +63 -0
  1082. templates/python/scaffold/docs/engineering/python-rules.md +27 -0
  1083. templates/python/scaffold/docs/playbooks/python-library.md +35 -0
  1084. templates/python/stack.yaml +60 -0
  1085. templates/rails/rules/backend.md +10 -0
  1086. templates/rails/scaffold/docs/engineering/rails-rules.md +33 -0
  1087. templates/rails/scaffold/docs/playbooks/rails-service.md +42 -0
  1088. templates/rails/scaffold/src/backend/Gemfile +12 -0
  1089. templates/rails/scaffold/src/backend/app/controllers/application_controller.rb +26 -0
  1090. templates/rails/scaffold/src/backend/app/controllers/health_controller.rb +6 -0
  1091. templates/rails/scaffold/src/backend/app/models/health.rb +6 -0
  1092. templates/rails/scaffold/src/backend/config/application.rb +12 -0
  1093. templates/rails/scaffold/src/backend/config/boot.rb +3 -0
  1094. templates/rails/scaffold/src/backend/config/routes.rb +4 -0
  1095. templates/rails/scaffold/src/backend/config.ru +5 -0
  1096. templates/rails/scaffold/src/backend/spec/rails_helper.rb +18 -0
  1097. templates/rails/scaffold/src/backend/spec/requests/health_spec.rb +24 -0
  1098. templates/rails/scaffold-boundary.yaml +25 -0
  1099. templates/rails/skills/rails/SKILL.md +62 -0
  1100. templates/rails/skills/rails/references/anatomy.md +71 -0
  1101. templates/rails/stack.yaml +72 -0
  1102. templates/react-native/rules/mobile.md +26 -0
  1103. templates/react-native/scaffold/docs/engineering/accessibility-mobile.md +95 -0
  1104. templates/react-native/scaffold/docs/engineering/mobile-rules.md +56 -0
  1105. templates/react-native/scaffold/docs/engineering/offline-first.md +61 -0
  1106. templates/react-native/scaffold/docs/playbooks/mobile-app.md +49 -0
  1107. templates/react-native/scaffold/src/mobile/App.tsx +9 -0
  1108. templates/react-native/scaffold/src/mobile/eslint.config.js +17 -0
  1109. templates/react-native/scaffold/src/mobile/package.json +23 -0
  1110. templates/react-native/scaffold/src/mobile/src/greeting.test.ts +9 -0
  1111. templates/react-native/scaffold/src/mobile/src/greeting.ts +3 -0
  1112. templates/react-native/scaffold/src/mobile/tsconfig.json +17 -0
  1113. templates/react-native/scaffold/src/mobile/vitest.config.ts +10 -0
  1114. templates/react-native/scaffold-boundary.yaml +30 -0
  1115. templates/react-native/skills/react-native-mobile/SKILL.md +119 -0
  1116. templates/react-native/skills/react-native-mobile/assets/rn-mobile-checklist.md +28 -0
  1117. templates/react-native/skills/react-native-mobile/references/anatomy.md +140 -0
  1118. templates/react-native/skills/react-native-mobile/references/rn-2026-practices.md +54 -0
  1119. templates/react-native/skills/react-native-mobile/scripts/new_screen.py +73 -0
  1120. templates/react-native/skills/react-native-mobile/versions.json +16 -0
  1121. templates/react-native/skills/react-native-patterns/SKILL.md +512 -0
  1122. templates/react-native/skills/react-native-patterns/assets/rn-review-checklist.md +26 -0
  1123. templates/react-native/skills/react-native-patterns/references/anatomy.md +62 -0
  1124. templates/react-native/skills/react-native-patterns/references/list-performance.md +70 -0
  1125. templates/react-native/skills/react-native-patterns/scripts/scan_rn_perf.py +77 -0
  1126. templates/react-native/stack.yaml +70 -0
  1127. templates/ruby-plain/scaffold/src/backend/Gemfile +8 -0
  1128. templates/ruby-plain/scaffold/src/backend/main.rb +3 -0
  1129. templates/ruby-plain/scaffold-boundary.yaml +23 -0
  1130. templates/ruby-plain/stack.yaml +50 -0
  1131. templates/rust-axum/rules/backend.md +20 -0
  1132. templates/rust-axum/scaffold/docs/engineering/rust-axum-rules.md +35 -0
  1133. templates/rust-axum/scaffold/docs/playbooks/rust-axum-service.md +43 -0
  1134. templates/rust-axum/scaffold/src/backend/Cargo.toml +20 -0
  1135. templates/rust-axum/scaffold/src/backend/src/app.rs +12 -0
  1136. templates/rust-axum/scaffold/src/backend/src/error.rs +48 -0
  1137. templates/rust-axum/scaffold/src/backend/src/main.rs +24 -0
  1138. templates/rust-axum/scaffold/src/backend/src/routes/health.rs +37 -0
  1139. templates/rust-axum/scaffold/src/backend/src/routes/mod.rs +2 -0
  1140. templates/rust-axum/scaffold-boundary.yaml +25 -0
  1141. templates/rust-axum/skills/rust/SKILL.md +73 -0
  1142. templates/rust-axum/skills/rust/references/anatomy.md +63 -0
  1143. templates/rust-axum/stack.yaml +65 -0
  1144. templates/rust-plain/scaffold/src/backend/Cargo.toml +6 -0
  1145. templates/rust-plain/scaffold/src/backend/src/main.rs +3 -0
  1146. templates/rust-plain/scaffold-boundary.yaml +23 -0
  1147. templates/rust-plain/stack.yaml +51 -0
  1148. templates/spring-boot/rules/backend.md +20 -0
  1149. templates/spring-boot/scaffold/docs/engineering/spring-boot-rules.md +35 -0
  1150. templates/spring-boot/scaffold/docs/playbooks/spring-boot-service.md +45 -0
  1151. templates/spring-boot/scaffold/src/backend/mvnw +302 -0
  1152. templates/spring-boot/scaffold/src/backend/pom.xml +69 -0
  1153. templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/Application.java +16 -0
  1154. templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/common/GlobalExceptionHandler.java +31 -0
  1155. templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthController.java +22 -0
  1156. templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthService.java +12 -0
  1157. templates/spring-boot/scaffold/src/backend/src/main/java/com/example/app/health/HealthStatus.java +4 -0
  1158. templates/spring-boot/scaffold/src/backend/src/test/java/com/example/app/health/HealthServiceTest.java +15 -0
  1159. templates/spring-boot/scaffold-boundary.yaml +26 -0
  1160. templates/spring-boot/skills/spring-boot/SKILL.md +84 -0
  1161. templates/spring-boot/skills/spring-boot/references/anatomy.md +63 -0
  1162. templates/spring-boot/stack.yaml +65 -0
  1163. templates/svelte-sveltekit/rules/frontend.md +20 -0
  1164. templates/svelte-sveltekit/scaffold/docs/engineering/svelte-sveltekit-rules.md +37 -0
  1165. templates/svelte-sveltekit/scaffold/docs/playbooks/svelte-sveltekit-app.md +36 -0
  1166. templates/svelte-sveltekit/scaffold/src/frontend/package.json +22 -0
  1167. templates/svelte-sveltekit/scaffold/src/frontend/src/app.html +12 -0
  1168. templates/svelte-sveltekit/scaffold/src/frontend/src/hooks.server.ts +14 -0
  1169. templates/svelte-sveltekit/scaffold/src/frontend/src/lib/components/Greeting.svelte +6 -0
  1170. templates/svelte-sveltekit/scaffold/src/frontend/src/lib/stores/count.test.ts +26 -0
  1171. templates/svelte-sveltekit/scaffold/src/frontend/src/lib/stores/count.ts +4 -0
  1172. templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+layout.svelte +24 -0
  1173. templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+page.svelte +9 -0
  1174. templates/svelte-sveltekit/scaffold/src/frontend/src/routes/+page.ts +7 -0
  1175. templates/svelte-sveltekit/scaffold/src/frontend/src/routes/health/+server.ts +7 -0
  1176. templates/svelte-sveltekit/scaffold/src/frontend/svelte.config.js +10 -0
  1177. templates/svelte-sveltekit/scaffold/src/frontend/tsconfig.json +7 -0
  1178. templates/svelte-sveltekit/scaffold/src/frontend/vite.config.ts +7 -0
  1179. templates/svelte-sveltekit/scaffold/src/frontend/vitest.config.ts +11 -0
  1180. templates/svelte-sveltekit/scaffold-boundary.yaml +29 -0
  1181. templates/svelte-sveltekit/skills/svelte/SKILL.md +90 -0
  1182. templates/svelte-sveltekit/skills/svelte/references/anatomy.md +62 -0
  1183. templates/svelte-sveltekit/stack.yaml +70 -0
  1184. templates/typescript-plain/scaffold/src/index.ts +3 -0
  1185. templates/typescript-plain/scaffold/tsconfig.json +13 -0
  1186. templates/typescript-plain/scaffold-boundary.yaml +22 -0
  1187. templates/typescript-plain/stack.yaml +44 -0
  1188. templates/vue-nuxt/rules/frontend.md +19 -0
  1189. templates/vue-nuxt/scaffold/docs/engineering/nuxt-rules.md +30 -0
  1190. templates/vue-nuxt/scaffold/docs/playbooks/nuxt-app.md +29 -0
  1191. templates/vue-nuxt/scaffold/src/frontend/app.vue +3 -0
  1192. templates/vue-nuxt/scaffold/src/frontend/nuxt.config.ts +11 -0
  1193. templates/vue-nuxt/scaffold/src/frontend/package.json +20 -0
  1194. templates/vue-nuxt/scaffold/src/frontend/pages/index.test.ts +19 -0
  1195. templates/vue-nuxt/scaffold/src/frontend/pages/index.vue +11 -0
  1196. templates/vue-nuxt/scaffold/src/frontend/vitest.config.ts +12 -0
  1197. templates/vue-nuxt/scaffold-boundary.yaml +26 -0
  1198. templates/vue-nuxt/skills/vue-nuxt/SKILL.md +57 -0
  1199. templates/vue-nuxt/skills/vue-nuxt/references/anatomy.md +60 -0
  1200. templates/vue-nuxt/stack.yaml +61 -0
  1201. templates/wordpress/rules/backend.md +19 -0
  1202. templates/wordpress/scaffold/docs/engineering/wordpress-rules.md +28 -0
  1203. templates/wordpress/scaffold/docs/playbooks/wordpress-service.md +29 -0
  1204. templates/wordpress/scaffold/src/backend/composer.json +17 -0
  1205. templates/wordpress/scaffold/src/backend/phpcs.xml.dist +11 -0
  1206. templates/wordpress/scaffold/src/backend/phpunit.xml +10 -0
  1207. templates/wordpress/scaffold/src/backend/plugin/inc/health.php +8 -0
  1208. templates/wordpress/scaffold/src/backend/plugin/plugin.php +28 -0
  1209. templates/wordpress/scaffold/src/backend/tests/HealthStatusTest.php +15 -0
  1210. templates/wordpress/scaffold/src/backend/theme/functions.php +18 -0
  1211. templates/wordpress/scaffold/src/backend/theme/style.css +11 -0
  1212. templates/wordpress/scaffold-boundary.yaml +23 -0
  1213. templates/wordpress/skills/wordpress/SKILL.md +110 -0
  1214. templates/wordpress/skills/wordpress/assets/wp-checklist.md +28 -0
  1215. templates/wordpress/skills/wordpress/references/wp-development.md +75 -0
  1216. templates/wordpress/skills/wordpress/references/wp-security.md +68 -0
  1217. templates/wordpress/skills/wordpress/scripts/scan_wp_smells.py +91 -0
  1218. templates/wordpress/skills/wordpress/versions.json +16 -0
  1219. templates/wordpress/stack.yaml +60 -0
  1220. thinking_os/__init__.py +1 -0
  1221. thinking_os/_agent_markers.py +32 -0
  1222. thinking_os/background.py +405 -0
  1223. thinking_os/bootstrap_outcomes.py +200 -0
  1224. thinking_os/budget.py +302 -0
  1225. thinking_os/capture.py +495 -0
  1226. thinking_os/cognition.py +516 -0
  1227. thinking_os/cognition_schemas.py +517 -0
  1228. thinking_os/compress.py +192 -0
  1229. thinking_os/concepts.py +233 -0
  1230. thinking_os/dashboard.py +159 -0
  1231. thinking_os/database.py +2883 -0
  1232. thinking_os/decay.py +393 -0
  1233. thinking_os/digest.py +295 -0
  1234. thinking_os/dispatcher.py +192 -0
  1235. thinking_os/dispatcher_helpers.py +48 -0
  1236. thinking_os/dispatchers/__init__.py +3 -0
  1237. thinking_os/dispatchers/default.py +47 -0
  1238. thinking_os/distill.py +192 -0
  1239. thinking_os/doc_indexer.py +905 -0
  1240. thinking_os/embeddings.py +943 -0
  1241. thinking_os/formula_composer.py +556 -0
  1242. thinking_os/gate_marker.py +75 -0
  1243. thinking_os/graph.py +296 -0
  1244. thinking_os/graph_indexer.py +360 -0
  1245. thinking_os/health_check.py +517 -0
  1246. thinking_os/impact.py +119 -0
  1247. thinking_os/memory_gc.py +356 -0
  1248. thinking_os/migrator_embeddings.py +318 -0
  1249. thinking_os/precision.py +194 -0
  1250. thinking_os/record_outcome.py +399 -0
  1251. thinking_os/repair.py +105 -0
  1252. thinking_os/retrieval_quality.py +239 -0
  1253. thinking_os/roles_state.py +168 -0
  1254. thinking_os/sanitizer.py +320 -0
  1255. thinking_os/server.py +3160 -0
  1256. thinking_os/session_enrich.py +272 -0
  1257. thinking_os/session_observe_worker.py +111 -0
  1258. thinking_os/session_startup.py +74 -0
  1259. thinking_os/session_summary.py +245 -0
  1260. thinking_os/task_analyzer.py +462 -0
  1261. thinking_os/task_parser.py +342 -0
  1262. thinking_os/task_sync.py +73 -0
  1263. thinking_os/tools/__init__.py +6 -0
  1264. thinking_os/tools/_shared.py +947 -0
  1265. thinking_os/tools/cognition.py +1867 -0
  1266. thinking_os/tools/docs.py +770 -0
  1267. thinking_os/tools/learning.py +2078 -0
  1268. thinking_os/tools/logs.py +79 -0
  1269. thinking_os/tools/memory.py +840 -0
  1270. thinking_os/tools/metrics.py +200 -0
  1271. thinking_os/tools/retrieve.py +415 -0
  1272. thinking_os/tools/routing.py +658 -0
  1273. thinking_os/tools/tasks.py +449 -0
  1274. thinking_os/tools/trajectory.py +181 -0
  1275. thinking_os/tracing.py +235 -0
  1276. web/__init__.py +5 -0
  1277. web/_cache.py +118 -0
  1278. web/_deps.py +56 -0
  1279. web/_envelope.py +85 -0
  1280. web/_project_context.py +140 -0
  1281. web/chat_providers.py +108 -0
  1282. web/init_jobs.py +216 -0
  1283. web/routes/__init__.py +25 -0
  1284. web/routes/_bounded_read.py +76 -0
  1285. web/routes/board.py +1089 -0
  1286. web/routes/cognition.py +1838 -0
  1287. web/routes/config.py +635 -0
  1288. web/routes/graph.py +513 -0
  1289. web/routes/health.py +180 -0
  1290. web/routes/hooks.py +288 -0
  1291. web/routes/hub.py +1219 -0
  1292. web/routes/logs.py +374 -0
  1293. web/routes/metrics.py +43 -0
  1294. web/routes/observability.py +400 -0
  1295. web/routes/patterns.py +227 -0
  1296. web/routes/presence.py +609 -0
  1297. web/routes/roles.py +446 -0
  1298. web/routes/scheduled.py +261 -0
  1299. web/routes/search.py +238 -0
  1300. web/routes/sessions.py +220 -0
  1301. web/routes/settings.py +363 -0
  1302. web/routes/stream.py +547 -0
  1303. web/security.py +157 -0
  1304. web/server.py +283 -0
@@ -0,0 +1,796 @@
1
+ #!/usr/bin/env python3
2
+ """branch-guard parser — detects branch-create or HEAD-rewriting git ops
3
+ in a Bash command and emits a verdict.
4
+
5
+ Stdin: {"tool_name": ..., "tool_input": {"command": "<bash cmd>"}}
6
+ Stdout: {"verdict": "allow"} OR
7
+ {"verdict": "block", "reason": "<rule-id>", "message": "<stderr msg>"}
8
+ Exit: 0 always — verdict in JSON is the signal (matches the pattern
9
+ used by other `_helpers/*.py` modules).
10
+
11
+ Why a Python helper instead of more bash: the parser must normalize
12
+ whitespace, strip git global options (`git -C path`, `git -c k=v`),
13
+ descend into nested `sh -c "..."` / `bash -c "..."`, split on shell
14
+ command separators, AND keep literal strings inside `echo`/`grep` args
15
+ from triggering — substring matching in bash slipped on all of these
16
+ (see TASK-013 reviewer probes). `shlex` handles quoting correctly.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import fnmatch
22
+ import json
23
+ import os
24
+ import re
25
+ import sys
26
+
27
+ from git_command_parse import (
28
+ abbrev_resolves,
29
+ command_groups,
30
+ commit_flags,
31
+ is_git_word,
32
+ normalize,
33
+ recover_indirect_commands,
34
+ resolve_command,
35
+ strip_env_vars,
36
+ strip_git_globals,
37
+ )
38
+
39
+ # Pre-subcommand git globals, kept local for the pr-mode-specific _git_dir_target
40
+ # below (the shared tokenizer's strip_git_globals already drops them for the
41
+ # subcommand lookup; this set lets _git_dir_target read the `-C`/--work-tree target).
42
+ _GLOBAL_OPTS_WITH_ARG = {"-C", "-c", "--git-dir", "--work-tree", "--namespace"}
43
+ _GLOBAL_OPTS_NO_ARG = {
44
+ "-p",
45
+ "--paginate",
46
+ "-P",
47
+ "--no-pager",
48
+ "--no-replace-objects",
49
+ "--bare",
50
+ "--no-optional-locks",
51
+ "--literal-pathspecs",
52
+ "--glob-pathspecs",
53
+ "--noglob-pathspecs",
54
+ "--icase-pathspecs",
55
+ }
56
+ _GLOBAL_LONG_EQ_PREFIXES = ("--git-dir=", "--work-tree=", "--namespace=", "-c=")
57
+
58
+
59
+ def _check_checkout(args: list[str]) -> tuple[str | None, str | None]:
60
+ # Branch create (-b/-B) — caught here too for consistency.
61
+ if any(a in {"-b", "-B"} for a in args):
62
+ return "branch-create-checkout", _MSG["branch-create"]
63
+ # File restore: `--` separator is present.
64
+ if "--" in args:
65
+ return None, None
66
+ arg = _first_positional(args)
67
+ if arg is None or arg in {"main", "HEAD", "."}:
68
+ return None, None
69
+ return "checkout-branch-switch", _MSG["checkout-switch"]
70
+
71
+
72
+ def _check_switch(args: list[str]) -> tuple[str | None, str | None]:
73
+ if any(a in {"-c", "-C"} for a in args):
74
+ return "branch-create-checkout", _MSG["branch-create"]
75
+ arg = _first_positional(args)
76
+ if arg is None or arg == "main":
77
+ return None, None
78
+ return "switch-branch", _MSG["switch-branch"]
79
+
80
+
81
+ def _check_branch(args: list[str]) -> tuple[str | None, str | None]:
82
+ # Plain create form `git branch <name> [<startpoint>]` — trunk forbids new
83
+ # branches.
84
+ if args and not args[0].startswith("-"):
85
+ return "branch-create", _MSG["branch-create"]
86
+ # Force-rewrite / rename / copy / delete TARGETING the integration or a
87
+ # protected ref (branch -f/-M/-C/-D main) corrupts the shared line — block at
88
+ # parity with pr-mode (BG-1), reusing its refspec-normalizing blocker. Other
89
+ # flagged forms (-d/-m/-v/--list on a feature branch) stay allowed.
90
+ if _pr_branch_blocks(args, _trunk_protected_refs()):
91
+ return "protected-ref-rewrite", _MSG["protected-ref-rewrite"]
92
+ return None, None
93
+
94
+
95
+ def _check_update_ref(args: list[str]) -> tuple[str | None, str | None]:
96
+ # `git update-ref` writes a ref directly; trunk previously had no checker for
97
+ # it (BG-2). Block writes/deletes of the integration/protected line OR HEAD
98
+ # (a direct HEAD move is an unguarded reset). Reuse pr-mode's blocker — it
99
+ # fails closed on --stdin — and add the HEAD guard on top.
100
+ positionals = _update_ref_positionals(args)
101
+ if positionals and _unqualify_ref(positionals[0]) == "HEAD":
102
+ return "protected-ref-rewrite", _MSG["protected-ref-rewrite"]
103
+ if _pr_update_ref_blocks(args, _trunk_protected_refs()):
104
+ return "protected-ref-rewrite", _MSG["protected-ref-rewrite"]
105
+ return None, None
106
+
107
+
108
+ def _check_worktree(args: list[str]) -> tuple[str | None, str | None]:
109
+ if args and args[0] == "add":
110
+ return "worktree-add", _MSG["branch-create"]
111
+ return None, None
112
+
113
+
114
+ def _check_rebase(args: list[str]) -> tuple[str | None, str | None]:
115
+ # Cleanup / inspection of an in-progress rebase doesn't rewrite history.
116
+ _SAFE_REBASE_FLAGS = {
117
+ "--abort",
118
+ "--continue",
119
+ "--skip",
120
+ "--quit",
121
+ "--edit-todo",
122
+ "--show-current-patch",
123
+ }
124
+ for a in args:
125
+ if a in _SAFE_REBASE_FLAGS:
126
+ return None, None
127
+ # Everything else (`git rebase main`, `-i HEAD~3`, bare → upstream)
128
+ # rewrites trunk history and breaks peers.
129
+ return "rebase-history-rewrite", _MSG["rebase-history"]
130
+
131
+
132
+ def _check_reset(args: list[str]) -> tuple[str | None, str | None]:
133
+ # Path-mode reset (`-p`, `--patch`, `--pathspec-from-file`, `--` separator)
134
+ # stages/unstages hunks — it NEVER moves HEAD, so it is always safe. git
135
+ # resolves any unambiguous prefix, so test `--pa…`/`--pat…` etc. by resolution,
136
+ # not a literal (`git reset --pa` → --patch was a bypass of the old `in {…}` set).
137
+ for a in args:
138
+ if a == "--" or a == "-p":
139
+ return None, None
140
+ if a.startswith("--") and (
141
+ abbrev_resolves(a, "--patch", _RESET_LONGS)
142
+ or abbrev_resolves(a, "--pathspec-from-file", _RESET_LONGS)
143
+ or abbrev_resolves(a, "--pathspec-file-nul", _RESET_LONGS)
144
+ ):
145
+ return None, None
146
+ # Strip ALL leading mode flags incl. abbreviations (`--har`→--hard,
147
+ # `--so`→--soft) and any other non-positional option, so the first POSITIONAL
148
+ # is reached — the old code stripped only a hardcoded literal set, so `--har`
149
+ # read as the first positional, hit the `startswith("--")` path-restore arm,
150
+ # and the HEAD-move slipped (the bypass this closes).
151
+ rest = [a for a in args if not a.startswith("-")]
152
+ if not rest:
153
+ return None, None # `git reset [--mode]` with no target — unstage, no HEAD move
154
+ first = rest[0]
155
+ if first == "HEAD":
156
+ return None, None # `reset HEAD` / `reset --mode HEAD` — HEAD does not move
157
+ return "reset-head-rewrite", _MSG["reset"]
158
+
159
+
160
+ # `git reset`'s long options — the competitor set for prefix disambiguation. A
161
+ # mode/HEAD-mover vs a path-mode marker only needs the options that share a prefix
162
+ # with the path-mode ones, but the full short list keeps `abbrev_resolves` honest
163
+ # if git adds a colliding option (e.g. a future `--pat*`).
164
+ _RESET_LONGS = frozenset(
165
+ {
166
+ "--soft",
167
+ "--mixed",
168
+ "--hard",
169
+ "--merge",
170
+ "--keep",
171
+ "--patch",
172
+ "--quiet",
173
+ "--no-quiet",
174
+ "--refresh",
175
+ "--no-refresh",
176
+ "--stdin",
177
+ "--pathspec-from-file",
178
+ "--pathspec-file-nul",
179
+ "--intent-to-add",
180
+ "--recurse-submodules",
181
+ }
182
+ )
183
+
184
+
185
+ # Accepts `-` (previous branch/ref) as a positional arg, plus any
186
+ # token that doesn't start with `-`.
187
+ def _first_positional(args: list[str]) -> str | None:
188
+ for a in args:
189
+ if a == "-":
190
+ return a
191
+ if not a.startswith("-"):
192
+ return a
193
+ return None
194
+
195
+
196
+ def _check_commit(args: list[str]) -> tuple[str | None, str | None]:
197
+ # Trunk requires explicit-path commits: `git commit -a/--all` stages every
198
+ # tracked modification, sweeping a concurrent session's WIP into this commit
199
+ # (git-workflow.md § The rule). Block the -a forms; `--amend`, `--author`,
200
+ # `--allow-empty`, `-m`, and explicit-path commits stay allowed.
201
+ short, longs = commit_flags(args)
202
+ if "a" in short or "--all" in longs:
203
+ return "commit-all-sweep", _MSG["commit-all"]
204
+ return None, None
205
+
206
+
207
+ def _check_filter(args: list[str]) -> tuple[str | None, str | None]:
208
+ # `git filter-branch` / `filter-repo` rewrite the ENTIRE history of the
209
+ # current branch (= main in trunk) — every published commit is replaced,
210
+ # orphaning every peer. No safe in-place form on a shared trunk.
211
+ return "history-rewrite", _MSG["history-rewrite"]
212
+
213
+
214
+ def _check_symbolic_ref(args: list[str]) -> tuple[str | None, str | None]:
215
+ # `git symbolic-ref HEAD <ref>` repoints HEAD (== a branch switch) and
216
+ # `--delete` detaches it — both move off main. A read form
217
+ # (`symbolic-ref HEAD`, `-q`, `--short`) names no target → allowed.
218
+ if any(a in {"-d", "--delete"} for a in args):
219
+ return "symbolic-ref-write", _MSG["protected-ref-rewrite"]
220
+ positionals = [a for a in args if not a.startswith("-")]
221
+ if len(positionals) >= 2: # <name> <new-target> → a write
222
+ return "symbolic-ref-write", _MSG["protected-ref-rewrite"]
223
+ return None, None
224
+
225
+
226
+ _DISPATCH = {
227
+ "checkout": _check_checkout,
228
+ "switch": _check_switch,
229
+ "branch": _check_branch,
230
+ "update-ref": _check_update_ref,
231
+ "worktree": _check_worktree,
232
+ "reset": _check_reset,
233
+ "rebase": _check_rebase,
234
+ "commit": _check_commit,
235
+ "filter-branch": _check_filter,
236
+ "filter-repo": _check_filter,
237
+ "symbolic-ref": _check_symbolic_ref,
238
+ }
239
+
240
+ _MSG = {
241
+ "branch-create": (
242
+ "BLOCKED: coding-os uses a trunk-based git workflow — commit\n"
243
+ "directly to main, do not create branches or worktrees.\n"
244
+ "\n"
245
+ " To fix: edit files, then 'git commit <explicit paths>' and\n"
246
+ " 'git pull --rebase origin main && git push origin main'.\n"
247
+ "\n"
248
+ " See src/core/rules/git-workflow.md for the full rule.\n"
249
+ " If the USER explicitly asked: enable pr-mode per-project (Hub →\n"
250
+ " Config → Git) or export COS_GIT_WORKFLOW=pr session-wide — an inline\n"
251
+ " 'COS_GIT_WORKFLOW=pr git …' prefix does NOT work (the guard reads its\n"
252
+ " own process env first)."
253
+ ),
254
+ "reset": (
255
+ "BLOCKED: this 'git reset' would move HEAD — in trunk mode\n"
256
+ "moving HEAD off a published commit clobbers peer work.\n"
257
+ "\n"
258
+ " Safe forms: 'git reset' (unstage), 'git reset --mixed HEAD',\n"
259
+ " 'git reset -- <path>' (unstage one path).\n"
260
+ " To undo the last commit: 'git revert HEAD' (new commit,\n"
261
+ " preserves history).\n"
262
+ "\n"
263
+ " See src/core/rules/git-workflow.md. pr-mode is enabled per-project\n"
264
+ " (Hub → Config → Git) or by exporting COS_GIT_WORKFLOW=pr session-wide\n"
265
+ " — an inline 'COS_GIT_WORKFLOW=pr git …' prefix does NOT work."
266
+ ),
267
+ "checkout-switch": (
268
+ "BLOCKED: this 'git checkout' switches branches — coding-os\n"
269
+ "uses a trunk-based workflow (main only).\n"
270
+ "\n"
271
+ " To restore a file: 'git restore <path>' or\n"
272
+ " 'git checkout -- <path>' (note the '--' separator).\n"
273
+ " To restore everything in cwd: 'git checkout .' is allowed.\n"
274
+ " To go to main: 'git switch main'.\n"
275
+ "\n"
276
+ " See src/core/rules/git-workflow.md. pr-mode is enabled per-project\n"
277
+ " (Hub → Config → Git) or by exporting COS_GIT_WORKFLOW=pr session-wide\n"
278
+ " — an inline 'COS_GIT_WORKFLOW=pr git …' prefix does NOT work."
279
+ ),
280
+ "switch-branch": (
281
+ "BLOCKED: this 'git switch' moves off main — coding-os uses\n"
282
+ "a trunk-based workflow.\n"
283
+ "\n"
284
+ " Only 'git switch main' is allowed in trunk mode.\n"
285
+ "\n"
286
+ " See src/core/rules/git-workflow.md. pr-mode is enabled per-project\n"
287
+ " (Hub → Config → Git) or by exporting COS_GIT_WORKFLOW=pr session-wide\n"
288
+ " — an inline 'COS_GIT_WORKFLOW=pr git …' prefix does NOT work."
289
+ ),
290
+ "rebase-history": (
291
+ "BLOCKED: 'git rebase' rewrites history on the shared trunk —\n"
292
+ "peer commits get orphaned and force-push is required.\n"
293
+ "\n"
294
+ " Safe forms (cleanup of an in-progress rebase):\n"
295
+ " git rebase --abort | --continue | --skip | --quit\n"
296
+ " To integrate concurrent commits before push:\n"
297
+ " git pull --rebase origin main (rebases LOCAL commits only)\n"
298
+ " To undo a bad commit:\n"
299
+ " git revert HEAD (new commit, history intact)\n"
300
+ "\n"
301
+ " See src/core/rules/git-workflow.md. pr-mode is enabled per-project\n"
302
+ " (Hub → Config → Git) or by exporting COS_GIT_WORKFLOW=pr session-wide\n"
303
+ " — an inline 'COS_GIT_WORKFLOW=pr git …' prefix does NOT work."
304
+ ),
305
+ "protected-ref-rewrite": (
306
+ "BLOCKED: this rewrites the protected integration ref directly\n"
307
+ "(git branch -f/-M/-C/-D main, git update-ref refs/heads/main or HEAD).\n"
308
+ "In trunk mode that clobbers the shared main line and every peer's history.\n"
309
+ "\n"
310
+ " To undo a published commit: 'git revert <sha>' — a new commit that\n"
311
+ " preserves history. Feature-branch admin must not target main.\n"
312
+ " See src/core/rules/git-workflow.md for the full rule."
313
+ ),
314
+ "commit-all": (
315
+ "BLOCKED: 'git commit -a/--all' stages every tracked modification —\n"
316
+ "in a multi-session checkout that sweeps another session's WIP into\n"
317
+ "your commit. Trunk requires EXPLICIT paths.\n"
318
+ "\n"
319
+ " To fix: stage what you mean, then 'git commit <explicit paths>'.\n"
320
+ " ('--amend', '--author', '--allow-empty', '-m' stay allowed.)\n"
321
+ " See src/core/rules/git-workflow.md § The rule."
322
+ ),
323
+ "history-rewrite": (
324
+ "BLOCKED: 'git filter-branch' / 'filter-repo' rewrites the ENTIRE\n"
325
+ "history of the current branch — on trunk that replaces every published\n"
326
+ "commit on main and orphans every peer's work.\n"
327
+ "\n"
328
+ " To undo specific commits: 'git revert <sha>' (new commits, history\n"
329
+ " preserved). A genuine history scrub is a human, force-push operation\n"
330
+ " done off the shared trunk. See src/core/rules/git-workflow.md."
331
+ ),
332
+ }
333
+
334
+
335
+ def _evaluate(command: str, _recover: bool = True) -> tuple[str, str, str]:
336
+ """Returns (verdict, reason, message). verdict is 'allow' or 'block'. Uses the
337
+ SHARED git_command_parse tokenizer (quote-aware AND `;`-aware) — no private
338
+ segmenter, so branch_guard and the commit/secret gates can never drift apart,
339
+ and a `;`/`(` inside a quoted commit message no longer false-splits (TASK-572)."""
340
+ groups = command_groups(normalize(command))
341
+ if not groups:
342
+ return "allow", "", ""
343
+ if os.environ.get("COS_GIT_WORKFLOW", "trunk") == "pr":
344
+ verdict = _evaluate_pr(groups)
345
+ else:
346
+ verdict = _evaluate_trunk(groups)
347
+ if verdict[0] == "block" or not _recover:
348
+ return verdict
349
+ # Shell-indirection backstop: a protected op hidden inside eval / pipe-into-sh /
350
+ # here-string / xargs is invisible to the tokenizer above. Recover each inner
351
+ # command string and re-evaluate it against the same rules — one level, since a
352
+ # recovered string is a plain git command.
353
+ for recovered in recover_indirect_commands(command):
354
+ r_verdict = _evaluate(recovered, _recover=False)
355
+ if r_verdict[0] == "block":
356
+ return r_verdict
357
+ return verdict
358
+
359
+
360
+ def _evaluate_trunk(groups: list[list[str]]) -> tuple[str, str, str]:
361
+ for g in groups:
362
+ # resolve_command strips a `VAR=val`/`env …`/`{` prefix; is_git_word accepts a
363
+ # path-qualified `/usr/bin/git`. `g` is already tokenized by command_groups.
364
+ _env, tokens = resolve_command(g)
365
+ if not tokens or not is_git_word(tokens[0]):
366
+ continue
367
+ tokens = strip_git_globals(tokens[1:])
368
+ if not tokens:
369
+ continue
370
+ subcmd, args = tokens[0], tokens[1:]
371
+ checker = _DISPATCH.get(subcmd)
372
+ if checker is None:
373
+ continue
374
+ reason, message = checker(args)
375
+ if reason:
376
+ return "block", reason, message or ""
377
+ return "allow", "", ""
378
+
379
+
380
+ # ---------------------------------------------------------------------------
381
+ # pr-mode policy (TASK-516) — COS_GIT_WORKFLOW=pr. A positive allow-list, NOT a
382
+ # guard-kill: branches and worktrees are the isolation mechanism, so they pass;
383
+ # what is BLOCKED is mutation of the SHARED integration checkout (direct commit,
384
+ # HEAD-rewrite) and any push to a protected/integration branch. HEAD-rewrites
385
+ # and commits are allowed when the command is scoped to a worktree.
386
+ # SPEC: docs/playbooks/pr-workflow.md § 5.
387
+ # ---------------------------------------------------------------------------
388
+ def _protected_branches() -> set[str]:
389
+ raw = os.environ.get("COS_GIT_PROTECTED_BRANCHES", "production")
390
+ return {b for b in re.split(r"[,\s]+", raw) if b}
391
+
392
+
393
+ def _trunk_protected_refs() -> set[str]:
394
+ # The refs trunk mode refuses to force-rewrite / rename / delete: the
395
+ # integration line (main) + any protected branch — the SAME set pr-mode
396
+ # guards, so neither mode is weaker than the other on ref integrity (BG-1/2).
397
+ integration = os.environ.get("COS_GIT_INTEGRATION_BRANCH", "main")
398
+ return _protected_branches() | {integration}
399
+
400
+
401
+ def _is_worktree_path(path: str) -> bool:
402
+ if not path:
403
+ return False
404
+ # Resolve symlinks AND `..` segments before comparing (Rule 5: macOS /tmp ↔
405
+ # /private/tmp); test ONLY the resolved path — a raw arm let a spoof like
406
+ # `.../worktrees/x/../../../realmain` (resolves INTO the shared checkout) pass.
407
+ real = os.path.realpath(path)
408
+ if "/.coding-os/worktrees/" in real:
409
+ return True
410
+ root = os.environ.get("COS_WORKTREE_ROOT", "")
411
+ if not root:
412
+ return False
413
+ root_real = os.path.realpath(root)
414
+ return real == root_real or real.startswith(root_real.rstrip("/") + "/")
415
+
416
+
417
+ def _current_dir() -> str:
418
+ try:
419
+ return os.getcwd()
420
+ except OSError:
421
+ return "" # cwd deleted out from under us — fall through to segment checks
422
+
423
+
424
+ def _worktree_scoped(groups: list[list[str]]) -> bool:
425
+ # Worktree scope for a git op with NO explicit -C: the process cwd is a
426
+ # worktree, or a `cd <worktree>` in the command line moved into one. An op
427
+ # WITH -C is scoped per-op from its own target in _evaluate_pr (finding 5).
428
+ cwd = _current_dir()
429
+ if cwd and _is_worktree_path(cwd):
430
+ return True
431
+ for g in groups:
432
+ toks = strip_env_vars(g)
433
+ if toks and toks[0] == "cd" and len(toks) >= 2 and _is_worktree_path(toks[1]):
434
+ return True
435
+ return False
436
+
437
+
438
+ # In-progress merge / cherry-pick cleanup flags — these don't advance a branch.
439
+ _SAFE_SEQUENCER_FLAGS = {"--abort", "--continue", "--skip", "--quit"}
440
+
441
+
442
+ def _unqualify_ref(ref: str) -> str:
443
+ # Map a `+force` / `refs/heads/` / `heads/` refspec to its bare branch name so
444
+ # it can't slip past a bare-name membership test. The `heads/` shorthand is a
445
+ # valid push destination git resolves to `refs/heads/` server-side, so it MUST
446
+ # normalize too (`refs/tags/` left intact — it's a tag).
447
+ ref = ref.lstrip("+")
448
+ # Strip the ref-namespace prefix REPEATEDLY: a doubled `refs/heads/refs/heads/x`
449
+ # (or `heads/heads/x`) must normalize to bare `x`, else the nested form slips the
450
+ # membership test and writes a protected branch (D1).
451
+ while True:
452
+ if ref.startswith("refs/heads/"):
453
+ ref = ref[len("refs/heads/") :]
454
+ elif ref.startswith("heads/"):
455
+ ref = ref[len("heads/") :]
456
+ else:
457
+ return ref
458
+
459
+
460
+ def _matches_blocked_ref(ref: str, blocked: set[str]) -> bool:
461
+ if not ref:
462
+ return False
463
+ bare = _unqualify_ref(ref)
464
+ return any(fnmatch.fnmatchcase(bare, _unqualify_ref(pattern)) for pattern in blocked)
465
+
466
+
467
+ def _push_targets(args: list[str], blocked: set[str]) -> bool:
468
+ # `--mirror` / `--all` push every local ref → can update the integration or a
469
+ # protected branch without naming it; treat as a protected-push (finding 15).
470
+ if any(a in {"--mirror", "--all"} for a in args):
471
+ return True
472
+ for a in args:
473
+ if a.startswith("-"):
474
+ continue
475
+ dst = a.rsplit(":", 1)[-1] if ":" in a else a
476
+ if _matches_blocked_ref(dst, blocked): # bare/+force/refs-heads forms all map here
477
+ return True
478
+ return False
479
+
480
+
481
+ def _push_names_explicit_dst(args: list[str]) -> bool:
482
+ # True when the push names at least one explicit destination ref that is not
483
+ # `HEAD` — i.e. it is provably NOT a bare/`HEAD`-only push that would advance
484
+ # whatever branch is currently checked out. `git push [remote] [refspec...]`:
485
+ # the first positional is the remote, the rest are refspecs.
486
+ positionals = [a for a in args if not a.startswith("-")]
487
+ for refspec in positionals[1:]:
488
+ dst = refspec.rsplit(":", 1)[-1] if ":" in refspec else refspec
489
+ if _unqualify_ref(dst) != "HEAD":
490
+ return True
491
+ return False
492
+
493
+
494
+ def _has_unsafe_push_default(global_tokens: list[str]) -> bool:
495
+ # `git -c push.default=matching push` makes a bare push update every same-name
496
+ # branch (incl. the integration line) and `current` pushes whatever is checked
497
+ # out — both can advance a blocked branch a refspec check never sees. The `-c`
498
+ # global is stripped before _pr_check, so it is inspected here on the raw tokens.
499
+ i = 0
500
+ while i < len(global_tokens):
501
+ t = global_tokens[i]
502
+ kv = None
503
+ if t == "-c" and i + 1 < len(global_tokens):
504
+ kv = global_tokens[i + 1]
505
+ i += 2
506
+ elif t.startswith("-c="):
507
+ kv = t[len("-c=") :]
508
+ i += 1
509
+ else:
510
+ i += 1
511
+ continue
512
+ key, _, val = kv.partition("=")
513
+ if key.strip() == "push.default" and val.strip() in {"matching", "current"}:
514
+ return True
515
+ return False
516
+
517
+
518
+ def _created_ref(subcmd: str, args: list[str]) -> str:
519
+ # The branch ref a checkout/switch force-creates or resets via -b/-B (checkout)
520
+ # or -b/-B/-c/-C (switch). "" when none (a plain switch onto an existing branch
521
+ # writes no ref). Plain `git checkout main` is a read-only switch → not a ref write.
522
+ flags = {"-b", "-B"} if subcmd == "checkout" else {"-b", "-B", "-c", "-C"}
523
+ for i, a in enumerate(args):
524
+ if a in flags and i + 1 < len(args):
525
+ return _unqualify_ref(args[i + 1])
526
+ return ""
527
+
528
+
529
+ def _worktree_add_branch(args: list[str]) -> str:
530
+ # The branch a `git worktree add` creates (`-b/-B <name>`) or checks out (the
531
+ # optional 2nd positional `git worktree add <path> <branch>`). "" when detached
532
+ # or based on a remote ref. Blocking this keeps the integration/protected line
533
+ # out of any worktree, so a worktree's HEAD is always a non-blocked branch.
534
+ for i, a in enumerate(args):
535
+ if a in {"-b", "-B"} and i + 1 < len(args):
536
+ return _unqualify_ref(args[i + 1])
537
+ positionals = [a for a in args if not a.startswith("-")]
538
+ if len(positionals) >= 2: # add <path> <branch>
539
+ return _unqualify_ref(positionals[1])
540
+ return ""
541
+
542
+
543
+ def _update_ref_positionals(args: list[str]) -> list[str]:
544
+ # Ref operands of `git update-ref`, dropping `-m <reason>`'s value (a reflog
545
+ # message, not a ref) so `update-ref -m main refs/heads/feature …` reads the
546
+ # ref operand, not the message (review finding B/D).
547
+ out: list[str] = []
548
+ skip = False
549
+ for a in args:
550
+ if skip:
551
+ skip = False
552
+ continue
553
+ if a in {"-m", "--reflog-message"}:
554
+ skip = True
555
+ continue
556
+ if not a.startswith("-"):
557
+ out.append(a)
558
+ return out
559
+
560
+
561
+ def _is_branch_filter_flag(arg: str) -> bool:
562
+ # `git branch` selectors whose ref/pattern operand is a FILTER, not a ref to
563
+ # write — present ⇒ a read-only list query, so a protected ref named as the
564
+ # filter must NOT block (review finding C: `branch --contains/--merged main`).
565
+ return arg.split("=", 1)[0] in {
566
+ "--contains",
567
+ "--no-contains",
568
+ "--merged",
569
+ "--no-merged",
570
+ "--points-at",
571
+ "--list",
572
+ }
573
+
574
+
575
+ def _pr_branch_blocks(args: list[str], blocked: set[str]) -> bool:
576
+ # Worktree scope is irrelevant — branch refs are shared across worktrees via
577
+ # the common dir, so a blocked target trips even from a worktree (agents/*
578
+ # create + `-D agents/...` cleanup still pass: only a blocked target trips).
579
+ if any(_is_branch_filter_flag(a) for a in args):
580
+ return False # read-only list/filter form — the ref operand is a filter
581
+ positionals = [a for a in args if not a.startswith("-")]
582
+ if not positionals:
583
+ return False
584
+ # Copy `-c/-C` writes only the TARGET (last positional); its source ref is
585
+ # read, not modified — `branch -c main backup` must not trip on `main`.
586
+ if any(a in {"-c", "-C", "--copy"} for a in args):
587
+ return _matches_blocked_ref(positionals[-1], blocked)
588
+ # Delete `-d/-D` and rename `-m/-M` put EVERY named ref at risk.
589
+ if any(a in {"-d", "-D", "--delete", "-m", "-M", "--move"} for a in args):
590
+ return any(_matches_blocked_ref(p, blocked) for p in positionals)
591
+ # Plain / force create-or-move: only the written ref (first positional).
592
+ return _matches_blocked_ref(positionals[0], blocked)
593
+
594
+
595
+ def _pr_update_ref_blocks(args: list[str], blocked: set[str]) -> bool:
596
+ if "--stdin" in args: # feeds ref commands we can't inspect → fail closed
597
+ return True
598
+ positionals = _update_ref_positionals(args)
599
+ return bool(positionals) and _matches_blocked_ref(positionals[0], blocked)
600
+
601
+
602
+ def _git_dir_target(global_tokens: list[str]) -> str | None:
603
+ # The path a git invocation is explicitly pointed at via -C / --work-tree /
604
+ # --git-dir (None = the ambient cwd). Scope is decided per git-op from THIS
605
+ # target, never command-globally, so `cd <wt> && git -C <main> reset` is
606
+ # judged against <main>, not the worktree cwd (finding 5).
607
+ i = 0
608
+ while i < len(global_tokens):
609
+ t = global_tokens[i]
610
+ if t in {"-C", "--work-tree", "--git-dir"} and i + 1 < len(global_tokens):
611
+ return global_tokens[i + 1]
612
+ matched_eq = [p for p in ("--work-tree=", "--git-dir=") if t.startswith(p)]
613
+ if matched_eq:
614
+ return t[len(matched_eq[0]) :]
615
+ if t in _GLOBAL_OPTS_WITH_ARG:
616
+ i += 2
617
+ continue
618
+ if t in _GLOBAL_OPTS_NO_ARG or any(t.startswith(p) for p in _GLOBAL_LONG_EQ_PREFIXES):
619
+ i += 1
620
+ continue
621
+ break
622
+ return None
623
+
624
+
625
+ def _evaluate_pr(groups: list[list[str]]) -> tuple[str, str, str]:
626
+ integration = os.environ.get("COS_GIT_INTEGRATION_BRANCH", "main")
627
+ blocked_push = _protected_branches() | {integration}
628
+ fallback_scope = _worktree_scoped(groups) # cwd/cd, for ops with no -C
629
+ for g in groups:
630
+ _env, tokens = resolve_command(g)
631
+ if not tokens or not is_git_word(tokens[0]):
632
+ continue
633
+ global_tokens = tokens[1:]
634
+ c_target = _git_dir_target(global_tokens)
635
+ sub = strip_git_globals(global_tokens)
636
+ if not sub:
637
+ continue
638
+ op_scope = _is_worktree_path(c_target) if c_target is not None else fallback_scope
639
+ reason, message = _pr_check(sub[0], sub[1:], op_scope, blocked_push)
640
+ if not reason and sub[0] == "push" and _has_unsafe_push_default(global_tokens):
641
+ reason, message = "pr-protected-push", _PR_MSG["protected-push"]
642
+ if reason:
643
+ return "block", reason, message or ""
644
+ return "allow", "", ""
645
+
646
+
647
+ def _pr_check(
648
+ subcmd: str, args: list[str], worktree: bool, blocked_push: set[str]
649
+ ) -> tuple[str | None, str | None]:
650
+ if subcmd == "push":
651
+ if _push_targets(args, blocked_push):
652
+ return "pr-protected-push", _PR_MSG["protected-push"]
653
+ # A bare / HEAD-only push from the shared checkout advances the integration
654
+ # line (its current branch is integration), outside PR+CI. Allow only when
655
+ # worktree-scoped (HEAD is agents/* there) or it names an explicit non-blocked
656
+ # destination refspec — the sanctioned `cos pr submit` does both.
657
+ if not worktree and not _push_names_explicit_dst(args):
658
+ return "pr-protected-push", _PR_MSG["protected-push"]
659
+ return None, None
660
+ if subcmd == "commit":
661
+ if worktree:
662
+ return None, None
663
+ return "pr-shared-commit", _PR_MSG["shared-commit"]
664
+ if subcmd in {"reset", "rebase"}:
665
+ reason, _ = _DISPATCH[subcmd](args)
666
+ if reason is None: # safe form (unstage/path/HEAD, rebase --abort/...)
667
+ return None, None
668
+ if worktree:
669
+ return None, None # HEAD-rewrite is fine inside an isolated worktree
670
+ return "pr-shared-head-rewrite", _PR_MSG["shared-head"]
671
+ if subcmd in {"merge", "cherry-pick"}:
672
+ # advancing HEAD on the shared checkout lands code outside PR+CI; a
673
+ # worktree only advances its own agents/* HEAD, so it's allowed.
674
+ if any(a in _SAFE_SEQUENCER_FLAGS for a in args):
675
+ return None, None # in-progress cleanup, not an advance
676
+ if worktree:
677
+ return None, None
678
+ # Sanctioned local_autonomous land (TASK-614): `cos pr land` exports COS_PR_LAND
679
+ # into the merge subprocess's ENV, so the guard reads it from os.environ. An
680
+ # agent's inline `COS_PR_LAND=1 git merge …` cannot forge it — resolve_command
681
+ # strips the inline assignment into _env, never os.environ (same protection as
682
+ # the COS_ALLOW_FORCE_PUSH_MAIN prefix guard).
683
+ if os.environ.get("COS_PR_LAND") == "1":
684
+ return None, None
685
+ return "pr-shared-head-rewrite", _PR_MSG["shared-head"]
686
+ if subcmd == "branch":
687
+ if _pr_branch_blocks(args, blocked_push):
688
+ return "pr-protected-ref", _PR_MSG["protected-ref"]
689
+ return None, None # agents/* create + delete stay allowed
690
+ if subcmd == "update-ref":
691
+ positionals = _update_ref_positionals(args)
692
+ if not worktree and positionals and _unqualify_ref(positionals[0]) == "HEAD":
693
+ return "pr-shared-head-rewrite", _PR_MSG["shared-head"]
694
+ if _pr_update_ref_blocks(args, blocked_push):
695
+ return "pr-protected-ref", _PR_MSG["protected-ref"]
696
+ return None, None
697
+ if subcmd in {"fetch", "pull"}:
698
+ # `git fetch/pull origin x:main` / `:production` writes a blocked LOCAL ref
699
+ # (pull is fetch+merge with identical refspec syntax); legit pr-mode fetches
700
+ # never use a colon, so a refspec with one whose destination is blocked is the
701
+ # leak. Refs are global → scope is moot (review finding 3).
702
+ for a in args:
703
+ if a.startswith("-") or ":" not in a:
704
+ continue
705
+ if _matches_blocked_ref(a.rsplit(":", 1)[-1], blocked_push):
706
+ return "pr-protected-ref", _PR_MSG["protected-ref"]
707
+ return None, None
708
+ if subcmd in {"checkout", "switch"}:
709
+ # -b/-B (checkout) or -b/-B/-c/-C (switch) force-create/reset a branch ref;
710
+ # a blocked target is a protected-ref write (refs are global, like branch -f).
711
+ if _matches_blocked_ref(_created_ref(subcmd, args), blocked_push):
712
+ return "pr-protected-ref", _PR_MSG["protected-ref"]
713
+ return None, None
714
+ if subcmd == "worktree":
715
+ # `git worktree add -b|-B <blocked>` or `... <path> <blocked>` would create or
716
+ # check the integration/protected line out into a worktree — refuse it so a
717
+ # worktree HEAD is always a non-blocked branch (keeps the push rule above safe).
718
+ if (
719
+ args
720
+ and args[0] == "add"
721
+ and _matches_blocked_ref(_worktree_add_branch(args[1:]), blocked_push)
722
+ ):
723
+ return "pr-protected-ref", _PR_MSG["protected-ref"]
724
+ return None, None
725
+ if subcmd in {"filter-branch", "filter-repo"}:
726
+ # History rewrite touches the shared object db + refs even from a worktree —
727
+ # always blocked (parity with trunk's history-rewrite guard, BG-1/BG-2).
728
+ return "pr-shared-head-rewrite", _PR_MSG["shared-head"]
729
+ if subcmd == "symbolic-ref":
730
+ # Repointing a worktree's OWN HEAD is isolated; on the shared checkout it
731
+ # is an off-integration switch outside PR+CI.
732
+ if _check_symbolic_ref(args)[0] is None:
733
+ return None, None
734
+ return (None, None) if worktree else ("pr-shared-head-rewrite", _PR_MSG["shared-head"])
735
+ # everything else: branches and worktrees are the pr-mode isolation mechanism — allowed.
736
+ return None, None
737
+
738
+
739
+ _PR_MSG = {
740
+ "shared-commit": (
741
+ "BLOCKED (pr-mode): direct commit on the shared integration checkout.\n"
742
+ " Every change must be isolated in a worktree.\n"
743
+ " To fix: 'cos pr open' (or 'cos pr open --adhoc' for no-task work),\n"
744
+ " then commit inside the worktree.\n"
745
+ " See docs/playbooks/pr-workflow.md § 5/§6."
746
+ ),
747
+ "shared-head": (
748
+ "BLOCKED (pr-mode): HEAD-rewrite (reset/rebase/merge/cherry-pick) on the\n"
749
+ "shared integration checkout corrupts the always-green integration line.\n"
750
+ " These are allowed INSIDE a worktree — scope the op with\n"
751
+ " 'git -C <worktree>' or 'cd <worktree> && …'.\n"
752
+ " See docs/playbooks/pr-workflow.md § 5."
753
+ ),
754
+ "protected-ref": (
755
+ "BLOCKED (pr-mode): this rewrites a protected/integration branch ref\n"
756
+ "directly (git branch -f/-D/-m / git update-ref). Branch refs are shared\n"
757
+ "across every worktree, so this corrupts the integration/production line\n"
758
+ "outside the PR+CI flow — worktree scope is NO protection here.\n"
759
+ " Agents mutate only their own 'agents/*' branch; land changes via a PR.\n"
760
+ " See docs/playbooks/pr-workflow.md § 5."
761
+ ),
762
+ "protected-push": (
763
+ "BLOCKED (pr-mode): push targets a protected/integration branch.\n"
764
+ " Agents push only to their own 'agents/*' branch, then open a PR.\n"
765
+ " To fix: 'git push --force-with-lease -u origin HEAD' from the\n"
766
+ " worktree branch, then open the PR ('cos pr open' / 'gh pr create').\n"
767
+ " See docs/playbooks/pr-workflow.md § 5/§11."
768
+ ),
769
+ }
770
+
771
+
772
+ def main() -> int:
773
+ try:
774
+ payload = json.load(sys.stdin)
775
+ except (json.JSONDecodeError, ValueError):
776
+ json.dump({"verdict": "allow"}, sys.stdout)
777
+ return 0
778
+ if payload.get("tool_name") != "Bash":
779
+ json.dump({"verdict": "allow"}, sys.stdout)
780
+ return 0
781
+ command = (payload.get("tool_input") or {}).get("command", "")
782
+ if not isinstance(command, str) or not command:
783
+ json.dump({"verdict": "allow"}, sys.stdout)
784
+ return 0
785
+
786
+ verdict, reason, message = _evaluate(command)
787
+ out: dict[str, str] = {"verdict": verdict}
788
+ if verdict == "block":
789
+ out["reason"] = reason
790
+ out["message"] = message
791
+ json.dump(out, sys.stdout)
792
+ return 0
793
+
794
+
795
+ if __name__ == "__main__":
796
+ sys.exit(main())