paneltir 0.10.1 → 0.12.0

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.
@@ -30,7 +30,10 @@ library shared with other projects. Rules:
30
30
  - The dashboard palette lives in <!-- path to this project's theme file, e.g.
31
31
  src/dashboard-theme.ts -->. Colour changes go there, never in the kit. The
32
32
  dashboard's **shape** is a `DashboardThemeForm` passed to the same provider
33
- (`panel` or `ledger`); it too is this project's choice, not the kit's.
33
+ (`panel`, `ledger` or `warRoom`); it too is this project's choice, not the
34
+ kit's. `warRoom` is the console one — square, tight, priority as a bar down
35
+ the left edge of each row — and the only one that fits more rows on a screen
36
+ rather than fewer.
34
37
  - **This project's theme goes to `PanelApp` as `extraThemes`, never as
35
38
  `themes`.** `extraThemes` offers it alongside the four the kit ships;
36
39
  `themes` means "exactly these and nothing else", so passing one theme there
@@ -52,6 +55,19 @@ library shared with other projects. Rules:
52
55
  moved underneath you, or both. The second is the one no `git diff` can find,
53
56
  because there is nothing in this project's history to diff against, and it is
54
57
  how a fix released upstream stayed out of a project for two releases.
58
+ - **A card finished more than a week ago leaves the board.** Nothing is
59
+ deleted and nothing is written: the panel derives it from `completedAt` on
60
+ every render, stops drawing that card in its column, and lists it in the
61
+ record view with the date it was finished. A done column that looks short has
62
+ not lost anything — read the board file, not the screen, when counting what
63
+ is finished. A card in a done column with no `completedAt` is never archived,
64
+ because its age is not known, which is one more reason to stamp the date when
65
+ a card is moved to done.
66
+ - **The top of the board says what is waiting on you and whether the system is
67
+ working.** Cards in the owner's column, questions nobody has answered, and
68
+ orders waiting on Claude, each as a count that filters the board or opens the
69
+ question when tapped — beside the health pills the project supplies. Nothing
70
+ to do there draws one sentence instead of a row of noughts.
55
71
  - **The panel explains itself once.** New readers get a short guided tour the
56
72
  first time they open the board; each note is dismissed and stays dismissed.
57
73
  **Help** in the header reports what the panel needs — the password, the
package/INSTALL.md CHANGED
@@ -19,7 +19,7 @@ identity** — never another project's.
19
19
  npm install paneltir
20
20
 
21
21
  # or, without npm access, straight from the repository:
22
- # npm install github:daifukus/paneltir#v0.10.1
22
+ # npm install github:daifukus/paneltir#v0.12.0
23
23
  ```
24
24
 
25
25
  (Use the tag you were given; never install without pinning a version.)
@@ -237,7 +237,7 @@ identity** — never another project's.
237
237
 
238
238
  ```bash
239
239
  npx paneltir version # version, fingerprint, where it came from
240
- npx paneltir check 0.10.1 # exits non-zero if that is not what is installed
240
+ npx paneltir check 0.12.0 # exits non-zero if that is not what is installed
241
241
  npx paneltir board # read the board and say what is wrong with it
242
242
  ```
243
243
 
package/README.md CHANGED
@@ -54,7 +54,7 @@ tag rather than a branch, so an unfinished push cannot reach a project:
54
54
  npm install paneltir
55
55
 
56
56
  # or, without npm access, straight from the repository:
57
- # npm install github:daifukus/paneltir#v0.10.1
57
+ # npm install github:daifukus/paneltir#v0.12.0
58
58
  ```
59
59
 
60
60
  Installing from Git runs the `prepare` script, which builds `dist/`, so the
package/dist/index.d.ts CHANGED
@@ -104,8 +104,13 @@ interface DashboardThemeForm {
104
104
  * carrying a coloured bar. The default.
105
105
  * - `ledger` — cards are ruled rows in a column with no fill, separated by
106
106
  * hairlines and marked in the gutter. Reads as a book rather than a HUD.
107
+ * - `warRoom` — an operations console. Square, hairline-ruled, tight, with
108
+ * priority carried as a full-height bar at the left edge of every row and
109
+ * counts set in the monospace face so columns of numbers line up. It is
110
+ * the shape for a board somebody is watching rather than browsing: state
111
+ * before ornament, and as many rows on the screen as will fit.
107
112
  */
108
- shape?: 'panel' | 'ledger';
113
+ shape?: 'panel' | 'ledger' | 'warRoom';
109
114
  /** Radius of columns, tiles and sheets. */
110
115
  radiusPanel?: string;
111
116
  /** Radius of cards. */
@@ -195,10 +200,25 @@ declare const ledgerForm: DashboardThemeForm;
195
200
  * free, so the shape does the separating instead.
196
201
  */
197
202
  declare const paperForm: DashboardThemeForm;
203
+ /**
204
+ * An operations console: square, tight, ruled, state before ornament.
205
+ *
206
+ * `panel` is a board you browse and `ledger` is a book you read; this is one
207
+ * somebody is watching. So the spacing scale comes down rather than up — it is
208
+ * the only form below 1 — the radii go flat, the labels are tracked out the way
209
+ * a console tracks them, and the face for anything countable is the monospace
210
+ * one, because a column of numbers that does not line up cannot be scanned.
211
+ *
212
+ * It changes the drawing and not the palette: a war room in Old Money's greens
213
+ * is still Old Money. That is the whole point of a form being separate from
214
+ * its colour.
215
+ */
216
+ declare const warRoomForm: DashboardThemeForm;
198
217
  declare const THEME_FORMS: {
199
218
  readonly panel: DashboardThemeForm;
200
219
  readonly ledger: DashboardThemeForm;
201
220
  readonly paper: DashboardThemeForm;
221
+ readonly warRoom: DashboardThemeForm;
202
222
  };
203
223
  type ThemeFormName = keyof typeof THEME_FORMS;
204
224
  declare const THEME_PRESETS: {
@@ -257,6 +277,63 @@ declare function HealthPillRow({ children }: {
257
277
  children: React.ReactNode;
258
278
  }): React.JSX.Element;
259
279
 
280
+ /**
281
+ * How loudly an item asks to be looked at.
282
+ *
283
+ * Deliberately three rather than the four a health pill carries: this row
284
+ * answers "is anything waiting on me", and "unknown" is not an answer to that
285
+ * question — a number is either zero or it is not.
286
+ */
287
+ type SituationTone = 'clear' | 'attention' | 'alarm';
288
+ interface SituationItem {
289
+ id: string;
290
+ /** What is waiting. Short: this is read at a glance, not studied. */
291
+ label: string;
292
+ count: number;
293
+ /** Who it is waiting on, or what it means. One line, under the label. */
294
+ hint?: string;
295
+ tone?: SituationTone;
296
+ /** Where looking at it leads. Without this the number is not a control. */
297
+ onClick?: () => void;
298
+ }
299
+ interface SituationRowProps {
300
+ /** The heading over the left half. */
301
+ blockingLabel: string;
302
+ /**
303
+ * What is outstanding. An item with a count of zero is still drawn — a
304
+ * counter that disappears when it reaches zero cannot be read as "nothing is
305
+ * waiting", only as "the panel is not telling me", which is the reading this
306
+ * row exists to prevent.
307
+ */
308
+ blocking: SituationItem[];
309
+ /** Said when every count is zero, in place of a row of noughts. */
310
+ clearLabel: string;
311
+ /** The heading over the right half. */
312
+ statusLabel: string;
313
+ /** The system's own state — health pills, a build, a version. */
314
+ status?: React.ReactNode;
315
+ }
316
+ /**
317
+ * The two things a board is opened to find out: whether anything is waiting on
318
+ * the reader, and whether the machinery under it is working.
319
+ *
320
+ * Both were already on the screen and neither was prominent. The counts sat in
321
+ * a grid of six identical tiles, where "three cards are yours" reads exactly as
322
+ * loudly as "forty-one are done"; the health pills sat under them as a line of
323
+ * small grey text. A board is looked at to decide what to do next, and a panel
324
+ * that makes that answer the same size as everything else has made the reader
325
+ * do the finding.
326
+ *
327
+ * So the outstanding counts are drawn large and are controls rather than
328
+ * labels, the whole left half goes quiet when there is nothing outstanding, and
329
+ * the system's state gets its own half with a heading instead of being a footer
330
+ * under the numbers.
331
+ *
332
+ * It draws no colour of its own: tone becomes a class and the palette arrives
333
+ * through `--pt-color-*`, like everything else here.
334
+ */
335
+ declare function SituationRow({ blockingLabel, blocking, clearLabel, statusLabel, status, }: SituationRowProps): React.JSX.Element;
336
+
260
337
  interface FilterChipProps {
261
338
  label: string;
262
339
  count?: number;
@@ -284,6 +361,18 @@ interface BoardColumnData<TCard extends BoardCardData = BoardCardData> {
284
361
  */
285
362
  hint?: string;
286
363
  cards: TCard[];
364
+ /**
365
+ * Drawn under the cards, inside the column's own scroll, so it takes no
366
+ * height from them.
367
+ *
368
+ * It was added for a done column to account for what it was no longer
369
+ * drawing, and the panel no longer uses it that way: a count in the middle of
370
+ * the board is a control for putting the cards back in the way, and the
371
+ * archive is now a place you go to instead. The slot stays because it is the
372
+ * honest shape for anything a column has to say about itself — a caller with
373
+ * such a line has somewhere to put it.
374
+ */
375
+ footer?: React.ReactNode;
287
376
  }
288
377
  interface BoardMoveResult {
289
378
  cardId: string;
@@ -1055,6 +1144,32 @@ declare function newId(): string;
1055
1144
  declare function today(): string;
1056
1145
  /** A card is created empty and named second — the same as tapping "+" on paper. */
1057
1146
  declare function emptyCard(column: string, area: string): Card;
1147
+ /**
1148
+ * How long a finished card stays on the board before it becomes history.
1149
+ *
1150
+ * A done column only grows. It is the one column nothing ever removes from,
1151
+ * so a board that is being worked turns into a wall of things already
1152
+ * finished, and the three columns that need reading get a third of the screen
1153
+ * between them. A week is the window in which "what did we ship" is still a
1154
+ * live question; after that it is a record, and a record does not need to be
1155
+ * in the way.
1156
+ */
1157
+ declare const ARCHIVE_AFTER_DAYS = 7;
1158
+ /**
1159
+ * Whether a finished card has been finished long enough to stop being drawn.
1160
+ *
1161
+ * Derived on every render and never written, which is the arrangement
1162
+ * `boardFacts()` already uses: a flag stored on the card would be wrong the
1163
+ * day after it was set, and setting it would mark the panel dirty for the
1164
+ * passage of time. Here the answer simply becomes true on its own.
1165
+ *
1166
+ * **A card with no `completedAt` is never archived**, whatever column it sits
1167
+ * in. It reached done without being stamped — a board edited by hand, or one
1168
+ * from before the stamp existed — so its age is not known, and hiding a card
1169
+ * whose age nobody knows is the same mistake as reporting a token missing
1170
+ * because the check could not run. `unknown` is not `old`.
1171
+ */
1172
+ declare function isArchived(card: Card, doneColumns: ReadonlySet<string>, now?: string, afterDays?: number): boolean;
1058
1173
  /**
1059
1174
  * Applies the column's own meaning to a card that just moved into it: a card
1060
1175
  * entering the working column is started, one reaching a done column is
@@ -1350,12 +1465,19 @@ interface UiStrings {
1350
1465
  filterForClaude: string;
1351
1466
  filterYours: string;
1352
1467
  filterHighRisk: string;
1468
+ situationBlocking: string;
1469
+ situationClear: string;
1470
+ situationStatus: string;
1471
+ situationYoursHint: string;
1472
+ situationDecisionsHint: string;
1473
+ situationOrdersHint: string;
1353
1474
  statOpen: string;
1354
1475
  statOrders: string;
1355
1476
  statYours: string;
1356
1477
  statDecisions: string;
1357
1478
  statHighRisk: string;
1358
1479
  statDone: string;
1480
+ statArchived: string;
1359
1481
  theme: string;
1360
1482
  themeSubtitle: string;
1361
1483
  themeNote: string;
@@ -1386,6 +1508,10 @@ interface UiStrings {
1386
1508
  needTokenEnables: string;
1387
1509
  needRepo: string;
1388
1510
  needRepoEnables: string;
1511
+ archiveTitle: string;
1512
+ archiveHeading: string;
1513
+ archiveIntro: string;
1514
+ archiveFinished: (date: string) => string;
1389
1515
  needGate: string;
1390
1516
  needGateEnables: string;
1391
1517
  fixGate: string;
@@ -1847,4 +1973,4 @@ interface CardSheetProps {
1847
1973
  }
1848
1974
  declare function CardSheet({ card, state, lang, ui, onChange, onDelete, onClose }: CardSheetProps): React.JSX.Element | null;
1849
1975
 
1850
- export { ANALYSIS_SECTIONS, AlertBanner, type AlertBannerProps, type Analysis, type AnalysisSection, AnalysisView, BOARD_VERSION, Board, type BoardCardData, type BoardCheck, type BoardColumnData, type BoardFacts, type BoardMoveResult, type BoardProblem, type BoardProps, type BoardTag, CAPABILITIES, type Capability, Card$1 as Card, type CardProps, CardSheet, type Check, type Choice, type ChoiceOption, type ColumnDef, type Competitor, type Constraint, CopyBlock, type CopyBlockLabels, type CopyBlockProps, type Counts, DashboardHeader, type DashboardHeaderProps, type DashboardThemeForm, DashboardThemeProvider, type DashboardThemeTokens, DetailSection, type DetailSectionProps, DetailSheet, type DetailSheetProps, FilterChip, type FilterChipProps, FilterChipRow, type GateReading, type GateStamp, type GateVerdict, type Goal, GuideNote, type GuideNoteProps, GuideTour, type GuideTourProps, type HealthFact, HealthPill, type HealthPillProps, HealthPillRow, type HealthStatus, INTENTS, INTENT_COPY, type ImportedTheme, type InstallState, type Intent, type IntentCopy, LANGS, LANG_LABELS, LEVELS, type Lang, type Level, MARKETPLACE_NAME, MARKETPLACE_URL, type Market, type MarketplaceReport, type MarketplaceTool, MarketplaceView, type Metric, type Note, NotificationBell, type NotificationBellProps, type NotificationLabels, type NotificationTone, OWNERS, type Owner, PANELTIR_FILE_COUNT, PANELTIR_FINGERPRINT, PANELTIR_TEMPLATE_HASH, PANELTIR_VERSION, PRESET_PANEL_THEMES, PanelApp, type PanelAppProps, type Card as PanelCard, type PanelNotification, type PanelState, type PanelTheme, type PanelThemes, type Preferences, type Reading, type Run, SetupGuide, type SetupGuideProps, type SetupRequirement, type SetupStatus, SetupWizard, type SetupWizardLabels, type SetupWizardProps, type Severity, StatTile, StatTileGrid, type StatTileProps, type Strategy, type Suggestion, type SuggestionStatus, THEME_FORMS, THEME_PRESETS, type Text, type ThemeFormName, type ThemePresetName, type Trend, UI, type UiStrings, type Weight, type WizardStep, applyMove, boardFacts, checkProgress, claimedWithoutStarting, claudeTheme, commandSnippet, countCards, cyberpunkTheme, decided, emptyCard, explainBoard, gateStatus, isCard, isFirstRun, ledgerForm, midnightTheme, moveCardInColumns, newId, offeredThemes, oldMoneyTheme, panelForm, paneltirBuild, paperForm, readBoard, readStoredLang, repositorySnippet, resetGuide, sparkPoints, stampForColumn, storeLang, text, today, trendOf, undecided, untranslated, useDashboardForm, useDashboardTheme, useDelegatedClick, useGuideNote, useMediaQuery, validateBoard, wizardStep, writeText };
1976
+ export { ANALYSIS_SECTIONS, ARCHIVE_AFTER_DAYS, AlertBanner, type AlertBannerProps, type Analysis, type AnalysisSection, AnalysisView, BOARD_VERSION, Board, type BoardCardData, type BoardCheck, type BoardColumnData, type BoardFacts, type BoardMoveResult, type BoardProblem, type BoardProps, type BoardTag, CAPABILITIES, type Capability, Card$1 as Card, type CardProps, CardSheet, type Check, type Choice, type ChoiceOption, type ColumnDef, type Competitor, type Constraint, CopyBlock, type CopyBlockLabels, type CopyBlockProps, type Counts, DashboardHeader, type DashboardHeaderProps, type DashboardThemeForm, DashboardThemeProvider, type DashboardThemeTokens, DetailSection, type DetailSectionProps, DetailSheet, type DetailSheetProps, FilterChip, type FilterChipProps, FilterChipRow, type GateReading, type GateStamp, type GateVerdict, type Goal, GuideNote, type GuideNoteProps, GuideTour, type GuideTourProps, type HealthFact, HealthPill, type HealthPillProps, HealthPillRow, type HealthStatus, INTENTS, INTENT_COPY, type ImportedTheme, type InstallState, type Intent, type IntentCopy, LANGS, LANG_LABELS, LEVELS, type Lang, type Level, MARKETPLACE_NAME, MARKETPLACE_URL, type Market, type MarketplaceReport, type MarketplaceTool, MarketplaceView, type Metric, type Note, NotificationBell, type NotificationBellProps, type NotificationLabels, type NotificationTone, OWNERS, type Owner, PANELTIR_FILE_COUNT, PANELTIR_FINGERPRINT, PANELTIR_TEMPLATE_HASH, PANELTIR_VERSION, PRESET_PANEL_THEMES, PanelApp, type PanelAppProps, type Card as PanelCard, type PanelNotification, type PanelState, type PanelTheme, type PanelThemes, type Preferences, type Reading, type Run, SetupGuide, type SetupGuideProps, type SetupRequirement, type SetupStatus, SetupWizard, type SetupWizardLabels, type SetupWizardProps, type Severity, type SituationItem, SituationRow, type SituationRowProps, type SituationTone, StatTile, StatTileGrid, type StatTileProps, type Strategy, type Suggestion, type SuggestionStatus, THEME_FORMS, THEME_PRESETS, type Text, type ThemeFormName, type ThemePresetName, type Trend, UI, type UiStrings, type Weight, type WizardStep, applyMove, boardFacts, checkProgress, claimedWithoutStarting, claudeTheme, commandSnippet, countCards, cyberpunkTheme, decided, emptyCard, explainBoard, gateStatus, isArchived, isCard, isFirstRun, ledgerForm, midnightTheme, moveCardInColumns, newId, offeredThemes, oldMoneyTheme, panelForm, paneltirBuild, paperForm, readBoard, readStoredLang, repositorySnippet, resetGuide, sparkPoints, stampForColumn, storeLang, text, today, trendOf, undecided, untranslated, useDashboardForm, useDashboardTheme, useDelegatedClick, useGuideNote, useMediaQuery, validateBoard, warRoomForm, wizardStep, writeText };