thth 5.6.2__tar.gz → 5.6.3__tar.gz

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 (845) hide show
  1. {thth-5.6.2 → thth-5.6.3}/PKG-INFO +3 -2
  2. {thth-5.6.2 → thth-5.6.3}/README.md +2 -1
  3. {thth-5.6.2 → thth-5.6.3}/mcp/server.py +29 -6
  4. {thth-5.6.2 → thth-5.6.3}/skills/thth/SKILL.md +7 -9
  5. thth-5.6.3/skills/thth-ads/SKILL.md +123 -0
  6. thth-5.6.3/skills/thth-flow/SKILL.md +91 -0
  7. thth-5.6.3/tests/test_ads_boost_563.py +93 -0
  8. thth-5.6.3/tests/test_ads_insights_engagement.py +124 -0
  9. thth-5.6.3/tests/test_ads_reads_563.py +194 -0
  10. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage4.py +14 -1
  11. {thth-5.6.2 → thth-5.6.3}/tests/test_packaging.py +2 -0
  12. thth-5.6.3/tests/test_skill_ads_doc.py +106 -0
  13. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_json_contract.py +2 -0
  14. thth-5.6.3/thth/VERSION +1 -0
  15. {thth-5.6.2 → thth-5.6.3}/thth/ads/cli.py +219 -14
  16. {thth-5.6.2 → thth-5.6.3}/thth/ads/graphread.py +346 -5
  17. {thth-5.6.2 → thth-5.6.3}/thth/ads/graphwrite.py +8 -1
  18. thth-5.6.3/thth/ads/guide.py +90 -0
  19. {thth-5.6.2 → thth-5.6.3}/thth/ads/ledger.py +18 -0
  20. {thth-5.6.2 → thth-5.6.3}/thth/ads/ops.py +52 -6
  21. thth-5.6.2/thth/VERSION +0 -1
  22. {thth-5.6.2 → thth-5.6.3}/.gitignore +0 -0
  23. {thth-5.6.2 → thth-5.6.3}/LICENSE +0 -0
  24. {thth-5.6.2 → thth-5.6.3}/accounts.example/bluesky.json +0 -0
  25. {thth-5.6.2 → thth-5.6.3}/accounts.example/facebook.json +0 -0
  26. {thth-5.6.2 → thth-5.6.3}/accounts.example/hatenablog.json +0 -0
  27. {thth-5.6.2 → thth-5.6.3}/accounts.example/instagram.json +0 -0
  28. {thth-5.6.2 → thth-5.6.3}/accounts.example/mastodon.json +0 -0
  29. {thth-5.6.2 → thth-5.6.3}/accounts.example/principal-hatena.json +0 -0
  30. {thth-5.6.2 → thth-5.6.3}/accounts.example/threads.json +0 -0
  31. {thth-5.6.2 → thth-5.6.3}/accounts.example/x.json +0 -0
  32. {thth-5.6.2 → thth-5.6.3}/bin/thth +0 -0
  33. {thth-5.6.2 → thth-5.6.3}/bin/thth-remote +0 -0
  34. {thth-5.6.2 → thth-5.6.3}/bin/thth-run +0 -0
  35. {thth-5.6.2 → thth-5.6.3}/pyproject.toml +0 -0
  36. {thth-5.6.2 → thth-5.6.3}/skills/thth/dashboard/README.md +0 -0
  37. {thth-5.6.2 → thth-5.6.3}/skills/thth/dashboard/all.html +0 -0
  38. {thth-5.6.2 → thth-5.6.3}/skills/thth/dashboard/campaign.html +0 -0
  39. {thth-5.6.2 → thth-5.6.3}/skills/thth/dashboard/project.html +0 -0
  40. {thth-5.6.2 → thth-5.6.3}/skills/thth/dashboard/series.html +0 -0
  41. {thth-5.6.2 → thth-5.6.3}/skills/thth-admin/SKILL.md +0 -0
  42. {thth-5.6.2 → thth-5.6.3}/systemd/thth@.service +0 -0
  43. {thth-5.6.2 → thth-5.6.3}/tests/__init__.py +0 -0
  44. {thth-5.6.2 → thth-5.6.3}/tests/conftest.py +0 -0
  45. {thth-5.6.2 → thth-5.6.3}/tests/coordination_snapshot.py +0 -0
  46. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/GraphemeBreakTest-17.0.0.txt +0 -0
  47. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/build_injection_eval.py +0 -0
  48. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/callback/worker_responses.json +0 -0
  49. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/injection_eval.json +0 -0
  50. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/limits_stage3/README.txt +0 -0
  51. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/limits_stage3/ledgers/vm-kopicha-hatenablog.json +0 -0
  52. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/limits_stage3/ledgers/vm-kopicha-x.json +0 -0
  53. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/limits_stage3/ledgers/vm-music-threads.json +0 -0
  54. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/limits_stage3/principals/vm-kopicha.json +0 -0
  55. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/scenario_v1_golden.json +0 -0
  56. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/twitter_text_v3_weighted.json +0 -0
  57. {thth-5.6.2 → thth-5.6.3}/tests/fixtures/umami-bile.md +0 -0
  58. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s1_flow_helpers.py +0 -0
  59. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s1_helpers.py +0 -0
  60. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s2_helpers.py +0 -0
  61. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s2_http.py +0 -0
  62. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s3_helpers.py +0 -0
  63. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s4_helpers.py +0 -0
  64. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s5_helpers.py +0 -0
  65. {thth-5.6.2 → thth-5.6.3}/tests/hatena_s6_helpers.py +0 -0
  66. {thth-5.6.2 → thth-5.6.3}/tests/helpers/__init__.py +0 -0
  67. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_oauth_server.py +0 -0
  68. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_push_adapter.py +0 -0
  69. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_redirect_server.py +0 -0
  70. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_search_adapter.py +0 -0
  71. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_threads_reader.py +0 -0
  72. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_threads_status.py +0 -0
  73. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_threads_writes.py +0 -0
  74. {thth-5.6.2 → thth-5.6.3}/tests/helpers/fake_x.py +0 -0
  75. {thth-5.6.2 → thth-5.6.3}/tests/helpers/hold_lock.py +0 -0
  76. {thth-5.6.2 → thth-5.6.3}/tests/helpers/hold_repo_lock.py +0 -0
  77. {thth-5.6.2 → thth-5.6.3}/tests/helpers/worker_probe.mjs +0 -0
  78. {thth-5.6.2 → thth-5.6.3}/tests/test_27_acceptance_fixes.py +0 -0
  79. {thth-5.6.2 → thth-5.6.3}/tests/test_account_name_check.py +0 -0
  80. {thth-5.6.2 → thth-5.6.3}/tests/test_account_report.py +0 -0
  81. {thth-5.6.2 → thth-5.6.3}/tests/test_accounts_dir.py +0 -0
  82. {thth-5.6.2 → thth-5.6.3}/tests/test_adapter_boundary.py +0 -0
  83. {thth-5.6.2 → thth-5.6.3}/tests/test_admin_http_mcp.py +0 -0
  84. {thth-5.6.2 → thth-5.6.3}/tests/test_admin_log.py +0 -0
  85. {thth-5.6.2 → thth-5.6.3}/tests/test_admin_notifications.py +0 -0
  86. {thth-5.6.2 → thth-5.6.3}/tests/test_admin_repairs.py +0 -0
  87. {thth-5.6.2 → thth-5.6.3}/tests/test_admin_report.py +0 -0
  88. {thth-5.6.2 → thth-5.6.3}/tests/test_after_cli.py +0 -0
  89. {thth-5.6.2 → thth-5.6.3}/tests/test_analytics_comparison.py +0 -0
  90. {thth-5.6.2 → thth-5.6.3}/tests/test_analytics_report.py +0 -0
  91. {thth-5.6.2 → thth-5.6.3}/tests/test_api_diagnostic.py +0 -0
  92. {thth-5.6.2 → thth-5.6.3}/tests/test_api_error_body.py +0 -0
  93. {thth-5.6.2 → thth-5.6.3}/tests/test_app_env_cli.py +0 -0
  94. {thth-5.6.2 → thth-5.6.3}/tests/test_approval.py +0 -0
  95. {thth-5.6.2 → thth-5.6.3}/tests/test_approve_cmd.py +0 -0
  96. {thth-5.6.2 → thth-5.6.3}/tests/test_ask.py +0 -0
  97. {thth-5.6.2 → thth-5.6.3}/tests/test_assess.py +0 -0
  98. {thth-5.6.2 → thth-5.6.3}/tests/test_atlas_fifth_review.py +0 -0
  99. {thth-5.6.2 → thth-5.6.3}/tests/test_atlas_fourth_review.py +0 -0
  100. {thth-5.6.2 → thth-5.6.3}/tests/test_atlas_review.py +0 -0
  101. {thth-5.6.2 → thth-5.6.3}/tests/test_atlas_second_review.py +0 -0
  102. {thth-5.6.2 → thth-5.6.3}/tests/test_atlas_third_review.py +0 -0
  103. {thth-5.6.2 → thth-5.6.3}/tests/test_audit1_fixes.py +0 -0
  104. {thth-5.6.2 → thth-5.6.3}/tests/test_audit2_fixes.py +0 -0
  105. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_b_counterexamples.py +0 -0
  106. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_b_m1_semantics.py +0 -0
  107. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_b_n1_depth.py +0 -0
  108. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_b_r1_closure.py +0 -0
  109. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_v201.py +0 -0
  110. {thth-5.6.2 → thth-5.6.3}/tests/test_audit_v23_details.py +0 -0
  111. {thth-5.6.2 → thth-5.6.3}/tests/test_auth.py +0 -0
  112. {thth-5.6.2 → thth-5.6.3}/tests/test_auth_identity_required.py +0 -0
  113. {thth-5.6.2 → thth-5.6.3}/tests/test_b17_remote_reads.py +0 -0
  114. {thth-5.6.2 → thth-5.6.3}/tests/test_behind_remote.py +0 -0
  115. {thth-5.6.2 → thth-5.6.3}/tests/test_bluesky_adapter.py +0 -0
  116. {thth-5.6.2 → thth-5.6.3}/tests/test_bluesky_secret_scrub.py +0 -0
  117. {thth-5.6.2 → thth-5.6.3}/tests/test_board_needs_review.py +0 -0
  118. {thth-5.6.2 → thth-5.6.3}/tests/test_board_running.py +0 -0
  119. {thth-5.6.2 → thth-5.6.3}/tests/test_branch_replies.py +0 -0
  120. {thth-5.6.2 → thth-5.6.3}/tests/test_bundle.py +0 -0
  121. {thth-5.6.2 → thth-5.6.3}/tests/test_bundle_not_type_mismatch.py +0 -0
  122. {thth-5.6.2 → thth-5.6.3}/tests/test_charcount.py +0 -0
  123. {thth-5.6.2 → thth-5.6.3}/tests/test_cli_entrypoint.py +0 -0
  124. {thth-5.6.2 → thth-5.6.3}/tests/test_cli_help.py +0 -0
  125. {thth-5.6.2 → thth-5.6.3}/tests/test_cli_vm_path.py +0 -0
  126. {thth-5.6.2 → thth-5.6.3}/tests/test_collect.py +0 -0
  127. {thth-5.6.2 → thth-5.6.3}/tests/test_collect_engagements.py +0 -0
  128. {thth-5.6.2 → thth-5.6.3}/tests/test_collect_runs.py +0 -0
  129. {thth-5.6.2 → thth-5.6.3}/tests/test_collect_sent.py +0 -0
  130. {thth-5.6.2 → thth-5.6.3}/tests/test_comparability.py +0 -0
  131. {thth-5.6.2 → thth-5.6.3}/tests/test_control_chars_refused.py +0 -0
  132. {thth-5.6.2 → thth-5.6.3}/tests/test_conversation_paging.py +0 -0
  133. {thth-5.6.2 → thth-5.6.3}/tests/test_count_for.py +0 -0
  134. {thth-5.6.2 → thth-5.6.3}/tests/test_docs_links.py +0 -0
  135. {thth-5.6.2 → thth-5.6.3}/tests/test_doctor.py +0 -0
  136. {thth-5.6.2 → thth-5.6.3}/tests/test_doctor_all_permissions.py +0 -0
  137. {thth-5.6.2 → thth-5.6.3}/tests/test_doctor_next_step.py +0 -0
  138. {thth-5.6.2 → thth-5.6.3}/tests/test_duplicate_front_matter_keys.py +0 -0
  139. {thth-5.6.2 → thth-5.6.3}/tests/test_editorial_audit.py +0 -0
  140. {thth-5.6.2 → thth-5.6.3}/tests/test_editorial_n3_n4.py +0 -0
  141. {thth-5.6.2 → thth-5.6.3}/tests/test_engagements.py +0 -0
  142. {thth-5.6.2 → thth-5.6.3}/tests/test_external_acceptance.py +0 -0
  143. {thth-5.6.2 → thth-5.6.3}/tests/test_facebook_adapter.py +0 -0
  144. {thth-5.6.2 → thth-5.6.3}/tests/test_facebook_auth.py +0 -0
  145. {thth-5.6.2 → thth-5.6.3}/tests/test_facebook_stage1.py +0 -0
  146. {thth-5.6.2 → thth-5.6.3}/tests/test_fake_api.py +0 -0
  147. {thth-5.6.2 → thth-5.6.3}/tests/test_form_spec.py +0 -0
  148. {thth-5.6.2 → thth-5.6.3}/tests/test_form_spec_cli.py +0 -0
  149. {thth-5.6.2 → thth-5.6.3}/tests/test_forms.py +0 -0
  150. {thth-5.6.2 → thth-5.6.3}/tests/test_fresh_install.py +0 -0
  151. {thth-5.6.2 → thth-5.6.3}/tests/test_front_matter_injection.py +0 -0
  152. {thth-5.6.2 → thth-5.6.3}/tests/test_healthcheck_notifications.py +0 -0
  153. {thth-5.6.2 → thth-5.6.3}/tests/test_hypotheses.py +0 -0
  154. {thth-5.6.2 → thth-5.6.3}/tests/test_hypothesis_boundaries.py +0 -0
  155. {thth-5.6.2 → thth-5.6.3}/tests/test_hypothesis_units.py +0 -0
  156. {thth-5.6.2 → thth-5.6.3}/tests/test_impact_cli.py +0 -0
  157. {thth-5.6.2 → thth-5.6.3}/tests/test_inbox_granted_scopes.py +0 -0
  158. {thth-5.6.2 → thth-5.6.3}/tests/test_incident_notifications.py +0 -0
  159. {thth-5.6.2 → thth-5.6.3}/tests/test_independent_thread_review.py +0 -0
  160. {thth-5.6.2 → thth-5.6.3}/tests/test_independent_topic_review.py +0 -0
  161. {thth-5.6.2 → thth-5.6.3}/tests/test_independent_topic_review_r2.py +0 -0
  162. {thth-5.6.2 → thth-5.6.3}/tests/test_inflight.py +0 -0
  163. {thth-5.6.2 → thth-5.6.3}/tests/test_inflight_tag_body_hash.py +0 -0
  164. {thth-5.6.2 → thth-5.6.3}/tests/test_jst.py +0 -0
  165. {thth-5.6.2 → thth-5.6.3}/tests/test_limits_policy.py +0 -0
  166. {thth-5.6.2 → thth-5.6.3}/tests/test_limits_stage2.py +0 -0
  167. {thth-5.6.2 → thth-5.6.3}/tests/test_limits_stage3.py +0 -0
  168. {thth-5.6.2 → thth-5.6.3}/tests/test_limits_stage4.py +0 -0
  169. {thth-5.6.2 → thth-5.6.3}/tests/test_lint.py +0 -0
  170. {thth-5.6.2 → thth-5.6.3}/tests/test_list_projections.py +0 -0
  171. {thth-5.6.2 → thth-5.6.3}/tests/test_llm_trial.py +0 -0
  172. {thth-5.6.2 → thth-5.6.3}/tests/test_llm_trial_engage.py +0 -0
  173. {thth-5.6.2 → thth-5.6.3}/tests/test_lock.py +0 -0
  174. {thth-5.6.2 → thth-5.6.3}/tests/test_m2_independent.py +0 -0
  175. {thth-5.6.2 → thth-5.6.3}/tests/test_maintain.py +0 -0
  176. {thth-5.6.2 → thth-5.6.3}/tests/test_mastodon_adapter.py +0 -0
  177. {thth-5.6.2 → thth-5.6.3}/tests/test_mastodon_visibility.py +0 -0
  178. {thth-5.6.2 → thth-5.6.3}/tests/test_max_per_run.py +0 -0
  179. {thth-5.6.2 → thth-5.6.3}/tests/test_mcp.py +0 -0
  180. {thth-5.6.2 → thth-5.6.3}/tests/test_mcp_robustness.py +0 -0
  181. {thth-5.6.2 → thth-5.6.3}/tests/test_measured.py +0 -0
  182. {thth-5.6.2 → thth-5.6.3}/tests/test_media_accounts.py +0 -0
  183. {thth-5.6.2 → thth-5.6.3}/tests/test_media_next_steps.py +0 -0
  184. {thth-5.6.2 → thth-5.6.3}/tests/test_media_registry.py +0 -0
  185. {thth-5.6.2 → thth-5.6.3}/tests/test_media_roundtrip.py +0 -0
  186. {thth-5.6.2 → thth-5.6.3}/tests/test_media_traits.py +0 -0
  187. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage0.py +0 -0
  188. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage2.py +0 -0
  189. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage3.py +0 -0
  190. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage5.py +0 -0
  191. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage5_1102.py +0 -0
  192. {thth-5.6.2 → thth-5.6.3}/tests/test_meta_stage6.py +0 -0
  193. {thth-5.6.2 → thth-5.6.3}/tests/test_mismatch_diagnostics.py +0 -0
  194. {thth-5.6.2 → thth-5.6.3}/tests/test_n5_reply_null_element.py +0 -0
  195. {thth-5.6.2 → thth-5.6.3}/tests/test_n6_replies_incomplete_ledger.py +0 -0
  196. {thth-5.6.2 → thth-5.6.3}/tests/test_n7_doctor_error_body.py +0 -0
  197. {thth-5.6.2 → thth-5.6.3}/tests/test_no_limits.py +0 -0
  198. {thth-5.6.2 → thth-5.6.3}/tests/test_observation_provenance.py +0 -0
  199. {thth-5.6.2 → thth-5.6.3}/tests/test_operations_handoff.py +0 -0
  200. {thth-5.6.2 → thth-5.6.3}/tests/test_preview.py +0 -0
  201. {thth-5.6.2 → thth-5.6.3}/tests/test_production_mode.py +0 -0
  202. {thth-5.6.2 → thth-5.6.3}/tests/test_pull_cli.py +0 -0
  203. {thth-5.6.2 → thth-5.6.3}/tests/test_pulse.py +0 -0
  204. {thth-5.6.2 → thth-5.6.3}/tests/test_queue.py +0 -0
  205. {thth-5.6.2 → thth-5.6.3}/tests/test_quiet_hours.py +0 -0
  206. {thth-5.6.2 → thth-5.6.3}/tests/test_r2_r4_r5.py +0 -0
  207. {thth-5.6.2 → thth-5.6.3}/tests/test_read_cli_bare_runtimeerror.py +0 -0
  208. {thth-5.6.2 → thth-5.6.3}/tests/test_reason_adoption.py +0 -0
  209. {thth-5.6.2 → thth-5.6.3}/tests/test_redact.py +0 -0
  210. {thth-5.6.2 → thth-5.6.3}/tests/test_redirect_token_leak.py +0 -0
  211. {thth-5.6.2 → thth-5.6.3}/tests/test_refresh.py +0 -0
  212. {thth-5.6.2 → thth-5.6.3}/tests/test_refresh_destination.py +0 -0
  213. {thth-5.6.2 → thth-5.6.3}/tests/test_rejudge_new.py +0 -0
  214. {thth-5.6.2 → thth-5.6.3}/tests/test_rejudge_r2_r3.py +0 -0
  215. {thth-5.6.2 → thth-5.6.3}/tests/test_replies.py +0 -0
  216. {thth-5.6.2 → thth-5.6.3}/tests/test_replies_refresh.py +0 -0
  217. {thth-5.6.2 → thth-5.6.3}/tests/test_repo_lock.py +0 -0
  218. {thth-5.6.2 → thth-5.6.3}/tests/test_repo_sync.py +0 -0
  219. {thth-5.6.2 → thth-5.6.3}/tests/test_report_checkout_import.py +0 -0
  220. {thth-5.6.2 → thth-5.6.3}/tests/test_report_http.py +0 -0
  221. {thth-5.6.2 → thth-5.6.3}/tests/test_report_isolation.py +0 -0
  222. {thth-5.6.2 → thth-5.6.3}/tests/test_report_service.py +0 -0
  223. {thth-5.6.2 → thth-5.6.3}/tests/test_retract_already_gone.py +0 -0
  224. {thth-5.6.2 → thth-5.6.3}/tests/test_reverse_audit.py +0 -0
  225. {thth-5.6.2 → thth-5.6.3}/tests/test_review_case_id_cluster_m2.py +0 -0
  226. {thth-5.6.2 → thth-5.6.3}/tests/test_review_case_id_cluster_r2.py +0 -0
  227. {thth-5.6.2 → thth-5.6.3}/tests/test_review_cli.py +0 -0
  228. {thth-5.6.2 → thth-5.6.3}/tests/test_review_evidence_account.py +0 -0
  229. {thth-5.6.2 → thth-5.6.3}/tests/test_review_form_spec_and_case_id.py +0 -0
  230. {thth-5.6.2 → thth-5.6.3}/tests/test_review_provenance.py +0 -0
  231. {thth-5.6.2 → thth-5.6.3}/tests/test_review_records.py +0 -0
  232. {thth-5.6.2 → thth-5.6.3}/tests/test_revoke.py +0 -0
  233. {thth-5.6.2 → thth-5.6.3}/tests/test_roundtrip.py +0 -0
  234. {thth-5.6.2 → thth-5.6.3}/tests/test_run_missing_env.py +0 -0
  235. {thth-5.6.2 → thth-5.6.3}/tests/test_run_record_failclosed.py +0 -0
  236. {thth-5.6.2 → thth-5.6.3}/tests/test_runs_collected.py +0 -0
  237. {thth-5.6.2 → thth-5.6.3}/tests/test_runs_read_rows.py +0 -0
  238. {thth-5.6.2 → thth-5.6.3}/tests/test_schedule_multiple.py +0 -0
  239. {thth-5.6.2 → thth-5.6.3}/tests/test_schedule_view.py +0 -0
  240. {thth-5.6.2 → thth-5.6.3}/tests/test_scopes_source_requested.py +0 -0
  241. {thth-5.6.2 → thth-5.6.3}/tests/test_search_engage_targets.py +0 -0
  242. {thth-5.6.2 → thth-5.6.3}/tests/test_search_media_routes.py +0 -0
  243. {thth-5.6.2 → thth-5.6.3}/tests/test_secret_value_redact.py +0 -0
  244. {thth-5.6.2 → thth-5.6.3}/tests/test_secrets_grep.py +0 -0
  245. {thth-5.6.2 → thth-5.6.3}/tests/test_security_small_fixes.py +0 -0
  246. {thth-5.6.2 → thth-5.6.3}/tests/test_select.py +0 -0
  247. {thth-5.6.2 → thth-5.6.3}/tests/test_selfupdate.py +0 -0
  248. {thth-5.6.2 → thth-5.6.3}/tests/test_send.py +0 -0
  249. {thth-5.6.2 → thth-5.6.3}/tests/test_send_cli.py +0 -0
  250. {thth-5.6.2 → thth-5.6.3}/tests/test_send_control_chars.py +0 -0
  251. {thth-5.6.2 → thth-5.6.3}/tests/test_send_guard_cli.py +0 -0
  252. {thth-5.6.2 → thth-5.6.3}/tests/test_send_media.py +0 -0
  253. {thth-5.6.2 → thth-5.6.3}/tests/test_send_visibility.py +0 -0
  254. {thth-5.6.2 → thth-5.6.3}/tests/test_sent_integrity.py +0 -0
  255. {thth-5.6.2 → thth-5.6.3}/tests/test_server_json.py +0 -0
  256. {thth-5.6.2 → thth-5.6.3}/tests/test_site.py +0 -0
  257. {thth-5.6.2 → thth-5.6.3}/tests/test_skill_doc.py +0 -0
  258. {thth-5.6.2 → thth-5.6.3}/tests/test_study_report.py +0 -0
  259. {thth-5.6.2 → thth-5.6.3}/tests/test_systemd.py +0 -0
  260. {thth-5.6.2 → thth-5.6.3}/tests/test_thread_publish.py +0 -0
  261. {thth-5.6.2 → thth-5.6.3}/tests/test_thread_read.py +0 -0
  262. {thth-5.6.2 → thth-5.6.3}/tests/test_threadrun.py +0 -0
  263. {thth-5.6.2 → thth-5.6.3}/tests/test_threads_read_permissions.py +0 -0
  264. {thth-5.6.2 → thth-5.6.3}/tests/test_threadshape.py +0 -0
  265. {thth-5.6.2 → thth-5.6.3}/tests/test_thth_root.py +0 -0
  266. {thth-5.6.2 → thth-5.6.3}/tests/test_token_exists.py +0 -0
  267. {thth-5.6.2 → thth-5.6.3}/tests/test_token_scopes_record.py +0 -0
  268. {thth-5.6.2 → thth-5.6.3}/tests/test_token_set.py +0 -0
  269. {thth-5.6.2 → thth-5.6.3}/tests/test_topic.py +0 -0
  270. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_advice.py +0 -0
  271. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_cli.py +0 -0
  272. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_models.py +0 -0
  273. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_review_fixes.py +0 -0
  274. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_shelf_observers.py +0 -0
  275. {thth-5.6.2 → thth-5.6.3}/tests/test_topic_store.py +0 -0
  276. {thth-5.6.2 → thth-5.6.3}/tests/test_topics_record_concurrent.py +0 -0
  277. {thth-5.6.2 → thth-5.6.3}/tests/test_topics_tool.py +0 -0
  278. {thth-5.6.2 → thth-5.6.3}/tests/test_trial_frictions.py +0 -0
  279. {thth-5.6.2 → thth-5.6.3}/tests/test_urgent_quiet_hours.py +0 -0
  280. {thth-5.6.2 → thth-5.6.3}/tests/test_v1015_path_semantics.py +0 -0
  281. {thth-5.6.2 → thth-5.6.3}/tests/test_v1015_take_what_we_can.py +0 -0
  282. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_admin_transaction.py +0 -0
  283. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_approve_account.py +0 -0
  284. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_length.py +0 -0
  285. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_lock_wait.py +0 -0
  286. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_mastodon_scopes.py +0 -0
  287. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_mentions.py +0 -0
  288. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_post_urls.py +0 -0
  289. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_repo_paths.py +0 -0
  290. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_reposts.py +0 -0
  291. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_study_add.py +0 -0
  292. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_tool_version.py +0 -0
  293. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_unanswered.py +0 -0
  294. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_unanswered_scope.py +0 -0
  295. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_where_arguments.py +0 -0
  296. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_where_filters.py +0 -0
  297. {thth-5.6.2 → thth-5.6.3}/tests/test_v210_who_arguments.py +0 -0
  298. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_auth_integration.py +0 -0
  299. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_authflow.py +0 -0
  300. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_bluesky_stdin.py +0 -0
  301. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_doctor_binding.py +0 -0
  302. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_mastodon_auth.py +0 -0
  303. {thth-5.6.2 → thth-5.6.3}/tests/test_v211_x_auth.py +0 -0
  304. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_ask_coordination.py +0 -0
  305. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_budget.py +0 -0
  306. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_budget_auth.py +0 -0
  307. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_budget_mcp.py +0 -0
  308. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_deletion.py +0 -0
  309. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_leave.py +0 -0
  310. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_leave_gate.py +0 -0
  311. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_leave_providers.py +0 -0
  312. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_leave_token_safety.py +0 -0
  313. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_mastodon_guide.py +0 -0
  314. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_mcp_compat.py +0 -0
  315. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_missing_token.py +0 -0
  316. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_read_coordination.py +0 -0
  317. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_relay.py +0 -0
  318. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_server_writes.py +0 -0
  319. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_token_parent.py +0 -0
  320. {thth-5.6.2 → thth-5.6.3}/tests/test_v212_write_storage.py +0 -0
  321. {thth-5.6.2 → thth-5.6.3}/tests/test_v2131_send_dry_run.py +0 -0
  322. {thth-5.6.2 → thth-5.6.3}/tests/test_v2131_threads_publish_wait.py +0 -0
  323. {thth-5.6.2 → thth-5.6.3}/tests/test_v2132_send_inflight_hint.py +0 -0
  324. {thth-5.6.2 → thth-5.6.3}/tests/test_v2132_threads_create_timeout.py +0 -0
  325. {thth-5.6.2 → thth-5.6.3}/tests/test_v2132_threads_create_unknown.py +0 -0
  326. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_acceptance_fixes.py +0 -0
  327. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_adts_asf.py +0 -0
  328. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_attachment_kinds.py +0 -0
  329. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_external.py +0 -0
  330. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_media.py +0 -0
  331. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_metadata.py +0 -0
  332. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_metadata_uri.py +0 -0
  333. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_metadata_video.py +0 -0
  334. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_record.py +0 -0
  335. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_record_video.py +0 -0
  336. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_video.py +0 -0
  337. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bluesky_webm_named.py +0 -0
  338. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_bmff_typed_metadata.py +0 -0
  339. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_budget_lock.py +0 -0
  340. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_capabilities.py +0 -0
  341. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_carryover_timeout.py +0 -0
  342. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_graphemes.py +0 -0
  343. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_auth_media.py +0 -0
  344. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_bmff_audio.py +0 -0
  345. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_flac.py +0 -0
  346. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_gif.py +0 -0
  347. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_link.py +0 -0
  348. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_media.py +0 -0
  349. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_mp3.py +0 -0
  350. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_ogg_opus.py +0 -0
  351. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_ogg_vorbis.py +0 -0
  352. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_poll.py +0 -0
  353. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_primary_size_boundary.py +0 -0
  354. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_quote.py +0 -0
  355. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_thumbnail.py +0 -0
  356. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_wav.py +0 -0
  357. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_webm_audio.py +0 -0
  358. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_mastodon_webm_video.py +0 -0
  359. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_cleanup.py +0 -0
  360. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_formats.py +0 -0
  361. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_foundation.py +0 -0
  362. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_prepared.py +0 -0
  363. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_relay.py +0 -0
  364. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_relay_refusals.py +0 -0
  365. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_media_upload.py +0 -0
  366. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_review_followups.py +0 -0
  367. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_stage810_audit.py +0 -0
  368. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_static_diagnostics.py +0 -0
  369. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_stop_observation.py +0 -0
  370. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_systemd_worker.py +0 -0
  371. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_ghost.py +0 -0
  372. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_gif.py +0 -0
  373. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_link.py +0 -0
  374. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_media.py +0 -0
  375. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_media_spoiler.py +0 -0
  376. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_poll.py +0 -0
  377. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_quote.py +0 -0
  378. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_quote_media.py +0 -0
  379. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_replies.py +0 -0
  380. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_text.py +0 -0
  381. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_text_spoiler.py +0 -0
  382. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_threads_video.py +0 -0
  383. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_transport_review.py +0 -0
  384. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_video_typed_metadata.py +0 -0
  385. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_vorbis_comment_boundary.py +0 -0
  386. {thth-5.6.2 → thth-5.6.3}/tests/test_v213_webm_schema_boundary.py +0 -0
  387. {thth-5.6.2 → thth-5.6.3}/tests/test_v2141_draft_lint_reason.py +0 -0
  388. {thth-5.6.2 → thth-5.6.3}/tests/test_v2141_managed_repo_umask.py +0 -0
  389. {thth-5.6.2 → thth-5.6.3}/tests/test_v214_release_signing.py +0 -0
  390. {thth-5.6.2 → thth-5.6.3}/tests/test_v214_x_adapter.py +0 -0
  391. {thth-5.6.2 → thth-5.6.3}/tests/test_v214_x_auth.py +0 -0
  392. {thth-5.6.2 → thth-5.6.3}/tests/test_v214_x_media.py +0 -0
  393. {thth-5.6.2 → thth-5.6.3}/tests/test_v214_x_posts_budget.py +0 -0
  394. {thth-5.6.2 → thth-5.6.3}/tests/test_v21b_approved_writes.py +0 -0
  395. {thth-5.6.2 → thth-5.6.3}/tests/test_v28_tags.py +0 -0
  396. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_docs.py +0 -0
  397. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_invite_admin_approval.py +0 -0
  398. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_invite_create.py +0 -0
  399. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_invite_credential.py +0 -0
  400. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_invite_limits.py +0 -0
  401. {thth-5.6.2 → thth-5.6.3}/tests/test_v3100_invite_worker.py +0 -0
  402. {thth-5.6.2 → thth-5.6.3}/tests/test_v310_morning.py +0 -0
  403. {thth-5.6.2 → thth-5.6.3}/tests/test_v310_search_timeout.py +0 -0
  404. {thth-5.6.2 → thth-5.6.3}/tests/test_v310_watch_words.py +0 -0
  405. {thth-5.6.2 → thth-5.6.3}/tests/test_v3111_observe_counts_only.py +0 -0
  406. {thth-5.6.2 → thth-5.6.3}/tests/test_v3111_observe_no_world.py +0 -0
  407. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_leave_same_user.py +0 -0
  408. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_mastodon_retract.py +0 -0
  409. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_morning_overdue.py +0 -0
  410. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_morning_own_exclusion.py +0 -0
  411. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_morning_unanswered_window.py +0 -0
  412. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_notifications_guidance.py +0 -0
  413. {thth-5.6.2 → thth-5.6.3}/tests/test_v311_replies_owned.py +0 -0
  414. {thth-5.6.2 → thth-5.6.3}/tests/test_v3120_activity.py +0 -0
  415. {thth-5.6.2 → thth-5.6.3}/tests/test_v3120_admin_write_reasons.py +0 -0
  416. {thth-5.6.2 → thth-5.6.3}/tests/test_v3120_guard.py +0 -0
  417. {thth-5.6.2 → thth-5.6.3}/tests/test_v3120_worker_version.py +0 -0
  418. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_leave_shared_token.py +0 -0
  419. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_own_handles_stopped.py +0 -0
  420. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_report_admin.py +0 -0
  421. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_report_channel.py +0 -0
  422. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_report_inbox.py +0 -0
  423. {thth-5.6.2 → thth-5.6.3}/tests/test_v312_report_mcp_user.py +0 -0
  424. {thth-5.6.2 → thth-5.6.3}/tests/test_v3140_api_relay.py +0 -0
  425. {thth-5.6.2 → thth-5.6.3}/tests/test_v3140_invite_key.py +0 -0
  426. {thth-5.6.2 → thth-5.6.3}/tests/test_v3140_remote_cli.py +0 -0
  427. {thth-5.6.2 → thth-5.6.3}/tests/test_v3140_server_reads.py +0 -0
  428. {thth-5.6.2 → thth-5.6.3}/tests/test_v3142_browser_login.py +0 -0
  429. {thth-5.6.2 → thth-5.6.3}/tests/test_v3143_activity_push.py +0 -0
  430. {thth-5.6.2 → thth-5.6.3}/tests/test_v3143_cli_umask_leave.py +0 -0
  431. {thth-5.6.2 → thth-5.6.3}/tests/test_v3143_inflight_remote.py +0 -0
  432. {thth-5.6.2 → thth-5.6.3}/tests/test_v3143_managed_repo_recover.py +0 -0
  433. {thth-5.6.2 → thth-5.6.3}/tests/test_v315_reactions.py +0 -0
  434. {thth-5.6.2 → thth-5.6.3}/tests/test_v317_run_lock_wait.py +0 -0
  435. {thth-5.6.2 → thth-5.6.3}/tests/test_v3180_json_names.py +0 -0
  436. {thth-5.6.2 → thth-5.6.3}/tests/test_v3180_map_timer.py +0 -0
  437. {thth-5.6.2 → thth-5.6.3}/tests/test_v3180_where_filters.py +0 -0
  438. {thth-5.6.2 → thth-5.6.3}/tests/test_v3180_where_keep.py +0 -0
  439. {thth-5.6.2 → thth-5.6.3}/tests/test_v3192_publish_hold.py +0 -0
  440. {thth-5.6.2 → thth-5.6.3}/tests/test_v31_analysis.py +0 -0
  441. {thth-5.6.2 → thth-5.6.3}/tests/test_v31_collection.py +0 -0
  442. {thth-5.6.2 → thth-5.6.3}/tests/test_v3200_x_weighted_length.py +0 -0
  443. {thth-5.6.2 → thth-5.6.3}/tests/test_v320_reply_to_file_display.py +0 -0
  444. {thth-5.6.2 → thth-5.6.3}/tests/test_v320_reply_to_file_lint.py +0 -0
  445. {thth-5.6.2 → thth-5.6.3}/tests/test_v320_reply_to_file_resolve.py +0 -0
  446. {thth-5.6.2 → thth-5.6.3}/tests/test_v320_report_fixes.py +0 -0
  447. {thth-5.6.2 → thth-5.6.3}/tests/test_v3220_account_scheduled.py +0 -0
  448. {thth-5.6.2 → thth-5.6.3}/tests/test_v3220_bluesky_reply_control.py +0 -0
  449. {thth-5.6.2 → thth-5.6.3}/tests/test_v3220_bluesky_retract.py +0 -0
  450. {thth-5.6.2 → thth-5.6.3}/tests/test_v3220_invite_mastodon.py +0 -0
  451. {thth-5.6.2 → thth-5.6.3}/tests/test_v3220_mentions_inbox.py +0 -0
  452. {thth-5.6.2 → thth-5.6.3}/tests/test_v3250_burst_reply_queue.py +0 -0
  453. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_fingerprint_version.py +0 -0
  454. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_held.py +0 -0
  455. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_held_names.py +0 -0
  456. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_last_refusals.py +0 -0
  457. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_notification_route.py +0 -0
  458. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_observe.py +0 -0
  459. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_report_friction.py +0 -0
  460. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_report_words.py +0 -0
  461. {thth-5.6.2 → thth-5.6.3}/tests/test_v330_reports_effect.py +0 -0
  462. {thth-5.6.2 → thth-5.6.3}/tests/test_v331_inflight_cli.py +0 -0
  463. {thth-5.6.2 → thth-5.6.3}/tests/test_v331_listing_resolve.py +0 -0
  464. {thth-5.6.2 → thth-5.6.3}/tests/test_v331_outbox_retention.py +0 -0
  465. {thth-5.6.2 → thth-5.6.3}/tests/test_v331_publish_status.py +0 -0
  466. {thth-5.6.2 → thth-5.6.3}/tests/test_v331_self_resolve.py +0 -0
  467. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_cli.py +0 -0
  468. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_docs.py +0 -0
  469. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_fields.py +0 -0
  470. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_mcp.py +0 -0
  471. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_morning.py +0 -0
  472. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_observe.py +0 -0
  473. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_open.py +0 -0
  474. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_open_confirm.py +0 -0
  475. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_reply.py +0 -0
  476. {thth-5.6.2 → thth-5.6.3}/tests/test_v340_plaza_store.py +0 -0
  477. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_docs.py +0 -0
  478. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_nodes.py +0 -0
  479. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_observe.py +0 -0
  480. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_plaza.py +0 -0
  481. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_retention.py +0 -0
  482. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_self.py +0 -0
  483. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_show.py +0 -0
  484. {thth-5.6.2 → thth-5.6.3}/tests/test_v350_map_world.py +0 -0
  485. {thth-5.6.2 → thth-5.6.3}/tests/test_v351_leave_timers.py +0 -0
  486. {thth-5.6.2 → thth-5.6.3}/tests/test_v351_plaza_open_holes.py +0 -0
  487. {thth-5.6.2 → thth-5.6.3}/tests/test_v351_who_owned.py +0 -0
  488. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_analytics.py +0 -0
  489. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_docs.py +0 -0
  490. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_observe_map.py +0 -0
  491. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_plaza.py +0 -0
  492. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_record.py +0 -0
  493. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_goal_send.py +0 -0
  494. {thth-5.6.2 → thth-5.6.3}/tests/test_v360_report_timeline.py +0 -0
  495. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_account_self_healing.py +0 -0
  496. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_approve_pending.py +0 -0
  497. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_click_attribution.py +0 -0
  498. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_collection_stale_basis.py +0 -0
  499. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_docs.py +0 -0
  500. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_follow_comparison.py +0 -0
  501. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_local_path.py +0 -0
  502. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_weekly_goals.py +0 -0
  503. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_where_aggregate.py +0 -0
  504. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_where_also.py +0 -0
  505. {thth-5.6.2 → thth-5.6.3}/tests/test_v370_where_zero.py +0 -0
  506. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_docs.py +0 -0
  507. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_digest.py +0 -0
  508. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_from.py +0 -0
  509. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_mcp.py +0 -0
  510. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_moments.py +0 -0
  511. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_owner.py +0 -0
  512. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_received.py +0 -0
  513. {thth-5.6.2 → thth-5.6.3}/tests/test_v380_plaza_triggers.py +0 -0
  514. {thth-5.6.2 → thth-5.6.3}/tests/test_v381_plaza_visibility_default.py +0 -0
  515. {thth-5.6.2 → thth-5.6.3}/tests/test_v382_confirm_file.py +0 -0
  516. {thth-5.6.2 → thth-5.6.3}/tests/test_v382_first_stage_not_refusal.py +0 -0
  517. {thth-5.6.2 → thth-5.6.3}/tests/test_v382_reader_lock_and_push_pending.py +0 -0
  518. {thth-5.6.2 → thth-5.6.3}/tests/test_v382_sync_without_fetch_head.py +0 -0
  519. {thth-5.6.2 → thth-5.6.3}/tests/test_v390_docs.py +0 -0
  520. {thth-5.6.2 → thth-5.6.3}/tests/test_v390_per_post_clicks.py +0 -0
  521. {thth-5.6.2 → thth-5.6.3}/tests/test_v390_where_rate.py +0 -0
  522. {thth-5.6.2 → thth-5.6.3}/tests/test_v390_where_suggest.py +0 -0
  523. {thth-5.6.2 → thth-5.6.3}/tests/test_v391_plaza_text_numbers.py +0 -0
  524. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_jikki_1017.py +0 -0
  525. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_jikki_1017_bookmark.py +0 -0
  526. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_approve.py +0 -0
  527. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_deliveries.py +0 -0
  528. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_events.py +0 -0
  529. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_fingerprints.py +0 -0
  530. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_guard.py +0 -0
  531. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_locks.py +0 -0
  532. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_principals.py +0 -0
  533. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_publish.py +0 -0
  534. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s1_remote.py +0 -0
  535. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_adapter.py +0 -0
  536. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_audit.py +0 -0
  537. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_audit_fixes.py +0 -0
  538. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_commit.py +0 -0
  539. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_convert.py +0 -0
  540. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_held.py +0 -0
  541. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_oauth1.py +0 -0
  542. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_principal_auth.py +0 -0
  543. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s2_syntax_readback.py +0 -0
  544. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s3_adapter.py +0 -0
  545. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s3_convert.py +0 -0
  546. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s3_flow.py +0 -0
  547. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s4_announce.py +0 -0
  548. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s4_audit_fixes.py +0 -0
  549. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s4_bookmark.py +0 -0
  550. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s4_ledger.py +0 -0
  551. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s5_audit_fixes.py +0 -0
  552. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s5_conflict.py +0 -0
  553. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s5_detect.py +0 -0
  554. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s5_guard_remote.py +0 -0
  555. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s5_jikki.py +0 -0
  556. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s6_audit_fixes.py +0 -0
  557. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s6_bundle.py +0 -0
  558. {thth-5.6.2 → thth-5.6.3}/tests/test_v400_s6_collect.py +0 -0
  559. {thth-5.6.2 → thth-5.6.3}/tests/test_v401_board_hatena_token.py +0 -0
  560. {thth-5.6.2 → thth-5.6.3}/tests/test_v401_bookmark_burst.py +0 -0
  561. {thth-5.6.2 → thth-5.6.3}/tests/test_v40_contract_json.py +0 -0
  562. {thth-5.6.2 → thth-5.6.3}/tests/test_v410_audit_night.py +0 -0
  563. {thth-5.6.2 → thth-5.6.3}/tests/test_v410_bookmark_batch.py +0 -0
  564. {thth-5.6.2 → thth-5.6.3}/tests/test_v411_batch_cleanup.py +0 -0
  565. {thth-5.6.2 → thth-5.6.3}/tests/test_v420_bookmark_edit.py +0 -0
  566. {thth-5.6.2 → thth-5.6.3}/tests/test_v420_bookmark_tag_bytes.py +0 -0
  567. {thth-5.6.2 → thth-5.6.3}/tests/test_v421_audit_fixes.py +0 -0
  568. {thth-5.6.2 → thth-5.6.3}/tests/test_v422_bookmark_rejections.py +0 -0
  569. {thth-5.6.2 → thth-5.6.3}/tests/test_v422_sparse_checkout.py +0 -0
  570. {thth-5.6.2 → thth-5.6.3}/tests/test_v430_reply_batch.py +0 -0
  571. {thth-5.6.2 → thth-5.6.3}/tests/test_v431_stopped_timer.py +0 -0
  572. {thth-5.6.2 → thth-5.6.3}/tests/test_v440_reply_follow.py +0 -0
  573. {thth-5.6.2 → thth-5.6.3}/tests/test_v441_approval_ledger.py +0 -0
  574. {thth-5.6.2 → thth-5.6.3}/tests/test_v442_sync_lookup.py +0 -0
  575. {thth-5.6.2 → thth-5.6.3}/tests/test_v450_x_full_archive.py +0 -0
  576. {thth-5.6.2 → thth-5.6.3}/tests/test_v452_schedule_stock.py +0 -0
  577. {thth-5.6.2 → thth-5.6.3}/tests/test_v453_approve_redo.py +0 -0
  578. {thth-5.6.2 → thth-5.6.3}/tests/test_v453_bookmark_gate.py +0 -0
  579. {thth-5.6.2 → thth-5.6.3}/tests/test_v454_schedule_thin.py +0 -0
  580. {thth-5.6.2 → thth-5.6.3}/tests/test_v455_media_inflight_published.py +0 -0
  581. {thth-5.6.2 → thth-5.6.3}/tests/test_v455_threads_publish_timeout.py +0 -0
  582. {thth-5.6.2 → thth-5.6.3}/tests/test_v456_not_after.py +0 -0
  583. {thth-5.6.2 → thth-5.6.3}/tests/test_v500_scenario.py +0 -0
  584. {thth-5.6.2 → thth-5.6.3}/tests/test_v50_audit_fixes.py +0 -0
  585. {thth-5.6.2 → thth-5.6.3}/tests/test_v50_dashboard.py +0 -0
  586. {thth-5.6.2 → thth-5.6.3}/tests/test_v50_joined.py +0 -0
  587. {thth-5.6.2 → thth-5.6.3}/tests/test_value_domains_shown.py +0 -0
  588. {thth-5.6.2 → thth-5.6.3}/tests/test_version.py +0 -0
  589. {thth-5.6.2 → thth-5.6.3}/tests/test_where_cli.py +0 -0
  590. {thth-5.6.2 → thth-5.6.3}/tests/test_where_threads_tag_author.py +0 -0
  591. {thth-5.6.2 → thth-5.6.3}/tests/test_who_cli.py +0 -0
  592. {thth-5.6.2 → thth-5.6.3}/tests/test_writeback_rebase.py +0 -0
  593. {thth-5.6.2 → thth-5.6.3}/tests/test_writeback_validate.py +0 -0
  594. {thth-5.6.2 → thth-5.6.3}/tests/test_x_community.py +0 -0
  595. {thth-5.6.2 → thth-5.6.3}/tests/test_x_list.py +0 -0
  596. {thth-5.6.2 → thth-5.6.3}/tests/test_x_metrics.py +0 -0
  597. {thth-5.6.2 → thth-5.6.3}/tests/test_x_owned_metrics.py +0 -0
  598. {thth-5.6.2 → thth-5.6.3}/tests/test_x_search_thread.py +0 -0
  599. {thth-5.6.2 → thth-5.6.3}/tests/test_x_token_autorefresh.py +0 -0
  600. {thth-5.6.2 → thth-5.6.3}/tests/test_x_trends_counts.py +0 -0
  601. {thth-5.6.2 → thth-5.6.3}/thth/__init__.py +0 -0
  602. {thth-5.6.2 → thth-5.6.3}/thth/__main__.py +0 -0
  603. {thth-5.6.2 → thth-5.6.3}/thth/_grapheme_data.py +0 -0
  604. {thth-5.6.2 → thth-5.6.3}/thth/account_cli.py +0 -0
  605. {thth-5.6.2 → thth-5.6.3}/thth/account_report.py +0 -0
  606. {thth-5.6.2 → thth-5.6.3}/thth/account_settings.py +0 -0
  607. {thth-5.6.2 → thth-5.6.3}/thth/accounts.py +0 -0
  608. {thth-5.6.2 → thth-5.6.3}/thth/activity.py +0 -0
  609. {thth-5.6.2 → thth-5.6.3}/thth/adapters/__init__.py +0 -0
  610. {thth-5.6.2 → thth-5.6.3}/thth/adapters/_x_text_data.py +0 -0
  611. {thth-5.6.2 → thth-5.6.3}/thth/adapters/auth_facebook.py +0 -0
  612. {thth-5.6.2 → thth-5.6.3}/thth/adapters/auth_instagram.py +0 -0
  613. {thth-5.6.2 → thth-5.6.3}/thth/adapters/auth_mastodon.py +0 -0
  614. {thth-5.6.2 → thth-5.6.3}/thth/adapters/auth_threads.py +0 -0
  615. {thth-5.6.2 → thth-5.6.3}/thth/adapters/auth_x.py +0 -0
  616. {thth-5.6.2 → thth-5.6.3}/thth/adapters/base.py +0 -0
  617. {thth-5.6.2 → thth-5.6.3}/thth/adapters/bluesky.py +0 -0
  618. {thth-5.6.2 → thth-5.6.3}/thth/adapters/bluesky_media.py +0 -0
  619. {thth-5.6.2 → thth-5.6.3}/thth/adapters/bluesky_video.py +0 -0
  620. {thth-5.6.2 → thth-5.6.3}/thth/adapters/facebook.py +0 -0
  621. {thth-5.6.2 → thth-5.6.3}/thth/adapters/fotolife.py +0 -0
  622. {thth-5.6.2 → thth-5.6.3}/thth/adapters/hatena_common.py +0 -0
  623. {thth-5.6.2 → thth-5.6.3}/thth/adapters/hatenablog.py +0 -0
  624. {thth-5.6.2 → thth-5.6.3}/thth/adapters/hatenabookmark.py +0 -0
  625. {thth-5.6.2 → thth-5.6.3}/thth/adapters/hatenastar.py +0 -0
  626. {thth-5.6.2 → thth-5.6.3}/thth/adapters/instagram.py +0 -0
  627. {thth-5.6.2 → thth-5.6.3}/thth/adapters/instagram_media.py +0 -0
  628. {thth-5.6.2 → thth-5.6.3}/thth/adapters/mastodon.py +0 -0
  629. {thth-5.6.2 → thth-5.6.3}/thth/adapters/mastodon_media.py +0 -0
  630. {thth-5.6.2 → thth-5.6.3}/thth/adapters/threads.py +0 -0
  631. {thth-5.6.2 → thth-5.6.3}/thth/adapters/threads_media.py +0 -0
  632. {thth-5.6.2 → thth-5.6.3}/thth/adapters/x.py +0 -0
  633. {thth-5.6.2 → thth-5.6.3}/thth/adapters/x_media.py +0 -0
  634. {thth-5.6.2 → thth-5.6.3}/thth/adapters/x_text.py +0 -0
  635. {thth-5.6.2 → thth-5.6.3}/thth/admin_diagnose.py +0 -0
  636. {thth-5.6.2 → thth-5.6.3}/thth/admin_log.py +0 -0
  637. {thth-5.6.2 → thth-5.6.3}/thth/admin_notifications.py +0 -0
  638. {thth-5.6.2 → thth-5.6.3}/thth/admin_report.py +0 -0
  639. {thth-5.6.2 → thth-5.6.3}/thth/ads/__init__.py +0 -0
  640. {thth-5.6.2 → thth-5.6.3}/thth/ads/auth.py +0 -0
  641. {thth-5.6.2 → thth-5.6.3}/thth/ads/budget.py +0 -0
  642. {thth-5.6.2 → thth-5.6.3}/thth/ads/digest.py +0 -0
  643. {thth-5.6.2 → thth-5.6.3}/thth/ads/watch.py +0 -0
  644. {thth-5.6.2 → thth-5.6.3}/thth/advise.py +0 -0
  645. {thth-5.6.2 → thth-5.6.3}/thth/after_cli.py +0 -0
  646. {thth-5.6.2 → thth-5.6.3}/thth/analytics_clicks.py +0 -0
  647. {thth-5.6.2 → thth-5.6.3}/thth/analytics_comparison.py +0 -0
  648. {thth-5.6.2 → thth-5.6.3}/thth/analytics_goals.py +0 -0
  649. {thth-5.6.2 → thth-5.6.3}/thth/analytics_report.py +0 -0
  650. {thth-5.6.2 → thth-5.6.3}/thth/analytics_shapes.py +0 -0
  651. {thth-5.6.2 → thth-5.6.3}/thth/analytics_threads.py +0 -0
  652. {thth-5.6.2 → thth-5.6.3}/thth/analytics_weekly.py +0 -0
  653. {thth-5.6.2 → thth-5.6.3}/thth/announce.py +0 -0
  654. {thth-5.6.2 → thth-5.6.3}/thth/api_diagnostic.py +0 -0
  655. {thth-5.6.2 → thth-5.6.3}/thth/api_requests.py +0 -0
  656. {thth-5.6.2 → thth-5.6.3}/thth/appconfig.py +0 -0
  657. {thth-5.6.2 → thth-5.6.3}/thth/appenv.py +0 -0
  658. {thth-5.6.2 → thth-5.6.3}/thth/approval.py +0 -0
  659. {thth-5.6.2 → thth-5.6.3}/thth/approval_ledger.py +0 -0
  660. {thth-5.6.2 → thth-5.6.3}/thth/approve_pending.py +0 -0
  661. {thth-5.6.2 → thth-5.6.3}/thth/archive_cli.py +0 -0
  662. {thth-5.6.2 → thth-5.6.3}/thth/article_cli.py +0 -0
  663. {thth-5.6.2 → thth-5.6.3}/thth/article_reactions.py +0 -0
  664. {thth-5.6.2 → thth-5.6.3}/thth/ask.py +0 -0
  665. {thth-5.6.2 → thth-5.6.3}/thth/ask_cli.py +0 -0
  666. {thth-5.6.2 → thth-5.6.3}/thth/assess.py +0 -0
  667. {thth-5.6.2 → thth-5.6.3}/thth/audioformats.py +0 -0
  668. {thth-5.6.2 → thth-5.6.3}/thth/auth_log.py +0 -0
  669. {thth-5.6.2 → thth-5.6.3}/thth/authclients.py +0 -0
  670. {thth-5.6.2 → thth-5.6.3}/thth/authflow.py +0 -0
  671. {thth-5.6.2 → thth-5.6.3}/thth/authpassword.py +0 -0
  672. {thth-5.6.2 → thth-5.6.3}/thth/bluesky_metadata.py +0 -0
  673. {thth-5.6.2 → thth-5.6.3}/thth/bookmark_batch.py +0 -0
  674. {thth-5.6.2 → thth-5.6.3}/thth/bookmark_cli.py +0 -0
  675. {thth-5.6.2 → thth-5.6.3}/thth/budget_x.py +0 -0
  676. {thth-5.6.2 → thth-5.6.3}/thth/budget_x_posts.py +0 -0
  677. {thth-5.6.2 → thth-5.6.3}/thth/bundle.py +0 -0
  678. {thth-5.6.2 → thth-5.6.3}/thth/burst_queue.py +0 -0
  679. {thth-5.6.2 → thth-5.6.3}/thth/cli.py +0 -0
  680. {thth-5.6.2 → thth-5.6.3}/thth/click_attribution.py +0 -0
  681. {thth-5.6.2 → thth-5.6.3}/thth/collect.py +0 -0
  682. {thth-5.6.2 → thth-5.6.3}/thth/collection_context.py +0 -0
  683. {thth-5.6.2 → thth-5.6.3}/thth/collection_status.py +0 -0
  684. {thth-5.6.2 → thth-5.6.3}/thth/community_cli.py +0 -0
  685. {thth-5.6.2 → thth-5.6.3}/thth/conflict_cli.py +0 -0
  686. {thth-5.6.2 → thth-5.6.3}/thth/core.py +0 -0
  687. {thth-5.6.2 → thth-5.6.3}/thth/dashboard_cli.py +0 -0
  688. {thth-5.6.2 → thth-5.6.3}/thth/deletion.py +0 -0
  689. {thth-5.6.2 → thth-5.6.3}/thth/deliveries.py +0 -0
  690. {thth-5.6.2 → thth-5.6.3}/thth/deliveries_cli.py +0 -0
  691. {thth-5.6.2 → thth-5.6.3}/thth/doctor.py +0 -0
  692. {thth-5.6.2 → thth-5.6.3}/thth/ebmlaudio.py +0 -0
  693. {thth-5.6.2 → thth-5.6.3}/thth/ebmlvideo.py +0 -0
  694. {thth-5.6.2 → thth-5.6.3}/thth/edit_cli.py +0 -0
  695. {thth-5.6.2 → thth-5.6.3}/thth/engagements.py +0 -0
  696. {thth-5.6.2 → thth-5.6.3}/thth/events_cli.py +0 -0
  697. {thth-5.6.2 → thth-5.6.3}/thth/fingerprint_golden.py +0 -0
  698. {thth-5.6.2 → thth-5.6.3}/thth/flacformats.py +0 -0
  699. {thth-5.6.2 → thth-5.6.3}/thth/forms.py +0 -0
  700. {thth-5.6.2 → thth-5.6.3}/thth/fotolife_cli.py +0 -0
  701. {thth-5.6.2 → thth-5.6.3}/thth/goals.py +0 -0
  702. {thth-5.6.2 → thth-5.6.3}/thth/graphemes.py +0 -0
  703. {thth-5.6.2 → thth-5.6.3}/thth/guard.py +0 -0
  704. {thth-5.6.2 → thth-5.6.3}/thth/handoff_cursor.py +0 -0
  705. {thth-5.6.2 → thth-5.6.3}/thth/hatena_bookmark.py +0 -0
  706. {thth-5.6.2 → thth-5.6.3}/thth/hatena_cli.py +0 -0
  707. {thth-5.6.2 → thth-5.6.3}/thth/hatena_conflict.py +0 -0
  708. {thth-5.6.2 → thth-5.6.3}/thth/hatena_convert.py +0 -0
  709. {thth-5.6.2 → thth-5.6.3}/thth/hatena_entry.py +0 -0
  710. {thth-5.6.2 → thth-5.6.3}/thth/hatena_fotolife.py +0 -0
  711. {thth-5.6.2 → thth-5.6.3}/thth/hatena_publish.py +0 -0
  712. {thth-5.6.2 → thth-5.6.3}/thth/hatena_reactions.py +0 -0
  713. {thth-5.6.2 → thth-5.6.3}/thth/healthcheck.py +0 -0
  714. {thth-5.6.2 → thth-5.6.3}/thth/httpsafe.py +0 -0
  715. {thth-5.6.2 → thth-5.6.3}/thth/incident.py +0 -0
  716. {thth-5.6.2 → thth-5.6.3}/thth/inflight.py +0 -0
  717. {thth-5.6.2 → thth-5.6.3}/thth/inflight_cli.py +0 -0
  718. {thth-5.6.2 → thth-5.6.3}/thth/inflight_resolve.py +0 -0
  719. {thth-5.6.2 → thth-5.6.3}/thth/invites.py +0 -0
  720. {thth-5.6.2 → thth-5.6.3}/thth/jst.py +0 -0
  721. {thth-5.6.2 → thth-5.6.3}/thth/leave.py +0 -0
  722. {thth-5.6.2 → thth-5.6.3}/thth/leave_gate.py +0 -0
  723. {thth-5.6.2 → thth-5.6.3}/thth/limits_config.py +0 -0
  724. {thth-5.6.2 → thth-5.6.3}/thth/limits_policy.py +0 -0
  725. {thth-5.6.2 → thth-5.6.3}/thth/limits_view.py +0 -0
  726. {thth-5.6.2 → thth-5.6.3}/thth/lint.py +0 -0
  727. {thth-5.6.2 → thth-5.6.3}/thth/list_cli.py +0 -0
  728. {thth-5.6.2 → thth-5.6.3}/thth/lock.py +0 -0
  729. {thth-5.6.2 → thth-5.6.3}/thth/maintain.py +0 -0
  730. {thth-5.6.2 → thth-5.6.3}/thth/managed_repo.py +0 -0
  731. {thth-5.6.2 → thth-5.6.3}/thth/map_cli.py +0 -0
  732. {thth-5.6.2 → thth-5.6.3}/thth/map_store.py +0 -0
  733. {thth-5.6.2 → thth-5.6.3}/thth/map_view.py +0 -0
  734. {thth-5.6.2 → thth-5.6.3}/thth/map_world.py +0 -0
  735. {thth-5.6.2 → thth-5.6.3}/thth/measured.py +0 -0
  736. {thth-5.6.2 → thth-5.6.3}/thth/media.py +0 -0
  737. {thth-5.6.2 → thth-5.6.3}/thth/media_capabilities.py +0 -0
  738. {thth-5.6.2 → thth-5.6.3}/thth/media_cleanup.py +0 -0
  739. {thth-5.6.2 → thth-5.6.3}/thth/media_cli.py +0 -0
  740. {thth-5.6.2 → thth-5.6.3}/thth/media_delivery.py +0 -0
  741. {thth-5.6.2 → thth-5.6.3}/thth/media_observations.py +0 -0
  742. {thth-5.6.2 → thth-5.6.3}/thth/media_registry.py +0 -0
  743. {thth-5.6.2 → thth-5.6.3}/thth/media_relay.py +0 -0
  744. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/bluesky.json +0 -0
  745. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/facebook.json +0 -0
  746. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/fotolife.json +0 -0
  747. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/hatenablog.json +0 -0
  748. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/hatenabookmark.json +0 -0
  749. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/instagram.json +0 -0
  750. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/mastodon.json +0 -0
  751. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/misskey.json +0 -0
  752. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/threads.json +0 -0
  753. {thth-5.6.2 → thth-5.6.3}/thth/media_traits/x.json +0 -0
  754. {thth-5.6.2 → thth-5.6.3}/thth/media_traits.py +0 -0
  755. {thth-5.6.2 → thth-5.6.3}/thth/media_uploads.py +0 -0
  756. {thth-5.6.2 → thth-5.6.3}/thth/mediaformats.py +0 -0
  757. {thth-5.6.2 → thth-5.6.3}/thth/meta/__init__.py +0 -0
  758. {thth-5.6.2 → thth-5.6.3}/thth/meta/errors.py +0 -0
  759. {thth-5.6.2 → thth-5.6.3}/thth/meta/graph.py +0 -0
  760. {thth-5.6.2 → thth-5.6.3}/thth/meta/media.py +0 -0
  761. {thth-5.6.2 → thth-5.6.3}/thth/meta/tokens.py +0 -0
  762. {thth-5.6.2 → thth-5.6.3}/thth/meta/usage.py +0 -0
  763. {thth-5.6.2 → thth-5.6.3}/thth/morning.py +0 -0
  764. {thth-5.6.2 → thth-5.6.3}/thth/mpeg_audio.py +0 -0
  765. {thth-5.6.2 → thth-5.6.3}/thth/notification_route.py +0 -0
  766. {thth-5.6.2 → thth-5.6.3}/thth/oauth.py +0 -0
  767. {thth-5.6.2 → thth-5.6.3}/thth/oauth1.py +0 -0
  768. {thth-5.6.2 → thth-5.6.3}/thth/oggformats.py +0 -0
  769. {thth-5.6.2 → thth-5.6.3}/thth/operations_handoff.py +0 -0
  770. {thth-5.6.2 → thth-5.6.3}/thth/plaza.py +0 -0
  771. {thth-5.6.2 → thth-5.6.3}/thth/plaza_cli.py +0 -0
  772. {thth-5.6.2 → thth-5.6.3}/thth/plaza_from.py +0 -0
  773. {thth-5.6.2 → thth-5.6.3}/thth/plaza_moments.py +0 -0
  774. {thth-5.6.2 → thth-5.6.3}/thth/plaza_observe.py +0 -0
  775. {thth-5.6.2 → thth-5.6.3}/thth/plaza_reads.py +0 -0
  776. {thth-5.6.2 → thth-5.6.3}/thth/plaza_redact.py +0 -0
  777. {thth-5.6.2 → thth-5.6.3}/thth/postid.py +0 -0
  778. {thth-5.6.2 → thth-5.6.3}/thth/principal_cli.py +0 -0
  779. {thth-5.6.2 → thth-5.6.3}/thth/principals.py +0 -0
  780. {thth-5.6.2 → thth-5.6.3}/thth/private_store.py +0 -0
  781. {thth-5.6.2 → thth-5.6.3}/thth/publish_hold.py +0 -0
  782. {thth-5.6.2 → thth-5.6.3}/thth/pulse.py +0 -0
  783. {thth-5.6.2 → thth-5.6.3}/thth/queuefile.py +0 -0
  784. {thth-5.6.2 → thth-5.6.3}/thth/quota_cli.py +0 -0
  785. {thth-5.6.2 → thth-5.6.3}/thth/reaction_cli.py +0 -0
  786. {thth-5.6.2 → thth-5.6.3}/thth/reactions.py +0 -0
  787. {thth-5.6.2 → thth-5.6.3}/thth/read_coordination.py +0 -0
  788. {thth-5.6.2 → thth-5.6.3}/thth/read_window.py +0 -0
  789. {thth-5.6.2 → thth-5.6.3}/thth/redact.py +0 -0
  790. {thth-5.6.2 → thth-5.6.3}/thth/refusals.py +0 -0
  791. {thth-5.6.2 → thth-5.6.3}/thth/relay.py +0 -0
  792. {thth-5.6.2 → thth-5.6.3}/thth/remote.py +0 -0
  793. {thth-5.6.2 → thth-5.6.3}/thth/replies.py +0 -0
  794. {thth-5.6.2 → thth-5.6.3}/thth/reply_follow.py +0 -0
  795. {thth-5.6.2 → thth-5.6.3}/thth/report.py +0 -0
  796. {thth-5.6.2 → thth-5.6.3}/thth/report_details.py +0 -0
  797. {thth-5.6.2 → thth-5.6.3}/thth/report_http.py +0 -0
  798. {thth-5.6.2 → thth-5.6.3}/thth/report_inbox.py +0 -0
  799. {thth-5.6.2 → thth-5.6.3}/thth/report_isolation.py +0 -0
  800. {thth-5.6.2 → thth-5.6.3}/thth/report_service.py +0 -0
  801. {thth-5.6.2 → thth-5.6.3}/thth/report_timeline.py +0 -0
  802. {thth-5.6.2 → thth-5.6.3}/thth/retract_cli.py +0 -0
  803. {thth-5.6.2 → thth-5.6.3}/thth/runs.py +0 -0
  804. {thth-5.6.2 → thth-5.6.3}/thth/scenario.py +0 -0
  805. {thth-5.6.2 → thth-5.6.3}/thth/scenario_cli.py +0 -0
  806. {thth-5.6.2 → thth-5.6.3}/thth/scopes.py +0 -0
  807. {thth-5.6.2 → thth-5.6.3}/thth/secrets_fs.py +0 -0
  808. {thth-5.6.2 → thth-5.6.3}/thth/select.py +0 -0
  809. {thth-5.6.2 → thth-5.6.3}/thth/selfupdate.py +0 -0
  810. {thth-5.6.2 → thth-5.6.3}/thth/sent.py +0 -0
  811. {thth-5.6.2 → thth-5.6.3}/thth/server_files.py +0 -0
  812. {thth-5.6.2 → thth-5.6.3}/thth/server_reads.py +0 -0
  813. {thth-5.6.2 → thth-5.6.3}/thth/server_writes.py +0 -0
  814. {thth-5.6.2 → thth-5.6.3}/thth/stop_observation.py +0 -0
  815. {thth-5.6.2 → thth-5.6.3}/thth/study_cli.py +0 -0
  816. {thth-5.6.2 → thth-5.6.3}/thth/study_report.py +0 -0
  817. {thth-5.6.2 → thth-5.6.3}/thth/summary_cli.py +0 -0
  818. {thth-5.6.2 → thth-5.6.3}/thth/systemd_gen.py +0 -0
  819. {thth-5.6.2 → thth-5.6.3}/thth/tags.py +0 -0
  820. {thth-5.6.2 → thth-5.6.3}/thth/thread_read.py +0 -0
  821. {thth-5.6.2 → thth-5.6.3}/thth/threadrun.py +0 -0
  822. {thth-5.6.2 → thth-5.6.3}/thth/threads_read_cli.py +0 -0
  823. {thth-5.6.2 → thth-5.6.3}/thth/threadshape.py +0 -0
  824. {thth-5.6.2 → thth-5.6.3}/thth/threadthrow.py +0 -0
  825. {thth-5.6.2 → thth-5.6.3}/thth/timer_cleanup.py +0 -0
  826. {thth-5.6.2 → thth-5.6.3}/thth/tool_version.py +0 -0
  827. {thth-5.6.2 → thth-5.6.3}/thth/topic_advice.py +0 -0
  828. {thth-5.6.2 → thth-5.6.3}/thth/topic_cli.py +0 -0
  829. {thth-5.6.2 → thth-5.6.3}/thth/topic_models.py +0 -0
  830. {thth-5.6.2 → thth-5.6.3}/thth/topic_store.py +0 -0
  831. {thth-5.6.2 → thth-5.6.3}/thth/topics.py +0 -0
  832. {thth-5.6.2 → thth-5.6.3}/thth/trends_cli.py +0 -0
  833. {thth-5.6.2 → thth-5.6.3}/thth/unanswered.py +0 -0
  834. {thth-5.6.2 → thth-5.6.3}/thth/vorbisformats.py +0 -0
  835. {thth-5.6.2 → thth-5.6.3}/thth/watch_cli.py +0 -0
  836. {thth-5.6.2 → thth-5.6.3}/thth/webhook.py +0 -0
  837. {thth-5.6.2 → thth-5.6.3}/thth/where_cli.py +0 -0
  838. {thth-5.6.2 → thth-5.6.3}/thth/where_keep.py +0 -0
  839. {thth-5.6.2 → thth-5.6.3}/thth/where_suggest.py +0 -0
  840. {thth-5.6.2 → thth-5.6.3}/thth/who_cli.py +0 -0
  841. {thth-5.6.2 → thth-5.6.3}/thth/worker.py +0 -0
  842. {thth-5.6.2 → thth-5.6.3}/thth/worker_version.py +0 -0
  843. {thth-5.6.2 → thth-5.6.3}/thth/writeback.py +0 -0
  844. {thth-5.6.2 → thth-5.6.3}/thth/x_archive.py +0 -0
  845. {thth-5.6.2 → thth-5.6.3}/thth/x_metrics.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: thth
3
- Version: 5.6.2
3
+ Version: 5.6.3
4
4
  Summary: 承認済みの投稿だけを投げる門(Threads・Bluesky・Mastodon)。人が承認し、記録は利用者の git に残る。
5
5
  Project-URL: Homepage, https://thth.me
6
6
  Project-URL: Source, https://github.com/aokings/thth
@@ -43,6 +43,7 @@ English: [README.en.md](README.en.md) · サイト: https://thth.me · 文書の
43
43
 
44
44
  - **調べる**: `thth topics <アカウント> --search <語>` で、その語の件数・投稿者の数・最新の投稿を見ます。`thth where` は「次にどこで話すか」を、自分がすでに絡んだ相手を重ねて探します。X の行には投稿者のフォロワー数(「フォロワー 1.2 万」)と投稿数も付きます(`--json` は `author_followers`・`author_posts`。保存しません)。
45
45
  - **出す**: `thth send` で今すぐ、`thth schedule` で予約、`--reply-to` で返信です。
46
+ - **広告の成績と手順の skill**(5.6.3・下書き): `thth ads insights` が反応の内訳(いいね・リアクション/コメント/シェア/写真を開いた/ページへのいいね)・サイトへの誘導(リンククリック・サイトへ出たクリック・頁が開いた)・1 件あたりの額・効率(frequency・cpm・ctr・cpc ほか Meta の計算済みの値)・動画の見られた深さを出します。`clicks` はリンクのクリックではありません。数が 0 か、計測が無くて分からないかを分けて書きます(`site.why`)。`--by age-gender|region|country|placement|device|hour` で内訳、`thth ads estimate` で出す前の見積もり、`thth ads doctor`・`show` でピクセルの有無と最後に動いた時刻を読みます(読むだけ)。`thth ads boost --utm-campaign <原稿のファイル名>` でリンクに有機の投稿と同じ campaign の UTM(`utm_medium=paid`)を付けます。広告を出す LLM 向けの手順は skill `thth-ads`(`skills/thth-ads/`・`thth ads skill --print`)で、広告の命令の次の一手(`next_steps`)とエラーの文は先頭でそれを示します([リリースノート 5.6.3(下書き)](docs/リリースノート_5.6.3_2026-11-03.md))。
46
47
  - **Meta の広告**(5.6.2): `thth ads boost` は全部 PAUSED で作り、始めるのは `thth ads activate` の 2 段だけです。`thth ads watch` は成績を読み続け、指定の額か表示数に達したら `thth ads stop` と同じに止めます(`--until` で必ず終わる)。`spend_cap`・月の上限・旗を上げる命令はありません。例外は 1 つで、止めた印を外す `thth ads resume` は 2 段+hub の承認の番号が必須です(masaru 11/02・外すのは印だけで、広告は PAUSED のまま)([リリースノート 5.6.2](docs/リリースノート_5.6.2_2026-11-02.md))。
47
48
  - **ブックマークの連投は記事と別に数える**(4.0.1): はてなブックマークは主体の別の窓(既定 10 分に 10 件)で数え、超えても主体を止めずにその 1 件だけ断ります。1 日 30 件・同じホストへ 1 日 3 件(自分の記事は 1 日 1 件のまま)。記事の連投で止める作りは変わりません([リリースノート 4.0.1](docs/リリースノート_4.0.1_2026-10-17.md))。
48
49
  - **X の全期間の検索**(4.5.0): `thth archive <口座> --from <handle> --title <曲名> [--max-total 20] [--json]` で 2006 年からの他人の公開投稿を読みます(id・URL・時刻・本文・handle・保存しない)。`--count-only` は件数だけ(1 回 0.010 USD)。返った本数で月の X 予算に数え、1 日の本数は `x_archive_daily_reads`(既定 0=読まない)で別に縛ります。timer からは叩きません([リリースノート 4.5.0](docs/リリースノート_4.5.0_2026-10-21.md))。
@@ -97,7 +98,7 @@ thth send <アカウント> --text "こんにちは"
97
98
  claude mcp add thth -- thth-mcp
98
99
  ```
99
100
 
100
- MCP の道具は CLI の写しで、同じ `thth` コマンドを呼ぶだけです。スキル(`skills/thth/`)は「投稿する前に何を見るか」「返信をどう扱うか」をアシスタントに教えます。キーはアシスタントに渡しません。`thth login` が手元に置いたキーを `thth` コマンドが使います。
101
+ MCP の道具は CLI の写しで、同じ `thth` コマンドを呼ぶだけです。スキル(`skills/thth/`)は「投稿する前に何を見るか」「返信をどう扱うか」をアシスタントに教えます。記事を軸に告知・セルクマ・広告までつなぐ流れと、印(UTM)・測り方は `skills/thth-flow/` が教えます。広告を出すときの手順は別のスキル(`skills/thth-ads/`・pip で入れた場合は `thth ads skill` が場所を出します)です。キーはアシスタントに渡しません。`thth login` が手元に置いたキーを `thth` コマンドが使います。
101
102
 
102
103
  ## ガード
103
104
 
@@ -19,6 +19,7 @@ English: [README.en.md](README.en.md) · サイト: https://thth.me · 文書の
19
19
 
20
20
  - **調べる**: `thth topics <アカウント> --search <語>` で、その語の件数・投稿者の数・最新の投稿を見ます。`thth where` は「次にどこで話すか」を、自分がすでに絡んだ相手を重ねて探します。X の行には投稿者のフォロワー数(「フォロワー 1.2 万」)と投稿数も付きます(`--json` は `author_followers`・`author_posts`。保存しません)。
21
21
  - **出す**: `thth send` で今すぐ、`thth schedule` で予約、`--reply-to` で返信です。
22
+ - **広告の成績と手順の skill**(5.6.3・下書き): `thth ads insights` が反応の内訳(いいね・リアクション/コメント/シェア/写真を開いた/ページへのいいね)・サイトへの誘導(リンククリック・サイトへ出たクリック・頁が開いた)・1 件あたりの額・効率(frequency・cpm・ctr・cpc ほか Meta の計算済みの値)・動画の見られた深さを出します。`clicks` はリンクのクリックではありません。数が 0 か、計測が無くて分からないかを分けて書きます(`site.why`)。`--by age-gender|region|country|placement|device|hour` で内訳、`thth ads estimate` で出す前の見積もり、`thth ads doctor`・`show` でピクセルの有無と最後に動いた時刻を読みます(読むだけ)。`thth ads boost --utm-campaign <原稿のファイル名>` でリンクに有機の投稿と同じ campaign の UTM(`utm_medium=paid`)を付けます。広告を出す LLM 向けの手順は skill `thth-ads`(`skills/thth-ads/`・`thth ads skill --print`)で、広告の命令の次の一手(`next_steps`)とエラーの文は先頭でそれを示します([リリースノート 5.6.3(下書き)](docs/リリースノート_5.6.3_2026-11-03.md))。
22
23
  - **Meta の広告**(5.6.2): `thth ads boost` は全部 PAUSED で作り、始めるのは `thth ads activate` の 2 段だけです。`thth ads watch` は成績を読み続け、指定の額か表示数に達したら `thth ads stop` と同じに止めます(`--until` で必ず終わる)。`spend_cap`・月の上限・旗を上げる命令はありません。例外は 1 つで、止めた印を外す `thth ads resume` は 2 段+hub の承認の番号が必須です(masaru 11/02・外すのは印だけで、広告は PAUSED のまま)([リリースノート 5.6.2](docs/リリースノート_5.6.2_2026-11-02.md))。
23
24
  - **ブックマークの連投は記事と別に数える**(4.0.1): はてなブックマークは主体の別の窓(既定 10 分に 10 件)で数え、超えても主体を止めずにその 1 件だけ断ります。1 日 30 件・同じホストへ 1 日 3 件(自分の記事は 1 日 1 件のまま)。記事の連投で止める作りは変わりません([リリースノート 4.0.1](docs/リリースノート_4.0.1_2026-10-17.md))。
24
25
  - **X の全期間の検索**(4.5.0): `thth archive <口座> --from <handle> --title <曲名> [--max-total 20] [--json]` で 2006 年からの他人の公開投稿を読みます(id・URL・時刻・本文・handle・保存しない)。`--count-only` は件数だけ(1 回 0.010 USD)。返った本数で月の X 予算に数え、1 日の本数は `x_archive_daily_reads`(既定 0=読まない)で別に縛ります。timer からは叩きません([リリースノート 4.5.0](docs/リリースノート_4.5.0_2026-10-21.md))。
@@ -73,7 +74,7 @@ thth send <アカウント> --text "こんにちは"
73
74
  claude mcp add thth -- thth-mcp
74
75
  ```
75
76
 
76
- MCP の道具は CLI の写しで、同じ `thth` コマンドを呼ぶだけです。スキル(`skills/thth/`)は「投稿する前に何を見るか」「返信をどう扱うか」をアシスタントに教えます。キーはアシスタントに渡しません。`thth login` が手元に置いたキーを `thth` コマンドが使います。
77
+ MCP の道具は CLI の写しで、同じ `thth` コマンドを呼ぶだけです。スキル(`skills/thth/`)は「投稿する前に何を見るか」「返信をどう扱うか」をアシスタントに教えます。記事を軸に告知・セルクマ・広告までつなぐ流れと、印(UTM)・測り方は `skills/thth-flow/` が教えます。広告を出すときの手順は別のスキル(`skills/thth-ads/`・pip で入れた場合は `thth ads skill` が場所を出します)です。キーはアシスタントに渡しません。`thth login` が手元に置いたキーを `thth` コマンドが使います。
77
78
 
78
79
  ## ガード
79
80
 
@@ -561,19 +561,26 @@ TOOLS += [
561
561
  # 広告(Meta 計画 段 5 の 7)。**出すのは show・boost(PAUSED まで)・pause・stop だけ。** 配信を始める
562
562
  # `activate`・延ばす `extend`・予算を下げる・終了日を早めるは MCP に出さない(始める・延ばすは CLI で masaru か
563
563
  # 運用が 2 段で押す)。`spend_cap`・月の上限・`ads_enabled` を上げる道具はどこにも無い(D-1)。
564
+ # 5.6.3(masaru 11/03「読めとかやれとか言う前に skills を提示するべき」): 広告の道具の説明は、まず skill を示す。
565
+ ADS_SKILL = ("まず広告の手順の skill thth-ads を読む(CLI `thth ads skill --print` で全文・repo の skills/thth-ads/SKILL.md・"
566
+ "pip では thth/skills/thth-ads/SKILL.md)。返る json の next_steps は先頭が skill、そのあとが個別の一手。")
567
+ ADS_PIXEL_FLOW = ("サイトへの誘導(objective traffic)は返る next_steps を上から読む: ピクセルが無ければイベントマネージャで作って"
568
+ "もらう・動いていなければ誘導先のサイトの repo にピクセルの基本のコードを入れ、thth ads doctor で動いたかを見る"
569
+ "(THTH はピクセルを作らない・サイトに触らない)。")
564
570
  ADS_NOTE = ("金額は最小単位の整数(JPY なら円)。お金が動くのは配信を始めたときだけで、始める(activate)・延ばす(extend)は "
565
571
  "MCP に無い(CLI で人が 2 段で押す)。spend_cap・上限を上げる道具も無い")
566
572
  ADS_TOOLS = [
567
573
  {"name": "thth_ads_show",
568
- "description": ("広告の口座を読む(thth ads show --json と同じ形・読むだけ)。spend_cap・amount_spent・動いている物・"
569
- "要対応(THTH の外で始まった配信・止めたと確かめられない ほか)。" + ADS_NOTE),
574
+ "description": (ADS_SKILL + "広告の口座を読む(thth ads show --json と同じ形・読むだけ)。spend_cap・amount_spent・"
575
+ "動いている物・ピクセル(pixels・pixel_ready)・要対応(THTH の外で始まった配信・止めたと確かめられない ほか)。"
576
+ + ADS_PIXEL_FLOW + ADS_NOTE),
570
577
  "inputSchema": {"type": "object", "properties": {
571
578
  "adaccount": {"type": "string", "description": "広告の口座の名前(例 kopicha-ads)"}},
572
579
  "required": ["adaccount"], "additionalProperties": False}},
573
580
  {"name": "thth_ads_boost",
574
- "description": ("ページの投稿を広告にする下書きを作る(キャンペーン・広告セット・クリエイティブ・広告を全部 PAUSED で作る・"
581
+ "description": (ADS_SKILL + "ページの投稿を広告にする下書きを作る(キャンペーン・広告セット・クリエイティブ・広告を全部 PAUSED で作る・"
575
582
  "お金は動かない)。終了日は必須。1 操作の上限(通しの予算・期間)を超える指定は作らない。"
576
- "始めるのは人が CLI で thth ads activate を 2 段で押す。" + ADS_NOTE),
583
+ "始めるのは人が CLI で thth ads activate を 2 段で押す。" + ADS_PIXEL_FLOW + ADS_NOTE),
577
584
  "inputSchema": {"type": "object", "properties": {
578
585
  "adaccount": {"type": "string", "description": "広告の口座の名前"},
579
586
  "post": {"type": "string", "description": "THTH で出したページの投稿の post_id(object_story_id とどちらか)"},
@@ -582,10 +589,18 @@ ADS_TOOLS = [
582
589
  "start": {"type": "string", "description": "開始(ISO 8601 か now・既定 now)"},
583
590
  "end": {"type": "string", "description": "終了(必須・ISO 8601)"},
584
591
  "platforms": {"type": "string", "description": "facebook か facebook,instagram(既定 facebook)"},
592
+ "objective": {"type": "string", "enum": ["engagement", "traffic", "reach"],
593
+ "description": "目的(既定 engagement。traffic=サイトへの誘導・reach=認知)"},
594
+ "url_tags": {"type": "string",
595
+ "description": "リンクに付ける印(クリエイティブの url_tags・例 utm_source=facebook&utm_medium=paid)"},
596
+ "utm_campaign": {"type": "string",
597
+ "description": "元の投稿の原稿のファイル名(拡張子なし)。url_tags が無ければ "
598
+ "utm_source=<出し先>&utm_medium=paid&utm_campaign=<これ> を付ける"},
599
+ "landing_url": {"type": "string", "description": "誘導先の頁の URL(次の一手の文に入る・Meta には送らない)"},
585
600
  "by": {"type": "string", "description": "打った人の名前(記録に残る)"}},
586
601
  "required": ["adaccount", "lifetime", "end", "by"], "additionalProperties": False}},
587
602
  {"name": "thth_ads_pause",
588
- "description": ("広告を止める(status=PAUSED・承認なし・止めた口座でも通す・量の制限で待たない)。all か ids のどちらか。"
603
+ "description": (ADS_SKILL + "広告を止める(status=PAUSED・承認なし・止めた口座でも通す・量の制限で待たない)。all か ids のどちらか。"
589
604
  "失敗した物があれば管理画面で止める"),
590
605
  "inputSchema": {"type": "object", "properties": {
591
606
  "adaccount": {"type": "string", "description": "広告の口座の名前"},
@@ -594,7 +609,7 @@ ADS_TOOLS = [
594
609
  "by": {"type": "string", "description": "打った人の名前"}},
595
610
  "required": ["adaccount", "by"], "additionalProperties": False}},
596
611
  {"name": "thth_ads_stop",
597
- "description": ("広告の口座を止める: 全部 PAUSED → THTH の止め → Meta から読み直して確かめる(処理中なら最大 30 秒待つ)"
612
+ "description": (ADS_SKILL + "広告の口座を止める: 全部 PAUSED → THTH の止め → Meta から読み直して確かめる(処理中なら最大 30 秒待つ)"
598
613
  " → spend_cap を使った額+少しの余白まで下げる。"
599
614
  "「止まった」と言うのは読み直しで確かめたときだけ。言えなければ hub に送る 1 行(waiting_on_masaru)を返すので、"
600
615
  "そのまま hub に送り、管理画面で止めてもらう"),
@@ -604,6 +619,9 @@ ADS_TOOLS = [
604
619
  "required": ["adaccount", "by"], "additionalProperties": False}},
605
620
  ]
606
621
  TOOLS += ADS_TOOLS
622
+ # MCP の instructions(initialize で返す)。広告は、まず skill を示す(5.6.3)。
623
+ MCP_INSTRUCTIONS = ("THTH は承認済みの投稿だけを投げる門。広告(thth_ads_*)を使う前に、" + ADS_SKILL
624
+ + "お金が動く始める・延ばすは MCP に無い(人が CLI で 2 段で押す)。")
607
625
 
608
626
 
609
627
  class ToolInputError(Exception):
@@ -1880,6 +1898,10 @@ def call_tool(name: str, arguments: dict | None) -> dict:
1880
1898
  args = ["ads", "boost", arguments["adaccount"], *target, "--lifetime", str(arguments["lifetime"]),
1881
1899
  "--start", arguments.get("start") or "now", "--end", arguments["end"],
1882
1900
  "--platforms", arguments.get("platforms") or "facebook",
1901
+ "--objective", arguments.get("objective") or "engagement",
1902
+ *(["--url-tags", arguments["url_tags"]] if arguments.get("url_tags") else []),
1903
+ *(["--landing-url", arguments["landing_url"]] if arguments.get("landing_url") else []),
1904
+ *(["--utm-campaign", arguments["utm_campaign"]] if arguments.get("utm_campaign") else []),
1883
1905
  "--by", arguments["by"], "--via", "mcp", "--json"]
1884
1906
  proc = run_cli(args)
1885
1907
  text = proc.stdout
@@ -1971,6 +1993,7 @@ def _handle_request(req: dict):
1971
1993
  "protocolVersion": "2024-11-05",
1972
1994
  "capabilities": {"tools": {}},
1973
1995
  "serverInfo": {"name": "thth", "version": "0.1.0"},
1996
+ "instructions": MCP_INSTRUCTIONS,
1974
1997
  },
1975
1998
  }
1976
1999
  if method == "notifications/initialized":
@@ -7,6 +7,8 @@ description: 投稿する前・返信を書く前・出したあと・絡みに
7
7
 
8
8
  **新しいセッションは最初に生きたコツ集を読む**(3.8.0): `thth_plaza_digest`(CLI は `thth plaza digest <project>`・読むだけ)。2 SNS以上で再現した施策・気づきが、再現しなかったSNSと試していないSNSも並んで(分母つき)出る(道具が付けた観測がある施策だけは置いたSNSも 1 と数え、各行に「数え方」が出る)。
9
9
 
10
+ **流れ全体(調べる→はてブ→はてなブログ→本体の記事→告知とセルクマ→広告)と印(UTM)・測り方は skill `thth-flow`(`skills/thth-flow/SKILL.md`)を先に見る。**
11
+
10
12
  **出来事と数だけを機械に読ませるときは `thth_events`・`thth_summary`**(4.0 の柱 1・読むだけ・媒体は呼ばない)。`thth events <project|account> --since 24h --json` は公開・取り下げ・届いた返信と言及・止まった口座・公開の結果待ち・予算切れ・予約の在庫切れの前触れ(`schedule_low`=最後の予約が 48 時間より手前・`schedule_thin`=1 日の本数が直近 7 日の平均の 6 割を切る日がある)を時刻順に(各行 `{schema: "thth.events/1", kind, account, occurred_at, recorded_at, ref, summary, event_id}`・他人の本文は入らない。続きは答えの `next_cursor` を `--after` に渡して読み、同じ出来事が 2 度来たら `event_id` で除く)、`thth summary <project|account> --json` は 24h・7d の公開数と反応の和・返していない返信・フォロワーの前日差・止まりを返す。`observe --json` の節は `sections_by_name.<名前>` で引く(`schema: "thth.observe/1"`。並びの `sections` は 4.0 で外す)。
11
13
 
12
14
  **断られたら・違和感があれば報告の口へ**: `thth_report_file`(CLI は `thth report file <account> --kind bug|request|friction --title … --body-file … --by <名前>`)。つまずき・迷い・期待との違いの報告は、利用者の作業の一部として歓迎します。小さいものも。重複は道具が束ねます。例: 「止まったのに気づかなかった」「断られた理由が分からなかった」「同じ操作を 3 回繰り返した」。道具が断った・結果が期待と違った・欲しい形がある・迷った(`friction`)、のどれかなら 1 回で置ける。**断られた直後なら、断りの最後の `report_channel:` の行をそのまま打てばよい**(`--from-last-refusal` が、道具が控えた直前の断り——時刻・版・コマンド・理由の符丁だけで、本文と引数の値は控えていない——を再現手順に添える。MCP は `thth_report_file {"account": …, "title": …, "from_last_refusal": true}`)。置いた報告がこの版で閉じたかは `thth_observe` の 0 段 `project_reports` に出る。返事は `thth_report_show` と `handoff-report --since-last-read` の `tool.reports` に出る。秘密らしき値が含まれていたら置かれない(伏せてから置き直す)。
@@ -77,7 +79,7 @@ THTH は CLI ツール。あなた(エージェント)が使う MCP の道
77
79
  ## キャンペーンとシリーズ(scenario・5.0 段 1)
78
80
 
79
81
  抜け・漏れ・忘れを 1 枚で見るための宣言。**THTH は読んで数えるだけ**(原稿を書かない・段を進めない・予約を置かない)。宣言は窓口が原稿の隣に書く: `docs/sns/scenarios/<id>.md`(queue の 1 つ上の `scenarios/`)。
80
- - キャンペーン(糸): front-matter に `thth_scenario: 1`・`kind: thread`・`id`(小文字・数字・`-`・`_`、ファイル名と同じ)・`title`・任意で `goal_text`(60 字まで)・`stale_after_days`(既定 7)・`started`(日付)。本文に段を上から順に 1 行ずつ `- <段>: <媒体> <条件>`(媒体は `hatena_bookmark`・`hatenablog`・`site`・`threads`・`x`・`bluesky`・`mastodon`・`facebook`、SNS は `threads,x` と並べられる。条件は `need=<本数>`・`tag=<タグ>`(はてブ・既定は id)・`signal=<出来事>`(site・既定 `article_published`)・`replies_within_hours=<時間>`(`warm`))。出来事は `- 2026-10-27 article_published <短い文>`(`researched`・`hypothesis`・`article_published`・`closed` など。`researched` は collect、`hypothesis` は diary の本数の代わりになる。`closed` で終わり)。
82
+ - キャンペーン(糸): front-matter に `thth_scenario: 1`・`kind: thread`・`id`(小文字・数字・`-`・`_`、ファイル名と同じ)・`title`・任意で `goal_text`(60 字まで)・`stale_after_days`(既定 7)・`started`(日付)。本文に段を上から順に 1 行ずつ `- <段>: <媒体> <条件>`(媒体は `hatena_bookmark`・`hatenablog`・`site`・`threads`・`x`・`bluesky`・`mastodon`・`facebook`・`instagram`、SNS は `threads,x` と並べられる。条件は `need=<本数>`・`tag=<タグ>`(はてブ・既定は id)・`signal=<出来事>`(site・既定 `article_published`)・`replies_within_hours=<時間>`(`warm`))。出来事は `- 2026-10-27 article_published <短い文>`(`researched`・`hypothesis`・`article_published`・`closed` など。`researched` は collect、`hypothesis` は diary の本数の代わりになる。`closed` で終わり)。
81
83
  - シリーズ(型): `kind: series`・`accounts: a, b`・`slots: tue 07:00, fri 07:00`(曜日を省けば毎日)・`stock_floor`(既定 2)・任意で `material_remaining`・`material_written_at`(窓口が書く数と日付)。期日の型は `deadline: true`(原稿の `not_after` を数える)。
82
84
  - 原稿の札: front-matter に `thread: <id>`・`series: <id>`。**承認の指紋に入らない**(付け足しても直しても再承認は要らない)。宣言が無い id は lint が `thread_not_declared`/`series_not_declared` の予告を出すだけ(断らない)。はてブはタグで結ぶ(札は書かない)。
83
85
  - 命令: `thth scenario <project|account> [--json]`(一覧・`schema: "thth.scenario/1"`)・`thth scenario show <project> <id> [--json]`(段ごとの原稿の名前と状態・出来事。キャンペーンは `stages[].items`(段ごとの成果物)、シリーズは `slots_upcoming`(今後 4 週の枠)、両方に `items[].delivery`・`post_ids` と `deliveries`)・`thth scenario lint <project> [--json]`(宣言の誤り・無い id を指す札・未分類の原稿)。`next` は名詞(「x に 1 本(announce)」「article_published を糸のファイルに 1 行」)で、本文は入らない。読めない台帳は `cannot_say`(0 と混ぜない)。
@@ -122,15 +124,11 @@ THTH は CLI ツール。あなた(エージェント)が使う MCP の道
122
124
  - **文字数の上限 2,200**(キャプションの公式の上限)。ハッシュタグ 30・@ 20 は媒体が数える。
123
125
  - **90 日ごとに `thth auth` をやり直す**: instagram の権限はデータに触れる期限(`data_access_expires_at`)に当たる見込み。14 日を切ると `thth maintain` が `data_access_expiring` と言う。
124
126
 
125
- ## 広告(Meta 計画 段 4〜5・10/31)
127
+ ## 広告(Meta 計画 段 4〜5・10/31〜)
126
128
 
127
- - 広告は投稿先の媒体ではないので `thth account` でなく `thth ads`。台帳は VM の `adaccounts/<名前>.json`(上限 `ceilings` は 0・`ads_enabled`/`production` は false が既定)、状態は `adaccount_state/<名前>/`。金額は**最小単位の整数**(JPY なら円)。
128
- - **上げる命令は無い**: `spend_cap` を上げる・外すのは masaru が広告マネージャで。月の上限・1 操作の上限(`lifetime_budget_max`・`days_max`)・`ads_enabled`・`production` を上げるのは VM の台帳を `cp -a` で控えてから直接書く。止めた口座を戻すのも VM(`adaccount_state/<名前>/guard/stopped.json` を控えてから消す)。この「上げられない・戻せない」は、VM の鍵と台帳を読める人以外に対しての柵(MCP からは越えられない)。
129
- - 読む: `thth ads add|auth|show|insights|doctor|accounts|collect`(段 4)。鍵が期限なし(`expires_at=0`)なら「期限なし」と言い、残り 14 日の柵はデータに触れる期限(`data_access_expires_at`)で効く。`thth ads doctor` は `/debug_token` の今の値で `.token` の期限の欄を書き直す。
130
- - 作る(お金は動かない): `thth ads boost <名前> --post <post_id>|--object-story-id <ページID>_<数字> --lifetime <額> --end <時刻> [--start now] [--platforms facebook,instagram] --by <名前>`。キャンペーン・広告セット・クリエイティブ・広告を**全部 `PAUSED`** で作る。終了日は必須・1 操作の上限を超える指定は作らない。MCP の `thth_ads_boost` も同じ。
131
- - **始める(お金が動く・CLI だけ)**: `thth ads activate <名前> <campaign_id> --by <名前>` が digest と木(予算・期間・広告)を出す → 人が見て hub で承認 → `--confirm <digest> --approval <hub の番号>` で 2 段目。2 段目で Meta から木を読み直し、変わっていれば `ads_tree_changed` で断る。月の上限の予約・`spend_cap` が入っていること・鍵の残り 14 日以上・`ads_enabled`・`production` が要る。延ばす・増やすは `thth ads extend`(同じ 2 段)。**MCP には無い。**
132
- - **止める(承認なし・止めた口座でも・量の制限で待たない)**: `thth ads stop <名前> --by <名前>` が全部 PAUSED → Meta から読み直して確かめる → `spend_cap` を使った額まで下げる → THTH の止め。**「止まった」と出なければ管理画面で止める**(出力の `waiting_on_masaru` の 1 行を hub に送る)。一部だけなら `thth ads pause <名前> --id <id>|--all`。減らす `thth ads budget lower <名前> --adset <id> --lifetime <額>`・早める `thth ads end <名前> <adset_id> --end <時刻>`・台帳の上限を下げる `thth ads budget lower <名前> --monthly <額>`。MCP は `thth_ads_pause`・`thth_ads_stop`。
133
- - 月の上限は**実支出で縛る**: 使った見積もり=口座の今月の実支出の全部+終わっていない予約の残り(月末に始めて翌月に続く配信も翌月に数える)。THTH の見積もり(`thth ads budget show`)は Meta の請求書ではない。THTH の承認(digest・hub の番号)は取り違えを防ぐ柵で、最後の柵は masaru が入れた `spend_cap` と終了日。
129
+ - **広告を出す・見張る・成績を読む・止めるときは、まず skill `thth-ads` を読む**(repo の `skills/thth-ads/SKILL.md`・`thth ads skill --print` で全文)。目的の決め方・見積もり・ピクセルと UTM・作る・人の承認・見張り・成績の読み方(0 と不明の違い)・止め方・報告の順と、お金の柵はそこにある。
130
+ - 広告は投稿先の媒体ではないので `thth account` でなく `thth ads`。金額は**最小単位の整数**(JPY なら円)。
131
+ - **お金が動く始める(`thth ads activate`)・延ばす(`thth ads extend`)は 2 段+人の承認の hub の番号・CLI だけ**。MCP の広告の道具は `thth_ads_show`・`thth_ads_boost`(全部 PAUSED で作る)・`thth_ads_pause`・`thth_ads_stop` だけ。`spend_cap`・上限・旗を上げる命令は無い。
134
132
  - 見張り(`thth events`・dashboard の要対応・`thth morning`): `ads_stop_unconfirmed`(`stop` が止まったと確かめられなかった・最優先)・`ads_active_outside_thth`(THTH の外で誰かが配信を始めた・最優先)・`ads_no_end_time`・`ads_account_status`・`ads_spend_cap_unset`・`ads_spend_cap_near`・`ads_budget_low`・`ads_spend_over_estimate`・`ads_token_expiring`(残り 14 日)・`ads_read_failed`。
135
133
 
136
134
  ## 何を拒むか
@@ -0,0 +1,123 @@
1
+ ---
2
+ name: thth-ads
3
+ description: THTH で Meta の広告(Facebook・Instagram)を 1 本出すとき、出した広告を見張る・成績を読む・止めるときに読む。目的の決め方から見積もり・ピクセルと UTM の確かめ・作る・人の承認・見張り・成績の読み方・止め方・報告までの順と、お金の柵。
4
+ ---
5
+
6
+ # 広告を 1 本出す(thth ads)
7
+
8
+ 届ける流れ全体(有機の投稿・セルクマ・広告に進む条件・印の決まり)は skill `thth-flow` にある(別の書き手が作る)。ここは広告の 1 本だけ。
9
+
10
+ 広告の命令は `thth ads …`。金額は**最小単位の整数**(JPY なら円)。この手順の本文は `thth ads skill --print` でいつでも出せる。広告の命令の「次の一手」(json の `next_steps`)とエラーの文は、先頭でこの skill を示し、そのあとに個別の一手を書く。`next_steps` は上から順に読む。
11
+
12
+ ## お金の柵(先に読む)
13
+
14
+ - **お金が動くのは配信を始めたときだけ。** 始める `thth ads activate` と延ばす・増やす `thth ads extend` は **2 段**で、2 段目に人(masaru)の承認の hub の番号が要る。LLM は 1 段目を打って digest と木を人に見せ、承認を待つ。**MCP には無い**(MCP の広告の道具は `thth_ads_show`・`thth_ads_boost`・`thth_ads_pause`・`thth_ads_stop` だけ)。
15
+ - **上げる命令は無い。** `spend_cap` を上げる・外す、月の上限・1 操作の上限(`lifetime_budget_max`・`days_max`)・`ads_enabled`・`production` を上げるのは THTH の外(`spend_cap` は管理画面で masaru、上限と旗は VM の台帳)。頼まれても THTH で上げる道を探さない。
16
+ - **`thth ads resume` は止めの印を外すだけの例外**(masaru 11/02)。2 段+hub の番号が要り、広告は PAUSED のまま。外したあと配信するには、もう一度 `activate` の 2 段を通す。
17
+ - **`spend_cap` の変更は 1 日 10 回まで**(Meta の決まり)。`stop` は `spend_cap` を使った額の近くまで下げるので、同じ日に `stop` を何度も打ち直さない。
18
+ - 止める(`thth ads pause`・`thth ads stop`)は承認なしで通る。迷ったら止める側に倒す。
19
+
20
+ ## 0. 口座の用意(人が VM で)
21
+
22
+ 広告の口座の台帳を書く `thth ads add` と鍵を取る `thth ads auth <広告の口座> --by <名前>` は人が VM で打つ(MCP には無い)。用意ができたかは `thth ads doctor <広告の口座>` で見る。
23
+
24
+ ## 1. 目的を決める
25
+
26
+ 人と次のどれかを決める。`thth ads boost` の `--objective` に入る。
27
+
28
+ - **反応**(いいね・コメント・シェア): `--objective engagement`(本番で確かめた)。
29
+ - **サイトへの誘導**: `--objective traffic`(本番未確認)。ピクセルと UTM を手順 3 で確かめる。
30
+ - **認知**(たくさんの人に見せる): `--objective reach`(本番未確認)。
31
+
32
+ ## 2. 出す前の見積もり(読むだけ)
33
+
34
+ ```
35
+ thth ads estimate <広告の口座> --targeting '{"geo_locations":{"countries":["JP"]},"age_min":18}' --goal LINK_CLICKS --json
36
+ ```
37
+
38
+ - `reach.users_lower_bound`〜`reach.users_upper_bound`: 狙う相手の人数の幅。-1 は「出せない」で、配信が止まる意味ではない。
39
+ - `delivery.daily_outcomes_curve`: 予算あたりの見込み。`delivery.confident` が false なら Meta に確度の高い予測が無い(全部 0 の 1 点)。
40
+ - `--goal` は `POST_ENGAGEMENT`・`LINK_CLICKS`・`LANDING_PAGE_VIEWS`・`REACH`・`IMPRESSIONS`。
41
+
42
+ ## 3. サイトへの誘導なら: ピクセルと UTM を確かめる
43
+
44
+ **ピクセルが要るかの判断の表**(入れるかは広告を出すときにこの表で決める):
45
+
46
+ | 広告の目的 | ピクセルが要るか | 無いとどうなるか |
47
+ |---|---|---|
48
+ | 反応(`--objective engagement`・最適化は POST_ENGAGEMENT) | 要らない | 何も欠けない(反応は `engagement` で読める) |
49
+ | サイトへの誘導(`--objective traffic`・最適化は LINK_CLICKS) | 無くても配信できる | `link_clicks`・`outbound_clicks` は読める。`landing_page_views`(頁が開いた)が測れず `not_measured_or_left` になる |
50
+ | 頁が開いた数で最適化(LANDING_PAGE_VIEWS) | 要るものとして扱う | THTH の boost はこの最適化で作らない(見積もり `--goal LANDING_PAGE_VIEWS` だけ)。Meta の公式の文書でピクセルが要るとは確かめられていない |
51
+
52
+ ピクセルをサイトに入れると Meta への外部送信が増える(サイトのプライバシーの頁の更新も要る)。**入れる前に masaru へ 1 行**(何のサイトに・どのピクセルを・なぜ)を送り、返事を待つ。
53
+
54
+ 1. `thth ads doctor <広告の口座> --json` の `next_steps` を読む(`thth ads show <広告の口座> --json` にも同じ欄がある)。
55
+ - `kind: pixel_create` … 広告アカウントにピクセルが無い。人にイベントマネージャでピクセルを作ってもらう(THTH からは作らない)。
56
+ - `kind: pixel_install` … ピクセルはあるが動いた記録が無い。**誘導先のサイトの repo で**、文に出ているピクセルの id の基本のコードを全部の頁の `<head>` に入れる(入れ方は文に出る公式の文書)。THTH はサイトのコードに触らない。
57
+ - `kind: pixel_check_page` … ピクセルは動いている。誘導先の頁にもコードが入っているかを確かめる。
58
+ - `kind: landing_url_unknown` … 誘導先の URL を `--landing-url` か台帳の `landing_url` に書くと、文に URL が入る。
59
+ 2. 入れたら `thth ads doctor <広告の口座>` を打ち直し、「ピクセル」の行が ○(最後に動いた時刻が出る)になるのを見る。
60
+ 3. **UTM**: 有機の投稿と同じ鍵にそろえる(10/27 に決まった形)。有機は `utm_source=<媒体>&utm_medium=social&utm_campaign=<原稿のファイル名、拡張子なし>`、広告は `utm_medium=paid` で campaign は同じ。`thth ads boost` の `--utm-campaign <元の投稿の原稿のファイル名、拡張子なし>` で `utm_source=<出し先の 1 つ目>&utm_medium=paid&utm_campaign=<それ>` を組む。違う形が要るときだけ `--url-tags 'key=value&key=value'`(無ければ台帳の `url_tags`)。どれもクリエイティブの `url_tags` として送られ、広告から押されたリンクに付く。口座名を campaign にしない(記事ごとに分けられない)。
61
+
62
+ ## 4. 作る(全部 PAUSED・お金は動かない)
63
+
64
+ ```
65
+ thth ads boost <広告の口座> --post <post_id> --lifetime <額> --end <終了の時刻> --objective traffic \
66
+ --utm-campaign <原稿のファイル名> --landing-url <誘導先の URL> --by <名前> --json
67
+ ```
68
+
69
+ - 投稿は `--post <post_id>`(THTH で出したページの投稿)か `--object-story-id <ページID>_<数字>`。
70
+ - `--end` は必須。1 操作の上限(通しの予算・期間)を越える指定は作らない。`--platforms facebook,instagram` で Instagram にも出す。
71
+ - 出力の `created`(キャンペーン・広告セット・クリエイティブ・広告の id)と `next_steps` を読む。サイトへの誘導でピクセルが動いていなければ、ここでも手順 3 の一手が出る。
72
+
73
+ ## 5. 人の承認を得て始める
74
+
75
+ 1. `thth ads activate <広告の口座> <campaign_id> --by <名前>` … 1 段目。digest と木(予算・期間・広告)が出る。**何も変わらない。**
76
+ 2. digest・予算・期間・見積もりを人に見せ、hub で承認の番号をもらう。
77
+ 3. `thth ads activate <広告の口座> <campaign_id> --confirm <digest> --approval <hub の番号> --by <名前>` … 2 段目(人か、人が許したときだけ)。Meta から木を読み直し、変わっていれば `ads_tree_changed` で断る。
78
+
79
+ ## 6. 見張る
80
+
81
+ ```
82
+ thth ads watch <広告の口座> <campaign_id> --stop-at-spend <額> --by <名前>
83
+ ```
84
+
85
+ - `--stop-at-spend <額>` か `--stop-at-impressions <数>` に達したら `thth ads stop` と同じに止める。指定なしなら配信が始まった(表示が 1 以上)ら知らせて終わる。`--interval <秒>`・`--until <時刻>` で間隔と終わりを決める。
86
+ - 終わりの表示に反応とサイトへの誘導の数も出る。
87
+ - 普段の見張りは `thth ads show <広告の口座>` と `thth events` の要対応(`ads_stop_unconfirmed`・`ads_active_outside_thth` は最優先)。
88
+
89
+ ## 7. 成績を読む
90
+
91
+ ```
92
+ thth ads insights <広告の口座> --preset maximum --level campaign --json
93
+ thth ads insights <広告の口座> --preset last_7d --by age-gender
94
+ ```
95
+
96
+ - `--preset` の `last_7d` などは**今日を含まない**。今日の分は `--preset today` か `--preset maximum`。`--since YYYY-MM-DD [--until YYYY-MM-DD]` でも読める。
97
+ - **反応** `engagement`: `reactions`(いいね・リアクション)・`comments`・`shares`・`photo_views`・`page_likes`。
98
+ - **サイトへの誘導** `site`: `link_clicks`・`outbound_clicks`(サイトへ出たクリック)・`landing_page_views`(頁が開いた)・`inline_link_clicks`。
99
+ - **1 件あたり** `cost_per`: 上の数ごとの spend ÷ 件数(0 件・不明は null)。
100
+ - **効率** `efficiency`(Meta の計算済み): `frequency`・`cpm`・`ctr`・`cpc`・`cost_per_unique_click`・`inline_link_click_ctr`・`cost_per_inline_link_click`・`outbound_clicks_ctr`・`cost_per_outbound_click`。
101
+ - **動画** `video`: `plays`・`p25`〜`p100`(見られた深さ)・`avg_time_watched`・`cost_per_thruplay`。動画でない広告では null。
102
+ - **内訳** `--by age-gender|region|country|placement|device|hour`: 1 区分 1 行。内訳つきは効率・動画を出さない。`hour` では reach が 0(Meta の決まり)。
103
+ - `actions`・`outbound_clicks_raw` は Meta の生の行。
104
+
105
+ **0 と不明を分けて読む**(`site.why` と `engagement_unknown`):
106
+
107
+ - `reported`: Meta が返した数。`zero_reported_list`: 並びに行が無い=0(Meta は 0 の行を出さない)。
108
+ - `no_link_clicks`: リンクが 1 度も押されていないので本当に 0。
109
+ - `not_measured_or_left`: リンクは押されたのに頁が開いた記録が無い。**0 と書かない**。頁の計測(ピクセル)が無いか、開く前に離れた。このとき `next_steps` にピクセルの一手が出る。
110
+ - `actions_missing`・`outbound_clicks_missing` など、値が null: 欄が無い=不明。
111
+ - `clicks` は広告のどこを押しても数える。**リンクのクリックではない**。サイトへの誘導は `site` を読む。
112
+ - 品質の評価(quality_ranking など)は THTH では読まない(公式の欄の一覧で名前を確かめられていない)。
113
+
114
+ ## 8. 止める
115
+
116
+ - 全部止める: `thth ads stop <広告の口座> --by <名前>`。全部 PAUSED → Meta から読み直して確かめる → `spend_cap` を下げる → THTH の止め。「止まった」と出なければ管理画面で止めてもらう(出力の `waiting_on_masaru` の 1 行を hub へ)。
117
+ - 一部だけ: `thth ads pause <広告の口座> --id <id>`(`--all` で全部)。
118
+ - 減らす: `thth ads budget lower <広告の口座> --adset <id> --lifetime <額>`。早く終える: `thth ads end <広告の口座> <adset_id> --end <時刻|now> --by <名前>`。
119
+ - 今月の見積もり: `thth ads budget show <広告の口座>`(Meta の請求書ではない)。
120
+
121
+ ## 9. 人への報告
122
+
123
+ 1 本ごとに、次を短く渡す: 目的・期間・使った額(`spend`)・表示とリーチ・反応の内訳・サイトへの誘導(リンククリック・サイトへ出たクリック・頁が開いた)と 1 件あたり・**0 か不明か**(不明ならその理由と `next_steps` の一手)・止めたか。数は `thth ads insights … --json` の値をそのまま書き、推して埋めない。
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: thth-flow
3
+ description: 記事を軸に「調べる→はてブ→はてなブログ→本体の記事→告知とセルクマ→広告」を回すとき、キャンペーン(糸)の宣言を書くとき、原稿のリンクに印(UTM)を付けるとき、効いたかを測るときに呼ぶ。各段で叩く THTH の命令と、数の読み方・広告に進む条件をまとめた流れの型。
4
+ ---
5
+
6
+ # THTH — 届ける流れの型(thth-flow)
7
+
8
+ THTH の出力が「次はこれ」と言う前に、まずこの型を読む。命令ひとつずつの詳しい使い方は skill `thth`(`skills/thth/SKILL.md`)、広告の段の手順は skill `thth-ads` に任せる。ここに書くのは流れの形と、THTH が触る所だけ。
9
+
10
+ **根っこは効果測定。** あとから取り直せないのは 3 つだけ——投稿の URL の印(UTM)・原稿の札 `thread:`・広告の `url_tags`。これは出す前に必ず付ける。数の読みは後からでもできる。
11
+
12
+ ## 1. 流れの型(段の名と順)
13
+
14
+ | 段 | 中身 | 宣言に書く行の例 |
15
+ |---|---|---|
16
+ | `collect` | 調べる・はてブで集める | `- collect: hatena_bookmark need=3`(タグは既定で糸の id) |
17
+ | `diary` | はてなブログに仮説を書く | `- diary: hatenablog` |
18
+ | `article` | 本体のサイトの記事を出す・直す | `- article: site`(出来事 `article_published` で満たす) |
19
+ | `promote` | 告知(Threads・X・Facebook・Instagram) | `- promote: threads,x,facebook need=3` |
20
+ | `selfbm` | セルクマ(自分の記事を自分のはてな ID で) | 下の §4 を見る |
21
+ | `boost` | 広告(有機の反応を見てから 1 本だけ) | 段 1(5.7)で入る予定。今は宣言に書かない |
22
+ | `warm` | 返信を返す | `- warm: threads replies_within_hours=24` |
23
+
24
+ - 段は窓口が選ぶ。全部は要らない。上から順に満たす形で、THTH は読んで数えるだけ(原稿を書かない・段を進めない・選ばない)。
25
+ - 段の名は自由(`[a-z][a-z0-9_]` 32 字まで)。`collect`・`diary`・`article`・`announce`・`warm` だけ画面に日本語の名が出る。`promote`・`selfbm` は今は「n 段目」と出る。
26
+ - 媒体として書けるのは今 9 つ: `hatena_bookmark`・`hatenablog`・`site`・`threads`・`x`・`bluesky`・`mastodon`・`facebook`・`instagram`。`ads`(広告)は段 1(5.7)で入る予定で、今書くと `stage_medium_unknown`。
27
+ - **台帳の更新は THTH の段ではない。** 知識の側(各 repo)の仕事。糸のファイルには出来事の 1 行だけ残す: `- 2026-11-03 researched <短い文>`・`hypothesis`・`article_published`・`closed`。`researched` は collect、`hypothesis` は diary の本数の代わりになる。
28
+ - 宣言の置き場と書式は skill `thth` の「キャンペーンとシリーズ(scenario)」の節。原稿の札 `thread: <id>` は承認の指紋に入らないので、あとから足しても再承認は要らない。
29
+
30
+ ## 2. 印(UTM)の決まり
31
+
32
+ | 何 | 印 |
33
+ |---|---|
34
+ | SNS の告知(有機) | `?utm_source=<threads|x|facebook|instagram>&utm_medium=social&utm_campaign=<原稿のファイル名、拡張子なし>` |
35
+ | 広告 | 同じ `utm_campaign`、`utm_medium=paid`(`utm_source=facebook|instagram`)。付け方は skill `thth-ads` |
36
+ | セルクマ・はてなブログからの導線 | 印を付けない(付けると別のエントリーになる)。参照元(`b.hatena.ne.jp`・`<blog>.hatenablog.com`)で見る |
37
+
38
+ - **印は窓口が原稿に書く。THTH は本文を書き換えない**(承認の指紋が変わるため)。
39
+ - いま印が付いているのはほぼ Facebook の原稿だけ。**Threads・X の原稿にも次の原稿から付ける。** 承認済みの原稿は付け直さない。
40
+ - `utm_campaign` を原稿のファイル名にしておけば、GA4 の campaign → 原稿 → `thread:` → 糸、と新しい札なしで結べる。口座名(例 `utm_campaign=kopicha`)にしない——記事ごとに分けられなくなる。
41
+ - THTH のクリックの照合は `utm_*` を外して数えるので、印を付けても数え方は壊れない。
42
+
43
+ ## 3. 各段で叩く THTH の命令
44
+
45
+ | 段 | 命令(実在するものだけ) |
46
+ |---|---|
47
+ | 全体 | `thth scenario <project> --json`(糸と型の一覧)・`thth scenario show <project> <id> --json`(段ごとの原稿と状態・`next`)・`thth scenario lint <project>`(宣言の誤り・宣言の無い札)・`thth dashboard <project> campaign <id> --json` |
48
+ | collect | `thth bookmark add <口座> --url <URL> --comment … --tags <糸の id>`(二段・1 段目は表示と digest だけ)・`thth bookmark list <口座>` |
49
+ | diary | 原稿を queue に置いて `thth approve` の二段。`thth deliveries <口座|project> [--article <記事の id>]` で配信の状態と配信 id |
50
+ | article | 本体の記事は各 repo の手順で出す。出たら糸のファイルに `- <日付> article_published …` の 1 行 |
51
+ | promote | 原稿に `thread: <id>`・`goal: click`・印つきの URL → `thth lint` → `thth approve` の二段 |
52
+ | selfbm | `thth bookmark add <口座> --delivery <配信 id> --comment … --tags …`(§4 の柵) |
53
+ | boost | skill `thth-ads`(`thth ads boost` は全部 PAUSED で作るだけ、お金が動くのは `thth ads activate` の二段+hub の承認) |
54
+ | warm | `thth replies`・`thth unanswered <口座> --since 7d --json`・返事は承認の二段 |
55
+ | 測る | `thth after <口座>|--project <p> --json`・`thth analytics-report <口座> --per-post-clicks --since 30d --json`・`thth article reactions <project> --article <記事の id> --json`・`thth events <project> --since 7d --json`(`bookmark_received`・`scenario_stalled`)・`thth measured <口座> --json`(`file` 欄で原稿の名と結ぶ) |
56
+
57
+ ### 測りの読み方
58
+
59
+ - **分母と窓を必ず添えて言う。** `null`・`cannot_say` は「取れない」で、0 ではない。0 と書かない。
60
+ - 投稿ごとのクリックが THTH で取れるのは Threads だけ(`--per-post-clicks`・同じリンク先を前後 72 時間で 1 本だけが使った投稿 `unique_url_72h`)。X・Facebook・Instagram の投稿ごとのクリックは THTH に無い。Meta の `clicks` はリンク以外も含む。**記事への訪問はサイト側(GA4)で見るのが本筋**——いまは各サイトの GA4 の画面で `utm_campaign` を見る(機械で読むのは hub の仕事・段 2〜3 で入る予定)。
61
+ - セルクマの効きは「第三者のブックマークが付いたか」: `thth events` の `bookmark_received`、`thth article reactions`。はてなブログの PV は取らない(公式の口が無い)。
62
+ - 効いた・効かなかったは施策としてプラザに置く: `thth plaza post <口座> --kind measure --from after <口座>`(または `--from analytics-report <口座>`)。糸 1 本まるごとを観測として付ける `--from scenario` は段 4 で入る予定。
63
+
64
+ ## 4. セルクマの柵
65
+
66
+ はてなの原文: 自分が運営するサイトを自分のアカウントでブックマークするのは問題にしていない(ただし宣伝目的・機械的な高頻度はスパムと判断されうる)。THTH の柵はこのまま使う:
67
+
68
+ - 自分の記事は `--delivery`(配信の台帳にある自分の記事)で付ける。主体ごとに 1 日 1 件。同じページは owner をまたいで 1 回だけ。
69
+ - コメントに運営者であることを書く(1 段目に「運営者であることが分かる文に」と出る)。
70
+ - 二段の承認。まとめ打ち(`thth bookmark batch`)や timer に混ぜず、人がその場で `bookmark add` を打つ。記事が出た直後に 1 件。
71
+ - 「何件で新着に載るか」を試さない(表示の仕組みの検証はガイドラインが禁じている)。URL に印を付けない。
72
+ - **宣言の段として数えるのは段 1(5.7)から**(`hatena_bookmark target=own`)。いまの `hatena_bookmark` の段は THTH で付けたブックマークをタグで数えるだけで、自分の記事か他人のページかを分けない。いま `selfbm` の段を書くなら、collect と別のタグ(例 `- selfbm: hatena_bookmark tag=<id>-self`)をセルクマにだけ付ける。
73
+
74
+ ## 5. 広告に進む条件とピクセル
75
+
76
+ - **有機の告知を出して 48〜72 時間の反応を見てから**(`thth after`・`--per-post-clicks`)、効いた 1 本だけを押し出す。THTH は選ばない(数を並べるだけ)。選ぶのは窓口と人。
77
+ - 手順・承認・止め方は skill `thth-ads`。
78
+
79
+ | 広告の目的 | ピクセル | 無いとどうなるか |
80
+ |---|---|---|
81
+ | 反応(`--objective engagement`) | 要らない | 何も欠けない |
82
+ | サイト誘導(`--objective traffic`・リンクのクリックで最適化) | 無くても出せる | 「頁が開いた」(`landing_page_view`)が取れない |
83
+ | サイト誘導で「頁が開いた」に最適化 | **要る** | 作れない・最適化が効かない |
84
+
85
+ - ピクセルをサイトに入れるのは窓口の仕事。Meta への外部送信が増えるのでプライバシーの頁も直す。**入れる前に masaru へ 1 行。**
86
+
87
+ ## 6. 知識の側の手順(THTH の外)
88
+
89
+ 台帳の更新・本体の記事の出し方・自分のサイトの GA4 の見方・プライバシーの文は、各メディアの repo の `docs/sns/README.md` などに書く(例: asmon の `docs/sns/README.md`)。そこからこの skill へリンクする。ここには写さない。
90
+
91
+ 設計の正本: `docs/設計_効果測定と連動_2026-11-03.md`(段 0〜5)。
@@ -0,0 +1,93 @@
1
+ """5.6.3: boost のリンクの印(url_tags)と、サイトへの誘導(traffic)のあとの次の一手。偽の Meta だけ。
2
+
3
+ - `--url-tags`(無ければ台帳の `url_tags`)をクリエイティブの `url_tags` として送る(AdCreative の文書)。
4
+ - traffic で作ったら、ピクセルを**読むだけ**で確かめ、動いていなければ次の一手を返す。**先頭は skill。**
5
+ - 書く口は増やさない(ピクセルを作る・変える POST は無い)。
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import json
10
+
11
+ import pytest
12
+
13
+ from thth.ads import guide, ledger, ops
14
+ from tests.test_meta_stage5 import ACT, NAME, STORY, V, end_in, env, posts, setup_ledger # noqa: F401
15
+
16
+
17
+ def test_url_tagsを付けるとクリエイティブにだけ送り_記録に残す(env):
18
+ setup_ledger(env)
19
+ out = ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
20
+ url_tags="utm_source=facebook&utm_medium=paid&utm_campaign=kopicha")
21
+ creative = posts(env, "/adcreatives")[0]["form"]
22
+ assert creative["url_tags"] == ["utm_source=facebook&utm_medium=paid&utm_campaign=kopicha"]
23
+ assert creative["object_story_id"] == [STORY]
24
+ assert all("url_tags" not in c["form"] for c in posts(env) if not c["path"].endswith("adcreatives"))
25
+ assert out["plan"]["url_tags"].startswith("utm_source=facebook")
26
+ rows = [r for r in ops.read_ops(NAME) if r["op"] == "boost"]
27
+ assert rows[-1]["plan"]["url_tags"] == out["plan"]["url_tags"]
28
+ # 印が無ければ送らない(既定の振る舞いは変えない)
29
+ ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1))
30
+ assert "url_tags" not in posts(env, "/adcreatives")[-1]["form"]
31
+ assert [s["kind"] for s in ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now",
32
+ end=end_in(1))["next_steps"]] == ["skill"]
33
+
34
+
35
+ def test_utm_campaignだけなら有機と同じ鍵でmediumだけpaidの印を組む(env):
36
+ """10/27 に窓口が決めた形(有機 utm_medium=social)に揃え、広告は paid・campaign は原稿のファイル名。"""
37
+ setup_ledger(env)
38
+ out = ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
39
+ utm_campaign="2026-11-04-fb-sakura")
40
+ tags = "utm_source=facebook&utm_medium=paid&utm_campaign=2026-11-04-fb-sakura"
41
+ assert posts(env, "/adcreatives")[0]["form"]["url_tags"] == [tags] and out["plan"]["url_tags"] == tags
42
+ # --url-tags を渡せばそちらが先
43
+ ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
44
+ utm_campaign="x", url_tags="utm_source=a")
45
+ assert posts(env, "/adcreatives")[-1]["form"]["url_tags"] == ["utm_source=a"]
46
+ with pytest.raises(ops.OpsRefused) as exc:
47
+ ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
48
+ utm_campaign="a&utm_source=b")
49
+ assert exc.value.code == "ads_utm_campaign_invalid"
50
+
51
+
52
+ def test_台帳のurl_tagsとlanding_urlを使い_形の違う物は作る前に断る(env):
53
+ setup_ledger(env)
54
+ path = ledger.path_for(NAME)
55
+ raw = json.loads(open(path, encoding="utf-8").read())
56
+ raw.update(url_tags="utm_source=facebook&utm_campaign={{campaign.id}}", landing_url="https://kopicha.example/lp")
57
+ open(path, "w", encoding="utf-8").write(json.dumps(raw))
58
+ out = ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1))
59
+ assert posts(env, "/adcreatives")[0]["form"]["url_tags"] == ["utm_source=facebook&utm_campaign={{campaign.id}}"]
60
+ assert out["plan"]["landing_url"] == "https://kopicha.example/lp"
61
+ before = len(posts(env))
62
+ for kwargs, code in (({"url_tags": "utm_source=a b"}, "ads_url_tags_invalid"),
63
+ ({"url_tags": "javascript:alert(1)"}, "ads_url_tags_invalid"),
64
+ ({"landing_url": "ftp://x"}, "ads_landing_url_invalid")):
65
+ with pytest.raises(ops.OpsRefused) as exc:
66
+ ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
67
+ **kwargs)
68
+ assert exc.value.code == code
69
+ assert len(posts(env)) == before
70
+ raw["url_tags"] = "壊れた 印"
71
+ open(path, "w", encoding="utf-8").write(json.dumps(raw))
72
+ with pytest.raises(ledger.AdAccountError):
73
+ ledger.load(NAME)
74
+
75
+
76
+ def test_trafficで作ったらピクセルを読み_動いていなければ入れる一手を返す_先頭はskill(env):
77
+ setup_ledger(env)
78
+ env["meta"].fail[("GET", V + f"/act_{ACT}/adspixels")] = (200, {"data": [{"id": "555", "name": "p"}]})
79
+ out = ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
80
+ objective="traffic", landing_url="https://kopicha.example/lp")
81
+ kinds = [s["kind"] for s in out["next_steps"]]
82
+ assert kinds == ["skill", "pixel_install", "url_tags_unset"]
83
+ assert out["skill"]["name"] == "thth-ads"
84
+ assert "誘導先 https://kopicha.example/lp のサイトにピクセル 555 の基本のコードを入れる" in out["next_steps"][1]["text"]
85
+ assert guide.PIXEL_DOC_URL in out["next_steps"][1]["text"]
86
+ # ピクセルが動いていて印も付けたなら skill だけ
87
+ env["meta"].fail[("GET", V + f"/act_{ACT}/adspixels")] = (
88
+ 200, {"data": [{"id": "555", "last_fired_time": "2026-11-03T05:00:00+0000"}]})
89
+ out = ops.boost(NAME, by="masaru", object_story_id=STORY, lifetime_minor=500, start="now", end=end_in(1),
90
+ objective="traffic", url_tags="utm_source=facebook")
91
+ assert [s["kind"] for s in out["next_steps"]] == ["skill"]
92
+ # ピクセルを読む口は GET だけ(作る・変える POST は無い)
93
+ assert not any("adspixels" in c["path"] for c in posts(env))