thth 2.3.1__tar.gz → 2.3.2__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.
- {thth-2.3.1 → thth-2.3.2}/PKG-INFO +3 -3
- {thth-2.3.1 → thth-2.3.2}/README.md +2 -2
- thth-2.3.2/tests/test_behind_remote.py +137 -0
- thth-2.3.2/tests/test_cli_vm_path.py +80 -0
- thth-2.3.2/tests/test_pull_cli.py +96 -0
- thth-2.3.2/thth/VERSION +1 -0
- {thth-2.3.1 → thth-2.3.2}/thth/cli.py +269 -1
- {thth-2.3.1 → thth-2.3.2}/thth/topic_cli.py +24 -0
- {thth-2.3.1 → thth-2.3.2}/thth/writeback.py +66 -0
- thth-2.3.1/thth/VERSION +0 -1
- {thth-2.3.1 → thth-2.3.2}/.gitignore +0 -0
- {thth-2.3.1 → thth-2.3.2}/LICENSE +0 -0
- {thth-2.3.1 → thth-2.3.2}/accounts.example/bluesky.json +0 -0
- {thth-2.3.1 → thth-2.3.2}/accounts.example/mastodon.json +0 -0
- {thth-2.3.1 → thth-2.3.2}/accounts.example/threads.json +0 -0
- {thth-2.3.1 → thth-2.3.2}/bin/thth +0 -0
- {thth-2.3.1 → thth-2.3.2}/bin/thth-remote +0 -0
- {thth-2.3.1 → thth-2.3.2}/bin/thth-run +0 -0
- {thth-2.3.1 → thth-2.3.2}/mcp/server.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/pyproject.toml +0 -0
- {thth-2.3.1 → thth-2.3.2}/skills/thth/SKILL.md +0 -0
- {thth-2.3.1 → thth-2.3.2}/systemd/thth@.service +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/__init__.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/conftest.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/fixtures/build_injection_eval.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/fixtures/callback/worker_responses.json +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/fixtures/injection_eval.json +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/fixtures/umami-bile.md +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/__init__.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_oauth_server.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_push_adapter.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_redirect_server.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_search_adapter.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_threads_reader.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/fake_threads_writes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/hold_lock.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/hold_repo_lock.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/helpers/worker_probe.mjs +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_account_name_check.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_account_report.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_accounts_dir.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_adapter_boundary.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_after_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_api_error_body.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_app_env_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_approval.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_approve_cmd.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_ask.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_atlas_fifth_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_atlas_fourth_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_atlas_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_atlas_second_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_atlas_third_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit1_fixes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit2_fixes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_b_counterexamples.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_b_m1_semantics.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_b_n1_depth.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_b_r1_closure.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_v201.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_audit_v23_details.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_auth.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_auth_identity_required.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_bluesky_adapter.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_bluesky_secret_scrub.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_board_needs_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_board_running.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_bundle.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_charcount.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_cli_entrypoint.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_cli_help.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_collect.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_collect_runs.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_collect_sent.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_comparability.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_control_chars_refused.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_conversation_paging.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_count_for.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_docs_links.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_doctor.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_doctor_all_permissions.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_doctor_next_step.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_duplicate_front_matter_keys.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_editorial_audit.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_editorial_n3_n4.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_engagements.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_external_acceptance.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_fake_api.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_form_spec.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_form_spec_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_forms.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_fresh_install.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_front_matter_injection.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_hypotheses.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_hypothesis_boundaries.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_hypothesis_units.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_impact_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_inbox_granted_scopes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_independent_thread_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_independent_topic_review.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_independent_topic_review_r2.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_inflight.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_jst.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_lint.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_list_projections.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_llm_trial.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_llm_trial_engage.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_lock.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_m2_independent.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_maintain.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_mastodon_adapter.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_mastodon_visibility.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_max_per_run.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_mcp.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_mcp_robustness.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_measured.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_media_accounts.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_media_next_steps.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_media_roundtrip.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_mismatch_diagnostics.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_n5_reply_null_element.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_n6_replies_incomplete_ledger.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_n7_doctor_error_body.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_no_limits.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_observation_provenance.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_packaging.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_preview.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_production_mode.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_queue.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_quiet_hours.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_r2_r4_r5.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_reason_adoption.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_redact.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_redirect_token_leak.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_refresh.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_refresh_destination.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_rejudge_new.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_rejudge_r2_r3.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_replies.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_replies_refresh.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_repo_lock.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_repo_sync.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_reverse_audit.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_case_id_cluster_m2.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_case_id_cluster_r2.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_evidence_account.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_form_spec_and_case_id.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_provenance.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_review_records.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_revoke.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_roundtrip.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_run_missing_env.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_run_record_failclosed.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_runs_collected.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_runs_read_rows.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_schedule_multiple.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_schedule_view.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_scopes_source_requested.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_search_engage_targets.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_secret_value_redact.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_secrets_grep.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_security_small_fixes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_select.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_selfupdate.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_send.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_send_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_send_media.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_send_visibility.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_sent_integrity.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_server_json.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_site.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_skill_doc.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_systemd.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_thread_publish.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_thread_read.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_threadrun.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_threads_read_permissions.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_threadshape.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_thth_root.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_token_exists.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_token_scopes_record.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_token_set.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_advice.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_models.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_review_fixes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_shelf_observers.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topic_store.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topics_record_concurrent.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_topics_tool.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_trial_frictions.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_v21b_approved_writes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_value_domains_shown.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_version.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_where_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_who_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_writeback_rebase.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/tests/test_writeback_validate.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/__init__.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/__main__.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/account_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/account_report.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/accounts.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/adapters/__init__.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/adapters/base.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/adapters/bluesky.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/adapters/mastodon.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/adapters/threads.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/after_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/appenv.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/approval.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/ask.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/ask_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/bundle.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/collect.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/core.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/doctor.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/engagements.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/forms.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/httpsafe.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/inflight.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/jst.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/lint.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/lock.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/maintain.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/measured.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/oauth.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/postid.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/queuefile.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/redact.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/replies.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/report.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/retract_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/runs.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/scopes.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/secrets_fs.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/select.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/selfupdate.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/sent.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/systemd_gen.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/thread_read.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/threadrun.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/threads_read_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/threadshape.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/threadthrow.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/topic_advice.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/topic_models.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/topic_store.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/topics.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/where_cli.py +0 -0
- {thth-2.3.1 → thth-2.3.2}/thth/who_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: thth
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
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
|
|
@@ -45,7 +45,7 @@ watchtower(`~/Developer/watchtower`)の隣に同じ流儀で並べる。watc
|
|
|
45
45
|
|
|
46
46
|
## いまの状態(2026-09-13)
|
|
47
47
|
|
|
48
|
-
版 **2.3.
|
|
48
|
+
版 **2.3.2**。全件テスト **2310 件**(`python -m pytest tests/ -q -n auto -p no:cacheprovider`・1 skip・rc=0)。
|
|
49
49
|
|
|
50
50
|
**媒体**: Threads(稼働)・Bluesky・Mastodon(同席用の台帳あり・未稼働)。
|
|
51
51
|
|
|
@@ -79,7 +79,7 @@ timer(systemd・`thth systemd` で生成)で毎時投稿、返信の採集
|
|
|
79
79
|
- **英語の文書**: [README.en.md](README.en.md)・[docs/usage.en.md](docs/usage.en.md)・[llms.txt](llms.txt)。
|
|
80
80
|
- **skill**: `skills/thth/SKILL.md`(wheel にも入る)。
|
|
81
81
|
|
|
82
|
-
- **動くもの**(`thth --help` の全
|
|
82
|
+
- **動くもの**(`thth --help` の全 35 サブコマンド): `lint`・`preview`・`approve`・`account`・`revoke`・`posts`・`replies`・`measured`・`threads`・`after`・`topics`・`forms`・`queue`・`schedule`・`throw`・`run`・`systemd`・`board`・`collect`・`pull`・`auth`・`refresh`・`maintain`・`send`・`doctor`・`app`・`token`・`ask`・`mentions`・`profile`・`thread`・`where`・`who`・`retract`・`location`。
|
|
83
83
|
- **最初の本番投稿の記録**: 2026-09-09、@aoking に疎通確認を 1 本(`17916074118445631`)。
|
|
84
84
|
- **未着手**: X・Facebook ページ・Instagram の各アダプタ。トピック検索の権限(tester には降りない)。泉のサーバ(v2-5)。
|
|
85
85
|
- **権限の制約**: tester に降りる scope は 5 つ。削除はできない。
|
|
@@ -21,7 +21,7 @@ watchtower(`~/Developer/watchtower`)の隣に同じ流儀で並べる。watc
|
|
|
21
21
|
|
|
22
22
|
## いまの状態(2026-09-13)
|
|
23
23
|
|
|
24
|
-
版 **2.3.
|
|
24
|
+
版 **2.3.2**。全件テスト **2310 件**(`python -m pytest tests/ -q -n auto -p no:cacheprovider`・1 skip・rc=0)。
|
|
25
25
|
|
|
26
26
|
**媒体**: Threads(稼働)・Bluesky・Mastodon(同席用の台帳あり・未稼働)。
|
|
27
27
|
|
|
@@ -55,7 +55,7 @@ timer(systemd・`thth systemd` で生成)で毎時投稿、返信の採集
|
|
|
55
55
|
- **英語の文書**: [README.en.md](README.en.md)・[docs/usage.en.md](docs/usage.en.md)・[llms.txt](llms.txt)。
|
|
56
56
|
- **skill**: `skills/thth/SKILL.md`(wheel にも入る)。
|
|
57
57
|
|
|
58
|
-
- **動くもの**(`thth --help` の全
|
|
58
|
+
- **動くもの**(`thth --help` の全 35 サブコマンド): `lint`・`preview`・`approve`・`account`・`revoke`・`posts`・`replies`・`measured`・`threads`・`after`・`topics`・`forms`・`queue`・`schedule`・`throw`・`run`・`systemd`・`board`・`collect`・`pull`・`auth`・`refresh`・`maintain`・`send`・`doctor`・`app`・`token`・`ask`・`mentions`・`profile`・`thread`・`where`・`who`・`retract`・`location`。
|
|
59
59
|
- **最初の本番投稿の記録**: 2026-09-09、@aoking に疎通確認を 1 本(`17916074118445631`)。
|
|
60
60
|
- **未着手**: X・Facebook ページ・Instagram の各アダプタ。トピック検索の権限(tester には降りない)。泉のサーバ(v2-5)。
|
|
61
61
|
- **権限の制約**: tester に降りる scope は 5 つ。削除はできない。
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""`writeback.behind_remote()` と `thth queue`/`schedule`/`board` の遅れ表示
|
|
2
|
+
(発注 T8-2・kopicha 続報)。
|
|
3
|
+
|
|
4
|
+
`thth approve`(と `revoke`・`throw`・`collect`・`retract`)は既に
|
|
5
|
+
`writeback.sync_repo()` を通しているが、**読むだけの口**(`queue`・
|
|
6
|
+
`schedule`・`board`)は通していない。push した直後に読むだけの口を見ると、
|
|
7
|
+
timer の `collect` が pull するまでの間、まだ取り込み前の一覧が出る
|
|
8
|
+
——**読むだけの口が勝手に pull するのは避ける**のが設計の芯なので、
|
|
9
|
+
ここでは「遅れていることを言う」だけを確かめる(取り込みは T8-3 の
|
|
10
|
+
`thth pull` か `thth approve` が行う)。
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from tests.conftest import init_git_pair, run_git, run_thth, write_queue_file
|
|
15
|
+
from thth import writeback
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_behind_remoteは追いついていれば0(tmp_path):
|
|
19
|
+
pair = init_git_pair(tmp_path / "a", seed_content="", seed_name=".gitkeep")
|
|
20
|
+
info = writeback.behind_remote(pair["work"])
|
|
21
|
+
assert info == {"behind": 0, "ahead": 0, "head": info["head"],
|
|
22
|
+
"fetched_at": info["fetched_at"], "reason": None}
|
|
23
|
+
assert info["head"]
|
|
24
|
+
assert info["reason"] is None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_behind_remoteはfetchだけでpullしない(tmp_path):
|
|
28
|
+
"""**pull はしない**——fetch のあと、work の作業ツリー(HEAD)は動かない。"""
|
|
29
|
+
pair = init_git_pair(tmp_path / "a", seed_content="旧", seed_name="a.md")
|
|
30
|
+
head_before = run_git(pair["work"], ["rev-parse", "HEAD"]).stdout.strip()
|
|
31
|
+
|
|
32
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
33
|
+
run_git(pair["seed"], ["push"])
|
|
34
|
+
|
|
35
|
+
info = writeback.behind_remote(pair["work"])
|
|
36
|
+
assert info["behind"] == 1
|
|
37
|
+
assert info["ahead"] == 0
|
|
38
|
+
|
|
39
|
+
head_after = run_git(pair["work"], ["rev-parse", "HEAD"]).stdout.strip()
|
|
40
|
+
assert head_after == head_before, "fetch だけのはずが HEAD が動いた(pull してしまった)"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_behind_remoteはfetchできないとNoneとreason(tmp_path):
|
|
44
|
+
broken = tmp_path / "broken"
|
|
45
|
+
run_git_init = __import__("subprocess").run(
|
|
46
|
+
["git", "init", "-b", "main", str(broken)], capture_output=True, text=True)
|
|
47
|
+
assert run_git_init.returncode == 0
|
|
48
|
+
run_git(str(broken), ["remote", "add", "origin", "/does/not/exist/repo.git"])
|
|
49
|
+
run_git(str(broken), ["commit", "--allow-empty", "-m", "x"])
|
|
50
|
+
|
|
51
|
+
info = writeback.behind_remote(str(broken))
|
|
52
|
+
assert info["behind"] is None
|
|
53
|
+
assert info["ahead"] is None
|
|
54
|
+
assert info["reason"]
|
|
55
|
+
assert "0" != info["reason"] # **0 と混ぜない**: reason があるのに behind: 0 ではない
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_queueは遅れているときに先頭に1行(isolated_account_factory, tmp_path):
|
|
59
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
60
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
61
|
+
write_queue_file(account["queue_dir"], "a.md",
|
|
62
|
+
fm_overrides={"status": "draft", "account": account["name"]})
|
|
63
|
+
|
|
64
|
+
# **`seed` を origin の最新に合わせてから**新しい commit を積む(`work` の
|
|
65
|
+
# `write_queue_file()` push で origin が進んでいるため、合わせないと
|
|
66
|
+
# `seed` の push 自体が non-fast-forward で失敗する)。
|
|
67
|
+
run_git(pair["seed"], ["pull"])
|
|
68
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
69
|
+
run_git(pair["seed"], ["push"])
|
|
70
|
+
|
|
71
|
+
result = run_thth(["queue", account["name"]])
|
|
72
|
+
assert result.returncode == 0, result.stderr
|
|
73
|
+
assert "remote に 1 commit 分の新しいものがあります" in result.stdout
|
|
74
|
+
assert f"thth pull {account['name']}" in result.stdout
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_queueは遅れていなければ何も出さない(isolated_account_factory, tmp_path):
|
|
78
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
79
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
80
|
+
write_queue_file(account["queue_dir"], "a.md",
|
|
81
|
+
fm_overrides={"status": "draft", "account": account["name"]})
|
|
82
|
+
|
|
83
|
+
result = run_thth(["queue", account["name"]])
|
|
84
|
+
assert result.returncode == 0, result.stderr
|
|
85
|
+
assert "remote に" not in result.stdout
|
|
86
|
+
assert "thth pull" not in result.stdout
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_queueのjsonにrepoが乗る(isolated_account_factory, tmp_path):
|
|
90
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
91
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
92
|
+
write_queue_file(account["queue_dir"], "a.md",
|
|
93
|
+
fm_overrides={"status": "draft", "account": account["name"]})
|
|
94
|
+
|
|
95
|
+
result = run_thth(["queue", account["name"], "--json"])
|
|
96
|
+
assert result.returncode == 0, result.stderr
|
|
97
|
+
import json
|
|
98
|
+
out = json.loads(result.stdout)
|
|
99
|
+
assert out[account["name"]]["repo"]["behind"] == 0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_scheduleは遅れているときに先頭に1行(isolated_account_factory, tmp_path):
|
|
103
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
104
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
105
|
+
write_queue_file(account["queue_dir"], "a.md",
|
|
106
|
+
fm_overrides={"status": "draft", "account": account["name"],
|
|
107
|
+
"publish_at": "2026-09-20T08:00:00+09:00"})
|
|
108
|
+
|
|
109
|
+
run_git(pair["seed"], ["pull"])
|
|
110
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
111
|
+
run_git(pair["seed"], ["push"])
|
|
112
|
+
|
|
113
|
+
result = run_thth(["schedule", account["name"]])
|
|
114
|
+
assert result.returncode == 0, result.stderr
|
|
115
|
+
assert "remote に 1 commit 分の新しいものがあります" in result.stdout
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_boardは遅れているaccountの行の下に1行(isolated_account_factory, tmp_path):
|
|
119
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
120
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
121
|
+
|
|
122
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
123
|
+
run_git(pair["seed"], ["push"])
|
|
124
|
+
|
|
125
|
+
result = run_thth(["board"])
|
|
126
|
+
assert result.returncode == 0, result.stderr
|
|
127
|
+
assert "repo が 1 commit 遅れています" in result.stdout
|
|
128
|
+
assert f"thth pull {account['name']}" in result.stdout
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_boardは遅れていなければ何も出さない(isolated_account_factory, tmp_path):
|
|
132
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
133
|
+
isolated_account_factory(repo_dir=pair["work"])
|
|
134
|
+
|
|
135
|
+
result = run_thth(["board"])
|
|
136
|
+
assert result.returncode == 0, result.stderr
|
|
137
|
+
assert "repo が" not in result.stdout
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""VM に無いパスを渡したときの断り方(発注 T8-1・kopicha 続報)。
|
|
2
|
+
|
|
3
|
+
`~/.local/bin/thth` は Mac から VM へ ssh する薄いラッパで、引数はそのまま
|
|
4
|
+
VM 側の `thth` に渡る。**Mac 側の相対パスも絶対パスも VM には無い**ので、
|
|
5
|
+
いままでは `FileNotFoundError` の素の traceback が出ていた(`--article
|
|
6
|
+
/tmp/x.json` で踏んだのと同じ根)。
|
|
7
|
+
|
|
8
|
+
ファイルを受け取る全ての引数(`lint`・`approve`・`revoke`・`preview`・
|
|
9
|
+
`send --text-file`・`topics suggest` の queue ファイル・`--article`・
|
|
10
|
+
`--proposal`・`--input`・`--draft`・`--revised-draft`)が、共通の
|
|
11
|
+
`cli._require_vm_path()` を通って rc=2・案内つきで断ることを確かめる。
|
|
12
|
+
存在するパスは従来どおり動くことも確かめる(回帰)。
|
|
13
|
+
"""
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
|
|
18
|
+
from tests.conftest import run_thth, write_queue_file
|
|
19
|
+
|
|
20
|
+
MISSING = "/tmp/thth-t8-does-not-exist-まさかここには無い.md"
|
|
21
|
+
MISSING_JSON = "/tmp/thth-t8-does-not-exist-まさかここには無い.json"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _assert_vm_refusal(result, *, rc=2):
|
|
25
|
+
combined = result.stdout + result.stderr
|
|
26
|
+
assert result.returncode == rc, f"rc={result.returncode}: {combined}"
|
|
27
|
+
assert "VM" in combined, combined
|
|
28
|
+
assert "thth queue" in combined, combined
|
|
29
|
+
assert "Traceback" not in result.stderr, result.stderr
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_lintにVMに無いパスを渡すとrc2で案内する():
|
|
33
|
+
result = run_thth(["lint", MISSING])
|
|
34
|
+
_assert_vm_refusal(result)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_approveにVMに無いパスを渡すとrc2で案内する():
|
|
38
|
+
result = run_thth(["approve", MISSING])
|
|
39
|
+
_assert_vm_refusal(result)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_sendのtext_fileにVMに無いパスを渡すとrc2で案内する(isolated_account):
|
|
43
|
+
result = run_thth(["send", isolated_account["name"], "--text-file", MISSING])
|
|
44
|
+
_assert_vm_refusal(result)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_topics_suggestのarticleにVMに無いパスを渡すとrc2で案内する(isolated_account):
|
|
48
|
+
queue_path = write_queue_file(
|
|
49
|
+
isolated_account["queue_dir"], "q.md",
|
|
50
|
+
body="## threads\n\nhello https://example.test/x\n",
|
|
51
|
+
fm_overrides={"status": "draft", "account": isolated_account["name"]})
|
|
52
|
+
result = run_thth(["topics", "suggest", queue_path, "--article", MISSING_JSON])
|
|
53
|
+
_assert_vm_refusal(result)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_revokeにVMに無いパスを渡すとrc2で案内する():
|
|
57
|
+
result = run_thth(["revoke", MISSING, "--by", "test"])
|
|
58
|
+
_assert_vm_refusal(result)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_previewにVMに無いパスを渡すとrc2で案内する():
|
|
62
|
+
result = run_thth(["preview", MISSING])
|
|
63
|
+
_assert_vm_refusal(result)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_存在するパスは従来どおり動く(isolated_account):
|
|
67
|
+
"""回帰: 存在するパスには案内を出さない(発注書「存在するパスは従来どおり」)。"""
|
|
68
|
+
queue_path = write_queue_file(
|
|
69
|
+
isolated_account["queue_dir"], "ok.md",
|
|
70
|
+
body="## threads\n\nこんにちは https://example.test/x\n",
|
|
71
|
+
fm_overrides={"status": "draft", "account": isolated_account["name"]})
|
|
72
|
+
assert os.path.exists(queue_path)
|
|
73
|
+
|
|
74
|
+
result = run_thth(["lint", queue_path])
|
|
75
|
+
assert "VM" not in (result.stdout + result.stderr)
|
|
76
|
+
assert "thth queue" not in (result.stdout + result.stderr)
|
|
77
|
+
|
|
78
|
+
result = run_thth(["preview", queue_path])
|
|
79
|
+
assert result.returncode == 0, result.stderr
|
|
80
|
+
assert "こんにちは" in result.stdout
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""`thth pull <account|--project P>`(発注 T8-3・kopicha 続報)。
|
|
2
|
+
|
|
3
|
+
読むだけの口(`queue`・`schedule`・`board`。T8-2)は遅れを**言うだけ**で
|
|
4
|
+
pull しない。この道具は、その案内から誘導される**明示の**取り込み口——
|
|
5
|
+
`writeback.sync_repo()` を呼ぶだけで、`thth approve` が既に通しているのと
|
|
6
|
+
同じ関数・同じ repo ロックを使う。
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
|
|
12
|
+
from tests.conftest import init_git_pair, run_git, run_thth
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_pullはffして取り込む(isolated_account_factory, tmp_path):
|
|
16
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="旧", seed_name="a.md")
|
|
17
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
18
|
+
head_before = run_git(pair["work"], ["rev-parse", "--short", "HEAD"]).stdout.strip()
|
|
19
|
+
|
|
20
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
21
|
+
run_git(pair["seed"], ["push"])
|
|
22
|
+
head_after_remote = run_git(pair["seed"], ["rev-parse", "--short", "HEAD"]).stdout.strip()
|
|
23
|
+
|
|
24
|
+
result = run_thth(["pull", account["name"]])
|
|
25
|
+
assert result.returncode == 0, result.stderr
|
|
26
|
+
assert f"取り込みました: {head_before} → {head_after_remote}(1 commit)" in result.stdout
|
|
27
|
+
|
|
28
|
+
# 本当に取り込まれている(work の HEAD が動いた)。
|
|
29
|
+
head_now = run_git(pair["work"], ["rev-parse", "--short", "HEAD"]).stdout.strip()
|
|
30
|
+
assert head_now == head_after_remote
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_pullはすでに最新なら何も変えない(isolated_account_factory, tmp_path):
|
|
34
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
35
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
36
|
+
head_before = run_git(pair["work"], ["rev-parse", "--short", "HEAD"]).stdout.strip()
|
|
37
|
+
|
|
38
|
+
result = run_thth(["pull", account["name"]])
|
|
39
|
+
assert result.returncode == 0, result.stderr
|
|
40
|
+
assert "すでに最新です" in result.stdout
|
|
41
|
+
|
|
42
|
+
head_after = run_git(pair["work"], ["rev-parse", "--short", "HEAD"]).stdout.strip()
|
|
43
|
+
assert head_after == head_before
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_pullのjsonはbehind_remoteの形(isolated_account_factory, tmp_path):
|
|
47
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="", seed_name=".gitkeep")
|
|
48
|
+
account = isolated_account_factory(repo_dir=pair["work"])
|
|
49
|
+
|
|
50
|
+
result = run_thth(["pull", account["name"], "--json"])
|
|
51
|
+
assert result.returncode == 0, result.stderr
|
|
52
|
+
out = json.loads(result.stdout)
|
|
53
|
+
assert len(out) == 1
|
|
54
|
+
row = out[0]
|
|
55
|
+
assert row["account"] == account["name"]
|
|
56
|
+
assert row["ok"] is True
|
|
57
|
+
assert set(row["repo"].keys()) == {"behind", "ahead", "head", "fetched_at", "reason"}
|
|
58
|
+
assert row["repo"]["behind"] == 0
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_pullのprojectは同じrepoを共有する2accountで1回だけ引く(
|
|
62
|
+
isolated_account_factory, tmp_path):
|
|
63
|
+
pair = init_git_pair(tmp_path / "acct", seed_content="旧", seed_name="a.md")
|
|
64
|
+
account_a = isolated_account_factory("a-threads", repo_dir=pair["work"], project="shared")
|
|
65
|
+
account_b = isolated_account_factory("b-threads", repo_dir=pair["work"], project="shared")
|
|
66
|
+
assert account_a["repo_dir"] == account_b["repo_dir"]
|
|
67
|
+
|
|
68
|
+
run_git(pair["seed"], ["commit", "--allow-empty", "-m", "second"])
|
|
69
|
+
run_git(pair["seed"], ["push"])
|
|
70
|
+
|
|
71
|
+
result = run_thth(["pull", "--project", "shared", "--json"])
|
|
72
|
+
assert result.returncode == 0, result.stderr
|
|
73
|
+
out = json.loads(result.stdout)
|
|
74
|
+
# **重複なく 1 回だけ**——2 account だが repo は 1 つ。
|
|
75
|
+
assert len(out) == 1
|
|
76
|
+
assert out[0]["repo"]["behind"] == 0
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_pullは失敗をsync_repoの理由のままrc1(isolated_account_factory, tmp_path):
|
|
80
|
+
account = isolated_account_factory(repo_dir=str(tmp_path / "no-such-repo-dir"))
|
|
81
|
+
|
|
82
|
+
result = run_thth(["pull", account["name"]])
|
|
83
|
+
assert result.returncode == 1, result.stdout
|
|
84
|
+
assert "取り込めませんでした" in result.stderr or "見当たりません" in result.stderr
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def test_pullはaccountもprojectも無ければ断る(isolated_account_factory):
|
|
88
|
+
result = run_thth(["pull"])
|
|
89
|
+
assert result.returncode == 2
|
|
90
|
+
assert "account" in result.stderr
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_pullは未知のprojectを断る(isolated_account_factory):
|
|
94
|
+
result = run_thth(["pull", "--project", "no-such-project"])
|
|
95
|
+
assert result.returncode == 2
|
|
96
|
+
assert "no-such-project" in result.stderr
|
thth-2.3.2/thth/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3.2
|