code-coordinator 0.5.184__tar.gz → 0.5.185__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.184 → code_coordinator-0.5.185}/PKG-INFO +1 -1
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/PKG-INFO +1 -1
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/scm_version.json +2 -2
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/reports.py +170 -5
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reports.py +302 -11
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/reports.rs +105 -4
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.claude/commands/board.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.claude/commands/complete-session.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.claude/commands/coordinator.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.githooks/_lib.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.githooks/post-checkout +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.githooks/post-commit +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.githooks/post-merge +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/coord-ci-acceptance.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/workflows/auto-release.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/workflows/cargo-test.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/workflows/publish.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/workflows/release-tui.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.github/workflows/test.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/.gitignore +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/CLAUDE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/GOAL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/LICENSE +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/MANIFEST.in +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/README.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/SOURCES.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/dependency_links.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/entry_points.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/requires.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/scm_file_list.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/code_coordinator.egg-info/top_level.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/_board_mapping.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/acceptance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/acceptance_drivers.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agent.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agent_app.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agent_update.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agents/opencode/.gitignore +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agents/opencode/agents/work.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/agents/opencode/routing.jsonc +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/auto_loop.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/block_log.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/board_bool_guard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/board_service.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/board_wire.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/brain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/branch_model.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/bug_intake.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/cargo_cache.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/ci_github.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/ci_store.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/claim.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/client.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/_common.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/acceptance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/agent_ops.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/dispatch_workers.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/drive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/drive_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/gate_a.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/gates.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/issues.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/lifecycle.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/merge.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/milestone.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/plan_followup.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/plans.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/portal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/release.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/repo.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/report.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/review.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/scorecard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/sessions.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/setup.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/status.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/terminal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/test_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/commands/tui.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/comments.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/config.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/config_reload.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/conflict_fix.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dao.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dashboard/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dashboard/fixture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dashboard/index.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dashboard/server.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dashboard/terminal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/db.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dead_end.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/README.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-agent.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-db-backup.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-db-backup.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-db-backup.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-drive-queue.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-drive-queue.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-notify.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-notify.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-release-propagate.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-release-propagate.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-release-window.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-release-window.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-serve.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-web-dist-build.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-web-dist-build.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy/coord-web.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy_manifest.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deploy_units.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/deps.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/diagnose.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/dist_name.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/drive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/drive_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/drive_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/events.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/failure_class.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/filelock.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/fleet_config_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/freshness.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/gate_a.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/gate_b.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/gate_snapshot.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/gates.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/github_ops.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/goal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/graph_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/aggregate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/agent_install.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/cargo_targets.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/claude_binary.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/coord_web_ci_pin.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/deploy_lane_facts.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/disk.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/fleet_board.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/fleet_deploy_lanes.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/fleet_phantom.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/fleet_unit_drift.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/graph.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/graphify_cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/index_lock.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/plan_usage.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/repo_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/spawned_coord.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/timer_active.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/toolchain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/unit_drift.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/unit_enablement.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/checks/worktrees.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/context.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/fleet_snapshot.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/models.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/pypi.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/registry.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/render.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/health/units.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/hooks.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/housekeeping.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/interactive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/issue_store.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/liveness_auditor.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/machine_pause.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/merge_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/milestone_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/milestone_dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/milestone_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/milestone_order.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/mock_author.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/models.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/network.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/new_issue_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/baseline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/collect.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/digest.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/models.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/predicate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/service.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/store.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notifier/transport.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/notify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/openapi.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/overlap_fence.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/overlap_predict.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/parentage.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/parentage_github.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/pipeline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/plan_parser.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/plans.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/platform_paths.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/portal_bridge.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/portal_store.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/portal_sync.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/pr_body_lint.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/prereqs.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/progress.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/providers/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/providers/base.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/providers/claude.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/providers/claude_pty.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/providers/opencode.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/queue_diagnose.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/reconcile.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/reconcile_tick.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/refine_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/release_cordon.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/release_propagate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/release_verify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/release_window.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/repo_edit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/repo_onboard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/revalidate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/review.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/scorecard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/self_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/serve_app.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/coord-dispatch-verbs/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/drive-queue-preflight/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/fleet-restart-safety/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/merge-stuck-triage/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/pipeline-limbo-triage/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/portal-followup/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/review-verdict-recovery/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/tui-quadraui-workflow/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/skills/update-issue/SKILL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/smoke.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/spend_ceiling.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/split_work.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/stage_projection.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/test_author.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/test_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/test_orchestrator.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/test_report.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/tui_release.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/usage.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/usage_limits.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/usage_rollup.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coord/worker_events.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/coordinator.example.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-agent.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-db-backup.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-db-backup.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-db-backup.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-drive-queue.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-drive-queue.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-notify.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-notify.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-release-propagate.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-release-propagate.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-release-window.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-release-window.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-serve.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-web-dist-build.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-web-dist-build.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-web-dist-build.timer +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-web-rollback.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/coord-web.service +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/deploy/node-shim.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ADR_COORD_WEB_ACCEPTANCE_SUITE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ADR_COORD_WEB_CI.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ADR_COORD_WEB_DIST.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/AGENT_OPERATIONS.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ARCHITECTURE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ARCH_SECURITY_GATES.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/COCKPIT.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/CONTROL_CENTER.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/COST_DISCIPLINE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/CROSS_PLATFORM.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/CUSTOMER_PORTAL.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/DRIVE_QUEUE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/EPHEMERAL_WORKERS.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/FORGE_MIGRATION.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/GRAPHIFY_SETUP.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ISSUE_GUIDANCE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/MAC_MINI.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/MERGE_AUTO_DRAIN_TRUST_BAR.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/NOTIFIER.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/OPENCODE_VERIFICATION.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/OPERATING_GOTCHAS.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/ORACLE_LOOP.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/PHONE_WEBAPP.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/PIPELINE_V2.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/PLATFORM_EVOLUTION.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/SECOND_BACKEND.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/STORE_SERVICE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/TEST_FIRST_BUG_LANE.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/WEB_CONTROL_CENTER.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/WSL_WINDOWS_WORKER.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/mocks/web/README.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/mocks/web/_tokens.css +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/mocks/web/issue-detail.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/mocks/web/pipeline-narrow.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/docs/mocks/web/pipeline-wide.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/graphify-out/.gitignore +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/install-agent.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/pyproject.toml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/audit_review_verdict_overrides.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/bootstrap-shared.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/build-worker-image.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/coordinator-machine.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/epic-down.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/epic-up.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/preflight.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/provision-worker.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/scrub-and-generalize.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/tailnet-acl.hujson +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/azure-workers/verify-github-token.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/codegen.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/coord-test-runner.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/drive-batch.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/gen_board_fixture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/next_release_tag.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/run_tests_in_populated_home.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/run_tests_without_gh.sh +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/smoke_437_interactive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/verify_878_review_capture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/verify_release_published.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/scripts/verify_release_wheel.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/setup.cfg +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/SMOKE_SET.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/__init__.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/audit_1039.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/contract.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/manifest.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/mocks/audit-panel-detail.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/mocks/audit-panel-empty.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/mocks/audit-panel-filters.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-33/mocks/audit-panel-populated.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-37/conftest.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-37/contract.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-37/manifest.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-37/test_usage_cli_1115.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-37/test_usage_core_1118.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/contract.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/manifest.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-base.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-detail-pane.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-help-overlay.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-palette.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-rightclick-epic.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-rightclick-header.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/mocks/plans-rightclick-stub.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/plans_detail_1122.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/plans_help_1124.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-38/plans_rightclick_1123.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/contract.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/home-active-extended.spec.ts +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/home-active.spec.ts +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/manifest.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/mocks/home-active.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-51/tsconfig.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/board_split_2288.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/board_tabs_2282.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/board_tabs_close_2283.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/contract.md +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/detail_substate_2285.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/manifest.yml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-baseline-no-tabs.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-pinned-3-tabs.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-preview-tab.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-split-side-by-side.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-tab-context-menu.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-tabs-help-overlay.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/board-tabs-overflow.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/mocks/pipeline-tabs-independent.screen +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/pipeline_tabs_2284.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/tabs_discoverability_2287.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-65/tabs_persistence_2286.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/acceptance/ms-example/mocks/home-active.html +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/conftest.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/board-pipeline-basic.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/board-pipeline-terminal-gates.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/opencode_run_failure_sample.jsonl +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/opencode_run_length_sample.jsonl +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/opencode_run_sample.jsonl +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/all_pass.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/global_setup_crash.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/mixed_fail.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/retry_then_pass.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/retry_then_pass.junit.xml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/skip.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/playwright/truncated.json +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/cargo_compile_error.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/cargo_multi_target_failures.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/cargo_no_parseable_failures.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/pytest_collection_error.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/pytest_error_string_in_body.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/pytest_internal_error.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/pytest_mixed_failures.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/fixtures/test_report/pytest_no_parseable_failures.txt +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_acceptance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_acceptance_drivers.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_api_error.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_app.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_branch_base.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_branch_capture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_config_free_1712.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_deploy_units_endpoint.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_dirty_worktree.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_drive_queue_reconcile_2373.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_graph_self_heal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_health_h3.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_idle_restart.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_push_failure.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_reap.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_repos_and_pull.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_restart_services_endpoint.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_skills_self_heal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_startup_diagnostics.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_update.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_update_bluegreen.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_usage_limit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_agent_zero_commit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_ambient_home_isolation.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_approve_reject_plan.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_approve_usage_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_assignment_already_recorded_daemon.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_audit_log.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_audit_outcome.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_audit_query.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_auto_loop.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_auto_release_publish_2035.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_base_checkout_restore.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_block_log.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_cap_762.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_fixture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_read_path.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_service.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_board_wire.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_brain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_branch_model.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_bug_intake.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_build_worker_image_env_update.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cargo_cache.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_ci_acceptance_gate_1950.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_ci_parity_2091.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_ci_store.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_claim.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_acceptance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_assign.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_assign_interactive_oracle_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_assign_interactive_remote.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_assign_provider.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_assign_repo_drift_2219.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_chat_continue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_decide.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_diagnose_config_provenance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_diagnose_graph.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_diagnose_self.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_doctor.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_doctor_config_free_1801.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_doctor_config_mismatch_1712.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_drive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_drive_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_escalate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_fix_headless_review.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_gate_a.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_install_drift.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_install_skills.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_issue_create_label.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_issue_reopen.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_merge.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_assign.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_capture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_chat_add_child.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_gate_b.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_gate_c.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_order.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_remove_and_issue_close.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_milestone_ship.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_network.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_new_issue_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_plans.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_portal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_pull_artifact.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_reattach_sessions.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_refine_board.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_release_preflight.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_release_propagate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_release_window.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_repo_2220.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_scorecard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_set_review_findings.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_advisory_terminal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_merge_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_provider.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_review_finalizing.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_test_failed_tag.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_status_usage_limit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_sync_comments_873.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_test_plan.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_track.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_tui_update.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cli_wait.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_client_base_install.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_comments.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_completion_summary.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config_acceptance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config_audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config_pricing.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config_snapshot_noncanonical_2208.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_config_usage_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_conflict_fix.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_conflict_fix_semantic.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_test.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_test_runner_baseline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_test_runner_populated_home.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_test_runner_routing.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_test_runner_toolchain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coord_web_sse_restart_live.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_coordinator_machine.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_cross_platform_imports.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dashboard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dashboard_fixture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dashboard_terminal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dashboard_terminal_live.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_db.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dead_end.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_coord_db_backup.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_coord_web_dist.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_coord_web_rollback.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_drive_queue_unit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_manifest.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_units_lane.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deploy_web_unit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_deps.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_diagnose.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dispatch_target_validation.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_dist_name.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_done_housekeeping.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_drive.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_drive_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_drive_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_drive_tmux.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_epic_up_capability_detection.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_epic_up_down_symlinked_config_1887.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_epic_up_image_provenance.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_errors.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_events.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_failure_class.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_filelock.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_finalize_interactive_exit_test_verdict.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_fix_of_force_override.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_fleet_config_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_fleet_health_probes.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_fleet_health_snapshot.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_freshness.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_gate_a.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_gate_b.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_gate_snapshot_staleness.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_gates.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_gather_fleet_tmux_sessions.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_generated_types_fixture.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_github_ops.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_goal.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_graph_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_graph_selfheal_absent_2237.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_handoff.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_checks.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_cli_graph.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_config.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_context.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_coord_web_ci_pin.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_deploy_lane_facts.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_incident_regression.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_pypi.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_registry.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_timer_active.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_toolchain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_unit_drift.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_health_unit_enablement.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_hooks.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_human_attended_437.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_init.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_integration.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_briefing_echo.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_prefill_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_session_relaunch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_test_verdict_backstop.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_token_attribution.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_interactive_worktree.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_issue_store_seam.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_liveness_auditor.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_liveness_notify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_machine_pause.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_merge_queue.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_merge_verify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_milestone_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_milestone_dispatch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_milestone_gate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_milestone_order.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_milestone_seam.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_mock_author.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_model_tiering.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_models.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_models_config_labels.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_needs_attention.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_network.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_new_issue_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_next_release_tag.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_no_direct_gh_calls.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_node_shim.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_baseline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_cli.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_collect.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_config.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_drive_seam.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_isolation.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_predicate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_quiet_hours.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notifier_service.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_notify_drain.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_openapi.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_operational_defaults.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_overlap_fence.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_overlap_predict.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_packaged_deploy_units.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_parentage.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_paste_landed.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_pipeline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_plan_followup_approve_plan_command.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_plan_followup_pr_command.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_plan_followup_review_command.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_plan_only.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_plan_parser.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_platform_paths.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_portal_bridge.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_portal_config.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_portal_sync.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_pr_body_lint.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_prereqs.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_production_db_guard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_progress.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_provider_seam.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_providers.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_providers_config_labels.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_providers_pty.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_quiet_hours.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_quiet_hours_store_2146.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reap_merged_sessions.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reap_stale_interactive_tick.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_branch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_completions.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_merges.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_no_agent_record.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_tick.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_reconcile_usage_limit_done.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_refine_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_cordon_2101.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_cordon_daemon_leads_2176.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_cordon_deadlock_2240.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_propagate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_unified_1242.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_verify.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_release_window.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_remote_auto_prune.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_remote_interactive_reaper.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_repo_edit_2220.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_repo_graph_fleet_2237.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_repo_onboard_2220.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_report_result_push.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_retry.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_retry_advisory_1606.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_retry_type_1636.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_revalidate.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_end_review_without_verdict.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_parse_failure_diagnostic.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_reaffirm.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_verdict_backstop.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_verdict_override_audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_verdict_relay.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_review_zero_commits.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_scoped_review_wiring.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_scorecard.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_self_health.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_serve.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_serve_app_board_trim.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_session.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_slice_issue_attribution.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_smoke.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_smoke_live_checkout_restore.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_smoke_workflow.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_spend_ceiling.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_spend_ceiling_coordinator.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_split.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_split_work.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_stage_projection.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_stalled_pipeline.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_state.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_state_review_findings_daemon.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_status_fleet_footer.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_stop_1567.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_stuck.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_terminal_command.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_author.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_chat.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_orchestrator.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_report.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_verdict_parsing.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_test_verdict_transcript_floor.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_thin_client_board_audit.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_thin_client_config_load_1080.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_thin_client_daemon_routing_906.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_tmux_host.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_tmux_session.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_transcript_floor.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_usage.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_usage_limits.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_usage_rollup.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_venv_live_install_2121.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_version_single_source.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_watch.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_windows_job_is_a_real_gate_2000.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worker_events.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worker_image_pin_sync.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worker_safety.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worker_test_scoping.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worktree.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tests/test_worktree_rmtree_chokepoint.py +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/Cargo.lock +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/Cargo.toml +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/cargo-config-local-quadraui.toml.example +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/audit.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/chat.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/data.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/dialogs.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/doc_tabs.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/drive.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/drive_queue.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/escalation.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/events.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/fixtures.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/fleet_health.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/fleet_sessions.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/fleet_terminals.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/format.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/milestone_dag.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/mod.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/msv.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/pipeline.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/plans.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/render.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/sessions.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/settings_ui.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/sidebar.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/terminal.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/tests.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/types.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/app/workspace.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/bin/gtk.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/commands.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/lib.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/main.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/src/settings.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/tests/acceptance.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/tests/cli.rs +0 -0
- {code_coordinator-0.5.184 → code_coordinator-0.5.185}/tui/tests/fixtures/board_sample.json +0 -0
|
@@ -2623,6 +2623,13 @@ COMPLETED_COLUMNS = [
|
|
|
2623
2623
|
"title",
|
|
2624
2624
|
"started_at",
|
|
2625
2625
|
"ended_at",
|
|
2626
|
+
# #2472's four. Appended, never interleaved: the client addresses columns
|
|
2627
|
+
# by INDEX for sorting (`reports_sort_by_column`), so inserting one in the
|
|
2628
|
+
# middle would silently re-point a saved sort at a different column.
|
|
2629
|
+
"legs",
|
|
2630
|
+
"tokens_in",
|
|
2631
|
+
"tokens_out",
|
|
2632
|
+
"cost_total",
|
|
2626
2633
|
]
|
|
2627
2634
|
|
|
2628
2635
|
# One entry per COMPLETED_COLUMNS entry, same order (#1760).
|
|
@@ -2633,14 +2640,109 @@ COMPLETED_COLUMNS = [
|
|
|
2633
2640
|
# server-side report has no such screen context, and its `repo` param
|
|
2634
2641
|
# defaults to *all repos*, so the pair has to be two real columns — which is
|
|
2635
2642
|
# also what `issue-activity` already does, and what `RowIdentity` reads.
|
|
2643
|
+
#
|
|
2644
|
+
# #2472's spend columns reuse `_USAGE_COLUMN_META`'s labels/kinds verbatim
|
|
2645
|
+
# (`Legs`, `Tok In`, `Tok Out`, `Total $`) rather than inventing near-synonyms:
|
|
2646
|
+
# an operator reading `completed` and `usage` side by side is looking at the
|
|
2647
|
+
# same numbers out of the same rollup, and two spellings of "Tok In" would
|
|
2648
|
+
# imply otherwise.
|
|
2649
|
+
#
|
|
2650
|
+
# ONE cost column, not `usage`'s `cost_captured`/`cost_est` split. `usage`
|
|
2651
|
+
# splits because it is the dedicated cost report, where "some legs have no
|
|
2652
|
+
# captured cost, don't silently price at $0" (#1763) is the headline; here the
|
|
2653
|
+
# headline is still the time-range list, and a 5-column table growing to 11
|
|
2654
|
+
# would push `title` off a narrow pane. Both halves still ship as extra ROW
|
|
2655
|
+
# keys (see `_completed_spend`) — the wire contract allows row keys beyond
|
|
2656
|
+
# `columns`, so a client that wants the split has it without another column,
|
|
2657
|
+
# and `usage` remains the report to visit for it on screen.
|
|
2636
2658
|
COMPLETED_COLUMN_META = [
|
|
2637
2659
|
ColumnMeta(id="repo", label="Repo", kind="text"),
|
|
2638
2660
|
ColumnMeta(id="issue", label="Issue", kind="int", align="right"),
|
|
2639
2661
|
ColumnMeta(id="title", label="Title", kind="text", weight=3.0),
|
|
2640
2662
|
ColumnMeta(id="started_at", label="Started", kind="timestamp"),
|
|
2641
2663
|
ColumnMeta(id="ended_at", label="Ended", kind="timestamp"),
|
|
2664
|
+
ColumnMeta(id="legs", label="Legs", kind="int", align="right", weight=0.6),
|
|
2665
|
+
ColumnMeta(id="tokens_in", label="Tok In", kind="int", align="right"),
|
|
2666
|
+
ColumnMeta(id="tokens_out", label="Tok Out", kind="int", align="right"),
|
|
2667
|
+
ColumnMeta(id="cost_total", label="Total $", kind="money", align="right"),
|
|
2642
2668
|
]
|
|
2643
2669
|
|
|
2670
|
+
def _completed_spend(
|
|
2671
|
+
assignment_rows: Sequence[Mapping[str, Any]], pricing: Any
|
|
2672
|
+
) -> dict[tuple[str, int], dict[str, Any]]:
|
|
2673
|
+
"""Per-issue ``legs``/tokens/cost, keyed ``(repo_name, issue_number)``.
|
|
2674
|
+
|
|
2675
|
+
A thin adapter over :func:`coord.usage_rollup.rollup`, **not** a second
|
|
2676
|
+
cost calculator: the pricing rules, the captured-vs-estimated split and
|
|
2677
|
+
the "never silently priced at $0" unknown-model rule all stay in
|
|
2678
|
+
``usage_rollup``, exactly as #1763 requires, and the numbers are shaped by
|
|
2679
|
+
the same :func:`_usage_metrics` that builds a ``usage`` row. ``legs``
|
|
2680
|
+
therefore counts agent SESSIONS (every dispatch attempt and retry), which
|
|
2681
|
+
is what ``GroupRollup.legs`` already means — no new arithmetic here.
|
|
2682
|
+
|
|
2683
|
+
One keying detail worth being explicit about: ``rollup``'s ``IssueKey``
|
|
2684
|
+
books a leg to :func:`~coord.usage_rollup.row_issue_number`, i.e.
|
|
2685
|
+
``for_issue_number`` when the leg carries one (#1553's oracle-loop
|
|
2686
|
+
attribution), while this fold's own ``first_dispatch``/``last_finish`` key
|
|
2687
|
+
on the raw ``issue_number``. That divergence is DELIBERATE: the whole
|
|
2688
|
+
point of #2472 is that ``completed``'s cost for an issue equals what
|
|
2689
|
+
``usage`` reports for the same issue, so the cost columns must use
|
|
2690
|
+
``usage``'s attribution rule. The timestamps keep #2454's, which is a
|
|
2691
|
+
port of ``completed_rows``.
|
|
2692
|
+
"""
|
|
2693
|
+
from coord.usage_rollup import IssueKey, TimeWindow, rollup # noqa: PLC0415
|
|
2694
|
+
|
|
2695
|
+
# THE WINDOW IS UNBOUNDED — the spend figures are the issue's *lifetime*
|
|
2696
|
+
# spend, not spend inside the report's own window.
|
|
2697
|
+
#
|
|
2698
|
+
# `completed`'s `since`/`until` filters on ENDED — "what finished in this
|
|
2699
|
+
# range". An issue's legs routinely ran before that window opened (a 24h
|
|
2700
|
+
# window over an issue dispatched a week ago is the normal case, not the
|
|
2701
|
+
# edge case), so windowing the cost the same way would answer "what did
|
|
2702
|
+
# this issue cost me *today*" under a column an operator reads as "what did
|
|
2703
|
+
# finishing this issue cost me" — and would report a smaller number every
|
|
2704
|
+
# time the window narrowed, for an issue whose true cost never changed.
|
|
2705
|
+
# `usage` is where a windowed spend question belongs; it has a `window`
|
|
2706
|
+
# param and this report does not.
|
|
2707
|
+
#
|
|
2708
|
+
# Consequence worth stating: an unbounded `TimeWindow` still drops a leg
|
|
2709
|
+
# with NEITHER `dispatched_at` NOR `finished_at` (`leg_in_window` needs one
|
|
2710
|
+
# of the two to be in range, and `contains(None)` is False). Such a row is
|
|
2711
|
+
# not a session that ran — it is a row with no evidence it ever started —
|
|
2712
|
+
# and `usage` excludes it on the same rule.
|
|
2713
|
+
result = rollup(
|
|
2714
|
+
[dict(a) for a in assignment_rows],
|
|
2715
|
+
group_by="issue",
|
|
2716
|
+
window=TimeWindow(),
|
|
2717
|
+
pricing=pricing,
|
|
2718
|
+
)
|
|
2719
|
+
spend: dict[tuple[str, int], dict[str, Any]] = {}
|
|
2720
|
+
for key, group in result.groups.items():
|
|
2721
|
+
if not isinstance(key, IssueKey) or not key.repo_name:
|
|
2722
|
+
continue
|
|
2723
|
+
spend[(str(key.repo_name), int(key.issue_number))] = _usage_metrics(group)
|
|
2724
|
+
return spend
|
|
2725
|
+
|
|
2726
|
+
|
|
2727
|
+
#: What a row gets when the rollup saw no legs at all for its issue — a real
|
|
2728
|
+
#: zero, not a missing key. An issue can be closed with no assignment ever
|
|
2729
|
+
#: dispatched against it (closed by hand, or fixed as a drive-by in someone
|
|
2730
|
+
#: else's PR), and that row's honest answer is "0 legs, $0", not a blank cell
|
|
2731
|
+
#: a client would have to guess the meaning of.
|
|
2732
|
+
_COMPLETED_NO_LEGS: dict[str, Any] = {
|
|
2733
|
+
"legs": 0,
|
|
2734
|
+
"tokens_in": 0,
|
|
2735
|
+
"tokens_out": 0,
|
|
2736
|
+
"cost_captured": 0.0,
|
|
2737
|
+
"cost_est": 0.0,
|
|
2738
|
+
"cost_total": 0.0,
|
|
2739
|
+
"tokens_cache_read": 0,
|
|
2740
|
+
"tokens_cache_creation": 0,
|
|
2741
|
+
"duration_secs": 0.0,
|
|
2742
|
+
"open_legs": 0,
|
|
2743
|
+
"unknown_model_legs": 0,
|
|
2744
|
+
}
|
|
2745
|
+
|
|
2644
2746
|
|
|
2645
2747
|
def fold_completed(
|
|
2646
2748
|
issues: Iterable[Mapping[str, Any]],
|
|
@@ -2650,6 +2752,8 @@ def fold_completed(
|
|
|
2650
2752
|
*,
|
|
2651
2753
|
repo: str = "",
|
|
2652
2754
|
generated_at: float | None = None,
|
|
2755
|
+
pricing: Any = None,
|
|
2756
|
+
extra_notes: Sequence[str] = (),
|
|
2653
2757
|
) -> ReportResult:
|
|
2654
2758
|
"""Fold the board's own tables into one row per issue that *finished*
|
|
2655
2759
|
inside ``window``.
|
|
@@ -2658,6 +2762,12 @@ def fold_completed(
|
|
|
2658
2762
|
above is testable without a database (same posture as
|
|
2659
2763
|
:func:`fold_issue_activity`). Rows come back newest-ENDED first, which
|
|
2660
2764
|
is #2405's default order; the client re-sorts by column head-click.
|
|
2765
|
+
|
|
2766
|
+
*pricing* left at ``None`` falls through to ``usage_rollup``'s built-in
|
|
2767
|
+
default rates, which is correct for a unit test and **not** what the
|
|
2768
|
+
runner does — :func:`run_completed` loads ``coordinator.yml`` and passes
|
|
2769
|
+
the real ``pricing:`` block, the same seam :func:`fold_usage` uses and for
|
|
2770
|
+
the same #1763 reason.
|
|
2661
2771
|
"""
|
|
2662
2772
|
start, end = window
|
|
2663
2773
|
generated_at = time.time() if generated_at is None else float(generated_at)
|
|
@@ -2719,6 +2829,8 @@ def fold_completed(
|
|
|
2719
2829
|
if value is not None and value > last_finish.get(key, float("-inf")):
|
|
2720
2830
|
last_finish[key] = value
|
|
2721
2831
|
|
|
2832
|
+
spend = _completed_spend(assignment_rows, pricing)
|
|
2833
|
+
|
|
2722
2834
|
rows: list[dict] = []
|
|
2723
2835
|
no_end_time = 0
|
|
2724
2836
|
for issue in issue_rows:
|
|
@@ -2752,6 +2864,10 @@ def fold_completed(
|
|
|
2752
2864
|
"title": str(issue.get("title") or "") or None,
|
|
2753
2865
|
"started_at": first_dispatch.get(key),
|
|
2754
2866
|
"ended_at": ended,
|
|
2867
|
+
# #2472. `**` copies the pairs into this row's own dict, so
|
|
2868
|
+
# the shared `_COMPLETED_NO_LEGS` constant can never end up
|
|
2869
|
+
# aliased by two zero-leg rows.
|
|
2870
|
+
**spend.get(key, _COMPLETED_NO_LEGS),
|
|
2755
2871
|
}
|
|
2756
2872
|
)
|
|
2757
2873
|
|
|
@@ -2760,7 +2876,7 @@ def fold_completed(
|
|
|
2760
2876
|
# `sort_completed_rows` takes the same precaution for the same reason).
|
|
2761
2877
|
rows.sort(key=lambda r: (-float(r["ended_at"]), r["repo"], r["issue"]))
|
|
2762
2878
|
|
|
2763
|
-
notes: list[str] =
|
|
2879
|
+
notes: list[str] = list(extra_notes)
|
|
2764
2880
|
if no_end_time:
|
|
2765
2881
|
notes.append(
|
|
2766
2882
|
f"{no_end_time} completed issue(s) have no end timestamp (no merged "
|
|
@@ -2774,6 +2890,27 @@ def fold_completed(
|
|
|
2774
2890
|
f"No issue in this board belongs to repo {repo_filter!r} — check the "
|
|
2775
2891
|
"coord-local repo name (the one in coordinator.yml), not the GitHub slug."
|
|
2776
2892
|
)
|
|
2893
|
+
# #1763's rule is "never silently priced at $0", and `cost_total` here is
|
|
2894
|
+
# exactly the number that would go silently short. So it IS noted — but as
|
|
2895
|
+
# ONE aggregate line rather than `fold_usage`'s line-per-issue: this report
|
|
2896
|
+
# is a time-range list that can easily carry a hundred rows, and a hundred
|
|
2897
|
+
# near-identical notes would bury the two above that are about the list
|
|
2898
|
+
# itself. The per-issue breakdown is a question for `usage`, which the note
|
|
2899
|
+
# names.
|
|
2900
|
+
unpriced = sorted(
|
|
2901
|
+
f"{r['repo']}#{r['issue']}" for r in rows if r.get("unknown_model_legs")
|
|
2902
|
+
)
|
|
2903
|
+
if unpriced:
|
|
2904
|
+
shown = ", ".join(unpriced[:5])
|
|
2905
|
+
more = f" (and {len(unpriced) - 5} more)" if len(unpriced) > 5 else ""
|
|
2906
|
+
notes.append(
|
|
2907
|
+
f"{len(unpriced)} issue(s) ran leg(s) on a model with no entry in "
|
|
2908
|
+
f"the loaded `pricing:` config — {shown}{more}. Their tokens are "
|
|
2909
|
+
"counted but that spend is NOT in `Total $` (never silently priced "
|
|
2910
|
+
"at $0), so those rows read LOW. Add a rate for the model to "
|
|
2911
|
+
"coordinator.yml, or run the `usage` report for the per-issue "
|
|
2912
|
+
"breakdown."
|
|
2913
|
+
)
|
|
2777
2914
|
|
|
2778
2915
|
return ReportResult(
|
|
2779
2916
|
report_id="completed",
|
|
@@ -2805,10 +2942,21 @@ def _default_completed_source() -> tuple[list[dict], list[dict], list[dict]]:
|
|
|
2805
2942
|
"SELECT repo_name, number, title, state FROM issues"
|
|
2806
2943
|
).fetchall()
|
|
2807
2944
|
]
|
|
2945
|
+
# #2472 widens this one SELECT rather than adding a second source
|
|
2946
|
+
# function: the spend columns fold out of the SAME assignment rows the
|
|
2947
|
+
# timestamps do, so a second round trip would re-read the same table to
|
|
2948
|
+
# get columns this one could have carried. Everything past
|
|
2949
|
+
# `finished_at` is what `usage_rollup.rollup`/`leg_cost` read — token
|
|
2950
|
+
# counts, the captured `cost_usd`, the `model` its estimate is keyed
|
|
2951
|
+
# by, and `for_issue_number` for #1553's attribution. `type` is NOT
|
|
2952
|
+
# selected: it only feeds `usage`'s per-stage drill-down, which this
|
|
2953
|
+
# report does not emit.
|
|
2808
2954
|
assignments = [
|
|
2809
2955
|
dict(r)
|
|
2810
2956
|
for r in conn.execute(
|
|
2811
|
-
"SELECT repo_name, issue_number,
|
|
2957
|
+
"SELECT repo_name, issue_number, for_issue_number, "
|
|
2958
|
+
"dispatched_at, finished_at, input_tokens, output_tokens, "
|
|
2959
|
+
"cache_read_tokens, cache_creation_tokens, cost_usd, model "
|
|
2812
2960
|
"FROM assignments"
|
|
2813
2961
|
).fetchall()
|
|
2814
2962
|
]
|
|
@@ -2834,9 +2982,10 @@ def run_completed(
|
|
|
2834
2982
|
Sequence[Mapping[str, Any]],
|
|
2835
2983
|
Sequence[Mapping[str, Any]],
|
|
2836
2984
|
]] | None = None,
|
|
2985
|
+
pricing: Any = None,
|
|
2837
2986
|
) -> ReportResult:
|
|
2838
|
-
"""Read the board and fold it. ``now``/``source`` are test
|
|
2839
|
-
(mirrors :func:`run_issue_activity`); the report's own parameters are
|
|
2987
|
+
"""Read the board and fold it. ``now``/``source``/``pricing`` are test
|
|
2988
|
+
seams (mirrors :func:`run_issue_activity`); the report's own parameters are
|
|
2840
2989
|
``since``/``until``/``repo`` — the same three, with the same vocabulary
|
|
2841
2990
|
and the same validators, that ``issue-activity`` uses."""
|
|
2842
2991
|
generated_at = time.time() if now is None else float(now)
|
|
@@ -2844,6 +2993,15 @@ def run_completed(
|
|
|
2844
2993
|
start = end - parse_duration(since)
|
|
2845
2994
|
source_fn = _default_completed_source if source is None else source
|
|
2846
2995
|
issues, assignments, merge_queue = source_fn()
|
|
2996
|
+
|
|
2997
|
+
# Same seam, same reason as `run_usage`: the estimated half of `cost_total`
|
|
2998
|
+
# has to be priced off the fleet's OWN `pricing:` block, and a config that
|
|
2999
|
+
# could not be loaded says so in a note instead of silently falling back
|
|
3000
|
+
# (#1763).
|
|
3001
|
+
extra_notes: list[str] = []
|
|
3002
|
+
if pricing is None:
|
|
3003
|
+
pricing, extra_notes = _load_pricing()
|
|
3004
|
+
|
|
2847
3005
|
return fold_completed(
|
|
2848
3006
|
issues,
|
|
2849
3007
|
assignments,
|
|
@@ -2851,6 +3009,8 @@ def run_completed(
|
|
|
2851
3009
|
(start, end),
|
|
2852
3010
|
repo=repo,
|
|
2853
3011
|
generated_at=generated_at,
|
|
3012
|
+
pricing=pricing,
|
|
3013
|
+
extra_notes=extra_notes,
|
|
2854
3014
|
)
|
|
2855
3015
|
|
|
2856
3016
|
|
|
@@ -2938,7 +3098,12 @@ COMPLETED = ReportDef(
|
|
|
2938
3098
|
"merged (the PR closed it before the brain synced the close). ENDED is "
|
|
2939
3099
|
"the merge timestamp, falling back to the last assignment to finish; "
|
|
2940
3100
|
"STARTED is the first dispatch. Issues with no end timestamp at all "
|
|
2941
|
-
"cannot be placed in a time range and are counted in a note instead."
|
|
3101
|
+
"cannot be placed in a time range and are counted in a note instead. "
|
|
3102
|
+
"Each row also carries what it cost: LEGS is how many agent sessions "
|
|
3103
|
+
"(dispatches and retries) ran against the issue, and the token and "
|
|
3104
|
+
"dollar figures are the issue's WHOLE-LIFE spend — not just the part "
|
|
3105
|
+
"inside this window — so narrowing the range never shrinks them. Use "
|
|
3106
|
+
"the `usage` report for windowed spend or the captured/estimated split."
|
|
2942
3107
|
),
|
|
2943
3108
|
params=(
|
|
2944
3109
|
# The same three params, the same vocabulary and the same validators
|
|
@@ -36,6 +36,7 @@ from coord.drive_queue import QUEUE_ALERT_ISSUE, QUEUE_ALERT_REPO
|
|
|
36
36
|
from coord.gate_a import park_marker
|
|
37
37
|
from coord.models import POLICY_REFUSAL_MARKER
|
|
38
38
|
from coord.reports import (
|
|
39
|
+
COMPLETED_COLUMNS,
|
|
39
40
|
REPORTS,
|
|
40
41
|
ColumnMeta,
|
|
41
42
|
ReportError,
|
|
@@ -4027,15 +4028,34 @@ def _completed_issues() -> list[dict]:
|
|
|
4027
4028
|
|
|
4028
4029
|
|
|
4029
4030
|
def _completed_assignments() -> list[dict]:
|
|
4031
|
+
"""#2454's timestamps plus #2472's spend, on the same rows.
|
|
4032
|
+
|
|
4033
|
+
The spend numbers are chosen to be exact under the DEFAULT
|
|
4034
|
+
:class:`~coord.config.PricingConfig` (sonnet input is $3.00/Mtok — see
|
|
4035
|
+
`TestUsagePricingFollowsConfig`), so the assertions can name a dollar
|
|
4036
|
+
figure instead of an approximation of one:
|
|
4037
|
+
|
|
4038
|
+
* myrepo#7's first leg estimates to exactly $3.00 and its RETRY carries a
|
|
4039
|
+
captured $2.00, so the issue is 2 legs / $5.00 — and the two halves
|
|
4040
|
+
exercise both branches of `leg_cost` in one row.
|
|
4041
|
+
* myrepo#9 is merged with NO assignment at all: 0 legs, $0.
|
|
4042
|
+
* other#7 is a fat leg that must not leak into myrepo#7's spend any more
|
|
4043
|
+
than it leaks into its timestamps.
|
|
4044
|
+
"""
|
|
4030
4045
|
return [
|
|
4031
4046
|
# Two legs on #7 — STARTED is the FIRST dispatch, ENDED the LAST finish.
|
|
4032
|
-
{"repo_name": "myrepo", "issue_number": 7, "dispatched_at": 100.0, "finished_at": 200.0
|
|
4033
|
-
|
|
4034
|
-
{"repo_name": "myrepo", "issue_number":
|
|
4035
|
-
|
|
4047
|
+
{"repo_name": "myrepo", "issue_number": 7, "dispatched_at": 100.0, "finished_at": 200.0,
|
|
4048
|
+
"model": "sonnet", "input_tokens": 1_000_000, "output_tokens": 0},
|
|
4049
|
+
{"repo_name": "myrepo", "issue_number": 7, "dispatched_at": 150.0, "finished_at": 250.0,
|
|
4050
|
+
"model": "sonnet", "cost_usd": 2.0, "input_tokens": 10, "output_tokens": 4},
|
|
4051
|
+
{"repo_name": "myrepo", "issue_number": 11, "dispatched_at": 900.0, "finished_at": None,
|
|
4052
|
+
"model": "sonnet", "input_tokens": 500, "output_tokens": 500},
|
|
4053
|
+
{"repo_name": "other", "issue_number": 13, "dispatched_at": 50.0, "finished_at": 300.0,
|
|
4054
|
+
"model": "sonnet", "cost_usd": 0.5, "input_tokens": 7, "output_tokens": 3},
|
|
4036
4055
|
# Same issue NUMBER in a different repo — must not contribute to
|
|
4037
|
-
# myrepo#7's timestamps.
|
|
4038
|
-
{"repo_name": "other", "issue_number": 7, "dispatched_at": 1.0, "finished_at": 9999.0
|
|
4056
|
+
# myrepo#7's timestamps, nor to its tokens or cost.
|
|
4057
|
+
{"repo_name": "other", "issue_number": 7, "dispatched_at": 1.0, "finished_at": 9999.0,
|
|
4058
|
+
"model": "sonnet", "cost_usd": 999.0, "input_tokens": 9_000_000, "output_tokens": 9_000},
|
|
4039
4059
|
]
|
|
4040
4060
|
|
|
4041
4061
|
|
|
@@ -4063,7 +4083,12 @@ class TestCompletedFold:
|
|
|
4063
4083
|
def test_columns_are_the_wire_contract(self) -> None:
|
|
4064
4084
|
result = _fold_completed()
|
|
4065
4085
|
assert result.report_id == "completed"
|
|
4066
|
-
assert result.columns == [
|
|
4086
|
+
assert result.columns == [
|
|
4087
|
+
"repo", "issue", "title", "started_at", "ended_at",
|
|
4088
|
+
# #2472's four, APPENDED — the client sorts by column index, so
|
|
4089
|
+
# #2454's five must keep the indices they had.
|
|
4090
|
+
"legs", "tokens_in", "tokens_out", "cost_total",
|
|
4091
|
+
]
|
|
4067
4092
|
assert [m.id for m in result.column_meta] == result.columns
|
|
4068
4093
|
|
|
4069
4094
|
def test_only_closed_or_merged_issues_appear(self) -> None:
|
|
@@ -4145,6 +4170,243 @@ class TestCompletedFold:
|
|
|
4145
4170
|
json.dumps(_fold_completed().to_dict())
|
|
4146
4171
|
|
|
4147
4172
|
|
|
4173
|
+
class TestCompletedSpend:
|
|
4174
|
+
"""#2472: the spend half of a row — `legs`, tokens and `cost_total`.
|
|
4175
|
+
|
|
4176
|
+
Every number here comes out of `coord.usage_rollup.rollup`; these tests
|
|
4177
|
+
pin the *joining* (right issue, right repo, right window) and the fact
|
|
4178
|
+
that `completed` and `usage` cannot disagree, which is the whole point of
|
|
4179
|
+
reusing the rollup instead of writing a second cost calculator.
|
|
4180
|
+
"""
|
|
4181
|
+
|
|
4182
|
+
def _row(self, issue: int = 7, repo: str = "myrepo", **kw) -> dict:
|
|
4183
|
+
return next(
|
|
4184
|
+
r for r in _fold_completed(**kw).rows
|
|
4185
|
+
if r["repo"] == repo and r["issue"] == issue
|
|
4186
|
+
)
|
|
4187
|
+
|
|
4188
|
+
def test_legs_counts_agent_sessions_not_issues(self) -> None:
|
|
4189
|
+
"""myrepo#7 was dispatched twice — a retry. `legs` is 2, not 1."""
|
|
4190
|
+
assert self._row(7)["legs"] == 2
|
|
4191
|
+
# …and an issue with a single leg reads 1, so `legs` is not just
|
|
4192
|
+
# "number of rows folded".
|
|
4193
|
+
assert self._row(13, repo="other")["legs"] == 1
|
|
4194
|
+
|
|
4195
|
+
def test_tokens_are_summed_across_every_leg(self) -> None:
|
|
4196
|
+
row = self._row(7)
|
|
4197
|
+
assert row["tokens_in"] == 1_000_010 # 1_000_000 + 10
|
|
4198
|
+
assert row["tokens_out"] == 4 # 0 + 4
|
|
4199
|
+
|
|
4200
|
+
def test_cost_total_is_captured_plus_estimated(self) -> None:
|
|
4201
|
+
row = self._row(7)
|
|
4202
|
+
# The retry's captured $2.00 is kept verbatim; the first leg has no
|
|
4203
|
+
# captured cost so its 1M sonnet input tokens estimate to $3.00.
|
|
4204
|
+
assert row["cost_total"] == pytest.approx(5.0)
|
|
4205
|
+
|
|
4206
|
+
def test_the_captured_estimated_split_ships_as_extra_row_keys(self) -> None:
|
|
4207
|
+
"""One `Total $` COLUMN, but no information thrown away — a client
|
|
4208
|
+
that wants `usage`'s split can read it off the row."""
|
|
4209
|
+
row = self._row(7)
|
|
4210
|
+
assert row["cost_captured"] == pytest.approx(2.0)
|
|
4211
|
+
assert row["cost_est"] == pytest.approx(3.0)
|
|
4212
|
+
assert "cost_captured" not in COMPLETED_COLUMNS
|
|
4213
|
+
assert "cost_est" not in COMPLETED_COLUMNS
|
|
4214
|
+
|
|
4215
|
+
def test_spend_is_scoped_by_coord_local_repo(self) -> None:
|
|
4216
|
+
"""other#7's fat leg ($999, 9M tokens) must not reach myrepo#7 — the
|
|
4217
|
+
same scoping the timestamps get, applied to the money."""
|
|
4218
|
+
row = self._row(7)
|
|
4219
|
+
assert row["cost_total"] == pytest.approx(5.0)
|
|
4220
|
+
assert row["tokens_in"] == 1_000_010
|
|
4221
|
+
|
|
4222
|
+
def test_spend_is_lifetime_not_windowed(self) -> None:
|
|
4223
|
+
"""The documented call: the window filters ENDED, never the legs.
|
|
4224
|
+
|
|
4225
|
+
myrepo#7's legs were dispatched at 100/150 and the window opens at
|
|
4226
|
+
240 — a windowed figure would report $2.00 (or $0) here. It reports
|
|
4227
|
+
the issue's whole-life $5.00, because "what did finishing this issue
|
|
4228
|
+
cost me" must not shrink when the operator narrows the range.
|
|
4229
|
+
"""
|
|
4230
|
+
wide = self._row(7)
|
|
4231
|
+
narrow = self._row(7, window=(240.0, C_END))
|
|
4232
|
+
assert narrow["ended_at"] == 250.0, "still in the window"
|
|
4233
|
+
assert narrow["legs"] == wide["legs"] == 2
|
|
4234
|
+
assert narrow["cost_total"] == wide["cost_total"] == pytest.approx(5.0)
|
|
4235
|
+
assert narrow["tokens_in"] == wide["tokens_in"]
|
|
4236
|
+
|
|
4237
|
+
def test_an_issue_with_no_legs_reads_zero_not_blank(self) -> None:
|
|
4238
|
+
"""myrepo#9 is merged with no assignment against it at all."""
|
|
4239
|
+
row = self._row(9)
|
|
4240
|
+
assert row["legs"] == 0
|
|
4241
|
+
assert row["tokens_in"] == 0
|
|
4242
|
+
assert row["tokens_out"] == 0
|
|
4243
|
+
assert row["cost_total"] == 0.0
|
|
4244
|
+
# A real 0, not a hole a client would have to render as "?".
|
|
4245
|
+
for column in COMPLETED_COLUMNS:
|
|
4246
|
+
assert column in row
|
|
4247
|
+
|
|
4248
|
+
def test_the_no_legs_default_is_not_shared_between_rows(self) -> None:
|
|
4249
|
+
"""`_COMPLETED_NO_LEGS` is a module constant; two zero-leg rows must
|
|
4250
|
+
not end up aliasing one mapping."""
|
|
4251
|
+
result = fold_completed(
|
|
4252
|
+
[
|
|
4253
|
+
{"repo_name": "r", "number": 1, "title": "a", "state": "closed"},
|
|
4254
|
+
{"repo_name": "r", "number": 2, "title": "b", "state": "closed"},
|
|
4255
|
+
],
|
|
4256
|
+
[],
|
|
4257
|
+
[
|
|
4258
|
+
{"repo_name": "r", "issue_number": 1, "state": "merged", "last_attempt": 10.0},
|
|
4259
|
+
{"repo_name": "r", "issue_number": 2, "state": "merged", "last_attempt": 20.0},
|
|
4260
|
+
],
|
|
4261
|
+
(C_START, C_END),
|
|
4262
|
+
generated_at=C_END,
|
|
4263
|
+
)
|
|
4264
|
+
first, second = result.rows
|
|
4265
|
+
first["legs"] = 99
|
|
4266
|
+
assert second["legs"] == 0
|
|
4267
|
+
|
|
4268
|
+
def test_every_completed_row_agrees_with_the_usage_report(self) -> None:
|
|
4269
|
+
"""The load-bearing guard, and the reason #2472 exists: an operator
|
|
4270
|
+
must never have to open `usage` and cross-reference by issue number to
|
|
4271
|
+
find a different number for the same issue."""
|
|
4272
|
+
from coord.config import PricingConfig
|
|
4273
|
+
from coord.reports import fold_usage
|
|
4274
|
+
from coord.usage_rollup import TimeWindow
|
|
4275
|
+
|
|
4276
|
+
pricing = PricingConfig()
|
|
4277
|
+
completed = _fold_completed(pricing=pricing)
|
|
4278
|
+
usage = fold_usage(
|
|
4279
|
+
_completed_assignments(),
|
|
4280
|
+
TimeWindow(start=None, end=None, label="all"),
|
|
4281
|
+
group_by="issue",
|
|
4282
|
+
pricing=pricing,
|
|
4283
|
+
)
|
|
4284
|
+
by_issue = {(r["repo"], r["issue"]): r for r in usage.rows}
|
|
4285
|
+
|
|
4286
|
+
checked = 0
|
|
4287
|
+
for row in completed.rows:
|
|
4288
|
+
peer = by_issue.get((row["repo"], row["issue"]))
|
|
4289
|
+
if peer is None:
|
|
4290
|
+
assert row["legs"] == 0, "only a no-leg issue may be absent from usage"
|
|
4291
|
+
continue
|
|
4292
|
+
for key in ("legs", "tokens_in", "tokens_out"):
|
|
4293
|
+
assert row[key] == peer[key], f"{row['repo']}#{row['issue']} {key}"
|
|
4294
|
+
assert row["cost_total"] == pytest.approx(peer["cost_total"])
|
|
4295
|
+
checked += 1
|
|
4296
|
+
assert checked >= 2, "the comparison must actually have compared something"
|
|
4297
|
+
|
|
4298
|
+
def test_a_leg_booked_to_another_issue_follows_usages_attribution(self) -> None:
|
|
4299
|
+
"""#1553: a leg carrying `for_issue_number` is spend on THAT issue.
|
|
4300
|
+
|
|
4301
|
+
`completed`'s timestamps key on the raw `issue_number` (#2454's rule,
|
|
4302
|
+
a port of `completed_rows`), but the cost columns must key the way
|
|
4303
|
+
`usage` does or the two reports would disagree — which is exactly what
|
|
4304
|
+
the previous test forbids.
|
|
4305
|
+
"""
|
|
4306
|
+
result = fold_completed(
|
|
4307
|
+
[{"repo_name": "myrepo", "number": 7, "title": "t", "state": "closed"}],
|
|
4308
|
+
[
|
|
4309
|
+
{"repo_name": "myrepo", "issue_number": 7,
|
|
4310
|
+
"dispatched_at": 100.0, "finished_at": 200.0,
|
|
4311
|
+
"model": "sonnet", "cost_usd": 1.0},
|
|
4312
|
+
# An oracle-loop acceptance slice: filed under the milestone's
|
|
4313
|
+
# tracking issue 999, but its spend belongs to #7.
|
|
4314
|
+
{"repo_name": "myrepo", "issue_number": 999, "for_issue_number": 7,
|
|
4315
|
+
"dispatched_at": 300.0, "finished_at": 400.0,
|
|
4316
|
+
"model": "sonnet", "cost_usd": 4.0},
|
|
4317
|
+
],
|
|
4318
|
+
[],
|
|
4319
|
+
(C_START, C_END),
|
|
4320
|
+
generated_at=C_END,
|
|
4321
|
+
)
|
|
4322
|
+
row = result.rows[0]
|
|
4323
|
+
assert row["legs"] == 2
|
|
4324
|
+
assert row["cost_total"] == pytest.approx(5.0)
|
|
4325
|
+
# …while ENDED stays #2454's: the last finish of an assignment whose
|
|
4326
|
+
# own `issue_number` is 7.
|
|
4327
|
+
assert row["ended_at"] == 200.0
|
|
4328
|
+
|
|
4329
|
+
def test_an_unpriced_model_is_noted_rather_than_shown_as_zero(self) -> None:
|
|
4330
|
+
"""#1763's rule, kept: a leg on a model with no `pricing:` entry is
|
|
4331
|
+
never silently priced at $0."""
|
|
4332
|
+
result = fold_completed(
|
|
4333
|
+
[{"repo_name": "myrepo", "number": 7, "title": "t", "state": "closed"}],
|
|
4334
|
+
[{"repo_name": "myrepo", "issue_number": 7,
|
|
4335
|
+
"dispatched_at": 100.0, "finished_at": 200.0,
|
|
4336
|
+
"model": "gpt-hypothetical", "input_tokens": 500, "output_tokens": 500}],
|
|
4337
|
+
[],
|
|
4338
|
+
(C_START, C_END),
|
|
4339
|
+
generated_at=C_END,
|
|
4340
|
+
)
|
|
4341
|
+
row = result.rows[0]
|
|
4342
|
+
# Tokens counted, spend NOT invented.
|
|
4343
|
+
assert row["tokens_in"] == 500
|
|
4344
|
+
assert row["cost_total"] == 0.0
|
|
4345
|
+
note = next(n for n in result.notes if "pricing" in n)
|
|
4346
|
+
assert "myrepo#7" in note
|
|
4347
|
+
assert "read LOW" in note
|
|
4348
|
+
|
|
4349
|
+
def test_the_unpriced_note_is_one_line_not_one_per_issue(self) -> None:
|
|
4350
|
+
"""`usage` emits a note per issue; `completed` is a time-range list
|
|
4351
|
+
that can carry a hundred rows, so it aggregates."""
|
|
4352
|
+
issues = [
|
|
4353
|
+
{"repo_name": "myrepo", "number": n, "title": "t", "state": "closed"}
|
|
4354
|
+
for n in range(1, 9)
|
|
4355
|
+
]
|
|
4356
|
+
assignments = [
|
|
4357
|
+
{"repo_name": "myrepo", "issue_number": n,
|
|
4358
|
+
"dispatched_at": 10.0 * n, "finished_at": 20.0 * n,
|
|
4359
|
+
"model": "gpt-hypothetical", "input_tokens": 10, "output_tokens": 10}
|
|
4360
|
+
for n in range(1, 9)
|
|
4361
|
+
]
|
|
4362
|
+
result = fold_completed(
|
|
4363
|
+
issues, assignments, [], (C_START, C_END), generated_at=C_END
|
|
4364
|
+
)
|
|
4365
|
+
pricing_notes = [n for n in result.notes if "pricing" in n]
|
|
4366
|
+
assert len(pricing_notes) == 1, pricing_notes
|
|
4367
|
+
assert "8 issue(s)" in pricing_notes[0]
|
|
4368
|
+
assert "and 3 more" in pricing_notes[0], "the list is capped, and says so"
|
|
4369
|
+
|
|
4370
|
+
def test_a_priced_fixture_still_produces_no_notes(self) -> None:
|
|
4371
|
+
"""The spend columns must not make every clean report noisy."""
|
|
4372
|
+
assert _fold_completed().notes == []
|
|
4373
|
+
|
|
4374
|
+
def test_pricing_overrides_move_the_estimate(self) -> None:
|
|
4375
|
+
"""Same #1116/#1763 seam `usage` has: the fleet's own `pricing:` block
|
|
4376
|
+
is what the dollar column is computed from, not a snapshot."""
|
|
4377
|
+
from coord.config import ModelRates, PricingConfig
|
|
4378
|
+
|
|
4379
|
+
override = PricingConfig(models={"sonnet": ModelRates(input=9.0, output=0.0)})
|
|
4380
|
+
row = self._row(7, pricing=override)
|
|
4381
|
+
# The captured $2.00 is untouched; the estimated leg's 1M input tokens
|
|
4382
|
+
# now price at $9.00 instead of $3.00.
|
|
4383
|
+
assert row["cost_captured"] == pytest.approx(2.0)
|
|
4384
|
+
assert row["cost_est"] == pytest.approx(9.0)
|
|
4385
|
+
assert row["cost_total"] == pytest.approx(11.0)
|
|
4386
|
+
|
|
4387
|
+
def test_a_leg_with_no_timestamps_at_all_is_not_counted(self) -> None:
|
|
4388
|
+
"""Documented consequence of the unbounded rollup window: a row with
|
|
4389
|
+
neither `dispatched_at` nor `finished_at` is not evidence a session
|
|
4390
|
+
ran, and `usage` excludes it on the same rule."""
|
|
4391
|
+
result = fold_completed(
|
|
4392
|
+
[{"repo_name": "myrepo", "number": 7, "title": "t", "state": "closed"}],
|
|
4393
|
+
[
|
|
4394
|
+
{"repo_name": "myrepo", "issue_number": 7,
|
|
4395
|
+
"dispatched_at": 100.0, "finished_at": 200.0, "cost_usd": 1.0},
|
|
4396
|
+
{"repo_name": "myrepo", "issue_number": 7,
|
|
4397
|
+
"dispatched_at": None, "finished_at": None, "cost_usd": 50.0},
|
|
4398
|
+
],
|
|
4399
|
+
[],
|
|
4400
|
+
(C_START, C_END),
|
|
4401
|
+
generated_at=C_END,
|
|
4402
|
+
)
|
|
4403
|
+
assert result.rows[0]["legs"] == 1
|
|
4404
|
+
assert result.rows[0]["cost_total"] == pytest.approx(1.0)
|
|
4405
|
+
|
|
4406
|
+
def test_the_result_is_still_json_serialisable(self) -> None:
|
|
4407
|
+
json.dumps(_fold_completed().to_dict())
|
|
4408
|
+
|
|
4409
|
+
|
|
4148
4410
|
class TestCompletedRunner:
|
|
4149
4411
|
def test_since_and_until_bound_the_window(self) -> None:
|
|
4150
4412
|
seen: list[tuple] = []
|
|
@@ -4200,9 +4462,20 @@ class TestCompletedAgainstTheRealSchema:
|
|
|
4200
4462
|
)
|
|
4201
4463
|
coord_db.execute(
|
|
4202
4464
|
"INSERT INTO assignments (assignment_id, machine_name, repo_name, "
|
|
4203
|
-
"issue_number, issue_title, status, dispatched_at, finished_at
|
|
4465
|
+
"issue_number, issue_title, status, dispatched_at, finished_at, "
|
|
4466
|
+
"model, cost_usd, input_tokens, output_tokens) "
|
|
4204
4467
|
"VALUES ('a1', 'precision', 'api', 1629, 'Closed and done', 'done', "
|
|
4205
|
-
"1000.0, 2000.0)"
|
|
4468
|
+
"1000.0, 2000.0, 'sonnet', 1.25, 4000, 700)"
|
|
4469
|
+
)
|
|
4470
|
+
# #2472: a RETRY, so `legs` has something to count past 1 and the
|
|
4471
|
+
# widened SELECT is proved to read every leg's tokens, not just
|
|
4472
|
+
# the first row's.
|
|
4473
|
+
coord_db.execute(
|
|
4474
|
+
"INSERT INTO assignments (assignment_id, machine_name, repo_name, "
|
|
4475
|
+
"issue_number, issue_title, status, dispatched_at, finished_at, "
|
|
4476
|
+
"model, cost_usd, input_tokens, output_tokens) "
|
|
4477
|
+
"VALUES ('a2', 'precision', 'api', 1629, 'Closed and done', 'done', "
|
|
4478
|
+
"2100.0, 2200.0, 'sonnet', 0.75, 1000, 300)"
|
|
4206
4479
|
)
|
|
4207
4480
|
coord_db.execute(
|
|
4208
4481
|
"INSERT INTO merge_queue (assignment_id, repo_name, repo_github, "
|
|
@@ -4222,6 +4495,18 @@ class TestCompletedAgainstTheRealSchema:
|
|
|
4222
4495
|
# The merged merge_queue row wins over the assignment's finished_at.
|
|
4223
4496
|
assert row["ended_at"] == 2500.0
|
|
4224
4497
|
|
|
4498
|
+
def test_the_widened_select_reaches_the_spend_columns(self, coord_db) -> None:
|
|
4499
|
+
"""#2472 added `for_issue_number`/tokens/`cost_usd`/`model` to that
|
|
4500
|
+
SELECT. They are all migration-added columns, and the source swallows
|
|
4501
|
+
every exception into an empty report — so a typo would show up as a
|
|
4502
|
+
silently blank report, never a traceback. Hence this."""
|
|
4503
|
+
self._seed(coord_db)
|
|
4504
|
+
row = run_completed(since="7d", until="3000", repo="api").rows[0]
|
|
4505
|
+
assert row["legs"] == 2, "both the first attempt and the retry"
|
|
4506
|
+
assert row["tokens_in"] == 5000 # 4000 + 1000
|
|
4507
|
+
assert row["tokens_out"] == 1000 # 700 + 300
|
|
4508
|
+
assert row["cost_total"] == pytest.approx(2.0) # 1.25 + 0.75, both captured
|
|
4509
|
+
|
|
4225
4510
|
def test_it_runs_through_the_cli(self, coord_db) -> None:
|
|
4226
4511
|
self._seed(coord_db)
|
|
4227
4512
|
result = CliRunner().invoke(
|
|
@@ -4266,8 +4551,14 @@ class TestCompletedCatalogue:
|
|
|
4266
4551
|
text = result_to_csv(_fold_completed())
|
|
4267
4552
|
# The header row is the `column_meta` LABELS (the shared serializer's
|
|
4268
4553
|
# rule), and the values stay raw epochs — not display strings.
|
|
4269
|
-
|
|
4270
|
-
|
|
4554
|
+
# #2472's four labels are `usage`'s verbatim, so a spreadsheet built
|
|
4555
|
+
# off one export lines up with the other.
|
|
4556
|
+
assert "Repo,Issue,Title,Started,Ended,Legs,Tok In,Tok Out,Total $" in text
|
|
4557
|
+
# myrepo#9 merged with no assignment: a real 0/0/0/0.0, not four
|
|
4558
|
+
# empty cells.
|
|
4559
|
+
assert 'myrepo,9,"Merged, still open",,400.0,0,0,0,0.0' in text
|
|
4560
|
+
# myrepo#7's retry: 2 legs, $2.00 captured + $3.00 estimated.
|
|
4561
|
+
assert "myrepo,7,Closed one,100.0,250.0,2,1000010,4,5.0" in text
|
|
4271
4562
|
|
|
4272
4563
|
|
|
4273
4564
|
class TestRowIdentity:
|