@bli-cockpit/cli 0.2.240 → 0.2.241

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.
@@ -0,0 +1,269 @@
1
+ {
2
+ "schema": 1,
3
+ "about": "Tower Manager's limits, rules and refusal names, generated from the manager server's constants (apps/dashboard/src/repo-shape/manager-limits-lib.ts). A skill or doc that quotes a number or a refusal name checks it against this list.",
4
+ "limits": [
5
+ {
6
+ "id": "addDetailCut",
7
+ "value": 200,
8
+ "unit": "characters",
9
+ "source": "the CLI's manager-render.ts savedTextLines: an add prints its detail cut to 200 characters (a display cut, not a server limit)"
10
+ },
11
+ {
12
+ "id": "attentionPart",
13
+ "value": 25,
14
+ "unit": "items",
15
+ "source": "TOWER_MANAGER_ATTENTION_PART_LIMIT"
16
+ },
17
+ {
18
+ "id": "blockerMax",
19
+ "value": 200,
20
+ "unit": "characters",
21
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.blockerMax"
22
+ },
23
+ {
24
+ "id": "bulletMax",
25
+ "value": 160,
26
+ "unit": "characters",
27
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.bulletMax"
28
+ },
29
+ {
30
+ "id": "bulletsMax",
31
+ "value": 5,
32
+ "unit": "bullets",
33
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.bulletsMax"
34
+ },
35
+ {
36
+ "id": "bulletsMin",
37
+ "value": 1,
38
+ "unit": "bullets",
39
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.bulletsMinPerson"
40
+ },
41
+ {
42
+ "id": "comingUp",
43
+ "value": 20,
44
+ "unit": "items",
45
+ "source": "TOWER_MANAGER_HOME_LIMITS.comingUp"
46
+ },
47
+ {
48
+ "id": "headlineMax",
49
+ "value": 140,
50
+ "unit": "characters",
51
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.headlineMax"
52
+ },
53
+ {
54
+ "id": "inTowerDays",
55
+ "value": 7,
56
+ "unit": "days",
57
+ "source": "TOWER_MANAGER_IN_TOWER_DAYS"
58
+ },
59
+ {
60
+ "id": "inTowerItems",
61
+ "value": 50,
62
+ "unit": "items",
63
+ "source": "TOWER_MANAGER_IN_TOWER_LIMIT"
64
+ },
65
+ {
66
+ "id": "listRows",
67
+ "value": 500,
68
+ "unit": "rows",
69
+ "source": "db/items.ts LIST_LIMIT"
70
+ },
71
+ {
72
+ "id": "longOverdueDays",
73
+ "value": 14,
74
+ "unit": "days",
75
+ "source": "SUMMARY_LONG_OVERDUE_DAYS"
76
+ },
77
+ {
78
+ "id": "needsAttention",
79
+ "value": 50,
80
+ "unit": "items",
81
+ "source": "TOWER_MANAGER_HOME_LIMITS.needsAttention"
82
+ },
83
+ {
84
+ "id": "needsAttentionDays",
85
+ "value": 7,
86
+ "unit": "days",
87
+ "source": "db/home.ts: due_at <= today + 6, so today and six days ahead (a window of 7 days)"
88
+ },
89
+ {
90
+ "id": "nextMax",
91
+ "value": 200,
92
+ "unit": "characters",
93
+ "source": "TOWER_MANAGER_SUMMARY_LIMITS.nextMax"
94
+ },
95
+ {
96
+ "id": "pageDefault",
97
+ "value": 50,
98
+ "unit": "rows",
99
+ "source": "MANAGER_LIST_PAGE.default (the MCP list tools' own default)"
100
+ },
101
+ {
102
+ "id": "pageMax",
103
+ "value": 200,
104
+ "unit": "rows",
105
+ "source": "MANAGER_LIST_PAGE.max (the MCP list tools' own cap)"
106
+ },
107
+ {
108
+ "id": "sourceNoteMax",
109
+ "value": 1000,
110
+ "unit": "characters",
111
+ "source": "routes/validation.ts: sourceNote .max(1000, ...)"
112
+ },
113
+ {
114
+ "id": "whatChanged",
115
+ "value": 100,
116
+ "unit": "items",
117
+ "source": "TOWER_MANAGER_HOME_LIMITS.whatChanged"
118
+ }
119
+ ],
120
+ "rules": [
121
+ {
122
+ "id": "long_overdue_makes_card_at_risk",
123
+ "text": "An open action more than 14 days past its due date (Tower's today, America/Vancouver) makes the card at_risk, or blocked with a named blocker; never on_track."
124
+ },
125
+ {
126
+ "id": "blocker_only_on_blocked",
127
+ "text": "A blocker goes only on a Blocked card: a blocker sent with any other health is refused (summary_blocker_needs_blocked), and sending only a new health drops the stored one; blocked always has a blocker."
128
+ },
129
+ {
130
+ "id": "every_item_write_names_its_version",
131
+ "text": "Every write on an existing item names the version (updatedAt) it last read; a stale one is refused by name and nothing is written."
132
+ }
133
+ ],
134
+ "refusals": {
135
+ "summary": [
136
+ "summary_changed",
137
+ "summary_empty",
138
+ "summary_incomplete",
139
+ "summary_health_invalid",
140
+ "summary_headline_empty",
141
+ "summary_headline_too_long",
142
+ "summary_bullets_count",
143
+ "summary_bullet_empty",
144
+ "summary_bullet_too_long",
145
+ "summary_bullet_date_invalid",
146
+ "summary_next_too_long",
147
+ "summary_blocker_too_long",
148
+ "summary_blocked_needs_blocker",
149
+ "summary_blocker_needs_blocked"
150
+ ],
151
+ "item": [
152
+ "item_archived",
153
+ "item_busy",
154
+ "item_changed",
155
+ "item_dismissed",
156
+ "item_not_archived",
157
+ "no_proposal",
158
+ "person_item_not_dismissable",
159
+ "proposal_decided",
160
+ "proposal_not_addable",
161
+ "proposal_replaced",
162
+ "request_reused",
163
+ "timeline_not_live"
164
+ ],
165
+ "owner": [
166
+ "owner_already_merged",
167
+ "owner_changed",
168
+ "owner_has_aliases",
169
+ "owner_not_merged",
170
+ "owner_same",
171
+ "owner_target_merged",
172
+ "owner_unknown"
173
+ ],
174
+ "read_only_door": [
175
+ "read_only_device_cannot_write",
176
+ "read_only_device_door_not_listed",
177
+ "read_only_device_on_admin"
178
+ ],
179
+ "door": [
180
+ "inference_not_configured",
181
+ "manager_body_too_large",
182
+ "manager_body_unreadable",
183
+ "manager_operation_not_on_this_door",
184
+ "manager_path_malformed",
185
+ "manager_role_denied",
186
+ "manager_route_not_found",
187
+ "manager_timeout",
188
+ "manager_unreachable",
189
+ "team_lookup_failed",
190
+ "team_membership_required"
191
+ ]
192
+ },
193
+ "refusalPrefixes": [
194
+ "summary_",
195
+ "item_",
196
+ "proposal_",
197
+ "owner_",
198
+ "read_only_device_",
199
+ "request_",
200
+ "manager_",
201
+ "team_",
202
+ "timeline_not_",
203
+ "person_item_",
204
+ "no_proposal"
205
+ ],
206
+ "tools": [
207
+ "archived",
208
+ "blocker",
209
+ "bullets",
210
+ "client_id",
211
+ "date",
212
+ "decision",
213
+ "detail",
214
+ "due",
215
+ "expected_updated_at",
216
+ "headline",
217
+ "health",
218
+ "item_id",
219
+ "kind",
220
+ "limit",
221
+ "manager_add",
222
+ "manager_approve",
223
+ "manager_archive",
224
+ "manager_client",
225
+ "manager_clients",
226
+ "manager_dismiss",
227
+ "manager_done",
228
+ "manager_drop",
229
+ "manager_edit",
230
+ "manager_home",
231
+ "manager_link",
232
+ "manager_list",
233
+ "manager_proposal",
234
+ "manager_queue",
235
+ "manager_reopen",
236
+ "manager_run",
237
+ "manager_set_summary",
238
+ "manager_show",
239
+ "manager_unarchive",
240
+ "meeting_id",
241
+ "needs_review",
242
+ "next",
243
+ "no_owner",
244
+ "overdue",
245
+ "owner",
246
+ "owner_name",
247
+ "owners",
248
+ "proposal_id",
249
+ "request_id",
250
+ "restore",
251
+ "review",
252
+ "run_id",
253
+ "search",
254
+ "source_note",
255
+ "source_url",
256
+ "status",
257
+ "timeline",
258
+ "title",
259
+ "version"
260
+ ],
261
+ "doorRefusedOperations": [
262
+ "create_client",
263
+ "merge_owner",
264
+ "rebuild_brief",
265
+ "sync_all",
266
+ "sync_client",
267
+ "unmerge_owner"
268
+ ]
269
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Why a read or a summary check stopped, in the words the manager page uses (`REASON_SENTENCES` in
3
+ * `apps/dashboard/src/app/(cockpit)/manager/manager-client-bar.tsx`, BLI-5777 batch 4). The CLI used to print the raw
4
+ * label ("notion_root_unreadable"). `manager-reason-words.test.ts` (dashboard repo-shape) fails when a reason the
5
+ * server can write has no sentence here, or when a sentence here is not the page's.
6
+ */
7
+ export const READ_REASON_SENTENCES = {
8
+ running: "Still running.",
9
+ ok: "Finished.",
10
+ client_locked: "Another run was already reading this client, so this one stood aside.",
11
+ client_not_found: "This client no longer exists.",
12
+ client_disabled: "This client is disabled.",
13
+ notion_not_configured: "Notion is not connected on this Tower deployment.",
14
+ notion_root_unreadable: "Tower cannot read this client's Notion page. Share it with the Tower Manager Dashboard integration again, then sync.",
15
+ notion_unavailable: "Notion did not answer. The next sync will try again.",
16
+ model_failed: "The model did not answer. Nothing was lost; the next sync reads the same pages again.",
17
+ model_timeout: "The model took too long to answer. Nothing was lost; the next sync reads the same pages again, fewer at a time.",
18
+ model_output_rejected: "The model's answer was not usable. Nothing was lost; the next sync reads the same pages again.",
19
+ root_owned_by_other_client: "This client's Notion page sits inside another client's tree, which holds it. Nothing was read.",
20
+ interrupted: "Interrupted when Tower restarted; will retry. The daily sync carries it on, or Sync now.",
21
+ batch_too_dense: "Those pages held more than one answer can carry, so they are being read again in smaller batches.",
22
+ database_error: "Tower could not save the result. The next sync will try again.",
23
+ unexpected_error: "The run stopped on an unexpected error. The next sync will try again.",
24
+ };
25
+ /** The page's sentence for a reason, with the label beside it so an agent can name it; an unknown label is printed as it is. */
26
+ export function readReasonText(reason) {
27
+ const sentence = READ_REASON_SENTENCES[reason];
28
+ return sentence ? `${sentence} (${reason})` : reason;
29
+ }
30
+ /**
31
+ * Why the AI's answer for a "Where we are" card was not used, in words (BLI-5777): every refusal name a summary check can record (the
32
+ * answer reader's `SummaryAnswerRefusal`, and the card's own `TOWER_MANAGER_SUMMARY_REFUSALS`). `manager-cli-mcp-rules.test.ts` fails
33
+ * when a name the server has no words here, so a new refusal cannot ship as a bare code.
34
+ */
35
+ export const SUMMARY_REFUSAL_WORDS = {
36
+ not_an_answer: "it was not a card at all",
37
+ health_invalid: "its health was none of on_track, at_risk, blocked",
38
+ headline_empty: "it had no headline",
39
+ bullets_empty: "it had no bullets",
40
+ summary_changed: "the card was changed after the version the edit named",
41
+ summary_empty: "there was nothing to change",
42
+ summary_incomplete: "a first card needs health, headline and a bullet",
43
+ summary_health_invalid: "its health was none of on_track, at_risk, blocked",
44
+ summary_headline_empty: "the headline was empty",
45
+ summary_headline_too_long: "the headline was over 140 characters",
46
+ summary_bullets_count: "too many or too few bullets",
47
+ summary_bullet_empty: "a bullet had no words",
48
+ summary_bullet_too_long: "a bullet was over 160 characters",
49
+ summary_bullet_date_invalid: "a bullet's date was not a real day",
50
+ summary_next_too_long: "next was over 200 characters",
51
+ summary_blocker_too_long: "the blocker was over 200 characters",
52
+ summary_blocked_needs_blocker: "blocked with no blocker",
53
+ summary_blocker_needs_blocked: "a blocker on a card that is not blocked",
54
+ };
55
+ /** Why a summary check kept the card that was there instead of writing one (the receipt's `kept_reason`), in words. */
56
+ export const SUMMARY_KEPT_WORDS = {
57
+ model_call_failed: "the model call failed, so the card that was there stays",
58
+ model_answer_refused: "the AI's answer was refused, so the card that was there stays",
59
+ card_changed_meanwhile: "someone wrote the card while the check ran, so theirs stays; it is newer",
60
+ };
61
+ /** "The AI's answer broke a card rule (too many or too few bullets: summary_bullets_count), so it was not used." The name stays after the words. */
62
+ export function summaryRefusalText(refusal) {
63
+ const words = SUMMARY_REFUSAL_WORDS[refusal];
64
+ return words ? `The AI's answer broke a card rule (${words}: ${refusal}), so it was not used.` : `The AI's answer was refused (${refusal}), so it was not used.`;
65
+ }
66
+ /** "the model call failed, so the card that was there stays (model_call_failed)"; an unknown reason is said as it is. */
67
+ export function keptReasonText(reason) {
68
+ const words = SUMMARY_KEPT_WORDS[reason];
69
+ return words ? `${words} (${reason})` : reason;
70
+ }
71
+ /** What started a summary check (the receipt's `trigger`), in words; an unknown one is said as it is. */
72
+ export const SUMMARY_TRIGGER_WORDS = {
73
+ read: "a read",
74
+ brief_rebuild: "Rebuild brief",
75
+ };
76
+ export function summaryTriggerText(trigger) {
77
+ return SUMMARY_TRIGGER_WORDS[trigger] ?? trigger;
78
+ }