code-coordinator 0.5.46__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- code_coordinator-0.5.46.dist-info/METADATA +625 -0
- code_coordinator-0.5.46.dist-info/RECORD +295 -0
- code_coordinator-0.5.46.dist-info/WHEEL +5 -0
- code_coordinator-0.5.46.dist-info/entry_points.txt +2 -0
- code_coordinator-0.5.46.dist-info/licenses/LICENSE +110 -0
- code_coordinator-0.5.46.dist-info/top_level.txt +1 -0
- coord/__init__.py +176 -0
- coord/_board_mapping.py +229 -0
- coord/acceptance.py +468 -0
- coord/acceptance_drivers.py +632 -0
- coord/agent.py +7517 -0
- coord/agent_app.py +1555 -0
- coord/agent_update.py +417 -0
- coord/agents/opencode/.gitignore +13 -0
- coord/agents/opencode/agents/work.md +129 -0
- coord/agents/opencode/routing.jsonc +49 -0
- coord/audit.py +301 -0
- coord/auto_loop.py +1440 -0
- coord/board_bool_guard.py +72 -0
- coord/board_service.py +141 -0
- coord/board_wire.py +309 -0
- coord/brain.py +581 -0
- coord/branch_model.py +214 -0
- coord/cargo_cache.py +258 -0
- coord/ci_github.py +386 -0
- coord/ci_store.py +560 -0
- coord/claim.py +353 -0
- coord/cli.py +454 -0
- coord/client.py +610 -0
- coord/commands/__init__.py +1 -0
- coord/commands/_common.py +329 -0
- coord/commands/acceptance.py +916 -0
- coord/commands/agent_ops.py +1339 -0
- coord/commands/audit.py +131 -0
- coord/commands/chat.py +320 -0
- coord/commands/dispatch.py +1780 -0
- coord/commands/dispatch_workers.py +4894 -0
- coord/commands/drive.py +616 -0
- coord/commands/drive_queue.py +1203 -0
- coord/commands/gate_a.py +217 -0
- coord/commands/gates.py +89 -0
- coord/commands/issues.py +681 -0
- coord/commands/lifecycle.py +513 -0
- coord/commands/merge.py +1900 -0
- coord/commands/milestone.py +2081 -0
- coord/commands/plan_followup.py +1243 -0
- coord/commands/plans.py +156 -0
- coord/commands/release.py +2232 -0
- coord/commands/report.py +341 -0
- coord/commands/review.py +1523 -0
- coord/commands/scorecard.py +252 -0
- coord/commands/sessions.py +1930 -0
- coord/commands/setup.py +576 -0
- coord/commands/status.py +2089 -0
- coord/commands/terminal.py +385 -0
- coord/commands/test_gate.py +775 -0
- coord/commands/tui.py +288 -0
- coord/comments.py +718 -0
- coord/config.py +3032 -0
- coord/conflict_fix.py +633 -0
- coord/dao.py +483 -0
- coord/dashboard/__init__.py +0 -0
- coord/dashboard/fixture.py +376 -0
- coord/dashboard/index.html +658 -0
- coord/dashboard/server.py +1894 -0
- coord/dashboard/terminal.py +382 -0
- coord/dashboard/webapp/.gitignore +9 -0
- coord/dashboard/webapp/components.json +17 -0
- coord/dashboard/webapp/dist/assets/Gallery-da3qNiIw.js +71 -0
- coord/dashboard/webapp/dist/assets/Terminal-9CEnUXvW.css +32 -0
- coord/dashboard/webapp/dist/assets/Terminal-skVFCxPU.js +63 -0
- coord/dashboard/webapp/dist/assets/index-DltfZR5f.js +184 -0
- coord/dashboard/webapp/dist/assets/index-Dq4kwTdw.css +1 -0
- coord/dashboard/webapp/dist/assets/workbox-window.prod.es5-BqEJf4Xk.js +2 -0
- coord/dashboard/webapp/dist/icons/icon-192.png +0 -0
- coord/dashboard/webapp/dist/icons/icon-512.png +0 -0
- coord/dashboard/webapp/dist/icons/icon.svg +5 -0
- coord/dashboard/webapp/dist/index.html +38 -0
- coord/dashboard/webapp/dist/manifest.webmanifest +1 -0
- coord/dashboard/webapp/dist/sw.js +1 -0
- coord/dashboard/webapp/dist/workbox-e4022e15.js +1 -0
- coord/dashboard/webapp/e2e/available-gates-terminal.spec.ts +75 -0
- coord/dashboard/webapp/e2e/deep-link.spec.ts +172 -0
- coord/dashboard/webapp/e2e/fixtureServer.ts +155 -0
- coord/dashboard/webapp/e2e/live-update-fixture.spec.ts +113 -0
- coord/dashboard/webapp/e2e/realtime.spec.ts +238 -0
- coord/dashboard/webapp/e2e/shell.spec.ts +309 -0
- coord/dashboard/webapp/e2e/smoke.spec.ts +191 -0
- coord/dashboard/webapp/e2e/terminal.spec.ts +420 -0
- coord/dashboard/webapp/e2e/theme.spec.ts +138 -0
- coord/dashboard/webapp/eslint.config.js +20 -0
- coord/dashboard/webapp/index.html +37 -0
- coord/dashboard/webapp/node_modules/flatted/python/flatted.py +144 -0
- coord/dashboard/webapp/package-lock.json +10584 -0
- coord/dashboard/webapp/package.json +63 -0
- coord/dashboard/webapp/playwright.acceptance.config.ts +166 -0
- coord/dashboard/webapp/playwright.config.ts +93 -0
- coord/dashboard/webapp/postcss.config.js +6 -0
- coord/dashboard/webapp/public/icons/icon-192.png +0 -0
- coord/dashboard/webapp/public/icons/icon-512.png +0 -0
- coord/dashboard/webapp/public/icons/icon.svg +5 -0
- coord/dashboard/webapp/src/App.tsx +140 -0
- coord/dashboard/webapp/src/api/client.ts +199 -0
- coord/dashboard/webapp/src/api/generated.ts +176 -0
- coord/dashboard/webapp/src/components/ConnectionBadge.tsx +52 -0
- coord/dashboard/webapp/src/components/Detail.tsx +800 -0
- coord/dashboard/webapp/src/components/Gallery.tsx +341 -0
- coord/dashboard/webapp/src/components/Home.tsx +435 -0
- coord/dashboard/webapp/src/components/MobileKeyBar.tsx +280 -0
- coord/dashboard/webapp/src/components/PanelHeader.tsx +59 -0
- coord/dashboard/webapp/src/components/PipelineCard.tsx +168 -0
- coord/dashboard/webapp/src/components/SessionCard.tsx +99 -0
- coord/dashboard/webapp/src/components/SessionDetail.tsx +140 -0
- coord/dashboard/webapp/src/components/SessionsList.tsx +81 -0
- coord/dashboard/webapp/src/components/Terminal.tsx +376 -0
- coord/dashboard/webapp/src/components/__tests__/ConnectionBadge.test.tsx +81 -0
- coord/dashboard/webapp/src/components/__tests__/Detail.test.tsx +680 -0
- coord/dashboard/webapp/src/components/__tests__/Gallery.test.tsx +83 -0
- coord/dashboard/webapp/src/components/__tests__/Home.test.tsx +271 -0
- coord/dashboard/webapp/src/components/__tests__/MobileKeyBar.test.tsx +197 -0
- coord/dashboard/webapp/src/components/__tests__/PipelineCard.test.tsx +143 -0
- coord/dashboard/webapp/src/components/__tests__/SessionCard.test.tsx +106 -0
- coord/dashboard/webapp/src/components/__tests__/Terminal.test.tsx +504 -0
- coord/dashboard/webapp/src/components/ui/badge.tsx +41 -0
- coord/dashboard/webapp/src/components/ui/button.tsx +54 -0
- coord/dashboard/webapp/src/components/ui/card.tsx +55 -0
- coord/dashboard/webapp/src/components/ui/dialog.tsx +99 -0
- coord/dashboard/webapp/src/components/ui/dropdown-menu.tsx +189 -0
- coord/dashboard/webapp/src/components/ui/empty-state.tsx +35 -0
- coord/dashboard/webapp/src/components/ui/sheet.tsx +123 -0
- coord/dashboard/webapp/src/components/ui/skeleton.tsx +9 -0
- coord/dashboard/webapp/src/components/ui/tabs.tsx +55 -0
- coord/dashboard/webapp/src/components/ui/theme-provider.tsx +78 -0
- coord/dashboard/webapp/src/components/ui/theme-toggle.tsx +20 -0
- coord/dashboard/webapp/src/components/ui/toast.tsx +123 -0
- coord/dashboard/webapp/src/components/ui/toaster.tsx +30 -0
- coord/dashboard/webapp/src/components/ui/tooltip.tsx +26 -0
- coord/dashboard/webapp/src/components/ui/use-toast.ts +134 -0
- coord/dashboard/webapp/src/index.css +210 -0
- coord/dashboard/webapp/src/lib/pipeline.ts +29 -0
- coord/dashboard/webapp/src/lib/utils.ts +6 -0
- coord/dashboard/webapp/src/main.tsx +46 -0
- coord/dashboard/webapp/src/realtime/RealtimeProvider.tsx +112 -0
- coord/dashboard/webapp/src/realtime/__tests__/RealtimeProvider.test.tsx +189 -0
- coord/dashboard/webapp/src/realtime/__tests__/connection.test.ts +255 -0
- coord/dashboard/webapp/src/realtime/connection.ts +227 -0
- coord/dashboard/webapp/src/realtime/events.ts +100 -0
- coord/dashboard/webapp/src/routes/__tests__/paths.test.ts +92 -0
- coord/dashboard/webapp/src/routes/paths.ts +92 -0
- coord/dashboard/webapp/src/shell/ActivityRail.tsx +335 -0
- coord/dashboard/webapp/src/shell/AppShell.tsx +276 -0
- coord/dashboard/webapp/src/shell/ComingSoon.tsx +33 -0
- coord/dashboard/webapp/src/shell/EmptyDetail.tsx +26 -0
- coord/dashboard/webapp/src/shell/RouteNotFound.tsx +33 -0
- coord/dashboard/webapp/src/shell/ShellLayout.tsx +147 -0
- coord/dashboard/webapp/src/shell/StatusBar.tsx +46 -0
- coord/dashboard/webapp/src/shell/__tests__/ShellLayout.test.tsx +520 -0
- coord/dashboard/webapp/src/shell/__tests__/shellState.test.ts +95 -0
- coord/dashboard/webapp/src/shell/__tests__/stubViewport.ts +40 -0
- coord/dashboard/webapp/src/shell/breakpoints.ts +87 -0
- coord/dashboard/webapp/src/shell/railItems.ts +105 -0
- coord/dashboard/webapp/src/shell/shellState.ts +174 -0
- coord/dashboard/webapp/src/shell/useRegionFocus.ts +95 -0
- coord/dashboard/webapp/src/test-setup.ts +41 -0
- coord/dashboard/webapp/src/vite-env.d.ts +2 -0
- coord/dashboard/webapp/tailwind.config.js +140 -0
- coord/dashboard/webapp/tsconfig.json +25 -0
- coord/dashboard/webapp/tsconfig.node.json +11 -0
- coord/dashboard/webapp/vite.config.ts +71 -0
- coord/db.py +1076 -0
- coord/dead_end.py +332 -0
- coord/deploy/README.md +33 -0
- coord/deploy/coord-agent.service +89 -0
- coord/deploy/coord-db-backup.service +60 -0
- coord/deploy/coord-db-backup.sh +74 -0
- coord/deploy/coord-db-backup.timer +18 -0
- coord/deploy/coord-drive-queue.service +117 -0
- coord/deploy/coord-drive-queue.timer +39 -0
- coord/deploy/coord-notify.service +48 -0
- coord/deploy/coord-notify.timer +24 -0
- coord/deploy/coord-release-propagate.service +83 -0
- coord/deploy/coord-release-propagate.timer +38 -0
- coord/deploy/coord-release-window.service +119 -0
- coord/deploy/coord-release-window.timer +36 -0
- coord/deploy/coord-serve.service +82 -0
- coord/deploy/coord-web-dist-build.service +43 -0
- coord/deploy/coord-web-dist-build.timer +36 -0
- coord/deploy/coord-web.service +125 -0
- coord/deploy_manifest.py +80 -0
- coord/deploy_units.py +384 -0
- coord/deps.py +115 -0
- coord/diagnose.py +1623 -0
- coord/dispatch.py +1009 -0
- coord/dist_name.py +123 -0
- coord/drive.py +3101 -0
- coord/drive_queue.py +2298 -0
- coord/drive_state.py +870 -0
- coord/events.py +381 -0
- coord/failure_class.py +914 -0
- coord/filelock.py +168 -0
- coord/fleet_config_health.py +300 -0
- coord/freshness.py +206 -0
- coord/gate_a.py +469 -0
- coord/gate_b.py +411 -0
- coord/gate_snapshot.py +385 -0
- coord/gates.py +582 -0
- coord/github_ops.py +1954 -0
- coord/goal.py +125 -0
- coord/graph_health.py +348 -0
- coord/health/__init__.py +69 -0
- coord/health/aggregate.py +129 -0
- coord/health/checks/__init__.py +13 -0
- coord/health/checks/agent_install.py +280 -0
- coord/health/checks/cargo_targets.py +171 -0
- coord/health/checks/claude_binary.py +65 -0
- coord/health/checks/deploy_lane_facts.py +458 -0
- coord/health/checks/disk.py +99 -0
- coord/health/checks/fleet_board.py +89 -0
- coord/health/checks/fleet_deploy_lanes.py +469 -0
- coord/health/checks/fleet_phantom.py +69 -0
- coord/health/checks/fleet_unit_drift.py +151 -0
- coord/health/checks/graph.py +192 -0
- coord/health/checks/plan_usage.py +88 -0
- coord/health/checks/repo_state.py +161 -0
- coord/health/checks/spawned_coord.py +465 -0
- coord/health/checks/timer_active.py +254 -0
- coord/health/checks/toolchain.py +547 -0
- coord/health/checks/unit_drift.py +648 -0
- coord/health/checks/unit_enablement.py +171 -0
- coord/health/checks/worktrees.py +96 -0
- coord/health/cli.py +121 -0
- coord/health/context.py +106 -0
- coord/health/fleet_snapshot.py +477 -0
- coord/health/models.py +250 -0
- coord/health/pypi.py +231 -0
- coord/health/registry.py +240 -0
- coord/health/render.py +82 -0
- coord/health/units.py +60 -0
- coord/hooks.py +106 -0
- coord/housekeeping.py +204 -0
- coord/interactive.py +4286 -0
- coord/issue_store.py +1496 -0
- coord/liveness_auditor.py +293 -0
- coord/machine_pause.py +755 -0
- coord/merge_queue.py +4681 -0
- coord/milestone_chat.py +600 -0
- coord/milestone_dispatch.py +943 -0
- coord/milestone_gate.py +709 -0
- coord/milestone_order.py +840 -0
- coord/mock_author.py +334 -0
- coord/models.py +891 -0
- coord/network.py +269 -0
- coord/new_issue_chat.py +229 -0
- coord/notify.py +3226 -0
- coord/openapi.py +404 -0
- coord/overlap_fence.py +133 -0
- coord/parentage.py +200 -0
- coord/parentage_github.py +58 -0
- coord/pipeline.py +481 -0
- coord/plan_parser.py +266 -0
- coord/plans.py +543 -0
- coord/platform_paths.py +43 -0
- coord/pr_body_lint.py +67 -0
- coord/prereqs.py +533 -0
- coord/progress.py +425 -0
- coord/providers/__init__.py +683 -0
- coord/providers/base.py +218 -0
- coord/providers/claude.py +284 -0
- coord/providers/claude_pty.py +610 -0
- coord/providers/opencode.py +896 -0
- coord/reconcile.py +2233 -0
- coord/refine_chat.py +485 -0
- coord/release_cordon.py +525 -0
- coord/release_propagate.py +1176 -0
- coord/release_verify.py +777 -0
- coord/release_window.py +322 -0
- coord/reports.py +1643 -0
- coord/revalidate.py +1101 -0
- coord/review.py +3317 -0
- coord/scorecard.py +484 -0
- coord/serve_app.py +7192 -0
- coord/skills/update-issue/SKILL.md +93 -0
- coord/smoke.py +1030 -0
- coord/split_work.py +210 -0
- coord/stage_projection.py +650 -0
- coord/state.py +5720 -0
- coord/test_author.py +1064 -0
- coord/test_chat.py +352 -0
- coord/test_orchestrator.py +494 -0
- coord/test_report.py +178 -0
- coord/tui_release.py +271 -0
- coord/usage.py +753 -0
- coord/usage_limits.py +358 -0
- coord/usage_rollup.py +709 -0
- coord/worker_events.py +954 -0
coord/commands/plans.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""`coord plans` — read-only milestone-roster aggregation (#974).
|
|
2
|
+
|
|
3
|
+
Fetches every open GitHub milestone across all configured repos (or a single
|
|
4
|
+
repo when ``--repo`` is given), finds each milestone's tracking epic (the
|
|
5
|
+
``"epic"``-labelled issue — open *or* closed, so a milestone left open after
|
|
6
|
+
its epic was tidied up still resolves correctly, #974), parses its
|
|
7
|
+
``## Work order`` block, and emits a JSON array (``--json``) or a
|
|
8
|
+
human-readable table of plan stats + attention signals.
|
|
9
|
+
|
|
10
|
+
This command is **read-only**: it never writes issues, comments, or the board.
|
|
11
|
+
The JSON output is the data backbone consumed by the TUI "Plans" panel (#975).
|
|
12
|
+
|
|
13
|
+
Attention signals (``needs_you`` field):
|
|
14
|
+
|
|
15
|
+
``no_work_order``
|
|
16
|
+
Milestone has no epic with a ``## Work order`` block — someone needs to
|
|
17
|
+
write one via ``coord milestone chat`` / ``coord milestone write-order``.
|
|
18
|
+
``ready_waiting``
|
|
19
|
+
≥1 ready-frontier entry exists. Use ``coord milestone dispatch`` to kick
|
|
20
|
+
it off, or ``coord milestone order`` to review the frontier first.
|
|
21
|
+
``stalled``
|
|
22
|
+
Has a work order, nothing is ready or in-flight, and the milestone is not
|
|
23
|
+
done. A dependency is blocking everything and may need attention.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import json
|
|
29
|
+
import sys
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
import click
|
|
33
|
+
|
|
34
|
+
from coord.commands._common import _CONFIG_OPTION, _load_config
|
|
35
|
+
from coord.plans import aggregate_repo_plans
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@click.command(
|
|
39
|
+
"plans",
|
|
40
|
+
help=(
|
|
41
|
+
"Read-only milestone-roster aggregation (#974). "
|
|
42
|
+
"Fetches every open milestone across all configured repos (or just REPO "
|
|
43
|
+
"when --repo is given), parses each tracking epic's `## Work order` "
|
|
44
|
+
"block, and reports per-plan stats + attention signals.\n\n"
|
|
45
|
+
"Primary output is --json (a JSON array of plan objects). "
|
|
46
|
+
"Without --json a compact human-readable table is printed instead."
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
@click.option(
|
|
50
|
+
"--repo",
|
|
51
|
+
default=None,
|
|
52
|
+
metavar="REPO",
|
|
53
|
+
help=(
|
|
54
|
+
"Restrict to this coord-local repo name "
|
|
55
|
+
"(from coordinator.yml). Default: all repos."
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
@click.option(
|
|
59
|
+
"--json",
|
|
60
|
+
"json_out",
|
|
61
|
+
is_flag=True,
|
|
62
|
+
help="Emit machine-readable JSON (array of plan objects).",
|
|
63
|
+
)
|
|
64
|
+
@_CONFIG_OPTION
|
|
65
|
+
def plans_cmd(repo: str | None, json_out: bool, config_path: Path) -> None:
|
|
66
|
+
from coord import board_service, github_ops # noqa: PLC0415
|
|
67
|
+
|
|
68
|
+
cfg = _load_config(config_path)
|
|
69
|
+
|
|
70
|
+
# Resolve the target repos.
|
|
71
|
+
if repo is not None:
|
|
72
|
+
repo_entry = cfg.repo(repo)
|
|
73
|
+
if repo_entry is None:
|
|
74
|
+
click.echo(f"error: unknown repo {repo!r} (not in coordinator.yml)", err=True)
|
|
75
|
+
sys.exit(2)
|
|
76
|
+
target_repos = [repo_entry]
|
|
77
|
+
else:
|
|
78
|
+
target_repos = list(cfg.repos)
|
|
79
|
+
|
|
80
|
+
board = board_service.read_board()
|
|
81
|
+
|
|
82
|
+
all_entries = []
|
|
83
|
+
errors: list[str] = []
|
|
84
|
+
|
|
85
|
+
for repo_entry in target_repos:
|
|
86
|
+
try:
|
|
87
|
+
milestones = github_ops.get_repo_milestones(repo_entry.github)
|
|
88
|
+
except RuntimeError as e:
|
|
89
|
+
errors.append(f"warning: could not list milestones for {repo_entry.github}: {e}")
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
if not milestones:
|
|
93
|
+
continue
|
|
94
|
+
|
|
95
|
+
try:
|
|
96
|
+
open_issues = github_ops.get_open_issues(repo_entry.github)
|
|
97
|
+
except RuntimeError as e:
|
|
98
|
+
errors.append(f"warning: could not fetch issues for {repo_entry.github}: {e}")
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
# #974 fix: a milestone can stay open after its tracking epic has
|
|
102
|
+
# been closed (e.g. work finished, epic tidied up before the
|
|
103
|
+
# milestone). Fetch closed epics too so that state is still detected
|
|
104
|
+
# instead of misreported as "no_work_order". Fail-open: a lookup
|
|
105
|
+
# error here just falls back to open-only tracking-issue detection.
|
|
106
|
+
try:
|
|
107
|
+
closed_epics = github_ops.get_closed_epics(repo_entry.github)
|
|
108
|
+
except RuntimeError as e:
|
|
109
|
+
errors.append(
|
|
110
|
+
f"warning: could not fetch closed epics for {repo_entry.github}: {e}"
|
|
111
|
+
)
|
|
112
|
+
closed_epics = []
|
|
113
|
+
|
|
114
|
+
entries = aggregate_repo_plans(
|
|
115
|
+
repo_name=repo_entry.name,
|
|
116
|
+
repo_github=repo_entry.github,
|
|
117
|
+
milestones=milestones,
|
|
118
|
+
open_issues=open_issues,
|
|
119
|
+
board=board,
|
|
120
|
+
closed_tracking_issues=closed_epics,
|
|
121
|
+
)
|
|
122
|
+
all_entries.extend(entries)
|
|
123
|
+
|
|
124
|
+
# Emit warnings regardless of output mode.
|
|
125
|
+
for msg in errors:
|
|
126
|
+
click.echo(msg, err=True)
|
|
127
|
+
|
|
128
|
+
if json_out:
|
|
129
|
+
click.echo(json.dumps([e.to_dict() for e in all_entries], indent=2))
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
# Human-readable table.
|
|
133
|
+
if not all_entries:
|
|
134
|
+
click.echo("No open milestones found.")
|
|
135
|
+
return
|
|
136
|
+
|
|
137
|
+
for entry in all_entries:
|
|
138
|
+
status_parts: list[str] = []
|
|
139
|
+
if entry.has_work_order:
|
|
140
|
+
status_parts.append(
|
|
141
|
+
f"ready={entry.ready_frontier} "
|
|
142
|
+
f"in-flight={entry.in_flight} "
|
|
143
|
+
f"blocked={entry.blocked} "
|
|
144
|
+
f"done={entry.done}/{entry.total}"
|
|
145
|
+
)
|
|
146
|
+
else:
|
|
147
|
+
status_parts.append("no work order")
|
|
148
|
+
|
|
149
|
+
if entry.needs_you:
|
|
150
|
+
status_parts.append(f"[{', '.join(entry.needs_you)}]")
|
|
151
|
+
|
|
152
|
+
tracking = f"#{entry.tracking_issue}" if entry.tracking_issue else "—"
|
|
153
|
+
click.echo(
|
|
154
|
+
f"{entry.repo} #{entry.milestone_number} {entry.title!r} "
|
|
155
|
+
f"epic:{tracking} {' '.join(status_parts)}"
|
|
156
|
+
)
|