1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! The `tm issue transition` → tracker sync hook (#8448).
//!
//! Why: the `phases` block is regenerated from child state, and until this hook
//! the regeneration ran only when a session remembered `tm issue epic sync`
//! after a transition — O3 of the plan is that a phase closing never leaves a
//! stale tracker without anyone remembering. The obvious wrong implementation
//! fails open: the label advances, the sync throws, the error becomes a warning,
//! and the tracker is stale with nothing recording it. Here the sync's failure
//! is the command's failure (AC1), and the message says which tracker is stale
//! and how to repair it.
//! What: [`transition_with_tracker_sync`] runs the ordinary
//! [`super::super::ops::transition`], then — for a phase-titled issue, no-op or
//! not — [`sync_tracker_of_phase`] reads its parent and syncs it. An issue
//! whose title is not `[EPIC_<n> PHASE_<m>]` costs no `EpicBackend` call at
//! all, and a phase-titled issue with no parent costs one parent read and no
//! tracker read or write (AC2).
//!
//! # A re-run converges
//!
//! A run killed between the label swap and the sync, or one whose sync failed,
//! leaves the label moved and the tracker stale. Re-issuing the same command
//! is then a no-op transition (#8003) — and if a no-op skipped the sync, that
//! re-run would exit 0 and repair nothing. So a no-op on a phase still syncs;
//! the sync itself writes nothing when the block is already current, which is
//! what keeps the no-op cheap on a healthy tracker.
//!
//! Test: `transition_hook_regenerates_the_parent_trackers_block`,
//! `transition_hook_fails_the_command_when_the_sync_fails`,
//! `transition_hook_makes_no_epic_call_for_a_non_phase_title`,
//! `transition_hook_reads_no_tracker_for_a_parentless_phase`,
//! `transition_hook_regenerates_a_stale_tracker_on_a_no_op_transition`,
//! `transition_hook_makes_no_epic_call_for_a_no_op_on_a_non_phase_title`,
//! `transition_hook_names_the_tracker_when_the_parent_read_fails`.
use crateStateModel;
use crate;
use crateTicketSystem;
use EpicBackend;
use render;
use ;
/// A transition and the tracker sync it triggered, if any.
///
/// Test: `transition_hook_regenerates_the_parent_trackers_block`.
pub
/// `tm issue transition`, followed by the phase's tracker sync.
///
/// Why: one function composes the two so the dispatcher cannot swallow the
/// second half — the fail-open shape AC1 exists to forbid is a `?` missing at
/// exactly this seam.
/// What: runs the transition, then hands the issue's title — read by the
/// transition's own `validate`, so a non-phase costs no extra call — to
/// [`sync_tracker_of_phase`], whose error is this function's error. A no-op
/// (#8003) syncs too, so a re-run after an interrupted sync converges; the
/// sync writes nothing when the block is already current.
/// Test: see the module doc.
pub
/// Regenerate the tracker of a phase issue that just changed state.
///
/// Why: called AFTER the label moved, so every failure arm has to say two
/// things — that the transition itself stands, and which tracker is now stale
/// — or an operator reading the exit code would retry a transition that is
/// already a no-op and never learn the tracker needs `sync`.
/// What: `Ok(None)` for a title that is not a phase title (no call made) or a
/// phase with no parent (one parent read). Otherwise syncs the parent under
/// `status_prefix`. A parent read that fails names the tracker by the title's
/// embedded number; a sync that fails names the parent. Both carry the
/// `tm issue epic sync <n>` repair.
/// Test: `transition_hook_fails_the_command_when_the_sync_fails`,
/// `transition_hook_names_the_tracker_when_the_parent_read_fails`.
pub