@skrr-ai/cli 0.1.128 → 0.1.130

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.
Files changed (103) hide show
  1. package/dist/base-command.d.ts +12 -0
  2. package/dist/base-command.js +65 -0
  3. package/dist/commands/agenda/trigger/create.js +9 -1
  4. package/dist/commands/agenda/trigger/list.d.ts +2 -1
  5. package/dist/commands/agenda/trigger/list.js +55 -6
  6. package/dist/commands/agents/create.js +3 -1
  7. package/dist/commands/agents/reflect.d.ts +6 -0
  8. package/dist/commands/agents/reflect.js +45 -6
  9. package/dist/commands/agents/schedule-overview.d.ts +17 -0
  10. package/dist/commands/agents/schedule-overview.js +33 -9
  11. package/dist/commands/agents/triggers/policy.js +3 -1
  12. package/dist/commands/browser/persistent-profile.d.ts +22 -0
  13. package/dist/commands/browser/persistent-profile.js +46 -0
  14. package/dist/commands/commitments/create.js +3 -1
  15. package/dist/commands/commitments/effective-policy.js +6 -0
  16. package/dist/commands/commitments/explain.js +10 -1
  17. package/dist/commands/commitments/plan.d.ts +14 -0
  18. package/dist/commands/commitments/plan.js +32 -0
  19. package/dist/commands/commitments/preflight.d.ts +1 -1
  20. package/dist/commands/commitments/preflight.js +12 -4
  21. package/dist/commands/commitments/show.d.ts +9 -0
  22. package/dist/commands/commitments/show.js +14 -1
  23. package/dist/commands/compass/revisions.d.ts +6 -2
  24. package/dist/commands/compass/revisions.js +13 -5
  25. package/dist/commands/compass/tactic.d.ts +5 -0
  26. package/dist/commands/compass/tactic.js +14 -0
  27. package/dist/commands/followups/plans/create.js +1 -1
  28. package/dist/commands/harnesses/list.js +1 -1
  29. package/dist/commands/northstars/create.js +6 -1
  30. package/dist/commands/northstars/governance/configure.js +1 -1
  31. package/dist/commands/northstars/intents/decide.js +2 -3
  32. package/dist/commands/northstars/list.js +1 -1
  33. package/dist/commands/northstars/review-now.js +5 -0
  34. package/dist/commands/northstars/reviews.js +15 -3
  35. package/dist/commands/northstars/show.js +1 -1
  36. package/dist/commands/spaces/auto-executor/runs.d.ts +9 -1
  37. package/dist/commands/spaces/auto-executor/runs.js +18 -1
  38. package/dist/commands/spaces/heartbeats/create.js +7 -5
  39. package/dist/commands/spaces/heartbeats/status.js +10 -0
  40. package/dist/commands/spaces/heartbeats/update.js +5 -3
  41. package/dist/commands/store/artifacts/releases.d.ts +20 -0
  42. package/dist/commands/store/artifacts/releases.js +85 -0
  43. package/dist/commands/store/library.d.ts +14 -0
  44. package/dist/commands/store/library.js +71 -0
  45. package/dist/commands/tasks/archive.js +6 -0
  46. package/dist/commands/tasks/list.d.ts +48 -0
  47. package/dist/commands/tasks/list.js +141 -9
  48. package/dist/commands/tasks/pause-schedule.js +1 -1
  49. package/dist/commands/tasks/remind.js +23 -11
  50. package/dist/commands/tasks/resume-schedule.js +4 -1
  51. package/dist/commands/tasks/retry-schedule.js +6 -3
  52. package/dist/commands/tasks/schedule.js +35 -8
  53. package/dist/commands/tasks/self-schedule.d.ts +56 -0
  54. package/dist/commands/tasks/self-schedule.js +179 -21
  55. package/dist/commands/tasks/show.js +4 -0
  56. package/dist/lib/agent-trigger-listing.d.ts +26 -0
  57. package/dist/lib/agent-trigger-listing.js +63 -0
  58. package/dist/lib/agentic-stream.js +138 -41
  59. package/dist/lib/commitment-ledgers.js +3 -1
  60. package/dist/lib/commitments.d.ts +24 -0
  61. package/dist/lib/commitments.js +64 -4
  62. package/dist/lib/compasses.d.ts +2 -0
  63. package/dist/lib/iso-instant.d.ts +52 -0
  64. package/dist/lib/iso-instant.js +162 -0
  65. package/dist/lib/northstars.d.ts +87 -4
  66. package/dist/lib/northstars.js +226 -94
  67. package/dist/lib/proposals.js +6 -2
  68. package/dist/lib/reflection.d.ts +58 -0
  69. package/dist/lib/reflection.js +115 -6
  70. package/dist/lib/store-artifact-releases.d.ts +39 -0
  71. package/dist/lib/store-artifact-releases.js +12 -0
  72. package/dist/lib/store-library.d.ts +37 -0
  73. package/dist/lib/store-library.js +12 -0
  74. package/dist/lib/task-calendar.d.ts +19 -0
  75. package/dist/lib/task-calendar.js +72 -0
  76. package/dist/lib/task-operations.js +2 -0
  77. package/dist/lib/task-recurrence-outcome.js +3 -1
  78. package/dist/lib/task-recurrence-summary.d.ts +15 -0
  79. package/dist/lib/task-recurrence-summary.js +228 -0
  80. package/dist/lib/task-reminder.d.ts +28 -0
  81. package/dist/lib/task-reminder.js +50 -0
  82. package/dist/lib/task-schedule-notes.d.ts +46 -0
  83. package/dist/lib/task-schedule-notes.js +71 -0
  84. package/dist/lib/triggers.d.ts +31 -2
  85. package/dist/lib/triggers.js +38 -18
  86. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/daemonWire.js +11 -1
  87. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.d.ts +9 -0
  88. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/deviceIdentityBridge.js +22 -0
  89. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.d.ts +123 -0
  90. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/executorStopReceipt.js +160 -0
  91. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -1
  92. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +19 -0
  93. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/daemonWire.js +11 -1
  94. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.d.ts +9 -0
  95. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/deviceIdentityBridge.js +28 -0
  96. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.d.ts +123 -0
  97. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/executorStopReceipt.js +173 -0
  98. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -1
  99. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +3 -1
  100. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  101. package/dist/node_modules/@skrr-ai/data-provider/index.js +6772 -6675
  102. package/oclif.manifest.json +282 -40
  103. package/package.json +1 -1
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * One reading of "an ISO-8601 UTC instant" for every CLI flag that takes one.
4
+ *
5
+ * `tasks remind --at` and `tasks schedule --at` each had their own: remind ran
6
+ * `new Date(value)` behind a `/^\d{4}-\d{2}-\d{2}T/` check, and schedule forwarded
7
+ * the string and printed the server's zod issue. `new Date()` is the wrong tool
8
+ * for an instant, in two ways that both stored a different time than the one
9
+ * typed and said nothing (OSK-21504, OSK-21506):
10
+ *
11
+ * - a time with no zone is read in the zone of the MACHINE running the CLI, so
12
+ * the same command stored different instants on different laptops;
13
+ * - a day that does not exist overflows into the next month
14
+ * (`2027-02-30` is `2027-03-02`).
15
+ *
16
+ * The rule here is the one `tasks schedule --help` already states and the server's
17
+ * `z.string().datetime()` enforces: a calendar-real date, a time with seconds, and
18
+ * a literal `Z`. A numeric offset is refused too, even though it names an instant:
19
+ * the two commands must agree, and the server's schedule door does not take one.
20
+ *
21
+ * Never reads the machine's zone. Pure.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.parseUtcInstant = parseUtcInstant;
25
+ exports.formatUtcInstant = formatUtcInstant;
26
+ exports.formatLocalInstant = formatLocalInstant;
27
+ exports.describeInstant = describeInstant;
28
+ const EXAMPLE = '2026-12-01T09:00:00Z';
29
+ const UTC_INSTANT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?Z$/;
30
+ const ZONELESS = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(\.\d+)?)?$/;
31
+ const OFFSET = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(\.\d+)?)?([+-])(\d{2}):?(\d{2})$/;
32
+ const DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
33
+ const MONTH_NAMES = [
34
+ 'January',
35
+ 'February',
36
+ 'March',
37
+ 'April',
38
+ 'May',
39
+ 'June',
40
+ 'July',
41
+ 'August',
42
+ 'September',
43
+ 'October',
44
+ 'November',
45
+ 'December',
46
+ ];
47
+ function daysInMonth(year, month) {
48
+ return new Date(Date.UTC(year, month, 0)).getUTCDate();
49
+ }
50
+ /**
51
+ * What is wrong with the calendar part, or `null` when the date exists.
52
+ * Checked by construction rather than by `new Date()`, which accepts the overflow.
53
+ */
54
+ function calendarProblem(year, month, day) {
55
+ if (month < 1 || month > 12)
56
+ return `month ${String(month).padStart(2, '0')} does not exist`;
57
+ const last = daysInMonth(year, month);
58
+ if (day < 1 || day > last) {
59
+ return `${MONTH_NAMES[month - 1]} ${year} has ${last} days, so day ${String(day).padStart(2, '0')} does not exist`;
60
+ }
61
+ return null;
62
+ }
63
+ function clockProblem(hour, minute, second) {
64
+ if (hour > 23 || minute > 59 || second > 59) {
65
+ return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')} is not a time of day`;
66
+ }
67
+ return null;
68
+ }
69
+ function rule(label) {
70
+ return `${label} must be an ISO-8601 UTC time ending in Z, for example ${EXAMPLE}`;
71
+ }
72
+ /**
73
+ * Parse a flag value as a UTC instant, or say precisely what is wrong with it.
74
+ *
75
+ * `label` is what the user typed (`--at`, `scheduledFor`), so the message names
76
+ * their input rather than a REST field they never saw.
77
+ */
78
+ function parseUtcInstant(raw, label = '--at') {
79
+ const value = String(raw ?? '').trim();
80
+ const fail = (problem, reason) => ({
81
+ ok: false,
82
+ problem,
83
+ message: `${rule(label)}. ${reason}`,
84
+ });
85
+ const utc = UTC_INSTANT.exec(value);
86
+ if (utc) {
87
+ const [year, month, day, hour, minute, second] = utc.slice(1, 7).map(Number);
88
+ const calendar = calendarProblem(year, month, day);
89
+ if (calendar)
90
+ return fail('not_a_real_date', `"${value}" is not a real date: ${calendar}.`);
91
+ const clock = clockProblem(hour, minute, second);
92
+ if (clock)
93
+ return fail('not_a_real_time', `"${value}" is not a real time: ${clock}.`);
94
+ const date = new Date(value);
95
+ if (Number.isNaN(date.getTime())) {
96
+ return fail('not_a_date', `"${value}" is not a date.`);
97
+ }
98
+ return { ok: true, date, iso: date.toISOString() };
99
+ }
100
+ const zoneless = ZONELESS.exec(value);
101
+ if (zoneless) {
102
+ return fail('no_zone', `"${value}" has no time zone, so it could mean a different moment on each machine. ` +
103
+ `Add Z if it is UTC, or convert it to UTC first.`);
104
+ }
105
+ const offset = OFFSET.exec(value);
106
+ if (offset) {
107
+ const [year, month, day, hour, minute] = offset.slice(1, 6).map(Number);
108
+ const second = Number(offset[6] ?? 0);
109
+ const sign = offset[8] === '-' ? -1 : 1;
110
+ const shiftMinutes = sign * (Number(offset[9]) * 60 + Number(offset[10]));
111
+ let converted = '';
112
+ if (!calendarProblem(year, month, day) && !clockProblem(hour, minute, second)) {
113
+ const at = new Date(Date.UTC(year, month - 1, day, hour, minute, second) - shiftMinutes * 60_000);
114
+ converted = ` (${value} is ${at.toISOString().replace(/\.000Z$/, 'Z')})`;
115
+ }
116
+ return fail('numeric_offset', `Numeric offsets such as ${offset[8]}${offset[9]}:${offset[10]} are not accepted; convert the time to UTC and end it with Z${converted}.`);
117
+ }
118
+ const dateOnly = DATE_ONLY.exec(value);
119
+ if (dateOnly) {
120
+ const calendar = calendarProblem(Number(dateOnly[1]), Number(dateOnly[2]), Number(dateOnly[3]));
121
+ return fail(calendar ? 'not_a_real_date' : 'date_only', calendar
122
+ ? `"${value}" is not a real date: ${calendar}.`
123
+ : `"${value}" is a date without a time; add a time of day, e.g. ${value}T09:00:00Z.`);
124
+ }
125
+ return fail('not_a_date', `"${value}" is not an ISO-8601 date and time.`);
126
+ }
127
+ /** `2027-02-02T09:00:00Z` - the instant in UTC, whole seconds when there are no milliseconds. */
128
+ function formatUtcInstant(date) {
129
+ return date.toISOString().replace(/\.000Z$/, 'Z');
130
+ }
131
+ /**
132
+ * `2027-02-02 01:00:00 PST` - the same instant on this machine's wall clock, with the
133
+ * zone NAMED. `toLocaleString()` printed neither the zone nor anything that mapped back
134
+ * to the instant that was typed (OSK-21505). `timeZone` is for tests and defaults to
135
+ * the machine's own.
136
+ */
137
+ function formatLocalInstant(date, timeZone) {
138
+ const parts = new Intl.DateTimeFormat('en-CA', {
139
+ ...(timeZone ? { timeZone } : {}),
140
+ year: 'numeric',
141
+ month: '2-digit',
142
+ day: '2-digit',
143
+ hour: '2-digit',
144
+ minute: '2-digit',
145
+ second: '2-digit',
146
+ hourCycle: 'h23',
147
+ timeZoneName: 'short',
148
+ }).formatToParts(date);
149
+ const get = (type) => parts.find((p) => p.type === type)?.value ?? '';
150
+ return `${get('year')}-${get('month')}-${get('day')} ${get('hour')}:${get('minute')}:${get('second')} ${get('timeZoneName')}`;
151
+ }
152
+ /**
153
+ * The instant for a person: UTC first (it is what was typed and what is stored), then the
154
+ * local reading with its zone name. A machine already on UTC gets the UTC form alone.
155
+ */
156
+ function describeInstant(date, timeZone) {
157
+ const utc = formatUtcInstant(date);
158
+ const local = formatLocalInstant(date, timeZone);
159
+ if (/ (UTC|GMT)$/.test(local))
160
+ return utc;
161
+ return `${utc} (${local})`;
162
+ }
@@ -1,7 +1,8 @@
1
- import { NORTHSTAR_ANALYSIS_MODES, NORTHSTAR_APPROVAL_TRIGGERS, NORTHSTAR_EXECUTION_MODES, NORTHSTAR_INTENT_VERDICTS, NORTHSTAR_MANAGEMENT_INTENT_KINDS, NORTHSTAR_REVIEW_STATUSES } from '@skrr-ai/data-provider';
1
+ import { NORTHSTAR_ANALYSIS_MODES, NORTHSTAR_APPROVAL_TRIGGERS, NORTHSTAR_EXECUTION_MODES, NORTHSTAR_INTENT_VERDICTS, NORTHSTAR_MANAGEMENT_INTENT_KINDS, NORTHSTAR_REASON_WORDS, NORTHSTAR_REVIEW_STATUSES, describeNorthstarReason } from '@skrr-ai/data-provider';
2
2
  import type { Northstar, NorthstarAnalysisMode, NorthstarExecutionMode, NorthstarGovernance, NorthstarGovernanceStatus, NorthstarGovernanceUpdateParams, NorthstarListResponse, NorthstarManagementIntent, NorthstarManagementIntentKind, NorthstarRecommendation, NorthstarReviewRecord, NorthstarStatusResponse } from '@skrr-ai/data-provider';
3
3
  import { withQuery } from './triggers';
4
4
  export { NORTHSTAR_ANALYSIS_MODES, NORTHSTAR_APPROVAL_TRIGGERS, NORTHSTAR_EXECUTION_MODES, NORTHSTAR_INTENT_VERDICTS, NORTHSTAR_MANAGEMENT_INTENT_KINDS, NORTHSTAR_REVIEW_STATUSES, };
5
+ export { NORTHSTAR_REASON_WORDS, describeNorthstarReason };
5
6
  export type { Northstar, NorthstarAnalysisMode, NorthstarExecutionMode, NorthstarGovernance, NorthstarGovernanceStatus, NorthstarManagementIntent, NorthstarManagementIntentKind, NorthstarRecommendation, NorthstarReviewRecord, };
6
7
  /**
7
8
  * oclif's `options:` needs runtime arrays, and these two are LIFECYCLE
@@ -11,6 +12,10 @@ export type { Northstar, NorthstarAnalysisMode, NorthstarExecutionMode, Northsta
11
12
  export declare const NORTHSTAR_STATUSES: readonly ["active", "paused", "achieved", "archived"];
12
13
  export declare const NORTHSTAR_PRIORITY_TIERS: readonly ["critical", "high", "medium", "low"];
13
14
  export declare const NORTHSTAR_RECOMMENDATION_STATUSES: readonly ["open", "applied", "dismissed"];
15
+ export declare function intentRisk(intent: {
16
+ riskLevel?: string | null;
17
+ } | null | undefined): string;
18
+ export declare function shortReviewId(id: string): string;
14
19
  /**
15
20
  * What a configure that changed the allocation inputs (the run budget, the critical reserve, the
16
21
  * cadence band) says it did to the linked commitments. Additive on the server: absent from an
@@ -52,12 +57,22 @@ export declare const northstarApi: {
52
57
  }>;
53
58
  decideIntent: (id: string, intentId: string, body: Record<string, unknown>) => Promise<Record<string, unknown>>;
54
59
  };
60
+ /**
61
+ * One review, from the id a person typed. The full id is asked for first, exactly as before. Only when
62
+ * the server has no review of that exact id is the typed text read as the start of one, among the
63
+ * northstar's newest 100 reviews: that is what the REVIEW column of `intents list` prints
64
+ * (`shortReviewId`), so the table's own output can be pasted back. A prefix of several reviews is
65
+ * reported, not guessed; one of none, or of a review older than the newest 100, raises the server's
66
+ * original "not found". Both ids are in `--json`.
67
+ */
68
+ export declare function lookupReview(northstarId: string, typed: string): Promise<{
69
+ review: NorthstarReviewRecord;
70
+ } | {
71
+ ambiguous: string[];
72
+ }>;
55
73
  /** ms → a short human duration, for a table cell that must stay narrow. */
56
74
  export declare function humanMs(ms?: number): string;
57
75
  export declare function shortDate(value?: string): string;
58
- export declare const NORTHSTAR_REASON_WORDS: Readonly<Record<string, string>>;
59
- /** A code in words; an unknown code comes back unchanged, an absent one says so. */
60
- export declare function describeNorthstarReason(code: string | null | undefined): string;
61
76
  export type NorthstarDecisionContext = {
62
77
  northstarId: string;
63
78
  intentId: string;
@@ -114,6 +129,48 @@ export declare function listFooter(input: {
114
129
  nextCursor?: string | null;
115
130
  cursor?: boolean;
116
131
  }): string;
132
+ /** What a northstar with no workspace is called wherever a workspace is named. */
133
+ export declare const PERSONAL_NORTHSTAR_WORKSPACE = "personal";
134
+ /** Why a personal northstar can look missing on the web. The one sentence the others build on. */
135
+ export declare const NORTHSTAR_WEB_SCOPE_SENTENCE: string;
136
+ /** Help text shared by `list` and `show`: where a northstar's workspace is printed. */
137
+ export declare const NORTHSTAR_WORKSPACE_READ_HELP: string;
138
+ /** Help text for `create`: which workspace it lands in, and how to choose one. */
139
+ export declare const NORTHSTAR_WORKSPACE_CREATE_HELP: string;
140
+ /**
141
+ * Anything that may carry a `workspaceId`: a typed Northstar, or the raw record `create` prints (it
142
+ * is read through `Record<string, unknown>` so `--json` is the server's body plus the url).
143
+ */
144
+ type WorkspaceBearing = {
145
+ workspaceId?: unknown;
146
+ } | Record<string, unknown>;
147
+ export declare function shortWorkspaceId(id: string): string;
148
+ /** The workspace a northstar lives in, in one word or id: `personal` when it has none. */
149
+ export declare function northstarWorkspaceLabel(northstar: WorkspaceBearing, options?: {
150
+ short?: boolean;
151
+ }): string;
152
+ /** The line `show` and `create` print: the full workspace id, or `personal`. */
153
+ export declare function northstarWorkspaceLine(northstar: WorkspaceBearing): string;
154
+ /** What the process that ran `create` asked for: the inputs to which note a personal northstar gets. */
155
+ export type PersonalNorthstarContext = {
156
+ /** An Agent session: its workspace comes from the session, and `--workspace` is ignored. */
157
+ autonomous?: boolean;
158
+ /** The workspace the request carried (`--workspace`, or the one `workspaces use` chose). */
159
+ requestedWorkspaceId?: string;
160
+ };
161
+ /**
162
+ * What `create` adds when the northstar landed in no workspace. Three causes, three endings:
163
+ *
164
+ * - an Agent session takes its workspace from the session and ignores `--workspace`, so telling
165
+ * it to pass the flag would send it round in a circle;
166
+ * - a workspace WAS requested but the person is not a member of it: the server does not refuse,
167
+ * it creates the northstar personal (`resolveWorkspaceContext`), so "pass --workspace" would
168
+ * be said to someone who just did;
169
+ * - nothing was requested, and the way out is the flag.
170
+ */
171
+ export declare function personalNorthstarNote(context?: PersonalNorthstarContext): string;
172
+ /** The note for a northstar `create` just made: nothing when it is in a workspace. */
173
+ export declare function createdNorthstarNote(northstar: WorkspaceBearing, context?: PersonalNorthstarContext): string | undefined;
117
174
  export declare function renderNorthstarList(rows: Northstar[], log: (line: string) => void): void;
118
175
  /**
119
176
  * The active-commitment cap, in words. `0` is accepted and stored, and a review
@@ -166,6 +223,32 @@ export declare function describeReviewAllocations(result: {
166
223
  allocations?: unknown;
167
224
  attention?: unknown;
168
225
  }): string;
226
+ /**
227
+ * The sentence for a portfolio run budget smaller than the number of linked active commitments
228
+ * (OSK-21334): each still gets the floor of 1 run/day, so the ceilings add up to more than the
229
+ * budget. The server derives it once (`portfolioRunBudgetFloor.js`) and carries it, when it
230
+ * applies, on the `governance show` read, the `review-now` result and the effective policy's
231
+ * `portfolio`; every one of those three prints THIS sentence, so none composes its own and they
232
+ * cannot disagree. Absent from an older server, and from a budget that covers every commitment:
233
+ * no line, never a guess.
234
+ *
235
+ * Takes the carried field as it arrives (`unknown`), because two of the three callers read it off
236
+ * an untyped body.
237
+ */
238
+ export declare function runBudgetFloorNote(value: unknown): string | undefined;
239
+ /**
240
+ * What `critical_commitment` on the always-ask list does and does not do (OSK-21333).
241
+ *
242
+ * The list governs PROMOTION to critical (`critical_promotion`): remove the class and a bounded_auto
243
+ * review applies a small promotion itself. It does not govern the way back: a demotion away from
244
+ * critical is held for a person in `bounded_auto` whatever the list says (`critical_demotion`,
245
+ * `NorthstarGovernancePolicy.classifyIntent`: the demotion rule never reads the list). The behaviour
246
+ * is pinned by `NorthstarGovernancePolicy.spec.js` ("critical_commitment off the approval list"),
247
+ * the words by `cli/src/commands/northstars/__tests__/critical-approval-help.spec.ts`. The flag help
248
+ * and the `Approval for` line of `governance show` both read this one sentence, so neither can
249
+ * drift from the other.
250
+ */
251
+ export declare const CRITICAL_COMMITMENT_APPROVAL_NOTE = "critical_commitment governs promotion to critical only; demotion away from critical (critical_demotion) is always held for a person, whatever this list says";
169
252
  export declare function renderGovernance(status: NorthstarGovernanceStatus, log: (line: string) => void): void;
170
253
  /**
171
254
  * The automatic-change budget line.