code-coordinator 0.5.195__tar.gz → 0.5.197__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.
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/workflows/test.yml +33 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/PKG-INFO +1 -1
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/PKG-INFO +1 -1
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/SOURCES.txt +3 -1
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/scm_file_list.json +3 -1
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/scm_version.json +2 -2
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/release.py +67 -1
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/status.py +43 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/release_cordon.py +43 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/release_propagate.py +8 -0
- code_coordinator-0.5.197/scripts/check_gh_argv_containment.py +176 -0
- code_coordinator-0.5.197/tests/test_check_gh_argv_containment.py +156 -0
- code_coordinator-0.5.197/tests/test_release_cordon_stuck_2490.py +272 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_propagate.py +20 -0
- code_coordinator-0.5.195/tests/test_no_direct_gh_calls.py +0 -112
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.claude/commands/board.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.claude/commands/complete-session.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.claude/commands/coordinator.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.githooks/_lib.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.githooks/post-checkout +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.githooks/post-commit +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.githooks/post-merge +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/coord-ci-acceptance.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/workflows/auto-release.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/workflows/cargo-test.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/workflows/publish.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.github/workflows/release-tui.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/.gitignore +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/CLAUDE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/GOAL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/LICENSE +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/MANIFEST.in +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/README.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/dependency_links.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/entry_points.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/requires.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/top_level.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/_board_mapping.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/acceptance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/acceptance_drivers.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agent.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agent_app.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agent_update.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agents/opencode/.gitignore +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agents/opencode/agents/work.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/agents/opencode/routing.jsonc +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/auto_loop.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/block_log.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/board_bool_guard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/board_service.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/board_wire.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/brain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/branch_model.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/bug_intake.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/cargo_cache.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/ci_github.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/ci_store.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/claim.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/client.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/_common.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/acceptance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/agent_ops.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/dispatch_workers.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/drive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/drive_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/gate_a.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/gates.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/issues.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/lifecycle.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/merge.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/milestone.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/plan_followup.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/plans.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/portal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/repo.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/report.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/review.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/scorecard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/sessions.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/setup.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/terminal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/test_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/commands/tui.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/comments.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/config.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/config_reload.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/confirm_test.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/conflict_fix.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dao.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dashboard/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dashboard/fixture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dashboard/index.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dashboard/server.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dashboard/terminal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/db.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dead_end.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/README.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-agent.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-db-backup.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-db-backup.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-db-backup.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-drive-queue.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-drive-queue.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-notify.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-notify.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-release-propagate.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-release-propagate.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-release-window.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-release-window.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-serve.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-web-dist-build.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-web-dist-build.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy/coord-web.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy_manifest.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deploy_units.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/deps.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/diagnose.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/dist_name.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/drive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/drive_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/drive_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/events.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/failure_class.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/filelock.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/fleet_config_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/forge_availability.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/freshness.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/gate_a.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/gate_b.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/gate_snapshot.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/gates.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/github_ops.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/goal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/graph_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/aggregate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/agent_install.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/cargo_targets.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/claude_binary.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/coord_web_ci_pin.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/deploy_lane_facts.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/disk.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/fleet_board.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/fleet_deploy_lanes.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/fleet_phantom.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/fleet_unit_drift.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/graph.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/graphify_cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/index_lock.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/plan_usage.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/repo_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/spawned_coord.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/timer_active.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/toolchain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/unit_drift.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/unit_enablement.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/checks/worktrees.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/context.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/fleet_snapshot.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/models.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/pypi.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/registry.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/render.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/health/units.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/hooks.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/housekeeping.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/interactive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/issue_store.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/liveness_auditor.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/machine_pause.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/merge_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/milestone_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/milestone_dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/milestone_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/milestone_order.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/mock_author.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/models.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/network.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/new_issue_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/baseline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/collect.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/digest.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/models.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/predicate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/service.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/store.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notifier/transport.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/notify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/openapi.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/overlap_fence.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/overlap_predict.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/parentage.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/parentage_github.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/pipeline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/plan_parser.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/plans.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/platform_paths.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/portal_bridge.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/portal_store.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/portal_sync.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/pr_body_lint.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/prereqs.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/progress.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/providers/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/providers/base.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/providers/claude.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/providers/claude_pty.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/providers/opencode.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/queue_diagnose.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/reconcile.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/reconcile_tick.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/refine_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/release_verify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/release_window.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/repo_edit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/repo_onboard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/reports.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/revalidate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/review.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/scorecard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/self_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/serve_app.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/coord-dispatch-verbs/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/drive-queue-preflight/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/fleet-restart-safety/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/merge-stuck-triage/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/pipeline-limbo-triage/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/portal-followup/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/review-verdict-recovery/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/tui-quadraui-workflow/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/skills/update-issue/SKILL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/smoke.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/spend_ceiling.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/split_work.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/stage_projection.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/test_author.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/test_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/test_orchestrator.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/test_report.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/tui_release.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/usage.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/usage_limits.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/usage_rollup.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coord/worker_events.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/coordinator.example.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-agent.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-db-backup.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-db-backup.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-db-backup.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-drive-queue.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-drive-queue.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-notify.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-notify.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-release-propagate.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-release-propagate.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-release-window.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-release-window.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-serve.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-web-dist-build.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-web-dist-build.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-web-dist-build.timer +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-web-rollback.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/coord-web.service +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/deploy/node-shim.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ADR_COORD_WEB_ACCEPTANCE_SUITE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ADR_COORD_WEB_CI.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ADR_COORD_WEB_DIST.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/AGENT_OPERATIONS.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ARCHITECTURE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ARCH_SECURITY_GATES.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/COCKPIT.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/CONTROL_CENTER.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/COST_DISCIPLINE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/CROSS_PLATFORM.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/CUSTOMER_PORTAL.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/DRIVE_QUEUE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/EPHEMERAL_WORKERS.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/FORGE_MIGRATION.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/GRAPHIFY_SETUP.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ISSUE_GUIDANCE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/MAC_MINI.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/MERGE_AUTO_DRAIN_TRUST_BAR.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/NOTIFIER.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/OPENCODE_VERIFICATION.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/OPERATING_GOTCHAS.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/ORACLE_LOOP.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/PHONE_WEBAPP.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/PIPELINE_V2.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/PLATFORM_EVOLUTION.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/SECOND_BACKEND.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/STORE_SERVICE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/TEST_FIRST_BUG_LANE.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/WEB_CONTROL_CENTER.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/WSL_WINDOWS_WORKER.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/mocks/web/README.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/mocks/web/_tokens.css +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/mocks/web/issue-detail.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/mocks/web/pipeline-narrow.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/docs/mocks/web/pipeline-wide.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/graphify-out/.gitignore +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/install-agent.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/pyproject.toml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/audit_review_verdict_overrides.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/bootstrap-shared.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/build-worker-image.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/coordinator-machine.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/epic-down.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/epic-up.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/preflight.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/provision-worker.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/scrub-and-generalize.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/tailnet-acl.hujson +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/azure-workers/verify-github-token.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/codegen.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/coord-test-runner.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/drive-batch.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/gen_board_fixture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/next_release_tag.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/run_tests_in_populated_home.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/run_tests_without_gh.sh +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/smoke_437_interactive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/verify_878_review_capture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/verify_release_published.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/scripts/verify_release_wheel.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/setup.cfg +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/SMOKE_SET.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/__init__.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/audit_1039.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/contract.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/manifest.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/mocks/audit-panel-detail.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/mocks/audit-panel-empty.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/mocks/audit-panel-filters.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-33/mocks/audit-panel-populated.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-37/conftest.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-37/contract.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-37/manifest.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-37/test_usage_cli_1115.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-37/test_usage_core_1118.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/contract.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/manifest.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-base.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-detail-pane.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-help-overlay.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-palette.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-rightclick-epic.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-rightclick-header.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/mocks/plans-rightclick-stub.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/plans_detail_1122.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/plans_help_1124.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-38/plans_rightclick_1123.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/contract.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/home-active-extended.spec.ts +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/home-active.spec.ts +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/manifest.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/mocks/home-active.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-51/tsconfig.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/board_split_2288.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/board_tabs_2282.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/board_tabs_close_2283.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/contract.md +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/detail_substate_2285.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/manifest.yml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-baseline-no-tabs.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-pinned-3-tabs.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-preview-tab.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-split-side-by-side.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-tab-context-menu.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-tabs-help-overlay.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/board-tabs-overflow.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/mocks/pipeline-tabs-independent.screen +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/pipeline_tabs_2284.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/tabs_discoverability_2287.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-65/tabs_persistence_2286.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/acceptance/ms-example/mocks/home-active.html +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/conftest.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/board-pipeline-basic.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/board-pipeline-terminal-gates.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/opencode_run_failure_sample.jsonl +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/opencode_run_length_sample.jsonl +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/opencode_run_sample.jsonl +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/all_pass.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/global_setup_crash.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/mixed_fail.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/retry_then_pass.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/retry_then_pass.junit.xml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/skip.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/playwright/truncated.json +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/cargo_compile_error.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/cargo_multi_target_failures.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/cargo_no_parseable_failures.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/pytest_collection_error.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/pytest_error_string_in_body.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/pytest_internal_error.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/pytest_mixed_failures.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/fixtures/test_report/pytest_no_parseable_failures.txt +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_acceptance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_acceptance_drivers.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_api_error.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_app.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_branch_base.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_branch_capture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_config_free_1712.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_deploy_units_endpoint.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_dirty_worktree.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_drive_queue_reconcile_2373.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_graph_self_heal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_health_h3.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_idle_restart.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_push_failure.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_reap.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_repos_and_pull.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_restart_services_endpoint.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_skills_self_heal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_startup_diagnostics.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_update.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_update_bluegreen.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_usage_limit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_agent_zero_commit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_ambient_home_isolation.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_approve_reject_plan.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_approve_usage_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_assignment_already_recorded_daemon.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_audit_log.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_audit_outcome.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_audit_query.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_auto_loop.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_auto_release_publish_2035.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_base_checkout_restore.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_block_log.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_cap_762.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_fixture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_read_path.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_service.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_board_wire.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_brain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_branch_model.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_bug_intake.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_build_worker_image_env_update.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cargo_cache.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_ci_acceptance_gate_1950.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_ci_parity_2091.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_ci_store.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_claim.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_acceptance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_assign.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_assign_interactive_oracle_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_assign_interactive_remote.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_assign_provider.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_assign_repo_drift_2219.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_chat_continue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_decide.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_diagnose_config_provenance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_diagnose_forge_availability.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_diagnose_graph.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_diagnose_self.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_doctor.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_doctor_config_free_1801.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_doctor_config_mismatch_1712.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_drive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_drive_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_escalate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_fix_headless_review.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_gate_a.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_install_drift.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_install_skills.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_issue_create_label.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_issue_reopen.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_merge.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_assign.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_capture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_chat_add_child.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_gate_b.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_gate_c.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_order.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_remove_and_issue_close.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_milestone_ship.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_network.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_new_issue_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_plans.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_portal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_pull_artifact.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_reattach_sessions.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_refine_board.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_release_preflight.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_release_propagate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_release_window.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_repo_2220.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_scorecard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_set_review_findings.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_advisory_terminal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_merge_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_provider.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_review_finalizing.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_test_failed_tag.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_status_usage_limit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_sync_comments_873.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_test_plan.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_track.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_tui_update.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cli_wait.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_client_base_install.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_comments.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_completion_summary.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config_acceptance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config_audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config_pricing.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config_snapshot_noncanonical_2208.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_config_usage_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_confirm_test.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_conflict_fix.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_conflict_fix_semantic.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_test.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_test_runner_baseline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_test_runner_populated_home.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_test_runner_routing.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_test_runner_toolchain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coord_web_sse_restart_live.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_coordinator_machine.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_cross_platform_imports.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dashboard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dashboard_fixture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dashboard_terminal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dashboard_terminal_live.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_db.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dead_end.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_coord_db_backup.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_coord_web_dist.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_coord_web_rollback.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_drive_queue_unit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_manifest.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_units_lane.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deploy_web_unit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_deps.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_diagnose.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dispatch_target_validation.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_dist_name.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_done_housekeeping.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_drive.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_drive_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_drive_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_drive_tmux.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_epic_up_capability_detection.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_epic_up_down_symlinked_config_1887.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_epic_up_image_provenance.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_errors.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_events.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_failure_class.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_filelock.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_finalize_interactive_exit_test_verdict.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_fix_of_force_override.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_fleet_config_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_fleet_health_probes.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_fleet_health_snapshot.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_forge_availability.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_freshness.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_gate_a.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_gate_b.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_gate_snapshot_staleness.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_gates.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_gather_fleet_tmux_sessions.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_generated_types_fixture.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_github_ops.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_goal.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_graph_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_graph_selfheal_absent_2237.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_handoff.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_checks.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_cli_graph.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_config.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_context.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_coord_web_ci_pin.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_deploy_lane_facts.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_incident_regression.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_pypi.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_registry.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_timer_active.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_toolchain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_unit_drift.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_health_unit_enablement.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_hooks.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_human_attended_437.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_init.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_integration.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_briefing_echo.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_prefill_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_session_relaunch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_test_verdict_backstop.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_token_attribution.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_interactive_worktree.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_issue_store_seam.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_liveness_auditor.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_liveness_notify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_machine_pause.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_merge_queue.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_merge_verify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_milestone_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_milestone_dispatch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_milestone_gate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_milestone_order.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_milestone_seam.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_mock_author.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_model_tiering.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_models.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_models_config_labels.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_needs_attention.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_network.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_new_issue_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_next_release_tag.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_node_shim.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_baseline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_cli.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_collect.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_config.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_drive_seam.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_isolation.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_predicate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_quiet_hours.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notifier_service.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_notify_drain.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_openapi.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_operational_defaults.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_overlap_fence.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_overlap_predict.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_packaged_deploy_units.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_parentage.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_paste_landed.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_pipeline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_plan_followup_approve_plan_command.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_plan_followup_pr_command.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_plan_followup_review_command.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_plan_only.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_plan_parser.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_platform_paths.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_portal_bridge.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_portal_config.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_portal_sync.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_pr_body_lint.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_prereqs.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_production_db_guard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_progress.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_provider_seam.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_providers.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_providers_config_labels.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_providers_pty.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_quiet_hours.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_quiet_hours_store_2146.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reap_merged_sessions.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reap_stale_interactive_tick.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_branch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_completions.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_merges.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_no_agent_record.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_tick.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reconcile_usage_limit_done.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_refine_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_cordon_2101.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_cordon_daemon_leads_2176.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_cordon_deadlock_2240.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_unified_1242.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_verify.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_release_window.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_remote_auto_prune.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_remote_interactive_reaper.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_repo_edit_2220.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_repo_graph_fleet_2237.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_repo_onboard_2220.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_report_result_push.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_reports.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_retry.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_retry_advisory_1606.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_retry_type_1636.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_revalidate.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_end_review_without_verdict.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_parse_failure_diagnostic.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_reaffirm.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_verdict_backstop.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_verdict_override_audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_verdict_relay.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_review_zero_commits.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_scoped_review_wiring.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_scorecard.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_self_health.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_serve.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_serve_app_board_trim.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_session.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_slice_issue_attribution.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_smoke.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_smoke_live_checkout_restore.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_smoke_workflow.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_spend_ceiling.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_spend_ceiling_coordinator.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_split.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_split_work.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_stage_projection.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_stalled_pipeline.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_state.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_state_review_findings_daemon.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_status_fleet_footer.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_stop_1567.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_stuck.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_terminal_command.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_author.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_chat.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_orchestrator.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_report.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_verdict_parsing.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_test_verdict_transcript_floor.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_thin_client_board_audit.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_thin_client_config_load_1080.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_thin_client_daemon_routing_906.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_tmux_host.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_tmux_session.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_transcript_floor.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_usage.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_usage_limits.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_usage_rollup.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_venv_live_install_2121.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_version_single_source.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_watch.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_windows_job_is_a_real_gate_2000.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worker_events.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worker_image_pin_sync.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worker_safety.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worker_test_scoping.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worktree.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tests/test_worktree_rmtree_chokepoint.py +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/Cargo.lock +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/Cargo.toml +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/cargo-config-local-quadraui.toml.example +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/audit.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/chat.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/data.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/dialogs.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/doc_tabs.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/drive.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/drive_queue.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/escalation.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/events.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/fixtures.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/fleet_health.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/fleet_sessions.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/fleet_terminals.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/format.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/milestone_dag.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/mod.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/msv.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/pipeline.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/plans.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/render.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/reports.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/sessions.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/settings_ui.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/sidebar.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/terminal.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/tests.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/types.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/app/workspace.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/bin/gtk.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/commands.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/lib.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/main.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/src/settings.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/tests/acceptance.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/tests/cli.rs +0 -0
- {code_coordinator-0.5.195 → code_coordinator-0.5.197}/tui/tests/fixtures/board_sample.json +0 -0
|
@@ -153,6 +153,39 @@ jobs:
|
|
|
153
153
|
# gated separately through the #2164 CI wrapper.
|
|
154
154
|
- run: scripts/run_tests_without_gh.sh python -m pytest tests/ -q --ignore=tests/acceptance
|
|
155
155
|
|
|
156
|
+
# #2135 (child of epic #1902): "every `gh` argv construction lives inside
|
|
157
|
+
# coord/github_ops.py" is the load-bearing assumption under the #1902
|
|
158
|
+
# forge-portability cost estimate — it's the fact that makes the eventual
|
|
159
|
+
# port a refactor instead of a rewrite. #1483 already guarded direct
|
|
160
|
+
# call-argument leaks with an AST scan (formerly
|
|
161
|
+
# tests/test_no_direct_gh_calls.py), but that walk missed the
|
|
162
|
+
# variable-indirection shape (`cmd = ["gh", ...]; subprocess.run(cmd)`).
|
|
163
|
+
# This job's dedicated regex scan catches that gap too, so
|
|
164
|
+
# test_no_direct_gh_calls.py was retired in its favor rather than kept
|
|
165
|
+
# running alongside it as a second, disagreeing implementation of the
|
|
166
|
+
# same invariant (#2135 review) — see scripts/check_gh_argv_containment.py's
|
|
167
|
+
# module docstring for the full reconciliation.
|
|
168
|
+
#
|
|
169
|
+
# scripts/check_gh_argv_containment.py scans coord/**/*.py for a bare
|
|
170
|
+
# `"gh"`/`'gh'` token outside coord/github_ops.py, with one explicit,
|
|
171
|
+
# commented allowlist entry for coord/prereqs.py's binary-version probe
|
|
172
|
+
# (it checks `gh` is installed; it doesn't drive the forge). See that
|
|
173
|
+
# script's module docstring for the full rationale and
|
|
174
|
+
# tests/test_check_gh_argv_containment.py for the negative-test proof
|
|
175
|
+
# that the guard can actually fail.
|
|
176
|
+
#
|
|
177
|
+
# Stdlib-only (re/pathlib/dataclasses), so no `pip install` needed here —
|
|
178
|
+
# this is meant to be as cheap as `no-gh-on-path` above, a grep-shaped
|
|
179
|
+
# check, not a build step.
|
|
180
|
+
gh-argv-containment:
|
|
181
|
+
runs-on: ubuntu-latest
|
|
182
|
+
steps:
|
|
183
|
+
- uses: actions/checkout@v4
|
|
184
|
+
- uses: actions/setup-python@v5
|
|
185
|
+
with:
|
|
186
|
+
python-version: "3.12"
|
|
187
|
+
- run: python scripts/check_gh_argv_containment.py .
|
|
188
|
+
|
|
156
189
|
# #2170: run the full suite in the environment of a REAL FLEET MACHINE — a
|
|
157
190
|
# populated `~/.coord/` (thin-client shaped), no `sqlite3` on PATH, and a
|
|
158
191
|
# `$TMPDIR` under an ancestor pytest config.
|
|
@@ -309,6 +309,7 @@ docs/mocks/web/pipeline-narrow.html
|
|
|
309
309
|
docs/mocks/web/pipeline-wide.html
|
|
310
310
|
graphify-out/.gitignore
|
|
311
311
|
scripts/audit_review_verdict_overrides.py
|
|
312
|
+
scripts/check_gh_argv_containment.py
|
|
312
313
|
scripts/codegen.py
|
|
313
314
|
scripts/coord-test-runner.sh
|
|
314
315
|
scripts/drive-batch.sh
|
|
@@ -379,6 +380,7 @@ tests/test_branch_model.py
|
|
|
379
380
|
tests/test_bug_intake.py
|
|
380
381
|
tests/test_build_worker_image_env_update.py
|
|
381
382
|
tests/test_cargo_cache.py
|
|
383
|
+
tests/test_check_gh_argv_containment.py
|
|
382
384
|
tests/test_ci_acceptance_gate_1950.py
|
|
383
385
|
tests/test_ci_parity_2091.py
|
|
384
386
|
tests/test_ci_store.py
|
|
@@ -554,7 +556,6 @@ tests/test_needs_attention.py
|
|
|
554
556
|
tests/test_network.py
|
|
555
557
|
tests/test_new_issue_chat.py
|
|
556
558
|
tests/test_next_release_tag.py
|
|
557
|
-
tests/test_no_direct_gh_calls.py
|
|
558
559
|
tests/test_node_shim.py
|
|
559
560
|
tests/test_notifier_baseline.py
|
|
560
561
|
tests/test_notifier_cli.py
|
|
@@ -607,6 +608,7 @@ tests/test_refine_chat.py
|
|
|
607
608
|
tests/test_release_cordon_2101.py
|
|
608
609
|
tests/test_release_cordon_daemon_leads_2176.py
|
|
609
610
|
tests/test_release_cordon_deadlock_2240.py
|
|
611
|
+
tests/test_release_cordon_stuck_2490.py
|
|
610
612
|
tests/test_release_propagate.py
|
|
611
613
|
tests/test_release_unified_1242.py
|
|
612
614
|
tests/test_release_verify.py
|
{code_coordinator-0.5.195 → code_coordinator-0.5.197}/code_coordinator.egg-info/scm_file_list.json
RENAMED
|
@@ -313,6 +313,7 @@
|
|
|
313
313
|
"scripts/azure-workers/scrub-and-generalize.sh",
|
|
314
314
|
"scripts/azure-workers/tailnet-acl.hujson",
|
|
315
315
|
"scripts/azure-workers/verify-github-token.sh",
|
|
316
|
+
"scripts/check_gh_argv_containment.py",
|
|
316
317
|
"scripts/codegen.py",
|
|
317
318
|
"scripts/coord-test-runner.sh",
|
|
318
319
|
"scripts/drive-batch.sh",
|
|
@@ -441,6 +442,7 @@
|
|
|
441
442
|
"tests/test_bug_intake.py",
|
|
442
443
|
"tests/test_build_worker_image_env_update.py",
|
|
443
444
|
"tests/test_cargo_cache.py",
|
|
445
|
+
"tests/test_check_gh_argv_containment.py",
|
|
444
446
|
"tests/test_ci_acceptance_gate_1950.py",
|
|
445
447
|
"tests/test_ci_parity_2091.py",
|
|
446
448
|
"tests/test_ci_store.py",
|
|
@@ -616,7 +618,6 @@
|
|
|
616
618
|
"tests/test_network.py",
|
|
617
619
|
"tests/test_new_issue_chat.py",
|
|
618
620
|
"tests/test_next_release_tag.py",
|
|
619
|
-
"tests/test_no_direct_gh_calls.py",
|
|
620
621
|
"tests/test_node_shim.py",
|
|
621
622
|
"tests/test_notifier_baseline.py",
|
|
622
623
|
"tests/test_notifier_cli.py",
|
|
@@ -669,6 +670,7 @@
|
|
|
669
670
|
"tests/test_release_cordon_2101.py",
|
|
670
671
|
"tests/test_release_cordon_daemon_leads_2176.py",
|
|
671
672
|
"tests/test_release_cordon_deadlock_2240.py",
|
|
673
|
+
"tests/test_release_cordon_stuck_2490.py",
|
|
672
674
|
"tests/test_release_propagate.py",
|
|
673
675
|
"tests/test_release_unified_1242.py",
|
|
674
676
|
"tests/test_release_verify.py",
|
|
@@ -1354,6 +1354,7 @@ def _apply_cordons( # noqa: PLR0912 — one linear apply-the-plan pass
|
|
|
1354
1354
|
outcome.cooling_seconds = plan.cooling_seconds
|
|
1355
1355
|
outcome.collateral_spared = list(plan.collateral_spared)
|
|
1356
1356
|
outcome.blocked_behind = plan.blocked_behind
|
|
1357
|
+
outcome.stuck_in_cooldown = list(plan.stuck_in_cooldown)
|
|
1357
1358
|
if plan.released is not None:
|
|
1358
1359
|
outcome.released = plan.released.to_dict()
|
|
1359
1360
|
# stderr as well as stdout: on the timer host this line IS the
|
|
@@ -2148,8 +2149,18 @@ def release_cordon(
|
|
|
2148
2149
|
)
|
|
2149
2150
|
)
|
|
2150
2151
|
return
|
|
2152
|
+
# #2490: hosts the newest propagate run flagged as behind, idle, and
|
|
2153
|
+
# left uncordoned only because the #2240 cooldown is suppressing new
|
|
2154
|
+
# cordons. These are exactly the machines an operator would otherwise
|
|
2155
|
+
# have to notice by hand (`coord status` showing `online • idle` on a
|
|
2156
|
+
# host that's actually stuck on an old version) — surface them even when
|
|
2157
|
+
# `active` is empty, since a stuck host is by definition NOT cordoned.
|
|
2158
|
+
stuck_hosts, stuck_target = _stuck_hosts_from_journal()
|
|
2151
2159
|
if not active:
|
|
2152
|
-
|
|
2160
|
+
if stuck_hosts:
|
|
2161
|
+
_echo_stuck_hosts(stuck_hosts, stuck_target)
|
|
2162
|
+
else:
|
|
2163
|
+
click.echo("no machines are cordoned — the fleet is free to take work")
|
|
2153
2164
|
return
|
|
2154
2165
|
for name, record in sorted(active.items()):
|
|
2155
2166
|
remaining = max(0.0, record.expires_at - now) / 60.0
|
|
@@ -2180,6 +2191,8 @@ def release_cordon(
|
|
|
2180
2191
|
f"`coord release propagate` releases it by itself after "
|
|
2181
2192
|
f"{rc.DEFAULT_MAX_DEFERRALS}."
|
|
2182
2193
|
)
|
|
2194
|
+
if stuck_hosts:
|
|
2195
|
+
_echo_stuck_hosts(stuck_hosts, stuck_target)
|
|
2183
2196
|
click.echo(
|
|
2184
2197
|
f"\nclear one with `coord release cordon --clear <machine>` "
|
|
2185
2198
|
f"(default lifetime {rc.DEFAULT_TTL_SECONDS / 60:.0f}m — a cordon "
|
|
@@ -2197,6 +2210,59 @@ def _read_propagation_records() -> list[dict]:
|
|
|
2197
2210
|
return []
|
|
2198
2211
|
|
|
2199
2212
|
|
|
2213
|
+
def _stuck_hosts_from_journal() -> tuple[list[str], str | None]:
|
|
2214
|
+
"""Hosts the NEWEST propagate run flagged as stuck-in-cooldown (#2490).
|
|
2215
|
+
|
|
2216
|
+
``CordonPlan.stuck_in_cooldown`` (mirrored onto ``CordonOutcome`` and
|
|
2217
|
+
journalled under a run's ``cordons`` key) names behind, idle hosts a run
|
|
2218
|
+
left uncordoned only because the #2240 deadlock-release cooldown is
|
|
2219
|
+
still active — the gap the issue is about: nothing gave such a host a
|
|
2220
|
+
signal or a path back to rolling for up to the cooldown's full length.
|
|
2221
|
+
|
|
2222
|
+
Only the single newest record counts, deliberately: this is a
|
|
2223
|
+
point-in-time reading ("as of the last tick"), and a host named in an
|
|
2224
|
+
older record may since have gone busy, rolled, or had its cooldown
|
|
2225
|
+
lift — reporting it from a stale record would be a false alarm, which is
|
|
2226
|
+
exactly the kind of noise this fleet already has too much of. No
|
|
2227
|
+
journal (a thin client, or a host that has never run propagate)
|
|
2228
|
+
degrades to nothing rather than raising — mirrors every other reader of
|
|
2229
|
+
this journal in this module.
|
|
2230
|
+
"""
|
|
2231
|
+
try:
|
|
2232
|
+
records = _read_propagation_records()
|
|
2233
|
+
except Exception: # noqa: BLE001 — never load-bearing
|
|
2234
|
+
return [], None
|
|
2235
|
+
if not records:
|
|
2236
|
+
return [], None
|
|
2237
|
+
newest = records[-1]
|
|
2238
|
+
if not isinstance(newest, dict):
|
|
2239
|
+
return [], None
|
|
2240
|
+
cordons = newest.get("cordons")
|
|
2241
|
+
if not isinstance(cordons, dict):
|
|
2242
|
+
return [], None
|
|
2243
|
+
stuck = cordons.get("stuck_in_cooldown") or []
|
|
2244
|
+
if not isinstance(stuck, list):
|
|
2245
|
+
return [], None
|
|
2246
|
+
target = newest.get("target_version")
|
|
2247
|
+
return [str(h) for h in stuck], (str(target) if target else None)
|
|
2248
|
+
|
|
2249
|
+
|
|
2250
|
+
def _echo_stuck_hosts(stuck_hosts: list[str], stuck_target: str | None) -> None:
|
|
2251
|
+
"""The #2490 notice both branches of ``release_cordon`` share.
|
|
2252
|
+
|
|
2253
|
+
One line per host, each naming its own override command — the format
|
|
2254
|
+
the issue itself asks for: "precision: 18m behind v0.5.192, idle, cordon
|
|
2255
|
+
suppressed by cooldown (#2240) — consider `coord agent update --machine
|
|
2256
|
+
precision`."
|
|
2257
|
+
"""
|
|
2258
|
+
version = f"v{stuck_target}" if stuck_target else "the release"
|
|
2259
|
+
click.echo(f"\n! STUCK (#2490): behind {version}, idle, cordon suppressed "
|
|
2260
|
+
"by the #2240 deadlock-release cooldown — no automatic path "
|
|
2261
|
+
"back to rolling until it lifts on its own:")
|
|
2262
|
+
for host in sorted(stuck_hosts):
|
|
2263
|
+
click.echo(f" ! {host}: consider `coord agent update --machine {host}`")
|
|
2264
|
+
|
|
2265
|
+
|
|
2200
2266
|
@release_group.command(
|
|
2201
2267
|
"rollback",
|
|
2202
2268
|
help=(
|
|
@@ -55,6 +55,30 @@ def _cordon_stall_suffix(cordons: dict) -> str:
|
|
|
55
55
|
return f" ({described})" if described else ""
|
|
56
56
|
|
|
57
57
|
|
|
58
|
+
def _stuck_in_cooldown_hosts() -> dict[str, str | None]:
|
|
59
|
+
"""Machine name -> target version, for hosts stuck-in-cooldown (#2490).
|
|
60
|
+
|
|
61
|
+
Thin wrapper around :func:`coord.commands.release._stuck_hosts_from_journal`
|
|
62
|
+
— same journal, same "newest record only" reading, reused rather than
|
|
63
|
+
reimplemented. A host in this dict is behind the target version, was
|
|
64
|
+
idle as of the last `coord release propagate` tick, and is NOT cordoned
|
|
65
|
+
(the #2240 cooldown is suppressing it) — which is exactly why it shows
|
|
66
|
+
up everywhere else in this command as a flatly ordinary `online • idle`.
|
|
67
|
+
That silence is the whole finding of #2490: a human noticed only because
|
|
68
|
+
they happened to be watching `coord status` themselves.
|
|
69
|
+
|
|
70
|
+
Degrades to ``{}`` on any error (no journal, an unreadable one, a thin
|
|
71
|
+
client) — never load-bearing, same contract as `_cordon_stall_suffix`.
|
|
72
|
+
"""
|
|
73
|
+
from coord.commands.release import _stuck_hosts_from_journal # noqa: PLC0415
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
hosts, target = _stuck_hosts_from_journal()
|
|
77
|
+
except Exception: # noqa: BLE001 — a status render must never fail on this
|
|
78
|
+
return {}
|
|
79
|
+
return {h: target for h in hosts}
|
|
80
|
+
|
|
81
|
+
|
|
58
82
|
def _live_advisory_entries(
|
|
59
83
|
entries: list[dict],
|
|
60
84
|
cfg: "Config",
|
|
@@ -187,6 +211,9 @@ def status(config_path: Path, machine_filter: str | None, no_reconcile: bool, ti
|
|
|
187
211
|
# same, which is why the 70-minute stall was invisible.
|
|
188
212
|
cordon_stall = _cordon_stall_suffix(cordons)
|
|
189
213
|
quiet_windows = effective_quiet_hours(cfg.machines)
|
|
214
|
+
# #2490: hosts the last propagate run flagged as behind + idle + stuck
|
|
215
|
+
# behind an active #2240 cooldown — see `_stuck_in_cooldown_hosts`.
|
|
216
|
+
stuck_in_cooldown = _stuck_in_cooldown_hosts()
|
|
190
217
|
|
|
191
218
|
statuses = check_all(machines, timeout=timeout)
|
|
192
219
|
agent_completed: dict[str, dict] = {}
|
|
@@ -314,6 +341,22 @@ def status(config_path: Path, machine_filter: str | None, no_reconcile: bool, ti
|
|
|
314
341
|
for repo_name, reason in degraded.items():
|
|
315
342
|
click.echo(f" ⚠ degraded: {repo_name} — {reason}")
|
|
316
343
|
|
|
344
|
+
# #2490: this host is behind the release, was idle last tick, and
|
|
345
|
+
# nothing is cordoning it because a #2240 deadlock-release cooldown
|
|
346
|
+
# is suppressing all new cordons fleet-wide. Without this line the
|
|
347
|
+
# machine above reads as a plain `online • idle` — indistinguishable
|
|
348
|
+
# from a machine with nothing to do, which is exactly how the
|
|
349
|
+
# 2026-08-20 incident went unnoticed for the length of the cooldown.
|
|
350
|
+
if m.name in stuck_in_cooldown:
|
|
351
|
+
stuck_target = stuck_in_cooldown[m.name]
|
|
352
|
+
stuck_version = f"v{stuck_target}" if stuck_target else "the release"
|
|
353
|
+
click.echo(
|
|
354
|
+
f" ⚠ STUCK: behind {stuck_version} and idle, but cordoning "
|
|
355
|
+
"is suppressed by an active #2240 deadlock-release cooldown "
|
|
356
|
+
"(#2490) — no automatic path back to rolling until it lifts; "
|
|
357
|
+
f"consider `coord agent update --machine {m.name}`"
|
|
358
|
+
)
|
|
359
|
+
|
|
317
360
|
if status_result and status_result.ok and status_result.data:
|
|
318
361
|
for entry in status_result.data.get("active", []):
|
|
319
362
|
progress = entry.get("progress")
|
|
@@ -658,6 +658,17 @@ class CordonPlan:
|
|
|
658
658
|
#: exactly when `collateral_spared` is non-empty. The single fact that
|
|
659
659
|
#: would have turned a 40-minute puzzle into one line of output.
|
|
660
660
|
blocked_behind: str | None = None
|
|
661
|
+
#: #2490: hosts that are BEHIND *target_version*, have no busy signal of
|
|
662
|
+
#: their own this run (idle), and are not being cordoned only because an
|
|
663
|
+
#: unexpired deadlock-release cooldown is suppressing all new cordons —
|
|
664
|
+
#: set exactly when ``cooling_seconds > 0``. This is the gap the issue
|
|
665
|
+
#: names: a host in this state has no automatic path back to rolling for
|
|
666
|
+
#: up to the cooldown's full length, and nothing surfaced that it was
|
|
667
|
+
#: sitting there idle, behind, and unflagged. Reported separately from
|
|
668
|
+
#: ``collateral_spared`` (blocked behind a busy daemon host — a different
|
|
669
|
+
#: reason a behind host stays uncordoned) so each surface can name the
|
|
670
|
+
#: actual cause instead of collapsing both into "not cordoned".
|
|
671
|
+
stuck_in_cooldown: tuple[str, ...] = ()
|
|
661
672
|
|
|
662
673
|
@property
|
|
663
674
|
def empty(self) -> bool:
|
|
@@ -668,6 +679,7 @@ class CordonPlan:
|
|
|
668
679
|
or self.expired
|
|
669
680
|
or self.released
|
|
670
681
|
or self.collateral_spared
|
|
682
|
+
or self.stuck_in_cooldown
|
|
671
683
|
)
|
|
672
684
|
|
|
673
685
|
def to_dict(self) -> dict:
|
|
@@ -681,6 +693,7 @@ class CordonPlan:
|
|
|
681
693
|
"cooling_seconds": self.cooling_seconds,
|
|
682
694
|
"collateral_spared": list(self.collateral_spared),
|
|
683
695
|
"blocked_behind": self.blocked_behind,
|
|
696
|
+
"stuck_in_cooldown": list(self.stuck_in_cooldown),
|
|
684
697
|
}
|
|
685
698
|
|
|
686
699
|
def render(self) -> list[str]:
|
|
@@ -718,6 +731,13 @@ class CordonPlan:
|
|
|
718
731
|
"release (#2240) is still letting the fleet work; nothing was "
|
|
719
732
|
"cordoned this run"
|
|
720
733
|
)
|
|
734
|
+
for host in self.stuck_in_cooldown:
|
|
735
|
+
lines.append(
|
|
736
|
+
f" ! STUCK: {host} is behind and idle, but cordoning is "
|
|
737
|
+
"suppressed by the deadlock-release cooldown above (#2490) — "
|
|
738
|
+
f"it has no automatic path back to rolling until the cooldown "
|
|
739
|
+
f"lifts. Consider `coord agent update --machine {host}`."
|
|
740
|
+
)
|
|
721
741
|
for esc in self.escalations:
|
|
722
742
|
lines.append(f" ! {esc.message}")
|
|
723
743
|
return lines
|
|
@@ -880,6 +900,21 @@ def plan_cordons(
|
|
|
880
900
|
pressure = pressure or DeferralPressure()
|
|
881
901
|
cooling = pressure.cooling_for(now, release_cooldown)
|
|
882
902
|
if cooling > 0:
|
|
903
|
+
# #2490: a behind host with no busy signal of its own has nothing
|
|
904
|
+
# left holding it back except this cooldown — it is idle, it is
|
|
905
|
+
# behind, and it will sit exactly like that until the cooldown
|
|
906
|
+
# lifts (up to `release_cooldown` seconds) with no cordon and,
|
|
907
|
+
# before this, no signal anywhere that it needs attention.
|
|
908
|
+
# `collateral` hosts are excluded: those are uncordoned for an
|
|
909
|
+
# unrelated reason (blocked behind a busy daemon host) that already
|
|
910
|
+
# has its own name (`collateral_spared`/`blocked_behind`).
|
|
911
|
+
stuck = tuple(
|
|
912
|
+
sorted(
|
|
913
|
+
host
|
|
914
|
+
for host in (drift.behind - collateral)
|
|
915
|
+
if not (busy_reasons or {}).get(host)
|
|
916
|
+
)
|
|
917
|
+
)
|
|
883
918
|
return CordonPlan(
|
|
884
919
|
uncordon=to_uncordon,
|
|
885
920
|
expired=expired,
|
|
@@ -887,6 +922,7 @@ def plan_cordons(
|
|
|
887
922
|
unknown=tuple(sorted(drift.undecided & set(live))),
|
|
888
923
|
collateral_spared=tuple(sorted(collateral)),
|
|
889
924
|
blocked_behind=blocked_behind,
|
|
925
|
+
stuck_in_cooldown=stuck,
|
|
890
926
|
)
|
|
891
927
|
if max_deferrals > 0 and pressure.consecutive >= max_deferrals:
|
|
892
928
|
return CordonPlan(
|
|
@@ -984,6 +1020,12 @@ class CordonOutcome:
|
|
|
984
1020
|
#: #2176: the daemon host `collateral_spared` was spared on account of.
|
|
985
1021
|
#: Mirrors `CordonPlan.blocked_behind`.
|
|
986
1022
|
blocked_behind: str | None = None
|
|
1023
|
+
#: #2490: mirrors `CordonPlan.stuck_in_cooldown` — behind, idle hosts this
|
|
1024
|
+
#: run left uncordoned only because the #2240 deadlock cooldown is still
|
|
1025
|
+
#: active. Journalled (not just printed) so a read-only surface like
|
|
1026
|
+
#: `coord status` can flag them without recomputing `plan_cordons` itself
|
|
1027
|
+
#: — see `coord.commands.status._stuck_in_cooldown_hosts`.
|
|
1028
|
+
stuck_in_cooldown: list[str] = field(default_factory=list)
|
|
987
1029
|
|
|
988
1030
|
def to_dict(self) -> dict:
|
|
989
1031
|
return {
|
|
@@ -999,4 +1041,5 @@ class CordonOutcome:
|
|
|
999
1041
|
"max_deferrals": self.max_deferrals,
|
|
1000
1042
|
"collateral_spared": list(self.collateral_spared),
|
|
1001
1043
|
"blocked_behind": self.blocked_behind,
|
|
1044
|
+
"stuck_in_cooldown": list(self.stuck_in_cooldown),
|
|
1002
1045
|
}
|
|
@@ -1294,6 +1294,14 @@ def render_record(record: PropagationRecord | Mapping[str, Any]) -> list[str]:
|
|
|
1294
1294
|
" cordons held off (post-release cooldown, #2240): "
|
|
1295
1295
|
f"{float(cordons['cooling_seconds']) / 60.0:.0f}m left"
|
|
1296
1296
|
)
|
|
1297
|
+
# #2490: name the hosts that were behind and idle but left uncordoned
|
|
1298
|
+
# purely because of the cooldown above — the gap that let `precision`
|
|
1299
|
+
# sit stuck for 30 minutes with no automatic path back to rolling.
|
|
1300
|
+
if cordons.get("stuck_in_cooldown"):
|
|
1301
|
+
lines.append(
|
|
1302
|
+
" ! STUCK (idle, behind, cooldown-suppressed, #2490): "
|
|
1303
|
+
+ ", ".join(cordons["stuck_in_cooldown"])
|
|
1304
|
+
)
|
|
1297
1305
|
for esc in cordons.get("escalated") or []:
|
|
1298
1306
|
lines.append(f" ! {esc.get('message') or esc}")
|
|
1299
1307
|
for err in cordons.get("errors") or []:
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""check_gh_argv_containment.py -- CI guard for #2135 (child of epic #1902).
|
|
3
|
+
|
|
4
|
+
The epic's headline finding (#1902) is that **every `["gh", ...]` argv
|
|
5
|
+
construction in this repo already lives inside `coord/github_ops.py`** --
|
|
6
|
+
that single fact is what makes the eventual forge-portability port a
|
|
7
|
+
*refactor* instead of a rewrite, and it is the load-bearing assumption
|
|
8
|
+
under the whole #1902 cost estimate. Until this script, that invariant was
|
|
9
|
+
protected by nothing but convention: whoever last thought to grep for it.
|
|
10
|
+
|
|
11
|
+
Same spirit as `scripts/run_tests_without_gh.sh` (#1484, the `no-gh-on-path`
|
|
12
|
+
CI job) -- that script proved `gh` calls are *mockable* by making the
|
|
13
|
+
binary unresolvable and watching the suite still pass; this script proves
|
|
14
|
+
they are *contained* by refusing any `gh` argv construction that lives
|
|
15
|
+
outside the one file that owns them. Deliberately kept a plain regex scan,
|
|
16
|
+
not an AST walk -- cheap enough to run on every PR, and the invariant it
|
|
17
|
+
guards ("does this file spell the literal string `gh` as its own quoted
|
|
18
|
+
token") does not need a parser to detect.
|
|
19
|
+
|
|
20
|
+
Supersedes `tests/test_no_direct_gh_calls.py` (#1483's original AST-based
|
|
21
|
+
guard for this same invariant, added when only `github_ops.py`'s
|
|
22
|
+
call-site shape needed catching). #2135 review flagged that the two
|
|
23
|
+
guards were an undocumented split-brain: the AST walk only fires when a
|
|
24
|
+
`["gh", ...]` literal is a *direct call argument*
|
|
25
|
+
(`subprocess.run(["gh", ...])`), so it silently missed the
|
|
26
|
+
variable-indirection shape (`cmd = ["gh", ...]; subprocess.run(cmd)`) that
|
|
27
|
+
this regex scan does catch, since it matches the token wherever it sits on
|
|
28
|
+
the line. Rather than keep two independently-maintained implementations of
|
|
29
|
+
one invariant with two different blind spots, `test_no_direct_gh_calls.py`
|
|
30
|
+
was deleted and this script is now the single implementation, exercised
|
|
31
|
+
both by the dedicated `gh-argv-containment` CI job (`.github/workflows/
|
|
32
|
+
test.yml`) and by the ordinary `pytest tests/` run, via
|
|
33
|
+
`tests/test_check_gh_argv_containment.py::test_real_tree_is_clean` and
|
|
34
|
+
friends -- one scan, reachable both ways, per the repo's "one question,
|
|
35
|
+
one answer" rule (epic #2096). The trade-off this leaves: being a plain
|
|
36
|
+
token scan rather than an AST walk, it can false-positive on a `"gh"`
|
|
37
|
+
token that isn't argv (e.g. inside a docstring or an unrelated string
|
|
38
|
+
literal) -- accepted deliberately, since a false positive costs an
|
|
39
|
+
allowlist entry or a reword, while a false negative (the AST gap above)
|
|
40
|
+
costs a silent regression of the epic's #1902 load-bearing assumption.
|
|
41
|
+
|
|
42
|
+
Usage:
|
|
43
|
+
python scripts/check_gh_argv_containment.py [repo-root]
|
|
44
|
+
|
|
45
|
+
Exit codes: 0 if the tree is clean, 1 if a `gh` argv construction is found
|
|
46
|
+
in coord/**/*.py outside coord/github_ops.py.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
import re
|
|
52
|
+
import sys
|
|
53
|
+
from dataclasses import dataclass
|
|
54
|
+
from pathlib import Path
|
|
55
|
+
|
|
56
|
+
SEAM = "coord/github_ops.py"
|
|
57
|
+
|
|
58
|
+
# Matches a bare `"gh"` or `'gh'` token -- the exact spelling every gh argv
|
|
59
|
+
# construction in this repo starts with, whether written `["gh", ...]`,
|
|
60
|
+
# `("gh", ...)`, or (as in github_ops.py's PR-checks call, where the list is
|
|
61
|
+
# opened on the previous line) as a bare leading element `"gh", "pr", ...,`.
|
|
62
|
+
# The closing quote must land immediately after the 'h', so this does not
|
|
63
|
+
# match longer identifiers that merely contain "gh", like "github" or
|
|
64
|
+
# "ghost".
|
|
65
|
+
_GH_TOKEN_RE = re.compile(r"""(["'])gh\1""")
|
|
66
|
+
|
|
67
|
+
# Explicit allowlist: (file, substring-of-the-matched-line) pairs for
|
|
68
|
+
# known-legitimate `gh` mentions outside the seam. Keyed on line CONTENT,
|
|
69
|
+
# not a line number -- numbers drift as a file changes (this very entry's
|
|
70
|
+
# line moved from prereqs.py:288, where #2135 was filed, to prereqs.py:290
|
|
71
|
+
# by the time this script was written), and a number-keyed allowlist would
|
|
72
|
+
# either miss a real leak that later lands on that number, or stop
|
|
73
|
+
# exempting the intended line the moment it shifts.
|
|
74
|
+
#
|
|
75
|
+
# Add an entry here ONLY with a comment explaining why the mention is not
|
|
76
|
+
# an argv construction -- a loose pattern (e.g. "any line in prereqs.py")
|
|
77
|
+
# would let a real leak through under cover of the exemption, which is
|
|
78
|
+
# exactly the failure mode this script exists to prevent.
|
|
79
|
+
_ALLOWLIST: tuple[tuple[str, str], ...] = (
|
|
80
|
+
(
|
|
81
|
+
"coord/prereqs.py",
|
|
82
|
+
'tool="gh", binary="gh"',
|
|
83
|
+
),
|
|
84
|
+
# ^ Prereq(tool="gh", binary="gh", version_args=("--version",), ...)
|
|
85
|
+
# probes for the `gh` BINARY's presence/version via shutil.which +
|
|
86
|
+
# `gh --version` -- it does not drive the forge, so it correctly lives
|
|
87
|
+
# outside the seam (#2135).
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(frozen=True)
|
|
92
|
+
class Violation:
|
|
93
|
+
path: str
|
|
94
|
+
lineno: int
|
|
95
|
+
line: str
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _is_allowlisted(rel_path: str, line: str) -> bool:
|
|
99
|
+
return any(
|
|
100
|
+
rel_path == allow_path and allow_substr in line
|
|
101
|
+
for allow_path, allow_substr in _ALLOWLIST
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def find_violations(repo_root: Path) -> list[Violation]:
|
|
106
|
+
"""Scan coord/**/*.py for `gh` argv construction outside the seam.
|
|
107
|
+
|
|
108
|
+
Pure function of the filesystem under ``repo_root`` -- no subprocess,
|
|
109
|
+
no network -- so it is cheap to point at a synthetic fixture tree in
|
|
110
|
+
tests, not just the real repo.
|
|
111
|
+
"""
|
|
112
|
+
violations: list[Violation] = []
|
|
113
|
+
coord_dir = repo_root / "coord"
|
|
114
|
+
if not coord_dir.is_dir():
|
|
115
|
+
return violations
|
|
116
|
+
for path in sorted(coord_dir.rglob("*.py")):
|
|
117
|
+
rel = path.relative_to(repo_root).as_posix()
|
|
118
|
+
if rel == SEAM:
|
|
119
|
+
continue
|
|
120
|
+
try:
|
|
121
|
+
text = path.read_text(encoding="utf-8")
|
|
122
|
+
except (UnicodeDecodeError, OSError) as exc:
|
|
123
|
+
# Every file under coord/ is expected to be UTF-8 Python
|
|
124
|
+
# source, so this should never actually fire -- but if it
|
|
125
|
+
# ever does, skipping silently would mean a real `gh` leak in
|
|
126
|
+
# that file goes undetected with no trace. Surface it on
|
|
127
|
+
# stderr rather than swallow it (#2135 review).
|
|
128
|
+
print(
|
|
129
|
+
f"check_gh_argv_containment: skipping {rel} "
|
|
130
|
+
f"(unreadable: {exc}) -- unable to scan for `gh` argv "
|
|
131
|
+
f"construction in this file",
|
|
132
|
+
file=sys.stderr,
|
|
133
|
+
)
|
|
134
|
+
continue
|
|
135
|
+
for lineno, line in enumerate(text.splitlines(), start=1):
|
|
136
|
+
if _GH_TOKEN_RE.search(line) and not _is_allowlisted(rel, line):
|
|
137
|
+
violations.append(Violation(rel, lineno, line.strip()))
|
|
138
|
+
return violations
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def format_report(violations: list[Violation]) -> str:
|
|
142
|
+
lines = [
|
|
143
|
+
f"check_gh_argv_containment: found `gh` argv construction outside "
|
|
144
|
+
f"{SEAM}:",
|
|
145
|
+
"",
|
|
146
|
+
]
|
|
147
|
+
for v in violations:
|
|
148
|
+
lines.append(f" {v.path}:{v.lineno}: {v.line}")
|
|
149
|
+
lines += [
|
|
150
|
+
"",
|
|
151
|
+
"Every `gh` invocation must go through coord/github_ops.py -- that "
|
|
152
|
+
"chokepoint is the load-bearing assumption behind the #1902 "
|
|
153
|
+
"forge-portability epic (it's what makes the eventual port a "
|
|
154
|
+
"refactor instead of a rewrite), and it's what makes `gh` mockable "
|
|
155
|
+
"for tests (the no-gh-on-path CI job, #1484, depends on it too).",
|
|
156
|
+
"",
|
|
157
|
+
'Fix: move this call into coord/github_ops.py. If it is a genuine '
|
|
158
|
+
'non-forge use of the literal string "gh" (like the binary-version '
|
|
159
|
+
"probe in coord/prereqs.py), add it to the ALLOWLIST in "
|
|
160
|
+
"scripts/check_gh_argv_containment.py with a comment explaining "
|
|
161
|
+
"why -- see #2135.",
|
|
162
|
+
]
|
|
163
|
+
return "\n".join(lines)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def main(argv: list[str]) -> int:
|
|
167
|
+
repo_root = Path(argv[1]) if len(argv) > 1 else Path(".")
|
|
168
|
+
violations = find_violations(repo_root.resolve())
|
|
169
|
+
if not violations:
|
|
170
|
+
return 0
|
|
171
|
+
print(format_report(violations), file=sys.stderr)
|
|
172
|
+
return 1
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
sys.exit(main(sys.argv))
|